ftp.nice.ch/pub/next/unix/developer/pcn.2.0.s.tar.gz#/contrib/gauge/Xsw/Scale.c

This is Scale.c in view mode; [Download] [Up]

#if ( !defined(lint) && !defined(SABER))
  static char PCN_rcsid[] = "$Header: /ufs/comp/mei/PROJ_PCN/onprofile/IFModel/Xsw/RCS/Scale.c,v 1.1 1992/04/17 18:26:39 mei Exp $";
#endif

/*AERO_MESG */

#include <math.h>

#include <X11/IntrinsicP.h>
#include "Xsw.h"

#include "ScaleP.h"

#define DIMENSION(widget) ( (widget->scale.vertical) ? (widget->core.height) : (widget->core.width) )

static XtResource resources[] = {
#define offset(field) XtOffset(ScaleWidget, scale.field)
  { XtNcallback, XtCCallback, XtRCallback, sizeof(XPointer),
	offset(callback), XtRCallback, NULL },
   { XtNlongest, XtCLongest, XtRInt, sizeof(int),
	  offset(longest), XtRString, "0" },
    { XtNaxisLength, XtCAxisLength, XtRInt, sizeof(int),
	  offset(axis_length), XtRString, "0" },
    { XtNindent, XtCIndent, XtRInt, sizeof(int),
	  offset(indent), XtRString, "-1" },
    { XtNfont, XtCFont, XtRFontStruct, sizeof(XtPointer),
	offset(font), XtRString, XtDefaultFont },
    { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
	offset(foreground), XtRString, XtDefaultForeground },
    { XtNmaximum, XtCMaximum, XtRFloat, sizeof(double),
	offset(maximum), XtRString, "1.0" },
    { XtNminimum, XtCMinimum, XtRFloat, sizeof(double),
	offset(minimum), XtRString, "0.0" },
    { XtNshowMax, XtCMaximum, XtRFloat, sizeof(double),
	offset(maxinterval), XtRString, "1.0" },
    { XtNshowMin, XtCMinimum, XtRFloat, sizeof(double),
	offset(mininterval), XtRString, "0.0" },
    { XtNvertical, XtCVertical, XtRBoolean, sizeof(Boolean),
	offset(vertical), XtRString, "True" },
    { XtNlog, XtCLog, XtRBoolean, sizeof(Boolean),
	offset(log), XtRString, "False" },
#undef offset
};

static void Initialize();
static void Redisplay();
static void Resize();
static void Destroy();
static Boolean SetValues();
static void SetScale();


ScaleClassRec scaleClassRec = {
  { /* core fields */
    /* superclass		*/	(WidgetClass) &coreClassRec,
    /* class_name		*/	"Scale",
    /* widget_size		*/	sizeof(ScaleRec),
    /* class_initialize		*/	NULL,
    /* class_part_initialize	*/	NULL,
    /* class_inited		*/	FALSE,
    /* initialize		*/	Initialize,
    /* initialize_hook		*/	NULL,
    /* realize			*/	XtInheritRealize,
    /* actions			*/	NULL,
    /* num_actions		*/	0,
    /* resources		*/	resources,
    /* num_resources		*/	XtNumber(resources),
    /* xrm_class		*/	NULLQUARK,
    /* compress_motion		*/	TRUE,
    /* compress_exposure	*/	TRUE,
    /* compress_enterleave	*/	TRUE,
    /* visible_interest		*/	FALSE,
    /* destroy			*/	Destroy,
    /* resize			*/	Resize,
    /* expose			*/	Redisplay,
    /* set_values		*/	SetValues,
    /* set_values_hook		*/	NULL,
    /* set_values_almost	*/	XtInheritSetValuesAlmost,
    /* get_values_hook		*/	NULL,
    /* accept_focus		*/	NULL,
    /* version			*/	XtVersion,
    /* callback_private		*/	NULL,
    /* tm_table			*/	NULL,
    /* query_geometry		*/	XtInheritQueryGeometry,
    /* display_accelerator	*/	XtInheritDisplayAccelerator,
    /* extension		*/	NULL
  },
  { /* template fields */
    /* empty			*/	0
  }
};

WidgetClass scaleWidgetClass = (WidgetClass)&scaleClassRec;

int
XswScaleGetCoord(cw, value)
ScaleWidget cw;
double value;
{
  int pos;
  double temp, max, min, val;

  /* hui 3/10 boundary check */
  if(value < cw->scale.mininterval) value=cw->scale.mininterval;
  if(value > cw->scale.maxinterval) value=cw->scale.maxinterval;

  if (cw->scale.log) {
    if (cw->scale.maxinterval > 0) max = log10(cw->scale.maxinterval);
    else max = 0;
    if (cw->scale.mininterval > 0) min = log10(cw->scale.mininterval);
    else min = 0;
    if (value > 0) val = log10(value);
    else val = 0;
  } else {
    max = cw->scale.maxinterval;
    min = cw->scale.mininterval;
    val = value;
  }

  temp = (double)cw->scale.axis_length / (max - min);
  
  pos = (int)(val > min ? 
	      (val - min)*temp : 0) +
		cw->scale.indent;

  if (cw->scale.vertical)
    pos = cw->core.height - pos;

  return pos;
}

 
static void
GetAllGC(cw)
ScaleWidget cw;
{
  XGCValues values;
  XtGCMask mask = GCForeground | GCBackground | GCFont;

  values.foreground = cw->core.background_pixel;
  values.background = cw->core.background_pixel;
  values.font = cw->scale.font->fid;
  cw->scale.cleargc = XtGetGC((Widget) cw, mask, &values);


  values.foreground = cw->scale.foreground;
  cw->scale.normgc = XtGetGC((Widget) cw, mask, &values);
}


static void ShowList(cw)
ScaleWidget cw;
{
  double dist, loc;
  int len, ht;
  double cur;
  char buf[80];
  double Del=0.0001;

  if (cw->scale.axis_length <= 0) return;

  dist = (double)cw->scale.axis_length / (double)cw->scale.numIntervals;

  cur = cw->scale.mininterval;

  if (cw->scale.vertical) {
    loc = cw->core.height - cw->scale.indent;
    dist = -dist;
  } else {
    loc = cw->scale.indent;
  }
  
  while (cur <= cw->scale.maxinterval + Del)	{
    sprintf (buf, "%g", cur);
    if (cw->scale.vertical) {
      ht = FONTHEIGHT(cw->scale.font);
      len = XTextWidth (cw->scale.font, buf, strlen (buf));
      XDrawString (XtDisplay(cw), XtWindow(cw), cw->scale.normgc,
		   cw->core.width - len,
		   loc + ht/2 <= cw->core.height ? 
		   (int)loc + ht/2 : (int)loc,
		   buf, strlen (buf));
    } else {
      len = XTextWidth (cw->scale.font, buf, strlen (buf));
      XDrawString (XtDisplay(cw), XtWindow(cw), cw->scale.normgc,
		   loc > len/2 ? (int)loc - len/2 : (int)loc,
		   cw->scale.font->max_bounds.ascent, 
		   buf, strlen (buf));
    }
    loc += dist;
    if (cw->scale.log)	{
      cur *= cw->scale.interval;
    } else {
      cur += cw->scale.interval;
    }
  }
}

/* ARGSUSED */
static void
Initialize(request, new)
ScaleWidget request, new;
{
  GetAllGC(new);

  SetScale(new);

  if (new->scale.vertical) {
    if (new->scale.indent < 0)
      new->scale.indent = FONTHEIGHT(new->scale.font)/2 + 1;
    if ((new->core.height >
	 new->scale.indent+FONTHEIGHT(new->scale.font)/2) &&
	(new->scale.axis_length == 0)) {
      new->scale.axis_length = new->core.height -
	(new->scale.indent + FONTHEIGHT(new->scale.font)/2);
      SetScale(new);
    } else {
      new->core.height = new->scale.axis_length + new->scale.indent +
	FONTHEIGHT(new->scale.font)/2;
    }
    new->core.width = new->scale.longest > 0 ? new->scale.longest : 1;    
    new->scale.old_height = new->core.height;
  } else {
    if (new->scale.indent < 0)
      new->scale.indent = new->scale.longest/2 + 1;
    new->core.height = FONTHEIGHT(new->scale.font);
    if ((new->core.width >
	 new->scale.indent+new->scale.longest/2) &&
	(new->scale.axis_length == 0)) {
      new->scale.axis_length = new->core.width -
	(new->scale.indent + new->scale.longest/2);
      SetScale(new);
    } else {
      new->core.width = new->scale.axis_length + new->scale.indent + 
	new->scale.longest/2;
    }
    new->scale.old_width = new->core.width;
  }    

}

/* ARGSUSED */
static void
Redisplay(cw, event)
ScaleWidget cw;
XExposeEvent *event;
{
  if (!XtIsRealized((Widget) cw))
    return;
  
  ShowList(cw);
}

/* ARGSUSED */ 
static Boolean
SetValues(current, request, new)
Widget current, request, new;
{
  ScaleWidget curcw = (ScaleWidget) current;
  ScaleWidget newcw = (ScaleWidget) new;
  Boolean redisplay = False;

  if (curcw->scale.foreground != newcw->scale.foreground) {
    if (newcw->scale.normgc)
      XtReleaseGC((Widget) newcw, newcw->scale.normgc);
    if (newcw->scale.cleargc)
      XtReleaseGC((Widget) newcw, newcw->scale.cleargc);
    GetAllGC(newcw);
    redisplay = True;
  }

  if (curcw->scale.log != newcw->scale.log) {
    redisplay = True;
  }

  if ((curcw->scale.maximum != newcw->scale.maximum) ||
      (curcw->scale.minimum != newcw->scale.minimum)){
    redisplay = True;
  }

  

  if (curcw->scale.axis_length != newcw->scale.axis_length) {  
    if (newcw->scale.vertical) {
      newcw->core.width = newcw->scale.longest;
      newcw->core.height = newcw->scale.axis_length+
	FONTHEIGHT(newcw->scale.font)+newcw->scale.indent;
    } else {
      newcw->core.height = FONTHEIGHT(newcw->scale.font);
      newcw->core.width = newcw->scale.axis_length +
	newcw->scale.longest/2 + newcw->scale.indent;
      newcw->scale.old_width = newcw->core.width;
    }    
  }
  SetScale(newcw);
   
  return redisplay;
}


/* ARGSUSED */ 
static void
Resize(cw, event)
ScaleWidget cw;
XExposeEvent *event;
{

  if (cw->scale.vertical) {
    cw->scale.axis_length += cw->core.height - cw->scale.old_height;
    cw->scale.old_height = cw->core.height;
  } else {
    cw->scale.axis_length += cw->core.width - cw->scale.old_width;
    cw->scale.old_width = cw->core.width;
  }    
  
  SetScale(cw);
}

static void 
SetScale(cw)
ScaleWidget cw;
{
  double interval, min, max, cur;
  double old_max, old_min;
  int nlabels, strwidth, maxwidth;
  int maxsize;
  double n;
  char valbuf[80];

    /* Set up x axis scaling, and x axis labels */
  (void)sprintf (valbuf, "88%g", cw->scale.maximum);
  strwidth = XTextWidth (cw->scale.font, valbuf, strlen (valbuf));
  if (cw->scale.vertical) {
    if ((nlabels = cw->scale.axis_length / FONTHEIGHT(cw->scale.font)) 
	== 0) {
      nlabels = 1;
    }    
  } else {
    if ((nlabels = cw->scale.axis_length / strwidth) == 0) {
      nlabels = 1;
    }
  }

  
  do	{
    if ((max = cw->scale.maximum) <= 0)	max = 100.0;
    min = cw->scale.minimum;
    if (cw->scale.log)	{
      if (min <= 0.0)	{
	min = 0.1;
      } else if (min > 1.0)	{
	min = 1.0;
      }
      if (min >= max) {
	min = max/10;
      }
      log_scale (min, max, nlabels, &min, &max, &interval);
    } else	{
      if (min >= max) {
	if (min > 0) min = 0;
	else if (min == 0) max = 1;
	else max = 0;
      }
      linear_scale (min, max, nlabels, &min, &max, &interval);
    }

    if (interval > 0.0)	{
      if (cw->scale.log) {
	n = (log10 (max) - log10 (min)) / log10 (interval);
      } else	{
	n = (max-min) / interval;
      }
    } else	{
      n = max;
    }
    maxwidth = 0;
    if (cw->scale.log)	{
      cur = min * interval;
    } else	{
      cur = min + interval;
    }
    while (cur <= max)	{
      sprintf (valbuf, "88%g", cur);
      if ((strwidth = 
	   XTextWidth (cw->scale.font, valbuf, strlen (valbuf)))
	  > maxwidth)	{
	maxwidth = strwidth;
      }
      if (cw->scale.log)	{
	cur *= interval;
      } else	{
	cur += interval;
      }
    }
    if (cw->scale.vertical) {
      maxsize = FONTHEIGHT(cw->scale.font);
    } else {
    
      maxsize = maxwidth;
    }
    nlabels -= 1;
  } while (nlabels > 0 && ((int)n * maxsize) > cw->scale.axis_length);
  
  old_max = cw->scale.maxinterval;
  old_min = cw->scale.mininterval;
  cw->scale.longest = maxwidth;
  cw->scale.numIntervals = (int)n;
  cw->scale.maxinterval = max;
  cw->scale.mininterval = min;
  cw->scale.interval = interval;
  if ((cw->scale.maxinterval != old_max) ||
      (cw->scale.mininterval != old_min)) {
    XtCallCallbacks((Widget) cw, XtNcallback, NULL);
  }
}

static void Destroy(cw)
ScaleWidget cw;
{
  if (cw->scale.normgc)
    XtReleaseGC((Widget) cw, cw->scale.normgc);
  if (cw->scale.cleargc)
    XtReleaseGC((Widget) cw, cw->scale.cleargc);
}



These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Marcel Waldvogel and Netfuture.ch.