aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/e-table/e-table-header.c
diff options
context:
space:
mode:
authorChristopher James Lahey <clahey@helixcode.com>2000-05-14 22:31:22 +0800
committerChris Lahey <clahey@src.gnome.org>2000-05-14 22:31:22 +0800
commit32471accadcf2099f9d3567f51add9fab197ec24 (patch)
tree8b070bcbdbcd962de9016b0fceaa15ec45848310 /widgets/e-table/e-table-header.c
parent623ba9a279db035339ac8ae5030683c1e79b8618 (diff)
downloadgsoc2013-evolution-32471accadcf2099f9d3567f51add9fab197ec24.tar.gz
gsoc2013-evolution-32471accadcf2099f9d3567f51add9fab197ec24.tar.zst
gsoc2013-evolution-32471accadcf2099f9d3567f51add9fab197ec24.zip
From widgets/e-table/ChangeLog
2000-05-14 Christopher James Lahey <clahey@helixcode.com> * Implemented the feature where the ETable columns automatically fill the given space. * e-cell-text.c, e-cell-text.h: Moved #include e-text-event-processor.h from the .h to the .c. * e-table-col.c, e-table-col.h: Added an expansion variable, and made it so that width isn't set by the programmer but instead by the e-table-header. * e-table-example-1.c, e-table-example-2.c, e-table-size-test.c, test-check.c, test-cols.c, test-table.c: Fixed to handle new ETable column resizing. * e-table-group-container.c, e-table-group-container.h, e-table-group-leaf.c, e-table-group-leaf.h, e-table-group.c, e-table-group.h, e-table-item.c, e-table-item.h: Fixed these to do a proper canvas reflow/update loop. Changed them to take a minimum width and return a width and a height. * e-table-header-item.c, e-table-header-item.h: Made this so that it depends on e-table-header.c for deciding the actual size of columns during resize (it was making incorrect decisions on its own.) * e-table-header.c, e-table-header.h: Changed this to make sure that the sum of the widths of the columns was always as close as possible to the width of the window. This is done by taking a full width and having each of the columns have an "expansion" field. This field is what makes each column have approximately the same portion of its part of the screen that it used to. * e-table.c: Changed this to set the width on the ETableHeader as well as set the proper minimum width on the ETableGroup and get the width and height it reports. From addressbook/ChangeLog 2000-05-14 Christopher James Lahey <clahey@helixcode.com> * backend/ebook/Makefile.am: Added libeutil for e-card's support for categories. * backend/ebook/e-card-list.c, backend/ebook/e-card-list.h: Added a function to get the length. * backend/ebook/e-card.c, backend/ebook/e-card.h: Added categories support (accessible either as "categories" or "category_list".) * contact-editor/Makefile.am: Added e-table and all of the categories files. * contact-editor/categories.glade, contact-editor/categories-strings.h, contact-editor/e-contact-editor-categories.c, contact-editor/e-contact-editor-categories.h: * contact-editor/contact-editor.glade, contact-editor/e-contact-editor-strings.h: Rearranged this dialog. * contact-editor/e-contact-editor.c: Rearranged dialog a bit. Added opening of categories dialog. * gui/component/Makefile.am: Rearranged libraries so that libetable would be available for the contact editor categories dialog. * gui/component/addressbook.c: Fix for new ETable resizing. Make contact editor dialog resizable. * gui/minicard/Makefile.am: Added libetable contact editor categories dialog. * gui/minicard/e-minicard.c: Make contact editor dialog resizable. From mail/ChangeLog 2000-05-14 Christopher James Lahey <clahey@helixcode.com> * message-list.c: Updated to work with new ETable resizing. svn path=/trunk/; revision=3027
Diffstat (limited to 'widgets/e-table/e-table-header.c')
-rw-r--r--widgets/e-table/e-table-header.c393
1 files changed, 253 insertions, 140 deletions
diff --git a/widgets/e-table/e-table-header.c b/widgets/e-table/e-table-header.c
index 4e9bf278ee..61e1f9a9da 100644
--- a/widgets/e-table/e-table-header.c
+++ b/widgets/e-table/e-table-header.c
@@ -12,6 +12,14 @@
#include <gtk/gtkobject.h>
#include <gtk/gtksignal.h>
#include "e-table-header.h"
+#include "e-table-defines.h"
+
+/* The arguments we take */
+enum {
+ ARG_0,
+ ARG_SORT_INFO,
+ ARG_WIDTH,
+};
enum {
STRUCTURE_CHANGE,
@@ -19,22 +27,33 @@ enum {
LAST_SIGNAL
};
+static void eth_set_arg (GtkObject *object, GtkArg *arg, guint arg_id);
+static void eth_get_arg (GtkObject *object, GtkArg *arg, guint arg_id);
+static void eth_do_remove (ETableHeader *eth, int idx, gboolean do_unref);
+
static guint eth_signals [LAST_SIGNAL] = { 0, };
static GtkObjectClass *e_table_header_parent_class;
static void
-e_table_header_destroy (GtkObject *object)
+eth_destroy (GtkObject *object)
{
ETableHeader *eth = E_TABLE_HEADER (object);
const int cols = eth->col_count;
int i;
+ if (eth->sort_info) {
+ if (eth->sort_info_group_change_id)
+ gtk_signal_disconnect(GTK_OBJECT(eth->sort_info),
+ eth->sort_info_group_change_id);
+ gtk_object_unref(GTK_OBJECT(eth->sort_info));
+ }
+
/*
* Destroy columns
*/
for (i = cols - 1; i >= 0; i--){
- e_table_header_remove (eth, i);
+ eth_do_remove (eth, i, TRUE);
}
if (e_table_header_parent_class->destroy)
@@ -44,10 +63,18 @@ e_table_header_destroy (GtkObject *object)
static void
e_table_header_class_init (GtkObjectClass *object_class)
{
- object_class->destroy = e_table_header_destroy;
+ object_class->destroy = eth_destroy;
+ object_class->set_arg = eth_set_arg;
+ object_class->get_arg = eth_get_arg;
+
e_table_header_parent_class = (gtk_type_class (gtk_object_get_type ()));
+ gtk_object_add_arg_type ("ETableHeader::width", GTK_TYPE_DOUBLE,
+ GTK_ARG_READWRITE, ARG_WIDTH);
+ gtk_object_add_arg_type ("ETableHeader::sort_info", GTK_TYPE_OBJECT,
+ GTK_ARG_READWRITE, ARG_SORT_INFO);
+
eth_signals [STRUCTURE_CHANGE] =
gtk_signal_new ("structure_change",
GTK_RUN_LAST,
@@ -66,6 +93,19 @@ e_table_header_class_init (GtkObjectClass *object_class)
gtk_object_class_add_signals (object_class, eth_signals, LAST_SIGNAL);
}
+static void
+e_table_header_init (ETableHeader *eth)
+{
+ eth->col_count = 0;
+ eth->width = 0;
+
+ eth->sort_info = NULL;
+ eth->sort_info_group_change_id = 0;
+
+ eth->columns = NULL;
+ eth->selectable = FALSE;
+}
+
GtkType
e_table_header_get_type (void)
{
@@ -77,7 +117,7 @@ e_table_header_get_type (void)
sizeof (ETableHeader),
sizeof (ETableHeaderClass),
(GtkClassInitFunc) e_table_header_class_init,
- (GtkObjectInitFunc) NULL,
+ (GtkObjectInitFunc) e_table_header_init,
NULL, /* reserved 1 */
NULL, /* reserved 2 */
(GtkClassInitFunc) NULL
@@ -100,12 +140,57 @@ e_table_header_new (void)
}
static void
-eth_do_insert (ETableHeader *eth, int pos, ETableCol *val)
+eth_group_info_changed(ETableSortInfo *info, ETableHeader *eth)
{
- memmove (&eth->columns [pos+1], &eth->columns [pos],
- sizeof (ETableCol *) * (eth->col_count - pos));
- eth->columns [pos] = val;
- eth->col_count ++;
+ e_table_header_calc_widths(eth);
+}
+
+static void
+eth_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ ETableHeader *eth = E_TABLE_HEADER (object);
+
+ switch (arg_id) {
+ case ARG_WIDTH:
+ eth->width = GTK_VALUE_DOUBLE (*arg);
+ e_table_header_calc_widths(eth);
+ break;
+ case ARG_SORT_INFO:
+ if (eth->sort_info) {
+ if (eth->sort_info_group_change_id)
+ gtk_signal_disconnect(GTK_OBJECT(eth->sort_info), eth->sort_info_group_change_id);
+ gtk_object_unref(GTK_OBJECT(eth->sort_info));
+ }
+ eth->sort_info = E_TABLE_SORT_INFO(GTK_VALUE_OBJECT (*arg));
+ if (eth->sort_info) {
+ gtk_object_ref(GTK_OBJECT(eth->sort_info));
+ eth->sort_info_group_change_id
+ = gtk_signal_connect(GTK_OBJECT(eth->sort_info), "group_info_changed",
+ GTK_SIGNAL_FUNC(eth_group_info_changed), eth);
+ }
+ e_table_header_calc_widths(eth);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+eth_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ ETableHeader *eth = E_TABLE_HEADER (object);
+
+ switch (arg_id) {
+ case ARG_SORT_INFO:
+ GTK_VALUE_OBJECT (*arg) = GTK_OBJECT(eth->sort_info);
+ break;
+ case ARG_WIDTH:
+ GTK_VALUE_DOUBLE (*arg) = eth->width;
+ break;
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
}
static void
@@ -122,6 +207,15 @@ eth_update_offsets (ETableHeader *eth)
}
}
+static void
+eth_do_insert (ETableHeader *eth, int pos, ETableCol *val)
+{
+ memmove (&eth->columns [pos+1], &eth->columns [pos],
+ sizeof (ETableCol *) * (eth->col_count - pos));
+ eth->columns [pos] = val;
+ eth->col_count ++;
+}
+
void
e_table_header_add_column (ETableHeader *eth, ETableCol *tc, int pos)
{
@@ -142,10 +236,9 @@ e_table_header_add_column (ETableHeader *eth, ETableCol *tc, int pos)
gtk_object_sink (GTK_OBJECT (tc));
eth_do_insert (eth, pos, tc);
- eth_update_offsets (eth);
+ e_table_header_calc_widths(eth);
gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
- gtk_signal_emit (GTK_OBJECT (eth), eth_signals [DIMENSION_CHANGE]);
}
ETableCol *
@@ -285,8 +378,8 @@ e_table_header_move (ETableHeader *eth, int source_index, int target_index)
eth_do_insert (eth, target_index, old);
eth_update_offsets (eth);
- gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
gtk_signal_emit (GTK_OBJECT (eth), eth_signals [DIMENSION_CHANGE]);
+ gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
}
void
@@ -298,8 +391,8 @@ e_table_header_remove (ETableHeader *eth, int idx)
g_return_if_fail (idx < eth->col_count);
eth_do_remove (eth, idx, TRUE);
+ e_table_header_calc_widths(eth);
gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
- gtk_signal_emit (GTK_OBJECT (eth), eth_signals [DIMENSION_CHANGE]);
}
void
@@ -310,14 +403,129 @@ e_table_header_set_selection (ETableHeader *eth, gboolean allow_selection)
void
e_table_header_set_size (ETableHeader *eth, int idx, int size)
{
+ double expansion;
+ double old_expansion;
+ int min_width;
+ int left_width;
+ int total_extra;
+ int expandable_count;
+ int usable_width;
+ int i;
g_return_if_fail (eth != NULL);
g_return_if_fail (E_IS_TABLE_HEADER (eth));
g_return_if_fail (idx >= 0);
g_return_if_fail (idx < eth->col_count);
- g_return_if_fail (size > 0);
+
+ /* If this column is not resizable, don't do anything. */
+ if (!eth->columns[idx]->resizeable)
+ return;
+
+ expansion = 0;
+ min_width = 0;
+ left_width = 0;
+ expandable_count = -1;
+
+ /* Calculate usable area. */
+ for (i = 0; i < idx; i++) {
+ left_width += eth->columns[i]->width;
+ }
+ usable_width = eth->width - left_width;
+
+ if (eth->sort_info)
+ usable_width -= e_table_sort_info_grouping_get_count(eth->sort_info) * GROUP_INDENT;
+
+ /* Calculate minimum_width of stuff on the right as well as
+ * total usable expansion on the right.
+ */
+ for (; i < eth->col_count; i++) {
+ min_width += eth->columns[i]->min_width;
+ if (eth->columns[i]->resizeable) {
+ printf ("Expansion[%d] = %f\n", i, eth->columns[i]->expansion);
+ expansion += eth->columns[i]->expansion;
+ expandable_count ++;
+ }
+ }
+ /* If there's no room for anything, don't change. */
+ if (expansion == 0)
+ return;
+
+ /* (1) If none of the columns to the right are expandable, use
+ * all the expansion space in this column.
+ */
+ if(expandable_count == 0) {
+ eth->columns[idx]->expansion = expansion;
+ for (i = idx + 1; i < eth->col_count; i++) {
+ eth->columns[i]->expansion = 0;
+ }
+ goto end;
+ }
+
+ total_extra = usable_width - min_width;
+ /* If there's no extra space, set all expansions to 0. */
+ if (total_extra <= 0) {
+ for (i = idx; i < eth->col_count; i++) {
+ eth->columns[i]->expansion = 0;
+ }
+ goto end;
+ }
+
+ /* If you try to resize smaller than the minimum width, it
+ * uses the minimum. */
+ if (size < eth->columns[idx]->min_width)
+ size = eth->columns[idx]->min_width;
+
+ printf ("size = %d, eth->columns[idx]->min_width = %d, total_extra = %d, expansion = %f\n", size, eth->columns[idx]->min_width, total_extra, expansion);
+
+ /* If all the extra space will be used up in this column, use
+ * all the expansion and set all others to 0.
+ */
+ if (size >= total_extra + eth->columns[idx]->min_width) {
+ eth->columns[idx]->expansion = expansion;
+ for (i = idx + 1; i < eth->col_count; i++) {
+ eth->columns[i]->expansion = 0;
+ }
+ goto end;
+ }
+
+ /* The old_expansion used by columns to the right. */
+ old_expansion = expansion;
+ old_expansion -= eth->columns[idx]->expansion;
+ /* Set the new expansion so that it will generate the desired size. */
+ eth->columns[idx]->expansion = expansion * (((double)(size - eth->columns[idx]->min_width))/((double)total_extra));
+ /* The expansion left for the columns on the right. */
+ expansion -= eth->columns[idx]->expansion;
+
+ printf ("eth->columns[idx]->expansion = %f\n", eth->columns[idx]->expansion);
+
+ printf ("At (2) old_expansion = %f, expansion = %f\n", old_expansion, expansion);
+
+ /* (2) If the old columns to the right didn't have any
+ * expansion before, expand them evenly. old_expansion > 0 by
+ * expansion = SUM(i=idx to col_count -1,
+ * columns[i]->min_width) - columns[idx]->min_width) =
+ * SUM(non-negatives).
+ */
+ if (old_expansion == 0) {
+ for (i = idx + 1; i < eth->col_count; i++) {
+ if (eth->columns[idx]->resizeable) {
+ /* expandable_count != 0 by (1) */
+ eth->columns[i]->expansion = expansion / expandable_count;
+ }
+ }
+ goto end;
+ }
- eth->columns [idx]->width = size;
- gtk_signal_emit (GTK_OBJECT (eth), eth_signals [DIMENSION_CHANGE], idx);
+ /* Remove from total_extra the amount used for this column. */
+ total_extra -= size - eth->columns[idx]->min_width;
+ for (i = idx + 1; i < eth->col_count; i++) {
+ if (eth->columns[idx]->resizeable) {
+ /* old_expansion != 0 by (2) */
+ eth->columns[i]->expansion *= expansion / old_expansion;
+ }
+ }
+
+ end:
+ e_table_header_calc_widths(eth);
}
int
@@ -344,133 +552,38 @@ e_table_header_col_diff (ETableHeader *eth, int start_col, int end_col)
return total;
}
-/* Forget model-view here. Really, this information belongs in the view anyway. */
-#if 0
-static void
-set_arrows (ETableHeader *eth, ETableHeaderSortInfo info)
-{
- ETableCol *col;
- for (col = eth->columns, i = 0; i < eth->col_count; i++, col++) {
- if (col->col_idx == info.model_col)
- e_table_column_set_arrow (col, info.ascending ? E_TABLE_COL_ARROW_DOWN : E_TABLE_COL_ARROW_UP);
- }
-}
-
-static void
-unset_arrows (ETableHeader *eth, ETableHeaderSortInfo info)
-{
- ETableCol *col;
- for (col = eth->columns, i = 0; i < eth->col_count; i++, col++) {
- if (col->col_idx == info.model_col)
- e_table_column_set_arrow (col, E_TABLE_COL_ARROW_NONE);
- }
-}
-
-ETableHeaderSortInfo
-e_table_header_get_sort_info (ETableHeader *eth)
-{
- ETableHeaderSortInfo dummy_info = {0, 1};
- g_return_val_if_fail (eth != NULL, dummy_info);
- g_return_val_if_fail (E_IS_TABLE_HEADER (eth), dummy_info);
-
- return eth->sort_info;
-}
-
void
-e_table_header_set_sort_info (ETableHeader *eth, ETableHeaderSortInfo info)
+e_table_header_calc_widths (ETableHeader *eth)
{
- g_return_if_fail (eth != NULL);
- g_return_if_fail (E_IS_TABLE_HEADER (eth));
-
- unset_arrows (eth, eth->sort_info);
- eth->sort_info = info;
- set_arrows (eth, eth->sort_info);
-
- gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
-}
-
-
-int
-e_table_header_get_group_count (ETableHeader *eth)
-{
- g_return_val_if_fail (eth != NULL, 0);
- g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0);
-
- return eth->grouping_count;
-}
-
-ETableHeaderSortInfo *
-e_table_header_get_groups (ETableHeader *eth)
-{
- ETableHeaderSortInfo *ret;
- g_return_val_if_fail (eth != NULL, NULL);
- g_return_val_if_fail (E_IS_TABLE_HEADER (eth), NULL);
-
- ret = g_new (ETableHeaderSortInfo, eth->grouping_count);
- memcpy (ret, eth->grouping, sizeof (ETableHeaderSortInfo) * eth->grouping_count);
- return eth->grouping;
-}
-
-ETableHeaderSortInfo
-e_table_header_get_group (ETableHeader *eth, gint index)
-{
- ETableHeaderSortInfo dummy_info = {0, 1};
- g_return_val_if_fail (eth != NULL, dummy_info);
- g_return_val_if_fail (E_IS_TABLE_HEADER (eth), dummy_info);
- g_return_val_if_fail (index >= 0, dummy_info);
- g_return_val_if_fail (index < eth->grouping_count, dummy_info);
-
- return eth->grouping[index];
-}
-
-void
-e_table_header_grouping_insert (ETableHeader *eth, gint index, ETableHeaderSortInfo info)
-{
- g_return_if_fail (eth != NULL);
- g_return_if_fail (E_IS_TABLE_HEADER (eth));
-
- eth->grouping = g_realloc (eth->grouping, sizeof(ETableHeaderSortInfo) * (eth->grouping_count + 1));
- memmove (eth->grouping + index + 1, eth->grouping + index, sizeof(ETableHeaderSortInfo) * (eth->grouping_count - index));
- eth->grouping[index] = info;
-
- eth->grouping_count ++;
-
- gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
-}
-
-void
-e_table_header_grouping_delete (ETableHeader *eth, gint index)
-{
- g_return_if_fail (eth != NULL);
- g_return_if_fail (E_IS_TABLE_HEADER (eth));
-
- memmove (eth->grouping + index, eth->grouping + index + 1, sizeof(ETableHeaderSortInfo) * (eth->grouping_count - index));
- eth->grouping = g_realloc (eth->grouping, sizeof(ETableHeaderSortInfo) * (eth->grouping_count - 1));
-
- eth->grouping_count --;
-
- gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
-}
-
-void
-e_table_header_grouping_move (ETableHeader *eth, gint old_idx, gint new_idx)
-{
- ETableHeaderSortInfo info;
-
- g_return_if_fail (eth != NULL);
- g_return_if_fail (E_IS_TABLE_HEADER (eth));
-
- if (old_idx == new_idx)
+ int i;
+ int extra, extra_left;
+ double expansion;
+ int last_resizeable = -1;
+ extra = eth->width;
+ expansion = 0;
+ for (i = 0; i < eth->col_count; i++) {
+ extra -= eth->columns[i]->min_width;
+ if (eth->columns[i]->resizeable) {
+ expansion += eth->columns[i]->expansion;
+ last_resizeable = i;
+ }
+ eth->columns[i]->width = eth->columns[i]->min_width;
+ }
+ if (eth->sort_info)
+ extra -= e_table_sort_info_grouping_get_count(eth->sort_info) * GROUP_INDENT;
+ if (expansion == 0 || extra < 0)
return;
-
- info = eth->grouping[old_idx];
- if (old_idx < new_idx){
- memmove (eth->grouping + old_idx, eth->grouping + old_idx + 1, sizeof(ETableHeaderSortInfo) * (new_idx - old_idx));
- } else {
- memmove (eth->grouping + new_idx + 1, eth->grouping + new_idx, sizeof(ETableHeaderSortInfo) * (old_idx - new_idx));
+ extra_left = extra;
+ for (i = 0; i < last_resizeable; i++) {
+ if (eth->columns[i]->resizeable) {
+ int this_extra = MIN(extra_left, extra * (eth->columns[i]->expansion / expansion));
+ eth->columns[i]->width += this_extra;
+ extra_left -= this_extra;
+ }
}
- eth->grouping[new_idx] = info;
+ if (i >= 0 && i < eth->col_count && eth->columns[i]->resizeable)
+ eth->columns[i]->width += extra_left;
- gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
+ eth_update_offsets (eth);
+ gtk_signal_emit (GTK_OBJECT (eth), eth_signals [DIMENSION_CHANGE]);
}
-#endif