00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #include <stdio.h>
00056 #include <X11/IntrinsicP.h>
00057 #include <X11/StringDefs.h>
00058 #include <X11/Xmu/Misc.h>
00059 #include <X11/Xaw3d/XawInit.h>
00060 #include <X11/Xaw3d/CommandP.h>
00061 #include <X11/Xmu/Converters.h>
00062 #include <X11/extensions/shape.h>
00063
00064 #define DEFAULT_HIGHLIGHT_THICKNESS 2
00065 #define DEFAULT_SHAPE_HIGHLIGHT 32767
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 static char defaultTranslations[] =
00076 "<EnterWindow>: highlight() \n\
00077 <LeaveWindow>: reset() \n\
00078 <Btn1Down>: set() \n\
00079 <Btn1Up>: notify() unset() ";
00080
00081 #define offset(field) XtOffsetOf(CommandRec, field)
00082 static XtResource resources[] = {
00083 {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer),
00084 offset(command.callbacks), XtRCallback, (XtPointer)NULL},
00085 {XtNhighlightThickness, XtCThickness, XtRDimension, sizeof(Dimension),
00086 offset(command.highlight_thickness), XtRImmediate,
00087 (XtPointer) DEFAULT_SHAPE_HIGHLIGHT},
00088 {XtNshapeStyle, XtCShapeStyle, XtRShapeStyle, sizeof(int),
00089 offset(command.shape_style), XtRImmediate, (XtPointer)XawShapeRectangle},
00090 {XtNcornerRoundPercent, XtCCornerRoundPercent,
00091 XtRDimension, sizeof(Dimension),
00092 offset(command.corner_round), XtRImmediate, (XtPointer) 25},
00093 {XtNshadowWidth, XtCShadowWidth, XtRDimension, sizeof(Dimension),
00094 offset(threeD.shadow_width), XtRImmediate, (XtPointer) 2},
00095 {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
00096 XtOffsetOf(RectObjRec,rectangle.border_width), XtRImmediate,
00097 (XtPointer)0}
00098 };
00099 #undef offset
00100
00101 static Boolean SetValues();
00102 static void Initialize(), Redisplay(), Set(), Reset(), Notify(), Unset();
00103 static void Highlight(), Unhighlight(), Destroy(), PaintCommandWidget();
00104 static void ClassInitialize();
00105 static Boolean ShapeButton();
00106 static void Realize(), Resize();
00107
00108 static XtActionsRec actionsList[] = {
00109 {"set", Set},
00110 {"notify", Notify},
00111 {"highlight", Highlight},
00112 {"reset", Reset},
00113 {"unset", Unset},
00114 {"unhighlight", Unhighlight}
00115 };
00116
00117 #define SuperClass ((LabelWidgetClass)&labelClassRec)
00118
00119 CommandClassRec commandClassRec = {
00120 {
00121 (WidgetClass) SuperClass,
00122 "Command",
00123 sizeof(CommandRec),
00124 ClassInitialize,
00125 NULL,
00126 FALSE,
00127 Initialize,
00128 NULL,
00129 Realize,
00130 actionsList,
00131 XtNumber(actionsList),
00132 resources,
00133 XtNumber(resources),
00134 NULLQUARK,
00135 FALSE,
00136 TRUE,
00137 TRUE,
00138 FALSE,
00139 Destroy,
00140 Resize,
00141 Redisplay,
00142 SetValues,
00143 NULL,
00144 XtInheritSetValuesAlmost,
00145 NULL,
00146 NULL,
00147 XtVersion,
00148 NULL,
00149 defaultTranslations,
00150 XtInheritQueryGeometry,
00151 XtInheritDisplayAccelerator,
00152 NULL
00153 },
00154 {
00155 XtInheritChangeSensitive
00156 },
00157 {
00158 XtInheritXaw3dShadowDraw,
00159 },
00160 {
00161 0,
00162 },
00163 {
00164 0,
00165 },
00166 };
00167
00168
00169 WidgetClass commandWidgetClass = (WidgetClass) &commandClassRec;
00170
00171
00172
00173
00174
00175
00176
00177 static GC
00178 Get_GC(cbw, fg, bg)
00179 CommandWidget cbw;
00180 Pixel fg, bg;
00181 {
00182 XGCValues values;
00183
00184 values.foreground = fg;
00185 values.background = bg;
00186 values.font = cbw->label.font->fid;
00187 values.cap_style = CapProjecting;
00188
00189 if (cbw->command.highlight_thickness > 1 )
00190 values.line_width = cbw->command.highlight_thickness;
00191 else
00192 values.line_width = 0;
00193
00194 if ( cbw->simple.international == True )
00195 return XtAllocateGC((Widget)cbw, 0,
00196 (GCForeground|GCBackground|GCLineWidth|GCCapStyle),
00197 &values, GCFont, 0 );
00198 else
00199 return XtGetGC((Widget)cbw,
00200 (GCForeground|GCBackground|GCFont|GCLineWidth|GCCapStyle),
00201 &values);
00202 }
00203
00204
00205
00206 static void
00207 Initialize(request, new, args, num_args)
00208 Widget request, new;
00209 ArgList args;
00210 Cardinal *num_args;
00211 {
00212 CommandWidget cbw = (CommandWidget) new;
00213 int shape_event_base, shape_error_base;
00214
00215 if (cbw->command.shape_style != XawShapeRectangle
00216 && !XShapeQueryExtension(XtDisplay(new), &shape_event_base,
00217 &shape_error_base))
00218 cbw->command.shape_style = XawShapeRectangle;
00219 if (cbw->command.highlight_thickness == DEFAULT_SHAPE_HIGHLIGHT) {
00220 if (cbw->command.shape_style != XawShapeRectangle)
00221 cbw->command.highlight_thickness = 0;
00222 else
00223 cbw->command.highlight_thickness = DEFAULT_HIGHLIGHT_THICKNESS;
00224 }
00225 if (cbw->command.shape_style != XawShapeRectangle) {
00226 cbw->threeD.shadow_width = 0;
00227 cbw->core.border_width = 1;
00228 }
00229
00230 cbw->command.normal_GC = Get_GC(cbw, cbw->label.foreground,
00231 cbw->core.background_pixel);
00232 cbw->command.inverse_GC = Get_GC(cbw, cbw->core.background_pixel,
00233 cbw->label.foreground);
00234 XtReleaseGC(new, cbw->label.normal_GC);
00235 cbw->label.normal_GC = cbw->command.normal_GC;
00236
00237 cbw->command.set = FALSE;
00238 cbw->command.highlighted = HighlightNone;
00239 }
00240
00241 static Region
00242 HighlightRegion(cbw)
00243 CommandWidget cbw;
00244 {
00245 static Region outerRegion = NULL, innerRegion, emptyRegion;
00246 Dimension s = cbw->threeD.shadow_width;
00247 XRectangle rect;
00248
00249 if (cbw->command.highlight_thickness == 0 ||
00250 cbw->command.highlight_thickness >
00251 (Dimension) ((Dimension) Min(cbw->core.width, cbw->core.height)/2))
00252 return(NULL);
00253
00254 if (outerRegion == NULL) {
00255
00256 outerRegion = XCreateRegion();
00257 innerRegion = XCreateRegion();
00258 emptyRegion = XCreateRegion();
00259 }
00260
00261 rect.x = rect.y = s;
00262 rect.width = cbw->core.width - 2 * s;
00263 rect.height = cbw->core.height - 2 * s;
00264 XUnionRectWithRegion( &rect, emptyRegion, outerRegion );
00265 rect.x = rect.y += cbw->command.highlight_thickness;
00266 rect.width -= cbw->command.highlight_thickness * 2;
00267 rect.height -= cbw->command.highlight_thickness * 2;
00268 XUnionRectWithRegion( &rect, emptyRegion, innerRegion );
00269 XSubtractRegion( outerRegion, innerRegion, outerRegion );
00270 return outerRegion;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280 static void
00281 Set(w,event,params,num_params)
00282 Widget w;
00283 XEvent *event;
00284 String *params;
00285 Cardinal *num_params;
00286 {
00287 CommandWidget cbw = (CommandWidget)w;
00288
00289 if (cbw->command.set)
00290 return;
00291
00292 cbw->command.set= TRUE;
00293 if (XtIsRealized(w))
00294 PaintCommandWidget(w, event, (Region) NULL, TRUE);
00295 }
00296
00297
00298 static void
00299 Unset(w,event,params,num_params)
00300 Widget w;
00301 XEvent *event;
00302 String *params;
00303 Cardinal *num_params;
00304 {
00305 CommandWidget cbw = (CommandWidget)w;
00306
00307 if (!cbw->command.set)
00308 return;
00309
00310 cbw->command.set = FALSE;
00311 if (XtIsRealized(w)) {
00312 XClearWindow(XtDisplay(w), XtWindow(w));
00313 PaintCommandWidget(w, event, (Region) NULL, TRUE);
00314 }
00315 }
00316
00317
00318 static void
00319 Reset(w,event,params,num_params)
00320 Widget w;
00321 XEvent *event;
00322 String *params;
00323 Cardinal *num_params;
00324 {
00325 CommandWidget cbw = (CommandWidget)w;
00326
00327 if (cbw->command.set) {
00328 cbw->command.highlighted = HighlightNone;
00329 Unset(w, event, params, num_params);
00330 } else
00331 Unhighlight(w, event, params, num_params);
00332 }
00333
00334
00335 static void
00336 Highlight(w,event,params,num_params)
00337 Widget w;
00338 XEvent *event;
00339 String *params;
00340 Cardinal *num_params;
00341 {
00342 CommandWidget cbw = (CommandWidget)w;
00343
00344 if ( *num_params == (Cardinal) 0)
00345 cbw->command.highlighted = HighlightWhenUnset;
00346 else {
00347 if ( *num_params != (Cardinal) 1)
00348 XtWarning("Too many parameters passed to highlight action table.");
00349 switch (params[0][0]) {
00350 case 'A':
00351 case 'a':
00352 cbw->command.highlighted = HighlightAlways;
00353 break;
00354 default:
00355 cbw->command.highlighted = HighlightWhenUnset;
00356 break;
00357 }
00358 }
00359
00360 if (XtIsRealized(w))
00361 PaintCommandWidget(w, event, HighlightRegion(cbw), TRUE);
00362 }
00363
00364
00365 static void
00366 Unhighlight(w,event,params,num_params)
00367 Widget w;
00368 XEvent *event;
00369 String *params;
00370 Cardinal *num_params;
00371 {
00372 CommandWidget cbw = (CommandWidget)w;
00373
00374 cbw->command.highlighted = HighlightNone;
00375 if (XtIsRealized(w))
00376 PaintCommandWidget(w, event, HighlightRegion(cbw), TRUE);
00377 }
00378
00379
00380 static void
00381 Notify(w,event,params,num_params)
00382 Widget w;
00383 XEvent *event;
00384 String *params;
00385 Cardinal *num_params;
00386 {
00387 CommandWidget cbw = (CommandWidget)w;
00388
00389
00390
00391
00392
00393 if (cbw->command.set)
00394 XtCallCallbackList(w, cbw->command.callbacks, (XtPointer) NULL);
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 static void
00409 Redisplay(w, event, region)
00410 Widget w;
00411 XEvent *event;
00412 Region region;
00413 {
00414 PaintCommandWidget(w, event, region, FALSE);
00415 }
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 static void
00426 PaintCommandWidget(w, event, region, change)
00427 Widget w;
00428 XEvent *event;
00429 Region region;
00430 Boolean change;
00431 {
00432 CommandWidget cbw = (CommandWidget) w;
00433 CommandWidgetClass cwclass = (CommandWidgetClass) XtClass (w);
00434 Boolean very_thick;
00435 GC norm_gc, rev_gc;
00436 Dimension s = cbw->threeD.shadow_width;
00437
00438 very_thick = cbw->command.highlight_thickness >
00439 (Dimension)((Dimension) Min(cbw->core.width, cbw->core.height)/2);
00440
00441 if (cbw->command.set) {
00442 cbw->label.normal_GC = cbw->command.inverse_GC;
00443 XFillRectangle(XtDisplay(w), XtWindow(w), cbw->command.normal_GC,
00444 s, s, cbw->core.width - 2 * s, cbw->core.height - 2 * s);
00445 region = NULL;
00446 }
00447 else
00448 cbw->label.normal_GC = cbw->command.normal_GC;
00449
00450 if (cbw->command.highlight_thickness <= 0)
00451 {
00452 (*SuperClass->core_class.expose) (w, event, region);
00453 (*cwclass->threeD_class.shadowdraw) (w, event, region, !cbw->command.set);
00454 return;
00455 }
00456
00457
00458
00459
00460
00461 if (cbw->command.set == (cbw->command.highlighted == HighlightNone)) {
00462 norm_gc = cbw->command.inverse_GC;
00463 rev_gc = cbw->command.normal_GC;
00464 }
00465 else {
00466 norm_gc = cbw->command.normal_GC;
00467 rev_gc = cbw->command.inverse_GC;
00468 }
00469
00470 if ( !( (!change && (cbw->command.highlighted == HighlightNone)) ||
00471 ((cbw->command.highlighted == HighlightWhenUnset) &&
00472 (cbw->command.set))) ) {
00473 if (very_thick) {
00474 cbw->label.normal_GC = norm_gc;
00475 XFillRectangle(XtDisplay(w),XtWindow(w), rev_gc,
00476 s, s, cbw->core.width - 2 * s, cbw->core.height - 2 * s);
00477 }
00478 else {
00479
00480 int offset = cbw->command.highlight_thickness/2;
00481 XDrawRectangle(XtDisplay(w),XtWindow(w), rev_gc, s + offset, s + offset,
00482 cbw->core.width - cbw->command.highlight_thickness - 2 * s,
00483 cbw->core.height - cbw->command.highlight_thickness - 2 * s);
00484 }
00485 }
00486 (*SuperClass->core_class.expose) (w, event, region);
00487 (*cwclass->threeD_class.shadowdraw) (w, event, region, !cbw->command.set);
00488 }
00489
00490 static void
00491 Destroy(w)
00492 Widget w;
00493 {
00494 CommandWidget cbw = (CommandWidget) w;
00495
00496
00497 if (cbw->label.normal_GC == cbw->command.normal_GC)
00498 XtReleaseGC( w, cbw->command.inverse_GC );
00499 else
00500 XtReleaseGC( w, cbw->command.normal_GC );
00501 }
00502
00503
00504
00505
00506
00507
00508 static Boolean
00509 SetValues (current, request, new, args, num_args)
00510 Widget current, request, new;
00511 ArgList args;
00512 Cardinal *num_args;
00513 {
00514 CommandWidget oldcbw = (CommandWidget) current;
00515 CommandWidget cbw = (CommandWidget) new;
00516 Boolean redisplay = False;
00517
00518 if ( oldcbw->core.sensitive != cbw->core.sensitive && !cbw->core.sensitive) {
00519
00520 cbw->command.set = FALSE;
00521 cbw->command.highlighted = HighlightNone;
00522 redisplay = TRUE;
00523 }
00524
00525 if ( (oldcbw->label.foreground != cbw->label.foreground) ||
00526 (oldcbw->core.background_pixel != cbw->core.background_pixel) ||
00527 (oldcbw->command.highlight_thickness !=
00528 cbw->command.highlight_thickness) ||
00529 (oldcbw->label.font != cbw->label.font) )
00530 {
00531 if (oldcbw->label.normal_GC == oldcbw->command.normal_GC)
00532
00533 XtReleaseGC(new, cbw->command.inverse_GC);
00534 else
00535 XtReleaseGC(new, cbw->command.normal_GC);
00536
00537 cbw->command.normal_GC = Get_GC(cbw, cbw->label.foreground,
00538 cbw->core.background_pixel);
00539 cbw->command.inverse_GC = Get_GC(cbw, cbw->core.background_pixel,
00540 cbw->label.foreground);
00541 XtReleaseGC(new, cbw->label.normal_GC);
00542 cbw->label.normal_GC = (cbw->command.set
00543 ? cbw->command.inverse_GC
00544 : cbw->command.normal_GC);
00545
00546 redisplay = True;
00547 }
00548
00549 if ( XtIsRealized(new)
00550 && oldcbw->command.shape_style != cbw->command.shape_style
00551 && !ShapeButton(cbw, TRUE))
00552 {
00553 cbw->command.shape_style = oldcbw->command.shape_style;
00554 }
00555
00556 return (redisplay);
00557 }
00558
00559 static void ClassInitialize()
00560 {
00561 XawInitializeWidgetSet();
00562 XtSetTypeConverter( XtRString, XtRShapeStyle, XmuCvtStringToShapeStyle,
00563 (XtConvertArgList)NULL, 0, XtCacheNone, (XtDestructor)NULL );
00564 }
00565
00566
00567 static Boolean
00568 ShapeButton(cbw, checkRectangular)
00569 CommandWidget cbw;
00570 Boolean checkRectangular;
00571 {
00572 Dimension corner_size = 0;
00573
00574 if ( (cbw->command.shape_style == XawShapeRoundedRectangle) ) {
00575 corner_size = (cbw->core.width < cbw->core.height) ? cbw->core.width
00576 : cbw->core.height;
00577 corner_size = (int) (corner_size * cbw->command.corner_round) / 100;
00578 }
00579
00580 if (checkRectangular || cbw->command.shape_style != XawShapeRectangle) {
00581 if (!XmuReshapeWidget((Widget) cbw, cbw->command.shape_style,
00582 corner_size, corner_size)) {
00583 cbw->command.shape_style = XawShapeRectangle;
00584 return(False);
00585 }
00586 }
00587 return(TRUE);
00588 }
00589
00590 static void Realize(w, valueMask, attributes)
00591 Widget w;
00592 Mask *valueMask;
00593 XSetWindowAttributes *attributes;
00594 {
00595 (*commandWidgetClass->core_class.superclass->core_class.realize)
00596 (w, valueMask, attributes);
00597
00598 ShapeButton( (CommandWidget) w, FALSE);
00599 }
00600
00601 static void Resize(w)
00602 Widget w;
00603 {
00604 if (XtIsRealized(w))
00605 ShapeButton( (CommandWidget) w, FALSE);
00606
00607 (*commandWidgetClass->core_class.superclass->core_class.resize)(w);
00608 }