home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / XfeWidgets / Xfe / BmButton.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  28.2 KB  |  939 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /*-----------------------------------------*/
  19. /*                                                                        */
  20. /* Name:        <Xfe/BmButton.c>                                        */
  21. /* Description:    XfeBmButton widget source.                                */
  22. /* Author:        Ramiro Estrugo <ramiro@netscape.com>                    */
  23. /*                                                                        */
  24. /*----------------------------------------------------------------------*/
  25.  
  26.  
  27. #include <Xfe/BmButtonP.h>
  28. #include <Xfe/ManagerP.h>
  29. #include <Xfe/BmCascade.h>
  30. #include <Xfe/CascadeP.h>
  31. #include <Xm/RowColumnP.h>
  32.  
  33. /*----------------------------------------------------------------------*/
  34. /*                                                                        */
  35. /* Warnings and messages                                                */
  36. /*                                                                        */
  37. /*----------------------------------------------------------------------*/
  38. #define MESSAGE1 "Widget is not a XfeBmButton."
  39. #define MESSAGE2 "XmNaccentType is a read-only reasource."
  40.  
  41. /*----------------------------------------------------------------------*/
  42. /*                                                                        */
  43. /* Core Class methods                                                    */
  44. /*                                                                        */
  45. /*----------------------------------------------------------------------*/
  46. static void                Initialize        (Widget,Widget,ArgList,Cardinal *);
  47. static void                Destroy            (Widget);
  48. static void                Resize            (Widget);
  49. static void                Redisplay        (Widget,XEvent *,Region);
  50. static Boolean            SetValues        (Widget,Widget,Widget,
  51.                                          ArgList,Cardinal *);
  52.  
  53. static XtGeometryResult    QueryGeometry    (Widget,XtWidgetGeometry *,
  54.                                          XtWidgetGeometry *);
  55.  
  56. /*----------------------------------------------------------------------*/
  57. /*                                                                        */
  58. /* XmPrimitive methods                                                    */
  59. /*                                                                        */
  60. /*----------------------------------------------------------------------*/
  61. static void     BorderHighlight            (Widget);
  62. static void     BorderUnhighlight        (Widget);
  63.  
  64. /*----------------------------------------------------------------------*/
  65. /*                                                                        */
  66. /* XfeBmButton action procedures                                        */
  67. /*                                                                        */
  68. /*----------------------------------------------------------------------*/
  69. static void     Enter            (Widget,XEvent *,char **,Cardinal *);
  70. static void     Leave            (Widget,XEvent *,char **,Cardinal *);
  71. static void     Motion            (Widget,XEvent *,char **,Cardinal *);
  72. static void     BtnDown            (Widget,XEvent *,char **,Cardinal *);
  73. static void     BtnUp            (Widget,XEvent *,char **,Cardinal *);
  74.  
  75. /*----------------------------------------------------------------------*/
  76. /*                                                                        */
  77. /* Misc XfeBmButton functions                                            */
  78. /*                                                                        */
  79. /*----------------------------------------------------------------------*/
  80. static void        PixmapDraw                (Widget,XEvent *,Region);
  81.  
  82. static void        AccentUpdate            (Widget,Position);
  83. static void        AccentDraw                (Widget);
  84. static void        AccentErase                (Widget);
  85.  
  86. /*----------------------------------------------------------------------*/
  87. /*                                                                        */
  88. /* XfeBmButton Resources                                                */
  89. /*                                                                        */
  90. /*----------------------------------------------------------------------*/
  91. static XtResource resources[] = 
  92. {
  93.     /* Pixmap resources */
  94.     { 
  95.         XmNaccentType,
  96.         XmCAccentType,
  97.         XmRAccentType,
  98.         sizeof(unsigned char),
  99.         XtOffsetOf(XfeBmButtonRec , bm_button . accent_type),
  100.         XmRImmediate, 
  101.         (XtPointer) XmACCENT_NONE
  102.     },
  103.     { 
  104.         XmNarmPixmapMask,
  105.         XmCArmPixmapMask,
  106.         XmRPixmap,
  107.         sizeof(Pixmap),
  108.         XtOffsetOf(XfeBmButtonRec , bm_button . arm_pixmap_mask),
  109.         XmRImmediate, 
  110.         (XtPointer) XmUNSPECIFIED_PIXMAP
  111.     },
  112.     { 
  113.         XmNlabelPixmapMask,
  114.         XmCLabelPixmapMask,
  115.         XmRPixmap,
  116.         sizeof(Pixmap),
  117.         XtOffsetOf(XfeBmButtonRec , bm_button . label_pixmap_mask),
  118.         XmRImmediate, 
  119.         (XtPointer) XmUNSPECIFIED_PIXMAP
  120.     },
  121. };
  122.  
  123. /*----------------------------------------------------------------------*/
  124. /*                                                                        */
  125. /* XmPrimitive extension record initialization                            */
  126. /*                                                                        */
  127. /*----------------------------------------------------------------------*/
  128. static XmPrimitiveClassExtRec xmPrimitiveClassExtRec = 
  129. {
  130.     NULL,                                    /* next_extension            */
  131.     NULLQUARK,                                /* record_type                */
  132.     XmPrimitiveClassExtVersion,                /* version                    */
  133.     sizeof(XmPrimitiveClassExtRec),            /* record_size                */
  134.     XmInheritBaselineProc,                    /* widget_baseline            */
  135.     XmInheritDisplayRectProc,                /* widget_display_rect        */
  136.     XmInheritMarginsProc,                    /* widget_margins            */
  137. };
  138.  
  139.  
  140. /*----------------------------------------------------------------------*/
  141. /*                                                                        */
  142. /* XmPushButton extension record initialization                            */
  143. /*                                                                        */
  144. /*----------------------------------------------------------------------*/
  145. static XmBaseClassExtRec xmPushButtonClassExtRec = 
  146. {
  147.     NULL,                                    /* Next extension            */
  148.     NULLQUARK,                                /* record type XmQmotif        */
  149.     XmBaseClassExtVersion,                    /* version                    */
  150.     sizeof(XmBaseClassExtRec),                /* size                        */
  151.     XmInheritInitializePrehook,                /* initialize prehook        */
  152.     XmInheritSetValuesPrehook,                /* set_values prehook        */
  153.     XmInheritInitializePosthook,            /* initialize posthook        */
  154.     XmInheritSetValuesPosthook,                /* set_values posthook        */
  155.     XmInheritClass,                            /* secondary class            */
  156.     XmInheritSecObjectCreate,                /* creation proc            */
  157.     XmInheritGetSecResData,                    /* getSecResData            */
  158.     {0},                                    /* fast subclass            */
  159.     XmInheritGetValuesPrehook,                /* get_values prehook        */
  160.     XmInheritGetValuesPosthook,                /* get_values posthook        */
  161.     XmInheritClassPartInitPrehook,            /* classPartInitPrehook        */
  162.     XmInheritClassPartInitPosthook,            /* classPartInitPosthook    */
  163.     NULL,                                    /* ext_resources            */
  164.     NULL,                                    /* compiled_ext_resources    */
  165.     0,                                        /* num_ext_resources        */
  166.     FALSE,                                    /* use_sub_resources        */
  167.     XmInheritWidgetNavigable,                /* widgetNavigable            */
  168.     XmInheritFocusChange,                    /* focusChange                */
  169. };
  170.  
  171. /*----------------------------------------------------------------------*/
  172. /*                                                                        */
  173. /* XfeBmButton actions                                                    */
  174. /*                                                                        */
  175. /*----------------------------------------------------------------------*/
  176. static XtActionsRec actions[] = 
  177. {
  178.     { "BtnDown",            BtnDown            },
  179.     { "BtnUp",                BtnUp            },
  180.     { "Enter",                Enter            },
  181.     { "Motion",                Motion            },
  182.     { "Leave",                Leave            },
  183. };
  184.  
  185. /*----------------------------------------------------------------------*/
  186. /*                                                                        */
  187. /* XfeBmButton widget class record initialization                        */
  188. /*                                                                        */
  189. /*----------------------------------------------------------------------*/
  190. _XFE_WIDGET_CLASS_RECORD(bmbutton,BmButton) =
  191. {
  192.     {
  193.         /* Core Part */
  194.         (WidgetClass) &xmPushButtonClassRec,    /* superclass             */
  195.         "XfeBmButton",                            /* class_name            */
  196.         sizeof(XfeBmButtonRec),                    /* widget_size            */
  197.         NULL,                                    /* class_initialize       */
  198.         NULL,                                    /* class_part_initialize*/
  199.         FALSE,                                  /* class_inited           */
  200.         Initialize,                                /* initialize            */
  201.         NULL,                                   /* initialize_hook        */
  202.         XtInheritRealize,                       /* realize                */
  203.         actions,                                /* actions                */
  204.         XtNumber(actions),                        /* num_actions            */
  205.         resources,                              /* resources              */
  206.         XtNumber(resources),                    /* num_resources          */
  207.         NULLQUARK,                              /* xrm_class              */
  208.         TRUE,                                   /* compress_motion        */
  209.         XtExposeCompressMaximal,                /* compress_exposure      */
  210.         TRUE,                                   /* compress_enterleave    */
  211.         FALSE,                                  /* visible_interest       */
  212.         Destroy,                                /* destroy                */
  213.         Resize,                                    /* resize                 */
  214.         Redisplay,                                /* expose                 */
  215.         SetValues,                              /* set_values             */
  216.         NULL,                                   /* set_values_hook        */
  217.         XtInheritSetValuesAlmost,                /* set_values_almost      */
  218.         NULL,                                    /* get_values_hook        */
  219.         NULL,                                   /* accept_focus           */
  220.         XtVersion,                              /* version                */
  221.         NULL,                                   /* callback_private       */
  222.         XtInheritTranslations,                    /* tm_table               */
  223.         QueryGeometry,                            /* query_geometry         */
  224.         XtInheritDisplayAccelerator,            /* display accel          */
  225.         (XtPointer) &xmPushButtonClassExtRec    /* extension              */
  226.     },
  227.  
  228.     /* XmPrimitive Part */
  229.     {
  230.         BorderHighlight,                        /* border_highlight     */
  231.         BorderUnhighlight,                        /* border_unhighlight     */
  232.         XtInheritTranslations,                  /* translations           */
  233.         XmInheritArmAndActivate,                /* arm_and_activate       */
  234.         NULL,                                    /* syn resources          */
  235.         0,                                        /* num syn_resources      */
  236.         (XtPointer) &xmPrimitiveClassExtRec,    /* extension              */
  237.     },
  238.  
  239.     /* XmLabel Part */
  240.     {
  241.         XmInheritWidgetProc,                    /* setOverrideCallback    */
  242.         XmInheritMenuProc,                        /* menu procedures        */
  243.         XtInheritTranslations,                    /* menu traversal xlat    */
  244.         (XtPointer) NULL,                        /* extension            */
  245.     },
  246.  
  247.     /* XmPushButton Part */
  248.     {
  249.         (XtPointer) NULL,                        /* extension            */
  250.     },
  251.  
  252.     /* XfeBmButton Part */
  253.     {
  254.         (XtPointer) NULL,                        /* extension            */
  255.     }
  256. };
  257.  
  258. /*----------------------------------------------------------------------*/
  259. /*                                                                        */
  260. /* xfeBmButtonWidgetClass declaration.                                    */
  261. /*                                                                        */
  262. /*----------------------------------------------------------------------*/
  263. _XFE_WIDGET_CLASS(bmbutton,BmButton);
  264.  
  265. /*----------------------------------------------------------------------*/
  266. /*                                                                        */
  267. /* Core Class methods                                                    */
  268. /*                                                                        */
  269. /*----------------------------------------------------------------------*/
  270. static void
  271. Initialize(Widget rw,Widget nw,ArgList args,Cardinal *nargs)
  272. {
  273.     XfeBmButtonPart *        bmp = _XfeBmButtonPart(nw);
  274.     XmLabelPart *            lp = _XfeXmLabelPart(nw);
  275.  
  276.     assert( XmIsRowColumn(XtParent(nw)) );
  277.  
  278.     /* Force the type to be string always */
  279.     lp->label_type = XmSTRING;
  280.  
  281.     bmp->pixmap_GC = XfeAllocateTransparentGc(nw);
  282.  
  283.     _XfePixmapPrepare(nw,
  284.                       &lp->pixmap,
  285.                       &bmp->pixmap_width,
  286.                       &bmp->pixmap_height,
  287.                       XmNlabelPixmap);
  288.  
  289.     XfeOverrideTranslations(nw,_XfeBmButtonExtraTranslations);
  290. }
  291. /*----------------------------------------------------------------------*/
  292. static void
  293. Destroy(Widget w)
  294. {
  295.     XfeBmButtonPart *        bmp = _XfeBmButtonPart(w);
  296.     
  297.     XtReleaseGC(w,bmp->pixmap_GC);
  298. }
  299. /*----------------------------------------------------------------------*/
  300. static XtGeometryResult
  301. QueryGeometry(Widget w,XtWidgetGeometry    *req,XtWidgetGeometry *reply)
  302. {
  303.     XfeBmButtonPart *        bmp = _XfeBmButtonPart(w);
  304.     XmLabelPart *            lp = _XfeXmLabelPart(w);
  305.     XtGeometryResult        result;
  306.     XmPushButtonWidgetClass pwc = 
  307.         (XmPushButtonWidgetClass) xmPushButtonWidgetClass;
  308.     
  309.     result = (*pwc->core_class.query_geometry)(w,req,reply);
  310.  
  311.     if (bmp->pixmap_width && bmp->pixmap_height)
  312.     {
  313.         Dimension offset;
  314.         Dimension label_height;
  315.  
  316.         reply->width += (bmp->pixmap_width + XfeBmPixmapGetOffset());
  317.  
  318.         offset = 
  319.             lp->margin_top +
  320.             lp->margin_bottom +
  321.             _XfePrimitiveOffset(w);
  322.  
  323.         label_height = reply->height - offset;
  324.  
  325.         reply->height = 
  326.             XfeMax(label_height,bmp->pixmap_height) +
  327.             offset;
  328.     }
  329.  
  330.     return result;
  331. }
  332. /*----------------------------------------------------------------------*/
  333. static void
  334. Resize(Widget w)
  335. {
  336.     XfeBmButtonPart *        bmp = _XfeBmButtonPart(w);
  337.     XmLabelPart *            lp = _XfeXmLabelPart(w);
  338.     XmPushButtonWidgetClass pwc = 
  339.         (XmPushButtonWidgetClass) xmPushButtonWidgetClass;
  340.  
  341.     (*pwc->core_class.resize)(w);
  342.  
  343.     /* Layout the pixmap if needed */
  344.     if (bmp->pixmap_width && bmp->pixmap_height)
  345.     {
  346.         /* Move the label outta the way to the right */
  347.         lp->TextRect.x += (bmp->pixmap_width + XfeBmPixmapGetOffset());
  348.     }
  349. }
  350. /*----------------------------------------------------------------------*/
  351. static void
  352. Redisplay(Widget w,XEvent *event,Region region)
  353. {
  354.     XmPushButtonWidgetClass        pwc = 
  355.         (XmPushButtonWidgetClass) xmPushButtonWidgetClass;
  356.  
  357.     if (XfeBmAccentIsEnabled())
  358.     {
  359.         Dimension shadow_thickness = _XfeShadowThickness(w);
  360.  
  361.         /*
  362.          * We change the shadow thickness to 0, so that the real Expose() 
  363.          * method not draw anything the shadow so that the accent lines
  364.          * are not disturbed.
  365.          */
  366.         _XfeShadowThickness(w)        = 0;
  367.         _XfeHighlightThickness(w)    = shadow_thickness;
  368.         
  369.         (*pwc->core_class.expose)(w,event,region);
  370.         
  371.         _XfeShadowThickness(w)        = shadow_thickness;
  372.         _XfeHighlightThickness(w)    = 0;
  373.     }
  374.     else
  375.     {
  376.         (*pwc->core_class.expose)(w,event,region);
  377.     }
  378.     
  379.     PixmapDraw(w,event,region);
  380. }
  381. /*----------------------------------------------------------------------*/
  382. static Boolean
  383. SetValues(Widget ow,Widget rw,Widget nw,ArgList args,Cardinal *nargs)
  384. {
  385.     Boolean                    redisplay = False;
  386.     Boolean                    resize = False;
  387.     XmPushButtonPart *        old_bp = _XfeXmPushButtonPart(ow);
  388.     XmPushButtonPart *        new_bp = _XfeXmPushButtonPart(nw);
  389.     XmLabelPart *            old_lp = _XfeXmLabelPart(ow);
  390.     XmLabelPart *            new_lp = _XfeXmLabelPart(nw);
  391.     XfeBmButtonPart *        new_bmp = _XfeBmButtonPart(nw);
  392.     XfeBmButtonPart *        old_bmp = _XfeBmButtonPart(ow);
  393.  
  394.     /* accent_type */
  395.     if (new_bmp->accent_type != old_bmp->accent_type)
  396.     {
  397.         new_bmp->accent_type = old_bmp->accent_type;
  398.  
  399.         _XfeWarning(nw,MESSAGE2);
  400.     }
  401.  
  402.     /* label_pixmap */
  403.     if (new_lp->pixmap != old_lp->pixmap)
  404.     {
  405.         _XfePixmapPrepare(nw,&new_lp->pixmap,
  406.                           &new_bmp->pixmap_width,
  407.                           &new_bmp->pixmap_height,
  408.                           XmNlabelPixmap);
  409.  
  410.         redisplay = True;
  411.         resize = True;
  412.     }
  413.  
  414.     /* arm_pixmap */
  415.     if (new_bp->arm_pixmap != old_bp->arm_pixmap)
  416.     {
  417.         Dimension width;
  418.         Dimension height;
  419.  
  420.         assert( _XfePixmapGood(new_lp->pixmap) );
  421.  
  422.         _XfePixmapPrepare(nw,&new_bp->arm_pixmap,
  423.                           &width,
  424.                           &height,
  425.                           XmNarmPixmap);
  426.  
  427.         assert( width == new_bmp->pixmap_width );
  428.         assert( height == new_bmp->pixmap_height );
  429.  
  430.         redisplay = True;
  431.         resize = True;
  432.     }
  433.  
  434.     if (resize)
  435.     {
  436.         Resize(nw);
  437.     }
  438.  
  439.     return redisplay;
  440. }
  441. /*----------------------------------------------------------------------*/
  442.  
  443. /*----------------------------------------------------------------------*/
  444. /*                                                                        */
  445. /* XmPrimitive methods                                                    */
  446. /*                                                                        */
  447. /*----------------------------------------------------------------------*/
  448. static void
  449. BorderHighlight(Widget w)
  450. {
  451.     XfeBmButtonPart *            bmp = _XfeBmButtonPart(w);
  452.     XmPushButtonWidgetClass        pwc = 
  453.         (XmPushButtonWidgetClass) xmPushButtonWidgetClass;
  454.  
  455.     if (XfeBmAccentIsEnabled())
  456.     {
  457.         _XfeBmProcWithoutDrawing(w,pwc->primitive_class.border_highlight);
  458.     }
  459.     else
  460.     {
  461.         (*pwc->primitive_class.border_highlight)(w);
  462.     }
  463.  
  464.     PixmapDraw(w,NULL,NULL);
  465. }
  466. /*----------------------------------------------------------------------*/
  467. static void
  468. BorderUnhighlight(Widget w)
  469. {
  470.     XfeBmButtonPart *            bmp = _XfeBmButtonPart(w);
  471.     XmPushButtonWidgetClass        pwc = 
  472.         (XmPushButtonWidgetClass) xmPushButtonWidgetClass;
  473.  
  474.     if (XfeBmAccentIsEnabled())
  475.     {
  476.         _XfeBmProcWithoutDrawing(w,pwc->primitive_class.border_unhighlight);
  477.     }
  478.     else
  479.     {
  480.         (*pwc->primitive_class.border_unhighlight)(w);
  481.     }
  482.  
  483.     PixmapDraw(w,NULL,NULL);
  484. }
  485. /*----------------------------------------------------------------------*/
  486.  
  487.  
  488. /*----------------------------------------------------------------------*/
  489. /*                                                                        */
  490. /* XfeBmButton action procedures                                        */
  491. /*                                                                        */
  492. /*----------------------------------------------------------------------*/
  493. static void
  494. Enter(Widget w,XEvent * event,char ** params,Cardinal * nparams)
  495. {
  496.     static XtActionProc        enter_action = NULL;
  497.     XfeBmButtonPart *        bmp = _XfeBmButtonPart(w);
  498.  
  499.     if (!enter_action)
  500.     {
  501.         enter_action = _XfeGetActionProc(xmPushButtonWidgetClass,"Enter");
  502.     }
  503.  
  504.     if (XfeBmAccentIsEnabled())
  505.     {
  506.         _XfeBmActionWithoutDrawing(w,enter_action,event,params,nparams);
  507.  
  508.         AccentUpdate(w,event->xcrossing.y);
  509.     }
  510.     else
  511.     {
  512.         enter_action(w,event,params,nparams);
  513.     }
  514.  
  515.     /*
  516.      * Redraw the pixmap since fancy motif menus such as those in 
  517.      * irix or cde will fill the whole background and erase the 
  518.      * previous menu.  This should be smarter, and redraw the pixmap
  519.      * only if needed, but the extra waste in time is smaller than
  520.      * the effort needed to implement it.
  521.      */
  522.     PixmapDraw(w,NULL,NULL);
  523. }
  524. /*----------------------------------------------------------------------*/
  525. static void
  526. Leave(Widget w,XEvent * event,char ** params,Cardinal * nparams)
  527. {
  528.     XfeBmButtonPart *        bmp = _XfeBmButtonPart(w);
  529.     static XtActionProc        leave_action = NULL;
  530.  
  531.     if (!leave_action)
  532.     {
  533.         leave_action = _XfeGetActionProc(xmPushButtonWidgetClass,"Leave");
  534.     }
  535.  
  536.     if (XfeBmAccentIsEnabled())
  537.     {
  538.         _XfeBmActionWithoutDrawing(w,leave_action,event,params,nparams);
  539.  
  540.         AccentUpdate(w,XfeACCENT_OUTSIDE);
  541.     }
  542.     else
  543.     {
  544.         leave_action(w,event,params,nparams);
  545.     }
  546.  
  547.     /*
  548.      * Redraw the pixmap since fancy motif menus such as those in 
  549.      * irix or cde will fill the whole background and erase the 
  550.      * previous menu.  This should be smarter, and redraw the pixmap
  551.      * only if needed, but the extra waste in time is smaller than
  552.      * the effort needed to implement it.
  553.      */
  554.     PixmapDraw(w,NULL,NULL);
  555. }
  556. /*----------------------------------------------------------------------*/
  557. static void
  558. Motion(Widget w,XEvent * event,char ** params,Cardinal * nparams)
  559. {
  560.     XfeBmButtonPart *        bmp = _XfeBmButtonPart(w);
  561.  
  562.     if (!XfeBmAccentIsEnabled())
  563.     {
  564.         return;
  565.     }
  566.  
  567.     AccentUpdate(w,event->xmotion.y);
  568. }
  569. /*----------------------------------------------------------------------*/
  570. static void
  571. BtnDown(Widget w,XEvent * event,char ** params,Cardinal * nparams)
  572. {
  573.     static XtActionProc        btn_down_action = NULL;
  574.     XfeBmButtonPart *        bmp = _XfeBmButtonPart(w);
  575.  
  576.     if (!btn_down_action)
  577.     {
  578.         btn_down_action = _XfeGetActionProc(xmPushButtonWidgetClass,"BtnDown");
  579.     }
  580.  
  581.     if (XfeBmAccentIsEnabled())
  582.     {
  583.         _XfeBmActionWithoutDrawing(w,btn_down_action,event,params,nparams);
  584.  
  585.         AccentUpdate(w,event->xbutton.y);
  586.     }
  587.     else
  588.     {
  589.         btn_down_action(w,event,params,nparams);
  590.     }
  591. }
  592. /*----------------------------------------------------------------------*/
  593. static void
  594. BtnUp(Widget w,XEvent * event,char ** params,Cardinal * nparams)
  595. {
  596.     static XtActionProc        btn_up_action = NULL;
  597.     XfeBmButtonPart *        bmp = _XfeBmButtonPart(w);
  598.  
  599.     if (!btn_up_action)
  600.     {
  601.         btn_up_action = _XfeGetActionProc(xmPushButtonWidgetClass,"BtnUp");
  602.     }
  603.  
  604.     if (XfeBmAccentIsEnabled())
  605.     {
  606.         _XfeBmActionWithoutDrawing(w,btn_up_action,event,params,nparams);
  607.  
  608.         AccentUpdate(w,XfeACCENT_OUTSIDE);
  609.     }
  610.     else
  611.     {
  612.         btn_up_action(w,event,params,nparams);
  613.     }
  614. }
  615. /*----------------------------------------------------------------------*/
  616.  
  617. /*----------------------------------------------------------------------*/
  618. /*                                                                        */
  619. /* Misc XfeBmButton functions                                            */
  620. /*                                                                        */
  621. /*----------------------------------------------------------------------*/
  622. static void
  623. PixmapDraw(Widget w,XEvent *event,Region region)
  624. {
  625.     XfeBmButtonPart *        bmp = _XfeBmButtonPart(w);
  626.     XmLabelPart *            lp = _XfeXmLabelPart(w);
  627.     XmPushButtonPart *        bp = _XfeXmPushButtonPart(w);
  628.     Pixmap                    pixmap = XmUNSPECIFIED_PIXMAP;
  629.     Pixmap                    mask = XmUNSPECIFIED_PIXMAP;
  630.  
  631.     if (bp->armed && _XfePixmapGood(bp->arm_pixmap))
  632.     {
  633.         pixmap = bp->arm_pixmap;
  634.  
  635.         if (_XfePixmapGood(bmp->arm_pixmap_mask))
  636.         {
  637.             mask = bmp->arm_pixmap_mask;
  638.         }
  639.     }
  640.     else if (_XfePixmapGood(lp->pixmap) && 
  641.              bmp->pixmap_width && bmp->pixmap_height)
  642.     {
  643.         pixmap = lp->pixmap;
  644.  
  645.         if (_XfePixmapGood(bmp->label_pixmap_mask))
  646.         {
  647.             mask = bmp->label_pixmap_mask;
  648.         }
  649.     }
  650.  
  651.     if (_XfePixmapGood(pixmap))
  652.     {
  653.         Position x = _XfePrimitiveOffset(w) + lp->margin_width;
  654.         Position y = (_XfeHeight(w) - bmp->pixmap_height) / 2;
  655.  
  656.         if (_XfePixmapGood(mask))
  657.         {
  658.             XSetClipOrigin(XtDisplay(w),bmp->pixmap_GC,x,y);
  659.             XSetClipMask(XtDisplay(w),bmp->pixmap_GC,mask);
  660.         }
  661.         else
  662.         {
  663.             XSetClipMask(XtDisplay(w),bmp->pixmap_GC,None);
  664.         }
  665.  
  666.         XCopyArea(XtDisplay(w),
  667.                   pixmap,
  668.                   _XfeWindow(w),
  669.                   bmp->pixmap_GC,
  670.                   0,0,
  671.                   bmp->pixmap_width,
  672.                   bmp->pixmap_height,
  673.                   x,
  674.                   y);
  675.     }
  676. }
  677. /*----------------------------------------------------------------------*/
  678. static void
  679. AccentUpdate(Widget w,Position y)
  680. {
  681.     unsigned char         new_accent_type = XmACCENT_NONE;
  682.     XfeBmButtonPart *     bmp = _XfeBmButtonPart(w);
  683.     Dimension            half = _XfeHeight(w) / 2;
  684.  
  685.     /* Determine the new accent */
  686.     if ( (y <= half) && (y >= 0) )
  687.     {
  688.         new_accent_type = XmACCENT_TOP;
  689.     }
  690.     else if ( (y > half) && (y <= _XfeHeight(w)) )
  691.     {
  692.         new_accent_type = XmACCENT_BOTTOM;
  693.     }
  694.  
  695.     /* Make sure the new accent has changed */
  696.     if (new_accent_type == bmp->accent_type)
  697.     {
  698.          return;
  699.     }
  700.  
  701.     AccentErase(w);
  702.  
  703.     bmp->accent_type = new_accent_type;
  704.  
  705.     AccentDraw(w);
  706. }
  707. /*----------------------------------------------------------------------*/
  708. static void
  709. AccentDraw(Widget w)
  710. {
  711.     XfeBmButtonPart *     bmp = _XfeBmButtonPart(w);
  712.  
  713.     if (bmp->accent_type == XmACCENT_NONE || bmp->accent_type == XmACCENT_ALL)
  714.     {
  715.         return;
  716.     }
  717.  
  718.     XfeMenuItemDrawAccent(w,
  719.                           bmp->accent_type,
  720.                           XfeBmAccentGetOffsetLeft(),
  721.                           XfeBmAccentGetOffsetRight(),
  722.                           XfeBmAccentGetShadowThickness(),
  723.                           XfeBmAccentGetThickness());
  724. }
  725. /*----------------------------------------------------------------------*/
  726. static void
  727. AccentErase(Widget w)
  728. {
  729.     XfeBmButtonPart *     bmp = _XfeBmButtonPart(w);
  730.  
  731.     if (bmp->accent_type == XmACCENT_NONE || bmp->accent_type == XmACCENT_ALL)
  732.     {
  733.         return;
  734.     }
  735.  
  736.     XfeMenuItemEraseAccent(w,
  737.                            bmp->accent_type,
  738.                            XfeBmAccentGetOffsetLeft(),
  739.                            XfeBmAccentGetOffsetRight(),
  740.                            XfeBmAccentGetShadowThickness(),
  741.                            XfeBmAccentGetThickness());
  742. }
  743. /*----------------------------------------------------------------------*/
  744. /* extern */ void
  745. _XfeBmActionWithoutDrawing(Widget            w,
  746.                            XtActionProc        proc,
  747.                            XEvent *            event,
  748.                            char **            params,
  749.                            Cardinal *        nparams)
  750. {
  751.     Widget shell;
  752.     Window window;
  753.  
  754.     assert( _XfeIsAlive(w) );
  755.     assert( proc != NULL );
  756.  
  757.     shell = XfeAncestorFindByClass(w,shellWidgetClass,XfeFIND_ANY);
  758.  
  759.     window = _XfeWindow(w);
  760.  
  761.     /*
  762.      * We change the width to 0, so that the real Enter() 
  763.      * action does not draw anything in the cascade button so that
  764.      * we can draw the accent lines.
  765.      */
  766.     _XfeWindow(w) = _XfeWindow(shell);
  767.         
  768.     (*proc)(w,event,params,nparams);
  769.         
  770.     _XfeWindow(w) = window;
  771. }
  772. /*----------------------------------------------------------------------*/
  773. /* extern */ void
  774. _XfeBmProcWithoutDrawing(Widget w,XtWidgetProc proc)
  775. {
  776.     Widget shell;
  777.     Window window;
  778.  
  779.     assert( _XfeIsAlive(w) );
  780.     assert( proc != NULL );
  781.  
  782.     /*
  783.      * We pretend that the closest shell's window is the button's.  This is 
  784.      * a hack so that the widget procedure 'proc' does not draw anything.
  785.      */
  786.     shell = XfeAncestorFindByClass(w,shellWidgetClass,XfeFIND_ANY);
  787.  
  788.     window = _XfeWindow(w);
  789.  
  790.     /*
  791.      * We change the width to 0, so that the real Enter() 
  792.      * action does not draw anything in the cascade button so that
  793.      * we can draw the accent lines.
  794.      */
  795.     _XfeWindow(w) = _XfeWindow(shell);
  796.         
  797.     (*proc)(w);
  798.         
  799.     _XfeWindow(w) = window;
  800. }
  801. /*----------------------------------------------------------------------*/
  802.  
  803. /*----------------------------------------------------------------------*/
  804. /*                                                                        */
  805. /* XfeBmButton public functions                                            */
  806. /*                                                                        */
  807. /*----------------------------------------------------------------------*/
  808. /*extern*/ Widget
  809. XfeCreateBmButton(Widget pw,char * name,Arg * av,Cardinal ac)
  810. {
  811.     return XtCreateWidget(name,xfeBmButtonWidgetClass,pw,av,ac);
  812. }
  813. /*----------------------------------------------------------------------*/
  814.  
  815. /*----------------------------------------------------------------------*/
  816. /*                                                                        */
  817. /* Accent enabled/disabled functions                                    */
  818. /*                                                                        */
  819. /*----------------------------------------------------------------------*/
  820. static Boolean _accent_is_enabled = False;
  821.  
  822. /* extern */ Boolean
  823. XfeBmAccentIsEnabled(void)
  824. {
  825.     return _accent_is_enabled;
  826. }
  827. /*----------------------------------------------------------------------*/
  828. /* extern */ void
  829. XfeBmAccentDisable(void)
  830. {
  831.     _accent_is_enabled = False;
  832. }
  833. /*----------------------------------------------------------------------*/
  834. /* extern */ void
  835. XfeBmAccentEnable(void)
  836. {
  837.     _accent_is_enabled = True;
  838. }
  839. /*----------------------------------------------------------------------*/
  840.  
  841. /*----------------------------------------------------------------------*/
  842. /*                                                                        */
  843. /* Global BmButton/BmCascade accent offset values set/get functions        */
  844. /*                                                                        */
  845. /*----------------------------------------------------------------------*/
  846. static Dimension    _accent_offset_left            = 4;
  847. static Dimension    _accent_offset_right        = 8;
  848. static Dimension    _accent_shadow_thickness    = 1;
  849. static Dimension    _accent_thickness            = 1;
  850.  
  851. /* extern */ void
  852. XfeBmAccentSetOffsetLeft(Dimension offset_left)
  853. {
  854.     _accent_offset_left = offset_left;
  855. }
  856. /*----------------------------------------------------------------------*/
  857. /* extern */ void
  858. XfeBmAccentSetOffsetRight(Dimension offset_right)
  859. {
  860.     _accent_offset_right = offset_right;
  861. }
  862. /*----------------------------------------------------------------------*/
  863. /* extern */ void
  864. XfeBmAccentSetShadowThickness(Dimension shadow_thickness)
  865. {
  866.     _accent_shadow_thickness = shadow_thickness;
  867. }
  868. /*----------------------------------------------------------------------*/
  869. /* extern */ void
  870. XfeBmAccentSetThickness(Dimension thickness)
  871. {
  872.     _accent_thickness = thickness;
  873. }
  874. /*----------------------------------------------------------------------*/
  875. /* extern */ Dimension
  876. XfeBmAccentGetOffsetLeft(void)
  877. {
  878.     return _accent_offset_left;
  879. }
  880. /*----------------------------------------------------------------------*/
  881. /* extern */ Dimension
  882. XfeBmAccentGetOffsetRight(void)
  883. {
  884.     return _accent_offset_right;
  885. }
  886. /*----------------------------------------------------------------------*/
  887. /* extern */ Dimension
  888. XfeBmAccentGetShadowThickness(void)
  889. {
  890.     return _accent_shadow_thickness;
  891. }
  892. /*----------------------------------------------------------------------*/
  893. /* extern */ Dimension
  894. XfeBmAccentGetThickness(void)
  895. {
  896.     return _accent_thickness;
  897. }
  898. /*----------------------------------------------------------------------*/
  899.  
  900. /*----------------------------------------------------------------------*/
  901. /*                                                                        */
  902. /* Global BmButton/BmCascade accent filing mode.                        */
  903. /*                                                                        */
  904. /*----------------------------------------------------------------------*/
  905. static XfeAccentFileMode    _accent_file_mode = XmACCENT_FILE_ANYWHERE;
  906.  
  907. /* extern */ void
  908. XfeBmAccentSetFileMode(XfeAccentFileMode file_mode)
  909. {
  910.     _accent_file_mode = file_mode;
  911. }
  912. /*----------------------------------------------------------------------*/
  913. /* extern */ XfeAccentFileMode
  914. XfeBmAccentGetFileMode(void)
  915. {
  916.     return _accent_file_mode;
  917. }
  918. /*----------------------------------------------------------------------*/
  919.  
  920. /*----------------------------------------------------------------------*/
  921. /*                                                                        */
  922. /* Global BmButton/BmCascade pixmap offset values set/get functions        */
  923. /*                                                                        */
  924. /*----------------------------------------------------------------------*/
  925. static Dimension    _pixmap_offset = 4;
  926.  
  927. /* extern */ void
  928. XfeBmPixmapSetOffset(Dimension offset)
  929. {
  930.     _pixmap_offset = offset;
  931. }
  932. /*----------------------------------------------------------------------*/
  933. /* extern */ Dimension
  934. XfeBmPixmapGetOffset(void)
  935. {
  936.     return _pixmap_offset;
  937. }
  938. /*----------------------------------------------------------------------*/
  939.