1
////////////////////////////////////////////////////////////////////////////////
3
// This file is part of Toolkit for Conceptual Modeling (TCM).
4
// (c) copyright 1997, Vrije Universiteit Amsterdam.
5
// Author: Frank Dehne (frank@cs.vu.nl).
7
// TCM is free software; you can redistribute it and/or modify
8
// it under the terms of the GNU General Public License as published by
9
// the Free Software Foundation; either version 2 of the License, or
10
// (at your option) any later version.
12
// TCM is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
// GNU General Public License for more details.
17
// You should have received a copy of the GNU General Public License
18
// along with TCM; if not, write to the Free Software
19
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21
////////////////////////////////////////////////////////////////////////////////
28
Menu::Menu(Widget parent, MenuType type, const char *n, char mnemonic,
29
MenuItem *items): MWidget(n) {
31
// create menu widget.
32
SetWidget(BuildMenu(parent, menuType, (char *)GetName()->getstr(),
34
// set up destruction handler.
35
InstallDestroyHandler();
38
Widget Menu::GetNthMenuItem(int n) {
39
return GetNthChild(GetWidget(), menuType, n);
42
Widget Menu::GetNthChild(Widget w, MenuType type, int n) {
44
WidgetList wlist; int numc;
46
XtVaGetValues(w, XmNsubMenuId, &submenu, 0);
51
XtVaGetValues(submenu, XmNchildren, &wlist, 0);
52
XtVaGetValues(submenu, XmNnumChildren, &numc, 0);
59
void Menu::SetNthChildToggleState(Widget w, MenuType type, int n,
60
bool state, bool notify) {
61
Widget child = GetNthChild(w, type, n);
63
XmToggleButtonSetState(child, state, notify);
66
void Menu::SetNthChildSensitive(Widget w, MenuType type, int n,
68
Widget child = GetNthChild(w, type, n);
70
XtVaSetValues(child, XmNsensitive, state, 0);
73
Widget Menu::GetMenuItem(const char *label) {
74
return GetChild(GetWidget(), menuType, label);
77
Widget Menu::GetChild(Widget w, MenuType menuType, const char *label) {
79
WidgetList wlist; int numc;
80
if (menuType == PULLDOWN)
81
XtVaGetValues(w, XmNsubMenuId, &submenu, 0);
86
XtVaGetValues(submenu, XmNchildren, &wlist, 0);
87
XtVaGetValues(submenu, XmNnumChildren, &numc, 0);
89
for (int i=0; i < numc; i++) {
90
s2 = CreateXmString("");
91
XtVaGetValues(wlist[i], XmNlabelString, &s2, 0);
93
if (XmStringGetLtoR(s2, XmFONTLIST_DEFAULT_TAG, &str)) {
94
// std::cout << str << std::endl;
95
// std::cout << label << std::endl;
96
if (strstr(str, label)) {
108
void Menu::SetChildToggleState(Widget w, MenuType type,
109
const char *label, bool state, bool notify) {
110
Widget child = GetChild(w, type, label);
112
XmToggleButtonSetState(child, state, notify);
115
void Menu::SetChildSensitive(Widget w, MenuType type,
116
const char *label, bool state) {
117
Widget child = GetChild(w, type, label);
119
XtVaSetValues(child, XmNsensitive, state, 0);
122
// Build popup, option and pulldown menus, depending on the menu type.
123
// It may be Pulldown, Option or Popup. Pulldowns
124
// return the CascadeButton that pops up the menu. Popups return the menu.
125
// Option menus are created, but the RowColumn that acts as the option
126
// "area" is returned unmanaged. (The user must manage it.)
127
// Pulldown menus are built from cascade buttons, so this function
128
// also builds pullright menus. The function also adds user data
129
// for PushButton or ToggleButton menu items.
130
Widget Menu::BuildMenu(Widget parent, MenuType type, const char *label,
131
char mnemonic, MenuItem *items) {
132
Widget menu, cascade, submenu;
136
if (type == PULLDOWN || type == OPTION) {
137
strcpy(wname, "_pulldown");
138
menu = XmCreatePulldownMenu(parent, wname, 0, 0);
140
else if (type == POPUP) {
141
strcpy(wname, "_popup");
142
menu = XmCreatePopupMenu(parent, wname, 0, 0);
145
XtWarning("Invalid menu type passed to BuildMenu()");
148
// Pulldown menus require a cascade button to be made
149
if (type == PULLDOWN) {
150
str = CreateXmString(label);
151
cascade = XtVaCreateManagedWidget(label,
152
xmCascadeButtonWidgetClass, parent,
155
XmNmnemonic, mnemonic, 0);
157
} else if (type == OPTION) {
158
// Option menus are a special case, but not hard to handle
160
str = CreateXmString(label);
161
XtSetArg(args[i], XmNsubMenuId, menu); i++;
162
XtSetArg(args[i], XmNlabelString, str); i++;
163
// This really isn't a cascade, but this is the widget handle
164
// we're going to return at the end of the function.
165
//HZ cascade = XmCreateSimpleOptionMenu(parent, label, args, i);
166
cascade = XmCreateOptionMenu(parent, (char *)label, args, i);
171
// Now add the menu items
172
for (i = 0; items[i].label != 0; i++) {
173
// If subitems exist, create the pull-right menu by calling this
174
// function recursively. Since the function returns a cascade
175
// button, the widget returned is used..
177
if (items[i].subitems) {
178
if (type == OPTION) {
179
XtWarning("You can't have submenus from "
180
"option menu items.");
183
submenu = BuildMenu(menu, PULLDOWN,
184
items[i].label, items[i].mnemonic,
189
int tp = items[i].itemType;
190
if (tp == MenuItem::SUBMENU)
191
wc = &xmCascadeButtonWidgetClass;
192
else if (tp == MenuItem::RADIOBUTTON ||
193
tp == MenuItem::CHECKBUTTON)
194
wc = &xmToggleButtonWidgetClass;
195
else if (tp == MenuItem::SEPARATOR)
196
wc = &xmSeparatorWidgetClass;
197
else if (tp == MenuItem::LABEL)
198
wc = &xmLabelWidgetClass;
200
wc = &xmPushButtonWidgetClass;
201
submenu = XtVaCreateManagedWidget(items[i].label,
204
// toggle buttons are always visible as such
205
if (items[i].itemType == MenuItem::RADIOBUTTON ||
206
items[i].itemType == MenuItem::CHECKBUTTON) {
208
XtVaSetValues(submenu, XmNindicatorOn, True,
209
XmNvisibleWhenOff, True,
210
XmNindicatorSize, 12,
213
if (items[i].itemType == MenuItem::RADIOBUTTON) {
215
XmNradioBehavior, True, 0);
216
XtVaSetValues(submenu,
217
XmNindicatorType, XmONE_OF_MANY, 0);
220
if ((int)items[i].userData & 0x1)
221
XtVaSetValues(submenu, XmNset, True, 0);
224
if (items[i].userData)
225
XtVaSetValues(submenu, XmNuserData,
226
items[i].userData, 0);
228
// Whether the item is a real item or a cascade button with a
229
// menu, it can still have a mnemonic.
231
if (items[i].mnemonic)
232
XtVaSetValues(submenu, XmNmnemonic,
233
items[i].mnemonic, 0);
234
// any item can have an accelerator, except cascade menus. But,
235
// we don't worry about that; we know better in our
237
if (items[i].accelerator) {
238
str = CreateXmString(items[i].accelText);
239
XtVaSetValues(submenu, XmNacceleratorText, str, 0);
240
XtVaSetValues(submenu, XmNaccelerator,
241
items[i].accelerator, 0);
245
if (items[i].callback)
246
// ToggleButton class or PushButton class
247
XtAddCallback(submenu,
248
(items[i].itemType == MenuItem::CHECKBUTTON ||
249
items[i].itemType == MenuItem::RADIOBUTTON)?
250
XmNvalueChangedCallback :
252
items[i].callback, items[i].callbackData);
254
// set if item is selectable
255
XtVaSetValues(submenu, XmNsensitive, items[i].sensitive, 0);
257
if (items[i].showBitmap) {
258
Bitmap b = items[i].bitmap;
259
if (check(XtDisplay(menu))) {
260
Pixmap px = b.CreatePixmap(menu,
262
XtVaSetValues(submenu,
263
XmNlabelType, XmPIXMAP,
264
XmNlabelPixmap, px, 0);
268
// for popup menus, just return the menu; pulldown menus, return
269
// the cascade button; option menus, return the thing returned
270
// from XmCreateOptionMenu(). This isn't a menu, or a cascade button!
271
return type == POPUP? menu : cascade;