Commit 4039c786 authored by Chong Yidong's avatar Chong Yidong
Browse files

Support for menu separators in the GTK tool-bar.

* src/gtkutil.c (XG_BIN_CHILD): New macro.
(xg_get_menu_item_label, xg_update_menubar)
(xg_update_menu_item, xg_tool_bar_menu_proxy)
(xg_show_toolbar_item, update_frame_tool_bar): Use it.
(separator_names, xg_separator_p): Move to keyboard.c.
(create_menus, xg_update_submenu, update_frame_tool_bar): Use
menu_separator_name_p.

* src/keyboard.c (parse_tool_bar_item): Allow menu separators in
tool-bar maps.
(menu_separator_name_p): New function, from gtkutil.c.
(separator_names): Move from gtkutil.c.

* src/keyboard.h (menu_separator_name_p): Add prototype.

* src/nsmenu.m (name_is_separator): Function deleted.
(addItemWithWidgetValue): Use menu_separator_name_p.

* src/w32menu.c (name_is_separator): Function deleted.
(add_menu_item): Use menu_separator_name_p.
parent 8b358e90
......@@ -690,6 +690,11 @@ The command `read-color' now requires a match for a color name or RGB
triplet, instead of signalling an error if the user provides a invalid
input.
** Tool-bars can display separators.
Tool-bar separators are handled like menu separators in menu-bar maps,
i.e. with entries of the form `(menu-item "--")'.
Currently, tool-bar separators are only displayed on GTK.
** Image API
......
2010-12-16 Chong Yidong <cyd@stupidchicken.com>
* tool-bar.el (tool-bar-setup): Add separators.
* menu-bar.el (featurep): Use menu-bar-separator.
2010-12-16 Daiki Ueno <ueno@unixuser.org>
* epa-file.el (epa-file-select-keys): Accept 'silent to inhibit
......
......@@ -523,7 +523,8 @@
,(purecopy "Cut (kill) text in region between mark and current position")))
;; ns-win.el said: Separate undo from cut/paste section.
(if (featurep 'ns)
(define-key menu-bar-edit-menu [separator-undo] `(,(purecopy "--"))))
(define-key menu-bar-edit-menu [separator-undo] menu-bar-separator))
(define-key menu-bar-edit-menu [undo]
`(menu-item ,(purecopy "Undo") undo
:enable (and (not buffer-read-only)
......
......@@ -257,23 +257,23 @@ holds a keymap."
;;; Set up some global items. Additions/deletions up for grabs.
(defun tool-bar-setup ()
;; People say it's bad to have EXIT on the tool bar, since users
;; might inadvertently click that button.
;;(tool-bar-add-item-from-menu 'save-buffers-kill-emacs "exit")
(tool-bar-add-item-from-menu 'find-file "new" nil :label "New File"
:vert-only t)
(tool-bar-add-item-from-menu 'menu-find-file-existing "open" nil
:vert-only t)
:label "Open" :vert-only t)
(tool-bar-add-item-from-menu 'dired "diropen" nil :vert-only t)
(tool-bar-add-item-from-menu 'kill-this-buffer "close" nil :vert-only t)
(tool-bar-add-item-from-menu 'save-buffer "save" nil :vert-only t
:label "Save"
:visible '(or buffer-file-name
(not (eq 'special
(get major-mode
'mode-class)))))
(define-key-after (default-value 'tool-bar-map) [separator-1] menu-bar-separator)
(tool-bar-add-item-from-menu 'undo "undo" nil :vert-only t
:visible '(not (eq 'special (get major-mode
'mode-class))))
(define-key-after (default-value 'tool-bar-map) [separator-2] menu-bar-separator)
(tool-bar-add-item-from-menu (lookup-key menu-bar-edit-menu [cut])
"cut" nil :vert-only t
:visible '(not (eq 'special (get major-mode
......@@ -284,6 +284,7 @@ holds a keymap."
"paste" nil :vert-only t
:visible '(not (eq 'special (get major-mode
'mode-class))))
(define-key-after (default-value 'tool-bar-map) [separator-3] menu-bar-separator)
(tool-bar-add-item-from-menu 'nonincremental-search-forward "search"
nil :label "Search")
;;(tool-bar-add-item-from-menu 'ispell-buffer "spell")
......
2010-12-17 Chong Yidong <cyd@stupidchicken.com>
* keyboard.c (parse_tool_bar_item): Allow menu separators in
tool-bar maps.
(menu_separator_name_p): New function, from gtkutil.c.
(separator_names): Move from gtkutil.c.
* keyboard.h (menu_separator_name_p): Add prototype.
* gtkutil.c (XG_BIN_CHILD): New macro.
(xg_get_menu_item_label, xg_update_menubar)
(xg_update_menu_item, xg_tool_bar_menu_proxy)
(xg_show_toolbar_item, update_frame_tool_bar): Use it.
(separator_names, xg_separator_p): Move to keyboard.c.
(create_menus, xg_update_submenu, update_frame_tool_bar): Use
menu_separator_name_p.
* nsmenu.m (name_is_separator): Function deleted.
(addItemWithWidgetValue): Use menu_separator_name_p.
* w32menu.c (name_is_separator): Function deleted.
(add_menu_item): Use menu_separator_name_p.
2010-12-16 Jan Djärv <jan.h.d@swipnet.se>
* nsterm.m (ns_draw_window_cursor): If the cursor color is the
......
......@@ -2881,7 +2881,8 @@ enum tool_bar_item_idx
/* The binding. */
TOOL_BAR_ITEM_BINDING,
/* Button type. One of nil, `:radio' or `:toggle'. */
/* Button type. One of nil (default button), t (a separator),
`:radio', or `:toggle'. The latter two currently do nothing. */
TOOL_BAR_ITEM_TYPE,
/* Help string. */
......
......@@ -72,6 +72,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define remove_submenu(w) gtk_menu_item_remove_submenu ((w))
#endif
#define XG_BIN_CHILD(x) gtk_bin_get_child (GTK_BIN (x))
/***********************************************************************
Display handling functions
......@@ -2128,54 +2130,6 @@ make_menu_item (const char *utf8_label,
return w;
}
/* Return non-zero if LABEL specifies a separator (GTK only has one
separator type) */
static const char* separator_names[] = {
"space",
"no-line",
"single-line",
"double-line",
"single-dashed-line",
"double-dashed-line",
"shadow-etched-in",
"shadow-etched-out",
"shadow-etched-in-dash",
"shadow-etched-out-dash",
"shadow-double-etched-in",
"shadow-double-etched-out",
"shadow-double-etched-in-dash",
"shadow-double-etched-out-dash",
0,
};
static int
xg_separator_p (const char *label)
{
if (! label) return 0;
else if (strlen (label) > 3
&& strncmp (label, "--", 2) == 0
&& label[2] != '-')
{
int i;
label += 2;
for (i = 0; separator_names[i]; ++i)
if (strcmp (label, separator_names[i]) == 0)
return 1;
}
else
{
/* Old-style separator, maybe. It's a separator if it contains
only dashes. */
while (*label == '-')
++label;
if (*label == 0) return 1;
}
return 0;
}
static int xg_detached_menus;
/* Returns non-zero if there are detached menus. */
......@@ -2374,7 +2328,7 @@ create_menus (widget_value *data,
GtkWidget *w;
if (pop_up_p && !item->contents && !item->call_data
&& !xg_separator_p (item->name))
&& !menu_separator_name_p (item->name))
{
char *utf8_label;
/* A title for a popup. We do the same as GTK does when
......@@ -2387,7 +2341,7 @@ create_menus (widget_value *data,
gtk_widget_set_sensitive (w, FALSE);
if (utf8_label) g_free (utf8_label);
}
else if (xg_separator_p (item->name))
else if (menu_separator_name_p (item->name))
{
group = NULL;
/* GTK only have one separator type. */
......@@ -2499,7 +2453,7 @@ xg_create_widget (const char *type, const char *name, FRAME_PTR f, widget_value
static const char *
xg_get_menu_item_label (GtkMenuItem *witem)
{
GtkLabel *wlabel = GTK_LABEL (gtk_bin_get_child (GTK_BIN (witem)));
GtkLabel *wlabel = GTK_LABEL (XG_BIN_CHILD (witem));
return gtk_label_get_label (wlabel);
}
......@@ -2652,7 +2606,7 @@ xg_update_menubar (GtkWidget *menubar,
Rename X to B (minibuf to C-mode menu).
If the X menu hasn't been invoked, the menu under B
is up to date when leaving the minibuffer. */
GtkLabel *wlabel = GTK_LABEL (gtk_bin_get_child (GTK_BIN (witem)));
GtkLabel *wlabel = GTK_LABEL (XG_BIN_CHILD (witem));
char *utf8_label = get_utf8_string (val->name);
GtkWidget *submenu = gtk_menu_item_get_submenu (witem);
......@@ -2751,7 +2705,7 @@ xg_update_menu_item (widget_value *val,
const char *old_key = 0;
xg_menu_item_cb_data *cb_data;
wchild = gtk_bin_get_child (GTK_BIN (w));
wchild = XG_BIN_CHILD (w);
utf8_label = get_utf8_string (val->name);
utf8_key = get_utf8_string (val->key);
......@@ -2910,7 +2864,7 @@ xg_update_submenu (GtkWidget *submenu,
if (GTK_IS_SEPARATOR_MENU_ITEM (w))
{
if (! xg_separator_p (cur->name))
if (! menu_separator_name_p (cur->name))
break;
}
else if (GTK_IS_CHECK_MENU_ITEM (w))
......@@ -2933,7 +2887,7 @@ xg_update_submenu (GtkWidget *submenu,
GtkWidget *sub;
if (cur->button_type != BUTTON_TYPE_NONE ||
xg_separator_p (cur->name))
menu_separator_name_p (cur->name))
break;
xg_update_menu_item (cur, w, select_cb, highlight_cb, cl_data);
......@@ -3725,9 +3679,8 @@ xg_get_tool_bar_widgets (GtkWidget *vb, GtkWidget **wimage)
static gboolean
xg_tool_bar_menu_proxy (GtkToolItem *toolitem, gpointer user_data)
{
GtkWidget *weventbox = gtk_bin_get_child (GTK_BIN (toolitem));
GtkButton *wbutton = GTK_BUTTON (gtk_bin_get_child (GTK_BIN (weventbox)));
GtkWidget *vb = gtk_bin_get_child (GTK_BIN (wbutton));
GtkButton *wbutton = GTK_BUTTON (XG_BIN_CHILD (XG_BIN_CHILD (toolitem)));
GtkWidget *vb = XG_BIN_CHILD (wbutton);
GtkWidget *c1;
GtkLabel *wlbl = GTK_LABEL (xg_get_tool_bar_widgets (vb, &c1));
GtkImage *wimage = GTK_IMAGE (c1);
......@@ -4180,9 +4133,9 @@ xg_show_toolbar_item (GtkToolItem *ti)
int show_label = ! EQ (style, Qimage) && ! (vert_only && horiz);
int show_image = ! EQ (style, Qtext);
GtkWidget *weventbox = gtk_bin_get_child (GTK_BIN (ti));
GtkWidget *wbutton = gtk_bin_get_child (GTK_BIN (weventbox));
GtkWidget *vb = gtk_bin_get_child (GTK_BIN (wbutton));
GtkWidget *weventbox = XG_BIN_CHILD (ti);
GtkWidget *wbutton = XG_BIN_CHILD (weventbox);
GtkWidget *vb = XG_BIN_CHILD (wbutton);
GtkWidget *wimage;
GtkWidget *wlbl = xg_get_tool_bar_widgets (vb, &wimage);
GtkWidget *new_box = NULL;
......@@ -4330,7 +4283,6 @@ update_frame_tool_bar (FRAME_PTR f)
char *icon_name = NULL;
Lisp_Object rtl;
GtkWidget *wbutton = NULL;
GtkWidget *weventbox;
Lisp_Object specified_file;
const char *label = (STRINGP (PROP (TOOL_BAR_ITEM_LABEL))
? SSDATA (PROP (TOOL_BAR_ITEM_LABEL)) : "");
......@@ -4338,16 +4290,34 @@ update_frame_tool_bar (FRAME_PTR f)
ti = gtk_toolbar_get_nth_item (GTK_TOOLBAR (wtoolbar), i);
if (ti)
{
weventbox = gtk_bin_get_child (GTK_BIN (ti));
wbutton = gtk_bin_get_child (GTK_BIN (weventbox));
}
/* If this is a separator, use a gtk separator item. */
if (EQ (PROP (TOOL_BAR_ITEM_TYPE), Qt))
{
if (ti == NULL || !GTK_IS_SEPARATOR_TOOL_ITEM (ti))
{
if (ti)
gtk_container_remove (GTK_CONTAINER (wtoolbar),
GTK_WIDGET (ti));
ti = gtk_separator_tool_item_new ();
gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, i);
}
gtk_widget_show (GTK_WIDGET (ti));
continue;
}
/* Otherwise, the tool-bar item is an ordinary button. */
if (ti && GTK_IS_SEPARATOR_TOOL_ITEM (ti))
{
gtk_container_remove (GTK_CONTAINER (wtoolbar), GTK_WIDGET (ti));
ti = NULL;
}
image = PROP (TOOL_BAR_ITEM_IMAGES);
if (ti)
wbutton = XG_BIN_CHILD (XG_BIN_CHILD (ti));
/* Ignore invalid image specifications. */
image = PROP (TOOL_BAR_ITEM_IMAGES);
if (!valid_image_p (image))
{
if (wbutton) gtk_widget_hide (wbutton);
......@@ -4426,7 +4396,7 @@ update_frame_tool_bar (FRAME_PTR f)
{
/* Insert an empty (non-image) button */
ti = xg_make_tool_item (f, NULL, NULL, "", i, 0);
gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, -1);
gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, i);
}
continue;
}
......@@ -4460,17 +4430,17 @@ update_frame_tool_bar (FRAME_PTR f)
gtk_misc_set_padding (GTK_MISC (w), hmargin, vmargin);
ti = xg_make_tool_item (f, w, &wbutton, label, i, vert_only);
gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, -1);
gtk_toolbar_insert (GTK_TOOLBAR (wtoolbar), ti, i);
gtk_widget_set_sensitive (wbutton, enabled_p);
}
else
{
GtkWidget *vb = gtk_bin_get_child (GTK_BIN (wbutton));
GtkWidget *vb = XG_BIN_CHILD (wbutton);
GtkWidget *wimage;
GtkWidget *wlbl = xg_get_tool_bar_widgets (vb, &wimage);
Pixmap old_img = (Pixmap)g_object_get_data (G_OBJECT (wimage),
XG_TOOL_BAR_IMAGE_DATA);
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);
gpointer old_icon_name = g_object_get_data (G_OBJECT (wimage),
......
......@@ -7464,6 +7464,54 @@ static Lisp_Object menu_bar_one_keymap_changed_items;
static Lisp_Object menu_bar_items_vector;
static int menu_bar_items_index;
static const char* separator_names[] = {
"space",
"no-line",
"single-line",
"double-line",
"single-dashed-line",
"double-dashed-line",
"shadow-etched-in",
"shadow-etched-out",
"shadow-etched-in-dash",
"shadow-etched-out-dash",
"shadow-double-etched-in",
"shadow-double-etched-out",
"shadow-double-etched-in-dash",
"shadow-double-etched-out-dash",
0,
};
/* Return non-zero if LABEL specifies a separator. */
int
menu_separator_name_p (const char *label)
{
if (!label)
return 0;
else if (strlen (label) > 3
&& strncmp (label, "--", 2) == 0
&& label[2] != '-')
{
int i;
label += 2;
for (i = 0; separator_names[i]; ++i)
if (strcmp (label, separator_names[i]) == 0)
return 1;
}
else
{
/* It's a separator if it contains only dashes. */
while (*label == '-')
++label;
return (*label == 0);
}
return 0;
}
/* Return a vector of menu items for a menu bar, appropriate
to the current buffer. Each item has three elements in the vector:
KEY STRING MAPLIST.
......@@ -8201,10 +8249,14 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
Rule out items that aren't lists, don't start with
`menu-item' or whose rest following `tool-bar-item' is not a
list. */
if (!CONSP (item)
|| !EQ (XCAR (item), Qmenu_item)
|| (item = XCDR (item),
!CONSP (item)))
if (!CONSP (item))
return 0;
/* As an exception, allow old-style menu separators. */
if (STRINGP (XCAR (item)))
item = Fcons (XCAR (item), Qnil);
else if (!EQ (XCAR (item), Qmenu_item)
|| (item = XCDR (item), !CONSP (item)))
return 0;
/* Create tool_bar_item_properties vector if necessary. Reset it to
......@@ -8234,10 +8286,18 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
}
PROP (TOOL_BAR_ITEM_CAPTION) = caption;
/* Give up if rest following the caption is not a list. */
/* If the rest following the caption is not a list, the menu item is
either a separator, or invalid. */
item = XCDR (item);
if (!CONSP (item))
return 0;
{
if (menu_separator_name_p (SDATA (caption)))
{
PROP (TOOL_BAR_ITEM_TYPE) = Qt;
return 1;
}
return 0;
}
/* Store the binding. */
PROP (TOOL_BAR_ITEM_BINDING) = XCAR (item);
......@@ -8270,10 +8330,10 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
if (NILP (menu_item_eval_property (value)))
return 0;
}
else if (EQ (key, QChelp))
else if (EQ (key, QChelp))
/* `:help HELP-STRING'. */
PROP (TOOL_BAR_ITEM_HELP) = value;
else if (EQ (key, QCvert_only))
else if (EQ (key, QCvert_only))
/* `:vert-only t/nil'. */
PROP (TOOL_BAR_ITEM_VERT_ONLY) = value;
else if (EQ (key, QClabel))
......
......@@ -492,6 +492,7 @@ extern int quit_char;
extern int timers_run;
extern int menu_separator_name_p (const char *);
extern int parse_menu_item (Lisp_Object, int);
extern void echo_now (void);
......
......@@ -507,21 +507,6 @@
}
/* Utility (from macmenu.c): is this item a separator? */
static int
name_is_separator ( const char *name)
{
const char *start = name;
/* Check if name string consists of only dashes ('-'). */
while (*name == '-') name++;
/* Separators can also be of the form "--:TripleSuperMegaEtched"
or "--deep-shadow". We don't implement them yet, se we just treat
them like normal separators. */
return (*name == '\0' || start + 2 == name);
}
/* ==========================================================================
Menu: class implementation
......@@ -624,7 +609,7 @@ - (NSMenuItem *)addItemWithWidgetValue: (void *)wvptr
NSMenuItem *item;
widget_value *wv = (widget_value *)wvptr;
if (name_is_separator (wv->name))
if (menu_separator_name_p (wv->name))
{
item = [NSMenuItem separatorItem];
[self addItem: item];
......
......@@ -1326,20 +1326,6 @@ simple_dialog_show (FRAME_PTR f, Lisp_Object contents, Lisp_Object header)
#endif /* !HAVE_DIALOGS */
/* Is this item a separator? */
static int
name_is_separator (const char *name)
{
const char *start = name;
/* Check if name string consists of only dashes ('-'). */
while (*name == '-') name++;
/* Separators can also be of the form "--:TripleSuperMegaEtched"
or "--deep-shadow". We don't implement them yet, se we just treat
them like normal separators. */
return (*name == '\0' || start + 2 == name);
}
/* UTF8: 0xxxxxxx, 110xxxxx 10xxxxxx, 1110xxxx, 10xxxxxx, 10xxxxxx */
static void
utf8to16 (unsigned char * src, int len, WCHAR * dest)
......@@ -1388,7 +1374,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
int return_value;
size_t nlen, orig_len;
if (name_is_separator (wv->name))
if (menu_separator_name_p (wv->name))
{
fuFlags = MF_SEPARATOR;
out_string = NULL;
......
......@@ -10317,6 +10317,10 @@ build_desired_tool_bar_string (struct frame *f)
int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
int hmargin, vmargin, relief, idx, end;
/* Ignore separator items. */
if (EQ (PROP (TOOL_BAR_ITEM_TYPE), Qt))
continue;
/* If image is a vector, choose the image according to the
button state. */
image = PROP (TOOL_BAR_ITEM_IMAGES);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment