Mercurial > emacs
changeset 82931:3a5f0fb127ce
(xg_tool_bar_expose_callback): Just do SET_FRAME_GARBAGED
so no Lisp code is executed.
(file_for_image, find_rtl_image): New functions.
(xg_get_image_for_pixmap): Use file_for_image
(update_frame_tool_bar): If direction is RTL, use RTL image if
defined. Use Gtk stock images if defined.
author | Jan Djärv <jan.h.d@swipnet.se> |
---|---|
date | Tue, 28 Aug 2007 10:11:19 +0000 |
parents | 57df421aa5e8 |
children | 7db330affbcb |
files | src/gtkutil.c |
diffstat | 1 files changed, 180 insertions(+), 63 deletions(-) [+] |
line wrap: on
line diff
--- a/src/gtkutil.c Tue Aug 28 05:48:08 2007 +0000 +++ b/src/gtkutil.c Tue Aug 28 10:11:19 2007 +0000 @@ -298,6 +298,23 @@ return icon_buf; } +static Lisp_Object +file_for_image(image) + Lisp_Object image; +{ + Lisp_Object specified_file = Qnil; + Lisp_Object tail; + extern Lisp_Object QCfile; + + for (tail = XCDR (image); + NILP (specified_file) && CONSP (tail) && CONSP (XCDR (tail)); + tail = XCDR (XCDR (tail))) + if (EQ (XCAR (tail), QCfile)) + specified_file = XCAR (XCDR (tail)); + + return specified_file; +} + /* For the image defined in IMG, make and return a GtkImage. For displays with 8 planes or less we must make a GdkPixbuf and apply the mask manually. Otherwise the highlightning and dimming the tool bar code in GTK does @@ -323,16 +340,8 @@ /* If we have a file, let GTK do all the image handling. This seems to be the only way to make insensitive and activated icons look good in all cases. */ - Lisp_Object specified_file = Qnil; - Lisp_Object tail; + Lisp_Object specified_file = file_for_image (img->spec); Lisp_Object file; - extern Lisp_Object QCfile; - - for (tail = XCDR (img->spec); - NILP (specified_file) && CONSP (tail) && CONSP (XCDR (tail)); - tail = XCDR (XCDR (tail))) - if (EQ (XCAR (tail), QCfile)) - specified_file = XCAR (XCDR (tail)); /* We already loaded the image once before calling this function, so this only fails if the image file has been removed. @@ -3332,6 +3341,16 @@ /* The key for storing the button widget in its proxy menu item. */ #define XG_TOOL_BAR_PROXY_BUTTON "emacs-tool-bar-proxy-button" +/* The key for the data we put in the GtkImage widgets. The data is + the stock name used by Emacs. We use this to see if we need to update + the GtkImage with a new image. */ +#define XG_TOOL_BAR_STOCK_NAME "emacs-tool-bar-stock-name" + +/* Callback function invoked when a tool bar item is pressed. + W is the button widget in the tool bar that got pressed, + CLIENT_DATA is an integer that is the index of the button in the + tool bar. 0 is the first button. */ + static gboolean xg_tool_bar_button_cb (widget, event, user_data) GtkWidget *widget; @@ -3614,8 +3633,10 @@ return FALSE; } +#define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX)) + /* This callback is called when a tool bar shall be redrawn. - We need to update the tool bar from here in case the image cache + We need to update the images in case the image cache has deleted the pixmaps used in the tool bar. W is the GtkToolbar to be redrawn. EVENT is the expose event for W. @@ -3629,7 +3650,8 @@ GdkEventExpose *event; gpointer client_data; { - update_frame_tool_bar ((FRAME_PTR) client_data); + FRAME_PTR f = (FRAME_PTR) client_data; + SET_FRAME_GARBAGED (f); return FALSE; } @@ -3690,6 +3712,40 @@ SET_FRAME_GARBAGED (f); } +/* Find the right-to-left image named by RTL in the tool bar images for F. + Returns IMAGE if RTL is not found. */ + +static Lisp_Object +find_rtl_image (f, image, rtl) + FRAME_PTR f; + Lisp_Object image; + Lisp_Object rtl; +{ + int i; + Lisp_Object file, rtl_name; + struct gcpro gcpro1, gcpro2; + GCPRO2 (file, rtl_name); + + rtl_name = Ffile_name_nondirectory (rtl); + + for (i = 0; i < f->n_tool_bar_items; ++i) + { + Lisp_Object rtl_image = PROP (TOOL_BAR_ITEM_IMAGES); + if (!NILP (file = file_for_image (rtl_image))) + { + file = call1 (intern ("file-name-sans-extension"), + Ffile_name_nondirectory (file)); + if (EQ (Fequal (file, rtl_name), Qt)) + { + image = rtl_image; + break; + } + } + } + + return image; +} + /* Update the tool bar for frame F. Add new buttons and remove old. */ void @@ -3700,7 +3756,9 @@ GtkRequisition old_req, new_req; struct x_output *x = f->output_data.x; int hmargin = 0, vmargin = 0; + GtkToolbar *wtoolbar; GtkToolItem *ti; + GtkTextDirection dir; if (! FRAME_GTK_WIDGET (f)) return; @@ -3734,20 +3792,27 @@ if (! x->toolbar_widget) xg_create_tool_bar (f); - gtk_widget_size_request (x->toolbar_widget, &old_req); + wtoolbar = GTK_TOOLBAR (x->toolbar_widget); + gtk_widget_size_request (GTK_WIDGET (wtoolbar), &old_req); + dir = gtk_widget_get_direction (x->toolbar_widget); for (i = 0; i < f->n_tool_bar_items; ++i) { -#define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX)) int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P)); int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P)); int idx; int img_id; - struct image *img; + int icon_size = 0; + struct image *img = NULL; Lisp_Object image; + Lisp_Object stock; + GtkStockItem stock_item; + char *stock_name = NULL; + Lisp_Object rtl; GtkWidget *wbutton; GtkWidget *weventbox; + Lisp_Object func = intern ("x-gtk-map-stock"); ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (x->toolbar_widget), i); @@ -3757,59 +3822,98 @@ wbutton = gtk_bin_get_child (GTK_BIN (weventbox)); } - /* If image is a vector, choose the image according to the - button state. */ image = PROP (TOOL_BAR_ITEM_IMAGES); - if (VECTORP (image)) - { - if (enabled_p) - idx = (selected_p - ? TOOL_BAR_IMAGE_ENABLED_SELECTED - : TOOL_BAR_IMAGE_ENABLED_DESELECTED); - else - idx = (selected_p - ? TOOL_BAR_IMAGE_DISABLED_SELECTED - : TOOL_BAR_IMAGE_DISABLED_DESELECTED); - - xassert (ASIZE (image) >= idx); - image = AREF (image, idx); - } - else - idx = -1; /* Ignore invalid image specifications. */ if (!valid_image_p (image)) { - if (ti) gtk_widget_hide_all (GTK_WIDGET (ti)); + if (wbutton) gtk_widget_hide (wbutton); continue; } - img_id = lookup_image (f, image); - img = IMAGE_FROM_ID (f, img_id); - prepare_image_for_display (f, img); - - if (img->load_failed_p || img->pixmap == None) + if (EQ (Qt, Ffboundp (func))) + stock = call1 (func, file_for_image (image)); + + if (! NILP (stock) && STRINGP (stock) + && gtk_stock_lookup (SSDATA (stock), &stock_item)) + { + stock_name = SSDATA (stock); + icon_size = gtk_toolbar_get_icon_size (wtoolbar); + } + else { - if (ti) - gtk_widget_hide_all (GTK_WIDGET (ti)); - else + /* No stock image, or stock item not known. Try regular image. */ + + /* If image is a vector, choose the image according to the + button state. */ + if (dir == GTK_TEXT_DIR_RTL + && !NILP (rtl = PROP (TOOL_BAR_ITEM_RTL_IMAGE)) + && STRINGP (rtl)) + { + image = find_rtl_image (f, image, rtl); + } + + if (VECTORP (image)) { - /* Insert an empty (non-image) button */ - weventbox = gtk_event_box_new (); - wbutton = gtk_button_new (); - gtk_button_set_focus_on_click (GTK_BUTTON (wbutton), FALSE); - gtk_button_set_relief (GTK_BUTTON (wbutton), GTK_RELIEF_NONE); - gtk_container_add (GTK_CONTAINER (weventbox), wbutton); - ti = gtk_tool_item_new (); - gtk_container_add (GTK_CONTAINER (ti), weventbox); - gtk_toolbar_insert (GTK_TOOLBAR (x->toolbar_widget), ti, -1); + if (enabled_p) + idx = (selected_p + ? TOOL_BAR_IMAGE_ENABLED_SELECTED + : TOOL_BAR_IMAGE_ENABLED_DESELECTED); + else + idx = (selected_p + ? TOOL_BAR_IMAGE_DISABLED_SELECTED + : TOOL_BAR_IMAGE_DISABLED_DESELECTED); + + xassert (ASIZE (image) >= idx); + image = AREF (image, idx); } - continue; + else + idx = -1; + + img_id = lookup_image (f, image); + img = IMAGE_FROM_ID (f, img_id); + prepare_image_for_display (f, img); + + if (img->load_failed_p || img->pixmap == None) + { + if (ti) + gtk_widget_hide_all (GTK_WIDGET (ti)); + else + { + /* Insert an empty (non-image) button */ + weventbox = gtk_event_box_new (); + wbutton = gtk_button_new (); + gtk_button_set_focus_on_click (GTK_BUTTON (wbutton), FALSE); + gtk_button_set_relief (GTK_BUTTON (wbutton), + GTK_RELIEF_NONE); + gtk_container_add (GTK_CONTAINER (weventbox), wbutton); + ti = gtk_tool_item_new (); + gtk_container_add (GTK_CONTAINER (ti), weventbox); + gtk_toolbar_insert (GTK_TOOLBAR (x->toolbar_widget), ti, -1); + } + continue; + } } if (ti == NULL) { - GtkWidget *w = xg_get_image_for_pixmap (f, img, x->widget, NULL); + GtkWidget *w; + if (stock_name) + { + w = gtk_image_new_from_stock (stock_name, icon_size); + g_object_set_data_full (G_OBJECT (w), XG_TOOL_BAR_STOCK_NAME, + (gpointer) xstrdup (stock_name), + (GDestroyNotify) xfree); + } + else + { + w = xg_get_image_for_pixmap (f, img, x->widget, NULL); + /* Save the image so we can see if an update is needed when + this function is called again. */ + g_object_set_data (G_OBJECT (w), XG_TOOL_BAR_IMAGE_DATA, + (gpointer)img->pixmap); + } + gtk_misc_set_padding (GTK_MISC (w), hmargin, vmargin); wbutton = gtk_button_new (); gtk_button_set_focus_on_click (GTK_BUTTON (wbutton), FALSE); @@ -3833,10 +3937,6 @@ gtk_widget_show_all (GTK_WIDGET (ti)); - /* Save the image so we can see if an update is needed when - this function is called again. */ - g_object_set_data (G_OBJECT (w), XG_TOOL_BAR_IMAGE_DATA, - (gpointer)img->pixmap); g_object_set_data (G_OBJECT (weventbox), XG_FRAME_DATA, (gpointer)f); @@ -3878,14 +3978,31 @@ GtkWidget *wimage = gtk_bin_get_child (GTK_BIN (wbutton)); Pixmap old_img = (Pixmap)g_object_get_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA); + gpointer old_stock_name = g_object_get_data (G_OBJECT (wimage), + XG_TOOL_BAR_STOCK_NAME); + if (stock_name && + (! old_stock_name || strcmp (old_stock_name, stock_name) != 0)) + { + gtk_image_set_from_stock (GTK_IMAGE (wimage), + stock_name, icon_size); + g_object_set_data_full (G_OBJECT (wimage), XG_TOOL_BAR_STOCK_NAME, + (gpointer) xstrdup (stock_name), + (GDestroyNotify) xfree); + g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA, + NULL); + } + else if (img && old_img != img->pixmap) + { + (void) xg_get_image_for_pixmap (f, img, x->widget, wimage); + g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA, + (gpointer)img->pixmap); + + g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_STOCK_NAME, + NULL); + } + gtk_misc_set_padding (GTK_MISC (wimage), hmargin, vmargin); - if (old_img != img->pixmap) - (void) xg_get_image_for_pixmap (f, img, x->widget, wimage); - - g_object_set_data (G_OBJECT (wimage), XG_TOOL_BAR_IMAGE_DATA, - (gpointer)img->pixmap); - gtk_widget_set_sensitive (wbutton, enabled_p); gtk_widget_show_all (GTK_WIDGET (ti)); } @@ -3901,7 +4018,7 @@ if (ti) gtk_widget_hide_all (GTK_WIDGET (ti)); } while (ti != NULL); - gtk_widget_size_request (x->toolbar_widget, &new_req); + gtk_widget_size_request (GTK_WIDGET (wtoolbar), &new_req); if (old_req.height != new_req.height && ! FRAME_X_OUTPUT (f)->toolbar_detached) {