diff options
Diffstat (limited to 'mail/e-mail-tab-picker.c')
-rw-r--r-- | mail/e-mail-tab-picker.c | 1347 |
1 files changed, 0 insertions, 1347 deletions
diff --git a/mail/e-mail-tab-picker.c b/mail/e-mail-tab-picker.c deleted file mode 100644 index c5751ca90f..0000000000 --- a/mail/e-mail-tab-picker.c +++ /dev/null @@ -1,1347 +0,0 @@ -/* - * Borrowed from Moblin-Web-Browser: The web browser for Moblin - * Copyright (c) 2009, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU Lesser General Public License, - * version 2.1, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-mail-tab-picker.h" - -#define E_MAIL_TAB_PICKER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_MAIL_TAB_PICKER, EMailTabPickerPrivate)) - -static void mx_droppable_iface_init (MxDroppableIface *iface); -static gint e_mail_tab_picker_find_tab_cb (gconstpointer a, gconstpointer b); - -G_DEFINE_TYPE_WITH_CODE ( - EMailTabPicker, - e_mail_tab_picker, - MX_TYPE_WIDGET, - G_IMPLEMENT_INTERFACE ( - MX_TYPE_DROPPABLE, mx_droppable_iface_init)) - -#define TAB_PICKER_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_MAIL_TYPE_TAB_PICKER, EMailTabPickerPrivate)) - -enum -{ - PROP_0, - - PROP_PREVIEW_MODE, - PROP_DROP_ENABLED, -}; - -enum -{ - TAB_ACTIVATED, - CHOOSER_CLICKED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0, }; - -typedef struct -{ - EMailTab *tab; - gfloat position; - gfloat width; - gboolean docking; - gboolean docked; -} EMailTabPickerProps; - -struct _EMailTabPickerPrivate -{ - GList *tabs; - gint n_tabs; - ClutterActor *chooser_button; - ClutterActor *close_button; - gint current_tab; - gboolean preview_mode; - gboolean drop_enabled; - gboolean in_drag; - gboolean drag_preview; - - gint width; - gint total_width; - gint max_offset; - gboolean docked_tabs; - - ClutterTimeline *scroll_timeline; - ClutterAlpha *scroll_alpha; - gint scroll_start; - gint scroll_end; - gint scroll_offset; - gboolean keep_current_visible; - MxAdjustment *scroll_adjustment; - ClutterActor *scroll_bar; - - ClutterTimeline *preview_timeline; - gfloat preview_progress; -}; - -static void -e_mail_tab_picker_over_in (MxDroppable *droppable, - MxDraggable *draggable) -{ -} - -static void -e_mail_tab_picker_over_out (MxDroppable *droppable, - MxDraggable *draggable) -{ -} - -static void -e_mail_tab_picker_drop (MxDroppable *droppable, - MxDraggable *draggable, - gfloat event_x, - gfloat event_y, - gint button, - ClutterModifierType modifiers) -{ - GList *t; - EMailTabPickerProps *tab; - ClutterActor *parent; - gint current_position, new_position; - - EMailTabPicker *picker = E_MAIL_TAB_PICKER (droppable); - EMailTabPickerPrivate *priv = picker->priv; - - /* Make sure this is a valid drop */ - if (!priv->drop_enabled) - return; - - if (!E_MAIL_IS_TAB (draggable)) - return; - - parent = clutter_actor_get_parent (CLUTTER_ACTOR (draggable)); - if (parent != (ClutterActor *) picker) - return; - - /* Get current position and property data structure */ - t = g_list_find_custom (priv->tabs, draggable, e_mail_tab_picker_find_tab_cb); - tab = (EMailTabPickerProps *) t->data; - if (!tab) { - g_warning ("Tab that's parented to a picker not actually in picker"); - return; - } - current_position = g_list_position (priv->tabs, t); - - /* Work out new position */ - for (new_position = 0, t = priv->tabs; t; t = t->next) { - EMailTabPickerProps *props = t->data; - - /* Ignore docked tabs */ - if (!props->docked) { - /* If the tab is beyond the dragged tab and not - * draggable, we don't want to drag past it. */ - if ((event_x >= props->position + priv->scroll_offset) && - (tab->position + tab->width <= props->position) && - !mx_draggable_is_enabled (MX_DRAGGABLE (props->tab))) { - new_position--; - break; - } - - /* The same check for dragging left instead of right */ - if ((event_x < props->position + props->width + priv->scroll_offset) && - (tab->position >= props->position) && - !mx_draggable_is_enabled (MX_DRAGGABLE (props->tab))) - break; - - /* If the tab-end position is after the drop position, - * break - we want to drop before here. */ - if (props->position + props->width + priv->scroll_offset > event_x) - break; - } - - /* Increment the position */ - new_position++; - } - - /* Re-order */ - e_mail_tab_picker_reorder (picker, current_position, new_position); -} - -static void -mx_droppable_iface_init (MxDroppableIface *iface) -{ - iface->over_in = e_mail_tab_picker_over_in; - iface->over_out = e_mail_tab_picker_over_out; - iface->drop = e_mail_tab_picker_drop; -} - -static void -e_mail_tab_picker_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - EMailTabPicker *tab_picker = E_MAIL_TAB_PICKER (object); - EMailTabPickerPrivate *priv = tab_picker->priv; - - switch (property_id) { - case PROP_PREVIEW_MODE: - g_value_set_boolean ( - value, e_mail_tab_picker_get_preview_mode ( - E_MAIL_TAB_PICKER (object))); - return; - - case PROP_DROP_ENABLED: - g_value_set_boolean (value, priv->drop_enabled); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -e_mail_tab_picker_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - EMailTabPicker *tab_picker = E_MAIL_TAB_PICKER (object); - EMailTabPickerPrivate *priv = tab_picker->priv; - - switch (property_id) { - case PROP_PREVIEW_MODE: - e_mail_tab_picker_set_preview_mode ( - E_MAIL_TAB_PICKER (object), - g_value_get_boolean (value)); - return; - - case PROP_DROP_ENABLED: - priv->drop_enabled = g_value_get_boolean (value); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -e_mail_tab_picker_dispose (GObject *object) -{ - EMailTabPicker *picker = E_MAIL_TAB_PICKER (object); - EMailTabPickerPrivate *priv = picker->priv; - - if (priv->scroll_bar) { - clutter_actor_unparent (CLUTTER_ACTOR (priv->scroll_bar)); - priv->scroll_bar = NULL; - } - - if (priv->scroll_timeline) { - clutter_timeline_stop (priv->scroll_timeline); - g_object_unref (priv->scroll_alpha); - g_object_unref (priv->scroll_timeline); - priv->scroll_timeline = NULL; - priv->scroll_alpha = NULL; - } - - if (priv->preview_timeline) { - clutter_timeline_stop (priv->preview_timeline); - g_object_unref (priv->preview_timeline); - priv->preview_timeline = NULL; - } - - if (priv->chooser_button) { - clutter_actor_unparent (CLUTTER_ACTOR (priv->chooser_button)); - priv->chooser_button = NULL; - } - - if (priv->close_button) { - clutter_actor_unparent (CLUTTER_ACTOR (priv->close_button)); - priv->close_button = NULL; - } - - while (priv->tabs) { - EMailTabPickerProps *props = priv->tabs->data; - e_mail_tab_picker_remove_tab (picker, props->tab); - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (e_mail_tab_picker_parent_class)->dispose (object); -} - -static void -e_mail_tab_picker_paint (ClutterActor *actor) -{ - GList *t; - gfloat width, height, offset; - EMailTabPickerPrivate *priv; - - priv = E_MAIL_TAB_PICKER_GET_PRIVATE (actor); - - CLUTTER_ACTOR_CLASS (e_mail_tab_picker_parent_class)->paint (actor); - - clutter_actor_get_size (actor, &width, &height); - - cogl_clip_push_rectangle (0, 0, width, height); - - offset = priv->scroll_offset; - cogl_translate (-priv->scroll_offset, 0, 0); - - /* Draw normal tabs */ - for (t = priv->tabs; t; t = t->next) { - EMailTabPickerProps *props = t->data; - - if (props->docked) - continue; - if (props->position + props->width < offset) - continue; - if (props->position > width + offset) - break; - - if (CLUTTER_ACTOR_IS_MAPPED (props->tab)) - clutter_actor_paint (CLUTTER_ACTOR (props->tab)); - } - - cogl_translate (priv->scroll_offset, 0, 0); - - /* Draw docked tabs */ - if (priv->docked_tabs) { - for (t = priv->tabs; t; t = t->next) { - EMailTabPickerProps *props = t->data; - - if (!props->docked) - continue; - - if (CLUTTER_ACTOR_IS_MAPPED (props->tab)) - clutter_actor_paint (CLUTTER_ACTOR (props->tab)); - } - } - - cogl_clip_pop (); - - /* Draw tab chooser button */ - if (CLUTTER_ACTOR_IS_MAPPED (priv->chooser_button)) - clutter_actor_paint (CLUTTER_ACTOR (priv->chooser_button)); - - /* Draw scrollbar */ - if (CLUTTER_ACTOR_IS_MAPPED (priv->scroll_bar)) { - gfloat height; - clutter_actor_get_preferred_height ( - CLUTTER_ACTOR (priv->close_button), - -1, NULL, &height); - height *= priv->preview_progress; - if (height >= 1.0) { - cogl_clip_push_rectangle (0, 0, width, height); - if (CLUTTER_ACTOR_IS_MAPPED (priv->close_button)) - clutter_actor_paint (CLUTTER_ACTOR (priv->close_button)); - clutter_actor_paint (CLUTTER_ACTOR (priv->scroll_bar)); - cogl_clip_pop (); - } - } -} - -static void -e_mail_tab_picker_pick (ClutterActor *actor, - const ClutterColor *color) -{ - EMailTabPickerPrivate *priv; - - priv = E_MAIL_TAB_PICKER_GET_PRIVATE (actor); - - /* Chain up to paint background */ - CLUTTER_ACTOR_CLASS (e_mail_tab_picker_parent_class)->pick (actor, color); - - if (!priv->in_drag) - e_mail_tab_picker_paint (actor); -} - -static void -e_mail_tab_picker_get_preferred_width (ClutterActor *actor, - gfloat for_height, - gfloat *min_width_p, - gfloat *natural_width_p) -{ - GList *t; - MxPadding padding; - EMailTabPickerPrivate *priv; - - priv = E_MAIL_TAB_PICKER_GET_PRIVATE (actor); - - clutter_actor_get_preferred_width ( - CLUTTER_ACTOR (priv->chooser_button), - for_height, min_width_p, natural_width_p); - - mx_widget_get_padding (MX_WIDGET (actor), &padding); - if (min_width_p) - *min_width_p += padding.left + padding.right; - if (natural_width_p) - *natural_width_p += padding.left + padding.right; - - for (t = priv->tabs; t; t = t->next) { - gfloat min_width, natural_width; - EMailTabPickerProps *props = t->data; - - clutter_actor_get_preferred_width ( - CLUTTER_ACTOR (props->tab), for_height, - &min_width, &natural_width); - - if (min_width_p && !t->prev) - *min_width_p += min_width; - if (natural_width_p) - *natural_width_p += natural_width; - } -} - -void -e_mail_tab_picker_get_preferred_height (EMailTabPicker *tab_picker, - gfloat for_width, - gfloat *min_height_p, - gfloat *natural_height_p, - gboolean with_previews) -{ - MxPadding padding; - - ClutterActor *actor = CLUTTER_ACTOR (tab_picker); - EMailTabPickerPrivate *priv = tab_picker->priv; - - clutter_actor_get_preferred_height ( - CLUTTER_ACTOR (priv->chooser_button), - for_width, min_height_p, natural_height_p); - - if (priv->tabs) { - gfloat min_height, natural_height, scroll_height; - EMailTabPickerProps *props = priv->tabs->data; - - /* Get the height of the first tab - it's assumed that - * tabs are fixed height. */ - if (with_previews) { - clutter_actor_get_preferred_height ( - CLUTTER_ACTOR (props->tab), - for_width, &min_height, - &natural_height); - - if (CLUTTER_ACTOR_IS_VISIBLE (priv->scroll_bar)) { - /* Add the height of the scrollbar-section */ - clutter_actor_get_preferred_height ( - CLUTTER_ACTOR (priv->close_button), - -1, NULL, &scroll_height); - scroll_height *= priv->preview_progress; - - min_height += scroll_height; - natural_height += scroll_height; - } - } else - e_mail_tab_get_height_no_preview ( - props->tab, for_width, - &min_height, &natural_height); - - if (min_height_p && (*min_height_p < min_height)) - *min_height_p = min_height; - if (natural_height_p && (*natural_height_p < natural_height)) - *natural_height_p = natural_height; - } - - mx_widget_get_padding (MX_WIDGET (actor), &padding); - if (min_height_p) - *min_height_p += padding.top + padding.bottom; - if (natural_height_p) - *natural_height_p += padding.top + padding.bottom; -} - -static void -_e_mail_tab_picker_get_preferred_height (ClutterActor *actor, - gfloat for_width, - gfloat *min_height_p, - gfloat *natural_height_p) -{ - e_mail_tab_picker_get_preferred_height ( - E_MAIL_TAB_PICKER (actor), for_width, - min_height_p, natural_height_p, TRUE); -} - -static void -e_mail_tab_picker_allocate_docked (EMailTabPicker *tab_picker, - const ClutterActorBox *picker_box_p, - const ClutterActorBox *chooser_box_p, - ClutterAllocationFlags flags) -{ - GList *t; - MxPadding padding; - ClutterActorBox picker_box, chooser_box, child_box; - gfloat offset, width, left, right, height; - - EMailTabPickerPrivate *priv = tab_picker->priv; - - if (!picker_box_p) { - clutter_actor_get_allocation_box ( - CLUTTER_ACTOR (tab_picker), &picker_box); - picker_box_p = &picker_box; - } - - if (!chooser_box_p) { - clutter_actor_get_allocation_box ( - CLUTTER_ACTOR (priv->chooser_button), &chooser_box); - chooser_box_p = &chooser_box; - } - - mx_widget_get_padding (MX_WIDGET (tab_picker), &padding); - - /* Calculate available width and height */ - width = picker_box_p->x2 - picker_box_p->x1 - padding.right; - - e_mail_tab_picker_get_preferred_height ( - tab_picker, -1, NULL, &height, FALSE); - child_box.y2 = picker_box_p->y2 - picker_box_p->y1 - padding.bottom; - child_box.y1 = child_box.y2 - height; - - /* Don't dock over the chooser button */ - width -= chooser_box_p->x2 - chooser_box_p->x1; - - offset = priv->scroll_offset; - - left = 0; - right = width; - priv->docked_tabs = FALSE; - - for (t = g_list_last (priv->tabs); t; t = t->prev) { - EMailTabPickerProps *props = t->data; - - props->docked = FALSE; - - if (!props->docking) - continue; - - if (props->position < offset) { - /* Dock left */ - priv->docked_tabs = TRUE; - props->docked = TRUE; - child_box.x1 = left; - child_box.x2 = child_box.x1 + props->width; - left += props->width; - } else if (props->position + props->width > width + offset) { - /* Dock right */ - priv->docked_tabs = TRUE; - props->docked = TRUE; - child_box.x2 = right; - child_box.x1 = child_box.x2 - props->width; - right -= props->width; - } else { - child_box.x1 = props->position; - child_box.x2 = child_box.x1 + props->width; - } - - clutter_actor_allocate ( - CLUTTER_ACTOR (props->tab), &child_box, flags); - } -} - -static void -e_mail_tab_picker_scroll_new_frame_cb (ClutterTimeline *timeline, - guint msecs, - EMailTabPicker *tab_picker) -{ - EMailTabPickerPrivate *priv = tab_picker->priv; - gdouble alpha = clutter_alpha_get_alpha (priv->scroll_alpha); - - priv->scroll_offset = - (priv->scroll_start * (1.0 - alpha)) + - (priv->scroll_end * alpha); - mx_adjustment_set_value (priv->scroll_adjustment, priv->scroll_offset); - e_mail_tab_picker_allocate_docked (tab_picker, NULL, NULL, 0); - clutter_actor_queue_redraw (CLUTTER_ACTOR (tab_picker)); -} - -static void -e_mail_tab_picker_scroll_completed_cb (ClutterTimeline *timeline, - EMailTabPicker *tab_picker) -{ - EMailTabPickerPrivate *priv = tab_picker->priv; - - priv->scroll_offset = priv->scroll_end; - mx_adjustment_set_value (priv->scroll_adjustment, priv->scroll_offset); - e_mail_tab_picker_allocate_docked (tab_picker, NULL, NULL, 0); - clutter_actor_queue_redraw (CLUTTER_ACTOR (tab_picker)); - - g_object_unref (priv->scroll_alpha); - g_object_unref (priv->scroll_timeline); - priv->scroll_alpha = NULL; - priv->scroll_timeline = NULL; -} - -static void -e_mail_tab_picker_scroll_to (EMailTabPicker *tab_picker, - gint destination, - guint duration) -{ - EMailTabPickerPrivate *priv = tab_picker->priv; - - priv->scroll_start = priv->scroll_offset; - priv->scroll_end = CLAMP (destination, 0, priv->max_offset); - - if (priv->scroll_timeline) { - clutter_timeline_stop (priv->scroll_timeline); - clutter_timeline_rewind (priv->scroll_timeline); - clutter_timeline_set_duration (priv->scroll_timeline, duration); - } else { - if (priv->scroll_end == priv->scroll_offset) - return; - - priv->scroll_timeline = clutter_timeline_new (duration); - priv->scroll_alpha = clutter_alpha_new_full ( - priv->scroll_timeline, CLUTTER_EASE_OUT_QUAD); - g_signal_connect ( - priv->scroll_timeline, "new_frame", - G_CALLBACK (e_mail_tab_picker_scroll_new_frame_cb), - tab_picker); - g_signal_connect ( - priv->scroll_timeline, "completed", - G_CALLBACK (e_mail_tab_picker_scroll_completed_cb), - tab_picker); - } - - clutter_timeline_start (priv->scroll_timeline); -} - -static void -e_mail_tab_picker_allocate (ClutterActor *actor, - const ClutterActorBox *box, - ClutterAllocationFlags flags) -{ - GList *t; - MxPadding padding; - gint old_max_offset, old_scroll_offset; - ClutterActorBox child_box, scroll_box; - gfloat width, total_width, height; - - EMailTabPicker *tab_picker = E_MAIL_TAB_PICKER (actor); - EMailTabPickerPrivate *priv = tab_picker->priv; - - mx_widget_get_padding (MX_WIDGET (actor), &padding); - - /* Allocate for scroll-bar and close button */ - clutter_actor_get_preferred_size ( - CLUTTER_ACTOR (priv->close_button), - NULL, NULL, &width, &height); - child_box.x1 = 0; - child_box.x2 = box->x2 - box->x1 - padding.right; - child_box.y1 = 0; - child_box.y2 = child_box.y1 + height; - clutter_actor_allocate ( - CLUTTER_ACTOR (priv->close_button), &child_box, flags); - - /* FIXME: Make this a property */ -#define SPACING 4.0 - /* Work out allocation for scroll-bar, but allocate it later */ - scroll_box = child_box; - scroll_box.x2 -= width + SPACING; - scroll_box.x1 += SPACING; - scroll_box.y1 += SPACING; - scroll_box.y2 -= SPACING; - - child_box.y1 += (height * priv->preview_progress) + padding.top; - - /* Allocate for tabs */ - total_width = 0; - child_box.x1 = padding.left; - e_mail_tab_picker_get_preferred_height ( - tab_picker, -1, NULL, &height, FALSE); - for (t = priv->tabs; t; t = t->next) { - EMailTabPickerProps *props = t->data; - ClutterActor *actor = CLUTTER_ACTOR (props->tab); - - clutter_actor_get_preferred_width ( - actor, child_box.y2, NULL, &width); - - /* Fill out data - note it's ok to fill out docking here - * as when it changes, the tab queues a relayout. */ - props->docking = e_mail_tab_get_docking (props->tab); - props->position = child_box.x1; - props->width = width; - - total_width += width; - - /* Don't stretch tabs without a preview to fit tabs - * with a preview. */ - if (e_mail_tab_get_preview_actor (props->tab)) - child_box.y2 = box->y2 - box->y1 - padding.bottom; - else - child_box.y2 = child_box.y1 + height; - - child_box.x2 = child_box.x1 + width; - clutter_actor_allocate (actor, &child_box, flags); - - child_box.x1 = child_box.x2; - } - - /* Allocate for the chooser button */ - clutter_actor_get_preferred_width ( - CLUTTER_ACTOR (priv->chooser_button), - box->y2 - box->y1, NULL, &width); - - child_box.x2 = box->x2 - box->x1 - padding.right; - child_box.x1 = child_box.x2 - width; - child_box.y1 = 0; - child_box.y2 = child_box.y1 + height; - clutter_actor_allocate ( - CLUTTER_ACTOR (priv->chooser_button), &child_box, flags); - - /* Cache some useful size values */ - priv->width = (gint)(box->x2 - box->x1); - - priv->total_width = (gint)(total_width + padding.left + padding.right); - - old_max_offset = priv->max_offset; - priv->max_offset = - priv->total_width - priv->width + - (gint) (child_box.x2 - child_box.x1); - if (priv->max_offset < 0) - priv->max_offset = 0; - - /* Allocate for tab picker */ - old_scroll_offset = priv->scroll_offset; - priv->scroll_offset = CLAMP (priv->scroll_offset, 0, priv->max_offset); - e_mail_tab_picker_allocate_docked (tab_picker, box, &child_box, flags); - - /* Chain up (store box) */ - CLUTTER_ACTOR_CLASS (e_mail_tab_picker_parent_class)-> - allocate (actor, box, flags); - - /* Sync up the scroll-bar properties */ - g_object_set ( - priv->scroll_adjustment, - "page-increment", (gdouble)(box->x2 - box->x1), - "page-size", (gdouble)(box->x2 - box->x1), - "upper", (gdouble)total_width, - NULL); - - if ((priv->max_offset != old_max_offset) || - (priv->scroll_offset != old_scroll_offset)) - mx_adjustment_set_value ( - priv->scroll_adjustment, - (gdouble) priv->scroll_offset); - - /* Allocate for scroll-bar */ - clutter_actor_allocate ( - CLUTTER_ACTOR (priv->scroll_bar), &scroll_box, flags); - - /* Keep current tab visible */ - if (priv->keep_current_visible) { - EMailTabPickerProps *current; - - current = g_list_nth_data (priv->tabs, priv->current_tab); - - if ((current->position < priv->scroll_offset) || - (current->position + current->width >= priv->max_offset)) - e_mail_tab_picker_scroll_to ( - tab_picker, current->position, 150); - } -} - -static void -e_mail_tab_picker_map (ClutterActor *actor) -{ - GList *t; - EMailTabPickerPrivate *priv; - - priv = E_MAIL_TAB_PICKER_GET_PRIVATE (actor); - - CLUTTER_ACTOR_CLASS (e_mail_tab_picker_parent_class)->map (actor); - - clutter_actor_map (CLUTTER_ACTOR (priv->chooser_button)); - clutter_actor_map (CLUTTER_ACTOR (priv->close_button)); - clutter_actor_map (CLUTTER_ACTOR (priv->scroll_bar)); - - for (t = priv->tabs; t; t = t->next) { - EMailTabPickerProps *props = t->data; - clutter_actor_map (CLUTTER_ACTOR (props->tab)); - } -} - -static void -e_mail_tab_picker_unmap (ClutterActor *actor) -{ - GList *t; - EMailTabPickerPrivate *priv; - - priv = E_MAIL_TAB_PICKER_GET_PRIVATE (actor); - - CLUTTER_ACTOR_CLASS (e_mail_tab_picker_parent_class)->unmap (actor); - - clutter_actor_unmap (CLUTTER_ACTOR (priv->chooser_button)); - clutter_actor_unmap (CLUTTER_ACTOR (priv->close_button)); - clutter_actor_unmap (CLUTTER_ACTOR (priv->scroll_bar)); - - for (t = priv->tabs; t; t = t->next) { - EMailTabPickerProps *props = t->data; - clutter_actor_unmap (CLUTTER_ACTOR (props->tab)); - } -} - -static void -e_mail_tab_picker_class_init (EMailTabPickerClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (class); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (class); - - g_type_class_add_private (class, sizeof (EMailTabPickerPrivate)); - - object_class->get_property = e_mail_tab_picker_get_property; - object_class->set_property = e_mail_tab_picker_set_property; - object_class->dispose = e_mail_tab_picker_dispose; - - actor_class->paint = e_mail_tab_picker_paint; - actor_class->pick = e_mail_tab_picker_pick; - actor_class->get_preferred_width = e_mail_tab_picker_get_preferred_width; - actor_class->get_preferred_height = _e_mail_tab_picker_get_preferred_height; - actor_class->allocate = e_mail_tab_picker_allocate; - actor_class->map = e_mail_tab_picker_map; - actor_class->unmap = e_mail_tab_picker_unmap; - - g_object_class_install_property ( - object_class, - PROP_PREVIEW_MODE, - g_param_spec_boolean ( - "preview-mode", - "Preview mode", - "Whether to display " - "in preview mode.", - FALSE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_override_property ( - object_class, - PROP_DROP_ENABLED, - "drop-enabled"); - - signals[TAB_ACTIVATED] = g_signal_new ( - "tab-activated", - G_TYPE_FROM_CLASS (class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EMailTabPickerClass, tab_activated), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - E_TYPE_MAIL_TAB); - - signals[CHOOSER_CLICKED] = g_signal_new ( - "chooser-clicked", - G_TYPE_FROM_CLASS (class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EMailTabPickerClass, chooser_clicked), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} - -static void -e_mail_tab_picker_chooser_clicked_cb (ClutterActor *button, - EMailTabPicker *picker) -{ - g_signal_emit (picker, signals[CHOOSER_CLICKED], 0); -} - -static gboolean -e_mail_tab_picker_scroll_event_cb (ClutterActor *actor, - ClutterScrollEvent *event, - gpointer user_data) -{ - EMailTabPicker *picker = E_MAIL_TAB_PICKER (actor); - EMailTabPickerPrivate *priv = picker->priv; - - priv->keep_current_visible = FALSE; - - switch (event->direction) { - case CLUTTER_SCROLL_UP : - case CLUTTER_SCROLL_LEFT : - e_mail_tab_picker_scroll_to ( - picker, priv->scroll_end - 200, 150); - break; - - case CLUTTER_SCROLL_DOWN : - case CLUTTER_SCROLL_RIGHT : - e_mail_tab_picker_scroll_to ( - picker, priv->scroll_end + 200, 150); - break; - } - - return TRUE; -} - -static void -e_mail_tab_picker_scroll_value_cb (MxAdjustment *adjustment, - GParamSpec *pspec, - EMailTabPicker *picker) -{ - EMailTabPickerPrivate *priv = picker->priv; - gdouble value = mx_adjustment_get_value (adjustment); - - if ((gint) value != priv->scroll_offset) { - priv->keep_current_visible = FALSE; - priv->scroll_offset = (gint) value; - clutter_actor_queue_relayout (CLUTTER_ACTOR (picker)); - } -} - -static void -e_mail_tab_picker_init (EMailTabPicker *picker) -{ - picker->priv = E_MAIL_TAB_PICKER_GET_PRIVATE (picker); - - clutter_actor_set_reactive (CLUTTER_ACTOR (picker), TRUE); - - picker->priv->chooser_button = mx_button_new (); - clutter_actor_set_name ( - CLUTTER_ACTOR (picker->priv->chooser_button), - "chooser-button"); - clutter_actor_set_parent ( - CLUTTER_ACTOR (picker->priv->chooser_button), - CLUTTER_ACTOR (picker)); - - picker->priv->close_button = mx_button_new (); - clutter_actor_set_name ( - CLUTTER_ACTOR (picker->priv->close_button), - "chooser-close-button"); - clutter_actor_set_parent ( - CLUTTER_ACTOR (picker->priv->close_button), - CLUTTER_ACTOR (picker)); - clutter_actor_hide (CLUTTER_ACTOR (picker->priv->close_button)); - - picker->priv->scroll_adjustment = - mx_adjustment_new_with_values (0, 0, 0, 100, 200, 200); - picker->priv->scroll_bar = - mx_scroll_bar_new_with_adjustment ( - picker->priv->scroll_adjustment); - g_object_unref (picker->priv->scroll_adjustment); - clutter_actor_set_parent ( - CLUTTER_ACTOR (picker->priv->scroll_bar), - CLUTTER_ACTOR (picker)); - clutter_actor_hide (CLUTTER_ACTOR (picker->priv->scroll_bar)); - - g_signal_connect ( - picker->priv->chooser_button, "clicked", - G_CALLBACK (e_mail_tab_picker_chooser_clicked_cb), picker); - g_signal_connect ( - picker->priv->close_button, "clicked", - G_CALLBACK (e_mail_tab_picker_chooser_clicked_cb), picker); - g_signal_connect ( - picker, "scroll-event", - G_CALLBACK (e_mail_tab_picker_scroll_event_cb), NULL); -} - -static gint -e_mail_tab_picker_find_tab_cb (gconstpointer a, - gconstpointer b) -{ - EMailTabPickerProps *props = (EMailTabPickerProps *) a; - EMailTab *tab = (EMailTab *) b; - - return (props->tab == tab) ? 0 : -1; -} - -static void -e_mail_tab_picker_tab_clicked_cb (EMailTab *tab, - EMailTabPicker *picker) -{ - EMailTabPickerPrivate *priv = picker->priv; - EMailTab *old_tab; - GList *new_tab_link; - - old_tab = ((EMailTabPickerProps *) g_list_nth_data ( - priv->tabs, priv->current_tab))->tab; - new_tab_link = g_list_find_custom ( - priv->tabs, tab, e_mail_tab_picker_find_tab_cb); - - if (!new_tab_link) - return; - - priv->keep_current_visible = TRUE; - - /* If the same tab is clicked, make sure we remain active and return */ - if (tab == old_tab) { - e_mail_tab_set_active (tab, TRUE); - if (priv->preview_mode) - g_signal_emit (picker, signals[TAB_ACTIVATED], 0, tab); - return; - } - - /* Deselect old tab */ - e_mail_tab_set_active (old_tab, FALSE); - - /* Set new tab */ - priv->current_tab = g_list_position (priv->tabs, new_tab_link); - g_signal_emit (picker, signals[TAB_ACTIVATED], 0, tab); -} - -ClutterActor * -e_mail_tab_picker_new (void) -{ - return g_object_new (E_TYPE_MAIL_TAB_PICKER, NULL); -} - -static void -e_mail_tab_picker_tab_drag_begin_cb (MxDraggable *draggable, - gfloat event_x, - gfloat event_y, - gint event_button, - ClutterModifierType modifiers, - EMailTabPicker *picker) -{ - EMailTabPickerPrivate *priv = picker->priv; - priv->in_drag = TRUE; - - if (!priv->preview_mode) { - e_mail_tab_picker_set_preview_mode (picker, TRUE); - priv->drag_preview = TRUE; - } -} - -static void -e_mail_tab_picker_tab_drag_end_cb (MxDraggable *draggable, - gfloat event_x, - gfloat event_y, - EMailTabPicker *picker) -{ - EMailTabPickerPrivate *priv = picker->priv; - priv->in_drag = FALSE; - - if (priv->drag_preview) { - e_mail_tab_picker_set_preview_mode (picker, FALSE); - priv->drag_preview = FALSE; - } -} - -void -e_mail_tab_picker_add_tab (EMailTabPicker *picker, - EMailTab *tab, - gint position) -{ - EMailTabPickerProps *props; - EMailTabPickerPrivate *priv = picker->priv; - - if (priv->tabs && (priv->current_tab >= position)) - priv->current_tab++; - - props = g_slice_new (EMailTabPickerProps); - props->tab = tab; - priv->tabs = g_list_insert (priv->tabs, props, position); - priv->n_tabs++; - - clutter_actor_set_parent (CLUTTER_ACTOR (tab), CLUTTER_ACTOR (picker)); - mx_draggable_set_axis (MX_DRAGGABLE (tab), MX_DRAG_AXIS_X); - - g_signal_connect_after ( - tab, "clicked", - G_CALLBACK (e_mail_tab_picker_tab_clicked_cb), picker); - g_signal_connect ( - tab, "drag-begin", - G_CALLBACK (e_mail_tab_picker_tab_drag_begin_cb), picker); - g_signal_connect ( - tab, "drag-end", - G_CALLBACK (e_mail_tab_picker_tab_drag_end_cb), picker); - - e_mail_tab_set_preview_mode (tab, priv->preview_mode); - clutter_actor_queue_relayout (CLUTTER_ACTOR (picker)); -} - -void -e_mail_tab_picker_remove_tab (EMailTabPicker *picker, - EMailTab *tab) -{ - GList *tab_link; - EMailTabPickerPrivate *priv = picker->priv; - - tab_link = g_list_find_custom ( - priv->tabs, tab, e_mail_tab_picker_find_tab_cb); - - if (!tab_link) - return; - - g_signal_handlers_disconnect_by_func ( - tab, e_mail_tab_picker_tab_clicked_cb, picker); - g_signal_handlers_disconnect_by_func ( - tab, e_mail_tab_picker_tab_drag_begin_cb, picker); - g_signal_handlers_disconnect_by_func ( - tab, e_mail_tab_picker_tab_drag_end_cb, picker); - - /* We don't want to do this during dispose, checking if chooser_button - * exists is a way of checking if we're in dispose without keeping an - * extra variable around. */ - if (priv->chooser_button) { - gint position = g_list_position (priv->tabs, tab_link); - if (priv->current_tab) { - if (priv->current_tab > position) - priv->current_tab--; - else if (priv->current_tab == position) - e_mail_tab_picker_set_current_tab ( - picker, priv->current_tab - 1); - } else if (priv->tabs->next && (position == 0)) { - e_mail_tab_picker_set_current_tab ( - picker, priv->current_tab + 1); - priv->current_tab--; - } - } - - g_slice_free (EMailTabPickerProps, tab_link->data); - priv->tabs = g_list_delete_link (priv->tabs, tab_link); - clutter_actor_unparent (CLUTTER_ACTOR (tab)); - priv->n_tabs--; - - clutter_actor_queue_relayout (CLUTTER_ACTOR (picker)); -} - -GList * -e_mail_tab_picker_get_tabs (EMailTabPicker *picker) -{ - GList *tab_list, *t; - - EMailTabPickerPrivate *priv = picker->priv; - - tab_list = NULL; - for (t = g_list_last (priv->tabs); t; t = t->prev) { - EMailTabPickerProps *props = t->data; - tab_list = g_list_prepend (tab_list, props->tab); - } - - return tab_list; -} - -EMailTab * -e_mail_tab_picker_get_tab (EMailTabPicker *picker, - gint tab) -{ - EMailTabPickerProps *props = g_list_nth_data (picker->priv->tabs, tab); - return props->tab; -} - -gint -e_mail_tab_picker_get_tab_no (EMailTabPicker *picker, - EMailTab *tab) -{ - GList *tab_link; - - tab_link = g_list_find_custom ( - picker->priv->tabs, tab, - e_mail_tab_picker_find_tab_cb); - - return g_list_position (picker->priv->tabs, tab_link); -} - -gint -e_mail_tab_picker_get_current_tab (EMailTabPicker *picker) -{ - return picker->priv->current_tab; -} - -void -e_mail_tab_picker_set_current_tab (EMailTabPicker *picker, - gint tab_no) -{ - EMailTabPickerPrivate *priv = picker->priv; - EMailTabPickerProps *props; - - printf("OLD %d new %d\n", priv->current_tab, tab_no); - if (priv->n_tabs == 0) - return; - - if (ABS (tab_no) >= priv->n_tabs) - return; - - if (tab_no < 0) - tab_no = priv->n_tabs + tab_no; - - props = g_list_nth_data (priv->tabs, (guint) tab_no); - - if (props) { - e_mail_tab_picker_tab_clicked_cb (props->tab, picker); - e_mail_tab_set_active (props->tab, TRUE); - } -} - -void -e_mail_tab_picker_reorder (EMailTabPicker *picker, - gint old_position, - gint new_position) -{ - GList *link; - gpointer data; - - EMailTabPickerPrivate *priv = picker->priv; - - if (old_position == new_position) - return; - - if (!(link = g_list_nth (priv->tabs, old_position))) - return; - - data = link->data; - priv->tabs = g_list_delete_link (priv->tabs, link); - priv->tabs = g_list_insert (priv->tabs, data, new_position); - - if (priv->current_tab == old_position) { - if (new_position < 0) - priv->current_tab = priv->n_tabs - 1; - else - priv->current_tab = CLAMP ( - new_position, 0, priv->n_tabs - 1); - } else if ((priv->current_tab > old_position) && - (new_position >= priv->current_tab)) - priv->current_tab--; - else if ((priv->current_tab < old_position) && - (new_position <= priv->current_tab)) - priv->current_tab++; - - clutter_actor_queue_relayout (CLUTTER_ACTOR (picker)); -} - -gint -e_mail_tab_picker_get_n_tabs (EMailTabPicker *picker) -{ - return picker->priv->n_tabs; -} - -static void -preview_new_frame_cb (ClutterTimeline *timeline, - guint msecs, - EMailTabPicker *picker) -{ - picker->priv->preview_progress = - clutter_timeline_get_progress (timeline); - clutter_actor_queue_relayout (CLUTTER_ACTOR (picker)); -} - -static void -preview_completed_cb (ClutterTimeline *timeline, - EMailTabPicker *picker) -{ - EMailTabPickerPrivate *priv = picker->priv; - - if (priv->preview_timeline) { - g_object_unref (priv->preview_timeline); - priv->preview_timeline = NULL; - - if (priv->preview_mode) { - priv->preview_progress = 1.0; - clutter_actor_hide ( - CLUTTER_ACTOR (priv->chooser_button)); - } else { - priv->preview_progress = 0.0; - clutter_actor_hide (CLUTTER_ACTOR (priv->scroll_bar)); - clutter_actor_hide (CLUTTER_ACTOR (priv->close_button)); - } - - clutter_actor_queue_relayout (CLUTTER_ACTOR (picker)); - } -} - -void -e_mail_tab_picker_set_preview_mode (EMailTabPicker *picker, - gboolean preview) -{ - GList *t; - - EMailTabPickerPrivate *priv = picker->priv; - - if ((priv->preview_mode ? 1 : 0) == (preview ? 1 : 0)) - return; - - priv->preview_mode = preview; - - /* Put all tabs in preview mode */ - for (t = priv->tabs; t; t = t->next) { - EMailTabPickerProps *prop = t->data; - e_mail_tab_set_preview_mode (prop->tab, preview); - } - - /* Slide in the scroll-bar */ - if (!priv->preview_timeline) { - if (preview) - clutter_actor_show (CLUTTER_ACTOR (priv->scroll_bar)); - - priv->preview_timeline = clutter_timeline_new (150); - g_signal_connect ( - priv->preview_timeline, "new-frame", - G_CALLBACK (preview_new_frame_cb), picker); - g_signal_connect ( - priv->preview_timeline, "completed", - G_CALLBACK (preview_completed_cb), picker); - clutter_timeline_start (priv->preview_timeline); - } - - clutter_timeline_set_direction ( - priv->preview_timeline, - preview ? CLUTTER_TIMELINE_FORWARD : - CLUTTER_TIMELINE_BACKWARD); - - /* Connect/disconnect the scrollbar */ - if (preview) - g_signal_connect ( - priv->scroll_adjustment, "notify::value", - G_CALLBACK (e_mail_tab_picker_scroll_value_cb), picker); - else - g_signal_handlers_disconnect_by_func ( - priv->scroll_adjustment, - e_mail_tab_picker_scroll_value_cb, picker); - - if (preview) { - /* Fade out the chooser button show close button */ - clutter_actor_animate ( - CLUTTER_ACTOR (priv->chooser_button), - CLUTTER_EASE_IN_OUT_QUAD, 150, - "opacity", 0x00, NULL); - clutter_actor_show (CLUTTER_ACTOR (priv->close_button)); - } else { - /* Fade in the chooser button */ - clutter_actor_show (CLUTTER_ACTOR (priv->chooser_button)); - clutter_actor_animate ( - CLUTTER_ACTOR (priv->chooser_button), - CLUTTER_EASE_IN_OUT_QUAD, 150, - "opacity", 0xff, NULL); - } - - clutter_actor_set_reactive ( - CLUTTER_ACTOR (priv->chooser_button), !preview); - - /* Remove the hover state, which likely got stuck when we clicked it */ - if (!preview) - mx_stylable_set_style_pseudo_class ( - MX_STYLABLE (priv->chooser_button), NULL); - - g_object_notify (G_OBJECT (picker), "preview-mode"); -} - -gboolean -e_mail_tab_picker_get_preview_mode (EMailTabPicker *picker) -{ - EMailTabPickerPrivate *priv = picker->priv; - return priv->preview_mode; -} - -void -e_mail_tab_picker_enable_drop (EMailTabPicker *picker, - gboolean enable) -{ - EMailTabPickerPrivate *priv = picker->priv; - - if ((priv->drop_enabled ? 1 : 0) == (enable ? 1 : 0)) - return; - - priv->drop_enabled = enable; - if (enable) - mx_droppable_enable (MX_DROPPABLE (picker)); - else - mx_droppable_disable (MX_DROPPABLE (picker)); - - g_object_notify (G_OBJECT (picker), "enabled"); -} - |