1 /*
2 **
3 ** MButton.c
4 **
5 ** Copyright (C) 1995, 1996, 1997 Johannes Plass
6 ** Copyright (C) 2004 Jose E. Marchesi
7 **
8 ** This program is free software; you can redistribute it and/or modify
9 ** it under the terms of the GNU General Public License as published by
10 ** the Free Software Foundation; either version 3 of the License, or
11 ** (at your option) any later version.
12 **
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ** GNU General Public License for more details.
17 **
18 ** You should have received a copy of the GNU General Public License
19 ** along with GNU gv; see the file COPYING. If not, write to
20 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 ** Boston, MA 02111-1307, USA.
22 **
23 ** Author: Johannes Plass (plass@thep.physik.uni-mainz.de)
24 ** Department of Physics
25 ** Johannes Gutenberg-University
26 ** Mainz, Germany
27 **
28 ** Jose E. Marchesi (jemarch@gnu.org)
29 ** GNU Project
30 **
31 */
32 #include "ac_config.h"
33
34 /*
35 #define MESSAGES
36 */
37 #include "message.h"
38
39 #include <stdio.h>
40 #include "paths.h"
41 #include INC_X11(IntrinsicP.h)
42 #include INC_X11(StringDefs.h)
43 #include INC_XAW(XawInit.h)
44 #include "MButtonP.h"
45
46 static void ClassInitialize(void);
47 static void PopupMenu(Widget,XEvent*,String*,Cardinal*);
48
49 #define superclass ((ButtonWidgetClass)&buttonClassRec)
50
51 static char defaultTranslations[] =
52 "Any<BtnDown>:set()PopupMenu()";
53
54 #define offset(field) XtOffsetOf(MButtonRec, field)
55 static XtResource resources[] = {
56 {XtNmenuName, XtCMenuName, XtRString, sizeof(String),
57 offset(mbutton.menu_name), XtRString, (XtPointer)"menu"},
58 {XtNsetFrameStyle, XtCSetFrameStyle, XtRFrameType, sizeof(XawFrameType),
59 offset(button.set_frame_style), XtRImmediate, (XtPointer) XawRAISED },
60 };
61 #undef offset
62
63 static XtActionsRec actionsList[] =
64 {
65 {"PopupMenu", PopupMenu}
66 };
67
68 MButtonClassRec mbuttonClassRec = {
69 {
70 (WidgetClass) superclass, /* superclass */
71 "MButton", /* class_name */
72 sizeof(MButtonRec), /* size */
73 ClassInitialize, /* class_initialize */
74 NULL, /* class_part_initialize */
75 FALSE, /* class_inited */
76 NULL, /* initialize */
77 NULL, /* initialize_hook */
78 XtInheritRealize, /* realize */
79 actionsList, /* actions */
80 XtNumber(actionsList), /* num_actions */
81 resources, /* resources */
82 XtNumber(resources), /* resource_count */
83 NULLQUARK, /* xrm_class */
84 FALSE, /* compress_motion */
85 TRUE, /* compress_exposure */
86 TRUE, /* compress_enterleave */
87 FALSE, /* visible_interest */
88 NULL, /* destroy */
89 XtInheritResize, /* resize */
90 XtInheritExpose, /* expose */
91 NULL, /* set_values */
92 NULL, /* set_values_hook */
93 XtInheritSetValuesAlmost, /* set_values_almost */
94 NULL, /* get_values_hook */
95 NULL, /* accept_focus */
96 XtVersion, /* version */
97 NULL, /* callback_private */
98 defaultTranslations, /* tm_table */
99 XtInheritQueryGeometry, /* query_geometry */
100 XtInheritDisplayAccelerator, /* display_accelerator */
101 NULL /* extension */
102 }, /* CoreClass fields initialization */
103 {
104 XtInheritChangeSensitive /* change_sensitive */
105 }, /* SimpleClass fields initialization */
106 {
107 XtInheritXaw3dShadowDraw, /* shadowdraw */
108 }, /* ThreeDClass fields initialization */
109 {
110 0, /* field not used */
111 }, /* LabelClass fields initialization */
112 {
113 0, /* field not used */
114 }, /* CommandClass fields initialization */
115 {
116 0, /* field not used */
117 }, /* ButtonClass fields initialization */
118 {
119 0, /* field not used */
120 } /* MbuttonClass fields initialization */
121 };
122
123 /* for public consumption */
124 WidgetClass mbuttonWidgetClass = (WidgetClass) &mbuttonClassRec;
125
126 /****************************************************************
127 *
128 * Private Procedures
129 *
130 ****************************************************************/
131
ClassInitialize(void)132 static void ClassInitialize(void)
133 {
134 XawInitializeWidgetSet();
135 XtRegisterGrabAction(PopupMenu, True,
136 (unsigned int)(ButtonPressMask | ButtonReleaseMask),
137 GrabModeAsync, GrabModeAsync);
138 }
139
140 void
PopupMenu(Widget w,XEvent * event _GL_UNUSED,String * params _GL_UNUSED,Cardinal * num_params)141 PopupMenu(Widget w, XEvent *event _GL_UNUSED, String *params _GL_UNUSED, Cardinal *num_params)
142 {
143 MButtonWidget mbw = (MButtonWidget) w;
144 Widget temp;
145 Widget menu;
146 Arg args[5];
147 Cardinal n;
148 int menu_x, menu_y;
149 Dimension menu_width, menu_height,button_width,button_height;
150 Position button_x, button_y;
151
152 BEGINMESSAGE(PopupMenu)
153
154 temp = w;
155 menu = NULL;
156 while(temp != NULL) {
157 menu = XtNameToWidget(temp, mbw->mbutton.menu_name);
158 if (!menu) temp = XtParent(temp);
159 else break;
160 }
161
162 if (!menu) {
163 #if 0
164 char error_buf[BUFSIZ];
165 (void) sprintf(error_buf, "Mbutton: %s %s.","Could not find menu widget named", mbw->mbutton.menu_name);
166 XtAppWarning(XtWidgetToApplicationContext(w), error_buf);
167 #endif
168 ENDMESSAGE(PopupMenu)
169 return;
170 }
171 if (!XtIsRealized(menu)) XtRealizeWidget(menu);
172
173 menu_width = menu->core.width + 2 * menu->core.border_width;
174 menu_height = menu->core.height + 2 * menu->core.border_width;
175 button_width = w->core.width + 2 * w->core.border_width;
176 button_height = w->core.height + 2 * w->core.border_width;
177
178 XtTranslateCoords(w, 0, 0, &button_x, &button_y);
179 menu_x = button_x;
180 menu_y = button_y;
181 if (*num_params==0) menu_y += button_height;
182
183 if (menu_x >= 0) {
184 int scr_width = WidthOfScreen(XtScreen(menu));
185 if (menu_x + menu_width > scr_width) menu_x = scr_width - menu_width;
186 }
187 if (menu_x < 0) menu_x = 0;
188
189 if (menu_y >= 0) {
190 int scr_height = HeightOfScreen(XtScreen(menu));
191 if (menu_y + menu_height > scr_height) menu_y = scr_height - menu_height;
192 }
193 if (menu_y < 0) menu_y = 0;
194
195 n = 0;
196 XtSetArg(args[n], XtNx, menu_x); n++;
197 XtSetArg(args[n], XtNy, menu_y); n++;
198 if (*num_params > 0 && menu_width<button_width) {
199 XtSetArg(args[n], XtNwidth, button_width-2*menu->core.border_width); n++;
200 }
201 XtSetValues(menu, args, n);
202
203 XtPopupSpringLoaded(menu);
204 ENDMESSAGE(PopupMenu)
205 }
206
207