1 |
/* Implements a lightweight menubar widget. |
/* Implements a lightweight menubar widget. |
2 |
Copyright (C) 1992 Lucid, Inc. |
Copyright (C) 1992 Lucid, Inc. |
3 |
|
Copyright (C) 2002 Free Software Foundation, Inc. |
4 |
|
|
5 |
This file is part of the Lucid Widget Library. |
This file is part of the Lucid Widget Library. |
6 |
|
|
115 |
<KeyUp>Alt_R: nothing()\n\ |
<KeyUp>Alt_R: nothing()\n\ |
116 |
<KeyUp>Caps_Lock: nothing()\n\ |
<KeyUp>Caps_Lock: nothing()\n\ |
117 |
<KeyUp>Shift_Lock:nothing()\n\ |
<KeyUp>Shift_Lock:nothing()\n\ |
118 |
|
<Key>Return: select()\n\ |
119 |
|
<Key>Down: down()\n\ |
120 |
|
<Key>Up: up()\n\ |
121 |
|
<Key>Left: left()\n\ |
122 |
|
<Key>Right: right()\n\ |
123 |
<Key>: key()\n\ |
<Key>: key()\n\ |
124 |
<KeyUp>: key()\n\ |
<KeyUp>: key()\n\ |
125 |
"; |
"; |
126 |
|
|
127 |
|
/* FIXME: Space should toggle toggleable menu item but not remove the menu |
128 |
|
so you can toggle the next one without entering the menu again. */ |
129 |
|
|
130 |
|
/* FIXME: Should ESC close one level of menu structure or the complete menu? */ |
131 |
|
|
132 |
|
|
133 |
#define offset(field) XtOffset(XlwMenuWidget, field) |
#define offset(field) XtOffset(XlwMenuWidget, field) |
134 |
static XtResource |
static XtResource |
135 |
xlwMenuResources[] = |
xlwMenuResources[] = |
186 |
static void XlwMenuClassInitialize(); |
static void XlwMenuClassInitialize(); |
187 |
static void Start(); |
static void Start(); |
188 |
static void Drag(); |
static void Drag(); |
189 |
|
static void Down(); |
190 |
|
static void Up(); |
191 |
|
static void Left(); |
192 |
|
static void Right(); |
193 |
static void Select(); |
static void Select(); |
194 |
static void Key(); |
static void Key(); |
195 |
static void Nothing(); |
static void Nothing(); |
200 |
{ |
{ |
201 |
{"start", Start}, |
{"start", Start}, |
202 |
{"drag", Drag}, |
{"drag", Drag}, |
203 |
|
{"down", Down}, |
204 |
|
{"up", Up}, |
205 |
|
{"left", Left}, |
206 |
|
{"right", Right}, |
207 |
{"select", Select}, |
{"select", Select}, |
208 |
{"key", Key}, |
{"key", Key}, |
209 |
{"nothing", Nothing}, |
{"nothing", Nothing}, |
2004 |
{ |
{ |
2005 |
} |
} |
2006 |
|
|
2007 |
|
widget_value * |
2008 |
|
find_next_selectable (mw, item) |
2009 |
|
XlwMenuWidget mw; |
2010 |
|
widget_value *item; |
2011 |
|
{ |
2012 |
|
widget_value *current = item; |
2013 |
|
enum menu_separator separator; |
2014 |
|
|
2015 |
|
while (current->next && (current=current->next) && |
2016 |
|
(lw_separator_p (current->name, &separator, 0) || !current->enabled)) |
2017 |
|
; |
2018 |
|
|
2019 |
|
if (current == item) |
2020 |
|
{ |
2021 |
|
current = mw->menu.old_stack [mw->menu.old_depth - 2]->contents; |
2022 |
|
|
2023 |
|
while (lw_separator_p (current->name, &separator, 0) || !current->enabled) |
2024 |
|
if (current->next) |
2025 |
|
current=current->next; |
2026 |
|
} |
2027 |
|
|
2028 |
|
return current; |
2029 |
|
} |
2030 |
|
|
2031 |
|
widget_value * |
2032 |
|
find_prev_selectable (mw, item) |
2033 |
|
XlwMenuWidget mw; |
2034 |
|
widget_value *item; |
2035 |
|
{ |
2036 |
|
widget_value *current = item; |
2037 |
|
widget_value *prev = item; |
2038 |
|
|
2039 |
|
while ((current=find_next_selectable (mw, current)) != item) |
2040 |
|
prev=current; |
2041 |
|
|
2042 |
|
return prev; |
2043 |
|
} |
2044 |
|
|
2045 |
|
static void |
2046 |
|
Down (w, ev, params, num_params) |
2047 |
|
Widget w; |
2048 |
|
XEvent *ev; |
2049 |
|
String *params; |
2050 |
|
Cardinal *num_params; |
2051 |
|
{ |
2052 |
|
XlwMenuWidget mw = (XlwMenuWidget) w; |
2053 |
|
widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; |
2054 |
|
|
2055 |
|
/* Inside top-level menu-bar? */ |
2056 |
|
if (mw->menu.old_depth == 2) |
2057 |
|
/* When <down> in the menu-bar is pressed, display the corresponding |
2058 |
|
sub-menu and select the first menu item there. */ |
2059 |
|
set_new_state (mw, selected_item->contents, mw->menu.old_depth); |
2060 |
|
else |
2061 |
|
/* Highlight next possible (enabled and not separator) menu item. */ |
2062 |
|
set_new_state (mw, find_next_selectable (mw, selected_item), mw->menu.old_depth - 1); |
2063 |
|
|
2064 |
|
remap_menubar (mw); |
2065 |
|
} |
2066 |
|
|
2067 |
|
static void |
2068 |
|
Up (w, ev, params, num_params) |
2069 |
|
Widget w; |
2070 |
|
XEvent *ev; |
2071 |
|
String *params; |
2072 |
|
Cardinal *num_params; |
2073 |
|
{ |
2074 |
|
XlwMenuWidget mw = (XlwMenuWidget) w; |
2075 |
|
widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; |
2076 |
|
|
2077 |
|
/* Inside top-level menu-bar? */ |
2078 |
|
if (mw->menu.old_depth == 2) |
2079 |
|
{ |
2080 |
|
/* FIXME: this is tricky. <up> in the menu-bar should select the |
2081 |
|
last selectable item in the list. So we select the first one and |
2082 |
|
find the previous selectable item. Is there a better way? */ |
2083 |
|
set_new_state (mw, selected_item->contents, mw->menu.old_depth); |
2084 |
|
remap_menubar (mw); |
2085 |
|
selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; |
2086 |
|
set_new_state (mw, find_prev_selectable (mw, selected_item), mw->menu.old_depth - 1); |
2087 |
|
} |
2088 |
|
else |
2089 |
|
/* Highlight previous (enabled and not separator) menu item. */ |
2090 |
|
set_new_state (mw, find_prev_selectable (mw, selected_item), mw->menu.old_depth - 1); |
2091 |
|
|
2092 |
|
remap_menubar (mw); |
2093 |
|
} |
2094 |
|
|
2095 |
|
static void |
2096 |
|
Left (w, ev, params, num_params) |
2097 |
|
Widget w; |
2098 |
|
XEvent *ev; |
2099 |
|
String *params; |
2100 |
|
Cardinal *num_params; |
2101 |
|
{ |
2102 |
|
XlwMenuWidget mw = (XlwMenuWidget) w; |
2103 |
|
widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; |
2104 |
|
|
2105 |
|
/* Inside top-level menu-bar? */ |
2106 |
|
if (mw->menu.old_depth == 2) |
2107 |
|
/* When <left> in the menu-bar is pressed, display the previous item on |
2108 |
|
the menu-bar. If the current item is the first one, highlight the |
2109 |
|
last item in the menubar (probably Help). */ |
2110 |
|
set_new_state (mw, find_prev_selectable (mw, selected_item), mw->menu.old_depth - 1); |
2111 |
|
else |
2112 |
|
{ |
2113 |
|
pop_new_stack_if_no_contents (mw); |
2114 |
|
set_new_state (mw, mw->menu.old_stack [mw->menu.old_depth - 2], mw->menu.old_depth - 2); |
2115 |
|
} |
2116 |
|
|
2117 |
|
remap_menubar (mw); |
2118 |
|
} |
2119 |
|
|
2120 |
|
static void |
2121 |
|
Right (w, ev, params, num_params) |
2122 |
|
Widget w; |
2123 |
|
XEvent *ev; |
2124 |
|
String *params; |
2125 |
|
Cardinal *num_params; |
2126 |
|
{ |
2127 |
|
XlwMenuWidget mw = (XlwMenuWidget) w; |
2128 |
|
widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; |
2129 |
|
|
2130 |
|
/* Inside top-level menu-bar? */ |
2131 |
|
if (mw->menu.old_depth == 2) |
2132 |
|
/* When <right> in the menu-bar is pressed, display the next item on |
2133 |
|
the menu-bar. If the current item is the last one, highlight the |
2134 |
|
first item (probably File). */ |
2135 |
|
set_new_state (mw, find_next_selectable (mw, selected_item), mw->menu.old_depth - 1); |
2136 |
|
else if (selected_item->contents) /* Is this menu item expandable? */ |
2137 |
|
set_new_state (mw, selected_item->contents, mw->menu.old_depth); |
2138 |
|
else |
2139 |
|
{ |
2140 |
|
pop_new_stack_if_no_contents (mw); |
2141 |
|
set_new_state (mw, mw->menu.old_stack [mw->menu.old_depth - 2], mw->menu.old_depth - 2); |
2142 |
|
} |
2143 |
|
|
2144 |
|
remap_menubar (mw); |
2145 |
|
} |
2146 |
|
|
2147 |
/* Handle key press and release events while menu is popped up. |
/* Handle key press and release events while menu is popped up. |
2148 |
Our action is to get rid of the menu. */ |
Our action is to get rid of the menu. */ |
2149 |
static void |
static void |