aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
authorChris Toshok <toshok@ximian.com>2003-02-17 10:38:15 +0800
committerChris Toshok <toshok@src.gnome.org>2003-02-17 10:38:15 +0800
commitbaa50a5c8934d74573914b6425a5457f420fba93 (patch)
tree1364d3782247632088cf6b0bfe97bfbcd08e8ae8 /widgets
parent9e048335b618fea2076c690479cd655d35a56515 (diff)
downloadgsoc2013-evolution-baa50a5c8934d74573914b6425a5457f420fba93.tar
gsoc2013-evolution-baa50a5c8934d74573914b6425a5457f420fba93.tar.gz
gsoc2013-evolution-baa50a5c8934d74573914b6425a5457f420fba93.tar.bz2
gsoc2013-evolution-baa50a5c8934d74573914b6425a5457f420fba93.tar.lz
gsoc2013-evolution-baa50a5c8934d74573914b6425a5457f420fba93.tar.xz
gsoc2013-evolution-baa50a5c8934d74573914b6425a5457f420fba93.tar.zst
gsoc2013-evolution-baa50a5c8934d74573914b6425a5457f420fba93.zip
enable this function to reflow the view from a particular column onward.
2003-02-16 Chris Toshok <toshok@ximian.com> * gal/widgets/e-reflow.c (reflow_columns): enable this function to reflow the view from a particular column onward. This is useful if you have a huge model and the only changes are happening at the end (as is normally the case if you're appending to a large model.) (item_changed): calculate the height of the changed item here, so we aren't doing it as we reflow the model. For now, reflow the entire model. Further optimization can be done here. (item_removed): new function. remove the item and reflow from the column that contained it. (items_inserted): calculate the heights of the new items, and calculate the lowest numbered column containing one of the inserted items. reflow from there. (model_changed): calculate the heights of everything here. (comparison_changed): new function, clear the sorter and reflow. (disconnect_model): disconnect comparison_changed and model_item_removed. (connect_model): connect comparison_changed and model_item_removed. (adjustment_changed): use queue_incarnate here, instead of forcing the reflow model to incarnate as we scroll. Not sure if this is actually the right solution, but it does make the scrollbar more responsive at the cost of redraw speed. * gal/widgets/e-reflow.h (struct _EReflow): add slots for the new signal ids, as well as "reflow_from_column". * gal/widgets/e-reflow-model.c (e_reflow_model_class_init): create the comparison_changed and model_item_removed signals. (e_reflow_model_comparison_changed): new function, emit the comparison_changed signal. (e_reflow_model_item_removed): new function, emit the model_item_removed signal. * gal/widgets/e-reflow-model.h: add comparison_changed and model_item_removed signals. svn path=/trunk/; revision=19917
Diffstat (limited to 'widgets')
-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;