1 # include "appFrameConfig.h"
2
3 # include <stdio.h>
4
5 # include "guiWidgetsImpl.h"
6 # include "guiWidgets.h"
7 # include "guiOptionmenu.h"
8
9 # include <appDebugon.h>
10
11 # ifdef USE_MOTIF
12
13 # include <Xm/RowColumn.h>
14 # include <Xm/PushBG.h>
15
16 # define RECLAIM_FOCUS 0
17
18 /************************************************************************/
19 /* */
20 /* Get around Motif's ridiculous resize behavior. */
21 /* */
22 /************************************************************************/
23
appOptionmenuSetWidthMotif(Widget menu,int newWidth)24 static void appOptionmenuSetWidthMotif( Widget menu,
25 int newWidth )
26 {
27 Dimension parentMarginWidth= 0;
28
29 Widget pulldown;
30 Widget buttonGadget;
31
32 XtWidgetGeometry xwg;
33
34 /*
35 SDEB(XtClass(menu)->core_class.class_name);
36 */
37
38 XtVaGetValues( menu,
39 XmNsubMenuId, &pulldown,
40 NULL );
41
42 XtVaGetValues( XtParent( pulldown ),
43 XmNmarginWidth, &parentMarginWidth,
44 NULL );
45
46 if ( newWidth < 2* parentMarginWidth )
47 { LLDEB(newWidth,parentMarginWidth); return; }
48
49 XtVaSetValues( pulldown,
50 XmNwidth, newWidth-
51 2* parentMarginWidth,
52 NULL );
53
54 buttonGadget= XmOptionButtonGadget( menu );
55
56 XtQueryGeometry( buttonGadget, NULL, &xwg );
57
58 XtResizeWidget( buttonGadget, newWidth, xwg.height, xwg.border_width );
59
60 return;
61 }
62
appOptionmenuRefreshWidth(AppOptionmenu * aom)63 void appOptionmenuRefreshWidth( AppOptionmenu * aom )
64 {
65 Dimension width;
66
67 if ( ! aom->aomInplace )
68 { XDEB(aom->aomInplace); return; }
69
70 XtVaGetValues( aom->aomInplace,
71 XmNwidth, &width,
72 NULL );
73
74 appOptionmenuSetWidthMotif( aom->aomInplace, width );
75
76 return;
77 }
78
79 /************************************************************************/
80 /* */
81 /* Dispatch the callback for an option menu and.. */
82 /* */
83 /* Reclaim focus that drifted away. */
84 /* This is to work around a bug in the Xfce window manager (Oct 2004). */
85 /* */
86 /************************************************************************/
87
appOptionMenuMotifCallback(Widget w,void * voidaom,void * pbcs)88 static void appOptionMenuMotifCallback( Widget w,
89 void * voidaom,
90 void * pbcs )
91 {
92 AppOptionmenu * aom= (AppOptionmenu *)voidaom;
93 short idx= -1;
94
95 XtVaGetValues( w, XmNpositionIndex, &idx,
96 NULL );
97 if ( idx < 0 )
98 { LDEB(idx); return; }
99
100 if ( aom->aomCallback )
101 { (*aom->aomCallback)( idx, aom->aomTarget ); }
102
103 # if RECLAIM_FOCUS
104 appGuiMotifSetFocusToWindow( aom->aomInplace );
105 # endif
106
107 return;
108 }
109
110 /************************************************************************/
111 /* */
112 /* Make a pulldown that is usable as a child of a form. */
113 /* */
114 /************************************************************************/
115
appOptionMenuConfigureMotif(Widget w,void * through,XEvent * event,Boolean * pRefused)116 static void appOptionMenuConfigureMotif( Widget w,
117 void * through,
118 XEvent * event,
119 Boolean * pRefused )
120 {
121 XConfigureEvent * cevent= &(event->xconfigure);
122
123 if ( cevent->type != ConfigureNotify )
124 { return; }
125
126 appOptionmenuSetWidthMotif( w, cevent->width );
127
128 *pRefused= 1;
129
130 return;
131 }
132
appFinishOptionmenuMotif(Widget menu,Widget pulldown)133 void appFinishOptionmenuMotif( Widget menu,
134 Widget pulldown )
135 {
136 Widget labelGadget;
137 Widget buttonGadget;
138
139 XtAddEventHandler( menu, StructureNotifyMask, False,
140 appOptionMenuConfigureMotif, (void *)0 );
141
142 labelGadget= XmOptionLabelGadget( menu );
143 buttonGadget= XmOptionButtonGadget( menu );
144
145 XtUnmanageChild( labelGadget );
146 XtManageChild( buttonGadget );
147
148 XtVaSetValues( buttonGadget,
149 XmNalignment, XmALIGNMENT_BEGINNING,
150 XmNmarginHeight, 1,
151 NULL );
152
153 return;
154 }
155
appMakeOptionmenuInColumn(AppOptionmenu * aom,APP_WIDGET column,OptionmenuCallback callBack,void * target)156 void appMakeOptionmenuInColumn( AppOptionmenu * aom,
157 APP_WIDGET column,
158 OptionmenuCallback callBack,
159 void * target )
160 {
161 Widget pulldown;
162 Widget inplace;
163
164 Arg al[20];
165 int ac= 0;
166
167 appInitOptionmenu( aom );
168
169 ac= 0;
170 /*
171 No! is counter productive..
172 XtSetArg( al[ac], XmNresizeWidth, False ); ac++;
173 */
174 XtSetArg( al[ac], XmNskipAdjust, True ); ac++;
175 /*
176 Does not make any difference..
177 XtSetArg( al[ac], XmNallowShellResize, False ); ac++;
178 */
179
180 pulldown= XmCreatePulldownMenu( column, WIDGET_NAME, al, ac );
181
182 ac= 0;
183 XtSetArg( al[ac], XmNsubMenuId, pulldown ); ac++;
184
185 XtSetArg( al[ac], XmNmarginHeight, 0 ); ac++;
186 XtSetArg( al[ac], XmNmarginWidth, 0 ); ac++;
187 XtSetArg( al[ac], XmNspacing, 0 ); ac++;
188 XtSetArg( al[ac], XmNentryBorder, 0 ); ac++;
189 XtSetArg( al[ac], XmNskipAdjust, True ); ac++;
190 XtSetArg( al[ac], XmNallowResize, True ); ac++;
191 XtSetArg( al[ac], XmNresizeHeight, True ); ac++;
192
193 inplace= XmCreateOptionMenu( column, WIDGET_NAME, al, ac );
194
195 appFinishOptionmenuMotif( inplace, pulldown );
196
197 XtManageChild( inplace );
198
199 appMotifTurnOfSashTraversal( column );
200
201 aom->aomPulldown= pulldown;
202 aom->aomInplace= inplace;
203 aom->aomCallback= callBack;
204 aom->aomTarget= target;
205 }
206
appMakeOptionmenuInRow(AppOptionmenu * aom,APP_WIDGET row,int column,int colspan,OptionmenuCallback callBack,void * target)207 void appMakeOptionmenuInRow( AppOptionmenu * aom,
208 APP_WIDGET row,
209 int column,
210 int colspan,
211 OptionmenuCallback callBack,
212 void * target )
213 {
214 Widget pulldown;
215 Widget inplace;
216
217 Arg al[20];
218 int ac= 0;
219
220 appInitOptionmenu( aom );
221
222 ac= 0;
223 XtSetArg( al[ac], XmNtopAttachment, XmATTACH_FORM ); ac++;
224 XtSetArg( al[ac], XmNtopOffset, 0 ); ac++;
225
226 XtSetArg( al[ac], XmNleftAttachment, XmATTACH_POSITION ); ac++;
227 XtSetArg( al[ac], XmNleftPosition, column ); ac++;
228
229 XtSetArg( al[ac], XmNrightAttachment, XmATTACH_POSITION ); ac++;
230 XtSetArg( al[ac], XmNrightPosition, column+ colspan ); ac++;
231
232 /*
233 No! is counter productive..
234 XtSetArg( al[ac], XmNresizeWidth, False ); ac++;
235 */
236
237 pulldown= XmCreatePulldownMenu( row, WIDGET_NAME, al, ac );
238
239 ac= 0;
240 XtSetArg( al[ac], XmNtopAttachment, XmATTACH_FORM ); ac++;
241 XtSetArg( al[ac], XmNtopOffset, 0 ); ac++;
242
243 XtSetArg( al[ac], XmNleftAttachment, XmATTACH_POSITION ); ac++;
244 XtSetArg( al[ac], XmNleftPosition, column ); ac++;
245
246 XtSetArg( al[ac], XmNrightAttachment, XmATTACH_POSITION ); ac++;
247 XtSetArg( al[ac], XmNrightPosition, column+ colspan ); ac++;
248
249 XtSetArg( al[ac], XmNsubMenuId, pulldown ); ac++;
250
251 XtSetArg( al[ac], XmNmarginHeight, 0 ); ac++;
252 XtSetArg( al[ac], XmNmarginWidth, 0 ); ac++;
253 XtSetArg( al[ac], XmNspacing, 0 ); ac++;
254 XtSetArg( al[ac], XmNentryBorder, 0 ); ac++;
255
256 inplace= XmCreateOptionMenu( row, WIDGET_NAME, al, ac );
257
258 appFinishOptionmenuMotif( inplace, pulldown );
259
260 XtManageChild( inplace );
261
262 aom->aomPulldown= pulldown;
263 aom->aomInplace= inplace;
264 aom->aomCallback= callBack;
265 aom->aomTarget= target;
266
267 return;
268 }
269
270 /************************************************************************/
271 /* */
272 /* Add an option to a pulldown. */
273 /* */
274 /************************************************************************/
275
appAddItemToOptionmenu(AppOptionmenu * aom,const char * label)276 APP_WIDGET appAddItemToOptionmenu( AppOptionmenu * aom,
277 const char * label )
278 {
279 Widget fresh;
280
281 WidgetList children;
282 Cardinal childCount= 0;
283
284 Arg al[20];
285 int ac= 0;
286
287 XtVaGetValues( aom->aomPulldown,
288 XmNchildren, &children,
289 XmNnumChildren, &childCount,
290 NULL );
291
292 XtSetArg( al[ac], XmNmarginHeight, 1 ); ac++;
293
294 if ( aom->aomOptionsVisible >= childCount )
295 {
296 fresh= XmCreatePushButtonGadget( aom->aomPulldown, (char *)label,
297 al, ac );
298 }
299 else{
300 XmString labelString;
301
302 fresh= children[aom->aomOptionsVisible];
303
304 labelString= XmStringCreateLocalized( (char *)label );
305
306 XtVaSetValues( fresh,
307 XmNlabelString, labelString,
308 NULL );
309
310 XmStringFree( labelString );
311 }
312
313 if ( aom->aomCallback )
314 {
315 XtAddCallback( fresh, XmNactivateCallback,
316 appOptionMenuMotifCallback, (void *)aom );
317 }
318
319 # if RECLAIM_FOCUS
320 XtAddCallback( fresh, XmNactivateCallback,
321 appRefocusOptionmenuMotif, (void *)aom );
322 # endif
323
324 XtManageChild( fresh );
325
326 aom->aomOptionsVisible++;
327
328 return fresh;
329 }
330
appDeleteItemFromOptionmenu(AppOptionmenu * aom,APP_WIDGET option)331 void appDeleteItemFromOptionmenu( AppOptionmenu * aom,
332 APP_WIDGET option )
333 {
334 XtDestroyWidget( option );
335 aom->aomOptionsVisible--;
336 }
337
338 /************************************************************************/
339 /* */
340 /* Select a particular option in an option menu. */
341 /* */
342 /************************************************************************/
343
appSetOptionmenu(AppOptionmenu * aom,int num)344 void appSetOptionmenu( AppOptionmenu * aom,
345 int num )
346 {
347 WidgetList children;
348 Cardinal childCount= 0;
349
350 XtVaGetValues( aom->aomPulldown,
351 XmNchildren, &children,
352 XmNnumChildren, &childCount,
353 NULL );
354
355 if ( num >= 0 && num < (int)childCount )
356 {
357 XtVaSetValues( aom->aomInplace,
358 XmNmenuHistory, children[num],
359 NULL );
360 }
361 else{
362 XtVaSetValues( aom->aomInplace,
363 XmNmenuHistory, (Widget)0,
364 NULL );
365 }
366
367 return;
368 }
369
appEmptyOptionmenu(AppOptionmenu * aom)370 void appEmptyOptionmenu( AppOptionmenu * aom )
371 {
372 WidgetList children;
373 Cardinal childCount;
374 int child;
375
376 XtVaSetValues( aom->aomInplace,
377 XmNmenuHistory, (Widget)0,
378 NULL );
379
380 /* Does not work!
381 appEmptyParentWidget( aom->aomPulldown );
382 */
383
384 XtVaGetValues( aom->aomPulldown,
385 XmNchildren, &children,
386 XmNnumChildren, &childCount,
387 NULL );
388
389 if ( childCount == 0 )
390 { return; }
391
392 if ( aom->aomOptionsVisible > childCount )
393 {
394 LLDEB(aom->aomOptionsVisible,childCount);
395 aom->aomOptionsVisible= childCount;
396 }
397
398 for ( child= 0; child < aom->aomOptionsVisible; child++ )
399 {
400 XtRemoveAllCallbacks( children[child], XmNactivateCallback );
401
402 # if 0
403 Count callbacks to make sure that only one exists:
404
405 XtCallbackList callBacks= (XtCallbackList)0;
406
407 XtVaGetValues( children[child],
408 XmNactivateCallback, &callBacks,
409 NULL );
410 if ( callBacks )
411 {
412 int n= 0;
413
414 while( callBacks[n].callback && callBacks[n].closure )
415 { n++; }
416 LLDEB(child,n);
417 }
418 # endif
419 }
420
421 /* 1 */
422 XtUnmanageChildren( children, childCount );
423 aom->aomOptionsVisible= 0;
424 }
425
appGuiEnableOptionmenu(AppOptionmenu * aom,int sensitive)426 void appGuiEnableOptionmenu( AppOptionmenu * aom,
427 int sensitive )
428 {
429 XtSetSensitive( aom->aomInplace, sensitive != 0 );
430 }
431
appInitOptionmenu(AppOptionmenu * aom)432 void appInitOptionmenu( AppOptionmenu * aom )
433 {
434 aom->aomPulldown= (APP_WIDGET)0;
435 aom->aomInplace= (APP_WIDGET)0;
436
437 aom->aomCallback= (OptionmenuCallback)0;
438 aom->aomTarget= (void *)0;
439
440 aom->aomOptionsVisible= 0;
441 }
442
appOptionmenuItemSetVisibility(APP_WIDGET w,int visible)443 void appOptionmenuItemSetVisibility( APP_WIDGET w,
444 int visible )
445 {
446 visible= ( visible != 0 );
447
448 if ( XtIsManaged( w ) == visible )
449 { return; }
450
451 if ( visible )
452 { XtManageChild( w ); }
453 else{ XtUnmanageChild( w ); }
454
455 return;
456 }
457
458 # endif
459