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
/
Zoom.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-28
|
18KB
|
578 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
* Zoom.c -- the Zoom widget
*
* DESCRIPTION
* This widget is used within the ColorScale Widget to
* display the Zoom lines between the two color bars.
*
* HISTORY
*
* HISTORY END
*
*/
#ifndef LINT
static char *copy_notice = "Copyright 1991 Tektronix, Inc.";
#ifdef RCS_ID
static char *rcsid= "$Header: Zoom.c,v 1.2 91/08/22 11:36:47 adamsc Exp $";
#endif /* RCS_ID */
#endif /* LINT */
#include <stdio.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/XawInit.h>
#include <X11/Xaw/SimpleP.h>
#include "ZoomP.h"
static XtResource resources[] = {
#define offset(field) XtOffset(ZoomWidget, zoom.field)
/* {name, class, type, size, offset, default_type, default_addr}, */
{ XtNleftMin, XtCMinimum, XtRInt, sizeof(int),
offset(leftMin), XtRImmediate, (XtPointer)0 },
{ XtNleftMax, XtCMaximum, XtRInt, sizeof(int),
offset(leftMax), XtRImmediate, (XtPointer)100 },
{ XtNrightMin, XtCMinimum, XtRInt, sizeof(int),
offset(rightMin), XtRImmediate, (XtPointer)0 },
{ XtNrightMax, XtCMaximum, XtRInt, sizeof(int),
offset(rightMax), XtRImmediate, (XtPointer)100 },
{ XtNleftLow, XtCValue, XtRInt, sizeof(int),
offset(leftLow), XtRImmediate, (XtPointer)-1 },
{ XtNleftHigh, XtCValue, XtRInt, sizeof(int),
offset(leftHigh), XtRImmediate, (XtPointer)-1 },
{ XtNleftValue, XtCValue, XtRInt, sizeof(int),
offset(leftValue), XtRImmediate, (XtPointer)0 },
{ XtNrightLow, XtCValue, XtRInt, sizeof(int),
offset(rightLow), XtRImmediate, (XtPointer)-1 },
{ XtNrightHigh, XtCValue, XtRInt, sizeof(int),
offset(rightHigh), XtRImmediate, (XtPointer)-1 },
{ XtNrightValue, XtCValue, XtRInt, sizeof(int),
offset(rightValue), XtRImmediate, (XtPointer)0 },
{ XtNorientation, XtCOrientation, XtROrientation, sizeof(XtOrientation),
offset(orientation), XtRImmediate, (XtPointer)XtorientVertical },
{ XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
offset(foreground_pixel), XtRString, "XtDefaultForeground" }
#undef offset
};
#define MIN_WIDTH 15
#define MIN_HEIGHT 15
#define MAX_WIDTH 30
/* forward declarations for the class struct */
static void Initialize();
static void Destroy();
static void Exposed();
static Boolean SetValues();
#ifdef LATER
static XtGeometryResult PreferredGeometry();
#endif
ZoomWidgetClassRec zoomWidgetClassRec = {
{ /* core fields */
/* superclass */ (WidgetClass) &simpleClassRec,
/* class_name */ "Zoom",
/* widget_size */ sizeof(ZoomWidgetRec),
/* 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 */ NULL,
/* 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 */ NULL,
/* query_geometry */ NULL,
/* display_accelerator */ NULL,
/* extension */ NULL
},
{ /* simple fields */
/* change_sensitive */ XtInheritChangeSensitive,
},
{ /* zoom fields */
/* extension */ NULL
}
};
WidgetClass zoomWidgetClass = (WidgetClass)&zoomWidgetClassRec;
/* forward declarations for utility functions */
static void Draw();
static void GetZoomGC();
static char *warning1 = "orientation is not vertical or horizontal";
static char *warning2 = "maximum must be greater than minimum";
static char *warning3 = "values must be within the range [min, max]";
static char *warning4 = "improper widget initialization";
static void Destroy(self)
ZoomWidget self;
{
if (self->zoom.gc)
XFreeGC(XtDisplay(self), self->zoom.gc);
}
/*ARGSUSED*/
static void Exposed(self, e, region)
ZoomWidget self;
XEvent *e;
Region region;
{
Draw(self);
}
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)
ZoomWidget req, new;
{
if ( (new->zoom.orientation != XtorientVertical)
&& (new->zoom.orientation != XtorientHorizontal) ) {
Warning(new, warning1);
new->zoom.orientation = XtorientVertical;
}
if (new->zoom.leftMin > new->zoom.leftMax) {
Warning(new, warning2);
new->zoom.leftMax = new->zoom.leftMin + 1;
}
if (new->zoom.rightMin > new->zoom.rightMax) {
Warning(new, warning2);
new->zoom.rightMax = new->zoom.rightMin + 1;
}
if (new->zoom.leftLow < 0)
new->zoom.llEffective = new->zoom.leftMin;
else
new->zoom.llEffective = new->zoom.leftLow;
if (new->zoom.leftHigh < 0)
new->zoom.lhEffective = new->zoom.leftMax;
else
new->zoom.lhEffective = new->zoom.leftHigh;
if (new->zoom.rightLow < 0)
new->zoom.rlEffective = new->zoom.rightMin;
else
new->zoom.rlEffective = new->zoom.rightLow;
if (new->zoom.rightHigh < 0)
new->zoom.rhEffective = new->zoom.rightMax;
else
new->zoom.rhEffective = new->zoom.rightHigh;
if ( (new->zoom.llEffective < new->zoom.leftMin)
|| (new->zoom.llEffective > new->zoom.leftMax) ) {
Warning(new, warning3);
new->zoom.llEffective = new->zoom.leftMin;
}
if ( (new->zoom.lhEffective < new->zoom.leftMin)
|| (new->zoom.lhEffective > new->zoom.leftMax) ) {
Warning(new, warning3);
new->zoom.lhEffective = new->zoom.leftMax;
}
if ( (new->zoom.leftValue < new->zoom.leftMin)
|| (new->zoom.leftValue > new->zoom.leftMax) ) {
Warning(new, warning3);
new->zoom.leftValue = new->zoom.leftMin;
}
if ( (new->zoom.rlEffective < new->zoom.rightMin)
|| (new->zoom.rlEffective > new->zoom.rightMax) ) {
Warning(new, warning3);
new->zoom.rlEffective = new->zoom.rightMin;
}
if ( (new->zoom.rhEffective < new->zoom.rightMin)
|| (new->zoom.rhEffective > new->zoom.rightMax) ) {
Warning(new, warning3);
new->zoom.rhEffective = new->zoom.rightMax;
}
if ( (new->zoom.rightValue < new->zoom.rightMin)
|| (new->zoom.rightValue > new->zoom.rightMax) ) {
Warning(new, warning3);
new->zoom.rightValue = new->zoom.rightMin;
}
if (req->core.width == 0)
new->core.width = MIN_WIDTH;
if (req->core.height == 0)
new->core.height = MIN_HEIGHT;
if (req->core.width > MAX_WIDTH)
new->core.width = MAX_WIDTH;
/* graphics context creation is deferred until first draw */
new->zoom.gc = 0;
}
/*ARGSUSED*/
static Boolean SetValues(cur, req, new)
ZoomWidget cur, req, new;
{
Boolean flag;
if ( (new->zoom.orientation != XtorientVertical)
&& (new->zoom.orientation != XtorientHorizontal) ) {
Warning(new, warning1);
new->zoom.orientation = XtorientVertical;
}
if (new->zoom.leftMin > new->zoom.leftMax) {
Warning(new, warning2);
new->zoom.leftMax = new->zoom.leftMin + 1;
}
if (new->zoom.rightMin > new->zoom.rightMax) {
Warning(new, warning2);
new->zoom.rightMax = new->zoom.rightMin + 1;
}
if (new->zoom.leftLow < 0)
new->zoom.llEffective = new->zoom.leftMin;
else
new->zoom.llEffective = new->zoom.leftLow;
if (new->zoom.leftHigh < 0)
new->zoom.lhEffective = new->zoom.leftMax;
else
new->zoom.lhEffective = new->zoom.leftHigh;
if (new->zoom.rightLow < 0)
new->zoom.rlEffective = new->zoom.rightMin;
else
new->zoom.rlEffective = new->zoom.rightLow;
if (new->zoom.rightHigh < 0)
new->zoom.rhEffective = new->zoom.rightMax;
else
new->zoom.rhEffective = new->zoom.rightHigh;
if ( (new->zoom.llEffective < new->zoom.leftMin)
|| (new->zoom.llEffective > new->zoom.leftMax) ) {
Warning(new, warning3);
new->zoom.llEffective = new->zoom.leftMin;
}
if ( (new->zoom.lhEffective < new->zoom.leftMin)
|| (new->zoom.lhEffective > new->zoom.leftMax) ) {
Warning(new, warning3);
new->zoom.lhEffective = new->zoom.leftMax;
}
if ( (new->zoom.leftValue < new->zoom.leftMin)
|| (new->zoom.leftValue > new->zoom.leftMax) ) {
Warning(new, warning3);
new->zoom.leftValue = new->zoom.leftMin;
}
if ( (new->zoom.rlEffective < new->zoom.rightMin)
|| (new->zoom.rlEffective > new->zoom.rightMax) ) {
Warning(new, warning3);
new->zoom.rlEffective = new->zoom.rightMin;
}
if ( (new->zoom.rhEffective < new->zoom.rightMin)
|| (new->zoom.rhEffective > new->zoom.rightMax) ) {
Warning(new, warning3);
new->zoom.rhEffective = new->zoom.rightMax;
}
if ( (new->zoom.rightValue < new->zoom.rightMin)
|| (new->zoom.rightValue > new->zoom.rightMax) ) {
Warning(new, warning3);
new->zoom.rightValue = new->zoom.rightMin;
}
flag = (new->zoom.orientation != cur->zoom.orientation)
|| (new->zoom.leftMin != cur->zoom.leftMin)
|| (new->zoom.leftMax != cur->zoom.leftMax)
|| (new->zoom.llEffective != cur->zoom.llEffective)
|| (new->zoom.lhEffective != cur->zoom.lhEffective)
|| (new->zoom.leftValue != cur->zoom.leftValue)
|| (new->zoom.rightMin != cur->zoom.rightMin)
|| (new->zoom.rightMax != cur->zoom.rightMax)
|| (new->zoom.rlEffective != cur->zoom.rlEffective)
|| (new->zoom.rhEffective != cur->zoom.rhEffective)
|| (new->zoom.rightValue != cur->zoom.rightValue);
return(flag);
}
#ifdef LATER
static XtGeometryResult PreferredGeometry(widget, request, prefer)
Widget widget;
XtWidgetGeometry *request;
XtWidgetGeometry *prefer;
{
if (!IsZoom(widget))
return (XtGeometryNo);
prefer->width = request->width;
prefer->height = request->height;
prefer->request_mode = CWWidth | CWHeight;
if ((!(request->request_mode & (CWWidth | CWHeight))) ||
(request->width == widget->core.width &&
request->height == widget->core.height))
return (XtGeometryYes);
if (request->request_mode & CWWidth) {
if (request->width < MIN_WIDTH) {
request->width = MIN_WIDTH;
}
}
return (XtGeometryAlmost);
}
#endif /* LATER */
#define LineSize 5
#define Left 0
#define Right (LineSize-1)
#define Top Left
#define Bot Right
static void Draw(self)
ZoomWidget self;
{
Display *dpy = XtDisplay(self);
Window win = XtWindow(self);
GC gc;
int width, height;
int x, y;
XPoint ltValue, lbValue, rtValue, rbValue;
XPoint hi[LineSize], lo[LineSize];
int slots;
int i;
int tdx, bdx, tdy, bdy;
int xdiv, ydiv;
/* back out gracefully if not realized */
if (!XtIsRealized((Widget)self))
return;
if (!self->zoom.gc)
GetZoomGC(self);
gc = self->zoom.gc;
/*
* Even though this widget does not draw a box around itself,
* the widgets adjacent to it do, and the effect is to draw lines
* with reference to the surrounding widgets.
*/
/* highlight thickness ??? */
width = self->core.width - 2 * self->core.border_width;
height = self->core.height - 2 * self->core.border_width;
x = self->core.border_width;
y = self->core.border_width;
/* Check if the widget is so small that zoom should not be drawn */
if ( (width <= 0) || (height <= 0) )
return;
if (self->zoom.orientation == XtorientVertical) {
/* this assumes max on top - should be attribute */
slots = self->zoom.leftMax - self->zoom.leftMin + 1;
hi[Left].x = x;
hi[Left].y = y + (self->zoom.leftMax - self->zoom.lhEffective)
* height / slots;
ltValue.x = x;
ltValue.y = y + (self->zoom.leftMax - self->zoom.leftValue)
* height / slots;
lbValue.x = x;
lbValue.y = y - 1 + (self->zoom.leftMax - self->zoom.leftValue + 1)
* height / slots;
lo[Left].x = x;
lo[Left].y = y - 1
+ (self->zoom.leftMax - self->zoom.llEffective + 1)
* height / slots;
slots = self->zoom.rightMax - self->zoom.rightMin + 1;
hi[Right].x = x + width;
hi[Right].y = y + (self->zoom.rightMax - self->zoom.rhEffective)
* height / slots;
rtValue.x = x + width;
rtValue.y = y + (self->zoom.rightMax - self->zoom.rightValue)
* height / slots;
rbValue.x = x + width;
rbValue.y = y-1 + (self->zoom.rightMax - self->zoom.rightValue + 1)
* height / slots;
lo[Right].x = x + width;
lo[Right].y = y - 1
+ (self->zoom.rightMax - self->zoom.rlEffective + 1)
* height / slots;
/* draw value delimiters with straight lines */
XDrawLine(dpy, win, gc, ltValue.x, ltValue.y, rtValue.x, rtValue.y);
XDrawLine(dpy, win, gc, lbValue.x, lbValue.y, rbValue.x, rbValue.y);
/* draw the hi and lo zoom lines with a simple quadratic */
tdx = width;
/* zooming left to right */
if ((lo[Left].y-hi[Left].y) < (lo[Right].y-hi[Right].y)) {
tdy = hi[Right].y - hi[Left].y;
bdy = lo[Right].y - lo[Left].y;
xdiv = 2;
ydiv = 4;
for (i = Right - 1; i > Left; i--) {
hi[i].x = x + (tdx + xdiv/2) / xdiv;
hi[i].y = hi[Left].y + (tdy + ydiv/2) / ydiv;
lo[i].x = hi[i].x;
lo[i].y = lo[Left].y + (bdy + ydiv/2) / ydiv;
xdiv *= 2;
ydiv = xdiv * xdiv;
}
/* zooming right to left */
} else {
tdy = hi[Left].y - hi[Right].y;
bdy = lo[Left].y - lo[Right].y;
xdiv = 2;
ydiv = 4;
for (i = Left + 1; i < Right; i++) {
hi[i].x = x + (tdx + xdiv/2) / xdiv;
hi[i].y = hi[Right].y + (tdy + ydiv/2) / ydiv;
lo[i].x = hi[i].x;
lo[i].y = lo[Right].y + (bdy + ydiv/2) / ydiv;
xdiv *= 2;
ydiv = xdiv * xdiv;
}
}
XDrawLines(dpy, win, gc, hi, LineSize, CoordModeOrigin);
XDrawLines(dpy, win, gc, lo, LineSize, CoordModeOrigin);
/* WARNING!!!: orientation code horizontal poorly tested */
} else {
/* this assumes max on right - should be attribute */
slots = self->zoom.leftMax - self->zoom.leftMin + 1;
hi[Top].y = y;
hi[Top].x = x + (self->zoom.lhEffective * width / slots);
ltValue.y = y;
ltValue.x = x + (self->zoom.leftValue * width / slots);
lbValue.y = y;
lbValue.x = x - 1 + (self->zoom.leftValue + 1) * width / slots;
lo[Top].y = y;
lo[Top].x = x - 1 + (self->zoom.llEffective + 1) * width / slots;
slots = self->zoom.rightMax - self->zoom.rightMin + 1;
hi[Bot].y = y;
hi[Bot].x = x + (self->zoom.rhEffective * width / slots);
ltValue.y = y;
ltValue.x = x + (self->zoom.rightValue * width / slots);
lbValue.y = y;
lbValue.x = x - 1 + (self->zoom.rightValue + 1) * width / slots;
lo[Bot].y = y;
lo[Bot].x = x - 1 + (self->zoom.rlEffective + 1) * width / slots;
/* draw value delimiters with straight lines */
XDrawLine(dpy, win, gc, ltValue.x, ltValue.y, rtValue.x, rtValue.y);
XDrawLine(dpy, win, gc, lbValue.x, lbValue.y, rbValue.x, rbValue.y);
/* draw the hi and lo zoom lines with a simple quadratic */
tdy = height;
/* zooming top to bottom */
if ((lo[Top].x-hi[Top].x) < (lo[Bot].x-hi[Bot].x)) {
tdx = hi[Bot].x - hi[Top].x;
bdx = lo[Bot].x - lo[Top].x;
ydiv = 2;
xdiv = 4;
for (i = Bot - 1; i > Top; i--) {
hi[i].y = y + (tdy + ydiv/2) / ydiv;
hi[i].x = hi[Top].x + (tdx + xdiv/2) / xdiv;
lo[i].y = hi[i].y;
lo[i].x = lo[Top].x + (bdx + xdiv/2) / xdiv;
ydiv *= 2;
xdiv = ydiv * ydiv;
}
/* zooming bottom to top */
} else {
tdx = hi[Top].x - hi[Bot].x;
bdx = lo[Top].x - lo[Bot].x;
ydiv = 2;
xdiv = 4;
for (i = Top + 1; i < Bot; i++) {
hi[i].y = y + (tdy + ydiv/2) / ydiv;
hi[i].x = hi[Bot].x + (tdx + xdiv/2) / xdiv;
lo[i].y = hi[i].y;
lo[i].x = lo[Bot].x + (bdx + xdiv/2) / xdiv;
ydiv *= 2;
xdiv = ydiv * ydiv;
}
}
XDrawLines(dpy, win, gc, hi, LineSize, CoordModeOrigin);
XDrawLines(dpy, win, gc, lo, LineSize, CoordModeOrigin);
}
}
static void GetZoomGC(self)
ZoomWidget self;
{
Display *dpy;
Window win;
XGCValues gcv;
XtGCMask mask;
if (!self ||
!(dpy = XtDisplayOfObject((Widget)self)) ||
!(win = XtWindowOfObject((Widget)self))) {
Warning(self, warning4);
return;
}
gcv.fill_style = FillSolid;
gcv.background = self->core.background_pixel;
gcv.foreground = self->zoom.foreground_pixel;
mask = GCFillStyle | GCBackground | GCForeground;
self->zoom.gc = XCreateGC(dpy, win, mask, &gcv);
}