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 >
Wrap
C/C++ Source or Header
|
1991-08-28
|
14KB
|
483 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
* Colorbar.c -- the Colorbar Widget
*
* DESCRIPTION
* This widget will display a series of entries from the colormap.
* It needs the lowest pixel, the increment value and the
* number of pixels to display to be useful. Note that
* the constraint of maximum width is a resource.
*
* HISTORY
*
* HISTORY END
*
*/
#ifndef LINT
static char *copy_notice = "Copyright 1991 Tektronix, Inc.";
#ifdef RCS_ID
static char *rcsid= "$Header: Colorbar.c,v 1.2 91/08/22 11:36:53 adamsc Exp $";
#endif /* RCS_ID */
#endif /* LINT */
#include <stdio.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/SimpleP.h>
#include <X11/Xmu/Misc.h>
#include "ColorbarP.h"
/* static char defaultTranslations[] =
* "<EnterWindow>: highlight() /n/
* <LeaveWindow>: reset() /n/
* <Btn1Down>: set() /n/
* <Btn1Up>: notify() unset() ";
*/
static char defaultTranslations[] =
"<Btn1Up>: notify()";
static XtResource resources[] = {
#define offset(field) XtOffset(ColorbarWidget, colorbar.field)
/* {name, class, type, size, offset, default_type, default_addr}, */
{ XtNbase, XtCBase, XtRPixel, sizeof(Pixel),
offset(base), XtRImmediate, (XtPointer)0 },
{ XtNlength, XtCLength, XtRInt, sizeof(int),
offset(length), XtRImmediate, (XtPointer)1 },
{ XtNpixelInc, XtCPixelInc, XtRPixel, sizeof(Pixel),
offset(pixelInc), XtRImmediate, (XtPointer)1 },
{ XtNsingleSelectionCallback, XtCCallback, XtRCallback,
sizeof(XtCallbackList), offset(select), XtRCallback, (XtPointer)NULL },
{ XtNorientation, XtCOrientation, XtROrientation, sizeof(XtOrientation),
offset(orientation), XtRImmediate, (XtPointer)XtorientVertical },
{ XtNmaxWidth, XtCMaxWidth, XtRDimension, sizeof(Dimension),
offset(max_width), XtRImmediate, (XtPointer)30 },
#undef offset
};
#define MIN_WIDTH 15
#define MIN_HEIGHT 15
/* forward declarations for the class struct */
static void Destroy();
static void Exposed();
static void HandleInput();
static void Initialize();
static void Notify();
static void Resized();
static Boolean SetValues();
static XtGeometryResult PreferredGeometry();
static XtActionsRec actionsList[] = {
{"notify", Notify}
};
ColorbarWidgetClassRec colorbarWidgetClassRec = {
{ /* core fields */
/* superclass */ (WidgetClass) &simpleClassRec,
/* class_name */ "Colorbar",
/* widget_size */ sizeof(ColorbarWidgetRec),
/* class_initialize */ NULL,
/* class_part_initialize */ NULL,
/* class_inited */ FALSE,
/* initialize */ Initialize,
/* initialize_hook */ NULL,
/* realize */ XtInheritRealize,
/* actions */ actionsList,
/* num_actions */ XtNumber(actionsList),
/* resources */ resources,
/* num_resources */ XtNumber(resources),
/* xrm_class */ NULLQUARK,
/* compress_motion */ TRUE,
/* compress_exposure */ TRUE,
/* compress_enterleave */ TRUE,
/* visible_interest */ FALSE,
/* destroy */ Destroy,
/* resize */ Resized,
/* expose */ Exposed,
/* 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 */ defaultTranslations,
/* query_geometry */ PreferredGeometry,
/* display_accelerator */ NULL,
/* extension */ NULL
},
{ /* simple fields */
/* change_sensitive */ XtInheritChangeSensitive,
},
{ /* colorbar fields */
/* extension */ NULL
}
};
WidgetClass colorbarWidgetClass = (WidgetClass)&colorbarWidgetClassRec;
/* forward declarations for utility functions */
static void Draw();
static void GetGC();
static int GetMapSize();
static char *warning1 = "orientation is not vertical or horizontal";
static char *warning3 = "length must be positive";
static char *warning4 = "widget improperly initialized";
static char *warning5 = "increment must be non-negative";
static void Destroy(cbar)
ColorbarWidget cbar;
{
if (cbar->colorbar.colorGC)
XFreeGC(XtDisplay(cbar), cbar->colorbar.colorGC);
}
/*ARGSUSED*/
static void Exposed(cbar, e, region)
ColorbarWidget cbar;
XEvent *e;
Region region;
{
Draw(cbar);
}
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)
ColorbarWidget req, new;
{
if ( (new->colorbar.orientation != XtorientVertical)
&& (new->colorbar.orientation != XtorientHorizontal) ) {
Warning(new, warning1);
new->colorbar.orientation = XtorientVertical;
}
if ((int)new->colorbar.length <= 0) {
Warning(new, warning3);
new->colorbar.length = 1;
}
if ((int)new->colorbar.pixelInc <= 0) {
Warning(new, warning5);
new->colorbar.pixelInc = 1;
}
if (req->core.width == 0)
new->core.width = MIN_WIDTH;
if (req->core.height == 0)
new->core.height = MIN_HEIGHT;
if (new->core.width > req->colorbar.max_width)
new->core.width = req->colorbar.max_width;
/* Building the GC is defered until we know there is a window, ie */
/* when the widget is first drawn */
new->colorbar.colorGC = 0;
}
/*ARGSUSED*/
static void Notify(wid, evnt, params, num_params)
Widget wid;
XEvent *evnt;
String *params; /* unused */
Cardinal *num_params; /* unused */
{
/* Should we act on press or release? Follow a drag ?? */
ColorbarWidget cbar = (ColorbarWidget)wid;
HandleInput(cbar, (XButtonEvent *)evnt);
}
static void Resized(cbar)
ColorbarWidget cbar;
{
XRectangle rect;
/* TODO: could cache drawing parameters: step, inc, rem */
if (!cbar->colorbar.colorGC)
return;
rect.x = cbar->core.border_width;
rect.y = cbar->core.border_width;
rect.width = cbar->core.width - 2 * cbar->core.border_width;
rect.height = cbar->core.height - 2 * cbar->core.border_width;
XSetClipRectangles(XtDisplay(cbar), cbar->colorbar.colorGC, 0, 0,
&rect, 1, YXBanded);
}
/*ARGSUSED*/
static Boolean SetValues(cur, req, new)
ColorbarWidget cur, req, new;
{
Boolean flag;
if ( (new->colorbar.orientation != XtorientVertical)
&& (new->colorbar.orientation != XtorientHorizontal) ) {
Warning(new, warning1);
new->colorbar.orientation = XtorientVertical;
}
if (new->colorbar.length <= 0) {
Warning(new, warning3);
new->colorbar.length = 1;
}
if ((int)new->colorbar.pixelInc <= 0) {
Warning(new, warning5);
new->colorbar.pixelInc = 1;
}
flag = (new->colorbar.orientation != cur->colorbar.orientation)
|| (new->colorbar.base != cur->colorbar.base)
|| (new->colorbar.length != cur->colorbar.length);
return(flag);
}
/*ARGSUSED*/
static XtGeometryResult PreferredGeometry(widget, request, prefer)
Widget widget;
XtWidgetGeometry *request;
XtWidgetGeometry *prefer;
{
return (XtGeometryNo);
}
/* this algorithm isn't terribly efficient, but it is simple */
static void Draw(cbar)
ColorbarWidget cbar;
{
Display *dpy = XtDisplay(cbar);
Window win = XtWindow(cbar);
Pixel increment = cbar->colorbar.pixelInc;
int len = cbar->colorbar.length;
int width, height;
int step, rem, inc;
int run = 0;
int extent;
int i;
int size;
int pix = cbar->colorbar.base;
int x, y;
if (!cbar->colorbar.colorGC) {
GetGC(cbar);
/* can now query visual of window, get size from visual */
size = GetMapSize(cbar);
} else
size = cbar->colorbar.mapSize;
width = cbar->core.width - 2 * cbar->core.border_width;
height = cbar->core.height - 2 * cbar->core.border_width;
x = cbar->core.border_width;
y = cbar->core.border_width;
/* Check if the widget is so small that colors aren't visible */
if ( (width <= 0) || (height <= 0) )
; /* prevent colors from drawing, but do allow border */
else if (cbar->colorbar.orientation == XtorientVertical) {
inc = 1;
step = height / len;
rem = height % len;
while (step < 1) {
inc++;
step = inc * height / len;
rem = (inc * height) % len;
}
extent = step + 1; /* some pixels will get painted twice */
/* color from top to bottom */
pix += (len - 1) * increment;
if (pix >= size)
pix = pix % size;
for (i = 0; i < len; i += inc) {
XSetForeground(dpy, cbar->colorbar.colorGC, pix);
XFillRectangle(dpy, win, cbar->colorbar.colorGC, x, y,
width, extent);
y += step;
run += rem;
if (run > len) {
y++;
run -= len;
}
pix -= increment;
if ((int)pix < 0)
pix = size - 1;
}
} else {
inc = 1;
step = width / len;
rem = width % len;
while (step < 4) {
inc++;
step = inc * width / len;
rem = (inc * width) % len;
}
extent = step + 1; /* some pixels will get painted twice */
/* color from left to right */
for (i = 0; i < len; i += inc) {
XSetForeground(dpy, cbar->colorbar.colorGC, pix);
XFillRectangle(dpy, win, cbar->colorbar.colorGC, x, y,
extent, height);
x += step;
run += rem;
if (run > len) {
x++;
run -= len;
}
pix += increment;
if (pix >= size)
pix -= size;
}
}
}
static void GetGC(cbar)
ColorbarWidget cbar;
{
Display *dpy;
Window win;
XGCValues gcv;
XRectangle rect;
/* the foreground of this widget will be modified, so avoid XtGetGC */
/* This should only be called when a window exists */
if (!cbar ||
!(dpy = XtDisplayOfObject((Widget)cbar)) ||
!(win = XtWindowOfObject((Widget)cbar))) {
Warning(cbar, warning4);
return;
}
gcv.fill_style = FillSolid;
cbar->colorbar.colorGC = XCreateGC(dpy, win, GCFillStyle, &gcv);
rect.x = cbar->core.border_width;
rect.y = cbar->core.border_width;
rect.width = cbar->core.width - 2 * cbar->core.border_width;
rect.height = cbar->core.height - 2 * cbar->core.border_width;
XSetClipRectangles(XtDisplay(cbar), cbar->colorbar.colorGC, 0, 0,
&rect, 1, YXBanded);
}
static int GetMapSize(cbar)
ColorbarWidget cbar;
{
Widget widget = (Widget)cbar;
Display *dpy;
Window win;
XWindowAttributes xwa;
XVisualInfo template, *returned, *pVis;
int ct, depth, i;
if (!widget)
return (0);
/* This should only be called when a window exists */
if (!(dpy = XtDisplayOfObject(widget)) ||
!(win = XtWindow(widget)) ||
!XGetWindowAttributes(dpy, win, &xwa)) {
Warning(cbar, warning4);
return(0);
}
/*
* To find the size of the colormap, get the window's visual,
* then turn the visual into a VisualInfo struct.
* (Could cheat and look inside of visual structure).
*/
template.visualid = XVisualIDFromVisual(xwa.visual);
pVis = returned = XGetVisualInfo(dpy, VisualIDMask, &template, &ct);
for (i = 0, depth = 0; i < ct; i++, pVis++) {
if (depth < pVis->depth)
depth = pVis->depth;
}
cbar->colorbar.mapSize = 1 << depth;
XFree((char *)returned);
return(cbar->colorbar.mapSize);
}
static void HandleInput(cbar, e)
ColorbarWidget cbar;
XButtonEvent *e;
{
int x, y;
int border = cbar->core.border_width;
int width = cbar->core.width - 2 * border;
int height = cbar->core.height - 2 * border;
XcmsFloat where;
ScaleCallbackStruct tmp;
x = e->x - border;
y = e->y - border;
/* but treat presses in border area as on ends */
if (x < 0)
x = 0;
else if (x > width)
x = width;
if (y < 0)
y = 0;
else if (y > height)
y = height;
if (cbar->colorbar.orientation == XtorientVertical)
where = 1.0 - (XcmsFloat)y / (XcmsFloat)height;
else
where = (XcmsFloat)x / (XcmsFloat)width;
tmp.value = (int)((XcmsFloat)CbarFractionBase * where);
tmp.event = (XEvent *)e;
tmp.reason = CR_SINGLE_SELECT;
XtCallCallbacks((Widget)cbar, XtNsingleSelectionCallback, &tmp);
}