home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xtici.zip / xtici / widgets / Hvcleaf.c < prev    next >
C/C++ Source or Header  |  1991-08-28  |  22KB  |  693 lines

  1. /*
  2.  * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
  3.  *     All Rights Reserved
  4.  * 
  5.  * This file is a component of an X Window System client which uses the Xcms 
  6.  * Color Management System.  TekColor is a trademark of Tektronix, Inc.  The
  7.  * TekColor Editor is the subject of U.S. and foreign patents pending.  The
  8.  * term "TekHVC" designates a particular color space that is the subject of
  9.  * U.S. Patent No. 4,985,853 (equivalent foreign patents pending).
  10.  * Permission is hereby granted to use, copy, modify, sell, and otherwise
  11.  * distribute this software and its documentation for the X Window System
  12.  * environment, for any purpose and without fee, provided that:
  13.  * 
  14.  * 1.    The code and documentation are only used to implement a 
  15.  *      TekColor Editor in an X Window System environment; and
  16.  * 2.    This copyright and permission notice is reproduced in all copies
  17.  *     of the code and in supporting documentation.
  18.  * 
  19.  * Permission is granted to modify this code as required to allow it to
  20.  * be compiled on any host computer, provided that the functionality of
  21.  * the TekColor Editor is not modified in any way.  A description of any 
  22.  * modifications must be sent to Tektronix, Inc.  Contact 
  23.  * Tektronix Inc., P.O. Box 1000, Mail Station 60-850, 
  24.  * Network Displays Division Engineering, Wilsonville, OR 97070.
  25.  *
  26.  * Tektronix makes no representation about the suitability of this software
  27.  * for any purpose.  It is provided "as is" and with all faults.
  28.  * 
  29.  * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
  30.  * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  31.  * PARTICULAR PURPOSE.  IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
  32.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  33.  * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
  34.  * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  35.  * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
  36.  *  
  37.  *  
  38.  *    NAME
  39.  *        Hvcleaf.c -- The HvcleafWidget to hold the HuelafWidget
  40.  *
  41.  *    DESCRIPTION
  42.  *        
  43.  *
  44.  *    HISTORY
  45.  *
  46.  *    HISTORY END
  47.  *
  48.  */
  49.  
  50. #ifndef LINT
  51. static char *copy_notice = "Copyright 1991 Tektronix, Inc.";
  52. #ifdef RCS_ID
  53. static char *rcsid=  "$Header: Hvcleaf.c,v 1.2 91/08/22 11:36:59 adamsc Exp $";
  54. #endif /* RCS_ID */
  55. #endif /* LINT */
  56.  
  57. #include <stdio.h>
  58. #include <X11/IntrinsicP.h>
  59. #include <X11/StringDefs.h>
  60. #include <X11/Xmu/Misc.h>
  61. #include <X11/Xaw/XawInit.h>
  62. #include <X11/Xaw/Form.h>
  63. #include <X11/Xaw/Label.h>
  64. #include "HvcleafP.h"
  65. #include "Hueleaf.h"
  66. #include "RepeatB.h"
  67.  
  68. #ifndef EPS
  69. #define EPS 0.001
  70. #endif
  71.  
  72. static XtResource resources[] = {
  73. #define offset(field) XtOffset(HvcleafWidget, hvcleaf.field)
  74.     /* {name, class, type, size, offset, default_type, default_addr}, */
  75.     { XtNhvc, XtCHvc, XtRHvc, sizeof(XcmsColor *),
  76.       offset(pHvc), XtRImmediate, (XtPointer)NULL },
  77.     { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  78.       offset(fgpixel), XtRImmediate, (XtPointer)XtDefaultForeground },
  79.     { XtNbase, XtCBase, XtRPixel, sizeof(Pixel),
  80.       offset(base), XtRImmediate, (XtPointer)-1 },
  81.     { XtNactivateCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
  82.       offset(activate), XtRImmediate, (XtPointer)NULL }
  83. #undef offset
  84. };
  85.  
  86. /* forward declarations for the class struct */
  87. static void ChangeManaged();
  88. static void Initialize();
  89. static void Resize();
  90. static Boolean SetValues();
  91. static XtGeometryResult GeometryManager();
  92. static XtGeometryResult QueryGeometry();
  93.  
  94. HvcleafClassRec hvcleafClassRec = {
  95.     { /* Core fields */
  96.     /* superclass        */    (WidgetClass) &compositeClassRec,
  97.     /* class_name        */    "Leaf",
  98.     /* widget_size        */    sizeof(HvcleafRec),
  99.     /* class_initialize        */    XawInitializeWidgetSet,
  100.     /* class_part_initialize    */    NULL,
  101.     /* class_inited        */    FALSE,
  102.     /* initialize        */    Initialize,
  103.     /* initialize_hook        */    NULL,
  104.     /* realize            */    XtInheritRealize,
  105.     /* actions            */    NULL,
  106.     /* num_actions        */    0,
  107.     /* resources        */    resources,
  108.     /* num_resources        */    XtNumber(resources),
  109.     /* xrm_class        */    NULLQUARK,
  110.     /* compress_motion        */    TRUE,
  111.     /* compress_exposure    */    TRUE,
  112.     /* compress_enterleave    */    TRUE,
  113.     /* visible_interest        */    FALSE,
  114.     /* destroy            */    NULL,
  115.     /* resize            */    Resize,
  116.     /* expose            */    NULL,
  117.     /* set_values        */    SetValues,
  118.     /* set_values_hook        */    NULL,
  119.     /* set_values_almost    */    XtInheritSetValuesAlmost,
  120.     /* get_values_hook        */    NULL,
  121.     /* accept_focus        */    NULL,
  122.     /* version            */    XtVersion,
  123.     /* callback_private        */    NULL,
  124.     /* tm_table            */    NULL,
  125.     /* query_geometry        */    QueryGeometry,
  126.     /* display_accelerator    */    NULL,
  127.     /* extension        */    NULL
  128.   },
  129.   { /* Composite fields */
  130.     /* geometry_manager        */    GeometryManager,
  131.     /* change_managed           */    ChangeManaged,
  132.     /* insert_child             */    XtInheritInsertChild,
  133.     /* delete_child             */    XtInheritDeleteChild,
  134.     /* extension                */    NULL
  135.   },
  136.   { /* hvcleaf fields */
  137.     /* extension        */    NULL
  138.   }
  139. };
  140.  
  141. WidgetClass hvcleafWidgetClass = (WidgetClass)&hvcleafClassRec;
  142.  
  143. /****************************************************************
  144.  *
  145.  * Private Routines
  146.  *
  147.  ****************************************************************/
  148. /*
  149.  *  Sometime in the future this geometry management could be simplified
  150.  *  for now just use the box routines.
  151.  *
  152.  * Do a layout, either actually assigning positions, or just calculating size.
  153.  * Returns minimum width and height that will preserve the same layout.
  154.  *
  155.  */
  156.  
  157. static DoLayout(hlw, width, height, reply_width, reply_height, position)
  158.     HvcleafWidget    hlw;
  159.     Dimension    width, height;
  160.     Dimension    *reply_width, *reply_height; /* bounding box */
  161.     Boolean    position;    /* actually reposition the windows? */
  162. {
  163.     Cardinal  i;
  164.     Dimension w, h;    /* Width and height needed for widget         */
  165.     Dimension lw, lh;    /* Width and height needed for current line     */
  166.     Dimension bw, bh;    /* Width and height needed for current widget     */
  167.     register Widget widget;    /* Current widget             */
  168.     int num_mapped_children = 0;
  169.  
  170.     /* Hvcleaf width and height */
  171.     w = 0;
  172.     h = 0;
  173.    
  174.     /* Line width and height */
  175.     lh = 0;
  176.     lw = 0;
  177.   
  178.     for (i = 0; i < hlw->composite.num_children; i++) {
  179.     widget = hlw->composite.children[i];
  180.     if (widget->core.managed) {
  181.         if (widget->core.mapped_when_managed) 
  182.         num_mapped_children++;
  183.         /* Compute widget width */
  184.         bw = widget->core.width + 2*widget->core.border_width;
  185.         if (lw + bw > width) {
  186.         if (lw != 0) {
  187.             /* At least one widget on this line, and
  188.              * can't fit any more.  Start new line.
  189.              */
  190.             AssignMax(w, lw);
  191.             h += lh;
  192.             lh = 0;
  193.             lw = 0;
  194.         } else if (!position) {
  195.             /* too narrow for this widget; we'll assume we can grow */
  196.             DoLayout(hlw, lw + bw, height, reply_width,
  197.                  reply_height, position);
  198.             return;
  199.         }
  200.         }
  201.         if (position && (lw != widget->core.x || h != widget->core.y)) {
  202.         /* It would be nice to use window gravity, but there isn't
  203.          * sufficient fine-grain control to nicely handle all
  204.          * situations (e.g. when only the height changes --
  205.          * a common case).  Explicit unmapping is a cheap hack
  206.          * to speed things up & avoid the visual jitter as
  207.          * things slide around.
  208.          *
  209.          * %%% perhaps there should be a client resource to
  210.          * control this.  If so, we'll have to optimize to
  211.          * perform the moves from the correct end so we don't
  212.          * force extra exposures as children occlude each other.
  213.          */
  214.         if (XtIsRealized(widget) && widget->core.mapped_when_managed)
  215.             XUnmapWindow( XtDisplay(widget), XtWindow(widget) );
  216.         XtMoveWidget(widget, (int)lw, (int)h);
  217.         }
  218.         lw += bw;
  219.         bh = widget->core.height + 2*widget->core.border_width;
  220.         AssignMax(lh, bh);
  221.     } /* if managed */
  222.     } /* for */
  223.  
  224.     if (position && XtIsRealized((Widget)hlw)) {
  225.     if (hlw->composite.num_children == num_mapped_children)
  226.         XMapSubwindows( XtDisplay((Widget)hlw), XtWindow((Widget)hlw) );
  227.     else {
  228.         int i = hlw->composite.num_children;
  229.         register Widget *childP = hlw->composite.children;
  230.         for (; i > 0; childP++, i--)
  231.         if (XtIsRealized(*childP) && XtIsManaged(*childP) &&
  232.             (*childP)->core.mapped_when_managed)
  233.             XtMapWidget(*childP);
  234.     }
  235.     }
  236.  
  237.     /* Finish off last line */
  238.     if (lw != 0) {
  239.     AssignMax(w, lw);
  240.         h += lh;
  241.     }
  242.  
  243.     *reply_width = Max(w, 1);
  244.     *reply_height = Max(h, 1);
  245. }
  246.  
  247. /*
  248.  *
  249.  * Calculate preferred size, given constraining box, caching it in the widget.
  250.  *
  251.  */
  252.  
  253. static XtGeometryResult QueryGeometry(widget, constraint, preferred)
  254.     Widget widget;
  255.     XtWidgetGeometry *constraint, *preferred;
  256. {
  257.     HvcleafWidget w = (HvcleafWidget)widget;
  258.     Dimension width /*, height */;
  259.     Dimension preferred_width = w->hvcleaf.preferred_width;
  260.     Dimension preferred_height = w->hvcleaf.preferred_height;
  261.  
  262.     constraint->request_mode &= CWWidth | CWHeight;
  263.  
  264.     if (constraint->request_mode == 0)
  265.     /* parent isn't going to change w or h, so nothing to re-compute */
  266.     return XtGeometryYes;
  267.  
  268.     if (constraint->request_mode == w->hvcleaf.last_query_mode &&
  269.     (!(constraint->request_mode & CWWidth) ||
  270.      constraint->width == w->hvcleaf.last_query_width) &&
  271.     (!(constraint->request_mode & CWHeight) ||
  272.      constraint->height == w->hvcleaf.last_query_height)) {
  273.     /* same query; current preferences are still valid */
  274.     preferred->request_mode = CWWidth | CWHeight;
  275.     preferred->width = preferred_width;
  276.     preferred->height = preferred_height;
  277.     if (constraint->request_mode == (CWWidth | CWHeight) &&
  278.         constraint->width == preferred_width &&
  279.         constraint->height == preferred_height)
  280.         return XtGeometryYes;
  281.     else
  282.         return XtGeometryAlmost;
  283.     }
  284.     
  285.     /* else gotta do it the long way...
  286.        I have a preference for tall and narrow, so if my width is
  287.        constrained, I'll accept it; otherwise, I'll compute the minimum
  288.        width that will fit me within the height constraint */
  289.  
  290.     w->hvcleaf.last_query_mode = constraint->request_mode;
  291.     w->hvcleaf.last_query_width = constraint->width;
  292.     w->hvcleaf.last_query_height= constraint->height;
  293.  
  294.     if (constraint->request_mode & CWWidth)
  295.     width = constraint->width;
  296.     else { /* if (constraint->request_mode & CWHeight) */ 
  297.        /* let's see if I can become any narrower */
  298.     width = 0;
  299.     constraint->width = 65535;
  300.     }
  301.  
  302.     /* height is currently ignored by DoLayout.
  303.        height = (constraint->request_mode & CWHeight) ? constraint->height
  304.                : *preferred_height;
  305.      */
  306.     DoLayout(w, width, (Dimension)0, &preferred_width, &preferred_height, 
  307.         FALSE);
  308.  
  309.     if (constraint->request_mode & CWHeight &&
  310.     preferred_height > constraint->height) {
  311.     /* find minimum width for this height */
  312.     if (preferred_width > constraint->width) {
  313.         /* punt; over-constrained */
  314.     } else {
  315.         width = preferred_width;
  316.         do { /* find some width big enough to stay within this height */
  317.         width *= 2;
  318.         if (width > constraint->width) 
  319.             width = constraint->width;
  320.         DoLayout(w, width, 0, &preferred_width, &preferred_height, FALSE);
  321.         } while (preferred_height > constraint->height &&
  322.              width < constraint->width);
  323.         if (width != constraint->width) {
  324.         do { /* find minimum width */
  325.             width = preferred_width;
  326.             DoLayout(w, preferred_width-1, 0,
  327.                  &preferred_width, &preferred_height, FALSE);
  328.         } while (preferred_height < constraint->height);
  329.         /* one last time */
  330.         DoLayout(w, width, 0, &preferred_width, &preferred_height, FALSE);
  331.         }
  332.     }
  333.     }
  334.  
  335.     preferred->request_mode = CWWidth | CWHeight;
  336.     preferred->width = w->hvcleaf.preferred_width = preferred_width;
  337.     preferred->height = w->hvcleaf.preferred_height = preferred_height;
  338.  
  339.     if (constraint->request_mode == (CWWidth|CWHeight)
  340.     && constraint->width == preferred_width
  341.     && constraint->height == preferred_height)
  342.     return XtGeometryYes;
  343.     else
  344.     return XtGeometryAlmost;
  345. }
  346.  
  347. /*
  348.  *
  349.  * Actually layout the widget
  350.  *
  351.  */
  352.  
  353. static void Resize(w)
  354.     Widget    w;
  355. {
  356.     Dimension junk;
  357.     Widget form = ((HvcleafWidget)w)->hvcleaf.form;
  358.  
  359.     DoLayout((HvcleafWidget)w, w->core.width, w->core.height, &junk, &junk, 
  360.         TRUE);
  361.  
  362.     XtResizeWidget(form, w->core.width, w->core.height, 
  363.            form->core.border_width);
  364. } /* Resize */
  365.  
  366. /*
  367.  *
  368.  * Try to do a new layout within the current width and height;
  369.  * if that fails try to resize and do it within the size returned
  370.  * by QueryGeometry.
  371.  *
  372.  * TryNewLayout just says if it's possible, and doesn't actually move the kids
  373.  */
  374.  
  375. static Boolean TryNewLayout(hlw)
  376.     HvcleafWidget    hlw;
  377. {
  378.     Dimension     preferred_width, preferred_height;
  379.     Dimension    proposed_width, proposed_height;
  380.     int        iterations;
  381.  
  382.     DoLayout( hlw, hlw->core.width, hlw->core.height,
  383.           &preferred_width, &preferred_height, FALSE );
  384.  
  385.     /* at this point, preferred_width is guaranteed to not be greater
  386.        than hlw->core.width unless some child is larger, so there's no
  387.        point in re-computing another layout */
  388.  
  389.     if ((hlw->core.width == preferred_width) &&
  390.     (hlw->core.height == preferred_height)) {
  391.         /* Same size */
  392.     return (TRUE);
  393.     }
  394.  
  395.     /* let's see if our parent will go for a new size. */
  396.     iterations = 0;
  397.     proposed_width = preferred_width;
  398.     proposed_height = preferred_height;
  399.     do {
  400.     switch (XtMakeResizeRequest((Widget)hlw,proposed_width,proposed_height,
  401.                      &proposed_width, &proposed_height))
  402.     {
  403.         case XtGeometryYes:
  404.         return (TRUE);
  405.  
  406.         case XtGeometryNo:
  407.         if (iterations > 0)
  408.             /* protect from malicious parents who change their minds */
  409.             DoLayout( hlw, hlw->core.width, hlw->core.height,
  410.                   &preferred_width, &preferred_height, FALSE );
  411.         if ((preferred_width <= hlw->core.width) &&
  412.             (preferred_height <= hlw->core.height))
  413.             return (TRUE);
  414.         else
  415.             return (FALSE);
  416.  
  417.         case XtGeometryAlmost:
  418.         if (proposed_height >= preferred_height &&
  419.             proposed_width >= preferred_width) {
  420.  
  421.             /*
  422.              * Take it, and assume the parent knows what it is doing.
  423.              *
  424.              * The parent must accept this since it was returned in
  425.              * almost.
  426.              *
  427.              */
  428.             (void) XtMakeResizeRequest( (Widget)hlw,
  429.                        proposed_width, proposed_height,
  430.                        &proposed_width, &proposed_height);
  431.             return(TRUE);
  432.         }
  433.         else if (proposed_width != preferred_width) {
  434.             /* recalc bounding box; height might change */
  435.             DoLayout(hlw, proposed_width, 0,
  436.                  &preferred_width, &preferred_height, FALSE);
  437.             proposed_height = preferred_height;
  438.         }
  439.         else { /* proposed_height != preferred_height */
  440.             XtWidgetGeometry constraints, reply;
  441.             constraints.request_mode = CWHeight;
  442.             constraints.height = proposed_height;
  443.             (void)QueryGeometry((Widget)hlw, &constraints, &reply);
  444.             proposed_width = preferred_width;
  445.         }
  446.     }
  447.     iterations++;
  448.     } while (iterations < 10);
  449.     return (FALSE);
  450. }
  451.  
  452. /*
  453.  *
  454.  * Geometry Manager
  455.  *
  456.  * 'reply' is unused; we say only yeay or nay, never almost.
  457.  *
  458.  */
  459.  
  460. /*ARGSUSED*/
  461. static XtGeometryResult GeometryManager(w, request, reply)
  462.     Widget        w;
  463.     XtWidgetGeometry    *request;
  464.     XtWidgetGeometry    *reply;    /* RETURN */
  465.  
  466. {
  467.     Dimension    width, height, borderWidth;
  468.     HvcleafWidget hlw;
  469.  
  470.     /* Position request always denied */
  471.     if ((request->request_mode & CWX && request->x != w->core.x) ||
  472.     (request->request_mode & CWY && request->y != w->core.y))
  473.         return (XtGeometryNo);
  474.  
  475.     /* Size changes must see if the new size can be accomodated */
  476.     if (request->request_mode & (CWWidth | CWHeight | CWBorderWidth)) {
  477.     /* Make all three fields in the request valid */
  478.     if ((request->request_mode & CWWidth) == 0)
  479.         request->width = w->core.width;
  480.     if ((request->request_mode & CWHeight) == 0)
  481.         request->height = w->core.height;
  482.         if ((request->request_mode & CWBorderWidth) == 0)
  483.         request->border_width = w->core.border_width;
  484.  
  485.     /* Save current size and set to new size */
  486.     width = w->core.width;
  487.     height = w->core.height;
  488.     borderWidth = w->core.border_width;
  489.     w->core.width = request->width;
  490.     w->core.height = request->height;
  491.     w->core.border_width = request->border_width;
  492.  
  493.     /* Decide if new layout works: (1) new widget is smaller,
  494.        (2) new widget fits in existing Hvcleaf, (3) Hvcleaf can be
  495.        expanded to allow new widget to fit */
  496.     hlw = (HvcleafWidget) w->core.parent;
  497.  
  498.     if (TryNewLayout(hlw)) {
  499.         /* Fits in existing or new space, relayout */
  500.         (*XtClass((Widget)hlw)->core_class.resize)((Widget)hlw);
  501.         return (XtGeometryYes);
  502.     } else {
  503.         /* Cannot satisfy request, change back to original geometry */
  504.         w->core.width = width;
  505.         w->core.height = height;
  506.         w->core.border_width = borderWidth;
  507.         return (XtGeometryNo);
  508.     }
  509.     } /* if any size changes requested */
  510.  
  511.     /* Any stacking changes don't make a difference, so allow if that's all */
  512.     return (XtGeometryYes);
  513. }
  514.  
  515. static void ChangeManaged(w)
  516.     Widget w;
  517. {
  518.     /* Reconfigure the widget */
  519.     (void) TryNewLayout((HvcleafWidget)w);
  520.     Resize(w);
  521. }
  522.  
  523. /* ARGSUSED */
  524. static void HvcActivate(widget, which, call) 
  525. Widget widget;
  526. XtPointer which;
  527. XtPointer call;
  528. {
  529.     Widget hw = widget;
  530.  
  531.     while (hw) {
  532.     if (IsHvcleaf(hw))
  533.         break;
  534.     hw = XtParent(hw);
  535.     }
  536.     if (!hw)
  537.     return;
  538.     XtCallCallbacks (hw, XtNactivateCallback, call);
  539. }
  540.  
  541. static void CreateChildren(new)
  542. HvcleafWidget new;
  543. {
  544.     Arg  args[10];
  545.     WidgetList wlist = new->hvcleaf.wlist;
  546.     Widget form;
  547.     int  cnt;
  548.  
  549.     cnt = 0;
  550.     XtSetArg(args[cnt], XtNborderWidth, 0);            cnt++;
  551.     XtSetArg(args[cnt], XtNwidth, new->core.width);        cnt++;
  552.     XtSetArg(args[cnt], XtNheight, new->core.height);        cnt++;
  553.     form = XtCreateManagedWidget ("hvcform", formWidgetClass, (Widget)new,
  554.                   args, cnt);
  555.     new->hvcleaf.form = form;
  556.  
  557.     cnt = 0;
  558.     XtSetArg(args[cnt], XtNlabel, "VALUE");                     cnt++;
  559.     XtSetArg (args[cnt], XtNvertDistance, 125);            cnt++;
  560.     XtSetArg (args[cnt], XtNresizable, True);            cnt++;
  561.     wlist[ValueLabel] = XtCreateWidget("value", labelWidgetClass, form,
  562.                     args, cnt);
  563.  
  564.     /* this is the up repeater button for the value up arrow */
  565.     cnt = 0;
  566.     XtSetArg (args[cnt], XtNvertDistance, 116);            cnt++;
  567.     XtSetArg (args[cnt], XtNfromHoriz, wlist[ValueLabel]);    cnt++;
  568.     XtSetArg (args[cnt], XtNarrowDirection, XtorientationUp);    cnt++;
  569.     XtSetArg (args[cnt], XtNresizable, True);            cnt++;
  570.     wlist[UpArrow] = XtCreateWidget("uparrow", repeaterButtonClass, form,
  571.                     args, cnt);
  572.  
  573.     /* this is the down repeater button for the value down arrow */
  574.     cnt = 0;
  575.     XtSetArg (args[cnt], XtNfromVert, wlist[UpArrow]);        cnt++;
  576.     XtSetArg (args[cnt], XtNfromHoriz, wlist[ValueLabel]);    cnt++;
  577.     XtSetArg (args[cnt], XtNarrowDirection, XtorientationDown);    cnt++;
  578.     XtSetArg (args[cnt], XtNresizable, True);            cnt++;
  579.     wlist[DownArrow] = XtCreateWidget("downarrow", repeaterButtonClass, form,
  580.                     args, cnt);
  581.  
  582.     cnt = 0;
  583.     XtSetArg (args[cnt], XtNwidth, 255);            cnt++;
  584.     XtSetArg (args[cnt], XtNheight, 255);            cnt++;
  585.     XtSetArg (args[cnt], XtNfromHoriz, wlist[UpArrow]);        cnt++;
  586.     XtSetArg (args[cnt], XtNresizable, True);            cnt++;
  587.     if (new->hvcleaf.pHvc) {
  588.     XtSetArg (args[cnt], XtNhvc, new->hvcleaf.pHvc);    cnt++;
  589.     }
  590.     wlist[HueLeaf] = XtCreateWidget("hueleaf", hueleafWidgetClass, form,
  591.                     args, cnt);
  592.     XtAddCallback (wlist[HueLeaf], XtNactivateCallback, HvcActivate, NULL);
  593.  
  594.     /* this is the left repeater button for the chroma left arrow */
  595.     cnt = 0;
  596.     XtSetArg (args[cnt], XtNhorizDistance, 115);            cnt++;
  597.     XtSetArg (args[cnt], XtNfromHoriz, wlist[UpArrow]);        cnt++;
  598.     XtSetArg (args[cnt], XtNfromVert, wlist[HueLeaf]);        cnt++;
  599.     XtSetArg (args[cnt], XtNarrowDirection, XtorientationLeft);    cnt++;
  600.     XtSetArg (args[cnt], XtNresizable, True);            cnt++;
  601.     wlist[LeftArrow] = XtCreateWidget("leftarrow", repeaterButtonClass, form,
  602.                     args, cnt);
  603.     
  604.     /* this is the right repeater button for the chroma right arrow */
  605.     cnt = 0;
  606.     XtSetArg (args[cnt], XtNfromHoriz, wlist[LeftArrow]);    cnt++;
  607.     XtSetArg (args[cnt], XtNfromVert, wlist[HueLeaf]);        cnt++;
  608.     XtSetArg (args[cnt], XtNarrowDirection, XtorientationRight);    cnt++;
  609.     XtSetArg (args[cnt], XtNresizable, True);            cnt++;
  610.     wlist[RightArrow] = XtCreateWidget("rightarrow", repeaterButtonClass, form,
  611.                     args, cnt);
  612.  
  613.     cnt = 0;
  614.     XtSetArg(args[cnt], XtNlabel, "CHROMA");            cnt++;
  615.     XtSetArg (args[cnt], XtNhorizDistance, 90);            cnt++;
  616.     XtSetArg (args[cnt], XtNfromHoriz, wlist[UpArrow]);        cnt++;
  617.     XtSetArg (args[cnt], XtNfromVert, wlist[LeftArrow]);    cnt++;
  618.     XtSetArg (args[cnt], XtNresizable, True);            cnt++;
  619.     wlist[ChromaLabel] = XtCreateWidget("chroma", labelWidgetClass, form,
  620.                     args, cnt);
  621.     
  622.     XtManageChildren (wlist, HvcLeafChildCt);
  623.     new->hvcleaf.numchildren = HvcLeafChildCt;
  624. }
  625.  
  626. static void Initialize(req, new)
  627. HvcleafWidget req, new;
  628. {
  629.     HvcleafWidget leaf;
  630.     XcmsFloat tmp;
  631.  
  632.     if (req->core.width == 0)
  633.     new->core.width = 100;
  634.     if (req->core.height == 0)
  635.     new->core.height = 100;
  636.  
  637.     new->hvcleaf.aspect = 1.0;
  638.  
  639.     CreateChildren(new);
  640.  
  641.     leaf = (HvcleafWidget)new->hvcleaf.wlist[HueLeaf];
  642.     if (req->core.width == 0)
  643.     new->core.width = leaf->core.width;
  644.     if (req->core.height == 0)
  645.     new->core.height = leaf->core.height;
  646.  
  647.     if (new->core.width < leaf->core.width)
  648.     new->core.width = leaf->core.width;
  649.     if (new->core.height < leaf->core.height)
  650.     new->core.height = leaf->core.height;
  651.  
  652.     tmp = (XcmsFloat)new->core.width / (XcmsFloat)new->core.height;
  653.  
  654.     if (tmp < 1.0 - EPS || tmp > 1.0 + EPS) {
  655.     if (new->core.width > new->core.height) {
  656.         new->core.width = new->core.height;
  657.     } else {
  658.         new->core.height = new->core.width;
  659.     }
  660.     }
  661.  
  662.     new->hvcleaf.preferred_width = 0;
  663.     new->hvcleaf.preferred_height = 0;
  664.     new->hvcleaf.last_query_mode = 0;
  665. }
  666.  
  667. /*
  668.  * Always draw ourselves if needed, so we can avoid redrawing shadows.
  669.  * This means we always return false, of course.
  670.  */
  671. /* ARGSUSED */
  672. static Boolean SetValues(cur, req, new)
  673. HvcleafWidget cur, req, new;
  674. {
  675.     Arg  args[10];
  676.     Widget leaf;
  677.     int  cnt = 0;
  678.  
  679.     if (new->hvcleaf.pHvc && new->hvcleaf.pHvc != cur->hvcleaf.pHvc) {
  680.     XtSetArg (args[cnt], XtNhvc, new->hvcleaf.pHvc);      cnt++;
  681.     }
  682.     if (new->hvcleaf.base != cur->hvcleaf.base) {
  683.     XtSetArg (args[cnt], XtNbase, new->hvcleaf.base);     cnt++;
  684.     }
  685.  
  686.     if (cnt) {
  687.     leaf = new->hvcleaf.wlist[HueLeaf];
  688.     XtSetValues (leaf, args, cnt);
  689.     }
  690.  
  691.     return (False);
  692. }
  693.