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