aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--widgets/misc/e-reflow-model.c70
-rw-r--r--widgets/misc/e-reflow-model.h18
-rw-r--r--widgets/misc/e-reflow.c114
-rw-r--r--widgets/misc/e-reflow.h4
4 files changed, 178 insertions, 28 deletions
diff --git a/widgets/misc/e-reflow-model.c b/widgets/misc/e-reflow-model.c
index 489a18b7e1..33a5498df5 100644
--- a/widgets/misc/e-reflow-model.c
+++ b/widgets/misc/e-reflow-model.c
@@ -36,8 +36,10 @@ static GObjectClass *e_reflow_model_parent_class;
enum {
MODEL_CHANGED,
+ COMPARISON_CHANGED,
MODEL_ITEMS_INSERTED,
MODEL_ITEM_CHANGED,
+ MODEL_ITEM_REMOVED,
LAST_SIGNAL
};
@@ -161,6 +163,15 @@ e_reflow_model_class_init (GObjectClass *object_class)
e_marshal_NONE__NONE,
G_TYPE_NONE, 0);
+ e_reflow_model_signals [COMPARISON_CHANGED] =
+ g_signal_new ("comparison_changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EReflowModelClass, comparison_changed),
+ NULL, NULL,
+ e_marshal_NONE__NONE,
+ G_TYPE_NONE, 0);
+
e_reflow_model_signals [MODEL_ITEMS_INSERTED] =
g_signal_new ("model_items_inserted",
G_OBJECT_CLASS_TYPE (object_class),
@@ -179,6 +190,15 @@ e_reflow_model_class_init (GObjectClass *object_class)
e_marshal_NONE__INT,
G_TYPE_NONE, 1, G_TYPE_INT);
+ e_reflow_model_signals [MODEL_ITEM_REMOVED] =
+ g_signal_new ("model_item_removed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EReflowModelClass, model_item_removed),
+ NULL, NULL,
+ e_marshal_NONE__INT,
+ G_TYPE_NONE, 1, G_TYPE_INT);
+
klass->set_width = NULL;
klass->count = NULL;
klass->height = NULL;
@@ -186,7 +206,9 @@ e_reflow_model_class_init (GObjectClass *object_class)
klass->reincarnate = NULL;
klass->model_changed = NULL;
+ klass->comparison_changed = NULL;
klass->model_items_inserted = NULL;
+ klass->model_item_removed = NULL;
klass->model_item_changed = NULL;
}
@@ -236,6 +258,29 @@ e_reflow_model_changed (EReflowModel *e_reflow_model)
}
/**
+ * e_reflow_model_comparison_changed:
+ * @e_reflow_model: the reflow model to notify of the change
+ *
+ * Use this function to notify any views of this reflow model that the
+ * sorting has changed. The actual contents of the items hasn't, so
+ * there's no need to re-query the model for the heights of the
+ * individual items.
+ */
+void
+e_reflow_model_comparison_changed (EReflowModel *e_reflow_model)
+{
+ g_return_if_fail (e_reflow_model != NULL);
+ g_return_if_fail (E_IS_REFLOW_MODEL (e_reflow_model));
+
+ d(print_tabs());
+ d(g_print("Emitting comparison_changed on model 0x%p.\n", e_reflow_model));
+ d(depth++);
+ g_signal_emit (e_reflow_model,
+ e_reflow_model_signals [COMPARISON_CHANGED], 0);
+ d(depth--);
+}
+
+/**
* e_reflow_model_items_inserted:
* @e_reflow_model: The model changed.
* @position: The position the items were insert in.
@@ -259,6 +304,31 @@ e_reflow_model_items_inserted (EReflowModel *e_reflow_model, int position, int c
}
/**
+ * e_reflow_model_item_removed:
+ * @e_reflow_model: The model changed.
+ * @n: The position from which the items were removed.
+ *
+ * Use this function to notify any views of the reflow model that an
+ * item has been removed.
+ **/
+void
+e_reflow_model_item_removed (EReflowModel *e_reflow_model,
+ int n)
+{
+ g_return_if_fail (e_reflow_model != NULL);
+ g_return_if_fail (E_IS_REFLOW_MODEL (e_reflow_model));
+
+ d(print_tabs());
+ d(g_print("Emitting item_removed on model 0x%p, n=%d.\n", e_reflow_model, n));
+ d(depth++);
+ g_signal_emit (e_reflow_model,
+ e_reflow_model_signals [MODEL_ITEM_REMOVED], 0,
+ n);
+ d(depth--);
+}
+
+
+/**
* e_reflow_model_item_changed:
* @e_reflow_model: the reflow model to notify of the change
* @item: the item that was changed in the model.
diff --git a/widgets/misc/e-reflow-model.h b/widgets/misc/e-reflow-model.h
index b755cee447..25731b2af5 100644
--- a/widgets/misc/e-reflow-model.h
+++ b/widgets/misc/e-reflow-model.h
@@ -63,10 +63,13 @@ typedef struct {
/*
* These all come after the change has been made.
* Major structural changes: model_changed
+ * Changes to the sorting of elements: comparison_changed
* Changes only in an item: item_changed
*/
void (*model_changed) (EReflowModel *etm);
+ void (*comparison_changed) (EReflowModel *etm);
void (*model_items_inserted) (EReflowModel *etm, int position, int count);
+ void (*model_item_removed) (EReflowModel *etm, int position);
void (*model_item_changed) (EReflowModel *etm, int n);
} EReflowModelClass;
@@ -92,12 +95,15 @@ void e_reflow_model_reincarnate (EReflowModel *e_reflow_mode
/*
* Routines for emitting signals on the e_reflow
*/
-void e_reflow_model_changed (EReflowModel *e_reflow_model);
-void e_reflow_model_items_inserted (EReflowModel *e_reflow_model,
- int position,
- int count);
-void e_reflow_model_item_changed (EReflowModel *e_reflow_model,
- int n);
+void e_reflow_model_changed (EReflowModel *e_reflow_model);
+void e_reflow_model_comparison_changed (EReflowModel *e_reflow_model);
+void e_reflow_model_items_inserted (EReflowModel *e_reflow_model,
+ int position,
+ int count);
+void e_reflow_model_item_removed (EReflowModel *e_reflow_model,
+ int n);
+void e_reflow_model_item_changed (EReflowModel *e_reflow_model,
+ int n);
#ifdef __cplusplus
}
diff --git a/widgets/misc/e-reflow.c b/widgets/misc/e-reflow.c
index e70cd61d0b..70b1f4a470 100644
--- a/widgets/misc/e-reflow.c
+++ b/widgets/misc/e-reflow.c
@@ -257,28 +257,32 @@ reflow_columns (EReflow *reflow)
{
GSList *list;
int count;
+ int start;
int i;
- int column_count;
+ int column_count, column_start;
double running_height;
- g_free (reflow->columns);
- reflow->column_count = 0;
- reflow->columns = NULL;
+ if (reflow->reflow_from_column <= 1) {
+ start = 0;
+ column_count = 1;
+ column_start = 0;
+ }
+ else {
+ /* we start one column before the earliest new entry,
+ so we can handle the case where the new entry is
+ inserted at the start of the column */
+ column_start = reflow->reflow_from_column - 1;
+ start = reflow->columns[column_start];
+ column_count = column_start;
+ }
list = NULL;
running_height = E_REFLOW_BORDER_WIDTH;
- column_count = 1;
- count = reflow->count;
- for (i = 0; i < count; i++) {
+ count = reflow->count - start;
+ for (i = start; i < count; i++) {
int unsorted = e_sorter_sorted_to_model (E_SORTER (reflow->sorter), i);
- if (reflow->heights[unsorted] == -1) {
- if (reflow->model)
- reflow->heights[unsorted] = e_reflow_model_height (reflow->model, unsorted, GNOME_CANVAS_GROUP (reflow));
- else
- reflow->heights[unsorted] = 0;
- }
if (i != 0 && running_height + reflow->heights[unsorted] + E_REFLOW_BORDER_WIDTH > reflow->height) {
list = g_slist_prepend (list, GINT_TO_POINTER(i));
column_count ++;
@@ -288,20 +292,22 @@ reflow_columns (EReflow *reflow)
}
reflow->column_count = column_count;
- reflow->columns = g_new (int, column_count);
+ reflow->columns = g_renew (int, reflow->columns, column_count);
column_count --;
- for (; column_count > 0; column_count--) {
+
+ for (; column_count > column_start; column_count--) {
GSList *to_free;
reflow->columns[column_count] = GPOINTER_TO_INT(list->data);
to_free = list;
list = list->next;
g_slist_free_1 (to_free);
}
- reflow->columns[0] = 0;
+ reflow->columns[column_start] = start;
queue_incarnate (reflow);
reflow->need_reflow_columns = FALSE;
+ reflow->reflow_from_column = -1;
}
static void
@@ -310,19 +316,46 @@ item_changed (EReflowModel *model, int i, EReflow *reflow)
if (i < 0 || i >= reflow->count)
return;
- reflow->heights[i] = -1;
+ reflow->heights[i] = e_reflow_model_height (reflow->model, i, GNOME_CANVAS_GROUP (reflow));
if (reflow->items[i] != NULL)
e_reflow_model_reincarnate (model, i, reflow->items[i]);
e_sorter_array_clean (reflow->sorter);
+ reflow->reflow_from_column = -1;
reflow->need_reflow_columns = TRUE;
e_canvas_item_request_reflow(GNOME_CANVAS_ITEM (reflow));
}
static void
+item_removed (EReflowModel *model, int i, EReflow *reflow)
+{
+ int c;
+ int sorted;
+
+ if (i < 0 || i >= reflow->count)
+ return;
+
+ sorted = e_sorter_model_to_sorted (E_SORTER (reflow->sorter), i);
+ for (c = reflow->column_count - 1; c >= 0; c--) {
+ int start_of_column = reflow->columns[c];
+
+ if (start_of_column <= sorted) {
+ reflow->reflow_from_column = c;
+ reflow->need_reflow_columns = TRUE;
+ set_empty (reflow);
+ e_canvas_item_request_reflow(GNOME_CANVAS_ITEM (reflow));
+
+ break;
+ }
+ }
+}
+
+static void
items_inserted (EReflowModel *model, int position, int count, EReflow *reflow)
{
- int i;
+ int i, c;
int oldcount;
+ int lowest_column;
+
if (position < 0 || position > reflow->count)
return;
@@ -340,7 +373,7 @@ items_inserted (EReflowModel *model, int position, int count, EReflow *reflow)
memmove (reflow->items + position + count, reflow->items + position, (reflow->count - position - count) * sizeof (GnomeCanvasItem *));
for (i = position; i < position + count; i++) {
reflow->items[i] = 0;
- reflow->heights[i] = -1;
+ reflow->heights[i] = e_reflow_model_height (reflow->model, i, GNOME_CANVAS_GROUP (reflow));
}
e_selection_model_simple_set_row_count (E_SELECTION_MODEL_SIMPLE (reflow->selection), reflow->count);
@@ -348,6 +381,23 @@ items_inserted (EReflowModel *model, int position, int count, EReflow *reflow)
e_sorter_array_append (reflow->sorter, count);
else
e_sorter_array_set_count (reflow->sorter, reflow->count);
+
+ for (i = position; i < position + count; i ++) {
+ int sorted = e_sorter_model_to_sorted (E_SORTER (reflow->sorter), i);
+ int c;
+
+ for (c = reflow->column_count - 1; c >= 0; c--) {
+ int start_of_column = reflow->columns[c];
+
+ if (start_of_column <= sorted) {
+ if (reflow->reflow_from_column == -1
+ || reflow->reflow_from_column > c)
+ reflow->reflow_from_column = c;
+ break;
+ }
+ }
+ }
+
reflow->need_reflow_columns = TRUE;
set_empty (reflow);
e_canvas_item_request_reflow(GNOME_CANVAS_ITEM (reflow));
@@ -377,7 +427,7 @@ model_changed (EReflowModel *model, EReflow *reflow)
count = reflow->count;
for (i = 0; i < count; i++) {
reflow->items[i] = 0;
- reflow->heights[i] = -1;
+ reflow->heights[i] = e_reflow_model_height (reflow->model, i, GNOME_CANVAS_GROUP (reflow));
}
e_selection_model_simple_set_row_count (E_SELECTION_MODEL_SIMPLE (reflow->selection), count);
@@ -391,6 +441,15 @@ model_changed (EReflowModel *model, EReflow *reflow)
}
static void
+comparison_changed (EReflowModel *model, EReflow *reflow)
+{
+ e_sorter_array_clean (reflow->sorter);
+ reflow->reflow_from_column = -1;
+ reflow->need_reflow_columns = TRUE;
+ e_canvas_item_request_reflow(GNOME_CANVAS_ITEM (reflow));
+}
+
+static void
set_empty(EReflow *reflow)
{
if (reflow->count == 0) {
@@ -416,7 +475,6 @@ set_empty(EReflow *reflow)
"width", reflow->minimum_width,
"clip", TRUE,
"use_ellipsis", TRUE,
- "font_gdk", gtk_style_get_font (GTK_WIDGET(GNOME_CANVAS_ITEM(reflow)->canvas)->style),
"fill_color", "black",
"justification", GTK_JUSTIFY_CENTER,
"text", reflow->empty_message,
@@ -444,13 +502,19 @@ disconnect_model (EReflow *reflow)
g_signal_handler_disconnect (reflow->model,
reflow->model_changed_id);
g_signal_handler_disconnect (reflow->model,
+ reflow->comparison_changed_id);
+ g_signal_handler_disconnect (reflow->model,
reflow->model_items_inserted_id);
g_signal_handler_disconnect (reflow->model,
+ reflow->model_item_removed_id);
+ g_signal_handler_disconnect (reflow->model,
reflow->model_item_changed_id);
g_object_unref (reflow->model);
reflow->model_changed_id = 0;
+ reflow->comparison_changed_id = 0;
reflow->model_items_inserted_id = 0;
+ reflow->model_item_removed_id = 0;
reflow->model_item_changed_id = 0;
reflow->model = NULL;
}
@@ -489,9 +553,15 @@ connect_model (EReflow *reflow, EReflowModel *model)
reflow->model_changed_id =
g_signal_connect (reflow->model, "model_changed",
G_CALLBACK (model_changed), reflow);
+ reflow->comparison_changed_id =
+ g_signal_connect (reflow->model, "comparison_changed",
+ G_CALLBACK (comparison_changed), reflow);
reflow->model_items_inserted_id =
g_signal_connect (reflow->model, "model_items_inserted",
G_CALLBACK (items_inserted), reflow);
+ reflow->model_item_removed_id =
+ g_signal_connect (reflow->model, "model_item_removed",
+ G_CALLBACK (item_removed), reflow);
reflow->model_item_changed_id =
g_signal_connect (reflow->model, "model_item_changed",
G_CALLBACK (item_changed), reflow);
@@ -501,7 +571,7 @@ connect_model (EReflow *reflow, EReflowModel *model)
static void
adjustment_changed (GtkAdjustment *adjustment, EReflow *reflow)
{
- incarnate (reflow);
+ queue_incarnate (reflow);
}
static void
diff --git a/widgets/misc/e-reflow.h b/widgets/misc/e-reflow.h
index 09f1292c4e..b92643a935 100644
--- a/widgets/misc/e-reflow.h
+++ b/widgets/misc/e-reflow.h
@@ -64,7 +64,9 @@ struct _EReflow
/* item specific fields */
EReflowModel *model;
guint model_changed_id;
+ guint comparison_changed_id;
guint model_items_inserted_id;
+ guint model_item_removed_id;
guint model_item_changed_id;
ESelectionModel *selection;
@@ -105,6 +107,8 @@ struct _EReflow
int cursor_row;
+ int reflow_from_column;
+
guint column_drag : 1;
guint need_height_update : 1;