home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / Xaw / Command.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-04  |  15.5 KB  |  560 lines

  1. /* $XConsortium: Command.c,v 1.76 91/05/04 19:29:00 converse Exp $ */
  2.  
  3. /***********************************************************
  4. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
  5. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  6.  
  7.                         All Rights Reserved
  8.  
  9. Permission to use, copy, modify, and distribute this software and its 
  10. documentation for any purpose and without fee is hereby granted, 
  11. provided that the above copyright notice appear in all copies and that
  12. both that copyright notice and this permission notice appear in 
  13. supporting documentation, and that the names of Digital or MIT not be
  14. used in advertising or publicity pertaining to distribution of the
  15. software without specific, written prior permission.  
  16.  
  17. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  18. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  19. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  20. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  22. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  23. SOFTWARE.
  24.  
  25. ******************************************************************/
  26.  
  27. /*
  28.  * Command.c - Command button widget
  29.  */
  30.  
  31. #include <stdio.h>
  32. #include <X11/IntrinsicP.h>
  33. #include <X11/StringDefs.h>
  34. #include <X11/Xmu/Misc.h>
  35. #include <X11/Xaw/XawInit.h>
  36. #include <X11/Xaw/CommandP.h>
  37. #include <X11/Xmu/Converters.h>
  38.  
  39. #define DEFAULT_HIGHLIGHT_THICKNESS 2
  40. #define DEFAULT_SHAPE_HIGHLIGHT 32767
  41.  
  42. /****************************************************************
  43.  *
  44.  * Full class record constant
  45.  *
  46.  ****************************************************************/
  47.  
  48. /* Private Data */
  49.  
  50. static char defaultTranslations[] =
  51.     "<EnterWindow>:    highlight()        \n\
  52.      <LeaveWindow>:    reset()            \n\
  53.      <Btn1Down>:    set()            \n\
  54.      <Btn1Up>:        notify() unset()    ";
  55.  
  56. #define offset(field) XtOffsetOf(CommandRec, field)
  57. static XtResource resources[] = { 
  58.    {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), 
  59.       offset(command.callbacks), XtRCallback, (XtPointer)NULL},
  60.    {XtNhighlightThickness, XtCThickness, XtRDimension, sizeof(Dimension),
  61.       offset(command.highlight_thickness), XtRImmediate,
  62.       (XtPointer) DEFAULT_SHAPE_HIGHLIGHT},
  63.    {XtNshapeStyle, XtCShapeStyle, XtRShapeStyle, sizeof(int),
  64.       offset(command.shape_style), XtRImmediate, (XtPointer)XawShapeRectangle},
  65.    {XtNcornerRoundPercent, XtCCornerRoundPercent, 
  66.     XtRDimension, sizeof(Dimension),
  67.     offset(command.corner_round), XtRImmediate, (XtPointer) 25},
  68. };
  69. #undef offset
  70.  
  71. static Boolean SetValues();
  72. static void Initialize(), Redisplay(), Set(), Reset(), Notify(), Unset();
  73. static void Highlight(), Unhighlight(), Destroy(), PaintCommandWidget();
  74. static void ClassInitialize();
  75. static Boolean ShapeButton();
  76. static void Realize(), Resize();
  77.  
  78. static XtActionsRec actionsList[] = {
  79.   {"set",        Set},
  80.   {"notify",        Notify},
  81.   {"highlight",        Highlight},
  82.   {"reset",        Reset},
  83.   {"unset",        Unset},
  84.   {"unhighlight",    Unhighlight}
  85. };
  86.  
  87. #define SuperClass ((LabelWidgetClass)&labelClassRec)
  88.  
  89. CommandClassRec commandClassRec = {
  90.   {
  91.     (WidgetClass) SuperClass,        /* superclass          */    
  92.     "Command",                /* class_name          */
  93.     sizeof(CommandRec),            /* size              */
  94.     ClassInitialize,            /* class_initialize      */
  95.     NULL,                /* class_part_initialize  */
  96.     FALSE,                /* class_inited          */
  97.     Initialize,                /* initialize          */
  98.     NULL,                /* initialize_hook      */
  99.     Realize,                /* realize          */
  100.     actionsList,            /* actions          */
  101.     XtNumber(actionsList),        /* num_actions          */
  102.     resources,                /* resources          */
  103.     XtNumber(resources),        /* resource_count      */
  104.     NULLQUARK,                /* xrm_class          */
  105.     FALSE,                /* compress_motion      */
  106.     TRUE,                /* compress_exposure      */
  107.     TRUE,                /* compress_enterleave    */
  108.     FALSE,                /* visible_interest      */
  109.     Destroy,                /* destroy          */
  110.     Resize,                /* resize          */
  111.     Redisplay,                /* expose          */
  112.     SetValues,                /* set_values          */
  113.     NULL,                /* set_values_hook      */
  114.     XtInheritSetValuesAlmost,        /* set_values_almost      */
  115.     NULL,                /* get_values_hook      */
  116.     NULL,                /* accept_focus          */
  117.     XtVersion,                /* version          */
  118.     NULL,                /* callback_private      */
  119.     defaultTranslations,        /* tm_table          */
  120.     XtInheritQueryGeometry,        /* query_geometry      */
  121.     XtInheritDisplayAccelerator,    /* display_accelerator      */
  122.     NULL                /* extension          */
  123.   },  /* CoreClass fields initialization */
  124.   {
  125.     XtInheritChangeSensitive        /* change_sensitive    */
  126.   },  /* SimpleClass fields initialization */
  127.   {
  128.     0,                                     /* field not used    */
  129.   },  /* LabelClass fields initialization */
  130.   {
  131.     0,                                     /* field not used    */
  132.   },  /* CommandClass fields initialization */
  133. };
  134.  
  135.   /* for public consumption */
  136. WidgetClass commandWidgetClass = (WidgetClass) &commandClassRec;
  137.  
  138. /****************************************************************
  139.  *
  140.  * Private Procedures
  141.  *
  142.  ****************************************************************/
  143.  
  144. static GC 
  145. Get_GC(cbw, fg, bg)
  146. CommandWidget cbw;
  147. Pixel fg, bg;
  148. {
  149.   XGCValues    values;
  150.   
  151.   values.foreground   = fg;
  152.   values.background    = bg;
  153.   values.font        = cbw->label.font->fid;
  154.   values.cap_style = CapProjecting;
  155.   
  156.   if (cbw->command.highlight_thickness > 1 )
  157.     values.line_width   = cbw->command.highlight_thickness;
  158.   else 
  159.     values.line_width   = 0;
  160.   
  161.   return XtGetGC((Widget)cbw,
  162.          (GCForeground|GCBackground|GCFont|GCLineWidth|GCCapStyle),
  163.          &values);
  164. }
  165.  
  166.  
  167. /* ARGSUSED */
  168. static void 
  169. Initialize(request, new, args, num_args)
  170. Widget request, new;
  171. ArgList args;            /* unused */
  172. Cardinal *num_args;        /* unused */
  173. {
  174.   CommandWidget cbw = (CommandWidget) new;
  175.   int shape_event_base, shape_error_base;
  176.  
  177.   if (cbw->command.shape_style != XawShapeRectangle
  178.       && !XShapeQueryExtension(XtDisplay(new), &shape_event_base, 
  179.                    &shape_error_base))
  180.       cbw->command.shape_style = XawShapeRectangle;
  181.   if (cbw->command.highlight_thickness == DEFAULT_SHAPE_HIGHLIGHT) {
  182.       if (cbw->command.shape_style != XawShapeRectangle)
  183.       cbw->command.highlight_thickness = 0;
  184.       else
  185.       cbw->command.highlight_thickness = DEFAULT_HIGHLIGHT_THICKNESS;
  186.   }
  187.  
  188.   cbw->command.normal_GC = Get_GC(cbw, cbw->label.foreground, 
  189.                   cbw->core.background_pixel);
  190.   cbw->command.inverse_GC = Get_GC(cbw, cbw->core.background_pixel, 
  191.                    cbw->label.foreground);
  192.   XtReleaseGC(new, cbw->label.normal_GC);
  193.   cbw->label.normal_GC = cbw->command.normal_GC;
  194.  
  195.   cbw->command.set = FALSE;
  196.   cbw->command.highlighted = HighlightNone;
  197. }
  198.  
  199. static Region 
  200. HighlightRegion(cbw)
  201. CommandWidget cbw;
  202. {
  203.   static Region outerRegion = NULL, innerRegion, emptyRegion;
  204.   XRectangle rect;
  205.  
  206.   if (cbw->command.highlight_thickness == 0 ||
  207.       cbw->command.highlight_thickness >
  208.       (Dimension) ((Dimension) Min(cbw->core.width, cbw->core.height)/2))
  209.     return(NULL);
  210.  
  211.   if (outerRegion == NULL) {
  212.     /* save time by allocating scratch regions only once. */
  213.     outerRegion = XCreateRegion();
  214.     innerRegion = XCreateRegion();
  215.     emptyRegion = XCreateRegion();
  216.   }
  217.  
  218.   rect.x = rect.y = 0;
  219.   rect.width = cbw->core.width;
  220.   rect.height = cbw->core.height;
  221.   XUnionRectWithRegion( &rect, emptyRegion, outerRegion );
  222.   rect.x = rect.y = cbw->command.highlight_thickness;
  223.   rect.width -= cbw->command.highlight_thickness * 2;
  224.   rect.height -= cbw->command.highlight_thickness * 2;
  225.   XUnionRectWithRegion( &rect, emptyRegion, innerRegion );
  226.   XSubtractRegion( outerRegion, innerRegion, outerRegion );
  227.   return outerRegion;
  228. }
  229.  
  230. /***************************
  231. *
  232. *  Action Procedures
  233. *
  234. ***************************/
  235.  
  236. /* ARGSUSED */
  237. static void 
  238. Set(w,event,params,num_params)
  239. Widget w;
  240. XEvent *event;
  241. String *params;        /* unused */
  242. Cardinal *num_params;    /* unused */
  243. {
  244.   CommandWidget cbw = (CommandWidget)w;
  245.  
  246.   if (cbw->command.set)
  247.     return;
  248.  
  249.   cbw->command.set= TRUE;
  250.   if (XtIsRealized(w))
  251.     PaintCommandWidget(w, (Region) NULL, TRUE);
  252. }
  253.  
  254. /* ARGSUSED */
  255. static void
  256. Unset(w,event,params,num_params)
  257. Widget w;
  258. XEvent *event;
  259. String *params;        /* unused */
  260. Cardinal *num_params;
  261. {
  262.   CommandWidget cbw = (CommandWidget)w;
  263.  
  264.   if (!cbw->command.set)
  265.     return;
  266.  
  267.   cbw->command.set = FALSE;
  268.   if (XtIsRealized(w)) {
  269.     XClearWindow(XtDisplay(w), XtWindow(w));
  270.     PaintCommandWidget(w, (Region) NULL, TRUE);
  271.   }
  272. }
  273.  
  274. /* ARGSUSED */
  275. static void 
  276. Reset(w,event,params,num_params)
  277. Widget w;
  278. XEvent *event;
  279. String *params;        /* unused */
  280. Cardinal *num_params;   /* unused */
  281. {
  282.   CommandWidget cbw = (CommandWidget)w;
  283.  
  284.   if (cbw->command.set) {
  285.     cbw->command.highlighted = HighlightNone;
  286.     Unset(w, event, params, num_params);
  287.   }
  288.   else
  289.     Unhighlight(w, event, params, num_params);
  290. }
  291.  
  292. /* ARGSUSED */
  293. static void 
  294. Highlight(w,event,params,num_params)
  295. Widget w;
  296. XEvent *event;
  297. String *params;        
  298. Cardinal *num_params;    
  299. {
  300.   CommandWidget cbw = (CommandWidget)w;
  301.  
  302.   if ( *num_params == (Cardinal) 0) 
  303.     cbw->command.highlighted = HighlightWhenUnset;
  304.   else {
  305.     if ( *num_params != (Cardinal) 1) 
  306.       XtWarning("Too many parameters passed to highlight action table.");
  307.     switch (params[0][0]) {
  308.     case 'A':
  309.     case 'a':
  310.       cbw->command.highlighted = HighlightAlways;
  311.       break;
  312.     default:
  313.       cbw->command.highlighted = HighlightWhenUnset;
  314.       break;
  315.     }
  316.   }
  317.  
  318.   if (XtIsRealized(w))
  319.     PaintCommandWidget(w, HighlightRegion(cbw), TRUE);
  320. }
  321.  
  322. /* ARGSUSED */
  323. static void 
  324. Unhighlight(w,event,params,num_params)
  325. Widget w;
  326. XEvent *event;
  327. String *params;        /* unused */
  328. Cardinal *num_params;    /* unused */
  329. {
  330.   CommandWidget cbw = (CommandWidget)w;
  331.  
  332.   cbw->command.highlighted = HighlightNone;
  333.   if (XtIsRealized(w))
  334.     PaintCommandWidget(w, HighlightRegion(cbw), TRUE);
  335. }
  336.  
  337. /* ARGSUSED */
  338. static void 
  339. Notify(w,event,params,num_params)
  340. Widget w;
  341. XEvent *event;
  342. String *params;        /* unused */
  343. Cardinal *num_params;    /* unused */
  344. {
  345.   CommandWidget cbw = (CommandWidget)w; 
  346.  
  347.   /* check to be sure state is still Set so that user can cancel
  348.      the action (e.g. by moving outside the window, in the default
  349.      bindings.
  350.   */
  351.   if (cbw->command.set)
  352.     XtCallCallbackList(w, cbw->command.callbacks, NULL);
  353. }
  354.  
  355. /*
  356.  * Repaint the widget window
  357.  */
  358.  
  359. /************************
  360. *
  361. *  REDISPLAY (DRAW)
  362. *
  363. ************************/
  364.  
  365. /* ARGSUSED */
  366. static void 
  367. Redisplay(w, event, region)
  368. Widget w;
  369. XEvent *event;
  370. Region region;
  371. {
  372.   PaintCommandWidget(w, region, FALSE);
  373. }
  374.  
  375. /*    Function Name: PaintCommandWidget
  376.  *    Description: Paints the command widget.
  377.  *    Arguments: w - the command widget.
  378.  *                 region - region to paint (passed to the superclass).
  379.  *                 change - did it change either set or highlight state?
  380.  *    Returns: none
  381.  */
  382.  
  383. static void 
  384. PaintCommandWidget(w, region, change)
  385. Widget w;
  386. Region region;
  387. Boolean change;
  388. {
  389.   CommandWidget cbw = (CommandWidget) w;
  390.   Boolean very_thick;
  391.   GC norm_gc, rev_gc;
  392.    
  393.   very_thick = cbw->command.highlight_thickness >
  394.                (Dimension)((Dimension) Min(cbw->core.width, cbw->core.height)/2);
  395.  
  396.   if (cbw->command.set) {
  397.     cbw->label.normal_GC = cbw->command.inverse_GC;
  398.     XFillRectangle(XtDisplay(w), XtWindow(w), cbw->command.normal_GC,
  399.            0, 0, cbw->core.width, cbw->core.height);
  400.     region = NULL;        /* Force label to repaint text. */
  401.   }
  402.   else
  403.       cbw->label.normal_GC = cbw->command.normal_GC;
  404.  
  405.   if (cbw->command.highlight_thickness <= 0)
  406.   {
  407.     (*SuperClass->core_class.expose) (w, (XEvent *) NULL, region);
  408.     return;
  409.   }
  410.  
  411. /*
  412.  * If we are set then use the same colors as if we are not highlighted. 
  413.  */
  414.  
  415.   if (cbw->command.set == (cbw->command.highlighted == HighlightNone)) {
  416.     norm_gc = cbw->command.inverse_GC;
  417.     rev_gc = cbw->command.normal_GC;
  418.   }
  419.   else {
  420.     norm_gc = cbw->command.normal_GC;
  421.     rev_gc = cbw->command.inverse_GC;
  422.   }
  423.  
  424.   if ( !( (!change && (cbw->command.highlighted == HighlightNone)) ||
  425.       ((cbw->command.highlighted == HighlightWhenUnset) &&
  426.        (cbw->command.set))) ) {
  427.     if (very_thick) {
  428.       cbw->label.normal_GC = norm_gc; /* Give the label the right GC. */
  429.       XFillRectangle(XtDisplay(w),XtWindow(w), rev_gc,
  430.              0, 0, cbw->core.width, cbw->core.height);
  431.     }
  432.     else {
  433.       /* wide lines are centered on the path, so indent it */
  434.       int offset = cbw->command.highlight_thickness/2;
  435.       XDrawRectangle(XtDisplay(w),XtWindow(w), rev_gc, offset, offset, 
  436.              cbw->core.width - cbw->command.highlight_thickness,
  437.              cbw->core.height - cbw->command.highlight_thickness);
  438.     }
  439.   }
  440.   (*SuperClass->core_class.expose) (w, (XEvent *) NULL, region);
  441. }
  442.  
  443. static void 
  444. Destroy(w)
  445. Widget w;
  446. {
  447.   CommandWidget cbw = (CommandWidget) w;
  448.  
  449.   /* so Label can release it */
  450.   if (cbw->label.normal_GC == cbw->command.normal_GC)
  451.     XtReleaseGC( w, cbw->command.inverse_GC );
  452.   else
  453.     XtReleaseGC( w, cbw->command.normal_GC );
  454. }
  455.  
  456. /*
  457.  * Set specified arguments into widget
  458.  */
  459.  
  460. /* ARGSUSED */
  461. static Boolean 
  462. SetValues (current, request, new)
  463. Widget current, request, new;
  464. {
  465.   CommandWidget oldcbw = (CommandWidget) current;
  466.   CommandWidget cbw = (CommandWidget) new;
  467.   Boolean redisplay = False;
  468.  
  469.   if ( oldcbw->core.sensitive != cbw->core.sensitive && !cbw->core.sensitive) {
  470.     /* about to become insensitive */
  471.     cbw->command.set = FALSE;
  472.     cbw->command.highlighted = HighlightNone;
  473.     redisplay = TRUE;
  474.   }
  475.   
  476.   if ( (oldcbw->label.foreground != cbw->label.foreground)           ||
  477.        (oldcbw->core.background_pixel != cbw->core.background_pixel) ||
  478.        (oldcbw->command.highlight_thickness != 
  479.                                    cbw->command.highlight_thickness) ||
  480.        (oldcbw->label.font != cbw->label.font) ) 
  481.   {
  482.     if (oldcbw->label.normal_GC == oldcbw->command.normal_GC)
  483.     /* Label has release one of these */
  484.       XtReleaseGC(new, cbw->command.inverse_GC);
  485.     else
  486.       XtReleaseGC(new, cbw->command.normal_GC);
  487.  
  488.     cbw->command.normal_GC = Get_GC(cbw, cbw->label.foreground, 
  489.                     cbw->core.background_pixel);
  490.     cbw->command.inverse_GC = Get_GC(cbw, cbw->core.background_pixel, 
  491.                      cbw->label.foreground);
  492.     XtReleaseGC(new, cbw->label.normal_GC);
  493.     cbw->label.normal_GC = (cbw->command.set
  494.                 ? cbw->command.inverse_GC
  495.                 : cbw->command.normal_GC);
  496.     
  497.     redisplay = True;
  498.   }
  499.  
  500.   if ( XtIsRealized(new)
  501.        && oldcbw->command.shape_style != cbw->command.shape_style
  502.        && !ShapeButton(cbw, TRUE))
  503.   {
  504.       cbw->command.shape_style = oldcbw->command.shape_style;
  505.   }
  506.  
  507.   return (redisplay);
  508. }
  509.  
  510. static void ClassInitialize()
  511. {
  512.     XawInitializeWidgetSet();
  513.     XtSetTypeConverter( XtRString, XtRShapeStyle, XmuCvtStringToShapeStyle,
  514.                 NULL, 0, XtCacheNone, NULL );
  515. }
  516.  
  517.  
  518. static Boolean
  519. ShapeButton(cbw, checkRectangular)
  520. CommandWidget cbw;
  521. Boolean checkRectangular;
  522. {
  523.     Dimension corner_size;
  524.  
  525.     if ( (cbw->command.shape_style == XawShapeRoundedRectangle) ) {
  526.     corner_size = (cbw->core.width < cbw->core.height) ? cbw->core.width 
  527.                                                        : cbw->core.height;
  528.     corner_size = (int) (corner_size * cbw->command.corner_round) / 100;
  529.     }
  530.  
  531.     if (checkRectangular || cbw->command.shape_style != XawShapeRectangle) {
  532.     if (!XmuReshapeWidget((Widget) cbw, cbw->command.shape_style,
  533.                   corner_size, corner_size)) {
  534.         cbw->command.shape_style = XawShapeRectangle;
  535.         return(False);
  536.     }
  537.     }
  538.     return(TRUE);
  539. }
  540.  
  541. static void Realize(w, valueMask, attributes)
  542.     Widget w;
  543.     Mask *valueMask;
  544.     XSetWindowAttributes *attributes;
  545. {
  546.     (*commandWidgetClass->core_class.superclass->core_class.realize)
  547.     (w, valueMask, attributes);
  548.  
  549.     ShapeButton( (CommandWidget) w, FALSE);
  550. }
  551.  
  552. static void Resize(w)
  553.     Widget w;
  554. {
  555.     if (XtIsRealized(w)) 
  556.     ShapeButton( (CommandWidget) w, FALSE);
  557.  
  558.     (*commandWidgetClass->core_class.superclass->core_class.resize)(w);
  559. }
  560.