|
/*ScianColors.c
Color management routines for scian
Eric Pepke
March 15, 1990
*/
#include "Scian.h"
#include "ScianTypes.h"
#include "ScianIDs.h"
#include "ScianArrays.h"
#include "ScianWindows.h"
#include "ScianObjWindows.h"
#include "ScianButtons.h"
#include "ScianColors.h"
#include "ScianEvents.h"
#include "ScianErrors.h"
#include "ScianScripts.h"
#include "ScianPictures.h"
#include "ScianControls.h"
#include "ScianDialogs.h"
#include "ScianSliders.h"
#include "ScianDatasets.h"
#include "ScianStyle.h"
#include "ScianTitleBoxes.h"
#include "ScianTextBoxes.h"
#include "ScianLists.h"
#include "ScianMethods.h"
#include "ScianDraw.h"
#include "ScianIcons.h"
#include "ScianFiles.h"
#include "ScianVisWindows.h"
#include "ScianObjFunctions.h"
#include "ScianTemplates.h"
#include "ScianTemplateHelper.h"
#ifdef GRAPHICS
#ifndef GL4D
#include "gamtables.h"
#endif
#define OVERCLEAR 0 /*Clear in overlay planes*/
#define OVERRED 1 /*Red in overlay planes*/
#ifdef GL4D
/*No gamma correction on the 4d*/
#define CVAL(k) k
#else
/*3000's need gammacorrection*/
#define CVAL(k) LinToGamma[k]
#endif
#endif
int overDraw = 0; /*Counter for overlay drawing*/
short curRed, curGreen, curBlue; /*Current color components in other
than screen draw mode*/
ObjPtr iconColorPalette;
char *spfNames[NPALETTEFUNCS] =
{
"ramp",
"reverse",
"ruffle",
"smooth",
"sharpen"
};
char *toolNames[NPALETTETOOLS] =
{
"free form",
"sine wave",
"triangle wave",
"sawtooth wave",
"reverse sawtooth wave",
"square wave"
};
char *componentNames[NCOLORMODELS][3] =
{
{"red", "green", "blue"},
{"\"Y\"", "\"I\"", "\"Q\""},
{"hue", "saturation", "value"},
{"hue", "lightness", "saturation"}
};
char *shortComponentNames[NCOLORMODELS][3] =
{
{"R", "G", "B"},
{"Y", "I", "Q"},
{"H", "S", "V"},
{"H", "L", "S"}
};
char *colorModelNames[NCOLORMODELS] =
{
"RGB",
"YIQ",
"HSV",
"HLS"
};
real RGB2YIQMat[3][3] =
{{ 0.30, 0.59, 0.11},
{ 0.60, -0.28, -0.32},
{ 0.21, -0.52, 0.31}};
real YIQ2RGBMat[3][3] =
{{ 1.0000, 0.9483, 0.6240},
{ 1.0000, -0.2761, -0.6398},
{ 1.0000, -1.1055, 1.7299}};
int paletteSerialNum = 0; /*Serial num for palettes*/
static int ColorToPixel(ObjPtr, int);
static int PixelToColor(ObjPtr, int);
static int AllocColors(int);
typedef struct cr
{
struct cr *next; /*Next color range*/
int beg, end; /*Beginning and end (+ 1)*/
} ColorRange;
ColorRange *colorRanges; /*The available color ranges*/
PPtr activePalettes = 0; /*The active palettes*/
#define COLORWHEELBORDER 6 /*Border around HS control*/
#define COLORWHEELSPOTSIZE 4 /*Size of spot in HS control*/
int curUIColorIndex; /*Global current color index*/
short uiColors[NUICOLORS][3]; /*Components for the UI colors*/
int uiColorIndex[NUICOLORS]; /*Indices for ui colors*/
short3 *colorsToScavenge; /*Colors to scavenge*/
int nScavengeColors = 0; /*Number of colors for scavenging*/
PPtr curPalette; /*Current palette*/
int curNColors; /*Current number of colors*/
real curMin, curMax; /*Current min and max values*/
int curBeg;
real diffMult; /*Amount to multiply to get difference*/
short3 *curColors;
ObjPtr paletteClass; /*Class for a color palette*/
ObjPtr paletteDisplayClass; /*Class for a palette display*/
ObjPtr colorControlClass;
ObjPtr colorWheelClass;
ObjPtr colorBarClass;
#define COLORFAILTIMEOUT 60 /*Color failure timeout in seconds*/
long colorFailTime = 0; /*Time of last color failure*/
#define COLORWHEELHEIGHT 4 /*Height of a color wheel*/
#ifdef PROTO
static void SetColorComponent(PPtr palette, int whichColor, int comp, int cc);
static int GetColorComponent(PPtr palette, int whichColor, int comp);
#endif
static short o0r, o0g, o0b;
static short o1r, o1g, o1b;
static short o2r, o2g, o2b;
#ifdef PROTO
void OverDraw(Bool whether)
#else
void OverDraw(whether)
Bool whether;
#endif
/*Sets system into overlay drawing mode, or not*/
{
if (hasOverDraw == false)
{
printf("No overlay drawing!\n");
return;
}
#ifdef GRAPHICS
if (whether)
{
if (!overDraw++)
{
pushattributes();
drawmode(pupForOverDraw ? PUPDRAW : OVERDRAW);
getmcolor(OVERCLEAR, &o0r, &o0g, &o0b);
getmcolor(OVERRED, &o1r, &o1g, &o1b);
mapcolor(OVERCLEAR, 0, 0, 0);
mapcolor(OVERRED, 255, 0, 0);
color(1);
}
}
else
{
if (0 == --overDraw)
{
color(0);
clear();
mapcolor(OVERCLEAR, o0r, o0g, o0b);
mapcolor(OVERRED, o1r, o1g, o1b);
drawmode(NORMALDRAW);
popattributes();
}
}
#endif
}
#ifdef PROTO
void MapPalette(ObjPtr p)
#else
void MapPalette(p)
ObjPtr p;
#endif
/*Maps palette p*/
{
#ifdef GRAPHICS
int k;
if (hasCmap == false) return;
if (((PPtr) p) -> beg < 0) return;
for (k = 0; k < ((PPtr) p) -> nColors; ++k)
{
mapcolor(((PPtr) p) -> beg + k,
((PPtr) p) -> colors[k][0],
((PPtr) p) -> colors[k][1],
((PPtr) p) -> colors[k][2]);
TinyDelay();
}
#endif
}
#ifdef PROTO
void MapPaletteColors(PPtr p, int start, int end)
#else
void MapPaletteColors(p, start, end)
PPtr p; int start; int end;
#endif
/*Maps color from start to end in palette p*/
{
#ifdef GRAPHICS
int k;
if (hasCmap == false) return;
if (((PPtr) p) -> beg < 0) return;
for (k = start; k < MAX(((PPtr) p) -> nColors, end + 1); ++k)
{
mapcolor(((PPtr) p) -> beg + k,
((PPtr) p) -> colors[k][0],
((PPtr) p) -> colors[k][1],
((PPtr) p) -> colors[k][2]);
TinyDelay();
}
#endif
}
#ifdef PROTO
void CopyColorsToComponents(PPtr p, int start, int finish)
#else
void CopyColorsToComponents(p, start, finish)
PPtr p; int start; int finish;
#endif
/*Copies the colors to components based on color model*/
{
ObjPtr var;
int cm, k;
short3 *colors, *components;
real r, g, b, h, s, v, l, y, i, q;
var = GetIntVar("CopyColorsToComponents", (ObjPtr) p, COLORMODEL);
if (var)
{
cm = GetInt(var);
}
else
{
cm = CM_RGB;
}
colors = p -> colors;
components = p -> components;
for (k = start; k <= finish; ++k)
{
switch (cm)
{
case CM_RGB:
components[k][0] = colors[k][0];
components[k][1] = colors[k][1];
components[k][2] = colors[k][2];
break;
case CM_HSV:
r = ((real) colors[k][0]) / 255.0;
g = ((real) colors[k][1]) / 255.0;
b = ((real) colors[k][2]) / 255.0;
RGB2HSV(&h, &s, &v, r, g, b);
components[k][0] = h * 255.0 + 0.5;
components[k][1] = s * 255.0 + 0.5;
components[k][2] = v * 255.0 + 0.5;
break;
case CM_HLS:
r = ((real) colors[k][0]) / 255.0;
g = ((real) colors[k][1]) / 255.0;
b = ((real) colors[k][2]) / 255.0;
RGB2HLS(&h, &l, &s, r, g, b);
components[k][0] = h * 255.0 + 0.5;
components[k][1] = l * 255.0 + 0.5;
components[k][2] = s * 255.0 + 0.5;
break;
case CM_YIQ:
r = ((real) colors[k][0]) / 255.0;
g = ((real) colors[k][1]) / 255.0;
b = ((real) colors[k][2]) / 255.0;
RGB2YIQ(&y, &i, &q, r, g, b);
components[k][0] = y * 255.0 + 0.5;
components[k][1] = i * 255.0 + 0.5;
components[k][2] = q * 255.0 + 0.5;
break;
default:
components[k][0] = colors[k][0];
components[k][1] = colors[k][1];
components[k][2] = colors[k][2];
break;
}
}
}
#ifdef PROTO
void CopyComponentsToColors(PPtr p, int start, int finish)
#else
void CopyComponentsToColors(p, start, finish)
PPtr p; int start; int finish;
#endif
/*Copies the colors to components based on color model*/
{
ObjPtr var;
int cm, k;
short3 *colors, *components;
real r, g, b, h, s, v, l, y, i, q;
var = GetIntVar("CopyComponentsToColors", (ObjPtr) p, COLORMODEL);
if (var)
{
cm = GetInt(var);
}
else
{
cm = CM_RGB;
}
colors = p -> colors;
components = p -> components;
for (k = start; k <= finish; ++k)
{
switch (cm)
{
case CM_RGB:
colors[k][0] = components[k][0];
colors[k][1] = components[k][1];
colors[k][2] = components[k][2];
break;
case CM_HSV:
h = ((real) components[k][0]) / 255.0;
s = ((real) components[k][1]) / 255.0;
v = ((real) components[k][2]) / 255.0;
HSV2RGB(&r, &g, &b, h, s, v);
colors[k][0] = r * 255.0 + 0.5;
colors[k][1] = g * 255.0 + 0.5;
colors[k][2] = b * 255.0 + 0.5;
break;
case CM_HLS:
h = ((real) components[k][0]) / 255.0;
l = ((real) components[k][1]) / 255.0;
s = ((real) components[k][2]) / 255.0;
HLS2RGB(&r, &g, &b, h, l, s);
colors[k][0] = r * 255.0 + 0.5;
colors[k][1] = g * 255.0 + 0.5;
colors[k][2] = b * 255.0 + 0.5;
break;
case CM_YIQ:
y = ((real) components[k][0]) / 255.0;
i = ((real) components[k][1]) / 255.0;
q = ((real) components[k][2]) / 255.0;
YIQ2RGB(&r, &g, &b, y, i, q);
colors[k][0] = r * 255.0 + 0.5;
colors[k][1] = g * 255.0 + 0.5;
colors[k][2] = b * 255.0 + 0.5;
break;
default:
components[k][0] = colors[k][0];
components[k][1] = colors[k][1];
components[k][2] = colors[k][2];
break;
}
}
}
void CopyColorsToPalette(p, colors)
ObjPtr p;
short3 *colors;
/*Copies the colors into palette p*/
{
int k;
for (k = 0; k < ((PPtr) p) -> nColors; ++k)
{
((PPtr) p) -> colors[k][0] = colors[k][0];
((PPtr) p) -> colors[k][1] = colors[k][1];
((PPtr) p) -> colors[k][2] = colors[k][2];
}
CopyColorsToComponents((PPtr) p, 0, ((PPtr) p) -> nColors - 1);
}
void FieldPaletteName(palette, field)
ObjPtr palette, field;
/*Names a palette based on a field*/
{
ObjPtr name;
MakeVar(field, NAME);
name = GetStringVar("FieldPaletteName", field, NAME);
if (!name)
{
return;
}
strcpy(tempStr, GetString(name));
strcat(tempStr, " Palette");
SetVar(palette, NAME, NewString(tempStr));
}
ObjPtr MakePaletteName(palette)
ObjPtr palette;
/*Makes a name for a palette*/
{
if (GetVar(palette, NAME))
{
return ObjFalse;
}
else
{
sprintf(tempStr, "Palette %ld", ++paletteSerialNum);
SetVar(palette, NAME, NewString(tempStr));
return ObjTrue;
}
}
void AlertColorFailure()
/*Alerts the user that a color allocation has failed*/
{
WinInfoPtr errWindow;
errWindow = AlertUser(UICAUTIONALERT, (WinInfoPtr) 0,
"SciAn has run out of color table entries. It will continue to try to find enough \
colors to run normally. Until it does, you may see some unusual colors in \
some windows.",
0, 0, "Oh well");
SetVar((ObjPtr) errWindow, HELPSTRING,
NewString("All the windows of SciAn, as well as the windows of other \
processes, share the same color table. When there are several visualizations \
on the screen, SciAn must share the color table between windows. It tries to \
allocate and deallocate chunks of the color table according to need, but \
sometimes the number of visualizations grows so large that there are simply not \
enough colors to go around.\n\
\n\
SciAn will continue to try to allocate colors. You can reduce the number of \
colors you are using by a number of ways. If your computer can do 24-bit RGB, \
you can set some of the visualization windows to Full Color by clicking on the \
Full Color button at the bottom right of the visualization window. You can close \
visualization windows that you are not using. You can color some of the \
visualizations white or increase visualizations colored by datasets to full \
brightness."));
}
void SetPalette(p)
ObjPtr p;
/*Sets the current palette to p*/
{
PPtr tp;
tp = (PPtr) p;
curPalette = tp;
curNColors = tp -> nColors;
curMin = tp -> min;
curMax = tp -> max;
#ifdef GRAPHICS
if ((tp -> beg < 0) && (false == rgbp))
{
/*Allocate some colors on demand*/
tp -> beg = AllocColors(curNColors);
if (tp -> beg >= 0)
{
/*Allocation succeeded*/
MapPalette(p);
curBeg = tp -> beg + 2;
}
else
{
/*Allocation failed*/
struct tms buffer;
long curTime;
curTime = times(&buffer) / HEARTBEAT;
if (curTime > colorFailTime + COLORFAILTIMEOUT)
{
colorFailTime = curTime;
DoUniqueTask(AlertColorFailure);
}
curNColors = uiColorIndex[UIWHITE] -
uiColorIndex[UIBLACK];
curBeg = uiColorIndex[UIBLACK];
}
}
else
#endif
{
curBeg = tp -> beg + 2;
}
curColors = tp -> colors + 2;
diffMult = ((real) curNColors - 4) / (curMax - curMin);
}
#ifdef PROTO
void SetPaletteMinMax(ObjPtr p, real min, real max)
#else
void SetPaletteMinMax(p, min, max)
ObjPtr p;
real min, max;
#endif
/*Sets the min and max of palette p to min and max*/
{
((PPtr) p) -> min = min;
((PPtr) p) -> max = max;
SetVar(p, CHANGED, ObjTrue);
}
static void CompactColors()
/*Compacts all the colors*/
{
ColorRange *runner;
if (colorRanges == 0)
{
ReportError("CompactColors", "No color ranges");
return;
}
runner = colorRanges;
while (runner && runner -> next)
{
if (runner -> end >= runner -> next -> beg)
{
/*Compact two adjacent colors*/
ColorRange *next;
runner -> end = runner -> next -> end;
next = runner -> next -> next;
free(runner -> next);
runner -> next = next;
}
else
{
runner = runner -> next;
}
}
}
static int AllocColors(n)
int n;
/*Allocates n contiguous colors, returns their start or -1*/
{
ColorRange **runner, **bestFit;
int fit; /*Fit of best fit so far*/
if (colorRanges == 0)
{
ReportError("AllocColors", "No color ranges");
return -1;
}
/*Compact the colors*/
CompactColors();
/*Search for best fit*/
fit = 32767;
bestFit = (ColorRange **) 0;
runner = &colorRanges;
while (*runner)
{
int nAvailable;
nAvailable = (*runner) -> end - (*runner) -> beg;
if (nAvailable >= n)
{
if (nAvailable - n < fit)
{
fit = nAvailable - n;
bestFit = runner;
}
}
runner = &((*runner) -> next);
}
if (bestFit)
{
int retVal;
retVal = (*bestFit) -> beg;
if (fit == 0)
{
/*Must delete this fit*/
ColorRange *thisFit;
thisFit = (*bestFit);
free(thisFit);
(*bestFit) = (*bestFit) -> next;
}
else
{
/*Just need to adjust it*/
(*bestFit) -> beg += n;
}
return retVal;
}
else
{
/*Allocation failed*/
return -1;
}
}
static void FreeColors(start, n)
int start, n;
/*Frees n contiguous colors at start*/
{
ColorRange **runner, *next;
if (colorRanges == 0)
{
ReportError("FreeColors", "No color ranges");
return;
}
/*Add a new color range at the appropriate point*/
runner = &colorRanges;
while (*runner && (*runner) -> beg < start + n)
{
runner = &((*runner) -> next);
}
next = *runner;
*runner = new(ColorRange);
(*runner) -> beg = start;
(*runner) -> end = start + n;
(*runner) -> next = next;
}
static void MakeUIColor(whichColor, r, g, b)
int whichColor;
short r, g, b;
/*Makes UI color whichColor to r, g, b*/
{
#ifdef GRAPHICS
r = CVAL(r);
g = CVAL(g);
b = CVAL(b);
/*Search the existing colors for the best match.*/
if (hasCmap && scavengeColors)
{
short bestR, bestG, bestB;
int bestC;
short testR, testG, testB;
int testC;
int bestDist = MAXCDIST + 1;
int testDist;
for (testC = 0; testC < nScavengeColors; ++testC)
{
if (testC < 16 || testC >= 32)
{
/*Colors between 16 and 32 unreliable*/
testR = colorsToScavenge[testC][0];
testG = colorsToScavenge[testC][1];
testB = colorsToScavenge[testC][2];
testDist = MAX(ABS(testR - r), MAX(ABS(testG - g), ABS(testB - b)));
if (testDist <= bestDist) /*Change to < for first not last*/
{
if ((r == g) && (g == b))
{
/*Test for gray dirtiness failure*/
if (MAX(testR, MAX(testG, testB)) -
MIN(testR, MIN(testG, testB))
> MAXGRAYDIRT)
{
/*Disallow this one and continue search*/
continue;
}
}
bestDist = testDist;
bestR = testR;
bestG = testG;
bestB = testB;
bestC = testC;
}
}
}
/*Now see if it's good enough*/
if (bestDist <= MAXCDIST)
{
/*It's OK, use this one*/
if (showConfig)
{
printf("Best match to UI color %d (%d %d %d) found at %d (%d %d %d)\n",
whichColor, r, g, b, (int) bestC, (int) bestR, (int) bestG, (int) bestB);
}
uiColorIndex[whichColor] = bestC;
}
else
{
/*No good, allocate one*/
if (hasCmap)
{
if (showConfig)
{
printf("UI Color %d (%d %d %d) failed color scavenge search. Allocated at %d.\n",
whichColor, r, g, b, curUIColorIndex);
}
uiColorIndex[whichColor] = curUIColorIndex++;
mapcolor(uiColorIndex[whichColor], r, g, b);
TinyDelay();
}
else
{
uiColorIndex[whichColor] = -1;
if (showConfig)
{
printf("UI Color %d (%d %d %d) failed color scavenge search. Not allocated.\n",
whichColor, r, g, b);
}
}
}
}
else
{
/*Just use the next value in the color map*/
if (hasCmap)
{
if (showConfig)
{
printf("UI Color %d (%d %d %d) allocated at %d.\n",
whichColor, r, g, b, curUIColorIndex);
}
uiColorIndex[whichColor] = curUIColorIndex++;
if (hasCmap)
{
mapcolor(uiColorIndex[whichColor], r, g, b);
TinyDelay();
}
}
else
{
if (showConfig)
{
printf("UI Color %d (%d %d %d) not allocated because it's always RGB.\n",
whichColor, r, g, b);
}
uiColorIndex[whichColor] = -1;
}
}
uiColors[whichColor][0] = r;
uiColors[whichColor][1] = g;
uiColors[whichColor][2] = b;
#endif
}
#ifdef PROTO
int ClosestUIColor(float clr[3])
#else
int ClosestUIColor(clr)
float clr[3];
#endif
/*Returns the closest UI color to clr*/
{
int k;
short r, g, b;
short bestError;
short best;
r = clr[0] * 256.0;
g = clr[1] * 256.0;
b = clr[2] * 256.0;
bestError = 5000; /*Big*/
for (k = 0; k < NUICOLORS; ++k)
{
short error;
error = ABS(uiColors[k][0] - r) +
ABS(uiColors[k][1] - g) +
ABS(uiColors[k][2] - b);
if (error < bestError)
{
bestError = error;
best = k;
}
}
return best;
}
static ObjPtr DrawColorWheel(object)
ObjPtr object;
/*Draws an HS control*/
{
#ifdef GRAPHICS
int left, right, bottom, top;
int cx, cy;
int width, height, radius;
ObjPtr backColor; /*Color of the background*/
FuncTyp drawContents; /*Routine to draw the contents*/
ObjPtr valueArray;
real value[2];
Get2DIntBounds(object, &left, &right, &bottom, &top);
/*Draw the control frame*/
DrawRaisedRect(left, right, bottom, top, UIGRAY50);
/*Draw the color background*/
cx = (left + right) / 2;
cy = (bottom + top) / 2;
width = right - left;
height = top - bottom;
if (width > height)
{
radius = height / 2 - COLORWHEELBORDER;
}
else
{
radius = width / 2 - COLORWHEELBORDER;
}
/*Draw the color wedges*/
FillUIWedge(cx, cy, radius, -30, 30, UIRED);
FillUIWedge(cx, cy, radius, 30, 90, UIYELLOW);
FillUIWedge(cx, cy, radius, 90, 150, UIGREEN);
FillUIWedge(cx, cy, radius, 150, 210, UICYAN);
FillUIWedge(cx, cy, radius, 210, 270, UIBLUE);
FillUIWedge(cx, cy, radius, 270, 330, UIMAGENTA);
FillUIGauzeDisc(cx, cy, (int) radius * 2 / 3, UIWHITE);
FillUIDisc(cx, cy, (int) radius / 3, UIWHITE);
/*Draw the spot*/
valueArray = GetVar(object, VALUE);
if (valueArray)
{
Array2CArray(value, valueArray);
SetUIColor(UIBLACK);
cx += radius * value[1] * cos(2.0 * M_PI * value[0]);
cy += radius * value[1] * sin(2.0 * M_PI * value[0]);
DrawUILine(cx - COLORWHEELSPOTSIZE, cy, cx + COLORWHEELSPOTSIZE, cy, UIBLACK);
DrawUILine(cx, cy - COLORWHEELSPOTSIZE, cx, cy + COLORWHEELSPOTSIZE, UIBLACK);
}
if (!GetPredicate(object, ACTIVATED))
{
FillUIGauzeRect(left, right, bottom, top, UIBACKGROUND);
}
#endif
return ObjTrue;
}
#ifdef PROTO
void RGB2YIQ(real *y, real *i, real*q, real r, real g, real b)
#else
void RGB2YIQ(y, i, q, r, g, b)
real *y, *i, *q, r, g, b;
#endif
/*Converts r, g, b, into y, i, q*/
{
*y = RGB2YIQMat[0][0] * r +
RGB2YIQMat[0][1] * g +
RGB2YIQMat[0][2] * b;
*i = RGB2YIQMat[1][0] * r +
RGB2YIQMat[1][1] * g +
RGB2YIQMat[1][2] * b;
*q = RGB2YIQMat[2][0] * r +
RGB2YIQMat[2][1] * g +
RGB2YIQMat[2][2] * b;
*i = (*i + 0.6) / 1.2;
*q = (*q + 0.52) / 1.04;
if (*y < 0.0) *y = 0.0;
if (*y > 1.0) *y = 1.0;
if (*i < 0.0) *i = 0.0;
if (*i > 1.0) *i = 1.0;
if (*q < 0.0) *q = 0.0;
if (*q > 1.0) *q = 1.0;
}
#ifdef PROTO
void YIQ2RGB(real *r, real *g, real *b, real y, real i, real q)
#else
void YIQ2RGB(r, g, b, y, i, q)
real y, i, q, *r, *g, *b;
#endif
/*Converts y, i, q, into r, g, b*/
{
i = i * 1.2 - 0.6;
q = q * 1.04 - 0.52;
*r = YIQ2RGBMat[0][0] * y +
YIQ2RGBMat[0][1] * i +
YIQ2RGBMat[0][2] * q;
*g = YIQ2RGBMat[1][0] * y +
YIQ2RGBMat[1][1] * i +
YIQ2RGBMat[1][2] * q;
*b = YIQ2RGBMat[2][0] * y +
YIQ2RGBMat[2][1] * i +
YIQ2RGBMat[2][2] * q;
if (*r < 0.0) *r = 0.0;
if (*r > 1.0) *r = 1.0;
if (*g < 0.0) *g = 0.0;
if (*g > 1.0) *g = 1.0;
if (*b < 0.0) *b = 0.0;
if (*b > 1.0) *b = 1.0;
}
#ifdef PROTO
void HSV2RGB(real *r, real *g, real *b, real h, real s, real v)
#else
void HSV2RGB(r, g, b, h, s, v)
real *r, *g, *b, h, s, v;
#endif
/*Converts h s v into r g b. All within range 0..1
Adapted from Foley & VanDam*/
{
int i;
real f;
real p, q, t;
while (h < 0.0) h += 1.0;
while (h > 1.0) h -= 1.0;
h *= 6; /*h from 0 to 6*/
i = h;
f = h - i; /*fractional part of i*/
i %= 6; /*i from 0 to 5*/
p = v * (1.0 - s);
q = v * (1.0 - (s * f));
t = v * (1.0 - (s * (1.0 - f)));
switch (i)
{
case 0:
*r = v;
*g = t;
*b = p;
break;
case 1:
*r = q;
*g = v;
*b = p;
break;
case 2:
*r = p;
*g = v;
*b = t;
break;
case 3:
*r = p;
*g = q;
*b = v;
break;
case 4:
*r = t;
*g = p;
*b = v;
break;
case 5:
*r = v;
*g = p;
*b = q;
break;
}
}
#ifdef PROTO
real HLSValue(real n1, real n2, real h)
#else
real HLSValue(n1, n2, h)
real n1; real n2; real h;
#endif
{
while (h < 0.0) h += 1.0;
while (h > 1.0) h -= 1.0;
if (h < 1.0 / 6.0)
{
return n1 + (n2 - n1) * h * 6.0;
}
else if (h < 0.5)
{
return n2;
}
else if (h < 4.0 / 6.0)
{
return n1 + (n2 - n1) * (4.0 / 6.0 - h) * 6.0;
}
else
{
return n1;
}
}
#ifdef PROTO
void HLS2RGB(real *r, real *g, real *b, real h, real l, real s)
#else
void HLS2RGB(r, g, b, h, l, s)
real *r, *g, *b, h, s, l;
#endif
/*Converts h l s into r g b. All within range 0..1
Adapted from Foley & VanDam*/
{
real m1, m2;
if (l <= 0.5)
{
m2 = l * (1.0 + s);
}
else
{
m2 = l + s - l * s;
}
m1 = 2 * l - m2;
if (s == 0)
{
*r = *g = *b = 1.0;
}
else
{
*r = HLSValue(m1, m2, h + 1.0 / 3.0);
*g = HLSValue(m1, m2, h);
*b = HLSValue(m1, m2, h - 1.0 / 3.0);
}
}
#ifdef PROTO
void RGB2HSV(real *h, real *s, real *v, real r, real g, real b)
#else
void RGB2HSV(h, s, v, r, g, b)
real r, g, b, *h, *s, *v;
#endif
/*Converts rgb to hsv. All numbers within range 0 to 1.*/
{
real max, min;
max = MAX(r, MAX(g, b));
min = MIN(r, MIN(g, b));
*v = max;
if (max > 0.0)
{
*s = (max - min) / max;
}
else
{
*s = 0;
}
if (*s > 0.0)
{
real rc, gc, bc;
rc = (max - r) / (max - min);
gc = (max - g) / (max - min);
bc = (max - b) / (max - min);
if (r == max)
{
*h = (bc - gc) / 6.0;
}
else if (g == max)
{
*h = (2.0 + rc - bc) / 6.0;
}
else
{
*h = (4.0 + gc - rc) / 6.0;
}
}
else
{
*h = 0.0;
}
if (*h < 0.0) *h += 1.0;
}
#ifdef PROTO
void RGB2HLS(real *h, real *l, real *s, real r, real g, real b)
#else
void RGB2HLS(h, l, s, r, g, b)
real r, g, b, *h, *s, *l;
#endif
/*Converts rgb to hls. All numbers within range 0 to 1.*/
{
real max, min;
max = MAX(r, MAX(g, b));
min = MIN(r, MIN(g, b));
*l = (max + min) * 0.5;
if (max == min)
{
*s = 0.0;
*h = 0.0;
}
else
{
real rc, gc, bc;
if (*l <= 0.5)
{
*s = (max - min) / (max + min);
}
else
{
*s = (max - min) / (2 - max - min);
}
rc = (max - r) / (max - min);
gc = (max - g) / (max - min);
bc = (max - b) / (max - min);
if (r == max)
{
*h = (bc - gc) / 6.0;
}
else if (g == max)
{
*h = (2.0 + rc - bc) / 6.0;
}
else
{
*h = (4.0 + gc - rc) / 6.0;
}
}
}
static ObjPtr TrackColorWheel(object, mouseX, mouseY, flags)
ObjPtr object;
int mouseX, mouseY;
long flags;
/*Track a click in an HS control. Double-click snaps to closest pure hue*/
{
int left, right, bottom, top;
int cx, cy;
int width, height, radius;
ObjPtr backColor; /*Color of the background*/
FuncTyp drawContents; /*Routine to draw the contents*/
ObjPtr valueArray;
real value[2];
int lastX, lastY; /*Last X and Y mouse position*/
int sX, sY; /*Shifted x and y for calculation*/
Bool dontTrack; /*True iff don't track*/
Get2DIntBounds(object, &left, &right, &bottom, &top);
if (mouseX < left || mouseX > right || mouseY < bottom || mouseY > top)
{
return ObjFalse;
}
if (TOOL(flags) == T_HELP)
{
ContextHelp(object);
return ObjTrue;
}
if (!GetPredicate(object, ACTIVATED)) return ObjTrue;
cx = (left + right) / 2;
cy = (bottom + top) / 2;
width = right - left;
height = top - bottom;
if (width > height)
{
radius = height / 2 - COLORWHEELBORDER;
}
else
{
radius = width / 2 - COLORWHEELBORDER;
}
/*Get the current value of the control*/
valueArray = GetFixedArrayVar("TrackColorWheel", object, VALUE, 1, 2L);
if (!valueArray)
{
return ObjFalse;
}
Array2CArray(value, valueArray);
/*Make laxtX and lastY correspond to value*/
lastX = cx + value[1] * cos(2.0 * M_PI * value[0]);
lastY = cy + value[1] * sin(2.0 * M_PI * value[0]);
if (flags & F_DOUBLECLICK)
{
/*Snap current value to closest pure hue*/
if (value[1] < 0.33)
{
/*White*/
value[1] = 0.0;
}
else
{
int testo;
/*50 % or 100% saturated something*/
if (value[1] > 0.66)
{
value[1] = 1.0;
}
else
{
value[1] = 0.5;
}
testo = value[0] * 6.0 + 0.5;
value[0] = ((real) testo) / 6.0;
}
valueArray = NewRealArray(1, 2L);
CArray2Array(valueArray, value);
SetVar(object, VALUE, valueArray);
DrawMe(object);
ChangedValue(object);
if (logging)
{
LogControl(object);
}
return ObjTrue;
}
dontTrack = GetPredicate(object, TRACKNOT);
InhibitLogging(true);
while (Mouse(&mouseX, &mouseY))
{
if (mouseX != lastX || mouseY != lastY)
{
real hue, saturation;
/*Mouse has moved. Update.*/
sX = mouseX - cx;
sY = mouseY - cy;
if (sX == 0 && sY == 0)
{
/*It's at the origin, so choose 0 for h and s*/
hue = 0.0;
saturation = 0.0;
}
else
{
/*Hue is angle*/
hue = atan2(((double) sY) / ((double) radius),
((double) sX) / ((double) radius)) / (2.0 * M_PI);
while (hue < 0.0) hue += 1.0;
/*Saturation is radius, clipped*/
saturation = sqrt(((double) sY) * ((double) sY) +
((double) sX) * ((double) sX)) / ((double) radius);
if (saturation > 1.0) saturation = 1.0;
if (flags & F_SHIFTDOWN)
{
if (saturation > 0.66)
{
saturation = 1.0;
}
else if (saturation > 0.33)
{
saturation = 0.5;
}
else
{
saturation = 0.0;
}
}
}
/*See if value is different*/
valueArray = GetVar(object, VALUE);
if (valueArray)
{
Array2CArray(value, valueArray);
if (hue == value[0] && saturation == value[1])
{
continue;
}
}
value[0] = hue;
value[1] = saturation;
valueArray = NewRealArray(1, 2L);
CArray2Array(valueArray, value);
SetVar(object, VALUE, valueArray);
DrawMe(object);
if (!dontTrack)
{
ChangedValue(object);
}
}
}
if (dontTrack)
{
ChangedValue(object);
}
InhibitLogging(false);
if (logging)
{
LogControl(object);
}
return ObjTrue;
}
ObjPtr SetColorWheelVal(object, value)
ObjPtr object;
ObjPtr value;
/*Sets the value of the object to value*/
{
if (value == NULLOBJ ||
(IsRealArray(value) && RANK(value) == 1 && DIMS(value)[0] == 2))
{
SetVar(object, VALUE, value);
ImInvalid(object);
ChangedValue(object);
if (logging)
{
LogControl(object);
}
return ObjTrue;
}
else
{
return ObjFalse;
}
}
static ObjPtr CleanupPalette(palette)
ObjPtr palette;
/*Cleans up the palette before deleting*/
{
PPtr *runner;
if (((PPtr) palette) -> beg > 0 && ((PPtr) palette) -> nColors > 0)
{
/*There are some colors*/
FreeColors(((PPtr) palette) -> beg, ((PPtr) palette) -> nColors);
}
if (((PPtr) palette) -> colors)
{
free(((PPtr) palette) -> colors);
((PPtr) palette) -> colors = 0;
}
if (((PPtr) palette) -> components)
{
free(((PPtr) palette) -> components);
((PPtr) palette) -> components = 0;
}
runner = &activePalettes;
while (*runner)
{
if (*runner == (PPtr) palette)
{
*runner = (*runner) -> next;
}
else
{
runner = &((*runner) -> next);
}
}
return ObjTrue;
}
ObjPtr NewPalette(nColors)
int nColors;
/*Returns a new palette of nColors, initially set to a grey ramp. Returns
0 if it can't.*/
{
int k, colorBeg;
PPtr retVal;
short3 *colors, *components;
colors = (short3 *) malloc(sizeof(short3) * nColors);
if (!colors)
{
OMErr();
return NULLOBJ;
}
components = (short3 *) malloc(sizeof(short3) * nColors);
if (!components)
{
free(colors);
OMErr();
return NULLOBJ;
}
retVal = (PPtr)
NewObject(paletteClass,
sizeof(Palette) - sizeof(Thing));
if (!retVal)
{
return (ObjPtr) retVal;
}
retVal -> next = activePalettes;
activePalettes = retVal -> next;
SETOBJTYPE(retVal -> thing . flags, PALETTE);
retVal -> colors = colors;
retVal -> components = components;
retVal -> beg = -1;
retVal -> nColors = nColors;
retVal -> min = -1.0;
retVal -> max = 1.0;
for (k = 0; k < nColors; ++k)
{
retVal -> colors[k][0] =
retVal -> colors[k][1] =
retVal -> colors[k][2] = (k + 1) * 255 / nColors;
}
CopyColorsToComponents(retVal, k, nColors - 1);
return (ObjPtr) retVal;
}
void CopyPalette(d, s)
ObjPtr d, s;
/*Copies palette s to d*/
{
int k;
/*Free the colors*/
if (((PPtr) d) -> beg > 0)
{
FreeColors(((PPtr) d) -> beg, ((PPtr) d) -> nColors);
((PPtr) d) -> beg = -1;
}
if (((PPtr) d) -> nColors != ((PPtr) s) -> nColors)
{
SetVar(d, CHANGED, ObjTrue);
free(((PPtr) d) -> colors);
free(((PPtr) d) -> components);
((PPtr) d) -> colors = malloc(sizeof(short3) * ((PPtr) s) -> nColors);
((PPtr) d) -> components = malloc(sizeof(short3) * ((PPtr) s) -> nColors);
((PPtr) d) -> nColors = ((PPtr) s) -> nColors;
}
((PPtr) d) -> min = ((PPtr) s) -> min;
((PPtr) d) -> max = ((PPtr) s) -> max;
for (k = 0; k < ((PPtr) d) -> nColors; ++k)
{
((PPtr) d) -> colors[k][0] = ((PPtr) s) -> colors[k][0];
((PPtr) d) -> colors[k][1] = ((PPtr) s) -> colors[k][1];
((PPtr) d) -> colors[k][2] = ((PPtr) s) -> colors[k][2];
((PPtr) d) -> components[k][0] = ((PPtr) s) -> components[k][0];
((PPtr) d) -> components[k][1] = ((PPtr) s) -> components[k][1];
((PPtr) d) -> components[k][2] = ((PPtr) s) -> components[k][2];
}
SetVar(d, COLORMODEL, GetVar(s, COLORMODEL));
SetVar(d, JUSTCOLORCHANGE, ObjTrue);
MapPalette(d);
}
void SetPaletteNColors(p, nColors)
ObjPtr p;
int nColors;
/*Sets palette to be a nColors palette, doing any necessary resampling.*/
{
short3 *oldColors, *colors;
short3 *oldComponents, *components;
real beg, end, increment;
int s1, s2, i, k, comp;
int temp;
/*Free the colors*/
if (((PPtr) p) -> beg > 0)
{
FreeColors(((PPtr) p) -> beg, ((PPtr) p) -> nColors);
((PPtr) p) -> beg = -1;
}
/*Make a new set of colors*/
oldColors = ((PPtr) p) -> colors;
colors = (short3 *) malloc(nColors * sizeof(short3));
/*And a new set of components*/
oldComponents = ((PPtr) p) -> components;
components = (short3 *) malloc(nColors * sizeof(short3));
/*Copy ov, und, missing*/
colors[0][0] = oldColors[0][0];
colors[0][1] = oldColors[0][1];
colors[0][2] = oldColors[0][2];
colors[1][0] = oldColors[1][0];
colors[1][1] = oldColors[1][1];
colors[1][2] = oldColors[1][2];
colors[nColors - 1][0] = oldColors[((PPtr) p) -> nColors][0];
colors[nColors - 1][1] = oldColors[((PPtr) p) -> nColors][1];
colors[nColors - 1][2] = oldColors[((PPtr) p) -> nColors][2];
increment = ((real) ((PPtr) p) -> nColors - 3) / ((real) nColors - 3);
for (k = 0; k < nColors - 2; ++k)
{
beg = k * increment;
end = beg + increment;
for (comp = 0; comp < 3; ++comp)
{
s1 = beg;
s2 = end;
if (s1 == s2)
{
/*Chunk of just one color*/
colors[k + 2][comp] = oldColors[s1 + 2][comp];
}
else
{
/*Chunk of more than one color*/
real cum;
/*First one*/
cum = (1.0 - (beg - s1)) * oldColors[s1 + 2][comp];
/*Intermediate ones*/
for (i = s1 + 3; i < s2 + 2; ++i)
{
cum += oldColors[i][comp];
}
/*Last one*/
cum += (end - s2) * oldColors[s2 + 2][comp];
cum /= (end - beg);
temp = cum + 0.5;
if (temp < 0) temp = 0;
else if (temp > 255) temp = 255;
colors[k + 2][comp] = temp;
}
}
}
/*Update nColors*/
((PPtr) p) -> nColors = nColors;
((PPtr) p) -> colors = colors;
((PPtr) p) -> components = components;
/*Free the old colors*/
free(oldColors);
free(oldComponents);
CopyColorsToComponents((PPtr) p, 0, nColors - 1);
SetVar(p, CHANGED, ObjTrue);
}
#ifdef PROTO
void CopyAttenuatedPalette(ObjPtr d, ObjPtr s, real atten)
#else
void CopyAttenuatedPalette(d, s, atten)
ObjPtr d, s;
real atten;
#endif
/*Copies palette s to d, attenuated by d*/
{
int k;
/*Free the colors*/
if (((PPtr) d) -> beg > 0)
{
FreeColors(((PPtr) d) -> beg, ((PPtr) d) -> nColors);
((PPtr) d) -> beg = -1;
}
if (((PPtr) d) -> nColors != ((PPtr) s) -> nColors)
{
SetVar(d, CHANGED, ObjTrue);
free(((PPtr) d) -> colors);
((PPtr) d) -> colors = malloc(sizeof(short3) * ((PPtr) s) -> nColors);
free(((PPtr) d) -> components);
((PPtr) d) -> components = malloc(sizeof(short3) * ((PPtr) s) -> nColors);
((PPtr) d) -> nColors = ((PPtr) s) -> nColors;
}
((PPtr) d) -> min = ((PPtr) s) -> min;
((PPtr) d) -> max = ((PPtr) s) -> max;
for (k = 0; k < ((PPtr) d) -> nColors; ++k)
{
((PPtr) d) -> colors[k][0] = ((PPtr) s) -> colors[k][0] * atten;
((PPtr) d) -> colors[k][1] = ((PPtr) s) -> colors[k][1] * atten;
((PPtr) d) -> colors[k][2] = ((PPtr) s) -> colors[k][2] * atten;
}
SetVar(d, JUSTCOLORCHANGE, ObjTrue);
CopyColorsToComponents((PPtr) d, 0, ((PPtr) d) -> nColors - 1);
MapPalette(d);
}
ObjPtr ClonePalette(oldPalette)
ObjPtr oldPalette;
/*Clones a new palette*/
{
PPtr retVal;
short3 *colors, *components;
colors = (short3 *) malloc(sizeof(short3) * ((PPtr) oldPalette) -> nColors);
if (!colors)
{
OMErr();
return oldPalette;
}
components = (short3 *) malloc(sizeof(short3) * ((PPtr) oldPalette) -> nColors);
if (!components)
{
OMErr();
return oldPalette;
}
retVal = (PPtr)
NewObject(paletteClass,
sizeof(Palette) - sizeof(Thing));
if (!retVal)
{
return (ObjPtr) retVal;
}
retVal -> next = activePalettes;
activePalettes = retVal -> next;
SETOBJTYPE(retVal -> thing . flags, PALETTE);
retVal -> colors = colors;
retVal -> components = components;
retVal -> beg = -1;
retVal -> nColors = ((PPtr) oldPalette) -> nColors;
CopyPalette((ObjPtr) retVal, oldPalette);
return (ObjPtr) retVal;
}
void InterpPalette(palette, r1, g1, b1, r2, g2, b2)
ObjPtr palette;
int r1, g1, b1, r2, g2, b2;
/*Makes palette be an interpolation between r1, g1, b1, and r2, g2, b2*/
{
int k;
int n;
n = ((PPtr) palette) -> nColors - 3; /*Room for min, max, missing*/
for (k = 0; k < n; ++k)
{
((PPtr) palette) -> colors[k + 2][0] =
(k + 1) * r2 / n +
(n - k) * r1 / n;
((PPtr) palette) -> colors[k + 2][1] =
(k + 1) * g2 / n +
(n - k) * g1 / n;
((PPtr) palette) -> colors[k + 2][2] =
(k + 1) * b2 / n +
(n - k) * b1 / n;
}
/*Fill in missing*/
((PPtr) palette) -> colors[0][0] = 64;
((PPtr) palette) -> colors[0][1] = 64;
((PPtr) palette) -> colors[0][2] = 64;
/*Fill in min*/
((PPtr) palette) -> colors[1][0] = ((PPtr) palette) -> colors[2][0];
((PPtr) palette) -> colors[1][1] = ((PPtr) palette) -> colors[2][1];
((PPtr) palette) -> colors[1][2] = ((PPtr) palette) -> colors[2][2];
/*Fill in max*/
((PPtr) palette) -> colors[n + 2][0] = ((PPtr) palette) -> colors[n + 1][0];
((PPtr) palette) -> colors[n + 2][1] = ((PPtr) palette) -> colors[n + 1][1];
((PPtr) palette) -> colors[n + 2][2] = ((PPtr) palette) -> colors[n + 1][2];
CopyColorsToComponents((PPtr) palette, 0, ((PPtr) palette) -> nColors - 1);
MapPalette(palette);
}
void BlueToRedPalette(p)
ObjPtr p;
/*Makes a blue to red palette in p*/
{
int k;
real hue, r, g, b;
int n;
n = ((PPtr) p) -> nColors - 3; /*Room for min, max, missing*/
for (k = 0; k < n; ++k)
{
real v = 1.0;
/*
hue = (((real)(n - k))
/ (real) n) * 1.15 - 0.2;
*/
/*
hue = (((real)(n - k))
/ (real) n) * 0.8;
*/
hue = (((real)(n - k))
/ (real) n) * 0.9 - 0.1;
if (hue < 0.0) {v = 1.0 + (hue * 3.0); hue = 0.0;}
HSV2RGB(&r, &g, &b, hue, 1.0, v);
((PPtr) p) -> colors[k + 2][0] = r * 255;
((PPtr) p) -> colors[k + 2][1] = g * 255;
((PPtr) p) -> colors[k + 2][2] = b * 255;
}
/*Fill in missing*/
((PPtr) p) -> colors[0][0] = 64;
((PPtr) p) -> colors[0][1] = 64;
((PPtr) p) -> colors[0][2] = 64;
/*Fill in min*/
((PPtr) p) -> colors[1][0] = ((PPtr) p) -> colors[2][0];
((PPtr) p) -> colors[1][1] = ((PPtr) p) -> colors[2][1];
((PPtr) p) -> colors[1][2] = ((PPtr) p) -> colors[2][2];
/*Fill in max*/
((PPtr) p) -> colors[n + 2][0] = ((PPtr) p) -> colors[n + 1][0];
((PPtr) p) -> colors[n + 2][1] = ((PPtr) p) -> colors[n + 1][1];
((PPtr) p) -> colors[n + 2][2] = ((PPtr) p) -> colors[n + 1][2];
CopyColorsToComponents((PPtr) p, 0, ((PPtr) p) -> nColors - 1);
MapPalette(p);
}
void GreenToRedPalette(p)
ObjPtr p;
/*Makes a green to red palette in p*/
{
int k;
real hue, r, g, b;
int n;
n = ((PPtr) p) -> nColors - 3; /*Room for min, max, missing*/
for (k = 0; k < n; ++k)
{
hue = ((real)(n - k))
/ (real) n * 0.35;
HSV2RGB(&r, &g, &b, hue, 1.0, 1.0);
((PPtr) p) -> colors[k + 2][0] = r * 255;
((PPtr) p) -> colors[k + 2][1] = g * 255;
((PPtr) p) -> colors[k + 2][2] = b * 255;
}
/*Fill in missing*/
((PPtr) p) -> colors[0][0] = 64;
((PPtr) p) -> colors[0][1] = 64;
((PPtr) p) -> colors[0][2] = 64;
/*Fill in min*/
((PPtr) p) -> colors[1][0] = ((PPtr) p) -> colors[2][0];
((PPtr) p) -> colors[1][1] = ((PPtr) p) -> colors[2][1];
((PPtr) p) -> colors[1][2] = ((PPtr) p) -> colors[2][2];
/*Fill in max*/
((PPtr) p) -> colors[n + 2][0] = ((PPtr) p) -> colors[n + 1][0];
((PPtr) p) -> colors[n + 2][1] = ((PPtr) p) -> colors[n + 1][1];
((PPtr) p) -> colors[n + 2][2] = ((PPtr) p) -> colors[n + 1][2];
CopyColorsToComponents((PPtr) p, 0, ((PPtr) p) -> nColors - 1);
MapPalette(p);
}
void DisposePalette(palette)
ObjPtr palette;
/*Disposes of palette*/
{
free(palette);
}
real PSColor()
/*Returns a grayscale equivalent for the current color in DRAW_POSTSCRIPT mode*/
{
real hue, sat, val;
RGB2HSV(&hue, &sat, &val, curRed/255.0, curGreen/255.0, curBlue/255.0);
return val; /***/
}
void SetUIColor(c)
int c;
/*Sets the current drawing color to user interface color c, regardless
of whether the current window is RGB or colormap*/
{
#ifdef GRAPHICS
if (drawingMode == DRAW_SCREEN)
{
if (overDraw)
{
if (c == UIBLACK)
{
color(OVERCLEAR);
}
else
{
color(OVERRED);
}
}
else
if (rgbp)
{
/*It's an RGB window*/
lmcolor(LMC_COLOR);
#ifdef INDIGOCOLORS
if (uiColorIndex[c] >= 0)
{
color(uiColorIndex[c]);
}
else
#endif
c3s(uiColors[c]);
}
else
{
/*It's a cmap window*/
color(uiColorIndex[c]);
}
}
else
{
curRed = uiColors[c][0];
curGreen = uiColors[c][1];
curBlue = uiColors[c][2];
}
#endif
}
ObjPtr NewColorWheel(left, right, bottom, top, name)
int left, right, bottom, top;
char *name;
/*Makes a new hue/saturation control in left, right, bottom, top*/
{
real value[2];
ObjPtr valueArray;
ObjPtr retVal;
value[0] = 0.0;
value[1] = 0.0;
valueArray = NewRealArray(1, (long) 2);
if (valueArray)
{
CArray2Array(valueArray, value);
retVal = NewObject(colorWheelClass, 0);
Set2DIntBounds(retVal, left, right, bottom, top);
SetVar(retVal, VALUE, valueArray);
SetVar(retVal, NAME, NewString(name));
return retVal;
}
else
{
return NULLOBJ;
}
}
static int ColorToPixel(colorBar, clr)
ObjPtr colorBar;
int clr;
/*Returns the horizontal pixel for the color value in clr*/
{
int left, right, bottom, top;
PPtr palette;
int nColors;
/*Get the palette*/
palette = (PPtr) GetPaletteVar("ColorToPixel", colorBar, REPOBJ);
if (!palette)
{
return 0;
}
Get2DIntBounds(colorBar, &left, &right, &bottom, &top);
/*Get the stuff from the palette*/
nColors = palette -> nColors;
if (clr == 0)
{
/*Missing*/
return left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH / 2;
}
else if (clr == 1)
{
/*Underflow*/
return left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + CBBOXWIDTH / 2;
}
else if (clr == nColors - 1)
{
/*Overflow*/
return right - CBRBORDER - CBBOXWIDTH / 2;
}
else
{
/*In the center*/
int r, l;
l = left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP + 1;
r = right - CBRBORDER - CBBOXWIDTH - CBHGAP - 1;
return ((clr - 2) * (r - l) + (r - l) / 2) / (nColors - 3) + l;
}
}
static Bool ColorToPixels(int *, int *, ObjPtr, int);
static Bool ColorToPixels(lPix, rPix, colorBar, clr)
ObjPtr colorBar;
int clr;
int *lPix, *rPix;
/*Returns the horizontal pixelx around the color value in clr*/
{
int left, right, bottom, top;
PPtr palette;
int nColors;
/*Get the palette*/
palette = (PPtr) GetPaletteVar("ColorToPixel", colorBar, REPOBJ);
if (!palette)
{
return false;
}
Get2DIntBounds(colorBar, &left, &right, &bottom, &top);
/*Get the stuff from the palette*/
nColors = palette -> nColors;
if (clr == 0)
{
/*Missing*/
*lPix = left + CBLBORDER + CBLTEXTSPACE + 1;
*rPix = left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH - 1;
return true;
}
else if (clr == 1)
{
/*Underflow*/
*lPix = left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + 1;
*rPix = left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + CBHGAP - 1;
return true;
}
else if (clr == nColors - 1)
{
/*Overflow*/
*lPix = right - CBRBORDER - CBBOXWIDTH + 1;
*rPix = right - CBRBORDER - 1;
return true;
}
else
{
/*In the center*/
int r, l;
l = left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP + 1;
r = right - CBRBORDER - CBBOXWIDTH - CBHGAP - 1;
if (clr == 2)
{
*lPix = l;
}
else
{
*lPix = l + (clr - 2) * (r - l) / (nColors - 3) + 1;
}
*rPix = l + (clr - 1) * (r - l) / (nColors - 3);
return true;
}
}
static int PixelToColor(colorBar, pix)
ObjPtr colorBar;
int pix;
/*Returns the color for the horizontal pixel pixel*/
{
int left, right, bottom, top;
PPtr palette;
int nColors;
/*Get the palette*/
palette = (PPtr) GetPaletteVar("ColorToPixel", colorBar, REPOBJ);
if (!palette)
{
return 0;
}
Get2DIntBounds(colorBar, &left, &right, &bottom, &top);
/*Get the stuff from the palette*/
nColors = palette -> nColors;
if (pix < left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP / 2)
{
/*Missing*/
return 0;
}
else if (pix < left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + CBHGAP)
{
/*Underflow*/
return 1;
}
else if (pix > right - CBRBORDER - CBBOXWIDTH)
{
/*Overflow*/
return nColors - 1;
}
else
{
/*In the center*/
int r, l, retVal;
l = left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP + 1;
r = right - CBRBORDER - CBBOXWIDTH - CBHGAP - 1;
retVal = ((pix - l) * (nColors - 3) + (nColors - 3) / 2) / (r - l)
+ 2;
if (retVal >= nColors - 1)
{
retVal = nColors - 2;
}
if (retVal < 2)
{
retVal = 2;
}
return retVal;
}
}
#ifdef PROTO
void CalcGoodSteps(double diff, int pixWidth, int minMajorPix, double *majorWidth, int *nMinorSteps)
#else
void CalcGoodSteps(diff, pixWidth, minMajorPix, majorWidth, nMinorSteps)
double diff;
int pixWidth;
int minMajorPix;
double *majorWidth;
int *nMinorSteps;
#endif
/*Calculates good steps for a 10-base scale
diff is the difference between minimum and max
pixWidth is the width in pixels between minimum and max
minMajorPix is the minimum number of pixels between major tics
*majorWidth will be the width of a major step
*nMinorTics will be the number of minor steps
*/
{
long deltaLog; /*Log of the delta at minimum*/
double minDelta; /*Minimum delta between major tics*/
if (diff <= 0.0)
{
*majorWidth = 0.0;
*nMinorSteps = 1;
}
minDelta = diff * minMajorPix / pixWidth;
deltaLog = ((long) (1000.0 + log10((double) minDelta))) - 1000;
*majorWidth = pow((double) 10.0, (double) deltaLog);
*nMinorSteps = 1;
while (*majorWidth < minDelta)
{
if (*majorWidth < minDelta)
{
/*Try 2*/
*majorWidth *= 2.0;
*nMinorSteps = 2;
}
if (*majorWidth < minDelta)
{
/*Try 5*/
*majorWidth *= 2.5;
*nMinorSteps = 5;
}
if (*majorWidth < minDelta)
{
/*Try 10*/
*majorWidth *= 2.0;
*nMinorSteps = 10;
}
}
}
void ResetColorBarTools(colorBar)
ObjPtr colorBar;
/*Resets the tools associated with a color bar*/
{
ObjPtr radio, freeFormButton;
InhibitLogging(true);
freeFormButton = GetVar(colorBar, FREEFORMBUTTON);
radio = GetVar(colorBar, TOOLGROUP);
if (radio)
{
/***UPDATE For some reason, this doesn't work properly.*/
SetValue(radio, NewInt(freeFormButton ?
(GetPredicate(freeFormButton, ACTIVATED) ? PT_FREEFORM : -1)
: PT_FREEFORM));
}
InhibitLogging(false);
}
ObjPtr SetColorBarVal(object, value)
ObjPtr object;
ObjPtr value;
/*Sets the value of the object to value*/
{
if (IsRealArray(value) && RANK(value) == 1 && DIMS(value)[0] == 3)
{
ObjPtr radio;
PPtr repObj;
real *elements;
elements = ELEMENTS(value);
if (elements[0] < 0.0 || elements[0] > 3.0 ||
elements[1] < 0.0 || elements[2] < 0.0)
{
ReportError("SetColorBarVal", "Value error");
return ObjFalse;
}
repObj = (PPtr) GetPaletteVar("SetColorBarVal", object, REPOBJ);
if (repObj)
{
if (elements[1] >= ((real) repObj -> nColors) - 0.5 ||
elements[2] >= ((real) repObj -> nColors) - 0.5)
{
ReportError("SetColorBarVal", "Value error");
return ObjFalse;
}
}
SetVar(object, VALUE, value);
ImInvalid(object);
ChangedValue(object);
if (logging)
{
LogControl(object);
}
/*Set the edit tool to 0*/
ResetColorBarTools(object);
return ObjTrue;
}
else
{
ReportError("SetColorBarVal", "Bad value for color bar");
return ObjFalse;
}
}
static ObjPtr ReinitColorBar(colorBar)
ObjPtr colorBar;
/*Reinitializes a color bar*/
{
return ObjTrue;
}
real GetColorValue(palette, color)
ObjPtr palette;
int color;
/*Gets a field value for center of color color. Ignores missing*/
{
return
((PPtr) palette) -> min +
(color - 2) * (((PPtr) palette) -> max - ((PPtr) palette) -> min) /
(((PPtr) palette) -> nColors - 4);
}
static int hueColors[7] =
{
UIRED, UIYELLOW, UIGREEN, UICYAN, UIBLUE, UIMAGENTA, UIRED
};
#ifdef PROTO
static void ColorModelRect(int left, int right, int bottom, int top, int cm, int k)
#else
static void ColorModelRect(left, right, bottom, top, cm, k)
int left;
int right;
int bottom;
int top;
int cm;
int k;
#endif
/*Fills a rectangle within the bounds for color model cm in field k*/
{
#ifdef GRAPHICS
switch (cm)
{
case CM_RGB:
FillUIRect(left, right, bottom, top,
k == 1 ? UIBLUE : k == 2 ? UIGREEN : UIRED);
break;
case CM_HSV:
case CM_HLS:
shademodel(GOURAUD);
if (k == 3)
{
/*Hue*/
int c;
long v[2];
bgnpolygon();
SetUIColor(UIRED);
v[1] = bottom;
v[0] = left;
v2i(v);
v[0] = right + 1;
v2i(v);
for (c = 1; c < 5; ++c)
{
SetUIColor(hueColors[c]);
v[1] = bottom + (top - bottom) * c / 6;
v[0] = right + 1;
v2i(v);
v[0] = left;
v2i(v);
endpolygon();
bgnpolygon();
v2i(v);
v[0] = right + 1;
v2i(v);
}
SetUIColor(hueColors[c]);
v[1] = top + 1;
v[0] = right + 1;
v2i(v);
v[0] = left;
v2i(v);
endpolygon();
}
else if ((cm == CM_HSV && k == 2) ||
(cm == CM_HLS && k == 1))
{
/*Saturation*/
long v[2];
bgnpolygon();
SetUIColor(UIWHITE);
v[0] = left;
v[1] = bottom;
v2i(v);
v[0] = right + 1;
v2i(v);
SetUIColor(UICYAN);
v[1] = top + 1;
v2i(v);
v[0] = left;
v2i(v);
endpolygon();
}
else if (cm == CM_HSV)
{
/*Must be value*/
long v[2];
bgnpolygon();
SetUIColor(UIBLACK);
v[0] = left;
v[1] = bottom;
v2i(v);
v[0] = right + 1;
v2i(v);
SetUIColor(UICYAN);
v[1] = top + 1;
v2i(v);
v[0] = left;
v2i(v);
endpolygon();
}
else
{
/*Must be lightness*/
long v[2];
bgnpolygon();
SetUIColor(UIBLACK);
v[0] = left;
v[1] = bottom;
v2i(v);
v[0] = right + 1;
v2i(v);
SetUIColor(UICYAN);
v[1] = (top + bottom) / 2;
v2i(v);
v[0] = left;
v2i(v);
endpolygon();
bgnpolygon();
v[0] = left;
v2i(v);
v[0] = right + 1;
v2i(v);
SetUIColor(UIWHITE);
v[1] = top + 1;
v2i(v);
v[0] = left;
v2i(v);
endpolygon();
}
shademodel(FLAT);
break;
case CM_YIQ:
shademodel(GOURAUD);
if (k == 3)
{
/*Must be y*/
long v[2];
bgnpolygon();
SetUIColor(UIBLACK);
v[0] = left;
v[1] = bottom;
v2i(v);
v[0] = right + 1;
v2i(v);
SetUIColor(UICYAN);
v[1] = (top + bottom) / 2;
v2i(v);
v[0] = left;
v2i(v);
endpolygon();
bgnpolygon();
v[0] = left;
v2i(v);
v[0] = right + 1;
v2i(v);
SetUIColor(UIWHITE);
v[1] = top + 1;
v2i(v);
v[0] = left;
v2i(v);
endpolygon();
}
else if (k == 2)
{
/*i, cyan/orange index*/
long v[2];
bgnpolygon();
SetUIColor(UICYAN);
v[0] = left;
v[1] = bottom;
v2i(v);
v[0] = right + 1;
v2i(v);
SetUIColor(UIORANGE);
v[1] = top + 1;
v2i(v);
v[0] = left;
v2i(v);
endpolygon();
}
else
{
/*q, green/magenta axis*/
long v[2];
bgnpolygon();
SetUIColor(UIGREEN);
v[0] = left;
v[1] = bottom;
v2i(v);
v[0] = right + 1;
v2i(v);
SetUIColor(UIMAGENTA);
v[1] = top + 1;
v2i(v);
v[0] = left;
v2i(v);
endpolygon();
}
shademodel(FLAT);
break;
}
#endif
}
static ObjPtr DrawColorBar(colorBar)
ObjPtr colorBar;
/*Draws a color bar*/
{
#ifdef GRAPHICS
int left, right, bottom, top;
int l, r, b, t;
int start, diff, comp;
PPtr palette;
int nColors;
short3 *colors;
ObjPtr value; /*Value of the control*/
real *elements;
ObjPtr var;
int highlighted;
int k;
double majorWidth, minorWidth; /*Width of a major step*/
double ddiff; /*Data difference*/
int nTics; /*Number of minor tics*/
long temp;
double halfSpace;
int pixel; /*Temporary pixel*/
double curValue; /*Current value for making tics*/
int cm; /*Color model in use*/
Get2DIntBounds(colorBar, &left, &right, &bottom, &top);
if (IsDrawingRestricted(left, right, bottom, top)) return ObjFalse;
/*Get the palette*/
palette = (PPtr) GetPaletteVar("DrawColorBar", colorBar, REPOBJ);
if (!palette)
{
return ObjFalse;
}
/*Get the stuff from the palette*/
nColors = palette -> nColors;
colors = palette -> colors;
/*Draw the bump and plateau, but not if the changed bounds is smaller than
the bounds*/
var = GetVar(colorBar, CHANGEDBOUNDS);
if (!var || !IsArray(var))
{
DrawRaisedRect(left, right, bottom, top, UIBACKGROUND);
}
else
{
elements = ELEMENTS(var);
if (left >= CURSTATE . screenMask[0] - CURSTATE . translation[0] &&
right <= CURSTATE . screenMask[1] - CURSTATE . translation[0] &&
bottom >= CURSTATE . screenMask[2] - CURSTATE . translation[1] &&
top <= CURSTATE . screenMask[3] - CURSTATE . translation[1])
{
DrawRaisedRect(left, right, bottom, top, UIBACKGROUND);
}
}
/*Draw the legends and tic marks and stuff at the bottom*/
SetUIColor(UIBLACK);
SetupFont(CBTEXTFONT, CBTEXTSIZE);
b = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP;
DrawAString(CENTERALIGN,
left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH / 2,
bottom + CBBORDER + CBTEXTUP, "Missing");
DrawUILine( left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH / 2, b,
left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH / 2, b - CBMAJORTICLEN, UIBLACK);
DrawAString(CENTERALIGN,
left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + CBBOXWIDTH / 2,
bottom + CBBORDER + CBTEXTUP, "Under");
DrawUILine( left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + CBBOXWIDTH / 2, b,
left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + CBBOXWIDTH / 2, b - CBMAJORTICLEN, UIBLACK);
/*Draw all the tics in the middle*/
l = left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP + 1;
r = right - CBRBORDER - CBBOXWIDTH - CBHGAP - 1;
halfSpace = (palette -> max - palette -> min) / (palette -> nColors - 4) * 0.5;
ddiff = palette -> max - palette -> min;
CalcGoodSteps(ddiff,
r - l,
CBSTEPPIXELS,
&majorWidth, &nTics);
minorWidth = majorWidth / nTics;
/*Minor and major tics first*/
temp = palette -> min / majorWidth;
curValue = temp * majorWidth;
while (curValue > palette -> min)
{
curValue -= majorWidth;
}
k = 0;
while (curValue < palette -> min)
{
++k;
if (k >= nTics) k = 0;
curValue += minorWidth;
}
/*Now actually draw them*/
if (ABS(curValue) < ddiff * 1.0E-6) curValue = 0.0;
while (curValue <= palette -> max + ddiff * 1.0E-6)
{
pixel = l + (curValue - palette -> min) * (r - l) / (ddiff);
if (k == 0)
{
/*Major tic*/
DrawUILine(pixel, b,
pixel, b - CBMAJORTICLEN,
UIBLACK);
sprintf(tempStr, "%lg", curValue);
DrawAString(CENTERALIGN, pixel, b - CBTEXTSEP, tempStr);
}
else
{
/*Minor tic*/
DrawUILine(pixel, b,
pixel, b - CBMAJORTICLEN / 2,
UIBLACK);
}
curValue += minorWidth;
if (ABS(curValue) < ddiff * 1.0E-6) curValue = 0.0;
++k;
if (k >= nTics) k = 0;
}
DrawAString(CENTERALIGN,
right - CBRBORDER - CBBOXWIDTH + CBBOXWIDTH / 2,
bottom + CBBORDER + CBTEXTUP, "Over");
DrawUILine( right - CBRBORDER - CBBOXWIDTH + CBBOXWIDTH / 2, b,
right - CBRBORDER - CBBOXWIDTH + CBBOXWIDTH / 2, b - CBMAJORTICLEN, UIBLACK);
/*Get the color model*/
var = GetIntVar("DrawColorBar", (ObjPtr) palette, COLORMODEL);
if (!var)
{
return ObjFalse;
}
cm = GetInt(var);
/*Draw the boxes*/
b = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP;
SetupFont(CBBIGTEXTFONT, CBBIGTEXTSIZE);
for (k = 0; k < 4; ++k)
{
t = b + CBCOMPHEIGHT;
/*Draw the box outlines*/
/*Draw the missing data box*/
FrameUIRect(left + CBLBORDER + CBLTEXTSPACE, left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH, b, t, UIBLACK);
/*Now the underflow box*/
FrameUIRect(left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP,
left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + CBHGAP,
b, t, UIBLACK);
/*Now the middle bit*/
FrameUIRect(left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP,
right - CBRBORDER - CBBOXWIDTH - CBHGAP,
b, t, UIBLACK);
/*Now the overflow box*/
FrameUIRect(right - CBRBORDER - CBBOXWIDTH,
right - CBRBORDER,
b, t, UIBLACK);
/*Draw the background of the boxex*/
/*Draw the missing data box*/
ColorModelRect(left + CBLBORDER + CBLTEXTSPACE + 1, left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH - 1, b + 1, t - 1,
cm, k);
/*Now the underflow box*/
ColorModelRect(left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + 1,
left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + CBHGAP - 1,
b + 1, t - 1, cm, k);
/*Now the middle bit*/
ColorModelRect(left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP + 1,
right - CBRBORDER - CBBOXWIDTH - CBHGAP - 1,
b + 1, t - 1, cm, k);
/*Now the overflow box*/
ColorModelRect(right - CBRBORDER - CBBOXWIDTH + 1,
right - CBRBORDER - 1,
b + 1, t - 1, cm, k);
/*Now the component names*/
if (k)
{
SetUIColor(UIBLACK);
DrawAString(LEFTALIGN,
left + CBLBORDER, (b + t) / 2 - CBCOMPTEXTDOWN,
shortComponentNames[cm][3 - k]);
}
b = t + CBVGAP;
}
/*Now the expanded readout*/
FrameUIRect(left + CBLBORDER,
right - CBRBORDER,
b, top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP, UIBLACK);
b = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP + 1;
t = b + CBCOMPHEIGHT - 2;
/*Now draw the colors*/
if (rgbp)
{
/*It's in RGB mode, so we don't have to set the palette*/
l = left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP + 1;
r = right - CBRBORDER - CBBOXWIDTH - CBHGAP - 1;
/*Do missing data box*/
c3s(colors[0]);
rectfi( left + CBLBORDER + CBLTEXTSPACE + 1, b,
left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH - 1, t);
/*Do underflow data box*/
c3s(colors[1]);
rectfi( left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + 1, b,
left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + CBHGAP - 1, t);
/*Do the colors in the center*/
diff = r - l;
start = l;
for (k = 2; k < nColors - 1; ++k)
{
r = (k - 1) * diff / (nColors - 3) + start;
c3s(colors[k]);
rectfi(l, b, r, t);
l = r + 1;
}
/*Do overflow data box*/
c3s(colors[nColors - 1]);
rectfi( right - CBRBORDER - CBBOXWIDTH + 1, b,
right - CBRBORDER - 1, t);
}
else
{
/*It's a color map window, have to set the colors*/
int beg;
l = left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP + 1;
r = right - CBRBORDER - CBBOXWIDTH - CBHGAP - 1;
SetPalette((ObjPtr) palette);
beg = palette -> beg;
/*Do missing data box*/
color(beg);
rectfi( left + CBLBORDER + CBLTEXTSPACE + 1, b,
left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH - 1, t);
/*Do underflow data box*/
color(beg + 1);
rectfi( left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + 1, b,
left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + CBHGAP - 1, t);
/*Do the colors in the center*/
diff = r - l;
start = l;
for (k = 2; k < nColors - 1; ++k)
{
r = (k - 1) * diff / (nColors - 3) + start;
color(beg + k);
rectfi(l, b, r, t);
l = r + 1;
}
/*Do overflow data box*/
color(beg + nColors - 1);
rectfi( right - CBRBORDER - CBBOXWIDTH + 1, b,
right - CBRBORDER - 1, t);
}
b = t + CBVGAP + 2;
t = b + CBCOMPHEIGHT - 1;
/*Do 3 components*/
for (comp = 2; comp >= 0; --comp)
{
int height;
SetUIColor(UIGRAY62);
/*Do missing data box*/
height = GetColorComponent(palette, 0, comp) * (CBCOMPHEIGHT - 1) / 255;
if (height < CBCOMPHEIGHT - 1)
{
rectfi( left + CBLBORDER + CBLTEXTSPACE + 1, t - CBCOMPHEIGHT + height + 1,
left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH - 1, t - 1);
}
/*Do underflow data box*/
height = GetColorComponent(palette, 1, comp) * (CBCOMPHEIGHT - 1) / 255;
if (height < CBCOMPHEIGHT - 1)
{
rectfi( left + CBLBORDER + CBLTEXTSPACE + CBBOXWIDTH + CBHGAP + 1, t - CBCOMPHEIGHT + height + 1,
left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + CBHGAP - 1, t - 1);
}
/*Do the colors in the center*/
l = left + CBLBORDER + CBLTEXTSPACE + 2 * CBBOXWIDTH + 2 * CBHGAP + 1;
r = right - CBRBORDER - CBBOXWIDTH - CBHGAP - 1;
diff = r - l;
start = l;
for (k = 2; k < nColors - 1; ++k)
{
r = (k - 1) * diff / (nColors - 3) + start;
height = GetColorComponent(palette, k, comp) * (CBCOMPHEIGHT - 1) / 255;
if (height < CBCOMPHEIGHT - 1)
{
rectfi(l, t - CBCOMPHEIGHT + height + 1, r, t - 1);
}
l = r + 1;
}
/*Overflow*/
height = GetColorComponent(palette, nColors - 1, comp) * (CBCOMPHEIGHT - 1) / 255;
if (height < CBCOMPHEIGHT - 1)
{
rectfi(right - CBRBORDER - CBBOXWIDTH + 1, t - CBCOMPHEIGHT + height + 1,
right - CBRBORDER - 1, t - 1);
}
b = t + CBVGAP + 1;
t = b + CBCOMPHEIGHT - 1;
}
/*Now deal with the value*/
value = GetValue(colorBar);
if (!value)
{
/*Have to give it a value*/
value = NewRealArray(1, 3L);
elements = ELEMENTS(value);
elements[0] = 0.0;
elements[1] = 0.0;
elements[2] = 0.0;
}
else
{
elements = ELEMENTS(value);
}
if (elements[0] >= 0.5)
{
/*Draw the selection in the magnified area*/
int dummy;
b = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP +
((int) (elements[0] - 0.5)) * (CBVGAP + CBCOMPHEIGHT);
t = b + CBCOMPHEIGHT;
ColorToPixels(&l, &dummy, colorBar, (int) (elements[1] + 0.5));
ColorToPixels(&dummy, &r, colorBar, (int) (elements[2] + 0.5));
FrameUIRect(l - 1, r + 3, b - 2, t, UIBLACK);
FrameUIRect(l - 2, r + 1, b, t + 1, UIYELLOW);
FrameUIRect(l - 3, r + 2, b - 1, t + 2, UIYELLOW);
/*Draw the expanded range*/
if (elements[0] == 1.0)
{
int c1, c2;
/*Draw the full color*/
l = left + CBLBORDER + 1;
r = right - CBRBORDER - 1;
t = top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP - 1;
b = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP + 4 * CBCOMPHEIGHT
+ 4 * CBVGAP + 1;
if (rgbp)
{
/*It's in RGB mode, so we don't have to set the palette*/
/*Do the colors in the center*/
diff = r - l;
start = l;
c1 = elements[1];
c2 = elements[2];
for (k = c1; k <= c2; ++k)
{
r = (k - c1 + 1) * diff / (c2 - c1 + 1) + start;
c3s(colors[k]);
rectfi(l, b, r, t);
l = r + 1;
}
}
else
{
/*It's a color map window, have to set the colors*/
int beg;
SetPalette((ObjPtr) palette);
beg = palette -> beg;
/*Do the colors in the center*/
diff = r - l;
start = l;
c1 = elements[1];
c2 = elements[2];
for (k = c1; k <=c2; ++k)
{
r = (k - c1 + 1) * diff / (c2 - c1 + 1) + start;
color(beg + k);
rectfi(l, b, r, t);
l = r + 1;
}
}
}
else
{
int c1, c2;
int height;
c1 = elements[1];
c2 = elements[2];
comp = 4 - ((int) elements[0]);
l = left + CBLBORDER + 1;
r = right - CBRBORDER - 1;
t = top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP - 1;
b = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP + 4 * CBCOMPHEIGHT
+ 4 * CBVGAP + 1;
ColorModelRect(l, r, b, t, cm, (int) elements[0] - 1);
SetUIColor(UIGRAY62);
/*Do the colors in the center*/
diff = r - l;
start = l;
for (k = c1; k <= c2; ++k)
{
r = (k - c1 + 1) * diff / (c2 - c1 + 1) + start;
height = GetColorComponent(palette, k, comp) * (t - b) / 255.0 + 0.5;
if (height < t - b)
{
rectfi(l, b + height, r, t);
}
l = r + 1;
}
}
}
/*Draw the tics at the top*/
if (elements[0] > 0.0)
{
real start, finish, halfSpace;
l = left + CBLBORDER + 1;
r = right - CBRBORDER - 1;
t = top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP - 1;
b = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP + 4 * CBCOMPHEIGHT + 4 * CBVGAP + 1;
if (elements[2] >= elements[1])
{
/*It's a range*/
halfSpace = (palette -> max - palette -> min) / (palette -> nColors - 4) * 0.5;
start = GetColorValue((ObjPtr) palette, (int) elements[1]) - halfSpace;
finish = GetColorValue((ObjPtr) palette, (int) elements[2]) + halfSpace;
ddiff = finish - start;
CalcGoodSteps(ddiff,
r - l,
CBSTEPPIXELS,
&majorWidth, &nTics);
minorWidth = majorWidth / nTics;
/*Minor and major tics first*/
temp = start / majorWidth;
curValue = temp * majorWidth;
while (curValue > start)
{
curValue -= majorWidth;
}
k = 0;
while (curValue < start)
{
++k;
if (k >= nTics) k = 0;
curValue += minorWidth;
}
SetupFont(CBBIGTEXTFONT, CBBIGTEXTSIZE);
/*Now actually draw them*/
if (ABS(curValue) < ddiff * 1.0E-6) curValue = 0.0;
while (curValue <= finish + ddiff * 1.0E-6)
{
pixel = l + (curValue - start) * (r - l) / (ddiff);
if (k == 0)
{
/*Major tic*/
DrawUILine(pixel,
top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP,
pixel,
top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP + CBMAJORTICLEN,
UIBLACK);
sprintf(tempStr, "%lg", curValue);
{
DrawAString(CENTERALIGN, pixel, top - CBTBORDER - CBTEXTDOWN, tempStr);
}
}
else
{
/*Minor tic*/
DrawUILine(pixel,
top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP,
pixel,
top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP + CBMAJORTICLEN / 2,
UIBLACK);
}
curValue += minorWidth;
if (ABS(curValue) < ddiff * 1.0E-6) curValue = 0.0;
++k;
if (k >= nTics) k = 0;
}
/*Draw the function box, if any*/
var = GetVar(colorBar, FUNCTIONBOX);
if (var)
{
int boxL, boxR, boxB, boxT, boxX, boxY;
real *elements;
elements = ELEMENTS(var);
boxL = l + (elements[0] - start) * (r - l) / (ddiff);
boxR = l + (elements[1] - start) * (r - l) / (ddiff);
boxB = b + elements[2] * (t - b) / 255.0;
boxT = b + elements[3] * (t - b) / 255.0;
boxX = (boxL + boxR) / 2;
boxY = (boxB + boxT) / 2;
SetClipRect(left + 3, right - 3, bottom + 3, top - 3);
/*Now draw the box and its handles*/
FrameUIRect(boxL + 1, boxR + 2, boxB - 2, boxT - 1, UIBLACK);
FrameUIRect(boxL + 1 - CBHANDLESIZE, boxL + 1,
boxY - 1 - CBHANDLESIZE / 2, boxY - 1 + CBHANDLESIZE / 2, UIBLACK);
FrameUIRect(boxR + 2, boxR + 2 + CBHANDLESIZE,
boxY - 1 - CBHANDLESIZE / 2, boxY - 1 + CBHANDLESIZE / 2, UIBLACK);
FrameUIRect(boxX + 2 - CBHANDLESIZE / 2, boxX + 2 + CBHANDLESIZE / 2,
boxT - 1, boxT - 1 + CBHANDLESIZE, UIBLACK);
FrameUIRect(boxX + 2 - CBHANDLESIZE / 2, boxX + 2 + CBHANDLESIZE / 2,
boxB - 2 - CBHANDLESIZE, boxB - 2, UIBLACK);
FrameUIRect(boxL, boxR, boxB, boxT, UIYELLOW);
FrameUIRect(boxL - 1, boxR + 1, boxB - 1, boxT + 1, UIYELLOW);
FillUIRect(boxL - 1 - CBHANDLESIZE, boxL,
boxY - CBHANDLESIZE / 2, boxY + 1 + CBHANDLESIZE / 2, UIYELLOW);
FillUIRect(boxR, boxR + 1 + CBHANDLESIZE,
boxY - CBHANDLESIZE / 2, boxY + 1 + CBHANDLESIZE / 2, UIYELLOW);
FillUIRect(boxX - CBHANDLESIZE / 2, boxX + 1 + CBHANDLESIZE / 2,
boxT, boxT + 1 + CBHANDLESIZE, UIYELLOW);
FillUIRect(boxX - CBHANDLESIZE / 2, boxX + 1 + CBHANDLESIZE / 2,
boxB - 1 - CBHANDLESIZE, boxB, UIYELLOW);
RestoreClipRect();
}
}
}
#endif
return ObjTrue;
}
ObjPtr SetFunctionBox(colorBar, functionBox)
ObjPtr colorBar;
ObjPtr functionBox;
/*Sets the FUNCTIONBOX of colorBar to functionBox, also logs*/
{
real *elements;
PPtr repObj;
if (functionBox && (!IsRealArray(functionBox) || RANK(functionBox) != 1 ||
DIMS(functionBox)[0] != 4))
{
ReportError("SetFunctionBox", "Bad value given");
return ObjFalse;
}
repObj = (PPtr) GetPaletteVar("SetFunctionBox", colorBar, REPOBJ);
if (!repObj)
{
return ObjFalse;
}
if (functionBox)
{
elements = ELEMENTS(functionBox);
if (elements[2] < -0.5 || elements[2] >= 255.5 ||
elements[3] < -0.5 || elements[3] >= 255.5 ||
elements[2] > elements[3] ||
elements[0] > elements[1])
{
ReportError("SetFunctionBox", "Value out of range");
return ObjFalse;
}
}
SetVar(colorBar, FUNCTIONBOX, functionBox);
if (logging)
{
char cmd[256];
char *s;
sprintf(cmd, "set functionbox ");
s = &(cmd[0]);
while (*s) ++s;
MakeObjectName(s, colorBar);
while (*s) ++s;
*s++ = ' ';
PrintScriptObject(s, functionBox);
while (*s) ++s;
*s++ = '\n';
*s = 0;
Log(cmd);
}
return ObjTrue;
}
void LogColorChange(colorBar, colors, newColor)
ObjPtr colorBar;
short3 *colors;
int newColor;
/*Logs a change to colors[newColor] within colorBar*/
{
if (logging)
{
char cmd[256];
char *s;
sprintf(cmd, "set color ");
s = &(cmd[0]);
while (*s) ++s;
MakeObjectName(s, colorBar);
while (*s) ++s;
*s++ = ' ';
sprintf(s, "%d %d %d %d\n", newColor, colors[newColor][0],
colors[newColor][1], colors[newColor][2]);
Log(cmd);
}
}
ObjPtr SetColorBarColor(colorBar, whichColor, r, g, b)
ObjPtr colorBar;
int whichColor, r, g, b;
/*Sets color whichColor from inside a color bar*/
{
PPtr palette;
short3 *colors;
palette = (PPtr) GetPaletteVar("SetColorBarColor", colorBar, REPOBJ);
if (!palette)
{
return ObjFalse;
}
colors = palette -> colors;
colors[whichColor][0] = r;
colors[whichColor][1] = g;
colors[whichColor][2] = b;
ImInvalid(colorBar);
LogColorChange(colorBar, colors, whichColor);
ChangedValue(colorBar);
CopyColorsToComponents(palette, whichColor, whichColor);
#ifdef GRAPHICS
MapPaletteColors(palette, whichColor, whichColor);
#endif
SetVar((ObjPtr) palette, JUSTCOLORCHANGE, ObjTrue);
ForAllVisWindows(ImInvalid);
return ObjTrue;
}
static ObjPtr PressColorBar(colorBar, x, y, flags)
ObjPtr colorBar;
int x, y;
long flags;
/*Does a press in a color bar beginning at x and y. Returns
true iff the press really was in the control.*/
{
#ifdef INTERACTIVE
int left, right, bottom, top;
int l, r, b, t;
int k;
int cm;
Get2DIntBounds(colorBar, &left, &right, &bottom, &top);
if (x >= left && x <= right && y >= bottom && y <= top)
{
real val[3];
ObjPtr value, var;
real *origVal;
ObjPtr palette;
/*Hey! It really was a click in the color bar*/
if (TOOL(flags) == T_HELP)
{
ContextHelp(colorBar);
return ObjTrue;
}
b = bottom + CBBORDER + CBTEXTUP + CBTEXTSEP;
if (y < b)
{
/*Click below*/
val[0] = val[1] = val[2] = 0.0;
value = NewRealArray(1, 3L);
CArray2Array(value, val);
SetValue(colorBar, value);
return ObjTrue;
}
MakeMeCurrent(colorBar);
/*Get current value*/
value = GetFixedArrayVar("PressColorBar", colorBar, VALUE, 1, 3L);
if (!value)
{
return ObjFalse;
}
origVal = (real *) ELEMENTS(value);
palette = (ObjPtr) GetPaletteVar("PressColorBar", colorBar, REPOBJ);
if (!palette)
{
return ObjFalse;
}
/*Get the color model*/
var = GetIntVar("PressColorBar", (ObjPtr) palette, COLORMODEL);
if (!var)
{
return ObjFalse;
}
cm = GetInt(var);
/*See if it's in one of the components or full color*/
for (k = 0; k < 4; ++k)
{
t = b + CBCOMPHEIGHT;
if (y <= t && y >= b)
{
ObjPtr radio;
int newX, newY;
int startColor;
int lastColor;
int newColor;
Bool inp; /*True if inside*/
/*It's a press in track k*/
InhibitLogging(true);
if ((flags & F_SHIFTDOWN) || TOOL(flags) == T_ROTATE)
{
/*Shift click, determine start from farthest*/
newColor = PixelToColor(colorBar, x);
if (ABS(newColor - origVal[2]) < ABS(newColor - origVal[1]))
{
startColor = origVal[1];
}
else
{
startColor = origVal[2];
}
}
else
{
startColor = PixelToColor(colorBar, x);
}
lastColor = -1;
val[0] = (real) (k + 1);
inp = true;
/*Set the edit tool to free form*/
ResetColorBarTools(colorBar);
while (Mouse(&newX, &newY))
{
if (newY > t + SLOP ||
newY < b - SLOP ||
newX < left - SLOP ||
newX > right + SLOP)
{
/*It's outside*/
if (inp)
{
/*Transition from in to out*/
SetVar(colorBar, VALUE, value);
inp = false;
lastColor = -1;
DrawMe(colorBar);
}
}
else
{
/*It's inside*/
if (!inp)
{
/*Transition from out to in*/
inp = true;
}
newColor = PixelToColor(colorBar, newX);
if (newColor != lastColor)
{
ObjPtr var;
/*It's a new color, set it*/
if (newColor >= startColor)
{
val[1] = (real) startColor;
val[2] = (real) newColor;
}
else
{
val[2] = (real) startColor;
val[1] = (real) newColor;
}
var = NewRealArray(1, 3L);
CArray2Array(var, val);
SetVar(colorBar, VALUE, var);
DrawMe(colorBar);
lastColor = newColor;
}
}
}
ChangedValue(colorBar);
InhibitLogging(false);
LogControl(colorBar);
return ObjTrue;
}
b = t + CBVGAP;
}
/*It wasn't in a component, maybe it's in the readout*/
t = top - CBTBORDER - CBTEXTDOWN - CBTEXTDOWNSEP - 1;
l = left + CBLBORDER + 1;
r = right - CBRBORDER - 1;
if (origVal[0] > 1.0 &&
y >= b - SLOP && y <= t + SLOP && x >= l - SLOP && x <= r + SLOP)
{
/*It is! Do stuff based on edit mode*/
int editMode;
int lastColor, lastAmp;
PPtr palette;
int index1, index2;
int k;
int comp;
short3 *colors;
int newX, newY, newColor, newAmp;
ObjPtr panel, button;
palette = (PPtr) GetPaletteVar("PressColorBar", colorBar, REPOBJ);
if (!palette)
{
return ObjFalse;
}
colors = palette -> colors;
comp = 4 - origVal[0];
var = GetIntVar("PressColorBar", colorBar, EDITMODE);
if (!var)
{
return ObjFalse;
}
editMode = GetInt(var);
index1 = origVal[1] + 0.5;
index2 = origVal[2] + 0.5;
panel = GetVar(colorBar, PARENT);
if (panel)
{
button = GetVar(panel, KEEPBUTTON);
if (button)
{
ActivateButton(button, true);
}
button = GetVar(panel, REVERTBUTTON);
if (button)
{
ActivateButton(button, true);
}
}
if (editMode == PT_FREEFORM)
{
int firstAltered, lastAltered;
Bool constrainX, constrainY;
/*Free form*/
lastColor = lastAmp = -1;
firstAltered = index2 + 1;
lastAltered = index1 - 1;
constrainX = constrainY = false;
while (Mouse(&newX, &newY))
{
if (newX >= l - SLOP && newX <= r + SLOP && newY >= b - SLOP && newY <= t + SLOP)
{
if (flags & F_SHIFTDOWN)
{
if (!constrainX && !constrainY)
{
int xDiff, yDiff;
/*Must make some constraints*/
xDiff = ABS(newX - x);
yDiff = ABS(newY - y);
if (xDiff >= MINCONSTRAINT &&
yDiff >= MINCONSTRAINT)
{
if (yDiff > xDiff)
{
constrainX = true;
}
else
{
constrainY = true;
}
}
}
if (constrainX) newX = x;
if (constrainY) newY = y;
}
/*Calculate newAmp*/
newAmp = ((newY - b) + 0.5) * 255.0 / (real) (t - b - 1);
if (newAmp < 0) newAmp = 0;
else if (newAmp > 255) newAmp = 255;
/*Calculate newColor*/
newColor = index1 + ((real) newX - l) * ((real) index2 - index1 + 1) / ((real) (r - l - 1));
if (newColor < index1) newColor = index1;
else if (newColor > index2) newColor = index2;
if (newColor < firstAltered)
{
firstAltered = newColor;
}
if (newColor > lastAltered)
{
lastAltered = newColor;
}
if (newAmp != lastAmp || newColor != lastColor)
{
/*Set the new color to be correct*/
if (lastColor <= -1 || lastColor == newColor)
{
/*New in this range, just set this color*/
SetColorComponent(palette, newColor, comp, newAmp);
#ifdef GRAPHICS
MapPaletteColors(palette, newColor, newColor);
#endif
}
else if (newColor > lastColor)
{
int nc;
/*Linearly interpolate up to this color*/
for (k = lastColor + 1; k <= newColor; ++k)
{
nc = ((newColor - k) * lastAmp +
(k - lastColor) * newAmp) /
(newColor - lastColor);
if (nc < 0) nc = 0;
else if (nc > 255) nc = 255;
SetColorComponent(palette, k, comp, nc);
}
#ifdef GRAPHICS
MapPaletteColors(palette, lastColor, newColor);
#endif
}
else if (newColor < lastColor)
{
int nc;
/*Linearly interpolate down to this color*/
for (k = lastColor - 1; k >= newColor; --k)
{
nc = ((k - newColor) * lastAmp +
(lastColor - k) * newAmp) /
(lastColor - newColor);
if (nc < 0) nc = 0;
else if (nc > 255) nc = 255;
SetColorComponent(palette, k, comp, nc);
}
#ifdef GRAPHICS
MapPaletteColors(palette, lastColor, newColor);
#endif
}
DrawMeInBounds(colorBar, left + 3, right - 3, bottom + 3, top - 3);
lastAmp = newAmp;
lastColor = newColor;
}
}
else
{
lastColor = lastAmp = -1;
}
}
for (k = firstAltered; k <= lastAltered; ++k)
{
LogColorChange(colorBar, colors, k);
}
ChangedValue(colorBar);
SetVar((ObjPtr) palette, JUSTCOLORCHANGE, ObjTrue);
ForAllVisWindows(ImInvalid);
}
else
{
/*It's a tool*/
ObjPtr toolBounds;
int boxL, boxR, boxB, boxT;
int xOffset, yOffset;
double start, finish, ddiff, halfSpace;
real *elements;
real newElements[4];
int whichMove = 0;
real lastSide, nextSide;
double majorWidth, minorWidth;
int nTics;
long temp;
#define MOVEBOXTOP 1
#define MOVEBOXBOTTOM 2
#define MOVEBOXLEFT 3
#define MOVEBOXRIGHT 4
#define MOVEBOXLR 5
halfSpace = (palette -> max - palette -> min) / (palette -> nColors - 4) * 0.5;
start = GetColorValue((ObjPtr) palette, index1) - halfSpace;
finish = GetColorValue((ObjPtr) palette, index2) + halfSpace;
ddiff = finish - start;
toolBounds = GetFixedArrayVar("PressColorBar", colorBar, FUNCTIONBOX, 1, 4L);
if (!toolBounds)
{
return ObjFalse;
}
elements = ELEMENTS(toolBounds);
boxL = l + (elements[0] - start) * (r - l) / (ddiff);
boxR = l + (elements[1] - start) * (r - l) / (ddiff);
boxB = b + elements[2] * (t - b) / 255.0;
boxT = b + elements[3] * (t - b) / 255.0;
/*Figure out which side is clicked on*/
whichMove = 0;
if (y >= boxB - (CBHANDLESIZE + 2) && y <= boxT + (CBHANDLESIZE + 2))
{
if (x >= boxL - (CBHANDLESIZE + 2) && x <= boxL)
{
whichMove = MOVEBOXLEFT;
xOffset = x - boxL;
}
else if (x >= boxR && x <= boxR + (CBHANDLESIZE + 2))
{
whichMove = MOVEBOXRIGHT;
xOffset = x - boxR;
}
}
if (x >= boxL - (CBHANDLESIZE + 2) && x <= boxR + (CBHANDLESIZE + 2))
{
if (y >= boxB - (CBHANDLESIZE + 2) && y <= boxB)
{
whichMove = MOVEBOXBOTTOM;
yOffset = y - boxB;
}
else if (y >= boxT && y <= boxT + (CBHANDLESIZE + 2))
{
whichMove = MOVEBOXTOP;
yOffset = y - boxT;
}
}
if (!whichMove)
{
whichMove = MOVEBOXLR;
xOffset = x - boxL;
yOffset = y - (boxT + boxB) / 2;
}
newElements[0] = elements[0];
newElements[1] = elements[1];
newElements[2] = elements[2];
newElements[3] = elements[3];
if (flags & F_SHIFTDOWN)
{
/*Constrained motion, have to calc constraint stuff*/
halfSpace = (palette -> max - palette -> min) / (palette -> nColors - 4) * 0.5;
start = GetColorValue((ObjPtr) palette, index1) - halfSpace;
finish = GetColorValue((ObjPtr) palette, index2) + halfSpace;
ddiff = finish - start;
CalcGoodSteps(ddiff,
r - l,
CBSTEPPIXELS,
&majorWidth, &nTics);
minorWidth = majorWidth / nTics;
}
/*Now do it*/
if (whichMove == MOVEBOXLEFT || whichMove == MOVEBOXRIGHT)
{
lastSide = newElements[whichMove == MOVEBOXLEFT ? 0 : 1];
while (Mouse(&newX, &newY))
{
nextSide = start +
(newX - xOffset - l) * (finish - start) / (r - l);
if (flags & F_SHIFTDOWN)
{
/*Constrain*/
temp = nextSide / minorWidth + 0.5;
nextSide = temp * minorWidth;
}
if (nextSide != lastSide)
{
/*Change it*/
newElements[whichMove == MOVEBOXLEFT ? 0 : 1] = nextSide;
if (newElements[1] > newElements[0])
{
toolBounds = NewRealArray(1, 4L);
CArray2Array(toolBounds, newElements);
SetFunctionBox(colorBar, toolBounds);
InhibitLogging(true);
ImposeColorFunction(colorBar);
InhibitLogging(false);
DrawMe(colorBar);
lastSide = nextSide;
}
}
}
}
else if (whichMove == MOVEBOXTOP || whichMove == MOVEBOXBOTTOM)
{
lastAmp = newElements[whichMove == MOVEBOXBOTTOM ? 2 : 3] + 0.5;
while (Mouse(&newX, &newY))
{
newAmp = ((newY - yOffset - b) + 0.5) * 255.0 / (real) (t - b - 1);
if (newAmp < 0) newAmp = 0;
else if (newAmp > 255) newAmp = 255;
if (newAmp != lastAmp)
{
/*Change it*/
newElements[whichMove == MOVEBOXBOTTOM ? 2 : 3] = newAmp;
if (newElements[3] > newElements[2])
{
toolBounds = NewRealArray(1, 4L);
CArray2Array(toolBounds, newElements);
SetFunctionBox(colorBar, toolBounds);
InhibitLogging(true);
ImposeColorFunction(colorBar);
InhibitLogging(false);
DrawMe(colorBar);
lastAmp = newAmp;
}
}
}
}
if (whichMove == MOVEBOXLR)
{
lastSide = newElements[0];
while (Mouse(&newX, &newY))
{
nextSide = start +
(newX - xOffset - l) * (finish - start) / (r - l);
if (flags & F_SHIFTDOWN)
{
/*Constrain*/
temp = nextSide / minorWidth + 0.5;
nextSide = temp * minorWidth;
}
if (nextSide != lastSide)
{
/*Change it*/
newElements[0] = nextSide;
newElements[1] = nextSide + elements[1] - elements[0];
if (newElements[1] > newElements[0])
{
toolBounds = NewRealArray(1, 4L);
CArray2Array(toolBounds, newElements);
SetFunctionBox(colorBar, toolBounds);
InhibitLogging(true);
ImposeColorFunction(colorBar);
InhibitLogging(false);
DrawMe(colorBar);
lastSide = nextSide;
}
}
}
}
ChangedValue(colorBar);
SetVar((ObjPtr) palette, JUSTCOLORCHANGE, ObjTrue);
ForAllVisWindows(ImInvalid);
}
}
return ObjTrue;
}
else
{
return ObjFalse;
}
#else
return ObjFalse;
#endif
}
ObjPtr NewColorBar(left, right, bottom, top, name)
int left, right, bottom, top;
char *name;
/*Makes a new hue/saturation control in left, right, bottom, top*/
{
ObjPtr retVal;
ObjPtr value;
retVal = NewObject(colorBarClass, 0);
Set2DIntBounds(retVal, left, right, bottom, top);
SetVar(retVal, NAME, NewString(name));
SetVar(retVal, TYPESTRING, NewString("color bar control"));
value = NewRealArray(1, 3L);
((real *) ELEMENTS(value))[0] = 1.0;
((real *) ELEMENTS(value))[1] = 0.0;
((real *) ELEMENTS(value))[1] = 0.0;
SetVar(retVal, VALUE, value);
return retVal;
}
#ifdef PROTO
static void ChoosePaletteSliderValue(ObjPtr, PPtr, int, int, int);
#endif
static void ChoosePaletteSliderValue(slider, palette, component, index1, index2)
ObjPtr slider;
PPtr palette;
int index1, index2, component;
/*Chooses a value for the slider based on colors index1 through index2 of
palette. Component is 0 for rgb, 1 for r, 2 for g, and 3 for b, */
{
real min, max, testVal;
short3 *colors;
real hsv[3];
int k;
colors = palette -> colors;
min = 1.0;
max = 0.0;
if (component)
{
for (k = index1; k <= index2; ++k)
{
testVal = ((real) GetColorComponent(palette, k, component - 1)) / 255.0;
if (testVal < min)
{
min = testVal;
}
if (testVal > max)
{
max = testVal;
}
}
}
else
{
for (k = index1; k <= index2; ++k)
{
RGB2HSV(&(hsv[0]), &(hsv[1]), &(hsv[2]),
((real) colors[k][0]) / 255.0,
((real) colors[k][1]) / 255.0,
((real) colors[k][2]) / 255.0);
testVal = hsv[2];
if (testVal < min)
{
min = testVal;
}
if (testVal > max)
{
max = testVal;
}
}
}
testVal = (min + max) * 0.5;
if (testVal < 0.0) testVal = 0.0;
if (testVal > 1.0) testVal = 1.0;
SetSliderValue(slider, testVal);
SetVar(slider, INITVALUE, NewReal(testVal));
SetVar(slider, TEMPPALETTE, ClonePalette((ObjPtr) palette));
}
static ObjPtr ChangePaletteBar(colorBar)
ObjPtr colorBar;
/*Changed value for a color bar that controls a palette*/
{
ObjPtr colorWheel, slider, button, buttons;
ThingListPtr buttonList;
PPtr palette;
ObjPtr value, newValue;
FuncTyp changedValue;
real hsv[3];
short3 *colors;
int index;
real *elements;
value = GetFixedArrayVar("ChangePaletteBar", colorBar, VALUE, 1, 3L);
colorWheel = GetObjectVar("ChangePaletteBar", colorBar, COLORWHEEL);
palette = (PPtr) GetPaletteVar("ChangePaletteBar", colorBar, REPOBJ);
slider = GetObjectVar("ChangePaletteBar", colorBar, SLIDER);
if (!colorWheel || !palette || !value || !slider)
{
return ObjFalse;
}
elements = ELEMENTS(value);
if (elements[0] == 1.0)
{
/*Active color wheel*/
ActivateColorWheel(colorWheel, true);
if (elements[1] == elements[2])
{
/*Give it a value*/
colors = palette -> colors;
/*Update the left slider and color wheel*/
index = elements[1];
RGB2HSV(&(hsv[0]), &(hsv[1]), &(hsv[2]),
((real) colors[index][0]) / 255.0,
((real) colors[index][1]) / 255.0,
((real) colors[index][2]) / 255.0);
if (hsv[2] < 0.0) hsv[2] = 0.0;
else if (hsv[2] > 1.0) hsv[2] = 1.0;
}
else
{
/*No value*/
newValue = NULLOBJ;
}
changedValue = GetMethod(colorWheel, CHANGEDVALUE);
SetMethod(colorWheel, CHANGEDVALUE, 0);
newValue = NewRealArray(1, 2L);
((real *) ELEMENTS(newValue))[0] = hsv[0];
((real *) ELEMENTS(newValue))[1] = hsv[1];
SetValue(colorWheel, newValue);
SetMethod(colorWheel, CHANGEDVALUE, changedValue);
}
else
{
ActivateColorWheel(colorWheel, false);
}
buttons = GetVar(colorBar, FULLCOMPBUTTONS);
if (buttons)
{
buttonList = LISTOF(buttons);
}
else
{
buttonList = 0;
}
if (elements[0] > 0.0)
{
/*Active Slider and buttons*/
int index1, index2;
int comp;
changedValue = GetMethod(slider, CHANGEDVALUE);
SetMethod(slider, CHANGEDVALUE, 0);
ActivateSlider(slider, true);
/*Get a value for the slider*/
index1 = elements[1];
index2 = elements[2];
if (elements[0] == 1.0)
{
comp = 0;
}
else
{
comp = 5 - (int) elements[0];
}
ChoosePaletteSliderValue(slider, palette, comp,
index1, index2);
SetMethod(slider, CHANGEDVALUE, changedValue);
/*Activate buttons*/
while (buttonList)
{
ActivateButton(buttonList -> thing, true);
buttonList = buttonList -> next;
}
}
else
{
/*Inactive Slider*/
ActivateSlider(slider, false);
/*Deactivate buttons*/
while (buttonList)
{
ActivateButton(buttonList -> thing, false);
buttonList = buttonList -> next;
}
}
buttons = GetVar(colorBar, COMPBUTTONS);
if (buttons)
{
buttonList = LISTOF(buttons);
}
else
{
buttonList = 0;
}
if (elements[0] > 1.0 && elements[2] > elements[1])
{
/*Activate buttons*/
while (buttonList)
{
ActivateButton(buttonList -> thing, true);
buttonList = buttonList -> next;
}
}
else
{
/*Deactivate buttons*/
while (buttonList)
{
ActivateButton(buttonList -> thing, false);
buttonList = buttonList -> next;
}
}
button = GetVar(colorBar, FREEFORMBUTTON);
if (elements[0] > 1.0)
{
if (button)
{
ActivateButton(button, true);
}
}
else
{
if (button)
{
ActivateButton(button, false);
}
}
ImInvalid(colorBar);
return ObjTrue;
}
static ObjPtr ChangePaletteColorWheel(colorWheel)
ObjPtr colorWheel;
/*Changes a color wheel*/
{
ObjPtr slider, colorBar, panel, button;
PPtr palette;
ObjPtr var;
real h, s, v;
real r, g, b;
int rs, gs, bs;
short3 *colors;
int index1, index2, k;
real *elements;
slider = GetObjectVar("ChangePaletteColorWheel", colorWheel, SLIDER);
colorBar = GetObjectVar("ChangePaletteColorWheel", colorWheel, COLORBAR);
if (!slider || !colorBar)
{
return ObjFalse;
}
palette = (PPtr) GetPaletteVar("ChangePaletteColorWheel", colorBar, REPOBJ);
if (!palette)
{
return ObjFalse;
}
var = GetValue(colorBar);
if (!var)
{
return ObjFalse;
}
if (((real *) ELEMENTS(var))[0] != 1.0)
{
return ObjFalse;
}
index1 = ((real *) ELEMENTS(var))[1];
index2 = ((real *) ELEMENTS(var))[2];
var = GetValue(colorWheel);
if (!var)
{
return ObjFalse;
}
h = ((real *) ELEMENTS(var))[0];
s = ((real *) ELEMENTS(var))[1];
var = GetValue(slider);
if (!var)
{
return ObjFalse;
}
v = GetReal(var);
HSV2RGB(&r, &g, &b, h, s, v);
/*Change the palette. Tricky.*/
rs = r * 255.0;
gs = g * 255.0;
bs = b * 255.0;
if (rs > 255) rs = 255;
else if (rs < 0) rs = 0;
if (gs > 255) gs = 255;
else if (gs < 0) gs = 0;
if (bs > 255) rs = 255;
else if (bs < 0) bs = 0;
colors = palette -> colors;
for (k = index1; k <= index2; ++k)
{
colors[k][0] = rs;
colors[k][1] = gs;
colors[k][2] = bs;
}
CopyColorsToComponents(palette, index1, index2);
#ifdef GRAPHICS
MapPaletteColors(palette, index1, index2);
#endif
SetVar((ObjPtr) palette, JUSTCOLORCHANGE, ObjTrue);
panel = GetVar(colorWheel, PARENT);
if (panel)
{
button = GetVar(panel, KEEPBUTTON);
if (button)
{
ActivateButton(button, true);
}
button = GetVar(panel, REVERTBUTTON);
if (button)
{
ActivateButton(button, true);
}
}
SetVar(slider, TEMPPALETTE, ClonePalette((ObjPtr) palette));
/* interactiveMoving = false;*/
ForAllVisWindows(ImInvalid);
DrawMe(colorBar);
return ObjTrue;
}
static ObjPtr ChangePaletteSlider(slider)
ObjPtr slider;
/*Changes a palette's slider*/
{
ObjPtr colorBar, panel, button;
PPtr palette, tempPalette;
ObjPtr var;
short rs, gs, bs;
short3 *colors, *tempColors;
int index1, index2, k, comp;
real sliderValue, initValue;
real change;
ObjPtr radio;
ObjPtr colorWheel, hsObj;
colorBar = GetObjectVar("ChangePaletteSlider", slider, COLORBAR);
tempPalette = (PPtr) GetPaletteVar("ChangePaletteSlider", slider, TEMPPALETTE);
if (!colorBar || !tempPalette)
{
return ObjFalse;
}
palette = (PPtr) GetPaletteVar("ChangePaletteSlider", colorBar, REPOBJ);
if (!palette)
{
return ObjFalse;
}
colorWheel = GetObjectVar("ChangePaletteSlider", colorBar, COLORWHEEL);
if (!colorWheel)
{
return ObjFalse;
}
var = GetRealVar("ChangePaletteSlider", slider, INITVALUE);
if (var)
{
initValue = GetReal(var);
}
else
{
return ObjFalse;
}
var = GetValue(colorBar);
if (!var)
{
return ObjFalse;
}
comp = 5 - ((real *) ELEMENTS(var))[0];
if (comp == 4) comp = 0;
if (comp < 0)
{
return ObjFalse;
}
index1 = ((real *) ELEMENTS(var))[1];
index2 = ((real *) ELEMENTS(var))[2];
var = GetValue(slider);
if (!var)
{
return ObjFalse;
}
sliderValue = GetReal(var);
colors = palette -> colors;
tempColors = tempPalette -> colors;
if (sliderValue < initValue)
{
/*Attenuate value*/
change = sliderValue / initValue;
if (comp == 0)
{
/*Full color*/
real h, s, v, dummy;
real r, g, b;
for (k = index1; k <= index2; ++k)
{
r = tempColors[k][0] / 255.0;
g = tempColors[k][1] / 255.0;
b = tempColors[k][2] / 255.0;
RGB2HSV(&h, &s, &v, r, g, b);
if (index1 == index2)
{
hsObj = GetValue(colorWheel);
if (!hsObj || !IsRealArray(hsObj) || RANK(hsObj) != 1 || DIMS(hsObj)[0] != 2)
{
return ObjFalse;
}
/*Single color, refresh value from wheel*/
h = ((real *) ELEMENTS(hsObj))[0];
s = ((real *) ELEMENTS(hsObj))[1];
v = sliderValue;
}
else
{
v *= change;
}
if (v > 1.0) v = 1.0;
if (v < 0.0) v = 0.0;
HSV2RGB(&r, &g, &b, h, s, v);
rs = r * 255.0 + 0.5;
gs = g * 255.0 + 0.5;
bs = b * 255.0 + 0.5;
colors[k][0] = rs;
colors[k][1] = gs;
colors[k][2] = bs;
}
CopyColorsToComponents(palette, index1, index2);
}
else
{
real component;
for (k = index1; k <= index2; ++k)
{
component = ((real) GetColorComponent(tempPalette, k, comp - 1)) / 255.0;
component *= change;
if (component > 1.0) component = 1.0;
else if (component < 0.0) component = 0.0;
SetColorComponent(palette, k, comp - 1, (int) (component * 255.0 + 0.5));
}
CopyComponentsToColors(palette, index1, index2);
}
#ifdef GRAPHICS
MapPaletteColors(palette, index1, index2);
#endif
}
else
{
/*Brighten value*/
change = (1.0 - sliderValue) / (1.0 - initValue);
if (comp == 0)
{
/*Full color*/
real h, s, v, dummy;
real r, g, b;
for (k = index1; k <= index2; ++k)
{
r = tempColors[k][0] / 255.0;
g = tempColors[k][1] / 255.0;
b = tempColors[k][2] / 255.0;
RGB2HSV(&h, &s, &v, r, g, b);
if (index1 == index2)
{
/*Single color, refresh value from wheel*/
hsObj = GetValue(colorWheel);
if (!hsObj || !IsRealArray(hsObj) || RANK(hsObj) != 1 || DIMS(hsObj)[0] != 2)
{
return ObjFalse;
}
h = ((real *) ELEMENTS(hsObj))[0];
s = ((real *) ELEMENTS(hsObj))[1];
v = sliderValue;
}
else
{
v = 1.0 - (1.0 - v) * change;
}
if (v > 1.0) v = 1.0;
if (v < 0.0) v = 0.0;
HSV2RGB(&r, &g, &b, h, s, v);
rs = r * 255.0 + 0.5;
gs = g * 255.0 + 0.5;
bs = b * 255.0 + 0.5;
colors[k][0] = rs;
colors[k][1] = gs;
colors[k][2] = bs;
}
CopyColorsToComponents(palette, index1, index2);
}
else
{
real component;
for (k = index1; k <= index2; ++k)
{
component = ((real) GetColorComponent(tempPalette, k, comp - 1)) / 255.0;
component = 1.0 - (1.0 - component) * change;
if (component > 1.0) component = 1.0;
else if (component < 0.0) component = 0.0;
SetColorComponent(palette, k, comp - 1, (int) (component * 255.0 + 0.5));
}
CopyComponentsToColors(palette, index1, index2);
}
#ifdef GRAPHICS
MapPaletteColors(palette, index1, index2);
#endif
}
ResetColorBarTools(colorBar);
SetVar((ObjPtr) palette, JUSTCOLORCHANGE, ObjTrue);
panel = GetVar(slider, PARENT);
if (panel)
{
button = GetVar(panel, KEEPBUTTON);
if (button)
{
ActivateButton(button, true);
}
button = GetVar(panel, REVERTBUTTON);
if (button)
{
ActivateButton(button, true);
}
}
/* interactiveMoving = false;*/
ForAllVisWindows(ImInvalid);
DrawMe(colorBar);
return ObjTrue;
}
void DoRevertPalette()
/*Reverts a palette in the top window*/
{
ObjPtr repObj, keptPalette, colorBar, textBox, radio;
Log("revert\n");
if (!selWinInfo)
{
return;
}
repObj = GetPaletteVar("DoRevertPalette", (ObjPtr) selWinInfo, REPOBJ);
if (!repObj)
{
return;
}
keptPalette = GetPaletteVar("DoRevertPalette", repObj, KEPTPALETTE);
if (!keptPalette)
{
return;
}
CopyPalette(repObj, keptPalette);
SetVar(repObj, CHANGED, ObjTrue);
if (colorBar = GetObjectVar("DoRevertPalette", (ObjPtr) selWinInfo, COLORBAR))
{
ObjPtr var;
real newValue[3];
InhibitLogging(true);
newValue[0] = newValue[1] = newValue[2] = 0.0;
var = NewRealArray(1, 3L);
CArray2Array(var, newValue);
SetValue(colorBar, var);
InhibitLogging(false);
}
/*Change the text boxes*/
if (textBox = GetObjectVar("RevertButton", (ObjPtr) selWinInfo, NCOLORBOX))
{
sprintf(tempStr, "%d", ((PPtr) repObj) -> nColors);
SetValue(textBox, NewString(tempStr));
}
if (textBox = GetObjectVar("RevertButton", (ObjPtr) selWinInfo, MINBOX))
{
sprintf(tempStr, "%g", ((PPtr) repObj) -> min);
SetValue(textBox, NewString(tempStr));
}
if (textBox = GetObjectVar("RevertButton", (ObjPtr) selWinInfo, MAXBOX))
{
sprintf(tempStr, "%g", ((PPtr) repObj) -> max);
SetValue(textBox, NewString(tempStr));
}
if (radio = GetObjectVar("RevertButton", (ObjPtr) selWinInfo, CMODELRADIO))
{
FuncTyp method;
method = GetMethod(radio, CHANGEDVALUE);
SetMethod(radio, CHANGEDVALUE, (FuncTyp) 0);
SetValue(radio, GetVar(repObj, COLORMODEL));
SetMethod(radio, CHANGEDVALUE, method);
}
/*DIKEO figure out a better way of doing this*/
ForAllVisWindows(ImInvalid);
}
void DoKeepPalette()
/*Keeps the changes in the palette of the current window*/
{
ObjPtr repObj, keptPalette, colorBar;
Log("keep\n");
if (!selWinInfo)
{
return;
}
repObj = GetPaletteVar("DoKeepPalette", (ObjPtr) selWinInfo, REPOBJ);
if (!repObj)
{
return;
}
CopyPalette(keptPalette, repObj);
return;
}
static void SimplePaletteFunction(whichFunc, palette, index1, index2, comp, colorBar)
int whichFunc;
PPtr palette;
int index1, index2, comp;
ObjPtr colorBar;
/*Does a simple function on palette*/
{
int k;
real r1, g1, b1, r2, g2, b2, r3, g3, b3, r, g, b, c;
int rs, gs, bs, cs;
if (logging)
{
Log("effect ");
Log(spfNames[whichFunc]);
Log("\n");
}
switch (whichFunc)
{
case PF_RAMP:
/*Change the palette to a ramp*/
for (k = index1 + 1; k < index2; ++k)
{
if (comp == 0 || comp == 1)
{
c = ((k - index1) * (GetColorComponent(palette, index2, 0) / 255.0)
+ (index2 - k) * (GetColorComponent(palette, index1, 0) / 255.0)) / (index2 - index1);
cs = c * 255.0;
SetColorComponent(palette, k, 0, cs);
}
if (comp == 0 || comp == 2)
{
c = ((k - index1) * (GetColorComponent(palette, index2, 1) / 255.0)
+ (index2 - k) * (GetColorComponent(palette, index1, 1) / 255.0)) / (index2 - index1);
cs = c * 255.0;
SetColorComponent(palette, k, 1, cs);
}
if (comp == 0 || comp == 3)
{
c = ((k - index1) * (GetColorComponent(palette, index2, 2) / 255.0)
+ (index2 - k) * (GetColorComponent(palette, index1, 2) / 255.0)) / (index2 - index1);
cs = c * 255.0;
SetColorComponent(palette, k, 2, cs);
}
}
break;
case PF_REVERSE:
for (k = 0; k < (index2 - index1 + 1) / 2; ++k)
{
int tempColor;
if (comp == 0 || comp == 1)
{
/*First component*/
tempColor = GetColorComponent(palette, index2 - k, 0);
SetColorComponent(palette, index2 - k, 0,
GetColorComponent(palette, index1 + k, 0));
SetColorComponent(palette, index1 + k, 0, tempColor);
}
if (comp == 0 || comp == 2)
{
/*Secpmd component*/
tempColor = GetColorComponent(palette, index2 - k, 1);
SetColorComponent(palette, index2 - k, 1,
GetColorComponent(palette, index1 + k, 1));
SetColorComponent(palette, index1 + k, 1, tempColor);
}
if (comp == 0 || comp == 3)
{
/*Third component*/
tempColor = GetColorComponent(palette, index2 - k, 2);
SetColorComponent(palette, index2 - k, 2,
GetColorComponent(palette, index1 + k, 2));
SetColorComponent(palette, index1 + k, 2, tempColor);
}
}
break;
case PF_RUFFLE:
{
int left, right, bottom, top, l, r;
long oldQuotient, newQuotient;
double ddiff, majorWidth, minorWidth, halfSpace;
real val;
ObjPtr var;
int nTics;
Get2DIntBounds(colorBar, &left, &right, &bottom, &top);
l = left + CBLBORDER + 2 * CBBOXWIDTH + 2 * CBHGAP + 1;
r = right - CBRBORDER - CBBOXWIDTH - CBHGAP - 1;
halfSpace = (palette -> max - palette -> min) / (palette -> nColors - 4) * 0.5;
ddiff = palette -> max - palette -> min + 2 * halfSpace;
CalcGoodSteps(ddiff,
r - l,
CBSTEPPIXELS,
&majorWidth, &nTics);
minorWidth = majorWidth / nTics;
l = index1;
val = (l - 2) * ddiff / (palette -> nColors - 3);
oldQuotient = val / minorWidth;
for (r = l + 1; r <= index2; ++r)
{
val = (r - 2) * ddiff / (palette -> nColors - 3);
newQuotient = val / minorWidth;
if (newQuotient != oldQuotient ||
r == index2)
{
/*Time for a reversal*/
if (r == index2) ++r;
oldQuotient = newQuotient;
for (k = 0; k < (r - l) / 2; ++k)
{
int tempColor;
if (comp == 0 || comp == 1)
{
/*Component*/
tempColor = GetColorComponent(palette, r - 1 - k, 0);
SetColorComponent(palette, r - 1 - k, 0,
GetColorComponent(palette, l + k, 0));
SetColorComponent(palette, l + k, 0, tempColor);
}
if (comp == 0 || comp == 2)
{
/*Component*/
tempColor = GetColorComponent(palette, r - 1 - k, 1);
SetColorComponent(palette, r - 1 - k, 1,
GetColorComponent(palette, l + k, 1));
SetColorComponent(palette, l + k, 1, tempColor);
}
if (comp == 0 || comp == 3)
{
/*Component*/
tempColor = GetColorComponent(palette, r - 1 - k, 2);
SetColorComponent(palette, r - 1 - k, 2,
GetColorComponent(palette, l + k, 2));
SetColorComponent(palette, l + k, 2, tempColor);
}
}
l = r;
}
}
}
break;
case PF_SMOOTH:
if (index2 <= index1) break;
r1 = (GetColorComponent(palette, index1, 0) + 0.5) / 255.0;
g1 = (GetColorComponent(palette, index1, 1) + 0.5) / 255.0;
b1 = (GetColorComponent(palette, index1, 2) + 0.5) / 255.0;
r2 = (GetColorComponent(palette, index1 + 1, 0) + 0.5) / 255.0;
g2 = (GetColorComponent(palette, index1 + 1, 1) + 0.5) / 255.0;
b2 = (GetColorComponent(palette, index1 + 1, 2) + 0.5) / 255.0;
for (k = index1 + 2; k < index2; ++k)
{
r3 = (GetColorComponent(palette, k + 1, 0) + 0.5) / 255.0;
g3 = (GetColorComponent(palette, k + 1, 1) + 0.5) / 255.0;
b3 = (GetColorComponent(palette, k + 1, 2) + 0.5) / 255.0;
r = ((r1 + r3) * 0.5 + r2) * 0.5;
g = ((g1 + g3) * 0.5 + g2) * 0.5;
b = ((b1 + b3) * 0.5 + b2) * 0.5;
rs = r * 255.0;
gs = g * 255.0;
bs = b * 255.0;
if (comp == 0 || comp == 1)
{
SetColorComponent(palette, k, 0, rs);
}
if (comp == 0 || comp == 2)
{
SetColorComponent(palette, k, 1, gs);
}
if (comp == 0 || comp == 3)
{
SetColorComponent(palette, k, 2, bs);
}
r1 = r2; r2 = r3;
g1 = g2; g2 = g3;
b1 = b2; b2 = b3;
}
break;
case PF_SHARPEN:
if (index2 <= index1) break;
r1 = (GetColorComponent(palette, index1, 0) + 0.5) / 255.0;
g1 = (GetColorComponent(palette, index1, 1) + 0.5) / 255.0;
b1 = (GetColorComponent(palette, index1, 2) + 0.5) / 255.0;
r2 = (GetColorComponent(palette, index1 + 1, 0) + 0.5) / 255.0;
g2 = (GetColorComponent(palette, index1 + 1, 1) + 0.5) / 255.0;
b2 = (GetColorComponent(palette, index1 + 1, 2) + 0.5) / 255.0;
for (k = index1 + 2; k < index2; ++k)
{
r3 = (GetColorComponent(palette, k + 1, 0) + 0.5) / 255.0;
g3 = (GetColorComponent(palette, k + 1, 1) + 0.5) / 255.0;
b3 = (GetColorComponent(palette, k + 1, 2) + 0.5) / 255.0;
r = r2 + (r2 - (r1 + r3) * 0.5) * 2.0;
if (r > 1.0) r = 1.0; else if (r < 0.0) r = 0.0;
g = g2 + (g2 - (g1 + g3) * 0.5) * 2.0;
if (g > 1.0) g = 1.0; else if (g < 0.0) g = 0.0;
b = b2 + (b2 - (b1 + b3) * 0.5) * 2.0;
if (b > 1.0) b = 1.0; else if (b < 0.0) b = 0.0;
rs = r * 255.0;
gs = g * 255.0;
bs = b * 255.0;
if (comp == 0 || comp == 1)
{
SetColorComponent(palette, k, 0, rs);
}
if (comp == 0 || comp == 2)
{
SetColorComponent(palette, k, 1, gs);
}
if (comp == 0 || comp == 3)
{
SetColorComponent(palette, k, 2, bs);
}
r1 = r2; r2 = r3;
g1 = g2; g2 = g3;
b1 = b2; b2 = b3;
}
break;
}
CopyComponentsToColors(palette, index1, index2);
}
static ObjPtr SimpleFuncButton(button)
ObjPtr button;
/*Do a simple palette function*/
{
ObjPtr colorBar, panel;
PPtr palette;
ObjPtr var;
int whichFunc;
int index1, index2, comp, k;
colorBar = GetObjectVar("SimpleFuncButton", button, COLORBAR);
if (!colorBar)
{
return ObjFalse;
}
var = GetIntVar("SimpleFuncButton", button, PALETTEFUNC);
if (!var)
{
return ObjFalse;
}
whichFunc = GetInt(var);
palette = (PPtr) GetPaletteVar("SimpleFuncButton", colorBar, REPOBJ);
if (!palette)
{
return false;
}
var = GetValue(colorBar);
if (!var)
{
return ObjFalse;
}
if (((real *) ELEMENTS(var))[0] < 1.0)
{
return ObjFalse;
}
index1 = ((real *) ELEMENTS(var))[1];
index2 = ((real *) ELEMENTS(var))[2];
if (((real *) ELEMENTS(var))[0] == 1.0)
{
comp = 0;
}
else
{
comp = 5 - (int) ((real *) ELEMENTS(var))[0];
}
SimplePaletteFunction(whichFunc, palette, index1, index2, comp, colorBar);
#ifdef GRAPHICS
MapPaletteColors(palette, index1, index2);
#endif
SetVar((ObjPtr) palette, JUSTCOLORCHANGE, ObjTrue);
panel = GetVar(button, PARENT);
if (panel)
{
button = GetVar(panel, KEEPBUTTON);
if (button)
{
ActivateButton(button, true);
}
button = GetVar(panel, REVERTBUTTON);
if (button)
{
ActivateButton(button, true);
}
}
/* interactiveMoving = false;*/
InhibitLogging(true);
ChangedValue(colorBar);
InhibitLogging(false);
/*DIKEO figure out a better way of doing this*/
ForAllVisWindows(ImInvalid);
ImInvalid(colorBar);
return ObjTrue;
}
void SimpleFuncFromMenu(whichFunc)
int whichFunc;
/*Do a simple palette function*/
{
ObjPtr colorBar, panel;
PPtr palette;
ObjPtr var;
int index1, index2, comp, k;
if (!selWinInfo)
{
return;
}
#ifndef MENUSFROM0
--whichFunc;
#endif
colorBar = GetObjectVar("SimpleFuncFromMenu", (ObjPtr) selWinInfo, COLORBAR);
if (!colorBar)
{
return;
}
palette = (PPtr) GetPaletteVar("SimpleFuncButton", (ObjPtr) selWinInfo, REPOBJ);
if (!palette)
{
return;
}
var = GetValue(colorBar);
if (!var)
{
return;
}
if (((real *) ELEMENTS(var))[0] < 1.0)
{
return;
}
index1 = ((real *) ELEMENTS(var))[1];
index2 = ((real *) ELEMENTS(var))[2];
if (((real *) ELEMENTS(var))[0] == 1.0)
{
comp = 0;
}
else
{
comp = 5 - (int) ((real *) ELEMENTS(var))[0];
}
SimplePaletteFunction(whichFunc, palette, index1, index2, comp, colorBar);
#ifdef GRAPHICS
MapPaletteColors(palette, index1, index2);
#endif
SetVar((ObjPtr) palette, JUSTCOLORCHANGE, ObjTrue);
InhibitLogging(true);
ChangedValue(colorBar);
InhibitLogging(false);
/*DIKEO figure out a better way*/
ForAllVisWindows(ImInvalid);
ImInvalid(colorBar);
return;
}
#ifdef PROTO
void ActivateColorWheel(ObjPtr wheel, Bool whether)
#else
void ActivateColorWheel(wheel, whether)
ObjPtr wheel;
Bool whether;
#endif
/*Activates a color wheel*/
{
SetVar(wheel, ACTIVATED, whether ? ObjTrue : ObjFalse);
ImInvalid(wheel);
}
#ifdef PROTO
static int GetColorComponent(PPtr palette, int whichColor, int comp)
#else
static int GetColorComponent(palette, whichColor, comp)
PPtr palette;
int whichColor;
int comp;
#endif
/*Gets the color component comp from whichColor in palette*/
{
return palette -> components[whichColor][comp];
}
#ifdef PROTO
static void SetColorComponent(PPtr palette, int whichColor, int comp, int cc)
#else
static void SetColorComponent(palette, whichColor, comp, cc)
PPtr palette, int whichColor; int comp; int cc;
#endif
/*Changes component comp in whichColor of palette to cc*/
{
real rgb[3], hsv[3], hls[3], yiq[3];
palette -> components[whichColor][comp] = cc;
CopyComponentsToColors(palette, whichColor, whichColor);
}
ObjPtr ImposeColorFunction(colorBar)
ObjPtr colorBar;
/*Imposes a color function on colorBar.
Function is given by EDITMODE
Box is given by FUNCTIONBOX
*/
{
ObjPtr value, var, palette, panel, button;
real *elements;
int comp;
int index1, index2, k, cc;
real beg, end, fieldVal;
int min, max;
int tool;
int cm;
value = GetValue(colorBar);
if (!value)
{
return ObjFalse;
}
palette = GetPaletteVar("ImposeColorFunction", colorBar, REPOBJ);
if (!palette)
{
return ObjFalse;
}
elements = ELEMENTS(value);
if (elements[1] < 1.5)
{
/*Not on a component*/
return ObjFalse;
}
var = GetIntVar("ImposeColorFunction", colorBar, EDITMODE);
if (!var)
{
return ObjFalse;
}
tool = GetInt(var);
comp = 4 - elements[0];
index1 = elements[1] + 0.5;
index2 = elements[2] + 0.5;
var = GetVar(colorBar, FUNCTIONBOX);
if (!var)
{
/*No box around function!*/
return ObjFalse;
}
elements = ELEMENTS(var);
beg = elements[0];
end = elements[1];
min = elements[2] + 0.5;
max = elements[3] + 0.5;
var = GetVar(palette, COLORMODEL);
if (var)
{
cm = GetInt(var);
}
else
{
cm = CM_RGB;
}
for (k = index1; k <= index2; ++k)
{
fieldVal = GetColorValue(palette, k);
while (fieldVal < beg)
{
fieldVal += end - beg;
}
while (fieldVal > end)
{
fieldVal -= end - beg;
}
fieldVal -= beg;
fieldVal /= (end - beg);
/*Now fieldVal is in [0, 1) */
switch (tool)
{
case PT_SINE: /*Sine function*/
cc = min + (max - min) * ((1.0 + rsin(fieldVal * 2.0 * M_PI)) * 0.5);
break;
case PT_TRIANGLE: /*Triangle function*/
if (fieldVal < 0.25)
{
cc = (max + min) / 2 + fieldVal * 2.0 * (max - min);
}
else if (fieldVal > 0.75)
{
cc = min + (fieldVal - 0.75) * 2.0 * (max - min);
}
else
{
cc = min + (0.75 - fieldVal) * 2.0 * (max - min);
}
break;
case PT_SAWTOOTH: /*Sawtooth function*/
cc = min + fieldVal * (max - min);
break;
case PT_TOOTHSAW: /*Toothsaw function*/
cc = max - fieldVal * (max - min);
break;
case PT_SQUARE: /*Square wave function*/
if (fieldVal < 0.5)
{
cc = max;
}
else
{
cc = min;
}
break;
default:
cc = 0;
}
SetColorComponent((PPtr) palette, k, comp, cc);
}
CopyComponentsToColors((PPtr) palette, index1, index2);
MapPaletteColors((PPtr) palette, index1, index2);
panel = GetVar(colorBar, PARENT);
if (panel)
{
button = GetVar(panel, KEEPBUTTON);
if (button)
{
ActivateButton(button, true);
}
button = GetVar(panel, REVERTBUTTON);
if (button)
{
ActivateButton(button, true);
}
}
SetVar((ObjPtr) palette, JUSTCOLORCHANGE, ObjTrue);
return ObjTrue;
}
static ObjPtr ChangeColorTool(group)
ObjPtr group;
/*Changes a color tool in response to a radio button group*/
{
ObjPtr colorBar;
PPtr palette;
ObjPtr value;
ObjPtr var;
int tool;
ObjPtr selection;
real *elements;
colorBar = GetObjectVar("ChangeColorTool", group, REPOBJ);
if (!colorBar)
{
return ObjFalse;
}
selection = GetValue(colorBar);
elements = ELEMENTS(selection);
palette = (PPtr) GetPaletteVar("ChangeColorTool", colorBar, REPOBJ);
if (!palette)
{
return ObjFalse;
}
value = GetValue(group);
if (!value)
{
return false;
}
tool = GetInt(value);
var = GetVar(colorBar, EDITMODE);
if (var && GetInt(var) == tool)
{
/*Don't need to do anything*/
return ObjFalse;
}
SetVar(colorBar, EDITMODE, NewInt(tool));
if (tool > 0)
{
/*It's a function.*/
var = GetVar(colorBar, FUNCTIONBOX);
if (!var)
{
/*Calculate initial function box*/
int left, right, bottom, top, l, r, b, t;
double majorWidth;
double halfSpace;
double start, finish, middle, ddiff;
int nTics;
long temp;
Get2DIntBounds(colorBar, &left, &right, &bottom, &top);
l = left + CBLBORDER + 1;
r = right - CBRBORDER - 1;
halfSpace = (palette -> max - palette -> min) / (palette -> nColors - 4) * 0.5;
start = GetColorValue((ObjPtr) palette, (int) elements[1]) - halfSpace;
finish = GetColorValue((ObjPtr) palette, (int) elements[2]) + halfSpace;
middle = (start + finish) * 0.5;
ddiff = finish - start;
CalcGoodSteps(ddiff,
r - l,
CBSTEPPIXELS,
&majorWidth, &nTics);
/*Minor and major tics first*/
temp = middle / majorWidth;
start = temp * majorWidth;
finish = start + majorWidth;
var = NewRealArray(1, 4L);
((real *) ELEMENTS(var))[0] = start - majorWidth;
((real *) ELEMENTS(var))[1] = finish;
((real *) ELEMENTS(var))[2] = 0.0;
((real *) ELEMENTS(var))[3] = 255.0;
InhibitLogging(true);
SetFunctionBox(colorBar, var);
InhibitLogging(false);
}
InhibitLogging(true);
ImposeColorFunction(colorBar);
SetVar((ObjPtr) palette, JUSTCOLORCHANGE, ObjTrue);
ForAllVisWindows(ImInvalid);
InhibitLogging(false);
}
else
{
/*No function box*/
InhibitLogging(true);
SetFunctionBox(colorBar, NULLOBJ);
InhibitLogging(false);
}
ImInvalid(colorBar);
return ObjTrue;
}
static ObjPtr MakePaletteBarHelp(colorBar, class)
ObjPtr colorBar;
ObjPtr class;
/*Makes help for a color bar*/
{
ObjPtr help, temp;
ObjPtr var;
int editMode;
real *elements;
help = NewString("This control shows a color palette. The color bar at \
the bottom shows the range of colors in the palette associated with the field \
values, plus colors for missing data, overflow, and underflow values. \
Above the color bar are three bars showing the magnitude of the three components \
of each color, plus a magnified readout at the top.\n\
\n\
You can select a range of colors to edit by clicking in the color bar or one of the \
three component bars and dragging through the colors you want to edit. When you \
select a range, controls in the window that can edit the color will become active. \
Also, the selected range will be expanded to fill the magnified readout at the top of the control. \
When a color component is selected, you can edit it using the Edit Component \
buttons to the left.");
var = GetValue(colorBar);
if (var)
{
elements = ELEMENTS(var);
if (elements[0] > 1.5)
{
/*A component is selected*/
var = GetIntVar("MakePaletteBarHelp", colorBar, EDITMODE);
if (var)
{
ObjPtr palette;
int cm;
editMode = GetInt(var);
palette = GetVar(colorBar, REPOBJ);
if (!palette)
{
return ObjFalse;
}
var = GetVar(palette, COLORMODEL);
if (var)
{
cm = GetInt(var);
}
else
{
cm = CM_RGB;
}
sprintf(tempStr, "\n\nThe %s components of a range of colors are \
currently selected. The Intensity slider on the left lets you change the brightness \
of this component of the range. The buttons at the top of the window let you \
perform some simple functions over the entire range of colors. Use Help In \
Context to find out what each of these buttons does.\n\n",
componentNames[cm][4 - (int) (elements[0] + 0.5)]);
temp = NewString(tempStr);
help = ConcatStrings(help, temp);
if (editMode == PT_FREEFORM)
{
/*Free form tool*/
temp = NewString("The free form tool is selected. \
You can modify the waveform shown at the top of the control by clicking and drawing \
within the box. The Shift key will constrain motion in just the vertical or \
horizontal direction.\n");
help = ConcatStrings(help, temp);
}
else
{
/*Waveform tool*/
sprintf(tempStr, "The %s tool is selected. Notice \
that there is a yellow box within the magnified readout at \
the top of the control. This box encloses one period of a %s which is used \
to fill the entire selected range of the component. ",
toolNames[editMode], toolNames[editMode]);
temp = NewString(tempStr);
help = ConcatStrings(help, temp);
temp = NewString("Click and drag the square \
handles on the top or bottom to change the minimum and maximum values of the wave. Click \
Click and drag the handles on the left or right to change the beginning and end \
of the wave as well as its wavelength. The Shift key will constrain motion to \
the nearest tic mark. Click and drag within the box to move the entire waveform \
left or right.");
help = ConcatStrings(help, temp);
}
}
}
else if (elements[0] > 0.5)
{
temp = NewString("\n\nA range of colors is \
currently selected. The Intensity slider on the left lets you change the brightness \
of this component of the range. The Color color wheel lets you change \
the hue and saturation of the entire range. When you click on this \
control, the entire range will become a single color. \
The buttons at the top of the window let you \
perform some simple functions over the entire range of colors. Use Help In \
Context to find out what each of these buttons does.");
help = ConcatStrings(help, temp);
}
}
SetVar(class, HELPSTRING, help);
return ObjTrue;
}
static ObjPtr EnterMin(box)
ObjPtr box;
/*Enters the minimum value from box*/
{
ObjPtr value, colorBar, panel, button;
PPtr palette;
float min;
char *s;
FuncTyp method;
value = GetValue(box);
if (!value)
{
return ObjFalse;
}
s = GetString(value);
if (!ParseReal(&min, s))
{
return ObjFalse;
}
#if 0
if (min <= minusInf || min >= plusInf)
{
DoUniqueTask(DoInfinityError);
return ObjFalse;
}
#endif
if (min == missingData)
{
DoUniqueTask(DoMissingError);
}
colorBar = GetObjectVar("EnterMin", box, REPOBJ);
if (!colorBar)
{
return ObjFalse;
}
palette = (PPtr) GetVar(colorBar, REPOBJ);
if (!palette)
{
return ObjTrue;
}
if (min >= palette -> max)
{
DoUniqueTask(DoRangeError);
return ObjFalse;
}
palette -> min = min;
ReinitColorBar(colorBar);
ImInvalid(colorBar);
SetVar((ObjPtr) palette, CHANGED, ObjTrue);
ForAllVisWindows(ImInvalid);
panel = GetVar(box, PARENT);
if (panel)
{
button = GetVar(panel, KEEPBUTTON);
if (button)
{
ActivateButton(button, true);
}
button = GetVar(panel, REVERTBUTTON);
if (button)
{
ActivateButton(button, true);
}
}
return ObjTrue;
}
static ObjPtr EnterMax(box)
ObjPtr box;
/*Enters the max value from box*/
{
ObjPtr value, colorBar, panel, button;
PPtr palette;
float max;
FuncTyp method;
value = GetValue(box);
if (!value)
{
return ObjFalse;
}
if (!ParseReal(&max, GetString(value)))
{
DoUniqueTask(DoNumberError);
return ObjFalse;
}
if (max <= minusInf || max >= plusInf)
{
DoUniqueTask(DoInfinityError);
return ObjFalse;
}
if (max == missingData)
{
DoUniqueTask(DoMissingError);
}
colorBar = GetObjectVar("EnterMin", box, REPOBJ);
if (!colorBar)
{
return ObjFalse;
}
palette = (PPtr) GetVar(colorBar, REPOBJ);
if (!palette)
{
return ObjTrue;
}
if (max <= palette -> min)
{
DoUniqueTask(DoRangeError);
return ObjFalse;
}
palette -> max = max;
SetVar((ObjPtr) palette, CHANGED, ObjTrue);
ForAllVisWindows(ImInvalid);
ReinitColorBar(colorBar);
ImInvalid(colorBar);
panel = GetVar(box, PARENT);
if (panel)
{
button = GetVar(panel, KEEPBUTTON);
if (button)
{
ActivateButton(button, true);
}
button = GetVar(panel, REVERTBUTTON);
if (button)
{
ActivateButton(button, true);
}
}
return ObjTrue;
}
static ObjPtr EnterNColors(box)
ObjPtr box;
/*Enters the number of colors from box*/
{
ObjPtr value, colorBar, panel, button;
PPtr palette;
int nColors;
real *elements;
int oldNColors;
value = GetValue(box);
if (!value)
{
return ObjFalse;
}
if (!ParseInteger(&nColors, GetString(value)))
{
DoUniqueTask(DoNumberError);
return ObjFalse;
}
colorBar = GetObjectVar("EnterNColors", box, REPOBJ);
if (!colorBar)
{
return ObjFalse;
}
palette = (PPtr) GetVar(colorBar, REPOBJ);
if (!palette)
{
return ObjTrue;
}
if (nColors < 5 || nColors > 2048)
{
DoUniqueTask(DoWrongNColorsError);
return ObjFalse;
}
oldNColors = palette -> nColors;
SetPaletteNColors((ObjPtr) palette, nColors);
SetVar((ObjPtr) palette, CHANGED, ObjTrue);
ForAllVisWindows(ImInvalid);
panel = GetVar(box, PARENT);
if (panel)
{
button = GetVar(panel, KEEPBUTTON);
if (button)
{
ActivateButton(button, true);
}
button = GetVar(panel, REVERTBUTTON);
if (button)
{
ActivateButton(button, true);
}
}
value = GetValue(colorBar);
if (value)
{
real newValue[4];
elements = ELEMENTS(value);
newValue[0] = elements[0];
newValue[1] = elements[1];
newValue[2] = elements[2];
newValue[3] = elements[3];
if (elements[0] > 0.5)
{
int k;
for (k = 1; k <=2; ++k)
{
if (((int) elements[k] + 0.5) >= oldNColors - 1)
{
newValue[k] = nColors - 1;
}
else if (((int) elements[k] + 0.5) > 1)
{
newValue[k] = 2.0 +
(elements[k] - 2.0) * (nColors - 3) / (oldNColors - 3);
if (((int) newValue[k] + 0.5) >= nColors - 1)
{
newValue[k] = nColors - 2.0;
}
if (((int) newValue[k] + 0.5) < 2)
{
newValue[k] = 2.0;
}
}
}
if (newValue[3] <= newValue[2]) newValue[3] += 1.0;
}
value = NewRealArray(1, 3L);
CArray2Array(value, newValue);
InhibitLogging(true);
SetValue(colorBar, value);
InhibitLogging(false);
}
return ObjTrue;
}
ObjPtr ChangeTextColorWheel(wheel)
ObjPtr wheel;
/*Changes text colors according to a color wheel*/
{
ObjPtr repObj, slider;
ObjPtr value;
real hsv[3], rgb[3];
repObj = GetObjectVar("ChangeTextColorWheel", wheel, REPOBJ);
if (!repObj)
{
return ObjFalse;
}
slider = GetObjectVar("ChangeTextColorWheel", wheel, SLIDER);
if (!repObj)
{
return ObjFalse;
}
value = GetValue(wheel);
if (!value)
{
return ObjFalse;
}
Array2CArray(hsv, value);
value = GetValue(slider);
if (!value)
{
return ObjFalse;
}
hsv[2] = GetReal(value);
HSV2RGB(&(rgb[0]), &(rgb[1]), &(rgb[2]), hsv[0], hsv[1], hsv[2]);
value = NewRealArray(1, 3L);
CArray2Array(value, rgb);
SetVar(repObj, COLOR, value);
ImInvalid(repObj);
return ObjTrue;
}
ObjPtr ChangeTextColorSlider(slider)
ObjPtr slider;
/*Changes text color according to a color slider*/
{
ObjPtr repObj, wheel;
ObjPtr value;
real hsv[3], rgb[3];
repObj = GetObjectVar("ChangeTextColorWheel", slider, REPOBJ);
if (!repObj)
{
return ObjFalse;
}
wheel = GetObjectVar("ChangeTextColorWheel", slider, COLORWHEEL);
if (!repObj)
{
return ObjFalse;
}
value = GetValue(wheel);
if (!value)
{
return ObjFalse;
}
Array2CArray(hsv, value);
value = GetValue(slider);
if (!value)
{
return ObjFalse;
}
hsv[2] = GetReal(value);
HSV2RGB(&(rgb[0]), &(rgb[1]), &(rgb[2]), hsv[0], hsv[1], hsv[2]);
value = NewRealArray(1, 3L);
CArray2Array(value, rgb);
SetVar(repObj, COLOR, value);
ImInvalid(repObj);
return ObjTrue;
}
ObjPtr ChangeBackgroundColorWheel(wheel)
ObjPtr wheel;
/*Changes text colors according to a color wheel*/
{
ObjPtr repObj, slider, checkBox;
ObjPtr value;
real hsv[3], rgb[3];
repObj = GetObjectVar("ChangeBackgroundColorWheel", wheel, REPOBJ);
if (!repObj)
{
return ObjFalse;
}
slider = GetObjectVar("ChangeBackgroundColorWheel", wheel, SLIDER);
if (!repObj)
{
return ObjFalse;
}
value = GetValue(wheel);
if (!value)
{
return ObjFalse;
}
Array2CArray(hsv, value);
value = GetValue(slider);
if (!value)
{
return ObjFalse;
}
hsv[2] = GetReal(value);
HSV2RGB(&(rgb[0]), &(rgb[1]), &(rgb[2]), hsv[0], hsv[1], hsv[2]);
value = NewRealArray(1, 3L);
CArray2Array(value, rgb);
SetVar(repObj, BACKGROUND, value);
ImInvalid(repObj);
checkBox = GetVar(wheel, CHECKBOX);
if (checkBox)
{
FuncTyp method;
method = GetMethod(checkBox, CHANGEDVALUE);
SetMethod(checkBox, CHANGEDVALUE, 0);
InhibitLogging(true);
SetValue(checkBox, NewInt(0));
InhibitLogging(false);
SetMethod(checkBox, CHANGEDVALUE, method);
}
return ObjTrue;
}
ObjPtr ChangeBackgroundColorSlider(slider)
ObjPtr slider;
/*Changes background color according to a color slider*/
{
ObjPtr repObj, wheel, checkBox;
ObjPtr value;
real hsv[3], rgb[3];
repObj = GetObjectVar("ChangeBackgroundColorSlider", slider, REPOBJ);
if (!repObj)
{
return ObjFalse;
}
wheel = GetObjectVar("ChangeBackgroundColorSlider", slider, COLORWHEEL);
if (!repObj)
{
return ObjFalse;
}
value = GetValue(wheel);
if (!value)
{
return ObjFalse;
}
Array2CArray(hsv, value);
value = GetValue(slider);
if (!value)
{
return ObjFalse;
}
hsv[2] = GetReal(value);
HSV2RGB(&(rgb[0]), &(rgb[1]), &(rgb[2]), hsv[0], hsv[1], hsv[2]);
value = NewRealArray(1, 3L);
CArray2Array(value, rgb);
SetVar(repObj, BACKGROUND, value);
ImInvalid(repObj);
checkBox = GetVar(slider, CHECKBOX);
if (checkBox)
{
FuncTyp method;
method = GetMethod(checkBox, CHANGEDVALUE);
SetMethod(checkBox, CHANGEDVALUE, 0);
InhibitLogging(true);
SetValue(checkBox, NewInt(0));
InhibitLogging(false);
SetMethod(checkBox, CHANGEDVALUE, method);
}
return ObjTrue;
}
static ObjPtr ChangeColorByPalette(checkBox)
ObjPtr checkBox;
/*Changes an object's COLORBYFIELD according to checkBox*/
{
ObjPtr repObj, value;
repObj = GetObjectVar("ChangeColorByPalette", checkBox, REPOBJ);
if (!repObj)
{
return ObjFalse;
}
value = GetValue(checkBox);
if (!value)
{
return ObjFalse;
}
SetVar(repObj, COLORBYFIELD, value);
ImInvalid(repObj);
return ObjFalse;
}
ObjPtr ChangeNoBackground(checkBox)
ObjPtr checkBox;
/*Changes background color according to a check box*/
{
ObjPtr repObj, wheel, slider;
ObjPtr value;
real hsv[3], rgb[3];
repObj = GetObjectVar("ChangeBackgroundColorSlider", checkBox, REPOBJ);
if (!repObj)
{
return ObjFalse;
}
value = GetValue(checkBox);
if (!value)
{
return ObjFalse;
}
if (GetInt(value))
{
SetVar(repObj, BACKGROUND, NULLOBJ);
ImInvalid(repObj);
return ObjTrue;
}
wheel = GetObjectVar("ChangeBackgroundColorSlider", checkBox, COLORWHEEL);
if (!repObj)
{
return ObjFalse;
}
slider = GetObjectVar("ChangeBackgroundColorSlider", checkBox, SLIDER);
if (!repObj)
{
return ObjFalse;
}
value = GetValue(wheel);
if (!value)
{
return ObjFalse;
}
Array2CArray(hsv, value);
value = GetValue(slider);
if (!value)
{
return ObjFalse;
}
hsv[2] = GetReal(value);
HSV2RGB(&(rgb[0]), &(rgb[1]), &(rgb[2]), hsv[0], hsv[1], hsv[2]);
value = NewRealArray(1, 3L);
CArray2Array(value, rgb);
SetVar(repObj, BACKGROUND, value);
ImInvalid(repObj);
return ObjTrue;
}
static ObjPtr ChangeShowMissing(checkBox)
ObjPtr checkBox;
/*Changes the SHOWMISSING according to a checkbox*/
{
ObjPtr repObj;
repObj = GetObjectVar("ChangeShowMissing", checkBox, REPOBJ);
if (!repObj)
{
return ObjFalse;
}
SetVar(repObj, SHOWMISSING, GetValue(checkBox));
ImInvalid(repObj);
return ObjTrue;
}
static ObjPtr ChangeShowOverUnder(checkBox)
ObjPtr checkBox;
/*Changes the SHOWOVERUNDER according to a checkbox*/
{
ObjPtr repObj;
repObj = GetObjectVar("ChangeShowOverUnder", checkBox, REPOBJ);
if (!repObj)
{
return ObjFalse;
}
SetVar(repObj, SHOWOVERUNDER, GetValue(checkBox));
ImInvalid(repObj);
return ObjTrue;
}
static ObjPtr ChangeShowMinorTics(checkBox)
ObjPtr checkBox;
/*Changes the SHOWMINORTICS according to a checkbox*/
{
ObjPtr repObj;
repObj = GetObjectVar("ChangeShowMinorTics", checkBox, REPOBJ);
if (!repObj)
{
return ObjFalse;
}
SetVar(repObj, SHOWMINORTICS, GetValue(checkBox));
ImInvalid(repObj);
return ObjTrue;
}
static ObjPtr ChangeNumbersOnly(checkBox)
ObjPtr checkBox;
/*Changes the NUMBERSONLY according to a checkbox*/
{
ObjPtr repObj;
repObj = GetObjectVar("ChangeNumbersOnly", checkBox, REPOBJ);
if (!repObj)
{
return ObjFalse;
}
SetVar(repObj, NUMBERSONLY, GetValue(checkBox));
ImInvalid(repObj);
return ObjTrue;
}
static ObjPtr ShowPaletteDisplayControls(display, windowName)
ObjPtr display;
char *windowName;
/*Makes a new control window to control a palette display*/
{
WinInfoPtr controlWindow;
ObjPtr var;
ObjPtr panel;
ObjPtr corral;
ObjPtr contents;
real rgb[3], hsv[3];
WinInfoPtr dialogExists;
Bool hasBackground;
dialogExists = DialogExists((WinInfoPtr) display, NewString("Controls"));
controlWindow = GetDialog((WinInfoPtr) display, NewString("Controls"), windowName,
DSPPALWINWIDTH, DSPPALWINHEIGHT, DSPPALWINWIDTH,
DSPPALWINHEIGHT, WINDBUF + WINRGB + WINFIXEDSIZE);
if (!dialogExists)
{
long info;
ObjPtr value;
ObjPtr checkBox, icon, name, colorBar, titleBox, textBox, button;
ObjPtr colorWheel, slider, radioGroup;
int left, right, bottom, top;
SetVar((ObjPtr) controlWindow, REPOBJ, display);
/*Set help string*/
SetVar((ObjPtr) controlWindow, HELPSTRING, NewString("This window \
shows controls for a color palette legend. For information about any of the controls \
in the window, use Help In Context on the control.\n"));
/*Add in a panel*/
SelWindow(controlWindow);
GetWindowBounds(&left, &right, &bottom, &top);
panel = NewPanel(greyPanelClass, 0, right - left, 0, top - bottom);
if (!panel)
{
return ObjFalse;
}
contents = GetVar((ObjPtr) controlWindow, CONTENTS);
PrefixList(contents, panel);
SetVar(panel, PARENT, (ObjPtr) controlWindow);
contents = GetVar(panel, CONTENTS);
/*Add in the group of controls for text color*/
left = MAJORBORDER;
top = DSPPALWINHEIGHT - MAJORBORDER;
right = left + 4 * MAJORBORDER + COLORWHEELWIDTH + SLIDERWIDTH;
titleBox = NewTitleBox(left, right,
top - TITLEBOXTOP - MAJORBORDER - 2 * MINORBORDER - COLORWHEELWIDTH - CHECKBOXHEIGHT - TEXTBOXHEIGHT - TEXTBOXSEP,
top, "Text and Lines");
SetVar(titleBox, PARENT, panel);
PrefixList(contents, titleBox);
left += MAJORBORDER;
right -= MAJORBORDER;
top -= TITLEBOXTOP + MAJORBORDER;
/*Get the color for priming the controls*/
var = GetVar(display, COLOR);
if (IsRealArray(var) && RANK(var) == 1 && DIMS(var)[0] == 3)
{
Array2CArray(rgb, var);
}
else if (IsInt(var))
{
rgb[0] = uiColors[GetInt(var)][0] / 255.0;
rgb[1] = uiColors[GetInt(var)][1] / 255.0;
rgb[2] = uiColors[GetInt(var)][2] / 255.0;
}
else
{
ReportError("ShowPaletteDisplayControls", "Bad color");
rgb[0] = rgb[1] = rgb[2] = 1.0;
}
RGB2HSV(&(hsv[0]), &(hsv[1]), &(hsv[2]), (rgb[0]), (rgb[1]), (rgb[2]));
/*Make the color wheel*/
colorWheel = NewColorWheel(left, left + COLORWHEELWIDTH,
top - COLORWHEELWIDTH, top, "Text Color");
var = NewRealArray(1, 2L);
CArray2Array(var, hsv);
SetValue(colorWheel, var);
SetVar(colorWheel, PARENT, panel);
SetVar(colorWheel, REPOBJ, display);
PrefixList(contents, colorWheel);
SetMethod(colorWheel, CHANGEDVALUE, ChangeTextColorWheel);
SetVar(colorWheel, HELPSTRING, NewString("This color wheel controls the \
hue and saturation of the color used to draw the text and lines in the palette legend. \
The final color is a combination of this hue and saturation and the value, or brightness, \
given by the Value slider."));
/*Make the text box below*/
textBox = NewTextBox(left, left + COLORWHEELWIDTH,
top - COLORWHEELWIDTH - TEXTBOXSEP - TEXTBOXHEIGHT,
top - COLORWHEELWIDTH - TEXTBOXSEP,
PLAIN, "Text Color Label", "Color");
SetVar(textBox, PARENT, panel);
PrefixList(contents, textBox);
SetTextAlign(textBox, CENTERALIGN);
/*Make the brightness slider*/
slider = NewSlider(right - SLIDERWIDTH, right,
top - COLORWHEELWIDTH, top,
PLAIN, "Text Color Value");
SetVar(slider, PARENT, panel);
PrefixList(contents, slider);
SetSliderRange(slider, 1.0, 0.0, 0.0);
SetSliderValue(slider, hsv[2]);
SetVar(slider, REPOBJ, display);
SetMethod(slider, CHANGEDVALUE, ChangeTextColorSlider);
SetVar(slider, HELPSTRING, NewString("This slider controls the \
value, or brightness, of the color used to draw the text and lines in the palette legend. \
The final color is a combination of this value and the hue and saturation \
given by the Color color wheel."));
/*Make the text box below*/
textBox = NewTextBox(right - SLIDERWIDTH - MINORBORDER, right + MINORBORDER,
top - COLORWHEELWIDTH - TEXTBOXSEP - TEXTBOXHEIGHT,
top - COLORWHEELWIDTH - TEXTBOXSEP,
PLAIN, "Text Value Label", "Value");
SetVar(textBox, PARENT, panel);
PrefixList(contents, textBox);
SetTextAlign(textBox, CENTERALIGN);
/*Cross link the slider and color wheel*/
SetVar(colorWheel, SLIDER, slider);
SetVar(slider, COLORWHEEL, colorWheel);
left -= MINORBORDER;
right += MINORBORDER;
/*Make the check box*/
top -= COLORWHEELWIDTH + TEXTBOXSEP + TEXTBOXHEIGHT + MINORBORDER;
checkBox = NewCheckBox(left, right,
top - CHECKBOXHEIGHT, top,
"Color text by palette", GetPredicate(display, COLORBYFIELD));
SetVar(checkBox, PARENT, panel);
SetVar(checkBox, REPOBJ, display);
PrefixList(contents, checkBox);
SetMethod(checkBox, CHANGEDVALUE, ChangeColorByPalette);
SetVar(colorWheel, HELPSTRING, NewString("This check box controls \
how the numbers in the palette legend are colored. If the box is checked, the \
numbers are colored according to the values they represent. If the box is not \
checked, the numbers are colored with the same color used for the lines in the \
legend."));
/*Make the background controls*/
top = DSPPALWINHEIGHT - MAJORBORDER;
right = DSPPALWINWIDTH - MAJORBORDER;
left = right - (4 * MAJORBORDER + COLORWHEELWIDTH + SLIDERWIDTH);
titleBox = NewTitleBox(left, right,
top - TITLEBOXTOP - MAJORBORDER - 2 * MINORBORDER - COLORWHEELWIDTH - CHECKBOXHEIGHT - TEXTBOXHEIGHT - TEXTBOXSEP,
top, "Background");
SetVar(titleBox, PARENT, panel);
PrefixList(contents, titleBox);
left += MAJORBORDER;
right -= MAJORBORDER;
top -= TITLEBOXTOP + MAJORBORDER;
/*Get the color for priming the controls*/
var = GetVar(display, BACKGROUND);
if (var && IsRealArray(var) && RANK(var) == 1 && DIMS(var)[0] == 3)
{
Array2CArray(rgb, var);
hasBackground = true;
}
else if (var && IsInt(var))
{
rgb[0] = uiColors[GetInt(var)][0] / 255.0;
rgb[1] = uiColors[GetInt(var)][1] / 255.0;
rgb[2] = uiColors[GetInt(var)][2] / 255.0;
hasBackground = true;
}
else
{
rgb[0] = rgb[1] = rgb[2] = 0.5;
hasBackground = false;
}
RGB2HSV(&(hsv[0]), &(hsv[1]), &(hsv[2]), (rgb[0]), (rgb[1]), (rgb[2]));
/*Make the color wheel*/
colorWheel = NewColorWheel(left, left + COLORWHEELWIDTH,
top - COLORWHEELWIDTH, top, "Background Color");
var = NewRealArray(1, 2L);
CArray2Array(var, hsv);
SetValue(colorWheel, var);
SetVar(colorWheel, PARENT, panel);
SetVar(colorWheel, REPOBJ, display);
PrefixList(contents, colorWheel);
SetMethod(colorWheel, CHANGEDVALUE, ChangeBackgroundColorWheel);
SetVar(colorWheel, HELPSTRING, NewString("This color wheel controls the \
hue and saturation of the color used to draw the background of the palette legend. \
The final color is a combination of this hue and saturation and the value, or brightness, \
given by the Value slider."));
/*Make the text box below*/
textBox = NewTextBox(left, left + COLORWHEELWIDTH,
top - COLORWHEELWIDTH - TEXTBOXSEP - TEXTBOXHEIGHT,
top - COLORWHEELWIDTH - TEXTBOXSEP,
PLAIN, "Background Color Label", "Color");
SetVar(textBox, PARENT, panel);
PrefixList(contents, textBox);
SetTextAlign(textBox, CENTERALIGN);
/*Make the brightness slider*/
slider = NewSlider(right - SLIDERWIDTH, right,
top - COLORWHEELWIDTH, top,
PLAIN, "Background Value");
SetVar(slider, PARENT, panel);
PrefixList(contents, slider);
SetSliderRange(slider, 1.0, 0.0, 0.0);
SetSliderValue(slider, hsv[2]);
SetVar(slider, REPOBJ, display);
SetMethod(slider, CHANGEDVALUE, ChangeBackgroundColorSlider);
SetVar(slider, HELPSTRING, NewString("This slider controls the \
value, or brightness, of the color used to draw the background of the palette legend. \
The final color is a combination of this value and the hue and saturation \
given by the Color color wheel."));
/*Make the text box below*/
textBox = NewTextBox(right - SLIDERWIDTH - MINORBORDER, right + MINORBORDER,
top - COLORWHEELWIDTH - TEXTBOXSEP - TEXTBOXHEIGHT,
top - COLORWHEELWIDTH - TEXTBOXSEP,
PLAIN, "Background Value Label", "Value");
SetVar(textBox, PARENT, panel);
PrefixList(contents, textBox);
SetTextAlign(textBox, CENTERALIGN);
/*Cross link the slider and color wheel*/
SetVar(colorWheel, SLIDER, slider);
SetVar(slider, COLORWHEEL, colorWheel);
left -= MINORBORDER;
right += MINORBORDER;
/*Make the check box*/
top -= COLORWHEELWIDTH + TEXTBOXSEP + TEXTBOXHEIGHT + MINORBORDER;
checkBox = NewCheckBox(left, right,
top - CHECKBOXHEIGHT, top,
"No background", hasBackground ? false : true);
SetVar(checkBox, PARENT, panel);
SetVar(checkBox, REPOBJ, display);
SetVar(checkBox, SLIDER, slider);
SetVar(checkBox, COLORWHEEL, colorWheel);
PrefixList(contents, checkBox);
SetMethod(checkBox, CHANGEDVALUE, ChangeNoBackground);
SetVar(checkBox, HELPSTRING, NewString("This checkbox controls whether \
a background is shown. If it is selected, no background is shown, and the \
objects behind can be seen."));
/*Link the checkbox to the slider and color wheel*/
SetVar(colorWheel, CHECKBOX, checkBox);
SetVar(slider, CHECKBOX, checkBox);
top -= CHECKBOXHEIGHT + MINORBORDER + MINORBORDER;
left = MAJORBORDER;
right = DSPPALWINWIDTH - MAJORBORDER;
/*Make checkbox for show missing*/
checkBox = NewCheckBox(left, (left + right) / 2,
top - CHECKBOXHEIGHT, top,
"Show Missing", GetPredicate(display, SHOWMISSING));
SetVar(checkBox, PARENT, panel);
SetVar(checkBox, REPOBJ, display);
PrefixList(contents, checkBox);
SetMethod(checkBox, CHANGEDVALUE, ChangeShowMissing);
SetVar(colorWheel, HELPSTRING, NewString("This check box controls \
whether an entry for Missing data is shown in the palette legend."));
/*Make checkbox for show Over and Under*/
checkBox = NewCheckBox((left + right) / 2, right,
top - CHECKBOXHEIGHT, top,
"Show Over and Under", GetPredicate(display, SHOWOVERUNDER));
SetVar(checkBox, PARENT, panel);
SetVar(checkBox, REPOBJ, display);
PrefixList(contents, checkBox);
SetMethod(checkBox, CHANGEDVALUE, ChangeShowOverUnder);
SetVar(colorWheel, HELPSTRING, NewString("This check box controls \
whether entries for Over and Under data are shown in the palette legend."));
top -= CHECKBOXHEIGHT + MINORBORDER;
/*Make checkbox for show minor tics*/
checkBox = NewCheckBox(left, (left + right) / 2,
top - CHECKBOXHEIGHT, top,
"Show Minor Tics", GetPredicate(display, SHOWMINORTICS));
SetVar(checkBox, PARENT, panel);
SetVar(checkBox, REPOBJ, display);
PrefixList(contents, checkBox);
SetMethod(checkBox, CHANGEDVALUE, ChangeShowMinorTics);
SetVar(colorWheel, HELPSTRING, NewString("This check box controls \
whether minor tic marks are shown in the palette legend in addition to major \
tic marks and numbers."));
/*Make checkbox for numbers only*/
checkBox = NewCheckBox((left + right) / 2, right,
top - CHECKBOXHEIGHT, top,
"Numbers Only", GetPredicate(display, NUMBERSONLY));
SetVar(checkBox, PARENT, panel);
SetVar(checkBox, REPOBJ, display);
PrefixList(contents, checkBox);
SetMethod(checkBox, CHANGEDVALUE, ChangeNumbersOnly);
SetVar(colorWheel, HELPSTRING, NewString("When this check box is down, \
only the numbers are shown in the palette legend. This is useful in conjunction \
with the \"Color text by palette\" check box."));
}
return (ObjPtr) controlWindow;
}
void ColorModelFromMenu(whichColorModel)
int whichColorModel;
/*Sets the color model in the current window from whichColorModel*/
{
ObjPtr colorBar, palette;
if (!selWinInfo)
{
return;
}
#ifndef MENUSFROM0
--whichColorModel;
#endif
if (logging)
{
Log("model ");
Log(colorModelNames[whichColorModel]);
Log("\n");
}
colorBar = GetVar((ObjPtr) selWinInfo, COLORBAR);
if (!colorBar)
{
return;
}
palette = GetPaletteVar("ColorModelFromMenu", colorBar, REPOBJ);
if (!colorBar)
{
return;
}
SetVar(palette, COLORMODEL, NewInt(whichColorModel));
CopyColorsToComponents((PPtr) palette, 0, ((PPtr) palette) -> nColors - 1);
ChangedValue(colorBar);
ImInvalid(colorBar);
/*Set the edit tool to free form*/
ResetColorBarTools(colorBar);
}
#if 0
static ObjPtr ChangeColorModel(radio)
ObjPtr radio;
/*Changes the color model based on the value of a radio group*/
{
ObjPtr colorBar, palette;
ObjPtr value;
colorBar = GetObjectVar("ChangeColorModel", radio, REPOBJ);
if (!colorBar)
{
return ObjFalse;
}
palette = GetVar(colorBar, REPOBJ);
if (!colorBar)
{
return ObjFalse;
}
value = GetValue(radio);
if (!value || !IsInt(value))
{
return ObjFalse;
}
SetVar(palette, COLORMODEL, value);
CopyColorsToComponents((PPtr) palette, 0, ((PPtr) palette) -> nColors - 1);
ChangedValue(colorBar);
ImInvalid(colorBar);
/*Set the edit tool to free form*/
ResetColorBarTools(colorBar);
return ObjTrue;
}
#endif
static ObjPtr ShowPaletteControls(palette, windowName)
ObjPtr palette;
char *windowName;
/*Makes a new control window to control a palette*/
{
WinInfoPtr controlWindow;
ObjPtr var;
ObjPtr panel;
ObjPtr corral;
ObjPtr contents;
WinInfoPtr dialogExists;
int left, right, bottom, top;
GetTemplateBounds(PaletteTemplate, "Panel", &left, &right, &bottom, &top);
dialogExists = DialogExists((WinInfoPtr) palette, NewString("Controls"));
controlWindow = GetDialog((WinInfoPtr) palette, NewString("Controls"), windowName,
right - left, top - bottom, SCRWIDTH, SCRHEIGHT, WINDBUF + WINRGB);
if (!dialogExists)
{
long info;
ObjPtr value;
int k;
ObjPtr checkBox, icon, name, colorBar, titleBox, textBox, button;
ObjPtr colorWheel, slider, fullCompList, compList, radioGroup;
char numBuf[200];
char *s;
/*Add some menu items*/
DefineMenuItem((ObjPtr) controlWindow, FILEMENU, "Save Palette", DoSaveObject);
DefineMenuItem((ObjPtr) controlWindow, COLORMENU, "Save Palette", DoSaveObject);
DefineMenuItem((ObjPtr) controlWindow, COLORMENU, "Keep Changes", DoKeepPalette);
DefineMenuItem((ObjPtr) controlWindow, COLORMENU, "Revert to Original", DoRevertPalette);
for (k = 0; k < NPALETTEFUNCS; ++k)
{
strcpy(numBuf, spfNames[k]);
numBuf[0] = toupper(numBuf[0]);
DefineMenuItem((ObjPtr) controlWindow, EFFECTSMENU, numBuf, SimpleFuncFromMenu);
}
for (k = 0; k < NCOLORMODELS; ++k)
{
strcpy(numBuf, colorModelNames[k]);
numBuf[0] = toupper(numBuf[0]);
DefineMenuItem((ObjPtr) controlWindow, COLORMODELMENU, numBuf, ColorModelFromMenu);
}
SetVar((ObjPtr) controlWindow, REPOBJ, palette);
/*Set help string*/
SetVar((ObjPtr) controlWindow, HELPSTRING, NewString("This window \
shows controls for a color palette. For information about any of the controls \
in the window, use Help In Context on the control.\n"));
/*Add in a panel*/
panel = TemplatePanel(PaletteTemplate, "Panel");
if (!panel)
{
return ObjFalse;
}
contents = GetVar((ObjPtr) controlWindow, CONTENTS);
PrefixList(contents, panel);
SetVar(panel, PARENT, (ObjPtr) controlWindow);
contents = GetVar(panel, CONTENTS);
/*Create a color bar to add in later*/
left = 2 * MAJORBORDER + PCWINLSIDE;
right = PCWINWIDTH - MAJORBORDER;
bottom = MAJORBORDER + PCBARUP;
top = bottom + PCBARHEIGHT;
colorBar = TemplateColorBar(PaletteTemplate, "Palette Colors");
fullCompList = NewList(); /*List of buttons active on full or component*/
compList = NewList(); /*List of buttons active on component*/
SetVar(colorBar, FULLCOMPBUTTONS, fullCompList);
SetVar(colorBar, COMPBUTTONS, compList);
SetVar(colorBar, EDITMODE, NewInt(PT_FREEFORM)); /*Freeform editor*/
SetVar((ObjPtr) controlWindow, COLORBAR, colorBar);
SetVar(colorBar, STICKINESS, NewInt(STICKYLEFT + STICKYRIGHT + STICKYBOTTOM + STICKYTOP));
/*Ramp button*/
button = TemplateButton(PaletteTemplate, "Ramp");
PrefixList(contents, button);
SetVar(button, PARENT, panel);
SetVar(button, REPOBJ, palette);
SetVar(button, COLORBAR, colorBar);
SetMethod(button, CHANGEDVALUE, SimpleFuncButton);
SetVar(button, PALETTEFUNC, NewInt(PF_RAMP));
ActivateButton(button, false);
PrefixList(fullCompList, button);
SetVar(button, HELPSTRING,
NewString("This button interpolates between the selected \
colors to make a smooth color ramp. When a range in the full color bar is \
selected, all components will be interpolated. When a range of a single component \
is selected, just that component will be interpolated.\n"));
SetVar(button, HALTHELP, ObjTrue);
/*Reverse button*/
button = TemplateButton(PaletteTemplate, "Reverse");
PrefixList(contents, button);
SetVar(button, PARENT, panel);
SetVar(button, REPOBJ, palette);
SetVar(button, COLORBAR, colorBar);
SetMethod(button, CHANGEDVALUE, SimpleFuncButton);
SetVar(button, PALETTEFUNC, NewInt(PF_REVERSE));
ActivateButton(button, false);
PrefixList(fullCompList, button);
SetVar(button, HELPSTRING,
NewString("This button reverses the range of selected colors. \
When a range in the full color bar is \
selected, all components will be reversed. When a range of a single component \
is selected, just that component will be reversed.\n"));
SetVar(button, HALTHELP, ObjTrue);
/*Smooth button*/
button = TemplateButton(PaletteTemplate, "Smooth");
PrefixList(contents, button);
SetVar(button, PARENT, panel);
SetVar(button, REPOBJ, palette);
SetVar(button, COLORBAR, colorBar);
SetMethod(button, CHANGEDVALUE, SimpleFuncButton);
SetVar(button, PALETTEFUNC, NewInt(PF_SMOOTH));
ActivateButton(button, false);
PrefixList(fullCompList, button);
SetVar(button, HELPSTRING,
NewString("This button smooths the selected colors. \
This will reduce the abrupt changes which can worsen artifacts such as Mach bands. \
You can smooth a range more by pressing the button repeatedly. \
When a range in the full color bar is \
selected, all components will be smoothed. When a range of a single component \
is selected, just that component will be smoothed.\n"));
SetVar(button, HALTHELP, ObjTrue);
/*Sharpen button*/
button = TemplateButton(PaletteTemplate, "Sharpen");
PrefixList(contents, button);
SetVar(button, PARENT, panel);
SetVar(button, REPOBJ, palette);
SetVar(button, COLORBAR, colorBar);
SetMethod(button, CHANGEDVALUE, SimpleFuncButton);
SetVar(button, PALETTEFUNC, NewInt(PF_SHARPEN));
ActivateButton(button, false);
PrefixList(fullCompList, button);
SetVar(button, HELPSTRING,
NewString("This button sharpens color distinction within the selected colors. \
This may increase artifacts such as Mach bands. Sharpen and Smooth are not \
quite inverse operations, but they have roughly opposite effects. Sharpen will \
amplify noise and variations in the colors, which will become evident after the \
button is pressed three or four times. \
When a range in the full color bar is \
selected, all components will be sharpened. When a range of a single component \
is selected, just that component will be sharpened.\n"));
SetVar(button, HALTHELP, ObjTrue);
/*Put in the min and max text boxes below*/
sprintf(numBuf, "%g", ((PPtr) palette) -> min);
textBox = TemplateTextBox(PaletteTemplate, "Field Min", EDITABLE + WITH_PIT + ONE_LINE, numBuf);
SetVar(textBox, PARENT, panel);
PrefixList(contents, textBox);
SetTextAlign(textBox, RIGHTALIGN);
SetVar(textBox, REPOBJ, colorBar);
SetVar(panel, MINBOX, textBox);
SetVar((ObjPtr) controlWindow, MINBOX, textBox);
SetVar(textBox, HELPSTRING, NewString("This text box shows the maximum \
field value represented by the color table. Any value above this will use the \
overflow color. To change this value, enter the new number and press the Enter \
key."));
SetMethod(textBox, CHANGEDVALUE, EnterMin);
SetVar(textBox, STICKINESS, NewInt(FLOATINGLEFT + FLOATINGRIGHT + FLOATINGBOTTOM));
/*Min legend*/
textBox = TemplateTextBox(PaletteTemplate, "Field Min Legend", 0, "Minimum:");
SetVar(textBox, PARENT, panel);
PrefixList(contents, textBox);
SetTextAlign(textBox, RIGHTALIGN);
SetVar(textBox, STICKINESS, NewInt(FLOATINGLEFT + FLOATINGRIGHT + FLOATINGBOTTOM));
/*Max text box*/
sprintf(numBuf, "%g", ((PPtr) palette) -> max);
textBox = TemplateTextBox(PaletteTemplate, "Field Max", EDITABLE + WITH_PIT + ONE_LINE, numBuf);
SetVar(textBox, PARENT, panel);
PrefixList(contents, textBox);
SetTextAlign(textBox, RIGHTALIGN);
SetVar(textBox, REPOBJ, colorBar);
SetVar(panel, MAXBOX, textBox);
SetVar((ObjPtr) controlWindow, MAXBOX, textBox);
SetVar(textBox, HELPSTRING, NewString("This text box shows the minimum \
field value represented by the color table. Any value below this will use the \
underflow color. To change this value, enter the new number and press the Enter \
key."));
SetMethod(textBox, CHANGEDVALUE, EnterMax);
SetVar(textBox, STICKINESS, NewInt(FLOATINGLEFT + FLOATINGRIGHT + FLOATINGBOTTOM));
/*Max legend*/
textBox = TemplateTextBox(PaletteTemplate, "Field Max Legend", 0, "Maximum:");
SetVar(textBox, PARENT, panel);
PrefixList(contents, textBox);
SetTextAlign(textBox, RIGHTALIGN);
SetVar(textBox, STICKINESS, NewInt(FLOATINGLEFT + FLOATINGRIGHT + FLOATINGBOTTOM));
/*nColors text box*/
sprintf(numBuf, "%d", ((PPtr) palette) -> nColors);
left = MAJORBORDER;
textBox = TemplateTextBox(PaletteTemplate, "N Colors", EDITABLE + WITH_PIT + ONE_LINE, numBuf);
SetVar(textBox, PARENT, panel);
PrefixList(contents, textBox);
SetTextAlign(textBox, RIGHTALIGN);
SetVar(textBox, REPOBJ, colorBar);
SetVar(panel, NCOLORBOX, textBox);
SetVar((ObjPtr) controlWindow, NCOLORBOX, textBox);
SetVar(textBox, HELPSTRING, NewString("This text box shows the number of colors \
in the palette, including the missing data, underflow, and overflow entries. \
To change the number of colors, enter the new number and press the Enter \
key. The palette will be resampled with the new number of colors. When increasing \
the number of colors, it is sometimes useful to do a Smooth operation afterward \
to smooth out the changes."));
SetMethod(textBox, CHANGEDVALUE, EnterNColors);
SetVar(textBox, STICKINESS, NewInt(FLOATINGLEFT + FLOATINGRIGHT + FLOATINGBOTTOM));
/*nColors legend*/
textBox = TemplateTextBox(PaletteTemplate, "NColors Legend", 0, "Colors");
SetVar(textBox, PARENT, panel);
PrefixList(contents, textBox);
SetVar(textBox, STICKINESS, NewInt(FLOATINGLEFT + FLOATINGRIGHT + FLOATINGBOTTOM));
/*Add in the left color control group*/
left = MINORBORDER;
right = left + PCWINLSIDE;
top = PCWINHEIGHT - MINORBORDER;
SetVar(palette, KEPTPALETTE, ClonePalette(palette));
bottom = MINORBORDER + PCBARUP;
top = bottom + COLORWHEELWIDTH + TEXTBOXHEIGHT + TEXTBOXSEP;
/*Color wheel*/
colorWheel = TemplateColorWheel(PaletteTemplate, "Color");
SetVar(colorWheel, PARENT, panel);
PrefixList(contents, colorWheel);
SetVar(colorWheel, REPOBJ, palette);
ActivateColorWheel(colorWheel, false);
SetVar(colorWheel, VALUE, false);
SetVar(colorWheel, HELPSTRING,
NewString("This color wheel controls the hue and saturation of the \
entire range of selected colors. When you use this control, the entire range \
will be set to the new color."));
SetVar(colorWheel, HALTHELP, ObjTrue);
/*Color wheel text box*/
textBox = TemplateTextBox(PaletteTemplate, "HS Text", 0, "Color");
PrefixList(contents, textBox);
SetVar(textBox, PARENT, panel);
SetTextAlign(textBox, CENTERALIGN);
/*Slider*/
slider = TemplateSlider(PaletteTemplate, "Intensity", PLAIN);
PrefixList(contents, slider);
SetVar(slider, PARENT, panel);
SetSliderRange(slider, 1.0, 0.0, 0.0);
SetSliderValue(slider, 1.0);
ActivateSlider(slider, false);
SetVar(slider, HELPSTRING, NewString("This slider controls the intensity of \
the colors selected in the color bar control to the right. When a range of colors is selected, this slider controls the value \
of the colors represented in the Hue/Saturation/Value color model. \
When a range of a single color component is selected, it controls the intensity \
of that component."));
SetVar(slider, HALTHELP, ObjTrue);
/*Slider text box*/
textBox = TemplateTextBox(PaletteTemplate, "Intensity Text", 0, "Intensity");
PrefixList(contents, textBox);
SetVar(textBox, PARENT, panel);
SetTextAlign(textBox, CENTERALIGN);
/*Link slider and color wheel*/
SetVar(slider, COLORWHEEL, colorWheel);
SetVar(colorWheel, SLIDER, slider);
/*Link the color wheels to the color bar*/
SetVar(slider, COLORBAR, colorBar);
SetVar(colorWheel, COLORBAR, colorBar);
/*Waveform tools*/
top = MAJORBORDER + PCBARHEIGHT + PCBARUP;
bottom = top - (TITLEBOXTOP + 2 * MINORBORDER + VWTOOLBORDER + 2 * SMALLICONBUTTONSIZE);
titleBox = TemplateTitleBox(PaletteTemplate, "Edit Component");
PrefixList(contents, titleBox);
SetVar(titleBox, PARENT, panel);
left += MINORBORDER;
right -= MINORBORDER;
bottom += MINORBORDER;
top -= TITLEBOXTOP + MINORBORDER;
/*Icons*/
radioGroup = NewRadioButtonGroup("Waveform Tools");
SetVar(colorBar, TOOLGROUP, radioGroup);
SetVar(radioGroup, HELPSTRING,
NewString("This is a group of tools that allow you to edit the \
currently selected color component. \
To use one of these tools, \
first select a range in any one of the color components by dragging through the range \
and then press the button of the tool \
you want to use."));
SetVar(radioGroup, PARENT, panel);
PrefixList(contents, radioGroup);
SetVar(radioGroup, HALTHELP, ObjTrue);
/*Freeform*/
button = TemplateIconButton(PaletteTemplate, "Free form", ICONFREEFORM, UIYELLOW, BS_PLAIN);
AddRadioButton(radioGroup, button);
ActivateButton(button, false);
SetVar(colorBar, FREEFORMBUTTON, button);
SetVar(button, HELPSTRING, NewString("This button selects the \
free form tool, which allows you to edit the waveform simply by clicking \
and drawing in the magnified readout at the top of the color bar to the right. \
Hold down the Shift key to constrain motion to just the horizontal or \
vertical direction."));
/*Sine*/
button = TemplateIconButton(PaletteTemplate, "Sine", ICONSINE, UIYELLOW, BS_PLAIN);
AddRadioButton(radioGroup, button);
ActivateButton(button, false);
PrefixList(compList, button);
SetVar(button, HELPSTRING, NewString("This button selects the \
sine wave tool, which fills the entire selected range with a sine wave. \
When this tool is selected, a yellow box in the magnified readout lets you \
change the period, phase, and position of the wave."));
/*Triangle*/
button = TemplateIconButton(PaletteTemplate, "Triangle", ICONTRIANGLE, UIYELLOW, BS_PLAIN);
AddRadioButton(radioGroup, button);
ActivateButton(button, false);
PrefixList(compList, button);
SetVar(button, HELPSTRING, NewString("This button selects the \
triangle wave tool, which fills the entire selected range with a triangle wave. \
When this tool is selected, a yellow box in the magnified readout lets you \
change the period, phase, and position of the wave."));
/*Sawtooth*/
button = TemplateIconButton(PaletteTemplate, "Sawtooth", ICONSAWTOOTH, UIYELLOW, BS_PLAIN);
AddRadioButton(radioGroup, button);
ActivateButton(button, false);
PrefixList(compList, button);
SetVar(button, HELPSTRING, NewString("This button selects the \
sawtooth wave tool, which fills the entire selected range with a sawtooth wave. \
When this tool is selected, a yellow box in the magnified readout lets you \
change the period, phase, and position of the wave."));
/*Toothsaw*/
button = TemplateIconButton(PaletteTemplate, "Toothsaw", ICONTOOTHSAW, UIYELLOW, BS_PLAIN);
AddRadioButton(radioGroup, button);
ActivateButton(button, false);
PrefixList(compList, button);
SetVar(button, HELPSTRING, NewString("This button selects the \
reverse sawtooth wave tool, which fills the entire selected range with a reverse sawtooth wave. \
When this tool is selected, a yellow box in the magnified readout lets you \
change the period, phase, and position of the wave."));
/*Square*/
button = TemplateIconButton(PaletteTemplate, "Square", ICONSQUARE, UIYELLOW, BS_PLAIN);
AddRadioButton(radioGroup, button);
ActivateButton(button, false);
PrefixList(compList, button);
SetVar(button, HELPSTRING, NewString("This button selects the \
square wave tool, which fills the entire selected range with a square wave. \
When this tool is selected, a yellow box in the magnified readout lets you \
change the period, phase, and position of the wave."));
SetValue(radioGroup, NewInt(PT_FREEFORM));
SetVar(radioGroup, REPOBJ, colorBar);
SetMethod(radioGroup, CHANGEDVALUE, ChangeColorTool);
#if 0
/*Color model controls*/
left -= MINORBORDER;
right += MINORBORDER;
top = top - 2 * ICONBUTTONSIZE - 3 * MINORBORDER;
bottom = top - TITLEBOXTOP - 2 * MINORBORDER - 2 * CHECKBOXHEIGHT - CHECKBOXSPACING;
titleBox = NewTitleBox(left, right, bottom, top, "Color Model");
PrefixList(contents, titleBox);
SetVar(titleBox, PARENT, panel);
/*Create the radio button group*/
radioGroup = NewRadioButtonGroup("Color Models");
SetVar(radioGroup, PARENT, panel);
SetVar(panel, CMODELRADIO, radioGroup);
SetVar((ObjPtr) controlWindow, CMODELRADIO, radioGroup);
PrefixList(contents, radioGroup);
SetVar(radioGroup, REPOBJ, colorBar);
SetVar(radioGroup, HELPSTRING,
NewString("This group controls which color model the palette editor \
uses. It will affect the information shown in the three color component bars \
in the color bar. SciAn always uses the RGB color model internally and converts \
to the selected color model for editing."));
/*And the individual radio buttons*/
left += MINORBORDER;
right -= MINORBORDER;
top -= TITLEBOXTOP + MINORBORDER;
bottom += MINORBORDER;
button = NewRadioButton(left, left + (right - left) / 2,
top - CHECKBOXHEIGHT, top,
"RGB");
AddRadioButton(radioGroup, button);
SetVar(button, HELPSTRING,
NewString("This button selects the RGB color model. In this model, \
color is composed of red, green, and blue components, which are added together \
to produce the final color."));
button = NewRadioButton(left, left + (right - left) / 2,
bottom, bottom + CHECKBOXHEIGHT,
"YIQ");
AddRadioButton(radioGroup, button);
SetVar(button, HELPSTRING,
NewString("This button selects the YIQ color model. This color \
model is exactly the same model used to encode NTSC composite television \
signals. This color model uses properties of the visual system to optimize \
the amount of information that can be transmitted in the fixed bandwidth of \
the NTSC composite signal.\n\nWARNING: Not all possible YIQ combinations encode \
into valid RGB combinations. This will only be apparent after you have edited the \
color components in the YIQ model, switch to another color model, and switch back."));
button = NewRadioButton(left + (right - left) / 2, right,
top - CHECKBOXHEIGHT, top,
"HSV");
AddRadioButton(radioGroup, button);
SetVar(button, HELPSTRING,
NewString("This button selects the HSV color model. In this model, \
color is composed of hue, saturation, and value. The hue and saturation control \
the shade of the color, and the value controls its intensity. This color model \
is the same color model which is usedused by the color wheels and intensity sliders in SciAn."));
button = NewRadioButton(left + (right - left) / 2, right,
bottom, bottom + CHECKBOXHEIGHT,
"HLS");
AddRadioButton(radioGroup, button);
SetVar(button, HELPSTRING,
NewString("This button selects the HLS color model. In this model, \
color is composed of hue, lightness, and saturation. Hue and saturation control the \
basic shade of the color. Lightness controls how much black or white is mixed in \
with the color."));
var = GetIntVar("ShowPaletteControls", palette, COLORMODEL);
if (var)
{
SetValue(radioGroup, var);
}
SetMethod(radioGroup, CHANGEDVALUE, ChangeColorModel);
#endif
/*Now add in the color bar*/
SetMethod(colorBar, MAKE1HELPSTRING, MakePaletteBarHelp);
SetVar(colorBar, HALTHELP, ObjTrue);
PrefixList(contents, colorBar);
SetVar(colorBar, PARENT, (ObjPtr) panel);
SetVar(colorBar, REPOBJ, palette);
SetVar(colorBar, SLIDER, slider);
SetVar(colorBar, COLORWHEEL, colorWheel);
SetVar(panel, COLORBAR, colorBar);
value = NewRealArray(1, 3L);
((real *) ELEMENTS(value))[0] = 0.0;
((real *) ELEMENTS(value))[1] = 0.0;
((real *) ELEMENTS(value))[2] = 0.0;
SetMethod(colorBar, CHANGEDVALUE, ChangePaletteBar);
SetValue(colorBar, value);
ReinitColorBar(colorBar);
/*Give the color wheels and sliders changedValue routines*/
SetMethod(colorWheel, CHANGEDVALUE, ChangePaletteColorWheel);
SetMethod(slider, CHANGEDVALUE, ChangePaletteSlider);
}
return (ObjPtr) controlWindow;
}
#ifdef PROTO
int ChooseSelectionColor(ObjPtr object)
#else
int ChooseSelectionColor(object)
ObjPtr object;
#endif
/*Chooses a selection color to contrast with object's COLOR and BACKGROUND*/
{
ObjPtr color, background, oneOnly;
float target[3];
float r1, g1, b1, r2, g2, b2, t, b;
real *elements;
color = GetVar(object, COLOR);
background = GetVar(object, BACKGROUND);
if (!color && !background)
{
/*Nothing there, so use UIWHITE*/
return UIWHITE;
}
if (color)
{
if (IsInt(color))
{
int c;
c = GetInt(color);
r1 = ((float) uiColors[c][0]) / 255.0;
g1 = ((float) uiColors[c][1]) / 255.0;
b1 = ((float) uiColors[c][2]) / 255.0;
}
else if (IsRealArray(color) && RANK(color) == 1 && DIMS(color)[0] == 3)
{
elements = ELEMENTS(color);
r1 = elements[0];
g1 = elements[1];
b1 = elements[2];
}
else
{
ReportError("ChooseSelectionColor", "Bad color");
return UIWHITE;
}
}
else
{
r1 = g1 = b1 = 0.0;
}
if (background)
{
if (IsInt(background))
{
int c;
c = GetInt(background);
r2 = ((float) uiColors[c][0]) / 255.0;
g2 = ((float) uiColors[c][1]) / 255.0;
b2 = ((float) uiColors[c][2]) / 255.0;
}
else if (IsRealArray(background) && RANK(background) == 1 && DIMS(background)[0] == 3)
{
elements = ELEMENTS(background);
r2 = elements[0];
g2 = elements[1];
b2 = elements[2];
}
else
{
ReportError("ChooseSelectionColor", "Bad background");
return UIWHITE;
}
}
else
{
r2 = g2 = b2 = 0.0;
}
/*Try to choose a good target color*/
/*First r*/
t = MAX(r1, r2);
b = MIN(r1, r2);
if (t < 0.75) target[0] = 1.0; else target[0] = 0.0;
/*Now g*/
t = MAX(g1, g2);
b = MIN(g1, g2);
if (t < 0.75) target[1] = 1.0; else target[1] = 0.0;
/*Now b*/
t = MAX(b1, b2);
b = MIN(b1, b2);
if (b > 0.25) target[2] = 0.0; else target[2] = 1.0;
return ClosestUIColor(target);
}
void SetObjectColor(col)
ObjPtr col;
/*If col is an int, sets its ui color.
If col is a real 3-array, sets its value
*/
{
#ifdef GRAPHICS
if (overDraw)
{
if (IsInt(col) && GetInt(col) == UIBLACK)
{
color(OVERCLEAR);
}
else
{
color(OVERRED);
}
}
else
{
if (IsInt(col))
{
SetUIColor(GetInt(col));
}
else if (IsRealArray(col) && RANK(col) == 1 && DIMS(col)[0] == 3)
{
float clr[3];
real *elements;
elements = ELEMENTS(col);
if (drawingMode == DRAW_SCREEN)
{
clr[0] = elements[0];
clr[1] = elements[1];
clr[2] = elements[2];
RGBC(clr);
}
else
{
curRed = elements[0];
curGreen = elements[1];
curBlue = elements[2];
}
}
else
{
ReportError("SetObjectColor", "Bad color value");
}
}
#endif
}
#define PALDISPLAYBORDER 20
#define PALDISPLAYTEXTWIDTH 0.6
#define PALDISPLAYVCOLORWIDTH 0.3
#define PALDISPLAYVCOLORHEIGHT 0.08
#define PALDISPLAYHCOLORWIDTH 0.12
#define PALDISPLAYHCOLORHEIGHT 0.6
ObjPtr DrawPaletteDisplay(display)
ObjPtr display;
/*Draws a display*/
{
#ifdef GRAPHICS
int left, right, bottom, top;
int l, r, b, t;
int intLeft, intRight, intBottom, intTop; /*Interior dims*/
double halfSpace, ddiff, majorWidth, minorWidth, curValue;
int pixel;
long temp;
int nTics;
int k, diff, start;
int alignment;
Bool drawOverUnder;
Bool drawMissing;
Bool numbersOnly;
Bool drawMinorTics;
PPtr palette;
ObjPtr var;
char *textFont;
short3 *colors;
int beg;
int nColors;
int textSize;
ObjPtr textColor;
int minMajorStep;
Bool colorByPalette;
int boxWidth, boxHeight, stringWidth, stringHeight;
Get2DIntBounds(display, &left, &right, &bottom, &top);
intLeft = left + PALDISPLAYBORDER;
intRight = right - PALDISPLAYBORDER;
intBottom = bottom + PALDISPLAYBORDER;
intTop = top - PALDISPLAYBORDER;
textColor = GetVar(display, COLOR);
palette = (PPtr) GetPaletteVar("DrawPaletteDisplay", display, REPOBJ);
if (!palette)
{
return ObjFalse;
}
colors = ((PPtr) palette) -> colors;
beg = ((PPtr) palette) -> beg;
nColors = ((PPtr) palette) -> nColors;
/*Get colorByPalette predicate*/
colorByPalette = GetPredicate(display, COLORBYFIELD);
/*Get draw portions predicates*/
drawOverUnder = GetPredicate(display, SHOWOVERUNDER);
drawMissing = GetPredicate(display, SHOWMISSING);
numbersOnly = GetPredicate(display, NUMBERSONLY);
drawMinorTics = GetPredicate(display, SHOWMINORTICS);
/*Set the color palette*/
SetPalette((ObjPtr) palette);
/*Draw the background*/
var = GetVar(display, BACKGROUND);
if (var)
{
SetObjectColor(var);
FillRect(left, right, bottom, top);
}
/*Draw the info on the palette itself*/
SetObjectColor(textColor);
var = GetIntVar("DrawPaletteDisplay", display, MINMAJORSTEP);
if (var)
{
minMajorStep = GetInt(var);
}
else
{
minMajorStep = 30;
}
var = GetStringVar("DrawPaletteDisplay", display, TEXTFONT);
if (var)
{
textFont = GetString(var);
}
else
{
textFont = "Helvetica";
}
var = GetIntVar("DrawPaletteDisplay", display, TEXTSIZE);
if (var)
{
textSize = GetInt(var);
}
else
{
textSize = 18;
}
var = GetIntVar("DrawPaletteDisplay", display, ALIGNMENT);
if (var)
{
alignment = GetInt(var);
}
else
{
alignment = CENTERALIGN;
}
SetupFont(textFont, textSize);
stringWidth = (intRight - intLeft) * PALDISPLAYTEXTWIDTH;
stringHeight = textSize;
if (right - left < top - bottom)
{
/*It's vertical*/
int rangeBot, rangeTop;
int x;
b = intBottom;
t = intTop;
boxWidth = (intRight - intLeft) * PALDISPLAYVCOLORWIDTH;
boxHeight = (intTop - intBottom) * PALDISPLAYVCOLORHEIGHT;
if (drawMissing)
{
/*Draw the missing data box*/
t = b + boxHeight;
if (numbersOnly)
{
l = intLeft;
r = intRight;
}
else
{
r = intRight;
l = r - boxWidth;
FrameRect(l, r, b, t);
FrameRect(l - 1, r + 1, b - 1, t + 1);
if (rgbp)
{
c3s(colors[0]);
}
else
{
color(beg);
}
FillRect(l + 1, r - 1, b + 1, t - 1);
SetObjectColor(textColor);
r = intLeft + stringWidth;
DrawLine(l, (b + t) / 2, r, (b + t) / 2);
DrawLine(l, (b + t) / 2 + 1, r, (b + t) / 2 + 1);
l = intLeft;
}
strcpy(tempStr, "Missing");
switch(alignment)
{
case LEFTALIGN:
x = l;
break;
case CENTERALIGN:
x = (l + r - DSPPALETTESTL) / 2;
break;
case RIGHTALIGN:
x = r - DSPPALETTESTL;
break;
}
if (colorByPalette)
{
SetRealColor(missingData);
}
DrawAString(alignment, x, (b + t - textSize) / 2, tempStr);
if (colorByPalette)
{
SetObjectColor(textColor);
}
b = t + MINORBORDER;
t = intTop;
}
if (drawOverUnder)
{
/*Draw the underflow data box*/
t = b + boxHeight;
if (numbersOnly)
{
l = intLeft;
r = intRight;
}
else
{
r = intRight;
l = r - boxWidth;
FrameRect(l, r, b, t);
FrameRect(l - 1, r + 1, b - 1, t + 1);
if (rgbp)
{
c3s(colors[1]);
}
else
{
color(beg + 1);
}
FillRect(l + 1, r - 1, b + 1, t - 1);
SetObjectColor(textColor);
r = intLeft + stringWidth;
DrawLine(l, (b + t) / 2, r, (b + t) / 2);
DrawLine(l, (b + t) / 2 + 1, r, (b + t) / 2 + 1);
l = intLeft;
}
strcpy(tempStr, "Under");
switch(alignment)
{
case LEFTALIGN:
x = l;
break;
case CENTERALIGN:
x = (l + r - DSPPALETTESTL) / 2;
break;
case RIGHTALIGN:
x = r - DSPPALETTESTL;
break;
}
if (colorByPalette)
{
SetRealColor(MINUSINF);
}
DrawAString(alignment, x, (b + t - textSize) / 2, tempStr);
if (colorByPalette)
{
SetObjectColor(textColor);
}
b = t + MINORBORDER;
/*Draw the overflow data box*/
t = intTop;
if (numbersOnly)
{
l = intLeft;
r = intRight;
}
else
{
r = intRight;
l = r - boxWidth;
FrameRect(l, r, t - boxHeight, t);
FrameRect(l - 1, r + 1, t - boxHeight - 1, t + 1);
if (rgbp)
{
c3s(colors[nColors - 1]);
}
else
{
color(beg + nColors - 1);
}
FillRect(l + 1, r - 1, t - boxHeight + 1, t - 1);
SetObjectColor(textColor);
r = intLeft + stringWidth;
DrawLine(l, t - boxHeight / 2, r, t - boxHeight / 2);
DrawLine(l, t - boxHeight / 2 + 1, r, t - boxHeight / 2 + 1);
l = intLeft;
}
strcpy(tempStr, "Over");
switch(alignment)
{
case LEFTALIGN:
x = l;
break;
case CENTERALIGN:
x = (l + r - DSPPALETTESTL) / 2;
break;
case RIGHTALIGN:
x = r - DSPPALETTESTL;
break;
}
if (colorByPalette)
{
SetRealColor(PLUSINF);
}
DrawAString(alignment, x, t - boxHeight / 2 - textSize / 2, tempStr);
if (colorByPalette)
{
SetObjectColor(textColor);
}
t = intTop - boxHeight - MINORBORDER;
}
/*Draw the main section of the display*/
r = intRight;
l = r - boxWidth;
if (!numbersOnly)
{
FrameRect(l, r, b, t);
FrameRect(l - 1, r + 1, b - 1, t + 1);
}
/*Do the colors in the center*/
rangeBot = b + 1;
rangeTop = t - 1;
diff = t - b - 2;
if (diff > 0)
{
b = start = rangeBot;
if (!numbersOnly)
{
for (k = 2; k < nColors - 1; ++k)
{
t = (k - 1) * diff / (nColors - 3) + start;
if (rgbp)
{
c3s(colors[k]);
}
else
{
color(beg + k);
}
FillRect(l + 1, r - 1, b, t);
b = t + 1;
}
}
SetObjectColor(textColor);
r = l - 1;
l = intLeft + stringWidth;
/*Draw all the tics in the middle*/
halfSpace = (palette -> max - palette -> min) / (palette -> nColors - 4) * 0.5;
ddiff = palette -> max - palette -> min;
CalcGoodSteps(ddiff,
rangeTop - rangeBot,
minMajorStep,
&majorWidth, &nTics);
minorWidth = majorWidth / nTics;
/*Minor and major tics first*/
temp = palette -> min / majorWidth;
curValue = temp * majorWidth;
while (curValue > palette -> min)
{
curValue -= majorWidth;
}
k = 0;
while (curValue < palette -> min)
{
++k;
if (k >= nTics) k = 0;
curValue += minorWidth;
}
/*Now actually draw them*/
if (ABS(curValue) < ddiff * 1.0E-6) curValue = 0.0;
while (curValue <= palette -> max + ddiff * 1.0E-6)
{
pixel = rangeBot + (curValue - palette -> min) * (rangeTop - rangeBot) / (ddiff);
if (k == 0)
{
/*Major tic*/
if (numbersOnly)
{
sprintf(tempStr, "%lg", curValue);
switch(alignment)
{
case LEFTALIGN:
x = intLeft;
break;
case CENTERALIGN:
x = (intLeft + intRight - DSPPALETTESTL - StrWidth(tempStr)) / 2;
break;
case RIGHTALIGN:
x = intRight - DSPPALETTESTL - StrWidth(tempStr);
break;
}
}
else
{
DrawLine(l, pixel, r, pixel);
DrawLine(l, pixel + 1, r, pixel + 1);
sprintf(tempStr, "%lg", curValue);
switch(alignment)
{
case LEFTALIGN:
x = intLeft;
break;
case CENTERALIGN:
x = (intLeft + l - DSPPALETTESTL) / 2;
break;
case RIGHTALIGN:
x = l - DSPPALETTESTL;
break;
}
}
if (colorByPalette)
{
SetRealColor(curValue);
}
DrawAString(alignment, x, pixel - textSize / 2, tempStr);
if (colorByPalette)
{
SetObjectColor(textColor);
}
}
else if ((!numbersOnly) && drawMinorTics)
{
/*Minor tic*/
DrawLine((l + r) / 2, pixel, r, pixel);
DrawLine((l + r) / 2, pixel + 1, r, pixel + 1);
}
curValue += minorWidth;
if (ABS(curValue) < ddiff * 1.0E-6) curValue = 0.0;
++k;
if (k >= nTics) k = 0;
}
}
}
else
{
/*It's horizontal*/
int rangeLeft, rangeRight;
int x;
minMajorStep *= 3;
l = intLeft;
r = intRight;
boxWidth = (intRight - intLeft) * PALDISPLAYHCOLORWIDTH;
boxHeight = (intTop - intBottom) * PALDISPLAYHCOLORHEIGHT;
if (drawMissing)
{
/*Draw the missing data box*/
r = l + boxWidth;
if (numbersOnly)
{
b = intBottom;
t = intTop;
}
else
{
t = intTop;
b = t - boxHeight;
FrameRect(l, r, b, t);
FrameRect(l - 1, r + 1, b - 1, t + 1);
if (rgbp)
{
c3s(colors[0]);
}
else
{
color(beg);
}
FillRect(l + 1, r - 1, b + 1, t - 1);
SetObjectColor(textColor);
b = intBottom + stringHeight;
DrawLine((l + r) / 2, b, (l + r) / 2, t - boxHeight);
DrawLine((l + r) / 2 + 1, b, (l + r) / 2 + 1, t - boxHeight);
b = intBottom;
}
strcpy(tempStr, "Missing");
switch(alignment)
{
case LEFTALIGN:
x = (l + r) / 2;
break;
case CENTERALIGN:
x = (l + r) / 2;
break;
case RIGHTALIGN:
x = (l + r) / 2;
break;
}
if (colorByPalette)
{
SetRealColor(missingData);
}
DrawAString(alignment, x, b, tempStr);
if (colorByPalette)
{
SetObjectColor(textColor);
}
l = r + MINORBORDER;
r = intRight;
}
if (drawOverUnder)
{
/*Draw the underflow data box*/
r = l + boxWidth;
if (numbersOnly)
{
b = intBottom;
t = intTop;
}
else
{
t = intTop;
b = t - boxHeight;
FrameRect(l, r, b, t);
FrameRect(l - 1, r + 1, b - 1, t + 1);
if (rgbp)
{
c3s(colors[1]);
}
else
{
color(beg + 1);
}
FillRect(l + 1, r - 1, b + 1, t - 1);
SetObjectColor(textColor);
b = intBottom + stringHeight;
DrawLine((l + r) / 2, b, (l + r) / 2, t - boxHeight);
DrawLine((l + r) / 2 + 1, b, (l + r) / 2 + 1, t - boxHeight);
b = intBottom;
}
strcpy(tempStr, "Under");
switch(alignment)
{
case LEFTALIGN:
x = (l + r) / 2;
break;
case CENTERALIGN:
x = (l + r) / 2;
break;
case RIGHTALIGN:
x = (l + r) / 2;
break;
}
if (colorByPalette)
{
SetRealColor(MINUSINF);
}
DrawAString(alignment, x, b, tempStr);
if (colorByPalette)
{
SetObjectColor(textColor);
}
l = r + MINORBORDER;
r = intRight;
/*Draw the overflow data box*/
if (numbersOnly)
{
b = intBottom;
t = intTop;
}
else
{
t = intTop;
b = t - boxHeight;
FrameRect(r - boxWidth, r, b, t);
FrameRect(r - boxWidth - 1, r + 1, b - 1, t + 1);
if (rgbp)
{
c3s(colors[nColors - 1]);
}
else
{
color(beg + nColors - 1);
}
FillRect(r - boxWidth + 1, r - 1, b + 1, t - 1);
SetObjectColor(textColor);
b = intBottom + stringHeight;
DrawLine((r - boxWidth + r) / 2, b, (r - boxWidth + r) / 2, t - boxHeight);
DrawLine((r - boxWidth + r) / 2 + 1, b, (r - boxWidth + r) / 2 + 1, t - boxHeight);
b = intBottom;
}
strcpy(tempStr, "Over");
switch(alignment)
{
case LEFTALIGN:
x = (r - boxWidth + r) / 2;
break;
case CENTERALIGN:
x = (r - boxWidth + r) / 2;
break;
case RIGHTALIGN:
x = (r - boxWidth + r) / 2;
break;
}
if (colorByPalette)
{
SetRealColor(PLUSINF);
}
DrawAString(alignment, x, b, tempStr);
if (colorByPalette)
{
SetObjectColor(textColor);
}
r = intRight - boxWidth - MINORBORDER;
}
/*Draw the main section of the display*/
t = intTop;
b = t - boxHeight;
if (!numbersOnly)
{
FrameRect(l, r, b, t);
FrameRect(l - 1, r + 1, b - 1, t + 1);
}
/*Do the colors in the center*/
rangeLeft = l + 1;
rangeRight = r - 1;
diff = r - l - 2;
if (diff > 0)
{
l = start = rangeLeft;
if (!numbersOnly)
{
for (k = 2; k < nColors - 1; ++k)
{
r = (k - 1) * diff / (nColors - 3) + start;
if (rgbp)
{
c3s(colors[k]);
}
else
{
color(beg + k);
}
FillRect(l, r, b + 1, t - 1);
l = r + 1;
}
}
SetObjectColor(textColor);
t = b - 1;
b = intBottom + stringHeight + 2;
/*Draw all the tics in the middle*/
halfSpace = (palette -> max - palette -> min) / (palette -> nColors - 4) * 0.5;
ddiff = palette -> max - palette -> min;
CalcGoodSteps(ddiff,
rangeRight - rangeLeft,
minMajorStep,
&majorWidth, &nTics);
minorWidth = majorWidth / nTics;
/*Minor and major tics first*/
temp = palette -> min / majorWidth;
curValue = temp * majorWidth;
while (curValue > palette -> min)
{
curValue -= majorWidth;
}
k = 0;
while (curValue < palette -> min)
{
++k;
if (k >= nTics) k = 0;
curValue += minorWidth;
}
/*Now actually draw them*/
if (ABS(curValue) < ddiff * 1.0E-6) curValue = 0.0;
while (curValue <= palette -> max + ddiff * 1.0E-6)
{
pixel = rangeLeft + (curValue - palette -> min) * (rangeRight - rangeLeft) / (ddiff);
if (k == 0)
{
/*Major tic*/
if (numbersOnly)
{
sprintf(tempStr, "%lg", curValue);
}
else
{
DrawLine(pixel, b, pixel, t);
DrawLine(pixel + 1, b, pixel + 1, t);
sprintf(tempStr, "%lg", curValue);
}
if (colorByPalette)
{
SetRealColor(curValue);
}
DrawAString(alignment, pixel, intBottom, tempStr);
if (colorByPalette)
{
SetObjectColor(textColor);
}
}
else if ((!numbersOnly) && drawMinorTics)
{
/*Minor tic*/
DrawLine(pixel, (t + b) / 2, pixel, t);
DrawLine(pixel + 1, (t + b) / 2, pixel + 1, t);
}
curValue += minorWidth;
if (ABS(curValue) < ddiff * 1.0E-6) curValue = 0.0;
++k;
if (k >= nTics) k = 0;
}
}
}
if (IsSelected(display))
{
int horCent = (left + right)/2;
int vertCent = (bottom + top)/2;
/* Draw incredibly fancy frame for moving and resizing palette display */
if (1 || right - left < top - bottom)
{
#if 0
/*Draw bits for vertical box*/
if (!numbersOnly)
{
/*First the string end*/
DrawUILine(intLeft + stringWidth, bottom + INSET,
intLeft + stringWidth, top - INSET, UIBLACK);
DrawUILine(intLeft + stringWidth - 1, bottom + INSET,
intLeft + stringWidth - 1, top - INSET, UIBLACK);
DrawUILine(intLeft + stringWidth + 1, bottom + INSET,
intLeft + stringWidth + 1, top - INSET, UIBLACK);
DrawUILine(intLeft + stringWidth - 2, bottom + INSET,
intLeft + stringWidth - 2, top - INSET, UIWHITE);
DrawUILine(intLeft + stringWidth + 2, bottom + INSET,
intLeft + stringWidth + 2, top - INSET, UIWHITE);
DrawUILine(intLeft + stringWidth - 3, bottom + INSET,
intLeft + stringWidth - 3, top - INSET, UIWHITE);
DrawUILine(intLeft + stringWidth + 3, bottom + INSET,
intLeft + stringWidth + 3, top - INSET, UIWHITE);
/*Now the box end*/
DrawUILine(intRight - boxWidth, bottom + INSET,
intRight - boxWidth, top - INSET, UIBLACK);
DrawUILine(intRight - boxWidth - 1, bottom + INSET,
intRight - boxWidth - 1, top - INSET, UIBLACK);
DrawUILine(intRight - boxWidth + 1, bottom + INSET,
intRight - boxWidth + 1, top - INSET, UIBLACK);
DrawUILine(intRight - boxWidth - 2, bottom + INSET,
intRight - boxWidth - 2, top - INSET, UIWHITE);
DrawUILine(intRight - boxWidth + 2, bottom + INSET,
intRight - boxWidth + 2, top - INSET, UIWHITE);
DrawUILine(intRight - boxWidth - 3, bottom + INSET,
intRight - boxWidth - 3, top - INSET, UIWHITE);
DrawUILine(intRight - boxWidth + 3, bottom + INSET,
intRight - boxWidth + 3, top - INSET, UIWHITE);
}
#endif
}
FrameUIWideRect(left+INSET, right-INSET,
bottom+INSET, top-INSET,
OUTSIDEFRAMEWEIGHT, OUTSIDEFRAMECOLOR);
FrameUIWideRect(left+INSET+OUTSIDEFRAMEWEIGHT,
right-INSET-OUTSIDEFRAMEWEIGHT,
bottom+INSET+OUTSIDEFRAMEWEIGHT,
top-INSET-OUTSIDEFRAMEWEIGHT,
INSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
FrameUIWideRect(left+INSET+OUTSIDEFRAMEWEIGHT+INSIDEFRAMEWEIGHT,
right-INSET-OUTSIDEFRAMEWEIGHT-INSIDEFRAMEWEIGHT,
bottom+INSET+OUTSIDEFRAMEWEIGHT+INSIDEFRAMEWEIGHT,
top-INSET-OUTSIDEFRAMEWEIGHT-INSIDEFRAMEWEIGHT,
OUTSIDEFRAMEWEIGHT, OUTSIDEFRAMECOLOR);
/* Now draw the handles */
/* center of sides */
FillUIRect(left, left+HANDLESIZE,
vertCent-HANDLESIZE/2, vertCent+HANDLESIZE/2, OUTSIDEFRAMECOLOR);
FillUIRect(left+OUTSIDEFRAMEWEIGHT,
left+HANDLESIZE-OUTSIDEFRAMEWEIGHT,
vertCent-HANDLESIZE/2+OUTSIDEFRAMEWEIGHT,
vertCent+HANDLESIZE/2-OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
FillUIRect(right-HANDLESIZE, right,
vertCent-HANDLESIZE/2, vertCent+HANDLESIZE/2, OUTSIDEFRAMECOLOR);
FillUIRect(right-HANDLESIZE+OUTSIDEFRAMEWEIGHT,
right-OUTSIDEFRAMEWEIGHT,
vertCent-HANDLESIZE/2+OUTSIDEFRAMEWEIGHT,
vertCent+HANDLESIZE/2-OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
/* top edge */
FillUIRect(horCent-HANDLESIZE/2, horCent+HANDLESIZE/2,
top-HANDLESIZE, top, OUTSIDEFRAMECOLOR);
FillUIRect(horCent-HANDLESIZE/2+OUTSIDEFRAMEWEIGHT,
horCent+HANDLESIZE/2-OUTSIDEFRAMEWEIGHT,
top-HANDLESIZE+OUTSIDEFRAMEWEIGHT,
top-OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
FillUIRect(left, left+HANDLESIZE,
top-HANDLESIZE, top, OUTSIDEFRAMECOLOR);
FillUIRect(left+OUTSIDEFRAMEWEIGHT,
left+HANDLESIZE-OUTSIDEFRAMEWEIGHT,
top-HANDLESIZE+OUTSIDEFRAMEWEIGHT,
top-OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
FillUIRect(right-HANDLESIZE, right,
top-HANDLESIZE, top, OUTSIDEFRAMECOLOR);
FillUIRect(right-HANDLESIZE+OUTSIDEFRAMEWEIGHT,
right-OUTSIDEFRAMEWEIGHT,
top-HANDLESIZE+OUTSIDEFRAMEWEIGHT,
top-OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
/* bottom edge */
FillUIRect(horCent-HANDLESIZE/2, horCent+HANDLESIZE/2,
bottom, bottom+HANDLESIZE, OUTSIDEFRAMECOLOR);
FillUIRect(horCent-HANDLESIZE/2+OUTSIDEFRAMEWEIGHT,
horCent+HANDLESIZE/2-OUTSIDEFRAMEWEIGHT,
bottom+OUTSIDEFRAMEWEIGHT,
bottom+HANDLESIZE-OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
FillUIRect(left, left+HANDLESIZE,
bottom, bottom+HANDLESIZE, OUTSIDEFRAMECOLOR);
FillUIRect(left+OUTSIDEFRAMEWEIGHT,
left+HANDLESIZE-OUTSIDEFRAMEWEIGHT,
bottom+OUTSIDEFRAMEWEIGHT,
bottom+HANDLESIZE-OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
FillUIRect(right-HANDLESIZE, right,
bottom, bottom+HANDLESIZE, OUTSIDEFRAMECOLOR);
FillUIRect(right-HANDLESIZE+OUTSIDEFRAMEWEIGHT,
right-OUTSIDEFRAMEWEIGHT,
bottom+OUTSIDEFRAMEWEIGHT,
bottom+HANDLESIZE-OUTSIDEFRAMEWEIGHT, INSIDEFRAMECOLOR);
}
#endif
return ObjTrue;
}
ObjPtr SelectPaletteDisplay(object, selectp)
ObjPtr object;
Bool selectp;
/*Selects an icon*/
{
if (selectp)
{
MakeMeCurrent(object);
}
ImInvalid(object);
return ObjTrue;
}
#define PDPICKSLOP 10
static ObjPtr PressPaletteDisplay(display, mouseX, mouseY, flags)
ObjPtr display;
int mouseX, mouseY;
long flags;
{
#ifdef INTERACTIVE
int left, right, bottom, top, hCent, vCent;
Bool ml, mr, mb, mt;
int mX, mY;
ObjPtr var, palette;
Get2DIntBounds(display, &left, &right, &bottom, &top);
/* return if mouse outside text box */
if (mouseX < left || mouseX > right || mouseY < bottom
|| mouseY > top) return ObjFalse;
if (TOOL(flags) == T_HELP) /* help mode? */
{
ContextHelp(display);
return ObjTrue;
}
Select(display, true); /* make text box current for editing or adjusting */
DrawMe(display);
hCent = (left + right)/2;
vCent = (bottom + top)/2;
ml = mr = mb = mt = false;
if (mouseX < left + HANDLESIZE) /* on left side */
{
if (mouseY > top - HANDLESIZE) /* top-left handle */
mt = ml = true;
else if (mouseY < bottom + HANDLESIZE) /* bottom-left handle */
mb = ml = true;
else if (mouseY > vCent - HANDLESIZE/2 && mouseY < vCent + HANDLESIZE/2)
ml = true; /* bottom middle handle */
else ml = mr = mb = mt = true; /* in frame */
}
else if (mouseX > right - HANDLESIZE) /* on right side */
{
if (mouseY > top - HANDLESIZE) /* top-right handle */
mt = mr = true;
else if (mouseY < bottom + HANDLESIZE) /* bottom-right handle */
mb = mr = true;
else if (mouseY > vCent - HANDLESIZE/2 && mouseY < vCent + HANDLESIZE/2)
mr = true;
else ml = mr = mb = mt = true; /* in frame */
}
else if (mouseY < bottom + HANDLESIZE) /* on bottom */
{
/* already handled (heh heh) corners */
if (mouseX > hCent - HANDLESIZE/2 && mouseX < hCent + HANDLESIZE/2)
mb = true; /* bottom middle handle */
else ml = mr = mb = mt = true; /* in frame */
}
else if (mouseY > top - HANDLESIZE) /* on top */
{
/* already handled (heh heh) corners */
if (mouseX > hCent - HANDLESIZE/2 && mouseX < hCent + HANDLESIZE/2)
mt = true; /* middle top handle */
else ml = mr = mb = mt = true; /* in frame */
}
if (mr || ml || mb || mt) /* drag the incredibly fancy frame around */
{
/* I am greatly indebted to my friend and colleague, Eric Pepke,
for the following code. Any errors or obfuscations are his. */
/*Oh yeah? Well, I stole it back! So now the bugs are yours!*/
int initX = mouseX, initY = mouseY;
int newLeft, newRight, newBottom, newTop;
int oldNewLeft, oldNewRight, oldNewBottom, oldNewTop;
newLeft = oldNewLeft = left;
newRight = oldNewRight = right;
newBottom = oldNewBottom = bottom;
newTop = oldNewTop = top;
while (Mouse(&mX, &mY))
{
if (ml) newLeft = left + mX - initX;
if (mr) newRight = right + mX - initX;
if (mb) newBottom = bottom + mY - initY;
if (mt) newTop = top + mY - initY;
if (flags & F_SHIFTDOWN)
{
/*Grid drag*/
if (ml && mr && mb && mt)
{
/*Special case--whole object gridded
Only grid top left*/
int width, height;
width = newRight - newLeft;
height = newTop - newBottom;
newLeft = GRIDX(newLeft);
newRight = newLeft + width;
newTop = top - (GRIDY(top - newTop));
newBottom = newTop - height;
}
else
{
/*Normal case*/
if (ml) newLeft = GRIDX(newLeft);
if (mr) newRight = right - GRIDX(right - newRight);
if (mb) newBottom = GRIDY(newBottom);
if (mt) newTop = top - GRIDY(top - newTop);
}
}
if (ml && newLeft + 3 * HANDLESIZE > newRight)
newLeft = newRight - 3 * HANDLESIZE;
if (mr && newLeft + 3 * HANDLESIZE > newRight)
newRight = newLeft + 3 * HANDLESIZE;
if (mb && newBottom + 3 * HANDLESIZE > newTop)
newBottom = newTop - 3 * HANDLESIZE;
if (mt && newBottom + 3 * HANDLESIZE > newTop)
newTop = newBottom + 3 * HANDLESIZE;
if ((newLeft != oldNewLeft ||
newRight != oldNewRight ||
newBottom != oldNewBottom ||
newTop != oldNewTop) &&
newLeft < newRight &&
newBottom < newTop)
{
Set2DIntBounds(display, newLeft, newRight, newBottom, newTop);
oldNewLeft = newLeft;
oldNewRight = newRight;
oldNewBottom = newBottom;
oldNewTop = newTop;
DrawMe(display);
}
}
if (logging)
{
char cmd[256];
MakeObjectName(tempStr, display);
sprintf(cmd, "set bounds %s [%d %d %d %d]\n",
tempStr, newLeft, newRight,
newBottom, newTop);
Log(cmd);
}
}
return ObjTrue;
#else
return ObjFalse;
#endif
}
ObjPtr NewPaletteDisplay(left, right, bottom, top, name, palette)
int left, right, bottom, top;
char *name;
ObjPtr palette;
/*Makes a new palette display*/
{
ObjPtr retVal;
retVal = NewObject(paletteDisplayClass, 0);
if (!retVal)
{
return NULLOBJ;
}
Set2DIntBounds(retVal, left, right, bottom, top);
SetVar(retVal, NAME, NewString(name));
SetVar(retVal, REPOBJ, palette);
return retVal;
}
ObjPtr CompleteSavePalette(palette, whichButton)
ObjPtr palette;
int whichButton;
/*Completes a "save palette" operation*/
{
SaveObjectControls(palette, GetVar(palette, DIRECTORY));
}
ObjPtr SavePalette(palette)
ObjPtr palette;
/*Asks for a palette to be saved*/
{
ObjPtr name, directory;
char *s, nameStr[401];
name = GetStringVar("SavePalette", palette, NAME);
if (!name)
{
return ObjFalse;
}
strcpy(nameStr, GetString(name));
s = nameStr;
while (*s) ++s;
while (*s != ' ') --s;
*s = 0;
directory = GetVar(palette, DIRECTORY);
if (directory)
{
sprintf(tempStr, "Save this palette for datasets named %s in directory %s?",
nameStr, GetString(directory));
}
else
{
sprintf(tempStr, "Save this palette for datasets named %s in the current directory?",
nameStr);
}
AlertUser(UICAUTIONALERT, (WinInfoPtr) palette, tempStr, CompleteSavePalette, 2, "Save", "Cancel");
return ObjTrue;
}
ObjPtr SavePaletteControls(palette)
ObjPtr palette;
/*Saves a palette by logging all palette controls*/
{
int k;
sprintf(tempStr, "set value Field\\ Min \"%g\"\n", MINUSINF);
Log(tempStr);
sprintf(tempStr, "set value Field\\ Max \"%g\"\n", ((PPtr) palette) -> max);
Log(tempStr);
sprintf(tempStr, "set value Field\\ Min \"%g\"\n", ((PPtr) palette) -> min);
Log(tempStr);
sprintf(tempStr, "set value N\\ Colors \"%d\"\n", ((PPtr) palette) -> nColors);
Log(tempStr);
for (k = 0; k < ((PPtr) palette) -> nColors; ++k)
{
sprintf(tempStr, "set color Palette\\ Colors %d %d %d %d\n",
k, ((PPtr) palette) -> colors[k][0], ((PPtr) palette) -> colors[k][1], ((PPtr) palette) -> colors[k][2]);
Log(tempStr);
}
}
void InitColors()
/*Initialize the color system*/
{
int k;
int colorBeg, colorEnd;
ObjPtr var;
iconColorPalette = NewIcon(0, 0, ICONCTABLE, "Color Palette");
AddToReferenceList(iconColorPalette);
/*Make a color palette class*/
paletteClass = NewObject(NULLOBJ, sizeof(Palette) - sizeof(Thing));
AddToReferenceList(paletteClass);
SETOBJTYPE(paletteClass -> flags, PALETTE);
((PPtr) paletteClass) -> colors = 0;
((PPtr) paletteClass) -> components = 0;
((PPtr) paletteClass) -> beg = 0;
((PPtr) paletteClass) -> nColors = 0;
SetVar(paletteClass, DEFAULTICON, iconColorPalette);
SetVar(paletteClass, COLORMODEL, NewInt(CM_RGB));
SetVar(paletteClass, DOUBLECLICK, NewString(OF_SHOW_CONTROLS));
SetMethod(paletteClass, NAME, MakePaletteName);
SetMethod(paletteClass, CLONE, ClonePalette);
SetMethod(paletteClass, CLEANUP, CleanupPalette);
SetMethod(paletteClass, NEWCTLWINDOW, ShowPaletteControls);
SetMethod(paletteClass, SHOWCONTROLS, NewControlWindow);
SetVar(paletteClass, EXTENSION, NewString("pal"));
SetMethod(paletteClass, SAVECPANEL, SavePalette);
SetMethod(paletteClass, SAVEALLCONTROLS, SavePaletteControls);
SetMethod(paletteClass, LOCALCOPY, MakeLocalCopy);
#ifdef GRAPHICS
/*If there is a cmap mode, figure out the number of colors*/
if (hasCmap)
{
char *nColorsString;
char *colorBegString;
colorEnd = 1;
for (k = 0; k < cmapBitPlanes; ++k)
{
colorEnd *= 2;
}
/*Trim off the top 512 if it's too big for the GTX version*/
if (colorEnd >= 4096)
{
colorEnd -= 512;
}
/*Determine beginning based on end*/
if (colorEnd <= 512)
{
colorBeg = COLORBEG8BITS;
}
else
{
colorBeg = COLORBEGMOREBITS;
}
if (colorBegString = getenv("SCIAN_COLOR_BEG"))
{
int temp;
if (1 == sscanf(colorBegString, "%d", &temp))
{
colorBeg = temp;
if (showConfig)
fprintf(stderr, "Color beginning overridden to %d\n", temp);
}
else
{
fprintf(stderr, "Bad color beginning: %s\n", colorBegString);
}
}
if (nColorsString = getenv("SCIAN_N_COLORS"))
{
int nColors;
if (1 == sscanf(nColorsString, "%d", &nColors))
{
colorEnd = colorBeg + nColors;
if (showConfig)
printf("Number of colors overridden to be %d\n", nColors);
}
else
{
fprintf(stderr, "Bad value for environment variable SCIAN_NCOLORS: %s\n", nColorsString);
}
}
if (showConfig)
{
printf("Visualization colors from %d to %d\n", colorBeg, colorEnd);
}
curUIColorIndex = colorBeg;
nScavengeColors = colorBeg;
}
if (hasCmap && scavengeColors)
{
Colorindex i;
nScavengeColors = colorBeg;
colorsToScavenge = (short3 *) malloc(nScavengeColors * sizeof(short3));
if (!colorsToScavenge)
{
nScavengeColors = 0;
}
/*Load up the scavenged colors*/
for (i = 0; i < nScavengeColors; ++i)
{
getmcolor(i,
&(colorsToScavenge[i][0]),
&(colorsToScavenge[i][1]),
&(colorsToScavenge[i][2]));
}
}
else
{
nScavengeColors = 0;
colorsToScavenge = 0;
}
/*Initialize user interface colors*/
MakeUIColor(UIBLACK, 0, 0, 0);
MakeUIColor(UIGRAY12, 30, 30, 30);
MakeUIColor(UIGRAY25, 61, 61, 61);
MakeUIColor(UIGRAY37, 95, 95, 95);
MakeUIColor(UIGRAY50, 128, 128, 128);
MakeUIColor(UIGRAY62, 163, 163, 163);
MakeUIColor(UIGRAY75, 193, 193, 193);
MakeUIColor(UIGRAY87, 224, 224, 224);
MakeUIColor(UIWHITE, 255, 255, 255);
MakeUIColor(UIRED, 225, 0, 0);
MakeUIColor(UIGREEN, 0, 225, 0);
MakeUIColor(UIBLUE, 0, 0, 225);
MakeUIColor(UIMAGENTA, 225, 0, 225);
MakeUIColor(UIYELLOW, 245, 245, 0);
MakeUIColor(UICYAN, 0, 225, 225);
MakeUIColor(UIORANGE, 255, 88, 0);
MakeUIColor(UIPURPLE, 100, 0, 225);
MakeUIColor(UIGOLD, 247, 188, 0);
MakeUIColor(UIPRED, 182, 128, 128);
MakeUIColor(UIPGREEN, 128, 171, 128);
MakeUIColor(UIPBLUE, 128, 145, 171);
MakeUIColor(UIPMAGENTA, 171, 128, 171);
MakeUIColor(UIPYELLOW, 171, 171, 128);
MakeUIColor(UIPCYAN, 128, 171, 171);
if (colorsToScavenge)
{
free(colorsToScavenge);
colorsToScavenge = 0;
}
/*Now colorBeg set to be above NUICOLORS*/
if (hasCmap)
{
colorBeg = curUIColorIndex;
/*Make first color range*/
colorRanges = new(ColorRange);
colorRanges -> beg = colorBeg;
colorRanges -> end = colorEnd;
colorRanges -> next = (ColorRange *) 0;
}
else
{
colorRanges = 0;
}
#endif
colorControlClass = NewObject(controlClass, 0);
AddToReferenceList(colorControlClass);
colorWheelClass = NewObject(colorControlClass, 0);
AddToReferenceList(colorWheelClass);
#ifdef GRAPHICS
SetMethod(colorWheelClass, DRAW, DrawColorWheel);
#endif
#ifdef INTERACTIVE
SetMethod(colorWheelClass, PRESS, TrackColorWheel);
#endif
SetMethod(colorWheelClass, SETVAL, SetColorWheelVal);
SetVar(colorWheelClass, TYPESTRING, NewString("color wheel"));
SetVar(colorWheelClass, HELPSTRING, NewString("To select a color, click at the color you desire. \
Colors around the edge of the circle are fully saturated; colors near the center are \
less saturated. Hold down the Shift key while pressing to \
constrain to full or half saturation. Double-click to snap to the closest full- or half-saturated \
color or white."));
/*Create a color bar class*/
colorBarClass = NewObject(controlClass, 0);
AddToReferenceList(colorBarClass);
#ifdef GRAPHICS
SetMethod(colorBarClass, DRAW, DrawColorBar);
#endif
#ifdef INTERACTIVE
SetMethod(colorBarClass, PRESS, PressColorBar);
#endif
SetVar(colorBarClass, OPAQUE, ObjTrue);
SetMethod(colorBarClass, SETVAL, SetColorBarVal);
/*Create a palette display class*/
paletteDisplayClass = NewObject(controlClass, 0);
AddToReferenceList(paletteDisplayClass);
SetVar(paletteDisplayClass, SHOWMINORTICS, ObjTrue);
#ifdef GRAPHICS
SetMethod(paletteDisplayClass, DRAW, DrawPaletteDisplay);
#endif
#ifdef INTERACTIVE
SetMethod(paletteDisplayClass, PRESS, PressPaletteDisplay);
#endif
SetMethod(paletteDisplayClass, NEWCTLWINDOW, ShowPaletteDisplayControls);
SetMethod(paletteDisplayClass, SHOWCONTROLS, NewControlWindow);
var = NewRealArray(1, 3L);
((real *) ELEMENTS(var))[0] = 1.0;
((real *) ELEMENTS(var))[1] = 1.0;
((real *) ELEMENTS(var))[2] = 1.0;
SetVar(paletteDisplayClass, COLOR, var);
SetTextFont(paletteDisplayClass, DSPPALETTEFONT);
SetTextSize(paletteDisplayClass, DSPPALETTESIZE);
SetMethod(paletteDisplayClass, SELECT, SelectPaletteDisplay);
SetTextAlign(paletteDisplayClass, RIGHTALIGN);
SetVar(paletteDisplayClass, TICDENSITY, NewReal(10.0));
SetVar(paletteDisplayClass, MINMAJORSTEP, NewInt(30));
}
void KillColors()
{
DeleteThing(paletteDisplayClass);
DeleteThing(colorBarClass);
DeleteThing(colorWheelClass);
DeleteThing(colorControlClass);
DeleteThing(paletteClass);
DeleteThing(iconColorPalette);
}
|