diff options
Diffstat (limited to 'widgets/misc/e-icon-entry.c')
-rw-r--r-- | widgets/misc/e-icon-entry.c | 505 |
1 files changed, 332 insertions, 173 deletions
diff --git a/widgets/misc/e-icon-entry.c b/widgets/misc/e-icon-entry.c index 7f0dbaaaee..cfcce8f8c5 100644 --- a/widgets/misc/e-icon-entry.c +++ b/widgets/misc/e-icon-entry.c @@ -32,25 +32,75 @@ * */ -#include "config.h" - #include "e-icon-entry.h" -#define E_ICON_ENTRY_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), E_TYPE_ICON_ENTRY, EIconEntryPrivate)) +#define E_ICON_ENTRY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ICON_ENTRY, EIconEntryPrivate)) -struct _EIconEntryPrivate -{ +struct _EIconEntryPrivate { + GtkStateType visual_state; + GtkWidget *entry; GtkWidget *hbox; }; -static GtkWidgetClass *parent_class = NULL; +enum { + PROP_0, + PROP_VISUAL_STATE +}; -/* private helper functions */ +static gpointer parent_class; + +static void +icon_entry_proxy_set_cursor (GtkWidget *widget, + GdkEventCrossing *event) +{ + if (event->type == GDK_ENTER_NOTIFY) { + GdkCursor *cursor; + + cursor = gdk_cursor_new (GDK_HAND1); + gdk_window_set_cursor (widget->window, cursor); + gdk_cursor_unref (cursor); + } else + gdk_window_set_cursor (widget->window, NULL); +} +static GtkWidget * +icon_entry_create_proxy (GtkAction *action) +{ + GtkWidget *proxy; + GtkWidget *widget; + gchar *tooltip; + + proxy = gtk_event_box_new (); + gtk_event_box_set_visible_window (GTK_EVENT_BOX (proxy), FALSE); + gtk_container_set_border_width (GTK_CONTAINER (proxy), 2); + gtk_widget_show (proxy); + + widget = gtk_action_create_icon (action, GTK_ICON_SIZE_MENU); + gtk_container_add (GTK_CONTAINER (proxy), widget); + gtk_widget_show (widget); + + g_object_get (action, "tooltip", &tooltip, NULL); + gtk_widget_set_tooltip_text (proxy, tooltip); + g_free (tooltip); + + g_signal_connect_swapped ( + proxy, "button-press-event", + G_CALLBACK (gtk_action_activate), action); + g_signal_connect_after ( + proxy, "enter-notify-event", + G_CALLBACK (icon_entry_proxy_set_cursor), NULL); + g_signal_connect_after ( + proxy, "leave-notify-event", + G_CALLBACK (icon_entry_proxy_set_cursor), NULL); + + return proxy; +} static gboolean -entry_focus_change_cb (GtkWidget *widget, - GdkEventFocus *event, - GtkWidget *entry) +icon_entry_focus_change_cb (GtkWidget *widget, + GdkEventFocus *event, + GtkWidget *entry) { gtk_widget_queue_draw (entry); @@ -58,111 +108,137 @@ entry_focus_change_cb (GtkWidget *widget, } static void -e_icon_entry_get_borders (GtkWidget *widget, - GtkWidget *entry, - int *xborder, - int *yborder) +icon_entry_get_borders (GtkWidget *widget, + GtkWidget *entry, + gint *xborder, + gint *yborder) { - int focus_width; + gint focus_width; gboolean interior_focus; g_return_if_fail (entry->style != NULL); - gtk_widget_style_get (entry, - "focus-line-width", &focus_width, - "interior-focus", &interior_focus, - NULL); + gtk_widget_style_get ( + entry, "focus-line-width", &focus_width, + "interior-focus", &interior_focus, NULL); *xborder = entry->style->xthickness; *yborder = entry->style->ythickness; - if (!interior_focus) - { + if (!interior_focus) { *xborder += focus_width; *yborder += focus_width; } } static void -e_icon_entry_paint (GtkWidget *widget, - GdkEventExpose *event) +icon_entry_paint (GtkWidget *widget, + GdkEventExpose *event) { EIconEntry *entry = E_ICON_ENTRY (widget); - GtkWidget *entry_widget = entry->entry; + GtkWidget *entry_widget = entry->priv->entry; int x = 0, y = 0, width, height, focus_width; gboolean interior_focus; - gtk_widget_style_get (entry_widget, - "interior-focus", &interior_focus, - "focus-line-width", &focus_width, - NULL); + gtk_widget_style_get ( + entry_widget, + "interior-focus", &interior_focus, + "focus-line-width", &focus_width, NULL); gdk_drawable_get_size (widget->window, &width, &height); - if (GTK_WIDGET_HAS_FOCUS (entry_widget) && !interior_focus) - { + if (GTK_WIDGET_HAS_FOCUS (entry_widget) && !interior_focus) { x += focus_width; y += focus_width; width -= 2 * focus_width; height -= 2 * focus_width; } - gtk_paint_flat_box (entry_widget->style, widget->window, - GTK_WIDGET_STATE (entry_widget), GTK_SHADOW_NONE, - NULL, entry_widget, "entry_bg", - /* FIXME: was 0, 0 in gtk_entry_expose, but I think this is correct: */ - x, y, width, height); + gtk_paint_flat_box ( + entry_widget->style, widget->window, + GTK_WIDGET_STATE (entry_widget), GTK_SHADOW_NONE, + NULL, entry_widget, "entry_bg", + /* FIXME: was 0, 0 in gtk_entry_expose, but I think this is correct: */ + x, y, width, height); - gtk_paint_shadow (entry_widget->style, widget->window, - GTK_STATE_NORMAL, GTK_SHADOW_IN, - NULL, entry_widget, "entry", - x, y, width, height); + gtk_paint_shadow ( + entry_widget->style, widget->window, + GTK_STATE_NORMAL, GTK_SHADOW_IN, + NULL, entry_widget, "entry", + x, y, width, height); - if (GTK_WIDGET_HAS_FOCUS (entry_widget) && !interior_focus) - { + if (GTK_WIDGET_HAS_FOCUS (entry_widget) && !interior_focus) { x -= focus_width; y -= focus_width; width += 2 * focus_width; height += 2 * focus_width; - gtk_paint_focus (entry_widget->style, widget->window, - GTK_WIDGET_STATE (entry_widget), - NULL, entry_widget, "entry", - /* FIXME: was 0, 0 in gtk_entry_draw_frame, but I think this is correct: */ - x, y, width, height); + gtk_paint_focus ( + entry_widget->style, widget->window, + GTK_WIDGET_STATE (entry_widget), + NULL, entry_widget, "entry", + /* FIXME: was 0, 0 in gtk_entry_draw_frame, but I think this is correct: */ + x, y, width, height); } } -/* Class implementation */ +static void +icon_entry_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_VISUAL_STATE: + e_icon_entry_set_visual_state ( + E_ICON_ENTRY (object), + g_value_get_enum (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} static void -e_icon_entry_init (EIconEntry *entry) +icon_entry_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - EIconEntryPrivate *priv; - GtkWidget *widget = (GtkWidget *) entry; + switch (property_id) { + case PROP_VISUAL_STATE: + g_value_set_enum ( + value, e_icon_entry_get_visual_state ( + E_ICON_ENTRY (object))); + return; + } - priv = entry->priv = E_ICON_ENTRY_GET_PRIVATE (entry); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} - GTK_WIDGET_UNSET_FLAGS (widget, GTK_NO_WINDOW); +static void +icon_entry_dispose (GObject *object) +{ + EIconEntryPrivate *priv; - priv->hbox = gtk_hbox_new (FALSE, /* FIXME */ 0); - gtk_container_add (GTK_CONTAINER (entry), priv->hbox); + priv = E_ICON_ENTRY_GET_PRIVATE (object); - entry->entry = gtk_entry_new (); - gtk_entry_set_has_frame (GTK_ENTRY (entry->entry), FALSE); - gtk_box_pack_start (GTK_BOX (priv->hbox), entry->entry, TRUE, TRUE, /* FIXME */ 0); + if (priv->entry != NULL) { + g_object_unref (priv->entry); + priv->entry = NULL; + } - /* We need to queue a redraw when focus changes, to comply with themes - * (like Clearlooks) which draw focused and unfocused entries differently. - */ - g_signal_connect_after (entry->entry, "focus-in-event", - G_CALLBACK (entry_focus_change_cb), entry); - g_signal_connect_after (entry->entry, "focus-out-event", - G_CALLBACK (entry_focus_change_cb), entry); + if (priv->hbox != NULL) { + g_object_unref (priv->hbox); + priv->hbox = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); } static void -e_icon_entry_realize (GtkWidget *widget) +icon_entry_realize (GtkWidget *widget) { GdkWindowAttr attributes; gint attributes_mask; @@ -185,34 +261,41 @@ e_icon_entry_realize (GtkWidget *widget) attributes.wclass = GDK_INPUT_OUTPUT; attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), - &attributes, attributes_mask); + widget->window = gdk_window_new ( + gtk_widget_get_parent_window (widget), + &attributes, attributes_mask); + gdk_window_set_user_data (widget->window, widget); widget->style = gtk_style_attach (widget->style, widget->window); - gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); + gtk_style_set_background ( + widget->style, widget->window, GTK_STATE_NORMAL); } static void -e_icon_entry_size_request (GtkWidget *widget, - GtkRequisition *requisition) +icon_entry_size_request (GtkWidget *widget, + GtkRequisition *requisition) { - EIconEntry *entry = E_ICON_ENTRY (widget); - GtkContainer *container = GTK_CONTAINER (widget); - GtkBin *bin = GTK_BIN (widget); - int xborder, yborder; + EIconEntryPrivate *priv; + GtkContainer *container; + GtkWidget *child; + gint xborder, yborder; - requisition->width = requisition->height = container->border_width * 2; + priv = E_ICON_ENTRY_GET_PRIVATE (widget); + container = GTK_CONTAINER (widget); - gtk_widget_ensure_style (entry->entry); - e_icon_entry_get_borders (widget, entry->entry, &xborder, &yborder); + requisition->width = container->border_width * 2; + requisition->height = container->border_width * 2; - if (GTK_WIDGET_VISIBLE (bin->child)) - { + gtk_widget_ensure_style (priv->entry); + icon_entry_get_borders (widget, priv->entry, &xborder, &yborder); + + child = GTK_BIN (widget)->child; + if (GTK_WIDGET_VISIBLE (child)) { GtkRequisition child_requisition; - gtk_widget_size_request (bin->child, &child_requisition); + gtk_widget_size_request (child, &child_requisition); requisition->width += child_requisition.width; requisition->height += child_requisition.height; } @@ -222,68 +305,126 @@ e_icon_entry_size_request (GtkWidget *widget, } static void -e_icon_entry_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) +icon_entry_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) { - EIconEntry *entry = E_ICON_ENTRY (widget); - GtkContainer *container = GTK_CONTAINER (widget); - GtkBin *bin = GTK_BIN (widget); + EIconEntryPrivate *priv; + GtkContainer *container; GtkAllocation child_allocation; - int xborder, yborder; + gint xborder, yborder; + gint width, height; + + priv = E_ICON_ENTRY_GET_PRIVATE (widget); + container = GTK_CONTAINER (widget); widget->allocation = *allocation; - e_icon_entry_get_borders (widget, entry->entry, &xborder, &yborder); + icon_entry_get_borders (widget, priv->entry, &xborder, &yborder); + + if (GTK_WIDGET_REALIZED (widget)) { + width = allocation->width - container->border_width * 2; + height = allocation->height - container->border_width * 2; - if (GTK_WIDGET_REALIZED (widget)) - { child_allocation.x = container->border_width; child_allocation.y = container->border_width; - child_allocation.width = MAX (allocation->width - container->border_width * 2, 0); - child_allocation.height = MAX (allocation->height - container->border_width * 2, 0); - - gdk_window_move_resize (widget->window, - allocation->x + child_allocation.x, - allocation->y + child_allocation.y, - child_allocation.width, - child_allocation.height); + child_allocation.width = MAX (width, 0); + child_allocation.height = MAX (height, 0); + + gdk_window_move_resize ( + widget->window, + allocation->x + child_allocation.x, + allocation->y + child_allocation.y, + child_allocation.width, + child_allocation.height); } + width = allocation->width - (container->border_width + xborder) * 2; + height = allocation->height - (container->border_width + yborder) * 2; + child_allocation.x = container->border_width + xborder; child_allocation.y = container->border_width + yborder; - child_allocation.width = MAX (allocation->width - (container->border_width + xborder) * 2, 0); - child_allocation.height = MAX (allocation->height - (container->border_width + yborder) * 2, 0); + child_allocation.width = MAX (width, 0); + child_allocation.height = MAX (height, 0); - gtk_widget_size_allocate (bin->child, &child_allocation); + gtk_widget_size_allocate (GTK_BIN (widget)->child, &child_allocation); } static gboolean -e_icon_entry_expose (GtkWidget *widget, - GdkEventExpose *event) +icon_entry_expose (GtkWidget *widget, + GdkEventExpose *event) { - if (GTK_WIDGET_DRAWABLE (widget) && - event->window == widget->window) - { - e_icon_entry_paint (widget, event); - } + if (GTK_WIDGET_DRAWABLE (widget) && event->window == widget->window) + icon_entry_paint (widget, event); - return parent_class->expose_event (widget, event); + /* Chain up to parent's expose() method. */ + return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event); } static void -e_icon_entry_class_init (EIconEntryClass *klass) +icon_entry_class_init (EIconEntryClass *class) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - - parent_class = GTK_WIDGET_CLASS (g_type_class_peek_parent (klass)); - - widget_class->realize = e_icon_entry_realize; - widget_class->size_request = e_icon_entry_size_request; - widget_class->size_allocate = e_icon_entry_size_allocate; - widget_class->expose_event = e_icon_entry_expose; + GObjectClass *object_class; + GtkWidgetClass *widget_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EIconEntryPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = icon_entry_set_property; + object_class->get_property = icon_entry_get_property; + object_class->dispose = icon_entry_dispose; + + widget_class = GTK_WIDGET_CLASS (class); + widget_class->realize = icon_entry_realize; + widget_class->size_request = icon_entry_size_request; + widget_class->size_allocate = icon_entry_size_allocate; + widget_class->expose_event = icon_entry_expose; + + g_object_class_install_property ( + object_class, + PROP_VISUAL_STATE, + g_param_spec_enum ( + "visual-state", + NULL, + NULL, + GTK_TYPE_STATE_TYPE, + GTK_STATE_NORMAL, + G_PARAM_READWRITE)); +} - g_type_class_add_private (object_class, sizeof (EIconEntryPrivate)); +static void +icon_entry_init (EIconEntry *icon_entry) +{ + GtkWidget *widget; + GtkWidget *container; + + icon_entry->priv = E_ICON_ENTRY_GET_PRIVATE (icon_entry); + icon_entry->priv->visual_state = GTK_STATE_NORMAL; + + GTK_WIDGET_UNSET_FLAGS (icon_entry, GTK_NO_WINDOW); + + widget = gtk_hbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (icon_entry), widget); + icon_entry->priv->hbox = g_object_ref (widget); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_entry_new (); + gtk_entry_set_has_frame (GTK_ENTRY (widget), FALSE); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + icon_entry->priv->entry = g_object_ref (widget); + gtk_widget_show (widget); + + /* We need to queue a redraw when focus changes, to comply with + * themes (like Clearlooks) which draw focused and unfocused + * entries differently. */ + g_signal_connect_after ( + widget, "focus-in-event", + G_CALLBACK (icon_entry_focus_change_cb), icon_entry); + g_signal_connect_after ( + widget, "focus-out-event", + G_CALLBACK (icon_entry_focus_change_cb), icon_entry); } GType @@ -293,92 +434,110 @@ e_icon_entry_get_type (void) if (G_UNLIKELY (type == 0)) { - static const GTypeInfo our_info = - { + static const GTypeInfo type_info = { sizeof (EIconEntryClass), - NULL, - NULL, - (GClassInitFunc) e_icon_entry_class_init, - NULL, - NULL, + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) icon_entry_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ sizeof (EIconEntry), - 0, - (GInstanceInitFunc) e_icon_entry_init + 0, /* n_preallocs */ + (GInstanceInitFunc) icon_entry_init, + NULL /* value_table */ }; - type = g_type_register_static (GTK_TYPE_BIN, - "EIconEntry", - &our_info, 0); + type = g_type_register_static ( + GTK_TYPE_BIN, "EIconEntry", &type_info, 0); } return type; } -/* public functions */ - GtkWidget * e_icon_entry_new (void) { return GTK_WIDGET (g_object_new (E_TYPE_ICON_ENTRY, NULL)); } -void -e_icon_entry_pack_widget (EIconEntry *entry, - GtkWidget *widget, - gboolean start) +GtkWidget * +e_icon_entry_get_entry (EIconEntry *icon_entry) { - EIconEntryPrivate *priv; + g_return_val_if_fail (E_IS_ICON_ENTRY (icon_entry), NULL); - g_return_if_fail (E_IS_ICON_ENTRY (entry)); + return icon_entry->priv->entry; +} - priv = entry->priv; +void +e_icon_entry_add_action_start (EIconEntry *icon_entry, + GtkAction *action) +{ + GtkWidget *proxy; + GtkBox *box; - if (start) - { - gtk_box_pack_start (GTK_BOX (priv->hbox), widget, FALSE, FALSE, /* FIXME */ 2); - gtk_box_reorder_child (GTK_BOX (priv->hbox), widget, 0); - } - else - { - gtk_box_pack_end (GTK_BOX (priv->hbox), widget, FALSE, FALSE, /* FIXME */ 2); - } + g_return_if_fail (E_IS_ICON_ENTRY (icon_entry)); + g_return_if_fail (GTK_IS_ACTION (action)); + + box = GTK_BOX (icon_entry->priv->hbox); + proxy = icon_entry_create_proxy (action); + gtk_box_pack_start (box, proxy, FALSE, FALSE, 2); + gtk_box_reorder_child (box, proxy, 0); } -static void -set_cursor (GtkWidget *widget, GdkEventCrossing *event, gpointer dummy) +void +e_icon_entry_add_action_end (EIconEntry *icon_entry, + GtkAction *action) { + GtkWidget *proxy; + GtkBox *box; + + g_return_if_fail (E_IS_ICON_ENTRY (icon_entry)); + g_return_if_fail (GTK_IS_ACTION (action)); - if (event->type == GDK_ENTER_NOTIFY) - gdk_window_set_cursor (widget->window, gdk_cursor_new (GDK_HAND1)); - else - gdk_window_set_cursor (widget->window, gdk_cursor_new (GDK_LEFT_PTR)); + box = GTK_BOX (icon_entry->priv->hbox); + proxy = icon_entry_create_proxy (action); + gtk_box_pack_end (box, proxy, FALSE, FALSE, 2); +} +GtkStateType +e_icon_entry_get_visual_state (EIconEntry *icon_entry) +{ + g_return_val_if_fail (E_IS_ICON_ENTRY (icon_entry), GTK_STATE_NORMAL); + return icon_entry->priv->visual_state; } -GtkWidget * -e_icon_entry_create_button (const char *stock) +void +e_icon_entry_set_visual_state (EIconEntry *icon_entry, + GtkStateType visual_state) { - GtkWidget *eventbox; - GtkWidget *image; + GtkWidget *widget; + const GdkColor *base_color; + const GdkColor *text_color; - eventbox = gtk_event_box_new (); - gtk_container_set_border_width (GTK_CONTAINER (eventbox), 2); - gtk_event_box_set_visible_window (GTK_EVENT_BOX (eventbox), FALSE); + g_return_if_fail (E_IS_ICON_ENTRY (icon_entry)); - image = gtk_image_new_from_stock (stock, GTK_ICON_SIZE_MENU); - gtk_container_add (GTK_CONTAINER (eventbox), image); + if (visual_state == GTK_STATE_NORMAL) { + base_color = NULL; + text_color = NULL; + } else { + GtkStyle *style; - g_signal_connect_after (eventbox, "enter-notify-event", (GCallback) set_cursor, NULL); - g_signal_connect_after (eventbox, "leave-notify-event", (GCallback) set_cursor, NULL); + style = gtk_widget_get_default_style (); + base_color = &style->base[visual_state]; + text_color = &style->text[visual_state]; + } - return eventbox; -} + widget = GTK_WIDGET (icon_entry); + gtk_widget_modify_base (widget, GTK_STATE_NORMAL, base_color); -GtkWidget * -e_icon_entry_get_entry (EIconEntry *entry) -{ - g_return_val_if_fail (E_IS_ICON_ENTRY (entry), NULL); + widget = icon_entry->priv->entry; + gtk_widget_modify_base (widget, GTK_STATE_NORMAL, base_color); + gtk_widget_modify_text (widget, GTK_STATE_NORMAL, text_color); + + widget = icon_entry->priv->hbox; + gtk_widget_modify_base (widget, GTK_STATE_NORMAL, base_color); - return entry->entry; + icon_entry->priv->visual_state = visual_state; + g_object_notify (G_OBJECT (icon_entry), "visual-state"); } |