Command.c

Go to the documentation of this file.
00001 /* $XConsortium: Command.c,v 1.79 94/04/17 20:11:58 kaleb Exp $ */
00002 
00003 /***********************************************************
00004 
00005 Copyright (c) 1987, 1988, 1994  X Consortium
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a copy
00008 of this software and associated documentation files (the "Software"), to deal
00009 in the Software without restriction, including without limitation the rights
00010 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00011 copies of the Software, and to permit persons to whom the Software is
00012 furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00020 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023 
00024 Except as contained in this notice, the name of the X Consortium shall not be
00025 used in advertising or otherwise to promote the sale, use or other dealings
00026 in this Software without prior written authorization from the X Consortium.
00027 
00028 
00029 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
00030 
00031                         All Rights Reserved
00032 
00033 Permission to use, copy, modify, and distribute this software and its 
00034 documentation for any purpose and without fee is hereby granted, 
00035 provided that the above copyright notice appear in all copies and that
00036 both that copyright notice and this permission notice appear in 
00037 supporting documentation, and that the name of Digital not be
00038 used in advertising or publicity pertaining to distribution of the
00039 software without specific, written prior permission.  
00040 
00041 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
00042 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
00043 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
00044 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
00045 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
00046 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00047 SOFTWARE.
00048 
00049 ******************************************************************/
00050 
00051 /*
00052  * Command.c - Command button widget
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  * Full class record constant
00070  *
00071  ****************************************************************/
00072 
00073 /* Private Data */
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,           /* superclass             */    
00122     "Command",                          /* class_name             */
00123     sizeof(CommandRec),                 /* size                   */
00124     ClassInitialize,                    /* class_initialize       */
00125     NULL,                               /* class_part_initialize  */
00126     FALSE,                              /* class_inited           */
00127     Initialize,                         /* initialize             */
00128     NULL,                               /* initialize_hook        */
00129     Realize,                            /* realize                */
00130     actionsList,                        /* actions                */
00131     XtNumber(actionsList),              /* num_actions            */
00132     resources,                          /* resources              */
00133     XtNumber(resources),                /* resource_count         */
00134     NULLQUARK,                          /* xrm_class              */
00135     FALSE,                              /* compress_motion        */
00136     TRUE,                               /* compress_exposure      */
00137     TRUE,                               /* compress_enterleave    */
00138     FALSE,                              /* visible_interest       */
00139     Destroy,                            /* destroy                */
00140     Resize,                             /* resize                 */
00141     Redisplay,                          /* expose                 */
00142     SetValues,                          /* set_values             */
00143     NULL,                               /* set_values_hook        */
00144     XtInheritSetValuesAlmost,           /* set_values_almost      */
00145     NULL,                               /* get_values_hook        */
00146     NULL,                               /* accept_focus           */
00147     XtVersion,                          /* version                */
00148     NULL,                               /* callback_private       */
00149     defaultTranslations,                /* tm_table               */
00150     XtInheritQueryGeometry,             /* query_geometry         */
00151     XtInheritDisplayAccelerator,        /* display_accelerator    */
00152     NULL                                /* extension              */
00153   },  /* CoreClass fields initialization */
00154   {
00155     XtInheritChangeSensitive            /* change_sensitive     */
00156   },  /* SimpleClass fields initialization */
00157   {
00158     XtInheritXaw3dShadowDraw,           /* shadowdraw           */
00159   },  /* ThreeD Class fields initialization */
00160   {
00161     0,                                     /* field not used    */
00162   },  /* LabelClass fields initialization */
00163   {
00164     0,                                     /* field not used    */
00165   },  /* CommandClass fields initialization */
00166 };
00167 
00168   /* for public consumption */
00169 WidgetClass commandWidgetClass = (WidgetClass) &commandClassRec;
00170 
00171 /****************************************************************
00172  *
00173  * Private Procedures
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 /* ARGSUSED */
00206 static void 
00207 Initialize(request, new, args, num_args)
00208 Widget request, new;
00209 ArgList args;                   /* unused */
00210 Cardinal *num_args;             /* unused */
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     /* save time by allocating scratch regions only once. */
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 *  Action Procedures
00276 *
00277 ***************************/
00278 
00279 /* ARGSUSED */
00280 static void 
00281 Set(w,event,params,num_params)
00282 Widget w;
00283 XEvent *event;
00284 String *params;         /* unused */
00285 Cardinal *num_params;   /* unused */
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 /* ARGSUSED */
00298 static void
00299 Unset(w,event,params,num_params)
00300 Widget w;
00301 XEvent *event;
00302 String *params;         /* unused */
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 /* ARGSUSED */
00318 static void 
00319 Reset(w,event,params,num_params)
00320 Widget w;
00321 XEvent *event;
00322 String *params;         /* unused */
00323 Cardinal *num_params;   /* unused */
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 /* ARGSUSED */
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 /* ARGSUSED */
00365 static void 
00366 Unhighlight(w,event,params,num_params)
00367 Widget w;
00368 XEvent *event;
00369 String *params;         /* unused */
00370 Cardinal *num_params;   /* unused */
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 /* ARGSUSED */
00380 static void 
00381 Notify(w,event,params,num_params)
00382 Widget w;
00383 XEvent *event;
00384 String *params;         /* unused */
00385 Cardinal *num_params;   /* unused */
00386 {
00387   CommandWidget cbw = (CommandWidget)w; 
00388 
00389   /* check to be sure state is still Set so that user can cancel
00390      the action (e.g. by moving outside the window, in the default
00391      bindings.
00392   */
00393   if (cbw->command.set)
00394     XtCallCallbackList(w, cbw->command.callbacks, (XtPointer) NULL);
00395 }
00396 
00397 /*
00398  * Repaint the widget window
00399  */
00400 
00401 /************************
00402 *
00403 *  REDISPLAY (DRAW)
00404 *
00405 ************************/
00406 
00407 /* ARGSUSED */
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 /*      Function Name: PaintCommandWidget
00418  *      Description: Paints the command widget.
00419  *      Arguments: w - the command widget.
00420  *                 region - region to paint (passed to the superclass).
00421  *                 change - did it change either set or highlight state?
00422  *      Returns: none
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;              /* Force label to repaint text. */
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  * If we are set then use the same colors as if we are not highlighted. 
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; /* Give the label the right 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       /* wide lines are centered on the path, so indent it */
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   /* so Label can release it */
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  * Set specified arguments into widget
00505  */
00506 
00507 /* ARGSUSED */
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     /* about to become insensitive */
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         /* Label has release one of these */
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 }

Generated on Sun Mar 4 15:03:55 2007 for Scilab [trunk] by  doxygen 1.5.1