* src/widgets/modest-header-view-render.c:
authorJose Dapena Paz <jdapena@igalia.com>
Wed, 30 May 2007 16:55:50 +0000 (16:55 +0000)
committerJose Dapena Paz <jdapena@igalia.com>
Wed, 30 May 2007 16:55:50 +0000 (16:55 +0000)
        * (get_pixbuf_for_flag): now it also supports getting specific
          icons for high and low priorities.
        * Removed get_pixbuf_for_compact_flag,
          _modest_header_view_header_cell_data,
          _modest_header_view_compact_date_cell_data,  as it's not
          required in the new header view.
        * Modified the compact view for header view. Now it uses the
          new hbox and vbox cell renderers. Modified also to have
          specific cell renderers for the attachment and priority
          icons. Here we fill the new cell renderers using the model.
* Added src/widgets/modest-hbox-cell-renderer.c:
        * New cell renderer that let's developer embed cell renderers
          in an horizontal layout. Supports specific expanded cell
          renderers.
* Added src/widgets/modest-vbox-cell-renderer.c:
        * New cell renderer that let's developer embed cell renderers
          in an vertical layout. Supports specific expanded cell
          renderers.
* src/widgets/modest-header-view.c:
        * Now cmp_rows is only used for comparing flag columns.
        * Reworked all the sorting code, to use tree model column id's.
        * Modified the compact view for header view. Now it uses the
          new hbox and vbox cell renderers. Modified also to have
          specific cell renderers for the attachment and priority
          icons. Here we construct the cell renderers.
* src/modest-init.c:
        * Removed the old layout cells for compact view.
* src/maemo/modest-platform.c:
        * Reworked the sort dialog to fit with the new sort code
          in header view.

pmo-trunk-r2001

src/maemo/modest-msg-view-window.c
src/maemo/modest-platform.c
src/modest-init.c
src/widgets/Makefile.am
src/widgets/modest-hbox-cell-renderer.c [new file with mode: 0644]
src/widgets/modest-hbox-cell-renderer.h [new file with mode: 0644]
src/widgets/modest-header-view-priv.h
src/widgets/modest-header-view-render.c
src/widgets/modest-header-view.c
src/widgets/modest-vbox-cell-renderer.c [new file with mode: 0644]
src/widgets/modest-vbox-cell-renderer.h [new file with mode: 0644]

index 52deb47..bc8dcf2 100644 (file)
@@ -418,20 +418,20 @@ modest_msg_view_window_finalize (GObject *obj)
        ModestMsgViewWindowPrivate *priv;
 
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj);
-       if (priv->header_model != NULL) {
-               g_object_unref (priv->header_model);
-               priv->header_model = NULL;
-       }
        if (priv->clipboard_change_handler > 0) {
                g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler);
                priv->clipboard_change_handler = 0;
        }
-
-       /* disconnet operations queue observer */
        if (priv->queue_change_handler > 0) {
                g_signal_handler_disconnect (G_OBJECT (modest_runtime_get_mail_operation_queue ()), priv->queue_change_handler);
                priv->queue_change_handler = 0;
        }
+       if (priv->header_model != NULL) {
+               g_object_unref (priv->header_model);
+               priv->header_model = NULL;
+       }
+
+       /* disconnet operations queue observer */
        
        if (priv->progress_bar_timeout > 0) {
                g_source_remove (priv->progress_bar_timeout);
index 70b0f11..5161310 100644 (file)
@@ -465,11 +465,11 @@ launch_sort_headers_dialog (GtkWindow *parent_window,
 {
        ModestHeaderView *header_view = NULL;
        GList *cols = NULL;
-       GList *tmp = NULL;
        GtkSortType sort_type;
        gint sort_key;
        gint default_key = 0;
        gint result;
+       gboolean outgoing = FALSE;
        
        /* Get header window */
        if (MODEST_IS_MAIN_WINDOW (parent_window)) {
@@ -481,66 +481,50 @@ launch_sort_headers_dialog (GtkWindow *parent_window,
        /* Add sorting keys */
        cols = modest_header_view_get_columns (header_view);    
        if (cols == NULL) return;
-       int num_cols = g_list_length(cols);
-       int sort_ids[num_cols];
-       int sort_model_ids[num_cols];
-       GtkTreeViewColumn *sort_cols[num_cols];
-       for (tmp=cols; tmp; tmp=tmp->next) {
-               gint col_id = GPOINTER_TO_INT (g_object_get_data(G_OBJECT(tmp->data), MODEST_HEADER_VIEW_COLUMN));
-               switch (col_id) {
-               case MODEST_HEADER_VIEW_COLUMN_COMPACT_FLAG:
-                       sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_attachment"));
-                       sort_ids[sort_key] = col_id;
-                       sort_model_ids[sort_key] = TNY_HEADER_FLAG_ATTACHMENTS;
-                       sort_cols[sort_key] = tmp->data;
-
-                       sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_priority"));
-                       sort_ids[sort_key] = col_id;
-                       sort_model_ids[sort_key] = TNY_HEADER_FLAG_PRIORITY;
-                       sort_cols[sort_key] = tmp->data;
-                       break;
-               case MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT:
-                       sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_sender_recipient"));
-                       sort_ids[sort_key] = col_id;
-                       sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN;
-                       sort_cols[sort_key] = tmp->data;
-
-                       sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_subject"));
-                       sort_ids[sort_key] = col_id;
-                       sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN;
-                       sort_cols[sort_key] = tmp->data;
-                       break;
-               case MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN:
-                       sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_sender_recipient"));
-                       sort_ids[sort_key] = col_id;
-                       sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN;
-                       sort_cols[sort_key] = tmp->data;
-
-                       sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_subject"));
-                       sort_ids[sort_key] = col_id;
-                       sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN;
-                       sort_cols[sort_key] = tmp->data;
-                       break;
-               case MODEST_HEADER_VIEW_COLUMN_COMPACT_RECEIVED_DATE:
-                       sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_date"));
-                       sort_ids[sort_key] = col_id;
-                       sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN,
-                       sort_cols[sort_key] = tmp->data;
-                       default_key = sort_key;
-                       break;
-               case MODEST_HEADER_VIEW_COLUMN_COMPACT_SENT_DATE:
-                       sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_date"));
-                       sort_ids[sort_key] = col_id;
-                       sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN,
-                       sort_cols[sort_key] = tmp->data;
-                       default_key = sort_key;
-                       break;
-               default:
-                       g_printerr ("modest: column (id: %i) not valid", col_id);
-                       goto frees;
-               }
+       int sort_model_ids[6];
+       int sort_ids[6];
+
+       outgoing = (GPOINTER_TO_INT (g_object_get_data(G_OBJECT(cols->data), MODEST_HEADER_VIEW_COLUMN))==
+                   MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT);
+
+       sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_sender_recipient"));
+       if (outgoing) {
+               sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN;
+               sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
+       } else {
+               sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN;
+               sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
        }
-       
+
+       sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_date"));
+       if (outgoing) {
+               sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN;
+               sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_SENT_DATE;
+       } else {
+               sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN;
+               sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_RECEIVED_DATE;
+       }
+       default_key = sort_key;
+
+       sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_subject"));
+       sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN;
+       if (outgoing)
+               sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT;
+       else
+               sort_ids[sort_key] = MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN;
+
+       sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_attachment"));
+       sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
+       sort_ids[sort_key] = TNY_HEADER_FLAG_ATTACHMENTS;
+
+       sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_size"));
+       sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_MESSAGE_SIZE_COLUMN;
+       sort_ids[sort_key] = 0;
+
+       sort_key = hildon_sort_dialog_add_sort_key (dialog, _("mcen_li_sort_priority"));
+       sort_model_ids[sort_key] = TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN;
+       sort_ids[sort_key] = TNY_HEADER_FLAG_PRIORITY;
+
        /* Launch dialogs */
        hildon_sort_dialog_set_sort_key (dialog, default_key);
        hildon_sort_dialog_set_sort_order (dialog, GTK_SORT_DESCENDING);
@@ -548,19 +532,23 @@ launch_sort_headers_dialog (GtkWindow *parent_window,
        if (result == GTK_RESPONSE_OK) {
                sort_key = hildon_sort_dialog_get_sort_key (dialog);
                sort_type = hildon_sort_dialog_get_sort_order (dialog);
-               if (sort_ids[sort_key] == MODEST_HEADER_VIEW_COLUMN_COMPACT_FLAG)
-                       g_object_set_data(G_OBJECT(sort_cols[sort_key]), 
-                                         MODEST_HEADER_VIEW_FLAG_SORT, 
-                                         GINT_TO_POINTER(sort_model_ids[sort_key]));
-               
-               else
-                       gtk_tree_view_column_set_sort_column_id (sort_cols[sort_key], sort_model_ids[sort_key]);
-               
-               modest_header_view_sort_by_column_id (header_view, sort_ids[sort_key], sort_type);
+               if (sort_model_ids[sort_key] == TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN) {
+                       g_object_set_data (G_OBJECT(cols->data), MODEST_HEADER_VIEW_FLAG_SORT,
+                                          GINT_TO_POINTER (sort_ids[sort_key]));
+                       /* This is a hack to make it resort rows always when flag fields are
+                        * selected. If we do not do this, changing sort field from priority to
+                        * attachments does not work */
+                       modest_header_view_sort_by_column_id (header_view, 0, sort_type);
+               } else {
+                       gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (cols->data), 
+                                                                sort_model_ids[sort_key]);
+               }
+
+               modest_header_view_sort_by_column_id (header_view, sort_model_ids[sort_key], sort_type);
+               gtk_tree_sortable_sort_column_changed (GTK_TREE_SORTABLE (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view))));
        }
        
        /* free */
- frees:
        g_list_free(cols);      
 }
 
index 1dd4d87..ace733a 100644 (file)
@@ -77,9 +77,7 @@ static const FolderCols INBOX_COLUMNS_DETAILS[] = {
 };
 
 static const FolderCols INBOX_COLUMNS_TWOLINES[] = {
-       {MODEST_HEADER_VIEW_COLUMN_COMPACT_FLAG, 40, 0},
        {MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN, 180, 0},
-       {MODEST_HEADER_VIEW_COLUMN_COMPACT_RECEIVED_DATE, 240, -1}
 };
 
 static const FolderCols OUTBOX_COLUMNS_DETAILS[] = {
@@ -92,15 +90,12 @@ static const FolderCols OUTBOX_COLUMNS_DETAILS[] = {
 };
 
 static const FolderCols OUTBOX_COLUMNS_TWOLINES[] = {
-       {MODEST_HEADER_VIEW_COLUMN_COMPACT_FLAG, 40, 0},
        {MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT,180, 0},
        {MODEST_HEADER_VIEW_COLUMN_STATUS, 240, 0}
 };
 
 static const FolderCols SENT_COLUMNS_TWOLINES[] = {
-       {MODEST_HEADER_VIEW_COLUMN_COMPACT_FLAG, 40, 0},
        {MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT,180, 0},
-       {MODEST_HEADER_VIEW_COLUMN_COMPACT_SENT_DATE, 240, -1}
 };
 
 #ifdef MODEST_PLATFORM_MAEMO
index 702e9f2..6efc4ba 100644 (file)
@@ -30,6 +30,10 @@ libmodest_widgets_la_SOURCES=          \
        modest-folder-view.h           \
        modest-global-settings-dialog.c \
        modest-global-settings-dialog.h \
+       modest-hbox-cell-renderer.c    \
+       modest-hbox-cell-renderer.h    \
+       modest-vbox-cell-renderer.c    \
+       modest-vbox-cell-renderer.h    \
        modest-header-view-render.c    \
        modest-header-view.c           \
        modest-header-view.h           \
diff --git a/src/widgets/modest-hbox-cell-renderer.c b/src/widgets/modest-hbox-cell-renderer.c
new file mode 100644 (file)
index 0000000..9bc6f69
--- /dev/null
@@ -0,0 +1,340 @@
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <glib/gi18n-lib.h>
+
+#include <gtk/gtkwidget.h>
+
+#include <modest-text-utils.h>
+#include <modest-hbox-cell-renderer.h>
+
+#define RENDERER_EXPAND_ATTRIBUTE "box-expand"
+
+static GObjectClass *parent_class = NULL;
+
+/* /\* signals *\/ */
+/* enum { */
+/*     LAST_SIGNAL */
+/* }; */
+
+typedef struct _ModestHBoxCellRendererPrivate ModestHBoxCellRendererPrivate;
+
+struct _ModestHBoxCellRendererPrivate
+{
+       GList *renderers_list;
+};
+
+#define MODEST_HBOX_CELL_RENDERER_GET_PRIVATE(o)       \
+       (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_HBOX_CELL_RENDERER, ModestHBoxCellRendererPrivate))
+
+/* static guint signals[LAST_SIGNAL] = {0}; */
+
+/* static functions: GObject */
+static void modest_hbox_cell_renderer_instance_init (GTypeInstance *instance, gpointer g_class);
+static void modest_hbox_cell_renderer_finalize (GObject *object);
+static void modest_hbox_cell_renderer_class_init (ModestHBoxCellRendererClass *klass);
+
+/* static functions: GtkCellRenderer */
+static void modest_hbox_cell_renderer_get_size     (GtkCellRenderer       *cell,
+                                                   GtkWidget             *widget,
+                                                   GdkRectangle          *rectangle,
+                                                   gint                  *x_offset,
+                                                   gint                  *y_offset,
+                                                   gint                  *width,
+                                                   gint                  *height);
+static void modest_hbox_cell_renderer_render       (GtkCellRenderer       *cell,
+                                                   GdkDrawable           *window,
+                                                   GtkWidget             *widget,
+                                                   GdkRectangle          *background_area,
+                                                   GdkRectangle          *cell_area,
+                                                   GdkRectangle          *expose_area,
+                                                   GtkCellRendererState  flags);
+                                               
+
+/**
+ * modest_hbox_cell_renderer_new:
+ *
+ * Return value: a new #ModestHBoxCellRenderer instance implemented for Gtk+
+ **/
+GtkCellRenderer*
+modest_hbox_cell_renderer_new (void)
+{
+       ModestHBoxCellRenderer *self = g_object_new (MODEST_TYPE_HBOX_CELL_RENDERER, NULL);
+
+       return GTK_CELL_RENDERER (self);
+}
+
+static void
+modest_hbox_cell_renderer_instance_init (GTypeInstance *instance, gpointer g_class)
+{
+       ModestHBoxCellRendererPrivate *priv = MODEST_HBOX_CELL_RENDERER_GET_PRIVATE (instance);
+
+       priv->renderers_list = NULL;
+       
+       return;
+}
+
+static void
+modest_hbox_cell_renderer_finalize (GObject *object)
+{
+       ModestHBoxCellRendererPrivate *priv = MODEST_HBOX_CELL_RENDERER_GET_PRIVATE (object);
+
+       if (priv->renderers_list != NULL) {
+               g_list_foreach (priv->renderers_list, (GFunc) g_object_unref, NULL);
+               g_list_free (priv->renderers_list);
+               priv->renderers_list = NULL;
+       }
+
+       (*parent_class->finalize) (object);
+
+       return;
+}
+
+static void 
+modest_hbox_cell_renderer_class_init (ModestHBoxCellRendererClass *klass)
+{
+       GObjectClass *object_class;
+       GtkCellRendererClass *renderer_class;
+
+       parent_class = g_type_class_peek_parent (klass);
+       object_class = (GObjectClass*) klass;
+       renderer_class = (GtkCellRendererClass*) klass;
+
+       object_class->finalize = modest_hbox_cell_renderer_finalize;
+       renderer_class->get_size = modest_hbox_cell_renderer_get_size;
+       renderer_class->render = modest_hbox_cell_renderer_render;
+
+       g_type_class_add_private (object_class, sizeof (ModestHBoxCellRendererPrivate));
+
+       return;
+}
+
+GType 
+modest_hbox_cell_renderer_get_type (void)
+{
+       static GType type = 0;
+
+       if (G_UNLIKELY(type == 0))
+       {
+               static const GTypeInfo info = 
+               {
+                 sizeof (ModestHBoxCellRendererClass),
+                 NULL,   /* base_init */
+                 NULL,   /* base_finalize */
+                 (GClassInitFunc) modest_hbox_cell_renderer_class_init,   /* class_init */
+                 NULL,   /* class_finalize */
+                 NULL,   /* class_data */
+                 sizeof (ModestHBoxCellRenderer),
+                 0,      /* n_preallocs */
+                 modest_hbox_cell_renderer_instance_init    /* instance_init */
+               };
+
+               type = g_type_register_static (GTK_TYPE_CELL_RENDERER,
+                       "ModestHBoxCellRenderer",
+                       &info, 0);
+
+       }
+
+       return type;
+}
+
+
+/**
+ * modest_hbox_cell_renderer_append:
+ * @hbox_renderer: a #ModestHBoxCellRenderer
+ * @cell: a #GtkCellRenderer
+ *
+ * Appends @cell to the end of the list of renderers shown in @hbox_renderer
+ */
+void 
+modest_hbox_cell_renderer_append (ModestHBoxCellRenderer *hbox_renderer, 
+                                 GtkCellRenderer *cell,
+                                 gboolean expand)
+{
+       ModestHBoxCellRendererPrivate *priv = MODEST_HBOX_CELL_RENDERER_GET_PRIVATE (hbox_renderer);
+       
+       priv->renderers_list = g_list_append (priv->renderers_list, cell);
+       g_object_set_data (G_OBJECT (cell), RENDERER_EXPAND_ATTRIBUTE, GINT_TO_POINTER (expand));
+       g_object_ref_sink (G_OBJECT (cell));
+}
+
+static void 
+modest_hbox_cell_renderer_get_size     (GtkCellRenderer       *cell,
+                                       GtkWidget             *widget,
+                                       GdkRectangle          *rectangle,
+                                       gint                  *x_offset,
+                                       gint                  *y_offset,
+                                       gint                  *width,
+                                       gint                  *height)
+{
+       gint calc_width, calc_height;
+       gint full_width, full_height;
+       GList *node;
+       ModestHBoxCellRendererPrivate *priv = MODEST_HBOX_CELL_RENDERER_GET_PRIVATE (cell);
+
+       calc_width = 0;
+       calc_height = 0;
+
+       for (node = priv->renderers_list; node != NULL; node = g_list_next (node)) {
+               gint renderer_width, renderer_height;
+               GtkCellRenderer *renderer = (GtkCellRenderer *) node->data;
+
+               gtk_cell_renderer_get_size (renderer, widget, NULL, NULL, NULL,
+                                           &renderer_width, &renderer_height);
+               if ((renderer_width > 0)&&(renderer_height > 0)) {
+                       calc_height = MAX (calc_height, renderer_height);
+                       calc_width += renderer_width;
+               }
+       }
+
+       full_width = (gint) cell->xpad * 2 + calc_width;
+       full_height = (gint) cell->ypad * 2 + calc_height;
+
+       if (rectangle && calc_width > 0 && calc_height > 0) {
+               if (x_offset) {
+                       *x_offset = (((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ?
+                                     (1.0 - cell->xalign) : cell->xalign) *
+                                    (rectangle->width - full_width));
+                       *x_offset = MAX (*x_offset, 0);
+               }
+               if (y_offset) {
+                       *y_offset = ((cell->yalign) *
+                                    (rectangle->height - full_height));
+                       *y_offset = MAX (*y_offset, 0);
+               }
+       } else {
+               if (x_offset)
+                       *x_offset = 0;
+               if (y_offset)
+                       *y_offset = 0;
+       }
+
+       if (width)
+               *width = full_width;
+       if (height)
+               *height = full_height;
+}
+
+static void 
+modest_hbox_cell_renderer_render       (GtkCellRenderer       *cell,
+                                       GdkDrawable           *window,
+                                       GtkWidget             *widget,
+                                       GdkRectangle          *background_area,
+                                       GdkRectangle          *cell_area,
+                                       GdkRectangle          *expose_area,
+                                       GtkCellRendererState  flags)
+{
+       ModestHBoxCellRendererPrivate *priv = MODEST_HBOX_CELL_RENDERER_GET_PRIVATE (cell);
+       gint nvis_children = 0;
+       gint nexpand_children = 0;
+       GtkTextDirection direction;
+       GList *node = NULL;
+       GtkCellRenderer *child;
+       gint width, extra;
+       GtkRequisition req;
+       
+       direction = gtk_widget_get_direction (widget);
+       nvis_children = 0;
+       nexpand_children = 0;
+
+       /* first, retrieve the requisition of the children cell renderers */
+       modest_hbox_cell_renderer_get_size (cell, widget, NULL, NULL, NULL, &(req.width), &(req.height));
+
+       /* Counts visible and expandable children cell renderers */
+       for (node = priv->renderers_list; node != NULL; node = g_list_next (node)) {
+               gboolean visible, expand;
+               child = (GtkCellRenderer *) node->data;
+               g_object_get (G_OBJECT (child), "visible", &visible, NULL);
+               expand = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (child), RENDERER_EXPAND_ATTRIBUTE));
+               
+               if (visible) {
+                       nvis_children += 1;
+                       if (expand)
+                               nexpand_children += 1;
+               }
+       }
+
+       if (nvis_children > 0) {
+               gint x_pad, y_pad;
+               gint x;
+               GdkRectangle child_alloc;
+
+               if (nexpand_children > 0) {
+                       width = cell_area->width - req.width;
+                       extra = width / nexpand_children;
+               } else {
+                       width = 0;
+                       extra = 0;
+               }
+
+               g_object_get (cell, "xpad", &x_pad, "ypad", &y_pad, NULL);
+               x = cell_area->x + x_pad;
+               child_alloc.y = cell_area->y + y_pad;
+               child_alloc.height = MAX (1, cell_area->height - y_pad * 2);
+
+               for (node = priv->renderers_list; node != NULL; node = g_list_next (node)) {
+                       gboolean visible, expand;
+
+                       child = (GtkCellRenderer *) node->data;
+                       g_object_get (G_OBJECT (child), "visible", &visible, NULL);
+                       expand = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (child), RENDERER_EXPAND_ATTRIBUTE));
+
+                       if (visible) {
+                               GtkRequisition child_req;
+                               gint child_xpad, child_ypad;
+                               GdkRectangle child_expose_area;
+
+                               gtk_cell_renderer_get_size (child, widget, NULL, NULL, NULL, &(child_req.width), &(child_req.height));
+                               g_object_get (child, "xpad", &child_xpad, "ypad", &child_ypad, NULL);
+
+                               if (expand) {
+                                       if (nexpand_children == 1)
+                                               child_req.width += width;
+                                       else
+                                               child_req.width += extra;
+                                       nexpand_children -= 1;
+                                       width -= extra;
+                               }
+
+                               child_alloc.width = MAX (1, child_req.width);
+                               child_alloc.x = x;
+
+                               if (direction == GTK_TEXT_DIR_RTL)
+                                       child_alloc.x = cell_area->x + cell_area->width - (child_alloc.x - cell_area->x) - child_alloc.width;
+
+                               if (gdk_rectangle_intersect (&child_alloc, expose_area, &child_expose_area))
+                                       gtk_cell_renderer_render (child, window, widget, background_area, &child_alloc, &child_expose_area, flags);
+                               x += child_req.width;
+                       }
+               }
+       }
+       
+}
diff --git a/src/widgets/modest-hbox-cell-renderer.h b/src/widgets/modest-hbox-cell-renderer.h
new file mode 100644 (file)
index 0000000..dba7aca
--- /dev/null
@@ -0,0 +1,67 @@
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MODEST_HBOX_CELL_RENDERER_H
+#define MODEST_HBOX_CELL_RENDERER_H
+#include <glib-object.h>
+#include <gtk/gtkcellrenderer.h>
+
+G_BEGIN_DECLS
+
+#define MODEST_TYPE_HBOX_CELL_RENDERER             (modest_hbox_cell_renderer_get_type ())
+#define MODEST_HBOX_CELL_RENDERER(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), MODEST_TYPE_HBOX_CELL_RENDERER, ModestHBoxCellRenderer))
+#define MODEST_HBOX_CELL_RENDERER_CLASS(vtable)    (G_TYPE_CHECK_CLASS_CAST ((vtable), MODEST_TYPE_HBOX_CELL_RENDERER, ModestHBoxCellRendererClass))
+#define MODEST_IS_HBOX_CELL_RENDERER(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MODEST_TYPE_HBOX_CELL_RENDERER))
+#define MODEST_IS_HBOX_CELL_RENDERER_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MODEST_TYPE_HBOX_CELL_RENDERER))
+#define MODEST_HBOX_CELL_RENDERER_GET_CLASS(inst)  (G_TYPE_INSTANCE_GET_CLASS ((inst), MODEST_TYPE_HBOX_CELL_RENDERER, ModestHBoxCellRendererClass))
+
+typedef struct _ModestHBoxCellRenderer ModestHBoxCellRenderer;
+typedef struct _ModestHBoxCellRendererClass ModestHBoxCellRendererClass;
+
+struct _ModestHBoxCellRenderer
+{
+       GtkCellRenderer parent;
+
+};
+
+struct _ModestHBoxCellRendererClass
+{
+       GtkCellRendererClass parent_class;
+
+};
+
+GType modest_hbox_cell_renderer_get_type (void);
+
+GtkCellRenderer* modest_hbox_cell_renderer_new (void);
+
+void modest_hbox_cell_renderer_append (ModestHBoxCellRenderer *hbox_renderer, GtkCellRenderer *cell, gboolean expand);
+
+G_END_DECLS
+
+#endif
index 9a2a985..ad5f263 100644 (file)
@@ -46,15 +46,10 @@ void _modest_header_view_msgtype_cell_data (GtkTreeViewColumn *column, GtkCellRe
                                            GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data);
 void _modest_header_view_attach_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
                                           GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data);
-void _modest_header_view_compact_flag_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
-                                                GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data);
 void _modest_header_view_header_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
                                            GtkTreeModel *tree_model,  GtkTreeIter *iter,  gpointer user_data);
 void _modest_header_view_date_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
                                          GtkTreeModel *tree_model,  GtkTreeIter *iter,  gpointer user_data);
-void _modest_header_view_compact_date_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
-                                                 GtkTreeModel *tree_model,  GtkTreeIter *iter,
-                                                 gpointer user_data);
 void _modest_header_view_size_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
                                          GtkTreeModel *tree_model,  GtkTreeIter *iter,  gpointer user_data);
 void _modest_header_view_status_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
index 80158e0..6ab9e3b 100644 (file)
@@ -44,6 +44,8 @@ get_pixbuf_for_flag (TnyHeaderFlags flag)
        static GdkPixbuf *seen_pixbuf             = NULL;
        static GdkPixbuf *unread_pixbuf           = NULL;
        static GdkPixbuf *attachments_pixbuf      = NULL;
+       static GdkPixbuf *high_pixbuf             = NULL;
+       static GdkPixbuf *low_pixbuf             = NULL;
        
        switch (flag) {
        case TNY_HEADER_FLAG_DELETED:
@@ -58,6 +60,14 @@ get_pixbuf_for_flag (TnyHeaderFlags flag)
                if (G_UNLIKELY(!attachments_pixbuf))
                        attachments_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_ATTACH);
                return attachments_pixbuf;
+       case TNY_HEADER_FLAG_HIGH_PRIORITY:
+               if (G_UNLIKELY(!high_pixbuf))
+                       high_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_HIGH_PRIORITY);
+               return high_pixbuf;
+       case TNY_HEADER_FLAG_LOW_PRIORITY:
+               if (G_UNLIKELY(!low_pixbuf))
+                       low_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_LOW_PRIORITY);
+               return low_pixbuf;
        default:
                if (G_UNLIKELY(!unread_pixbuf))
                        unread_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_UNREAD);
@@ -65,57 +75,6 @@ get_pixbuf_for_flag (TnyHeaderFlags flag)
        }
 }
 
-static GdkPixbuf*
-get_pixbuf_for_compact_flag (TnyHeaderFlags flags)
-{
-       /* optimization */
-       static GdkPixbuf *high_attachments_pixbuf   = NULL;
-       static GdkPixbuf *normal_attachments_pixbuf = NULL;
-       static GdkPixbuf *low_attachments_pixbuf    = NULL;
-       static GdkPixbuf *high_pixbuf               = NULL;
-       static GdkPixbuf *low_pixbuf                = NULL;
-       static GdkPixbuf *normal_pixbuf             = NULL;
-
-       TnyHeaderPriorityFlags prior;
-
-       prior = flags & TNY_HEADER_FLAG_PRIORITY;
-       switch (prior) {
-       case TNY_HEADER_FLAG_HIGH_PRIORITY:
-               if (flags & TNY_HEADER_FLAG_ATTACHMENTS) {
-                       if (G_UNLIKELY(!high_attachments_pixbuf))
-                               high_attachments_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_ATTACH_HIGH_PRIORITY);
-                       return high_attachments_pixbuf;
-               } else {
-                       if (G_UNLIKELY(!high_pixbuf))
-                               high_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_HIGH_PRIORITY);
-                       return high_pixbuf;
-               }
-               break;
-       case TNY_HEADER_FLAG_LOW_PRIORITY:
-               if (flags & TNY_HEADER_FLAG_ATTACHMENTS) {
-                       if (G_UNLIKELY(!low_attachments_pixbuf))
-                               low_attachments_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_ATTACH_LOW_PRIORITY);
-                       return low_attachments_pixbuf;
-               } else {                
-                       if (G_UNLIKELY(!low_pixbuf))
-                               low_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_LOW_PRIORITY);
-                       return low_pixbuf;
-               }
-               break;
-       default:
-               if (flags & TNY_HEADER_FLAG_ATTACHMENTS) {
-                       if (G_UNLIKELY(!normal_attachments_pixbuf))
-                               normal_attachments_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_ATTACH_NORM_PRIORITY);
-                       return normal_attachments_pixbuf;
-               } else {                
-                       if (G_UNLIKELY(!normal_pixbuf))
-                               normal_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_NORM_PRIORITY);
-                       return normal_pixbuf;
-               }
-       }
-       return NULL;
-}
-
 static void
 set_common_flags (GtkCellRenderer *renderer, TnyHeaderFlags flags)
 {
@@ -162,20 +121,6 @@ _modest_header_view_attach_cell_data (GtkTreeViewColumn *column, GtkCellRenderer
 }
 
 void
-_modest_header_view_compact_flag_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
-                                           GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data)
-{
-       TnyHeaderFlags flags;
-       GdkPixbuf* pixbuf = NULL;
-
-       gtk_tree_model_get (tree_model, iter, TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN,
-                           &flags, -1);
-       
-       pixbuf = get_pixbuf_for_compact_flag (flags);
-       g_object_set (G_OBJECT (renderer), "pixbuf", pixbuf, NULL);
-}
-
-void
 _modest_header_view_header_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
                  GtkTreeModel *tree_model,  GtkTreeIter *iter,  gpointer user_data)
 {
@@ -215,37 +160,6 @@ _modest_header_view_date_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer
 }
 
 void
-_modest_header_view_compact_date_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
-                                            GtkTreeModel *tree_model,  GtkTreeIter *iter,
-                                            gpointer user_data)
-{
-       TnyHeaderFlags flags;
-       guint date, date_col;
-       gchar *display_date = NULL, *tmp_date = NULL;
-       gboolean received = GPOINTER_TO_INT(user_data);
-
-       if (received)
-               date_col = TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN;
-       else
-               date_col = TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN;
-
-       gtk_tree_model_get (tree_model, iter,
-                           TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags,
-                           date_col, &date,
-                           -1);
-
-       tmp_date = modest_text_utils_get_display_date (date);
-       display_date = g_strdup_printf ("\n<small>%s</small>", tmp_date);
-       g_object_set (G_OBJECT(renderer),
-                     "markup", display_date,
-                     NULL);    
-
-       set_common_flags (renderer, flags);
-       g_free (tmp_date);
-       g_free (display_date);
-}
-
-void
 _modest_header_view_sender_receiver_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
                            GtkTreeModel *tree_model,  GtkTreeIter *iter,  gboolean is_sender)
 {
@@ -279,11 +193,22 @@ void
 _modest_header_view_compact_header_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
                                               GtkTreeModel *tree_model,  GtkTreeIter *iter,  gpointer user_data)
 {
-       GObject *rendobj;
        TnyHeaderFlags flags;
        gchar *address, *subject, *header;
        time_t date;
        gboolean is_incoming;
+       GtkCellRenderer *recipient_cell, *date_cell, *subject_cell,
+               *attach_cell, *priority_cell,
+               *recipient_box, *subject_box;
+       gchar *display_date = NULL, *tmp_date = NULL;
+
+       recipient_box = GTK_CELL_RENDERER (g_object_get_data (G_OBJECT (renderer), "recpt-box-renderer"));
+       subject_box = GTK_CELL_RENDERER (g_object_get_data (G_OBJECT (renderer), "subject-box-renderer"));
+       priority_cell = GTK_CELL_RENDERER (g_object_get_data (G_OBJECT (subject_box), "priority-renderer"));
+       subject_cell = GTK_CELL_RENDERER (g_object_get_data (G_OBJECT (subject_box), "subject-renderer"));
+       attach_cell = GTK_CELL_RENDERER (g_object_get_data (G_OBJECT (recipient_box), "attach-renderer"));
+       recipient_cell = GTK_CELL_RENDERER (g_object_get_data (G_OBJECT (recipient_box), "recipient-renderer"));
+       date_cell = GTK_CELL_RENDERER (g_object_get_data (G_OBJECT (recipient_box), "date-renderer"));
 
        is_incoming = GPOINTER_TO_INT(user_data); /* GPOINTER_TO_BOOLEAN is not available
                                                   * in older versions of glib...*/
@@ -303,15 +228,39 @@ _modest_header_view_compact_header_cell_data  (GtkTreeViewColumn *column,  GtkCe
                                    TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &date,   
                                    -1);
 
-       rendobj = G_OBJECT(renderer);
-       header = g_markup_printf_escaped ("%s\n<small>%s</small>",
-                                         (subject && strlen(subject)) ? subject : _("mail_va_no_subject"),
-                                         modest_text_utils_get_display_address(address));
-       g_free (address);
+       /* flags */
+       if (flags & TNY_HEADER_FLAG_ATTACHMENTS)
+               g_object_set (G_OBJECT (attach_cell), "pixbuf",
+                             get_pixbuf_for_flag (TNY_HEADER_FLAG_ATTACHMENTS),
+                             NULL);
+       else
+               g_object_set (G_OBJECT (attach_cell), "pixbuf",
+                             get_pixbuf_for_flag (0), NULL);
+       if (flags & TNY_HEADER_FLAG_PRIORITY)
+               g_object_set (G_OBJECT (priority_cell), "pixbuf",
+                             get_pixbuf_for_flag (flags & TNY_HEADER_FLAG_PRIORITY),
+                             NULL);
+       else
+               g_object_set (G_OBJECT (priority_cell), "pixbuf",
+                             get_pixbuf_for_flag (0), NULL);
+       header = g_markup_printf_escaped ("%s", (subject && strlen (subject)) ? subject : _("mail_va_no_subject"));
        g_free (subject);
+       g_object_set (G_OBJECT (subject_cell), "markup", header, NULL);
+       set_common_flags (subject_cell, flags);
 
-       g_object_set (rendobj, "markup", header, NULL); 
-       set_common_flags (renderer, flags);
+       header = g_markup_printf_escaped ("<small>%s</small>", modest_text_utils_get_display_address (address));
+       g_free (address);
+       g_object_set (G_OBJECT (recipient_cell), "markup", header, NULL);
+
+       g_object_set (G_OBJECT (recipient_cell), "markup", header, NULL);       
+       set_common_flags (recipient_cell, flags);
+
+       tmp_date = modest_text_utils_get_display_date (date);
+       display_date = g_strdup_printf ("<small>%s</small>", tmp_date);
+       g_object_set (G_OBJECT (date_cell), "markup", display_date, NULL);
+       g_free (tmp_date);
+       g_free (display_date);
+       set_common_flags (date_cell, flags);
        
        g_free (header);
 }
index 1f84bb2..c4f239d 100644 (file)
@@ -43,6 +43,8 @@
 #include <modest-icon-names.h>
 #include <modest-runtime.h>
 #include "modest-platform.h"
+#include <modest-hbox-cell-renderer.h>
+#include <modest-vbox-cell-renderer.h>
 
 static void modest_header_view_class_init  (ModestHeaderViewClass *klass);
 static void modest_header_view_init        (ModestHeaderView *obj);
@@ -52,8 +54,8 @@ static gboolean      on_header_clicked      (GtkWidget *widget,
                                            GdkEventButton *event, 
                                            gpointer user_data);
 
-static gint          cmp_rows               (GtkTreeModel *tree_model, 
-                                            GtkTreeIter *iter1, 
+static gint          cmp_rows               (GtkTreeModel *tree_model,
+                                            GtkTreeIter *iter1,
                                             GtkTreeIter *iter2,
                                             gpointer user_data);
 
@@ -230,8 +232,6 @@ get_new_column (const gchar *name, GtkCellRenderer *renderer,
 }
 
 
-
-
 static void
 remove_all_columns (ModestHeaderView *obj)
 {
@@ -252,9 +252,12 @@ modest_header_view_set_columns (ModestHeaderView *self, const GList *columns, Tn
        GtkTreeViewColumn *column=NULL;
        GtkTreeSelection *selection = NULL;
        GtkCellRenderer *renderer_msgtype,*renderer_header,
-               *renderer_attach,  *renderer_comptact_flag, 
-               *renderer_compact_date;
+               *renderer_attach, *renderer_compact_date;
+       GtkCellRenderer *renderer_compact_header, *renderer_recpt_box, 
+               *renderer_subject, *renderer_subject_box, *renderer_recpt,
+               *renderer_priority;
        ModestHeaderViewPrivate *priv;
+       GtkTreeViewColumn *compact_column = NULL;
        const GList *cursor;
        
        priv = MODEST_HEADER_VIEW_GET_PRIVATE(self); 
@@ -262,16 +265,46 @@ modest_header_view_set_columns (ModestHeaderView *self, const GList *columns, Tn
        /* FIXME: check whether these renderers need to be freed */
        renderer_msgtype = gtk_cell_renderer_pixbuf_new ();
        renderer_attach  = gtk_cell_renderer_pixbuf_new ();
+       renderer_priority  = gtk_cell_renderer_pixbuf_new ();
        renderer_header  = gtk_cell_renderer_text_new ();
-       renderer_comptact_flag  = gtk_cell_renderer_pixbuf_new ();
+
+       renderer_compact_header = modest_vbox_cell_renderer_new ();
+       renderer_recpt_box = modest_hbox_cell_renderer_new ();
+       renderer_subject_box = modest_hbox_cell_renderer_new ();
+       renderer_recpt = gtk_cell_renderer_text_new ();
+       renderer_subject = gtk_cell_renderer_text_new ();
        renderer_compact_date  = gtk_cell_renderer_text_new ();
 
+       modest_vbox_cell_renderer_append (MODEST_VBOX_CELL_RENDERER (renderer_compact_header), renderer_subject_box, FALSE);
+       g_object_set_data (G_OBJECT (renderer_compact_header), "subject-box-renderer", renderer_subject_box);
+       modest_vbox_cell_renderer_append (MODEST_VBOX_CELL_RENDERER (renderer_compact_header), renderer_recpt_box, FALSE);
+       g_object_set_data (G_OBJECT (renderer_compact_header), "recpt-box-renderer", renderer_recpt_box);
+       modest_hbox_cell_renderer_append (MODEST_HBOX_CELL_RENDERER (renderer_subject_box), renderer_priority, FALSE);
+       g_object_set_data (G_OBJECT (renderer_subject_box), "priority-renderer", renderer_priority);
+       modest_hbox_cell_renderer_append (MODEST_HBOX_CELL_RENDERER (renderer_subject_box), renderer_subject, TRUE);
+       g_object_set_data (G_OBJECT (renderer_subject_box), "subject-renderer", renderer_subject);
+       modest_hbox_cell_renderer_append (MODEST_HBOX_CELL_RENDERER (renderer_recpt_box), renderer_attach, FALSE);
+       g_object_set_data (G_OBJECT (renderer_recpt_box), "attach-renderer", renderer_attach);
+       modest_hbox_cell_renderer_append (MODEST_HBOX_CELL_RENDERER (renderer_recpt_box), renderer_recpt, TRUE);
+       g_object_set_data (G_OBJECT (renderer_recpt_box), "recipient-renderer", renderer_recpt);
+       modest_hbox_cell_renderer_append (MODEST_HBOX_CELL_RENDERER (renderer_recpt_box), renderer_compact_date, FALSE);
+       g_object_set_data (G_OBJECT (renderer_recpt_box), "date-renderer", renderer_compact_date);
+
        g_object_set(G_OBJECT(renderer_header),
                     "ellipsize", PANGO_ELLIPSIZE_END,
                     NULL);
+       g_object_set (G_OBJECT (renderer_subject),
+                     "ellipsize", PANGO_ELLIPSIZE_END,
+                     NULL);
+       g_object_set (G_OBJECT (renderer_recpt),
+                     "ellipsize", PANGO_ELLIPSIZE_END,
+                     NULL);
        g_object_set(G_OBJECT(renderer_compact_date),
                     "xalign", 1.0,
                     NULL);
+
+       gtk_cell_renderer_set_fixed_size (renderer_attach, 32, 32);
+       gtk_cell_renderer_set_fixed_size (renderer_priority, 32, 32);
        
        remove_all_columns (self);
 
@@ -326,29 +359,22 @@ modest_header_view_set_columns (ModestHeaderView *self, const GList *columns, Tn
                                                 GINT_TO_POINTER(FALSE));
                        break;
                        
-               case MODEST_HEADER_VIEW_COLUMN_COMPACT_FLAG:
-                       column = get_new_column (_("F"), renderer_comptact_flag, FALSE,
-                                                TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN,
-                                                FALSE,
-                                                (GtkTreeCellDataFunc)_modest_header_view_compact_flag_cell_data,
-                                                NULL);
-                       gtk_tree_view_column_set_fixed_width (column, 45);
-                       break;
-
                case MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN:
-                       column = get_new_column (_("Header"), renderer_header, TRUE,
-                                                TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN,
-                                                TRUE,
-                                                (GtkTreeCellDataFunc)_modest_header_view_compact_header_cell_data,
-                                                GINT_TO_POINTER(TRUE));
+                       column = get_new_column (_("Header"), renderer_compact_header, TRUE,
+                                                    TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN,
+                                                    FALSE,
+                                                    (GtkTreeCellDataFunc)_modest_header_view_compact_header_cell_data,
+                                                    GINT_TO_POINTER(TRUE));
+                       compact_column = column;
                        break;
 
                case MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT:
-                       column = get_new_column (_("Header"), renderer_header, TRUE,
-                                                TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN,
-                                                TRUE,
-                                                (GtkTreeCellDataFunc)_modest_header_view_compact_header_cell_data,
-                                                GINT_TO_POINTER(FALSE));
+                       column = get_new_column (_("Header"), renderer_compact_header, TRUE,
+                                                    TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN,
+                                                    FALSE,
+                                                    (GtkTreeCellDataFunc)_modest_header_view_compact_header_cell_data,
+                                                    GINT_TO_POINTER(FALSE));
+                       compact_column = column;
                        break;
 
                        
@@ -376,23 +402,6 @@ modest_header_view_set_columns (ModestHeaderView *self, const GList *columns, Tn
                                                 GINT_TO_POINTER(FALSE));
                        break;
                        
-               case MODEST_HEADER_VIEW_COLUMN_COMPACT_RECEIVED_DATE:
-                       column = get_new_column (_("Received"), renderer_compact_date, FALSE,
-                                                TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN,
-                                                TRUE,
-                                                (GtkTreeCellDataFunc)_modest_header_view_compact_date_cell_data,
-                                                GINT_TO_POINTER(TRUE));
-                       gtk_tree_view_column_set_fixed_width (column, 130);
-                       break;
-                       
-               case MODEST_HEADER_VIEW_COLUMN_COMPACT_SENT_DATE:                                             
-                       column = get_new_column (_("Sent"), renderer_compact_date, FALSE,
-                                                TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN,
-                                                TRUE,
-                                                (GtkTreeCellDataFunc)_modest_header_view_compact_date_cell_data,
-                                                GINT_TO_POINTER(FALSE));
-                       gtk_tree_view_column_set_fixed_width (column, 130);
-                       break;
                case MODEST_HEADER_VIEW_COLUMN_SIZE:
                        column = get_new_column (_("Size"), renderer_header, TRUE,
                                                 TNY_GTK_HEADER_LIST_MODEL_MESSAGE_SIZE_COLUMN,
@@ -412,13 +421,6 @@ modest_header_view_set_columns (ModestHeaderView *self, const GList *columns, Tn
                        g_return_val_if_reached(FALSE);
                }
 
-               if (sortable) {
-                       gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(sortable),
-                                                        col,
-                                                        (GtkTreeIterCompareFunc) cmp_rows,
-                                                        column, NULL);
-               }
-
                /* we keep the column id around */
                g_object_set_data (G_OBJECT(column), MODEST_HEADER_VIEW_COLUMN,
                                   GINT_TO_POINTER(col));
@@ -429,6 +431,14 @@ modest_header_view_set_columns (ModestHeaderView *self, const GList *columns, Tn
                gtk_tree_view_append_column (GTK_TREE_VIEW(self), column);              
        }               
 
+       if (sortable) {
+               gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(sortable),
+                                                TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN,
+                                                (GtkTreeIterCompareFunc) cmp_rows,
+                                                compact_column, NULL);
+       }
+
+
        return TRUE;
 }
 
@@ -781,15 +791,6 @@ modest_header_view_set_folder_intern (ModestHeaderView *self, TnyFolder *folder)
 
        /* install our special sorting functions */
        cursor = cols = gtk_tree_view_get_columns (GTK_TREE_VIEW(self));
-       while (cursor) {
-               gint col_id = GPOINTER_TO_INT (g_object_get_data(G_OBJECT(cursor->data),
-                                                                MODEST_HEADER_VIEW_COLUMN));
-               gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(sortable),
-                                                col_id,
-                                                (GtkTreeIterCompareFunc) cmp_rows,
-                                                cursor->data, NULL);
-               cursor = g_list_next(cursor);
-       }
 
        /* Restore sort column id */
        if (cols) {
@@ -799,6 +800,10 @@ modest_header_view_set_folder_intern (ModestHeaderView *self, TnyFolder *folder)
                gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(sortable),
                                                      sort_colid,
                                                      sort_type);
+               gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(sortable),
+                                                TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN,
+                                                (GtkTreeIterCompareFunc) cmp_rows,
+                                                cols->data, NULL);
        }
 
        /* Set new model */
@@ -806,7 +811,7 @@ modest_header_view_set_folder_intern (ModestHeaderView *self, TnyFolder *folder)
        g_object_unref (G_OBJECT (sortable));
 
        /* Free */
-       g_list_free (cols);     
+       g_list_free (cols);
 }
 
 void
@@ -1023,13 +1028,12 @@ cmp_rows (GtkTreeModel *tree_model, GtkTreeIter *iter1, GtkTreeIter *iter2,
        gint col_id;
        gint t1, t2;
        gint val1, val2;
-       gchar *s1, *s2;
-       gint cmp;       
-       gint sort_colid;
+       gint cmp;
        static int counter = 0;
 
        g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN(user_data), 0);
-       col_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(user_data), MODEST_HEADER_VIEW_COLUMN));
+/*     col_id = gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (tree_model)); */
+       col_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(user_data), MODEST_HEADER_VIEW_FLAG_SORT));
        
        if (!(++counter % 100)) {
                GObject *header_view = g_object_get_data(G_OBJECT(user_data),
@@ -1037,147 +1041,35 @@ cmp_rows (GtkTreeModel *tree_model, GtkTreeIter *iter1, GtkTreeIter *iter2,
                g_signal_emit (header_view,
                               signals[STATUS_UPDATE_SIGNAL],
                               0, _("Sorting..."), 0, 0);
-       }       
-       switch (col_id) {               
-       case MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_IN:
-       case MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER_OUT:
-               sort_colid = gtk_tree_view_column_get_sort_column_id (GTK_TREE_VIEW_COLUMN(user_data));
-               gtk_tree_model_get (tree_model, iter1,
-                                   sort_colid, &s1,
-                                   TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1,
-                                   -1);
-               gtk_tree_model_get (tree_model, iter2,
-                                   sort_colid, &s2,
-                                   TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2,
-                                   -1);
-               cmp = modest_text_utils_utf8_strcmp (s1, s2, TRUE);
-               g_free (s1);
-               g_free (s2);
-               
-               return cmp ? cmp : t1 - t2;
-               
-               break;
-
-       case MODEST_HEADER_VIEW_COLUMN_COMPACT_RECEIVED_DATE:
-       case MODEST_HEADER_VIEW_COLUMN_RECEIVED_DATE:
-
-               gtk_tree_model_get (tree_model, iter1,
-                                   TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN,
-                                   &t1,-1);
-               gtk_tree_model_get (tree_model, iter2,
-                                   TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN,
-                                   &t2,-1);
-               return t1 - t2;
-
-       case MODEST_HEADER_VIEW_COLUMN_COMPACT_SENT_DATE:
-       case MODEST_HEADER_VIEW_COLUMN_SENT_DATE:
-               gtk_tree_model_get (tree_model, iter1,
-                                   TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN,
-                                   &t1,-1);
-               gtk_tree_model_get (tree_model, iter2,
-                                   TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN,
-                                   &t2,-1);
-               return t1 - t2;
-
-               
-               /* next ones, we try the search criteria first, if they're the same, then we use 'sent date' */
-               /* FIXME: what about received-date? */
-       case MODEST_HEADER_VIEW_COLUMN_SUBJECT: {
-
-               gtk_tree_model_get (tree_model, iter1,
-                                   TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN, &s1,
-                                   TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1,
-                                   -1);
-               gtk_tree_model_get (tree_model, iter2,
-                                   TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN, &s2,
-                                   TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2,
-                                   -1);
-
-               /* the prefix ('Re:', 'Fwd:' etc.) we ignore */ 
-               cmp = modest_text_utils_utf8_strcmp (s1 + modest_text_utils_get_subject_prefix_len(s1),
-                                                    s2 + modest_text_utils_get_subject_prefix_len(s2),
-                                                    TRUE);
-               g_free (s1);
-               g_free (s2);
-               
-               return cmp ? cmp : t1 - t2;
        }
-               
-       case MODEST_HEADER_VIEW_COLUMN_FROM:
-               
-               gtk_tree_model_get (tree_model, iter1,
-                                   TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN, &s1,
-                                   TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1,
-                                   -1);
-               gtk_tree_model_get (tree_model, iter2,
-                                   TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN, &s2,
-                                   TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2,
-                                   -1);
-               cmp = modest_text_utils_utf8_strcmp (s1, s2, TRUE);
-               g_free (s1);
-               g_free (s2);
-               
-               return cmp ? cmp : t1 - t2;
-               
-       case MODEST_HEADER_VIEW_COLUMN_TO: 
-               
-               gtk_tree_model_get (tree_model, iter1,
-                                   TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN, &s1,
-                                   TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1,
-                                   -1);
-               gtk_tree_model_get (tree_model, iter2,
-                                   TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN, &s2,
-                                   TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2,
-                                   -1);
-               cmp = modest_text_utils_utf8_strcmp (s1, s2, TRUE);
-               g_free (s1);
-               g_free (s2);
-               
-               return cmp ? cmp : t1 - t2;
-
-       case MODEST_HEADER_VIEW_COLUMN_ATTACH:
+       switch (col_id) {
+       case TNY_HEADER_FLAG_ATTACHMENTS:
 
                gtk_tree_model_get (tree_model, iter1, TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &val1,
                                    TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1, -1);
                gtk_tree_model_get (tree_model, iter2, TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &val2,
                                    TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2, -1);
-               
+
                cmp = (val1 & TNY_HEADER_FLAG_ATTACHMENTS) -
                        (val2 & TNY_HEADER_FLAG_ATTACHMENTS);
 
                return cmp ? cmp : t1 - t2;
                
-       case MODEST_HEADER_VIEW_COLUMN_MSGTYPE:
+       case TNY_HEADER_FLAG_PRIORITY:
                gtk_tree_model_get (tree_model, iter1, TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &val1,
                                    TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1,-1);
                gtk_tree_model_get (tree_model, iter2, TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &val2,
                                    TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2,-1);
-               cmp =  (val1 & TNY_HEADER_FLAG_SEEN) - (val2 & TNY_HEADER_FLAG_SEEN);
 
-               return cmp ? cmp : t1 - t2;
+               /* This is for making priority values respect the intuitive sort relationship 
+                * as HIGH is 11, LOW is 01, and we put NORMAL AS 10 (2) */
+               if (val1 == 0) val1 = 2;
+               if (val2 == 0) val2 = 2;
 
-       case MODEST_HEADER_VIEW_COLUMN_COMPACT_FLAG:
-               gtk_tree_model_get (tree_model, iter1, TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &val1,
-                                   TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t1, -1);
-               gtk_tree_model_get (tree_model, iter2, TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &val2,
-                                   TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &t2, -1);
+               cmp =  (val1 & TNY_HEADER_FLAG_PRIORITY) - (val2 & TNY_HEADER_FLAG_PRIORITY);
 
-               int flag_sort = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(user_data), MODEST_HEADER_VIEW_FLAG_SORT));
-               switch (flag_sort) {
-               case TNY_HEADER_FLAG_ATTACHMENTS:
-                       cmp = (val1 & TNY_HEADER_FLAG_ATTACHMENTS) -
-                               (val2 & TNY_HEADER_FLAG_ATTACHMENTS);
-                       break;
-               case TNY_HEADER_FLAG_PRIORITY:
-                       cmp = (val1 & TNY_HEADER_FLAG_PRIORITY) -
-                               (val2 & TNY_HEADER_FLAG_PRIORITY);
-                       break;
-               default:
-                       cmp = (val1 & TNY_HEADER_FLAG_PRIORITY) -
-                               (val2 & TNY_HEADER_FLAG_PRIORITY);
-               }
-               
                return cmp ? cmp : t1 - t2;
+
        default:
                return &iter1 - &iter2; /* oughhhh  */
        }
@@ -1326,9 +1218,6 @@ on_focus_in (GtkWidget     *self,
        return FALSE;
 }
 
-/*
- *
- */
 static void
 folder_monitor_update (TnyFolderObserver *self, 
                       TnyFolderChange *change)
diff --git a/src/widgets/modest-vbox-cell-renderer.c b/src/widgets/modest-vbox-cell-renderer.c
new file mode 100644 (file)
index 0000000..323dce0
--- /dev/null
@@ -0,0 +1,337 @@
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <glib/gi18n-lib.h>
+
+#include <gtk/gtkwidget.h>
+
+#include <modest-text-utils.h>
+#include <modest-vbox-cell-renderer.h>
+
+#define RENDERER_EXPAND_ATTRIBUTE "box-expand"
+
+static GObjectClass *parent_class = NULL;
+
+/* /\* signals *\/ */
+/* enum { */
+/*     LAST_SIGNAL */
+/* }; */
+
+typedef struct _ModestVBoxCellRendererPrivate ModestVBoxCellRendererPrivate;
+
+struct _ModestVBoxCellRendererPrivate
+{
+       GList *renderers_list;
+};
+
+#define MODEST_VBOX_CELL_RENDERER_GET_PRIVATE(o)       \
+       (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_VBOX_CELL_RENDERER, ModestVBoxCellRendererPrivate))
+
+/* static guint signals[LAST_SIGNAL] = {0}; */
+
+/* static functions: GObject */
+static void modest_vbox_cell_renderer_instance_init (GTypeInstance *instance, gpointer g_class);
+static void modest_vbox_cell_renderer_finalize (GObject *object);
+static void modest_vbox_cell_renderer_class_init (ModestVBoxCellRendererClass *klass);
+
+/* static functions: GtkCellRenderer */
+static void modest_vbox_cell_renderer_get_size     (GtkCellRenderer       *cell,
+                                                   GtkWidget             *widget,
+                                                   GdkRectangle          *rectangle,
+                                                   gint                  *x_offset,
+                                                   gint                  *y_offset,
+                                                   gint                  *width,
+                                                   gint                  *height);
+static void modest_vbox_cell_renderer_render       (GtkCellRenderer       *cell,
+                                                   GdkDrawable           *window,
+                                                   GtkWidget             *widget,
+                                                   GdkRectangle          *background_area,
+                                                   GdkRectangle          *cell_area,
+                                                   GdkRectangle          *expose_area,
+                                                   GtkCellRendererState  flags);
+                                               
+
+/**
+ * modest_vbox_cell_renderer_new:
+ *
+ * Return value: a new #ModestVBoxCellRenderer instance implemented for Gtk+
+ **/
+GtkCellRenderer*
+modest_vbox_cell_renderer_new (void)
+{
+       ModestVBoxCellRenderer *self = g_object_new (MODEST_TYPE_VBOX_CELL_RENDERER, NULL);
+
+       return GTK_CELL_RENDERER (self);
+}
+
+static void
+modest_vbox_cell_renderer_instance_init (GTypeInstance *instance, gpointer g_class)
+{
+       ModestVBoxCellRendererPrivate *priv = MODEST_VBOX_CELL_RENDERER_GET_PRIVATE (instance);
+
+       priv->renderers_list = NULL;
+       
+       return;
+}
+
+static void
+modest_vbox_cell_renderer_finalize (GObject *object)
+{
+       ModestVBoxCellRendererPrivate *priv = MODEST_VBOX_CELL_RENDERER_GET_PRIVATE (object);
+
+       if (priv->renderers_list != NULL) {
+               g_list_foreach (priv->renderers_list, (GFunc) g_object_unref, NULL);
+               g_list_free (priv->renderers_list);
+               priv->renderers_list = NULL;
+       }
+
+       (*parent_class->finalize) (object);
+
+       return;
+}
+
+static void 
+modest_vbox_cell_renderer_class_init (ModestVBoxCellRendererClass *klass)
+{
+       GObjectClass *object_class;
+       GtkCellRendererClass *renderer_class;
+
+       parent_class = g_type_class_peek_parent (klass);
+       object_class = (GObjectClass*) klass;
+       renderer_class = (GtkCellRendererClass*) klass;
+
+       object_class->finalize = modest_vbox_cell_renderer_finalize;
+       renderer_class->get_size = modest_vbox_cell_renderer_get_size;
+       renderer_class->render = modest_vbox_cell_renderer_render;
+
+       g_type_class_add_private (object_class, sizeof (ModestVBoxCellRendererPrivate));
+
+       return;
+}
+
+GType 
+modest_vbox_cell_renderer_get_type (void)
+{
+       static GType type = 0;
+
+       if (G_UNLIKELY(type == 0))
+       {
+               static const GTypeInfo info = 
+               {
+                 sizeof (ModestVBoxCellRendererClass),
+                 NULL,   /* base_init */
+                 NULL,   /* base_finalize */
+                 (GClassInitFunc) modest_vbox_cell_renderer_class_init,   /* class_init */
+                 NULL,   /* class_finalize */
+                 NULL,   /* class_data */
+                 sizeof (ModestVBoxCellRenderer),
+                 0,      /* n_preallocs */
+                 modest_vbox_cell_renderer_instance_init    /* instance_init */
+               };
+
+               type = g_type_register_static (GTK_TYPE_CELL_RENDERER,
+                       "ModestVBoxCellRenderer",
+                       &info, 0);
+
+       }
+
+       return type;
+}
+
+
+/**
+ * modest_vbox_cell_renderer_append:
+ * @vbox_renderer: a #ModestVBoxCellRenderer
+ * @cell: a #GtkCellRenderer
+ *
+ * Appends @cell to the end of the list of renderers shown in @vbox_renderer
+ */
+void 
+modest_vbox_cell_renderer_append (ModestVBoxCellRenderer *vbox_renderer, 
+                                 GtkCellRenderer *cell,
+                                 gboolean expand)
+{
+       ModestVBoxCellRendererPrivate *priv = MODEST_VBOX_CELL_RENDERER_GET_PRIVATE (vbox_renderer);
+       
+       priv->renderers_list = g_list_append (priv->renderers_list, cell);
+       g_object_set_data (G_OBJECT (cell), RENDERER_EXPAND_ATTRIBUTE, GINT_TO_POINTER (expand));
+       g_object_ref_sink (G_OBJECT (cell));
+}
+
+static void 
+modest_vbox_cell_renderer_get_size     (GtkCellRenderer       *cell,
+                                       GtkWidget             *widget,
+                                       GdkRectangle          *rectangle,
+                                       gint                  *x_offset,
+                                       gint                  *y_offset,
+                                       gint                  *width,
+                                       gint                  *height)
+{
+       gint calc_width, calc_height;
+       gint full_width, full_height;
+       GList *node;
+       ModestVBoxCellRendererPrivate *priv = MODEST_VBOX_CELL_RENDERER_GET_PRIVATE (cell);
+
+       calc_width = 0;
+       calc_height = 0;
+
+       for (node = priv->renderers_list; node != NULL; node = g_list_next (node)) {
+               gint renderer_width, renderer_height;
+               GtkCellRenderer *renderer = (GtkCellRenderer *) node->data;
+
+               gtk_cell_renderer_get_size (renderer, widget, NULL, NULL, NULL,
+                                           &renderer_width, &renderer_height);
+               if ((renderer_width > 0)&&(renderer_height > 0)) {
+                       calc_width = MAX (calc_width, renderer_width);
+                       calc_height += renderer_height;
+               }
+       }
+
+       full_width = (gint) cell->xpad * 2 + calc_width;
+       full_height = (gint) cell->ypad * 2 + calc_height;
+
+       if (rectangle && calc_width > 0 && calc_height > 0) {
+               if (x_offset) {
+                       *x_offset = (((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ?
+                                     (1.0 - cell->xalign) : cell->xalign) *
+                                    (rectangle->width - full_width));
+                       *x_offset = MAX (*x_offset, 0);
+               }
+               if (y_offset) {
+                       *y_offset = ((cell->yalign) *
+                                    (rectangle->height - full_height));
+                       *y_offset = MAX (*y_offset, 0);
+               }
+       } else {
+               if (x_offset)
+                       *x_offset = 0;
+               if (y_offset)
+                       *y_offset = 0;
+       }
+
+       if (width)
+               *width = full_width;
+       if (height)
+               *height = full_height;
+}
+
+static void 
+modest_vbox_cell_renderer_render       (GtkCellRenderer       *cell,
+                                       GdkDrawable           *window,
+                                       GtkWidget             *widget,
+                                       GdkRectangle          *background_area,
+                                       GdkRectangle          *cell_area,
+                                       GdkRectangle          *expose_area,
+                                       GtkCellRendererState  flags)
+{
+       ModestVBoxCellRendererPrivate *priv = MODEST_VBOX_CELL_RENDERER_GET_PRIVATE (cell);
+       gint nvis_children = 0;
+       gint nexpand_children = 0;
+       GtkTextDirection direction;
+       GList *node = NULL;
+       GtkCellRenderer *child;
+       gint height, extra;
+       GtkRequisition req;
+       
+       direction = gtk_widget_get_direction (widget);
+       nvis_children = 0;
+       nexpand_children = 0;
+
+       /* first, retrieve the requisition of the children cell renderers */
+       modest_vbox_cell_renderer_get_size (cell, widget, NULL, NULL, NULL, &(req.width), &(req.height));
+
+       /* Counts visible and expandable children cell renderers */
+       for (node = priv->renderers_list; node != NULL; node = g_list_next (node)) {
+               gboolean visible, expand;
+               child = (GtkCellRenderer *) node->data;
+               g_object_get (G_OBJECT (child), "visible", &visible, NULL);
+               expand = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (child), RENDERER_EXPAND_ATTRIBUTE));
+               
+               if (visible) {
+                       nvis_children += 1;
+                       if (expand)
+                               nexpand_children += 1;
+               }
+       }
+
+       if (nvis_children > 0) {
+               gint x_pad, y_pad;
+               gint y;
+               GdkRectangle child_alloc;
+
+               if (nexpand_children > 0) {
+                       height = cell_area->height - req.height;
+                       extra = height / nexpand_children;
+               } else {
+                       height = 0;
+                       extra = 0;
+               }
+
+               g_object_get (cell, "xpad", &x_pad, "ypad", &y_pad, NULL);
+               y = cell_area->y + y_pad;
+               child_alloc.x = cell_area->x + x_pad;
+               child_alloc.width = MAX (1, cell_area->width - x_pad * 2);
+
+               for (node = priv->renderers_list; node != NULL; node = g_list_next (node)) {
+                       gboolean visible, expand;
+
+                       child = (GtkCellRenderer *) node->data;
+                       g_object_get (G_OBJECT (child), "visible", &visible, NULL);
+                       expand = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (child), RENDERER_EXPAND_ATTRIBUTE));
+
+                       if (visible) {
+                               GtkRequisition child_req;
+                               gint child_xpad, child_ypad;
+                               GdkRectangle child_expose_area;
+
+                               gtk_cell_renderer_get_size (child, widget, NULL, NULL, NULL, &(child_req.width), &(child_req.height));
+                               g_object_get (child, "xpad", &child_xpad, "ypad", &child_ypad, NULL);
+
+                               if (expand) {
+                                       if (nexpand_children == 1)
+                                               child_req.height += height;
+                                       else
+                                               child_req.height += extra;
+                                       nexpand_children -= 1;
+                                       height -= extra;
+                               }
+
+                               child_alloc.height = MAX (1, child_req.height);
+                               child_alloc.y = y;
+
+                               if (gdk_rectangle_intersect (&child_alloc, expose_area, &child_expose_area))
+                                       gtk_cell_renderer_render (child, window, widget, background_area, &child_alloc, &child_expose_area, flags);
+                               y += child_req.height;
+                       }
+               }
+       }
+       
+}
diff --git a/src/widgets/modest-vbox-cell-renderer.h b/src/widgets/modest-vbox-cell-renderer.h
new file mode 100644 (file)
index 0000000..49bbed8
--- /dev/null
@@ -0,0 +1,67 @@
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MODEST_VBOX_CELL_RENDERER_H
+#define MODEST_VBOX_CELL_RENDERER_H
+#include <glib-object.h>
+#include <gtk/gtkcellrenderer.h>
+
+G_BEGIN_DECLS
+
+#define MODEST_TYPE_VBOX_CELL_RENDERER             (modest_vbox_cell_renderer_get_type ())
+#define MODEST_VBOX_CELL_RENDERER(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), MODEST_TYPE_VBOX_CELL_RENDERER, ModestVBoxCellRenderer))
+#define MODEST_VBOX_CELL_RENDERER_CLASS(vtable)    (G_TYPE_CHECK_CLASS_CAST ((vtable), MODEST_TYPE_VBOX_CELL_RENDERER, ModestVBoxCellRendererClass))
+#define MODEST_IS_VBOX_CELL_RENDERER(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MODEST_TYPE_VBOX_CELL_RENDERER))
+#define MODEST_IS_VBOX_CELL_RENDERER_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MODEST_TYPE_VBOX_CELL_RENDERER))
+#define MODEST_VBOX_CELL_RENDERER_GET_CLASS(inst)  (G_TYPE_INSTANCE_GET_CLASS ((inst), MODEST_TYPE_VBOX_CELL_RENDERER, ModestVBoxCellRendererClass))
+
+typedef struct _ModestVBoxCellRenderer ModestVBoxCellRenderer;
+typedef struct _ModestVBoxCellRendererClass ModestVBoxCellRendererClass;
+
+struct _ModestVBoxCellRenderer
+{
+       GtkCellRenderer parent;
+
+};
+
+struct _ModestVBoxCellRendererClass
+{
+       GtkCellRendererClass parent_class;
+
+};
+
+GType modest_vbox_cell_renderer_get_type (void);
+
+GtkCellRenderer* modest_vbox_cell_renderer_new (void);
+
+void modest_vbox_cell_renderer_append (ModestVBoxCellRenderer *vbox_renderer, GtkCellRenderer *cell, gboolean expand);
+
+G_END_DECLS
+
+#endif