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
/
ColorS.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-28
|
29KB
|
966 lines
/*
* Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
* All Rights Reserved
*
* This file is a component of an X Window System client which uses the Xcms
* Color Management System. TekColor is a trademark of Tektronix, Inc. The
* TekColor Editor is the subject of U.S. and foreign patents pending. The
* term "TekHVC" designates a particular color space that is the subject of
* U.S. Patent No. 4,985,853 (equivalent foreign patents pending).
* Permission is hereby granted to use, copy, modify, sell, and otherwise
* distribute this software and its documentation for the X Window System
* environment, for any purpose and without fee, provided that:
*
* 1. The code and documentation are only used to implement a
* TekColor Editor in an X Window System environment; and
* 2. This copyright and permission notice is reproduced in all copies
* of the code and in supporting documentation.
*
* Permission is granted to modify this code as required to allow it to
* be compiled on any host computer, provided that the functionality of
* the TekColor Editor is not modified in any way. A description of any
* modifications must be sent to Tektronix, Inc. Contact
* Tektronix Inc., P.O. Box 1000, Mail Station 60-850,
* Network Displays Division Engineering, Wilsonville, OR 97070.
*
* Tektronix makes no representation about the suitability of this software
* for any purpose. It is provided "as is" and with all faults.
*
* TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
* INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
*
* NAME
* ColorS.c -- Routines for ColorScaleWidget
*
* DESCRIPTION
* This widget implements the Colormap Scale and Huebar
*
* HISTORY
*
* HISTORY END
*
*/
#ifndef LINT
static char *copy_notice = "Copyright 1991 Tektronix, Inc.";
#ifdef RCS_ID
static char *rcsid= "$Header: ColorS.c,v 1.2 91/08/22 11:36:06 adamsc Exp $";
#endif /* RCS_ID */
#endif /* LINT */
#include <stdio.h>
#include <math.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/FormP.h>
#include <X11/Xaw/LabelP.h>
#include <X11/Xaw/ScrollbarP.h>
#include <X11/Xaw/Text.h>
#include "ColorSP.h"
#include "ColorbarP.h"
#include "RepeatBP.h"
#include "ZoomP.h"
/****************************************************************
*
* Color Scale Resources
*
****************************************************************/
static XtResource resources[] = {
#define offset(field) XtOffset(ColorScaleWidget, colorScale.field)
/* {name, class, type, size, offset, default_type, default_addr}, */
{ XtNbase, XtCBase, XtRPixel, sizeof(Pixel),
offset(base), XtRImmediate, (XtPointer)(-1) },
{ XtNlength, XtCLength, XtRInt, sizeof(int),
offset(length), XtRImmediate, (XtPointer)(-1) },
{ XtNpixelInc, XtCPixelInc, XtRPixel, sizeof(Pixel),
offset(pixelInc), XtRImmediate, (XtPointer)1 },
{ XtNlabel, XtCLabel, XtRString, sizeof(String),
offset(label), XtRImmediate, (XtPointer)NULL },
{ XtNincrement, XtCIncrement, XtRInt, sizeof(int),
offset(inc), XtRImmediate, (XtPointer)1 },
{ XtNminimum, XtCMinimum, XtRInt, sizeof(int),
offset(min), XtRImmediate, (XtPointer)0 },
{ XtNmaximum, XtCMaximum, XtRInt, sizeof(int),
offset(max), XtRImmediate, (XtPointer)100 },
{ XtNvalue, XtCValue, XtRInt, sizeof(int),
offset(value), XtRImmediate, (XtPointer)0 },
{ XtNvalueChangedCallback, XtCCallback, XtRCallback,
sizeof(XtCallbackList), offset(changed), XtRCallback, NULL },
{ XtNzoom, XtCZoom, XtRInt, sizeof(int),
offset(zoom), XtRImmediate, (XtPointer)0 },
{ XtNwrap, XtCBoolean, XtRBoolean, sizeof(Boolean),
offset(wrap), XtRImmediate, (XtPointer)False },
#undef offset
};
/*
* SliderFractionBase is the numerator for some percent calculations
*/
#define SliderFractionBase 1000
/*
* ColorScale actions are identical to those of Form.
* If I understand this correctly, I can set the action table to NULL,
* all superclass tables will be searched for an action.
* I can also just inherit actions themselves
*/
/* forward declarations for the class struct */
static void Initialize();
#ifdef LATER
static void Resize();
#endif
static Boolean SetValues();
ColorScaleClassRec colorScaleClassRec = {
{ /* core_class fields */
/* superclass */ (WidgetClass) &formClassRec,
/* class_name */ "ColorScale",
/* widget_size */ sizeof(ColorScaleRec),
/* 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 */ NULL,
/* resize */ XtInheritResize, /* Resize */
/* expose */ XtInheritExpose,
/* 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 */ XtInheritTranslations,
/* query_geometry */ XtInheritQueryGeometry,
/* display_accelerator */ NULL,
/* extension */ NULL
},
{ /* composite fields */
/* geometry manager */ XtInheritGeometryManager,
/* change managed */ XtInheritChangeManaged,
/* insert child */ XtInheritInsertChild,
/* delete child */ XtInheritDeleteChild,
/* extension */ NULL
},
{ /* constraint fields */
/* constraint resources */ NULL,
/* number of resources */ 0,
/* size of record */ sizeof(FormConstraintsRec),
/* constraint initialization*/ NULL,
/* constraint destroy */ NULL,
/* set values */ NULL,
/* extension */ NULL
},
{ /* form fields */
/* layout */ XtInheritLayout,
},
{ /* color scale fields */
/* extension */ NULL
},
};
WidgetClass colorScaleWidgetClass = (WidgetClass)&colorScaleClassRec;
/* forward declarations of utility functions */
static void AttachChildren();
static void AttachLabel();
static void AttachUpArrow();
static void AttachDownArrow();
static void AttachBar();
static void AttachScrollbar();
static void AttachExpand();
static void AttachZoom();
static void CreateChildren();
static void Incr();
static void Jump();
static void NewVal();
static void ResetZoom();
static void Scroll();
static void SetZoom();
static void Single();
static char *warning1 = "increment must be non-negative";
static char *warning2 = "maximum must be greater than or equal to minimum";
static char *warning3 = "value must be within range of minimum to maximum";
/* Up and Down mean positive and negative, not the direction of the arrow */
#define Label 0
#define UpArrow 1
#define DownArrow 2
#define Scrollbar 3
#define Bar 4
#define Zoom 5
#define Expand 6
static void Warning (widget, message)
Widget widget;
char *message;
{
/* R4 says use XtAppWarningMsg but no information on how to set
* the parameters.
*/
if (!widget)
XtWarning(message);
else
XtAppWarning(XtWidgetToApplicationContext(widget), message);
}
static void Initialize(req, new)
ColorScaleWidget req, new;
{
LabelWidget lbl;
/* Validate input resources */
if (new->colorScale.inc < 0) { /* 0 is valid, means no buttons */
Warning(new, warning1);
new->colorScale.inc = 1;
}
/* negative base and length mean use min / max instead */
if (new->colorScale.min > new->colorScale.max) {
Warning(new, warning2);
new->colorScale.max = new->colorScale.min + 100;
}
if ( (new->colorScale.value < new->colorScale.min)
|| (new->colorScale.value > new->colorScale.max) ) {
Warning(new, warning3);
new->colorScale.value = new->colorScale.min;
}
/* create all of the widgets */
CreateChildren(new);
lbl = (LabelWidget)new->colorScale.wlist[Label];
if (req->core.width == 0)
new->core.width = lbl->core.width * 3;
if (req->core.height == 0)
new->core.height = lbl->core.width * 3;
if (new->colorScale.zoom > 1)
ResetZoom(new);
}
/* Most values are passed on to one child or another */
/*ARGSUSED*/
static Boolean SetValues(cur, req, new)
ColorScaleWidget cur, req, new;
{
Arg arg;
Arg bargs[2], sargs[4];
int bct = 0, sct = 0;
int rezoom = 0;
int reattach = 0;
if (new->colorScale.inc < 0) {
Warning(new, warning1);
new->colorScale.inc = cur->colorScale.inc;
} else if ( (new->colorScale.inc == 0) && (cur->colorScale.inc != 0) ) {
reattach = 1;
} else if ( (new->colorScale.inc != 0) && (cur->colorScale.inc == 0) ) {
reattach = 1;
}
/* max and min may be used as defaults later, so insure they are right */
if (new->colorScale.min > new->colorScale.max) {
Warning(new, warning2);
new->colorScale.max = cur->colorScale.max;
new->colorScale.min = cur->colorScale.min;
}
if ( (new->colorScale.value < new->colorScale.min)
|| (new->colorScale.value > new->colorScale.max) ) {
Warning(new, warning3);
new->colorScale.value = new->colorScale.min;
}
if (new->colorScale.min != cur->colorScale.min ||
new->colorScale.max != cur->colorScale.max) {
XtSetArg(sargs[sct], XtNlength,
new->colorScale.max - new->colorScale.min + 1); sct++;
rezoom = 1;
}
if (new->colorScale.base != cur->colorScale.base) {
if ((int)new->colorScale.base >=0)
XtSetArg(bargs[bct], XtNbase, new->colorScale.base);
else
XtSetArg(bargs[bct], XtNbase, new->colorScale.min);
bct++;
rezoom = 1;
}
if (new->colorScale.length != cur->colorScale.length) {
if (new->colorScale.length >=0)
XtSetArg(bargs[bct], XtNlength, new->colorScale.length);
else
XtSetArg(bargs[bct], XtNlength,
new->colorScale.max - new->colorScale.min + 1);
bct++;
rezoom = 1;
}
if (new->colorScale.label != cur->colorScale.label) {
XtSetArg(arg, XtNlabel, new->colorScale.label);
XtSetValues(new->colorScale.wlist[Label], &arg, 1);
}
if (new->colorScale.value != cur->colorScale.value) {
if (new->colorScale.value < new->colorScale.max - 8) {
float top;
top = (float)(new->colorScale.max - (new->colorScale.value + 8)) /
(float)(new->colorScale.max - new->colorScale.min + 1);
XawScrollbarSetThumb(new->colorScale.wlist[Scrollbar], top, -1.0);
} else {
XawScrollbarSetThumb(new->colorScale.wlist[Scrollbar], 1.0, -1.0);
}
/* avoid doing a reset for just a value change */
if (new->colorScale.zoom > 1 && !rezoom)
SetZoom(new);
}
if (new->colorScale.zoom != cur->colorScale.zoom) {
if ( (new->colorScale.zoom > 1) && (cur->colorScale.zoom <= 1) ) {
reattach = 1;
} else if ((new->colorScale.zoom <= 1) && (cur->colorScale.zoom > 1)) {
reattach = 1;
}
/* if (new->colorScale.zoom > 1) {
* XtSetArg(sargs[sct], XtNsliderExtent,
* SliderFractionBase / new->colorScale.zoom); sct++;
* }
*/
rezoom = 1;
}
if (bct > 0)
XtSetValues(new->colorScale.wlist[Bar], bargs, bct);
if (sct > 0)
XtSetValues(new->colorScale.wlist[Scrollbar], sargs, sct);
if (reattach)
AttachChildren(new);
if (new->colorScale.zoom > 1 && rezoom)
ResetZoom(new);
return(False); /* there is nothing for this widget to redraw */
}
/*****************************************************************************
*
* Resize
*
***************************************************************************/
#ifdef LATER
static void Resize(cs)
ColorScaleWidget cs;
{
WidgetList wlist;
RepeaterButtonWidget upArw;
RepeaterButtonWidget dwArw;
LabelWidget lbl;
ScrollbarWidget sld;
ColorbarWidget cbar;
ColorbarWidget expnd;
ZoomWidget zm;
Dimension width, wr, hr;
Arg args[2];
String *pString;
XtGeometryResult result;
int lblwidth;
int cnt;
wlist = (WidgetList) cs->colorScale.wlist;
upArw = (RepeaterButtonWidget) wlist[UpArrow];
dwArw = (RepeaterButtonWidget) wlist[DownArrow];
lbl = (LabelWidget) wlist[Label];
sld = (ScrollbarWidget) wlist[Scrollbar];
cbar = (ColorbarWidget) wlist[Bar];
expnd = (ColorbarWidget) wlist[Expand];
zm = (ZoomWidget) wlist[Zoom];
/* Get the width of the string in the label */
lblwidth = lbl->core.width;
if (cs->colorScale.zoom > 1) {
if (lblwidth > 180) {
width = lblwidth;
} else {
width = 170;
}
} else {
if (lblwidth > 100) {
width = lblwidth;
} else {
width = 90;
}
}
if (upArw->core.width != 25 || upArw->core.height != 25)
XtResizeWidget(upArw, 25, 25, 0);
if (dwArw->core.width != 25 || dwArw->core.height != 25)
XtResizeWidget(dwArw, 25, 25, 0);
if (sld->core.width != 25)
XtResizeWidget(sld, 25, sld->core.height, 0);
if (cbar->core.width != 40)
XtResizeWidget(cbar, 40, cbar->core.height, 0);
if (cs->colorScale.zoom > 1) {
if (zm->core.width != 40)
XtResizeWidget(zm, 40, zm->core.height, 0);
if (expnd->core.width != 40)
XtResizeWidget(expnd, 40, expnd->core.height, 0);
}
if (width != cs->core.width) {
result = XtMakeResizeRequest (cs, width, cs->core.height, &wr, &hr);
if (result == XtGeometryAlmost) {
result = XtMakeResizeRequest (cs, wr, hr, NULL, NULL);
cs->core.width = wr;
} else {
cs->core.width = width;
}
}
return;
}
#endif /* LATER */
static void AttachChildren(cs)
ColorScaleWidget cs;
{
Widget *wlist = cs->colorScale.wlist;
Arg args[8];
int n = 0;
/* could only change some constraints on orientation or facing change */
AttachLabel(args, &n);
XtSetValues(wlist[Label], args, n);
if (cs->colorScale.inc > 0) {
n = 0;
AttachUpArrow(cs,args, &n);
XtSetValues(wlist[UpArrow], args, n);
n = 0;
AttachDownArrow(cs,args, &n);
XtSetValues(wlist[DownArrow], args, n);
XtManageChild(wlist[UpArrow]);
XtManageChild(wlist[DownArrow]);
} else {
XtUnmanageChild(wlist[UpArrow]);
XtUnmanageChild(wlist[DownArrow]);
}
n = 0;
AttachScrollbar(cs, args, &n);
XtSetValues(wlist[Scrollbar], args, n);
n = 0;
AttachExpand(cs, args, &n);
XtSetValues(wlist[Expand], args, n);
if (cs->colorScale.zoom > 1) {
n = 0;
AttachZoom(cs, args, &n);
XtSetValues(wlist[Zoom], args, n);
n = 0;
AttachBar(cs, args, &n);
XtSetValues(wlist[Bar], args, n);
XtManageChild(wlist[Bar]);
XtManageChild(wlist[Zoom]);
} else {
XtUnmanageChild(wlist[Bar]);
XtUnmanageChild(wlist[Zoom]);
}
}
static void AttachLabel(argList, ct)
Arg *argList;
int *ct;
{
Arg *args = argList + *ct;
int n = *ct;
XtSetArg(args[n], XtNjustify, XtJustifyCenter); n++;
*ct += n;
}
static void AttachUpArrow(cs, argList, ct)
ColorScaleWidget cs;
Arg *argList;
int *ct;
{
Widget lbl = cs->colorScale.wlist[Label];
Arg *args = argList + *ct;
int n = *ct;
XtSetArg(args[n], XtNfromVert, lbl); n++;
XtSetArg(args[n], XtNvertDistance, 85); n++;
XtSetArg(args[n], XtNarrowDirection, XtorientationUp); n++;
/* XtSetArg(args[n], XmNhighlightThickness, 2); n++; */
/* XtSetArg(args[n], XmNtraversalOn, True); n++; */
*ct += n;
}
static void AttachDownArrow(cs, argList, ct)
ColorScaleWidget cs;
Arg *argList;
int *ct;
{
Widget wid = cs->colorScale.wlist[UpArrow];
Arg *args = argList + *ct;
int n = *ct;
XtSetArg(args[n], XtNfromVert, wid); n++;
XtSetArg(args[n], XtNvertDistance, 10); n++;
XtSetArg(args[n], XtNarrowDirection, XtorientationDown); n++;
/* XtSetArg(args[n], XmNhighlightThickness, 2); n++; */
/* XtSetArg(args[n], XmNtraversalOn, True); n++; */
*ct += n;
}
static void AttachScrollbar(cs, argList, ct)
ColorScaleWidget cs;
Arg *argList;
int *ct;
{
Widget arw, lbl;
Arg *args = argList + *ct;
int n = *ct;
if (cs->colorScale.inc > 0)
arw = cs->colorScale.wlist[UpArrow];
else
arw = NULL;
lbl = cs->colorScale.wlist[Label];
XtSetArg(args[n], XtNfromHoriz, arw); n++;
XtSetArg(args[n], XtNfromVert, lbl); n++;
*ct += n;
}
/*
* BUG: Cannot get the form widget to properly constrain children when
* I set those constraints after creation time. This forces this rather
* arcane way of determining constraints.
*/
static void AttachBar(cs, argList, ct)
ColorScaleWidget cs;
Arg *argList;
int *ct;
{
Widget sb = cs->colorScale.wlist[Scrollbar];
Widget lbl = cs->colorScale.wlist[Label];
Arg *args = argList + *ct;
int n = *ct;
XtSetArg(args[n], XtNfromHoriz, sb); n++;
XtSetArg(args[n], XtNfromVert, lbl); n++;
*ct += n;
}
static void AttachZoom(cs, argList, ct)
ColorScaleWidget cs;
Arg *argList;
int *ct;
{
Widget lbl = cs->colorScale.wlist[Label];
Widget bar = cs->colorScale.wlist[Bar];
Arg *args = argList + *ct;
int n = *ct;
XtSetArg(args[n], XtNfromHoriz, bar); n++;
XtSetArg(args[n], XtNfromVert, lbl); n++;
*ct += n;
}
static void AttachExpand(cs, argList, ct)
ColorScaleWidget cs;
Arg *argList;
int *ct;
{
Widget lbl = cs->colorScale.wlist[Label];
Widget zm = cs->colorScale.wlist[Zoom];
Arg *args = argList + *ct;
int n = *ct;
XtSetArg(args[n], XtNfromHoriz, zm); n++;
XtSetArg(args[n], XtNfromVert, lbl); n++;
*ct += n;
}
static void CreateChildren(cs)
ColorScaleWidget cs;
{
int manage = MaxColorScaleChildCt;
int extent;
int n = 0;
float top, shown;
Arg args[20];
WidgetList wlist = (WidgetList)cs->colorScale.wlist;
AttachLabel(args, &n);
XtSetArg(args[n], XtNlabel, cs->colorScale.label); n++;
wlist[Label] = XtCreateWidget ("label", labelWidgetClass, (Widget)cs,
args, n);
n = 0;
AttachUpArrow(cs,args, &n);
XtSetArg(args[n], XtNwidth, 18); n++;
XtSetArg(args[n], XtNheight, 18); n++;
wlist[UpArrow] = XtCreateWidget ("up", repeaterButtonClass, (Widget)cs,
args, n);
n = 0;
AttachDownArrow(cs, args, &n);
XtSetArg(args[n], XtNwidth, 18); n++;
XtSetArg(args[n], XtNheight, 18); n++;
wlist[DownArrow] = XtCreateWidget("down", repeaterButtonClass, (Widget)cs,
args,n);
if (cs->colorScale.zoom <= 1) {
extent = 100;
manage -= 2;
} else{
extent = SliderFractionBase / cs->colorScale.zoom;
if (extent < 30)
extent = 30;
}
n = 0;
AttachScrollbar(cs, args, &n);
XtSetArg(args[n], XtNwidth, 17); n++;
XtSetArg(args[n], XtNheight, 253); n++;
XtSetArg(args[n], XtNlength, cs->colorScale.max - cs->colorScale.min + 1);
top = 1.0;
shown = 32 / (cs->colorScale.max - cs->colorScale.min + 1);
if (sizeof(float) > sizeof(XtArgVal)) {
XtSetArg(args[n], XtNtopOfThumb, &top); n++;
XtSetArg(args[n], XtNshown, &shown); n++;
} else {
XtArgVal *l_top = (XtArgVal *)⊤
XtArgVal *l_shown = (XtArgVal *)&shown;
XtSetArg(args[n], XtNtopOfThumb, *l_top); n++;
XtSetArg(args[n], XtNshown, *l_shown); n++;
}
/* XtSetArg(args[n], XtNsliderExtent, extent); n++; */
wlist[Scrollbar] = XtCreateWidget ("scrollbar", scrollbarWidgetClass,
(Widget)cs, args, n);
n = 0;
AttachBar(cs, args, &n);
XtSetArg(args[n], XtNwidth, 17); n++;
XtSetArg(args[n], XtNheight, 253); n++;
if ((int)cs->colorScale.base < 0) {
XtSetArg(args[n], XtNbase, cs->colorScale.min); n++;
} else {
XtSetArg(args[n], XtNbase, cs->colorScale.base); n++;
}
if (cs->colorScale.length < 0) {
XtSetArg(args[n], XtNlength,
(cs->colorScale.max - cs->colorScale.min + 1)); n++;
} else {
XtSetArg(args[n], XtNlength, cs->colorScale.length); n++;
}
if (cs->colorScale.pixelInc > 1) {
XtSetArg(args[n], XtNpixelInc, cs->colorScale.pixelInc); n++;
}
wlist[Bar] = XtCreateWidget ("bar", colorbarWidgetClass, (Widget)cs,
args, n);
/* always create zoom, even if not initially managed */
n = 0;
AttachZoom(cs, args, &n);
XtSetArg(args[n], XtNwidth, 18); n++;
XtSetArg(args[n], XtNheight, 253); n++;
wlist[Zoom] = XtCreateWidget ("zoom", zoomWidgetClass, (Widget)cs,
args, n);
n = 0;
AttachExpand(cs, args, &n);
XtSetArg(args[n], XtNwidth, 18); n++;
XtSetArg(args[n], XtNheight, 253); n++;
if (cs->colorScale.pixelInc > 1) {
XtSetArg(args[n], XtNpixelInc, cs->colorScale.pixelInc); n++;
}
wlist[Expand] = XtCreateWidget ("expand", colorbarWidgetClass, (Widget)cs,
args, n);
/* add callbacks */
XtAddCallback(wlist[DownArrow], XtNarmCallback, Incr, (XtPointer)DownArrow);
XtAddCallback(wlist[DownArrow], XtNactivateCallback, Incr, (XtPointer)DownArrow);
XtAddCallback(wlist[DownArrow], XtNdisarmCallback, Incr, (XtPointer)DownArrow);
XtAddCallback(wlist[UpArrow], XtNarmCallback, Incr, (XtPointer)UpArrow);
XtAddCallback(wlist[UpArrow], XtNactivateCallback, Incr, (XtPointer)UpArrow);
XtAddCallback(wlist[UpArrow], XtNdisarmCallback, Incr, (XtPointer)UpArrow);
XtAddCallback(wlist[Scrollbar], XtNjumpProc, Jump, (XtPointer)Scrollbar);
XtAddCallback(wlist[Scrollbar], XtNscrollProc, Scroll, (XtPointer)Scrollbar);
XtAddCallback(wlist[Bar], XtNsingleSelectionCallback, Single, (XtPointer)Bar);
XtAddCallback(wlist[Expand], XtNsingleSelectionCallback, Single, (XtPointer)Expand);
/* manage children; avoid mapping unneeded children */
if (cs->colorScale.inc > 0)
XtManageChildren(wlist, manage);
else
XtManageChildren(wlist + Label, manage - Label);
}
/*
* Callback for arrow button action
*/
static void Incr(w, which, call)
Widget w;
int which;
ScaleCallbackStruct *call;
{
ColorScaleWidget cs = (ColorScaleWidget)XtParent(w);
int val;
ScaleCallbackStruct tmp;
tmp.reason = call->reason;
/* if reason is not activate, just pass through without value changes */
if (call->reason == CR_ACTIVATE) {
if (which == UpArrow) {
val = cs->colorScale.value + cs->colorScale.inc;
tmp.reason = CR_INCREMENT;
} else {
val = cs->colorScale.value - cs->colorScale.inc;
tmp.reason = CR_DECREMENT;
}
/* If wrapping, move one beyond limit */
if (val < cs->colorScale.min) {
if (cs->colorScale.wrap)
val += cs->colorScale.max - cs->colorScale.min + 1;
else
val = cs->colorScale.min;
} else if (val > cs->colorScale.max) {
if (cs->colorScale.wrap)
val -= cs->colorScale.max - cs->colorScale.min + 1;
else
val = cs->colorScale.max;
}
if (val == cs->colorScale.value)
return;
tmp.value = val;
} else
tmp.value = cs->colorScale.value;
tmp.event = call->event;
XtCallCallbacks((Widget)cs, XtNvalueChangedCallback, &tmp);
/* Check if application trashed the value */
if ((tmp.value < cs->colorScale.min) || (tmp.value > cs->colorScale.max)) {
Warning(cs, warning3);
return;
}
if (tmp.value != cs->colorScale.value)
NewVal(cs, tmp.value);
}
/*
* Callback for scroll action
*/
/*ARGSUSED*/
static void Scroll(w, which, position)
Widget w;
int which;
int position;
{
ScrollbarWidget sbw = (ScrollbarWidget)w;
ColorScaleWidget cs = (ColorScaleWidget)XtParent(w);
ScaleCallbackStruct call;
float tmp;
if (position > 0)
tmp = (float)cs->colorScale.value +
((1.0 - ((float)position / (float)sbw->scrollbar.length)) *
((float)cs->colorScale.max - (float)cs->colorScale.min));
else
tmp = (float)cs->colorScale.value +
(((float)position / (float)sbw->scrollbar.length) *
((float)cs->colorScale.max - (float)cs->colorScale.min));
if (tmp > cs->colorScale.max)
tmp = cs->colorScale.max;
else if (tmp < cs->colorScale.min)
tmp = cs->colorScale.min;
call.reason = CR_VALUE_CHANGED;
call.event = NULL;
call.value = (int)tmp;
XtCallCallbacks((Widget)cs, XtNvalueChangedCallback, &call);
/* Check if application trashed the value */
if ( (call.value < cs->colorScale.min)
|| (call.value > cs->colorScale.max) ) {
Warning(cs, warning3);
return;
}
if (call.value != cs->colorScale.value)
NewVal(cs, call.value);
}
/*
* Callback for scale action
*/
/*ARGSUSED*/
static void Jump(w, which, percent_ptr)
Widget w;
int which;
float *percent_ptr;
{
ColorScaleWidget cs = (ColorScaleWidget)XtParent(w);
ScaleCallbackStruct call;
float tmp = (float)cs->colorScale.min +
((float)(1.0 - *percent_ptr) *
(float)(cs->colorScale.max - cs->colorScale.min) +
(float)(0.5));
call.reason = CR_VALUE_CHANGED;
call.event = NULL;
call.value = (int)tmp;
XtCallCallbacks((Widget)cs, XtNvalueChangedCallback, &call);
/* Check if application trashed the value */
if ( (call.value < cs->colorScale.min)
|| (call.value > cs->colorScale.max) ) {
Warning(cs, warning3);
return;
}
if (call.value != cs->colorScale.value)
NewVal(cs, call.value);
}
static void NewVal(cs, new)
ColorScaleWidget cs;
int new;
{
float top;
/* TODO: set this directly, avoiding SetValues */
cs->colorScale.value = new;
if (new < cs->colorScale.max - 7) {
top = (float)(cs->colorScale.max - (new + 8)) /
(float)(cs->colorScale.max - cs->colorScale.min + 1);
XawScrollbarSetThumb(cs->colorScale.wlist[Scrollbar], top, -1.0);
} else {
XawScrollbarSetThumb(cs->colorScale.wlist[Scrollbar], 1.0, -1.0);
}
if (cs->colorScale.zoom > 1)
SetZoom(cs);
}
/*
* ResetZoom is called when a basic change has occurred in the basic
* widget attributes like max or min. This does not happen very often.
* SetZoom is called in response to a current value change.
* ResetZoom performs a superset of SetZoom actions by calling it.
*/
static void ResetZoom(cs)
ColorScaleWidget cs;
{
Arg args[3];
XtSetArg(args[0], XtNleftMin, cs->colorScale.min);
XtSetArg(args[1], XtNleftMax, cs->colorScale.max);
/* rightMin defaults to zero, rightMax changes with zoomLen */
/* all left values change with current value */
/* rightLow and rightMax default to Min and Max */
/* rightValue changes with ZoomLen */
XtSetValues(cs->colorScale.wlist[Zoom], args, 2);
SetZoom(cs);
}
static void SetZoom(cs)
ColorScaleWidget cs;
{
int len, zoomlen;
int start;
Arg args[8];
int n = 0;
len = cs->colorScale.max - cs->colorScale.min + 1;
zoomlen = len / cs->colorScale.zoom;
start = cs->colorScale.value - zoomlen / 2;
if (start < cs->colorScale.min) {
zoomlen += start - cs->colorScale.min;
start = cs->colorScale.min;
} else if (start + zoomlen > cs->colorScale.min + len) {
zoomlen = cs->colorScale.min + len - start;
}
cs->colorScale.zoomBase = start;
cs->colorScale.zoomLen = zoomlen;
XtSetArg(args[n], XtNbase, start); n++;
XtSetArg(args[n], XtNlength, zoomlen); n++;
XtSetValues(cs->colorScale.wlist[Expand], args, n);
n = 0;
XtSetArg(args[n], XtNleftLow, start); n++;
XtSetArg(args[n], XtNleftValue, cs->colorScale.value); n++;
XtSetArg(args[n], XtNleftHigh, start+zoomlen-1); n++;
XtSetArg(args[n], XtNrightMax, zoomlen-1); n++;
XtSetArg(args[n], XtNrightValue, cs->colorScale.value - start); n++;
XtSetValues(cs->colorScale.wlist[Zoom], args, n);
}
/*
* Callback for color scale action from Colorbar.
* Use of ScaleCallbackStruct is required and handled by Colorbar.
*/
static void Single(w, which, call)
Widget w;
int which;
ScaleCallbackStruct *call;
{
ColorScaleWidget cs = (ColorScaleWidget)XtParent(w);
double spot = (float)call->value / (CbarFractionBase + 1);
int len, bs;
if (which == Bar) {
len = cs->colorScale.max - cs->colorScale.min + 1;
bs = cs->colorScale.min;
} else {
len = cs->colorScale.zoomLen;
bs = cs->colorScale.zoomBase;
}
call->value = (int)floor((double)bs + (spot * (double)len));
XtCallCallbacks((Widget)cs, XtNvalueChangedCallback, call);
/* Check if application trashed the value */
if ( (call->value < cs->colorScale.min)
|| (call->value > cs->colorScale.max) ) {
Warning(cs, warning3);
return;
}
if (call->value != cs->colorScale.value)
NewVal(cs, call->value);
}