home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / Microline3.0 / XmL / Progress.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  16.8 KB  |  602 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.  * The following source code is part of the Microline Widget Library.
  21.  * The Microline widget library is made available to Mozilla developers
  22.  * under the Netscape Public License (NPL) by Neuron Data.  To learn
  23.  * more about Neuron Data, please visit the Neuron Data Home Page at
  24.  * http://www.neurondata.com.
  25.  */
  26.  
  27. #include "ProgressP.h"
  28. #include <stdio.h>
  29. #include <sys/time.h>
  30.  
  31. static void ClassInitialize(void);
  32. static void Initialize(Widget , Widget, ArgList, Cardinal *);
  33. static void Resize(Widget);
  34. static void Destroy(Widget);
  35. static void Realize(Widget w, XtValueMask *valueMask,
  36.     XSetWindowAttributes *attr);
  37. static void Redisplay(Widget, XEvent *, Region);
  38. static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
  39. static void CopyFontList(XmLProgressWidget p);
  40. static void TimeStr(char *, int);
  41. static void DrawBarMeter(XmLProgressWidget p, XRectangle *rect);
  42. static void DrawBoxesMeter(XmLProgressWidget p, XRectangle *rect);
  43. static void DrawString(XmLProgressWidget, XmString, int, int,
  44.     int, XRectangle *, XRectangle *);
  45. static Boolean CvtStringToMeterStyle(Display *dpy, XrmValuePtr args,
  46.     Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal,
  47.     XtPointer *data);
  48.  
  49. static XtResource resources[] = 
  50.     {
  51.         {
  52.         XmNcompleteValue, XmCCompleteValue,
  53.         XtRInt, sizeof(int),
  54.         XtOffset(XmLProgressWidget, progress.completeValue),
  55.         XtRImmediate, (caddr_t)100
  56.         },
  57.         {
  58.         XmNnumBoxes, XmCNumBoxes,
  59.         XtRInt, sizeof(int),
  60.         XtOffset(XmLProgressWidget, progress.numBoxes),
  61.         XtRImmediate, (caddr_t)10
  62.         },
  63.         {
  64.         XmNvalue, XmCValue,
  65.         XtRInt, sizeof(int),
  66.         XtOffset(XmLProgressWidget, progress.value),
  67.         XtRImmediate, (caddr_t)0
  68.         },
  69.         {
  70.         XmNfontList, XmCFontList,
  71.         XmRFontList, sizeof(XmFontList),
  72.         XtOffset(XmLProgressWidget, progress.fontList),
  73.         XmRImmediate, (XtPointer)0,
  74.         },
  75.         {
  76.         XmNmeterStyle, XmCMeterStyle,
  77.         XmRMeterStyle, sizeof(unsigned char),
  78.         XtOffset(XmLProgressWidget, progress.meterStyle),
  79.         XmRImmediate, (XtPointer)XmMETER_BAR,
  80.         },
  81.         {
  82.         XmNshowTime, XmCShowTime,
  83.         XmRBoolean, sizeof(Boolean),
  84.         XtOffset(XmLProgressWidget, progress.showTime),
  85.         XmRImmediate, (XtPointer)False
  86.         },
  87.         {
  88.         XmNshowPercentage, XmCShowPercentage,
  89.         XmRBoolean, sizeof(Boolean),
  90.         XtOffset(XmLProgressWidget, progress.showPercentage),
  91.         XmRImmediate, (XtPointer)True
  92.         }
  93.     };
  94.  
  95. XmLProgressClassRec xmlProgressClassRec = 
  96.     {
  97.         { /* Core */
  98.         (WidgetClass)&xmPrimitiveClassRec,      /* superclass */
  99.         "XmLProgress",                          /* class_name */
  100.         sizeof(XmLProgressRec),                 /* widget_size */
  101.         ClassInitialize,                        /* class_initialize */
  102.         NULL,                                   /* class_part_initialize */
  103.         FALSE,                                  /* class_inited */
  104.         (XtInitProc)Initialize,                 /* initialize */
  105.         NULL,                                   /* initialize_hook */
  106.         (XtRealizeProc)Realize,                 /* realize */
  107.         NULL,                                   /* actions */
  108.         0,                                      /* num_actions */
  109.         resources,                              /* resources */
  110.         XtNumber(resources),                    /* num_resources */
  111.         NULLQUARK,                              /* xrm_class */
  112.         TRUE,                                   /* compress_motion */
  113.         FALSE,                                  /* compress_exposure */
  114.         TRUE,                                   /* compress_enterleave */
  115.         TRUE,                                   /* visible_interest */
  116.         (XtWidgetProc)Destroy,                  /* destroy */
  117.         (XtWidgetProc)Resize,                   /* resize */
  118.         (XtExposeProc)Redisplay,                /* expose */
  119.         (XtSetValuesFunc)SetValues,             /* set_values */
  120.         NULL,                                   /* set_values_hook */
  121.         XtInheritSetValuesAlmost,               /* set_values_almost */
  122.         NULL,                                   /* get_values_hook */
  123.         NULL,                                   /* accept_focus */
  124.         XtVersion,                              /* version */
  125.         NULL,                                   /* callback_private */
  126.         XtInheritTranslations,                  /* tm_table */
  127.         NULL,                                   /* query_geometry */
  128.         NULL,                                   /* display_accelerator */
  129.         NULL,                                   /* extension */
  130.         },
  131.         { /* Primitive */
  132.         (XtWidgetProc)_XtInherit,               /* border_highlight */
  133.         (XtWidgetProc)_XtInherit,               /* border_unhighlight */
  134.         XtInheritTranslations,                  /* translations */
  135.         NULL,                                   /* arm_and_activate */
  136.         NULL,                                   /* syn_resources */
  137.         0,                                      /* num_syn_resources */
  138.         NULL,                                   /* extension */
  139.         },
  140.         { /* Progress */
  141.         0,                                      /* unused */
  142.         }
  143.     };
  144.  
  145. WidgetClass xmlProgressWidgetClass = (WidgetClass)&xmlProgressClassRec;
  146.  
  147. static void 
  148. ClassInitialize(void)
  149.     {
  150.     XmLInitialize();
  151.  
  152.     XtSetTypeConverter(XmRString, XmRMeterStyle, CvtStringToMeterStyle,
  153.         0, 0, XtCacheNone, 0);
  154.     }
  155.  
  156. static void
  157. Initialize(Widget reqW,
  158.        Widget newW,
  159.        ArgList args,
  160.        Cardinal *narg)
  161.     {
  162.     XmLProgressWidget p;
  163.  
  164.     p = (XmLProgressWidget)newW;
  165.  
  166.     if (!p->core.width)
  167.         p->core.width = 200;
  168.     if (!p->core.height)
  169.         p->core.height = 30;
  170.  
  171.     p->progress.gc = 0;
  172.     p->progress.startTime = time(0);
  173.     CopyFontList(p);
  174.     if (p->progress.completeValue < 1)
  175.         {
  176.         XmLWarning(newW, "Initialize() - complete value can't be < 1");
  177.         p->progress.completeValue = 1;
  178.         }
  179.     if (p->progress.numBoxes < 1)
  180.         {
  181.         XmLWarning(newW, "Initialize() - number of boxes can't be < 1");
  182.         p->progress.numBoxes = 1;
  183.         }
  184.     if (p->progress.value < 0)
  185.         {
  186.         XmLWarning(newW, "Initialize() - value can't be < 0");
  187.         p->progress.value = 0;
  188.         }
  189.     if (p->progress.value > p->progress.completeValue)
  190.         {
  191.         XmLWarning(newW, "Initialize() - value can't be > completeValue");
  192.         p->progress.value = p->progress.completeValue;
  193.         }
  194.     XtVaSetValues(newW, XmNtraversalOn, False, NULL);
  195.     }
  196.  
  197. static void
  198. Resize(Widget w)
  199.     {
  200.     Display *dpy;
  201.     Window win;
  202.  
  203.     if (!XtIsRealized(w))
  204.         return;
  205.     dpy = XtDisplay(w);
  206.     win = XtWindow(w);
  207.     XClearArea(dpy, win, 0, 0, 0, 0, True);
  208.     }
  209.  
  210. static void
  211. Destroy(Widget w)
  212.     {
  213.     Display *dpy;
  214.     XmLProgressWidget p;
  215.  
  216.     p = (XmLProgressWidget)w;
  217.     dpy = XtDisplay(w);
  218.     if (p->progress.gc)
  219.         {
  220.         XFreeGC(dpy, p->progress.gc);
  221.         XFreeFont(dpy, p->progress.fallbackFont);
  222.         }
  223.     XmFontListFree(p->progress.fontList);
  224.     }
  225.  
  226. static void
  227. Realize(Widget w,
  228.     XtValueMask *valueMask,
  229.     XSetWindowAttributes *attr)
  230.     {
  231.     XmLProgressWidget p;
  232.     Display *dpy;
  233.     WidgetClass superClass;
  234.     XtRealizeProc realize;
  235.     XGCValues values;
  236.     /*    XtGCMask mask;*/
  237.  
  238.     p = (XmLProgressWidget)w;
  239.     dpy = XtDisplay(p);
  240.     superClass = xmlProgressWidgetClass->core_class.superclass;
  241.     realize = superClass->core_class.realize;
  242.     (*realize)(w, valueMask, attr);
  243.  
  244.     if (!p->progress.gc)
  245.         {
  246.         p->progress.fallbackFont = XLoadQueryFont(dpy, "fixed");
  247.         values.font = p->progress.fallbackFont->fid;
  248.         p->progress.gc = XCreateGC(dpy, XtWindow(p), GCFont, &values);
  249.         }
  250.     }
  251.  
  252. static void
  253. Redisplay(Widget w,
  254.       XEvent *event,
  255.       Region region)
  256.     {
  257.     XmLProgressWidget p;
  258.     Display *dpy;
  259.     Window win;
  260.     XRectangle rect;
  261.     int st;
  262.  
  263.     if (!XtIsRealized(w) || !w->core.visible)
  264.         return;
  265.  
  266.     p = (XmLProgressWidget)w;
  267.     dpy = XtDisplay(w);
  268.     win = XtWindow(w);
  269.     st = p->primitive.shadow_thickness;
  270.     rect.x = st;
  271.     rect.y = st;
  272.     rect.width = p->core.width - st * 2;
  273.     rect.height = p->core.height - st * 2;
  274.  
  275.     if (p->progress.meterStyle == XmMETER_BAR)
  276.         DrawBarMeter(p, &rect);
  277.     else if (p->progress.meterStyle == XmMETER_BOXES)
  278.         DrawBoxesMeter(p, &rect);
  279.  
  280. #ifdef MOTIF11
  281.     _XmDrawShadow(dpy, win,
  282.         p->primitive.bottom_shadow_GC,
  283.         p->primitive.top_shadow_GC,
  284.         p->primitive.shadow_thickness,
  285.         0, 0, p->core.width, p->core.height);
  286. #else
  287.     _XmDrawShadows(dpy, win,
  288.         p->primitive.top_shadow_GC,
  289.         p->primitive.bottom_shadow_GC,
  290.         0, 0, p->core.width, p->core.height,
  291.         p->primitive.shadow_thickness,
  292.         XmSHADOW_IN);
  293. #endif
  294.     }
  295.  
  296. static void
  297. DrawBoxesMeter(XmLProgressWidget p,
  298.            XRectangle *rect)
  299.     {
  300.     Display *dpy;
  301.     Window win;
  302.     int i, j, st, nb, x1, x2;
  303.  
  304.     dpy = XtDisplay(p);
  305.     win = XtWindow(p);
  306.     st = p->primitive.shadow_thickness;
  307.     nb = p->progress.numBoxes;
  308.     if (nb * st * 2 > (int)rect->width)
  309.         return;
  310.  
  311.     if (p->progress.completeValue)
  312.         j = (int)((long)nb * (long)p->progress.value /
  313.             (long)p->progress.completeValue);
  314.     else
  315.         j = 0;
  316.     x2 = 0;
  317.     for (i = 0; i < nb; i++)
  318.         {
  319.         if (i < j)
  320.             XSetForeground(dpy, p->progress.gc, p->primitive.foreground); 
  321.         else
  322.             XSetForeground(dpy, p->progress.gc, p->core.background_pixel);
  323.         x1 = x2;
  324.         if (i == nb - 1)
  325.             x2 = rect->width;
  326.         else
  327.             x2 = ((int)rect->width * (i + 1)) / nb;
  328.         XFillRectangle(dpy, win, p->progress.gc,
  329.             rect->x + x1 + st, rect->y + st,
  330.             x2 - x1 - st * 2, rect->height - st * 2);
  331. #ifdef MOTIF11
  332.         _XmDrawShadow(dpy, win,
  333.             p->primitive.bottom_shadow_GC,
  334.             p->primitive.top_shadow_GC,
  335.             p->primitive.shadow_thickness,
  336.             rect->x + x1, rect->y,
  337.             x2 - x1, rect->height);
  338. #else
  339.         _XmDrawShadows(dpy, win,
  340.             p->primitive.top_shadow_GC,
  341.             p->primitive.bottom_shadow_GC,
  342.             rect->x + x1, rect->y,
  343.             x2 - x1, rect->height,
  344.             p->primitive.shadow_thickness,
  345.             XmSHADOW_IN);
  346. #endif
  347.         }
  348.     }
  349.  
  350. static void
  351. DrawBarMeter(XmLProgressWidget p,
  352.          XRectangle *rect)
  353.     {
  354.     Display *dpy;
  355.     Window win;
  356.     int timeLeft, timeSoFar;
  357.     time_t currentTime;
  358.     XmString str;
  359.     Dimension strWidth, strHeight;
  360.     XRectangle lRect, rRect;
  361.     int percent;
  362.     char c[10];
  363.     long l;
  364.  
  365.     dpy = XtDisplay(p);
  366.     win = XtWindow(p);
  367.  
  368.     /* Left Rect */
  369.     if (p->progress.completeValue)
  370.         l = (long)rect->width * (long)p->progress.value /
  371.             (long)p->progress.completeValue;
  372.     else
  373.         l = 0;
  374.     lRect.x = rect->x;
  375.     lRect.y = rect->y;
  376.     lRect.width = (Dimension)l;
  377.     lRect.height = rect->height;
  378.     XSetForeground(dpy, p->progress.gc, p->primitive.foreground); 
  379.     XFillRectangle(dpy, win, p->progress.gc, lRect.x, lRect.y,
  380.         lRect.width, lRect.height);
  381.  
  382.     /* Right Rect */
  383.     rRect.x = rect->x + (int)l;
  384.     rRect.y = rect->y;
  385.     rRect.width = rect->width - (Dimension)l;
  386.     rRect.height = rect->height;
  387.     XSetForeground(dpy, p->progress.gc, p->core.background_pixel);
  388.     XFillRectangle(dpy, win, p->progress.gc, rRect.x, rRect.y,
  389.         rRect.width, rRect.height);
  390.  
  391.     if (p->progress.completeValue)
  392.         percent = (int)(((long)p->progress.value * 100) /
  393.             (long)p->progress.completeValue);
  394.     else
  395.         percent = 0;
  396.  
  397.     /* percent complete */
  398.     sprintf(c, "%d%c", percent, '%');
  399.     str = XmStringCreateSimple(c);
  400.     XmStringExtent(p->progress.fontList, str, &strWidth, &strHeight);
  401.     if (p->progress.showPercentage)
  402.         DrawString(p, str, rect->x + rect->width / 2 - (int)strWidth / 2,
  403.             rect->y + rect->height / 2 - (int)strHeight / 2, strWidth,
  404.             &lRect, &rRect);
  405.     XmStringFree(str);
  406.  
  407.     /* Left Time */
  408.     currentTime = time(0);
  409.     timeSoFar = (int)(currentTime - p->progress.startTime);
  410.     if (p->progress.showTime && p->progress.value &&
  411.         p->progress.value != p->progress.completeValue && timeSoFar)
  412.         {
  413.         TimeStr(c, timeSoFar);
  414.         str = XmStringCreateSimple(c);
  415.         XmStringExtent(p->progress.fontList, str,
  416.             &strWidth, &strHeight);
  417.         DrawString(p, str, rect->x + 5, rect->y + rect->height / 2 -
  418.             (int)strHeight / 2, strWidth, &lRect, &rRect);
  419.         XmStringFree(str);
  420.         }
  421.  
  422.     /* Right Time */
  423.     timeLeft = 0;
  424.     if (percent)
  425.         timeLeft = (timeSoFar * 100 / percent) - timeSoFar;
  426.     if (p->progress.showTime && percent && percent != 100 && timeLeft)
  427.         {
  428.         TimeStr(c, timeLeft);
  429.         str = XmStringCreateSimple(c);
  430.         XmStringExtent(p->progress.fontList, str,
  431.             &strWidth, &strHeight);
  432.         DrawString(p, str, rect->x + rect->width - strWidth - 5,
  433.             rect->y + rect->height / 2 - (int)strHeight / 2,
  434.             strWidth, &lRect, &rRect);
  435.         XmStringFree(str);
  436.         }
  437.     }
  438.  
  439. static void
  440. DrawString(XmLProgressWidget p,
  441.        XmString str,
  442.        int x,
  443.        int y,
  444.        int strWidth,
  445.        XRectangle *lRect,
  446.        XRectangle *rRect)
  447.     {
  448.     Display *dpy;
  449.     Window win;
  450.  
  451.     dpy = XtDisplay(p);
  452.     win = XtWindow(p);
  453.     if (lRect->width && lRect->height)
  454.         {
  455.         XSetForeground(dpy, p->progress.gc, p->core.background_pixel);
  456.         XSetClipRectangles(dpy, p->progress.gc, 0, 0, lRect, 1, Unsorted);
  457.         XmStringDraw(dpy, win, p->progress.fontList, str,
  458.             p->progress.gc, x, y, strWidth, XmALIGNMENT_BEGINNING,
  459.             XmSTRING_DIRECTION_L_TO_R, 0);
  460.         XSetClipMask(dpy, p->progress.gc, None);
  461.         }
  462.     if (rRect->width && rRect->height)
  463.         {
  464.         XSetForeground(dpy, p->progress.gc, p->primitive.foreground);
  465.         XSetClipRectangles(dpy, p->progress.gc, 0, 0, rRect, 1, Unsorted);
  466.         XmStringDraw(dpy, win, p->progress.fontList, str,
  467.             p->progress.gc, x, y, strWidth, XmALIGNMENT_BEGINNING,
  468.             XmSTRING_DIRECTION_L_TO_R, 0);
  469.         XSetClipMask(dpy, p->progress.gc, None);
  470.         }
  471.     }
  472.  
  473. static void
  474. TimeStr(char *c,
  475.     int seconds)
  476.     {
  477.     int h, m, s;
  478.  
  479.     s = seconds;
  480.     m = s / 60;
  481.     s -= m * 60;
  482.     h = m / 60;
  483.     m -= h * 60;
  484.     if (h > 99)
  485.         h = 99;
  486.     if (h > 0 && m < 10)
  487.         sprintf(c, "%d:0%d hr", h, m);
  488.     else if (h > 0)
  489.         sprintf(c, "%d:%d hr", h, m);
  490.     else if (m > 0 && s < 10)
  491.         sprintf(c, "%d:0%d min", m, s);
  492.     else if (m > 0)
  493.         sprintf(c, "%d:%d min", m, s);
  494.     else
  495.         sprintf(c, "%d sec", s);
  496.     }
  497.  
  498. static Boolean
  499. SetValues(Widget curW,
  500.       Widget reqW,
  501.       Widget newW,
  502.       ArgList args,
  503.       Cardinal *narg)
  504.     {
  505.     XmLProgressWidget cur, p;
  506.     XtAppContext app;
  507.  
  508.     cur = (XmLProgressWidget)curW;
  509.     p = (XmLProgressWidget)newW;
  510.     app = XtWidgetToApplicationContext(curW);
  511.     if (p->progress.value == 0)
  512.         p->progress.startTime = time(0);
  513.     if (p->progress.completeValue < 1)
  514.         {
  515.         XmLWarning(newW, "SetValues() - complete value can't be < 1");
  516.         p->progress.completeValue = 1;
  517.         }
  518.     if (p->progress.numBoxes < 1)
  519.         {
  520.         XmLWarning(newW, "SetValues() - number of boxes can't be < 1");
  521.         p->progress.numBoxes = 1;
  522.         }
  523.     if (p->progress.value < 0)
  524.         {
  525.         XmLWarning(newW, "SetValues() - value can't be < 0");
  526.         p->progress.value = 0;
  527.         }
  528.     if (p->progress.value > p->progress.completeValue)
  529.         {
  530.         XmLWarning(newW, "SetValues() - value can't be > completeValue");
  531.         p->progress.value = p->progress.completeValue;
  532.         }
  533.     if (p->progress.fontList != cur->progress.fontList)
  534.         {
  535.         XmFontListFree(cur->progress.fontList);
  536.         CopyFontList(p);
  537.         }
  538.     /* display changes immediately since we may be not get back
  539.        to XNextEvent if the calling application is computing */
  540.     if (p->core.background_pixel != cur->core.background_pixel ||
  541.         p->primitive.foreground != cur->primitive.foreground || 
  542.         p->progress.value != cur->progress.value ||
  543.         p->progress.completeValue != cur->progress.completeValue ||
  544.         p->progress.fontList != cur->progress.fontList ||
  545.         p->progress.showTime != cur->progress.showTime ||
  546.         p->progress.showPercentage != cur->progress.showPercentage ||
  547.         p->progress.meterStyle != cur->progress.meterStyle ||
  548.         p->progress.numBoxes != cur->progress.numBoxes ||
  549.         p->primitive.shadow_thickness != cur->primitive.shadow_thickness)
  550.         {
  551.         Redisplay(newW, 0, 0);
  552.         XFlush(XtDisplay(newW));
  553.         XmUpdateDisplay(newW);
  554.         }
  555.     return FALSE;
  556.     }
  557.  
  558. static void
  559. CopyFontList(XmLProgressWidget p)
  560.     { 
  561.     if (!p->progress.fontList)
  562.         p->progress.fontList = XmLFontListCopyDefault((Widget)p);
  563.     else
  564.         p->progress.fontList = XmFontListCopy(p->progress.fontList);
  565.     if (!p->progress.fontList)
  566.         XmLWarning((Widget)p, "- fatal error - font list NULL");
  567.     }
  568.  
  569. static Boolean
  570. CvtStringToMeterStyle(Display *dpy,
  571.               XrmValuePtr args,
  572.               Cardinal *narg,
  573.               XrmValuePtr fromVal,
  574.               XrmValuePtr toVal,
  575.               XtPointer *data)
  576.     {
  577.     static XmLStringToUCharMap map[] =
  578.         {
  579.         { "METER_BAR", XmMETER_BAR },
  580.         { "METER_BOXES", XmMETER_BOXES },
  581.         { 0, 0 },
  582.         };
  583.  
  584.     return XmLCvtStringToUChar(dpy, "XmRMeterStyle", map, fromVal, toVal);
  585.     }
  586.  
  587. /*
  588.    Public Functions
  589. */
  590.  
  591. Widget
  592. XmLCreateProgress(Widget parent,
  593.           char *name,
  594.           ArgList arglist,
  595.           Cardinal argcount)
  596.     {
  597.     return XtCreateWidget(name, xmlProgressWidgetClass, parent,
  598.         arglist, argcount);
  599.     }
  600.  
  601.  
  602.