2 static char Xrcsid
[] = "$XConsortium: Command.c,v 1.70 89/12/12 20:17:23 swick Exp $";
5 /***********************************************************
6 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
7 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
11 Permission to use, copy, modify, and distribute this software and its
12 documentation for any purpose and without fee is hereby granted,
13 provided that the above copyright notice appear in all copies and that
14 both that copyright notice and this permission notice appear in
15 supporting documentation, and that the names of Digital or MIT not be
16 used in advertising or publicity pertaining to distribution of the
17 software without specific, written prior permission.
19 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
20 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
21 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
22 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
23 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
27 ******************************************************************/
31 * Command.c - Command button widget
37 #include <X11/IntrinsicP.h>
38 #include <X11/StringDefs.h>
40 #include <X11/Xmu/Misc.h>
42 #include <./Xaw3_1XawInit.h>
43 #include <./Xaw3_1CommandP.h>
46 #include <X11/Xmu/Converters.h>
49 #define DEFAULT_HIGHLIGHT_THICKNESS 2
52 # define DEFAULT_SHAPE_HIGHLIGHT 32767
55 /****************************************************************
57 * Full class record constant
59 ****************************************************************/
63 static char defaultTranslations
[] =
64 "<EnterWindow>: highlight() \n\
65 <LeaveWindow>: reset() \n\
67 <Btn1Up>: notify() unset() ";
69 #define offset(field) XtOffset(CommandWidget, field)
70 static XtResource resources
[] = {
72 {XtNcallback
, XtCCallback
, XtRCallback
, sizeof(XtPointer
),
73 offset(command
.callbacks
), XtRCallback
, (XtPointer
)NULL
},
74 {XtNhighlightThickness
, XtCThickness
, XtRDimension
, sizeof(Dimension
),
76 offset(command
.highlight_thickness
), XtRImmediate
,
77 (XtPointer
)DEFAULT_HIGHLIGHT_THICKNESS
},
79 offset(command
.highlight_thickness
), XtRImmediate
,
80 (XtPointer
) DEFAULT_SHAPE_HIGHLIGHT
},
82 {XtNshapeStyle
, XtCShapeStyle
, XtRShapeStyle
, sizeof(int),
83 offset(command
.shape_style
), XtRImmediate
, (XtPointer
)XawShapeRectangle
},
84 {XtNcornerRoundPercent
, XtCCornerRoundPercent
,
85 XtRDimension
, sizeof(Dimension
),
86 offset(command
.corner_round
), XtRImmediate
, (XtPointer
) 25},
91 static Boolean
SetValues();
92 static void Initialize(), Redisplay(), Set(), Reset(), Notify(), Unset();
93 static void Highlight(), Unhighlight(), Destroy(), PaintCommandWidget();
94 static void ClassInitialize();
97 static Boolean
ShapeButton();
98 static void Realize(), Resize();
101 static XtActionsRec actionsList
[] =
105 {"highlight", Highlight
},
108 {"unhighlight", Unhighlight
},
112 * This is a temporary exported actions list for the command
113 * widget I have added this code because there is a bug in the MIT
114 * Xtk Intrinsics implementation that does not allow the action table
115 * to be retreived from the widget class, Ralph Swick has promised me that
116 * this will eventually be fixed, but until then this is how the toggle
117 * widget will get the command widget's actions list.
119 * Chris D. Peterson - 12/28/88.
122 XtActionList xaw_command_actions_list
= actionsList
;
124 #define SuperClass ((LabelWidgetClass)&labelClassRec)
126 CommandClassRec commandClassRec
= {
128 (WidgetClass
) SuperClass
, /* superclass */
129 "Command", /* class_name */
130 sizeof(CommandRec
), /* size */
131 ClassInitialize
, /* class_initialize */
132 NULL
, /* class_part_initialize */
133 FALSE
, /* class_inited */
134 Initialize
, /* initialize */
135 NULL
, /* initialize_hook */
137 Realize
, /* realize */
139 XtInheritRealize
, /* realize */
141 actionsList
, /* actions */
142 XtNumber(actionsList
), /* num_actions */
143 resources
, /* resources */
144 XtNumber(resources
), /* resource_count */
145 NULLQUARK
, /* xrm_class */
146 FALSE
, /* compress_motion */
147 TRUE
, /* compress_exposure */
148 TRUE
, /* compress_enterleave */
149 FALSE
, /* visible_interest */
150 Destroy
, /* destroy */
154 XtInheritResize
, /* resize */
156 Redisplay
, /* expose */
157 SetValues
, /* set_values */
158 NULL
, /* set_values_hook */
159 XtInheritSetValuesAlmost
, /* set_values_almost */
160 NULL
, /* get_values_hook */
161 NULL
, /* accept_focus */
162 XtVersion
, /* version */
163 NULL
, /* callback_private */
164 defaultTranslations
, /* tm_table */
165 XtInheritQueryGeometry
, /* query_geometry */
166 XtInheritDisplayAccelerator
, /* display_accelerator */
168 }, /* CoreClass fields initialization */
170 XtInheritChangeSensitive
/* change_sensitive */
171 }, /* SimpleClass fields initialization */
173 0, /* field not used */
174 }, /* LabelClass fields initialization */
176 0, /* field not used */
177 }, /* CommandClass fields initialization */
180 /* for public consumption */
181 WidgetClass commandWidgetClass
= (WidgetClass
) &commandClassRec
;
183 /****************************************************************
187 ****************************************************************/
196 values
.foreground
= fg
;
197 values
.background
= bg
;
198 values
.font
= cbw
->label
.font
->fid
;
199 values
.cap_style
= CapProjecting
;
201 if (cbw
->command
.highlight_thickness
> 1 )
202 values
.line_width
= cbw
->command
.highlight_thickness
;
204 values
.line_width
= 0;
206 return XtGetGC((Widget
)cbw
,
207 (GCForeground
|GCBackground
|GCFont
|GCLineWidth
|GCCapStyle
),
214 Initialize(request
, new, args
, num_args
)
216 ArgList args
; /* unused */
217 Cardinal
*num_args
; /* unused */
219 CommandWidget cbw
= (CommandWidget
) new;
221 int shape_event_base
, shape_error_base
;
223 if (cbw
->command
.shape_style
!= XawShapeRectangle
224 && !XShapeQueryExtension(XtDisplay(new), &shape_event_base
,
226 cbw
->command
.shape_style
= XawShapeRectangle
;
227 if (cbw
->command
.highlight_thickness
== DEFAULT_SHAPE_HIGHLIGHT
) {
228 if (cbw
->command
.shape_style
!= XawShapeRectangle
)
229 cbw
->command
.highlight_thickness
= 0;
231 cbw
->command
.highlight_thickness
= DEFAULT_HIGHLIGHT_THICKNESS
;
235 cbw
->command
.normal_GC
= Get_GC(cbw
, cbw
->label
.foreground
,
236 cbw
->core
.background_pixel
);
237 cbw
->command
.inverse_GC
= Get_GC(cbw
, cbw
->core
.background_pixel
,
238 cbw
->label
.foreground
);
239 XtReleaseGC(new, cbw
->label
.normal_GC
);
240 cbw
->label
.normal_GC
= cbw
->command
.normal_GC
;
242 cbw
->command
.set
= FALSE
;
243 cbw
->command
.highlighted
= HighlightNone
;
250 static Region outerRegion
= NULL
, innerRegion
, emptyRegion
;
253 if (cbw
->command
.highlight_thickness
== 0 ||
254 cbw
->command
.highlight_thickness
> Min(cbw
->core
.width
,
258 if (outerRegion
== NULL
) {
259 /* save time by allocating scratch regions only once. */
260 outerRegion
= XCreateRegion();
261 innerRegion
= XCreateRegion();
262 emptyRegion
= XCreateRegion();
266 rect
.width
= cbw
->core
.width
;
267 rect
.height
= cbw
->core
.height
;
268 XUnionRectWithRegion( &rect
, emptyRegion
, outerRegion
);
269 rect
.x
= rect
.y
= cbw
->command
.highlight_thickness
;
270 rect
.width
-= cbw
->command
.highlight_thickness
* 2;
271 rect
.height
-= cbw
->command
.highlight_thickness
* 2;
272 XUnionRectWithRegion( &rect
, emptyRegion
, innerRegion
);
273 XSubtractRegion( outerRegion
, innerRegion
, outerRegion
);
277 /***************************
281 ***************************/
285 Set(w
,event
,params
,num_params
)
288 String
*params
; /* unused */
289 Cardinal
*num_params
; /* unused */
291 CommandWidget cbw
= (CommandWidget
)w
;
293 if (cbw
->command
.set
)
296 cbw
->command
.set
= TRUE
;
298 PaintCommandWidget(w
, (Region
) NULL
, TRUE
);
303 Unset(w
,event
,params
,num_params
)
306 String
*params
; /* unused */
307 Cardinal
*num_params
;
309 CommandWidget cbw
= (CommandWidget
)w
;
311 if (!cbw
->command
.set
)
314 cbw
->command
.set
= FALSE
;
315 if (XtIsRealized(w
)) {
316 XClearWindow(XtDisplay(w
), XtWindow(w
));
317 PaintCommandWidget(w
, (Region
) NULL
, TRUE
);
323 Reset(w
,event
,params
,num_params
)
326 String
*params
; /* unused */
327 Cardinal
*num_params
; /* unused */
329 CommandWidget cbw
= (CommandWidget
)w
;
331 if (cbw
->command
.set
) {
332 cbw
->command
.highlighted
= HighlightNone
;
333 Unset(w
, event
, params
, num_params
);
336 Unhighlight(w
, event
, params
, num_params
);
341 Highlight(w
,event
,params
,num_params
)
345 Cardinal
*num_params
;
347 CommandWidget cbw
= (CommandWidget
)w
;
349 if ( *num_params
== (Cardinal
) 0)
350 cbw
->command
.highlighted
= HighlightWhenUnset
;
352 if ( *num_params
!= (Cardinal
) 1)
353 XtWarning("Too many parameters passed to highlight action table.");
354 switch (params
[0][0]) {
357 cbw
->command
.highlighted
= HighlightAlways
;
360 cbw
->command
.highlighted
= HighlightWhenUnset
;
366 PaintCommandWidget(w
, HighlightRegion(cbw
), TRUE
);
371 Unhighlight(w
,event
,params
,num_params
)
374 String
*params
; /* unused */
375 Cardinal
*num_params
; /* unused */
377 CommandWidget cbw
= (CommandWidget
)w
;
379 cbw
->command
.highlighted
= HighlightNone
;
381 PaintCommandWidget(w
, HighlightRegion(cbw
), TRUE
);
386 Notify(w
,event
,params
,num_params
)
389 String
*params
; /* unused */
390 Cardinal
*num_params
; /* unused */
392 CommandWidget cbw
= (CommandWidget
)w
;
394 /* check to be sure state is still Set so that user can cancel
395 the action (e.g. by moving outside the window, in the default
398 if (cbw
->command
.set
)
399 XtCallCallbackList(w
, cbw
->command
.callbacks
, NULL
);
403 * Repaint the widget window
406 /************************
410 ************************/
414 Redisplay(w
, event
, region
)
419 PaintCommandWidget(w
, region
, FALSE
);
422 /* Function Name: PaintCommandWidget
423 * Description: Paints the command widget.
424 * Arguments: w - the command widget.
425 * region - region to paint (passed to the superclass).
426 * change - did it change either set or highlight state?
431 PaintCommandWidget(w
, region
, change
)
436 CommandWidget cbw
= (CommandWidget
) w
;
440 very_thick
= cbw
->command
.highlight_thickness
> Min(cbw
->core
.width
,
443 if (cbw
->command
.set
) {
444 cbw
->label
.normal_GC
= cbw
->command
.inverse_GC
;
445 XFillRectangle(XtDisplay(w
), XtWindow(w
), cbw
->command
.normal_GC
,
446 0, 0, cbw
->core
.width
, cbw
->core
.height
);
447 region
= NULL
; /* Force label to repaint text. */
450 cbw
->label
.normal_GC
= cbw
->command
.normal_GC
;
452 if (cbw
->command
.highlight_thickness
<= 0)
454 (*SuperClass
->core_class
.expose
) (w
, (XEvent
*) NULL
, region
);
459 * If we are set then use the same colors as if we are not highlighted.
462 if (cbw
->command
.set
== (cbw
->command
.highlighted
== HighlightNone
)) {
463 norm_gc
= cbw
->command
.inverse_GC
;
464 rev_gc
= cbw
->command
.normal_GC
;
467 norm_gc
= cbw
->command
.normal_GC
;
468 rev_gc
= cbw
->command
.inverse_GC
;
471 if ( !( (!change
&& (cbw
->command
.highlighted
== HighlightNone
)) ||
472 ((cbw
->command
.highlighted
== HighlightWhenUnset
) &&
473 (cbw
->command
.set
))) ) {
475 cbw
->label
.normal_GC
= norm_gc
; /* Give the label the right GC. */
476 XFillRectangle(XtDisplay(w
),XtWindow(w
), rev_gc
,
477 0, 0, cbw
->core
.width
, cbw
->core
.height
);
480 /* wide lines are centered on the path, so indent it */
481 int offset
= cbw
->command
.highlight_thickness
/2;
482 XDrawRectangle(XtDisplay(w
),XtWindow(w
), rev_gc
, offset
, offset
,
483 cbw
->core
.width
- cbw
->command
.highlight_thickness
,
484 cbw
->core
.height
- cbw
->command
.highlight_thickness
);
487 (*SuperClass
->core_class
.expose
) (w
, (XEvent
*) NULL
, region
);
494 CommandWidget cbw
= (CommandWidget
) w
;
496 /* so Label can release it */
497 if (cbw
->label
.normal_GC
== cbw
->command
.normal_GC
)
498 XtReleaseGC( w
, cbw
->command
.inverse_GC
);
500 XtReleaseGC( w
, cbw
->command
.normal_GC
);
504 * Set specified arguments into widget
509 SetValues (current
, request
, new)
510 Widget current
, request
, new;
512 CommandWidget oldcbw
= (CommandWidget
) current
;
513 CommandWidget cbw
= (CommandWidget
) new;
514 Boolean redisplay
= False
;
516 if ( oldcbw
->core
.sensitive
!= cbw
->core
.sensitive
&& !cbw
->core
.sensitive
) {
517 /* about to become insensitive */
518 cbw
->command
.set
= FALSE
;
519 cbw
->command
.highlighted
= HighlightNone
;
523 if ( (oldcbw
->label
.foreground
!= cbw
->label
.foreground
) ||
524 (oldcbw
->core
.background_pixel
!= cbw
->core
.background_pixel
) ||
525 (oldcbw
->command
.highlight_thickness
!=
526 cbw
->command
.highlight_thickness
) ||
527 (oldcbw
->label
.font
!= cbw
->label
.font
) )
529 if (oldcbw
->label
.normal_GC
== oldcbw
->command
.normal_GC
)
530 /* Label has release one of these */
531 XtReleaseGC(new, cbw
->command
.inverse_GC
);
533 XtReleaseGC(new, cbw
->command
.normal_GC
);
535 cbw
->command
.normal_GC
= Get_GC(cbw
, cbw
->label
.foreground
,
536 cbw
->core
.background_pixel
);
537 cbw
->command
.inverse_GC
= Get_GC(cbw
, cbw
->core
.background_pixel
,
538 cbw
->label
.foreground
);
539 XtReleaseGC(new, cbw
->label
.normal_GC
);
540 cbw
->label
.normal_GC
= (cbw
->command
.set
541 ? cbw
->command
.inverse_GC
542 : cbw
->command
.normal_GC
);
548 if ( XtIsRealized(new)
549 && oldcbw
->command
.shape_style
!= cbw
->command
.shape_style
550 && !ShapeButton(cbw
))
552 cbw
->command
.shape_style
= oldcbw
->command
.shape_style
;
559 static void ClassInitialize()
561 XawInitializeWidgetSet();
563 XtSetTypeConverter( XtRString
, XtRShapeStyle
, XmuCvtStringToShapeStyle
,
564 NULL
, 0, XtCacheNone
, NULL
);
576 Dimension corner_size
;
578 if ( (cbw
->command
.shape_style
== XawShapeRoundedRectangle
) ) {
579 corner_size
= (cbw
->core
.width
< cbw
->core
.height
) ? cbw
->core
.width
581 corner_size
= (corner_size
* cbw
->command
.corner_round
) / 100;
584 if (cbw
->command
.shape_style
!= XawShapeRectangle
) {
585 if (!XmuReshapeWidget((Widget
) cbw
, cbw
->command
.shape_style
,
586 corner_size
, corner_size
)) {
587 cbw
->command
.shape_style
= XawShapeRectangle
;
594 static void Realize(w
, valueMask
, attributes
)
597 XSetWindowAttributes
*attributes
;
599 (*commandWidgetClass
->core_class
.superclass
->core_class
.realize
)
600 (w
, valueMask
, attributes
);
602 ShapeButton( (CommandWidget
) w
);
605 static void Resize(w
)
609 ShapeButton( (CommandWidget
) w
);
611 (*commandWidgetClass
->core_class
.superclass
->core_class
.resize
)(w
);