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 / Colorbar.c next >
C/C++ Source or Header  |  1991-08-28  |  14KB  |  483 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.  *        Colorbar.c -- the Colorbar Widget
  40.  *
  41.  *    DESCRIPTION
  42.  *        This widget will display a series of entries from the colormap.
  43.  *        It needs the lowest pixel, the increment value and the
  44.  *        number of pixels to display to be useful.  Note that 
  45.  *        the constraint of maximum width is a resource.
  46.  *
  47.  *    HISTORY
  48.  *
  49.  *    HISTORY END
  50.  *
  51.  */
  52.  
  53. #ifndef LINT
  54. static char *copy_notice = "Copyright 1991 Tektronix, Inc.";
  55. #ifdef RCS_ID
  56. static char *rcsid= "$Header: Colorbar.c,v 1.2 91/08/22 11:36:53 adamsc Exp $";
  57. #endif /* RCS_ID */
  58. #endif /* LINT */
  59.  
  60. #include <stdio.h>
  61. #include <X11/IntrinsicP.h>
  62. #include <X11/StringDefs.h>
  63. #include <X11/Shell.h>
  64. #include <X11/Xaw/SimpleP.h>
  65. #include <X11/Xmu/Misc.h>
  66. #include "ColorbarP.h"
  67.  
  68. /* static char defaultTranslations[] =
  69.  *    "<EnterWindow>:    highlight()        /n/
  70.  *     <LeaveWindow>:    reset()            /n/
  71.  *     <Btn1Down>:    set()            /n/
  72.  *     <Btn1Up>:    notify() unset()    ";
  73.  */
  74.  
  75. static char defaultTranslations[] =
  76.     "<Btn1Up>:        notify()";
  77.  
  78. static XtResource resources[] = {
  79. #define offset(field) XtOffset(ColorbarWidget, colorbar.field)
  80.     /* {name, class, type, size, offset, default_type, default_addr}, */
  81.     { XtNbase, XtCBase, XtRPixel, sizeof(Pixel),
  82.     offset(base), XtRImmediate, (XtPointer)0 },
  83.     { XtNlength, XtCLength, XtRInt, sizeof(int),
  84.     offset(length), XtRImmediate, (XtPointer)1 },
  85.     { XtNpixelInc, XtCPixelInc, XtRPixel,  sizeof(Pixel),
  86.         offset(pixelInc), XtRImmediate, (XtPointer)1 },
  87.     { XtNsingleSelectionCallback, XtCCallback, XtRCallback, 
  88.     sizeof(XtCallbackList), offset(select), XtRCallback, (XtPointer)NULL },
  89.     { XtNorientation, XtCOrientation, XtROrientation, sizeof(XtOrientation),
  90.     offset(orientation), XtRImmediate, (XtPointer)XtorientVertical },
  91.     { XtNmaxWidth, XtCMaxWidth, XtRDimension, sizeof(Dimension),
  92.     offset(max_width), XtRImmediate, (XtPointer)30 },
  93. #undef offset
  94. };
  95.  
  96. #define MIN_WIDTH   15
  97. #define MIN_HEIGHT  15
  98.  
  99. /* forward declarations for the class struct */
  100. static void Destroy();
  101. static void Exposed();
  102. static void HandleInput();
  103. static void Initialize();
  104. static void Notify();
  105. static void Resized();
  106. static Boolean SetValues();
  107. static XtGeometryResult PreferredGeometry();
  108.  
  109. static XtActionsRec actionsList[] = {
  110.     {"notify",        Notify}
  111. };
  112.  
  113. ColorbarWidgetClassRec colorbarWidgetClassRec = {
  114.   { /* core fields */
  115.     /* superclass        */    (WidgetClass) &simpleClassRec,
  116.     /* class_name        */    "Colorbar",
  117.     /* widget_size        */    sizeof(ColorbarWidgetRec),
  118.     /* class_initialize        */    NULL,
  119.     /* class_part_initialize    */    NULL,
  120.     /* class_inited        */    FALSE,
  121.     /* initialize        */    Initialize,
  122.     /* initialize_hook        */    NULL,
  123.     /* realize            */    XtInheritRealize,
  124.     /* actions            */    actionsList,
  125.     /* num_actions        */    XtNumber(actionsList),
  126.     /* resources        */    resources,
  127.     /* num_resources        */    XtNumber(resources),
  128.     /* xrm_class        */    NULLQUARK,
  129.     /* compress_motion        */    TRUE,
  130.     /* compress_exposure    */    TRUE,
  131.     /* compress_enterleave    */    TRUE,
  132.     /* visible_interest        */    FALSE,
  133.     /* destroy            */    Destroy,
  134.     /* resize            */    Resized,
  135.     /* expose            */    Exposed,
  136.     /* set_values        */    SetValues,
  137.     /* set_values_hook        */    NULL,
  138.     /* set_values_almost    */    XtInheritSetValuesAlmost,
  139.     /* get_values_hook        */    NULL,
  140.     /* accept_focus        */    NULL,
  141.     /* version            */    XtVersion,
  142.     /* callback_private        */    NULL,
  143.     /* tm_table            */    defaultTranslations,
  144.     /* query_geometry        */    PreferredGeometry,
  145.     /* display_accelerator    */    NULL,
  146.     /* extension        */    NULL
  147.   },
  148.   { /* simple fields */
  149.     /* change_sensitive        */    XtInheritChangeSensitive,
  150.   },
  151.   { /* colorbar fields */
  152.     /* extension        */    NULL
  153.   }
  154. };
  155.  
  156. WidgetClass colorbarWidgetClass = (WidgetClass)&colorbarWidgetClassRec;
  157.  
  158. /* forward declarations for utility functions */
  159. static void Draw();
  160. static void GetGC();
  161. static int GetMapSize();
  162.  
  163. static char *warning1 = "orientation is not vertical or horizontal";
  164. static char *warning3 = "length must be positive";
  165. static char *warning4 = "widget improperly initialized";
  166. static char *warning5 = "increment must be non-negative";
  167.  
  168. static void Destroy(cbar)
  169. ColorbarWidget cbar;
  170. {
  171.     if (cbar->colorbar.colorGC)
  172.     XFreeGC(XtDisplay(cbar), cbar->colorbar.colorGC);
  173. }
  174.  
  175. /*ARGSUSED*/
  176. static void Exposed(cbar, e, region)
  177. ColorbarWidget cbar;
  178. XEvent *e;
  179. Region region;
  180. {
  181.     Draw(cbar);
  182. }
  183. static void Warning (widget, message)
  184. Widget widget;
  185. char *message;
  186. {
  187.     /*  R4 says use XtAppWarningMsg but no information on how to set
  188.      *  the parameters. 
  189.      */
  190.     if (!widget)
  191.     XtWarning(message);
  192.     else
  193.     XtAppWarning(XtWidgetToApplicationContext(widget), message);
  194. }
  195.  
  196. static void Initialize(req, new)
  197. ColorbarWidget req, new;
  198. {
  199.     if ( (new->colorbar.orientation != XtorientVertical)
  200.         && (new->colorbar.orientation != XtorientHorizontal) ) {
  201.     Warning(new, warning1);
  202.     new->colorbar.orientation = XtorientVertical;
  203.     }
  204.  
  205.     if ((int)new->colorbar.length <= 0) {
  206.     Warning(new, warning3);
  207.     new->colorbar.length = 1;
  208.     }
  209.  
  210.     if ((int)new->colorbar.pixelInc <= 0) {
  211.     Warning(new, warning5);
  212.     new->colorbar.pixelInc = 1;
  213.     }
  214.  
  215.     if (req->core.width == 0)
  216.     new->core.width = MIN_WIDTH;
  217.     if (req->core.height == 0)
  218.     new->core.height = MIN_HEIGHT;
  219.  
  220.     if (new->core.width > req->colorbar.max_width)
  221.     new->core.width = req->colorbar.max_width;
  222.  
  223.     /* Building the GC is defered until we know there is a window, ie */
  224.     /* when the widget is first drawn */
  225.     new->colorbar.colorGC = 0;
  226. }
  227.  
  228. /*ARGSUSED*/
  229. static void Notify(wid, evnt, params, num_params)
  230. Widget wid;
  231. XEvent *evnt;
  232. String *params;         /* unused */
  233. Cardinal *num_params;   /* unused */
  234. {
  235.     /* Should we act on press or release?  Follow a drag ?? */
  236.     ColorbarWidget cbar = (ColorbarWidget)wid;
  237.  
  238.     HandleInput(cbar, (XButtonEvent *)evnt);
  239. }
  240.  
  241. static void Resized(cbar)
  242. ColorbarWidget cbar;
  243. {
  244.     XRectangle rect;
  245.  
  246.     /* TODO: could cache drawing parameters: step, inc, rem */
  247.     if (!cbar->colorbar.colorGC) 
  248.     return;
  249.     rect.x = cbar->core.border_width;
  250.     rect.y = cbar->core.border_width;
  251.     rect.width = cbar->core.width - 2 * cbar->core.border_width;
  252.     rect.height = cbar->core.height - 2 * cbar->core.border_width;
  253.     XSetClipRectangles(XtDisplay(cbar), cbar->colorbar.colorGC, 0, 0,
  254.             &rect, 1, YXBanded);
  255. }
  256.  
  257. /*ARGSUSED*/
  258. static Boolean SetValues(cur, req, new)
  259. ColorbarWidget cur, req, new;
  260. {
  261.     Boolean flag;
  262.  
  263.     if ( (new->colorbar.orientation != XtorientVertical)
  264.         && (new->colorbar.orientation != XtorientHorizontal) ) {
  265.     Warning(new, warning1);
  266.     new->colorbar.orientation = XtorientVertical;
  267.     }
  268.  
  269.     if (new->colorbar.length <= 0) {
  270.     Warning(new, warning3);
  271.     new->colorbar.length = 1;
  272.     }
  273.  
  274.     if ((int)new->colorbar.pixelInc <= 0) {
  275.     Warning(new, warning5);
  276.     new->colorbar.pixelInc = 1;
  277.     }
  278.  
  279.     flag = (new->colorbar.orientation != cur->colorbar.orientation)
  280.         || (new->colorbar.base != cur->colorbar.base)
  281.         || (new->colorbar.length != cur->colorbar.length);
  282.     return(flag);
  283. }
  284.  
  285. /*ARGSUSED*/
  286. static XtGeometryResult PreferredGeometry(widget, request, prefer)
  287. Widget widget;
  288. XtWidgetGeometry *request;
  289. XtWidgetGeometry *prefer;
  290. {
  291.     return (XtGeometryNo);
  292. }
  293.  
  294.  
  295.     /* this algorithm isn't terribly efficient, but it is simple */
  296. static void Draw(cbar)
  297. ColorbarWidget cbar;
  298. {
  299.     Display *dpy = XtDisplay(cbar);
  300.     Window win = XtWindow(cbar);
  301.     Pixel increment = cbar->colorbar.pixelInc;
  302.     int len = cbar->colorbar.length;
  303.     int width, height;
  304.     int step, rem, inc;
  305.     int run = 0;
  306.     int extent;
  307.     int i;
  308.     int size;
  309.     int pix = cbar->colorbar.base;
  310.     int x, y;
  311.  
  312.     if (!cbar->colorbar.colorGC) {
  313.     GetGC(cbar);
  314.     /* can now query visual of window, get size from visual */
  315.     size = GetMapSize(cbar);
  316.     } else
  317.     size = cbar->colorbar.mapSize;
  318.  
  319.     width = cbar->core.width - 2 * cbar->core.border_width;
  320.     height = cbar->core.height - 2 * cbar->core.border_width;
  321.     x = cbar->core.border_width;
  322.     y = cbar->core.border_width;
  323.  
  324.     /* Check if the widget is so small that colors aren't visible */
  325.     if ( (width <= 0) || (height <= 0) )
  326.     ;    /* prevent colors from drawing, but do allow border */
  327.     else if (cbar->colorbar.orientation == XtorientVertical) {
  328.     inc = 1;
  329.     step = height / len;
  330.     rem = height % len;
  331.     while (step < 1) {
  332.         inc++;
  333.         step = inc * height / len;
  334.         rem = (inc * height) % len;
  335.     }
  336.     extent = step + 1;  /* some pixels will get painted twice */
  337.     /* color from top to bottom */
  338.     pix += (len - 1) * increment;
  339.     if (pix >= size) 
  340.         pix = pix % size;
  341.     for (i = 0; i < len; i += inc) {
  342.         XSetForeground(dpy, cbar->colorbar.colorGC, pix);
  343.         XFillRectangle(dpy, win, cbar->colorbar.colorGC, x, y, 
  344.                 width, extent);
  345.         y += step;
  346.         run += rem;
  347.         if (run > len) {
  348.         y++;
  349.         run -= len;
  350.         }
  351.         pix -= increment;
  352.         if ((int)pix < 0)
  353.         pix = size - 1;
  354.     }
  355.     } else {
  356.     inc = 1;
  357.     step = width / len;
  358.     rem = width % len;
  359.     while (step < 4) {
  360.         inc++;
  361.         step = inc * width / len;
  362.         rem = (inc * width) % len;
  363.     }
  364.     extent = step + 1;  /* some pixels will get painted twice */
  365.     /* color from left to right */
  366.     for (i = 0; i < len; i += inc) {
  367.         XSetForeground(dpy, cbar->colorbar.colorGC, pix);
  368.         XFillRectangle(dpy, win, cbar->colorbar.colorGC, x, y, 
  369.                 extent, height);
  370.         x += step;
  371.         run += rem;
  372.         if (run > len) {
  373.         x++;
  374.         run -= len;
  375.         }
  376.         pix += increment;
  377.         if (pix >= size)
  378.         pix -= size;
  379.     }
  380.     }
  381. }
  382.  
  383. static void GetGC(cbar)
  384. ColorbarWidget cbar;
  385. {
  386.     Display *dpy;
  387.     Window   win;
  388.     XGCValues gcv;
  389.     XRectangle rect;
  390.  
  391.     /* the foreground of this widget will be modified, so avoid XtGetGC */
  392.  
  393.     /* This should only be called when a window exists */
  394.     if (!cbar ||
  395.     !(dpy = XtDisplayOfObject((Widget)cbar)) ||
  396.     !(win = XtWindowOfObject((Widget)cbar))) {
  397.     Warning(cbar, warning4);
  398.     return;
  399.     }
  400.  
  401.     gcv.fill_style = FillSolid;
  402.     cbar->colorbar.colorGC = XCreateGC(dpy, win, GCFillStyle, &gcv);
  403.  
  404.     rect.x = cbar->core.border_width;
  405.     rect.y = cbar->core.border_width;
  406.     rect.width = cbar->core.width - 2 * cbar->core.border_width;
  407.     rect.height = cbar->core.height - 2 * cbar->core.border_width;
  408.     XSetClipRectangles(XtDisplay(cbar), cbar->colorbar.colorGC, 0, 0,
  409.             &rect, 1, YXBanded);
  410. }
  411.  
  412. static int GetMapSize(cbar)
  413. ColorbarWidget cbar;
  414. {
  415.     Widget widget = (Widget)cbar;
  416.     Display *dpy;
  417.     Window win;
  418.     XWindowAttributes xwa;
  419.     XVisualInfo template, *returned, *pVis;
  420.     int ct, depth, i;
  421.  
  422.     if (!widget)
  423.     return (0);
  424.     /* This should only be called when a window exists */
  425.     if (!(dpy = XtDisplayOfObject(widget)) ||
  426.     !(win = XtWindow(widget)) ||
  427.     !XGetWindowAttributes(dpy, win, &xwa)) {
  428.     Warning(cbar, warning4);
  429.     return(0);
  430.     }
  431.  
  432.     /* 
  433.      * To find the size of the colormap, get the window's visual,
  434.      * then turn the visual into a VisualInfo struct.
  435.      * (Could cheat and look inside of visual structure).
  436.      */
  437.     template.visualid = XVisualIDFromVisual(xwa.visual);
  438.     pVis = returned = XGetVisualInfo(dpy, VisualIDMask, &template, &ct);
  439.  
  440.     for (i = 0, depth = 0; i < ct; i++, pVis++) {
  441.     if (depth < pVis->depth)
  442.         depth = pVis->depth;
  443.     }
  444.     cbar->colorbar.mapSize = 1 << depth;
  445.     XFree((char *)returned);
  446.  
  447.     return(cbar->colorbar.mapSize);
  448. }
  449.  
  450. static void HandleInput(cbar, e)
  451. ColorbarWidget cbar;
  452. XButtonEvent *e;
  453. {
  454.     int x, y;
  455.     int border = cbar->core.border_width;
  456.     int width = cbar->core.width - 2 * border;
  457.     int height = cbar->core.height - 2 * border;
  458.     XcmsFloat where;
  459.     ScaleCallbackStruct tmp;
  460.  
  461.     x = e->x - border;
  462.     y = e->y - border;
  463.     /* but treat presses in border area as on ends */
  464.     if (x < 0)
  465.     x = 0;
  466.     else if (x > width)
  467.     x = width;
  468.     if (y < 0)
  469.     y = 0;
  470.     else if (y > height)
  471.     y = height;
  472.  
  473.     if (cbar->colorbar.orientation == XtorientVertical) 
  474.     where = 1.0 - (XcmsFloat)y / (XcmsFloat)height;
  475.     else
  476.     where = (XcmsFloat)x / (XcmsFloat)width;
  477.  
  478.     tmp.value = (int)((XcmsFloat)CbarFractionBase * where);
  479.     tmp.event = (XEvent *)e;
  480.     tmp.reason = CR_SINGLE_SELECT;
  481.     XtCallCallbacks((Widget)cbar, XtNsingleSelectionCallback, &tmp);
  482. }
  483.