gecko-dev/cmd/xfe/colorpicker.c
1998-03-28 03:38:53 +00:00

1609 lines
39 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
* colorpicker.c --- Color related widgets, dialogs, and stuff.
*
* Created: David Williams <djw@netscape.com>, Apr-20-1997
*
* RCSID: "$Id: colorpicker.c,v 3.1 1998/03/28 03:19:56 ltabb Exp $"
*/
#include "mozilla.h"
#include "xfe.h"
#include <XmL/Folder.h> /* tab folder stuff */
#include <Xm/Label.h>
#include <Xm/DrawnBP.h>
#include <Xm/Scale.h>
#include <Xfe/XfeP.h> /* for xfe widgets and utilities */
#include <xpgetstr.h> /* for XP_GetString() */
#include "felocale.h"
#define DEFAULT_NCOLUMNS 10
#define DEFAULT_NROWS 7
#define DEFAULT_NCUSTOM_ROWS 2
#define DEFAULT_BUTTON_SIZE 18
#define DEFAULT_SPACE_SIZE 2
#define DEFAULT_MARGIN_SIZE 2
/*
* NOTE: a good size seems to be something between 1 or 4...
*
*/
#define XFE_COLOR_RED (0x1)
#define XFE_COLOR_GREEN (0x2)
#define XFE_COLOR_BLUE (0x4)
#define XFE_COLOR_UNITS (0x8)
#define XFE_COLOR_INIT (0x10)
/*
* NOTE: new palette per EditorSpec...
*
*/
static char* fe_color_picker_standard_palette[] = {
"#FFFFFF","#FFCCCC","#FFCC99","#FFFF99","#FFFFCC","#99FF99","#99FFFF","#CCFFFF","#CCCCFF","#FFCCFF",
"#CCCCCC","#FF6666","#FFCC33","#FFFF66","#FFFF99","#66FF99","#33FFFF","#66FFFF","#9999FF","#FF99FF",
"#CCCCCC","#FF0000","#FF9900","#FFCC66","#FFFF00","#33FF33","#66CCCC","#33CCFF","#6666CC","#CC66CC",
"#999999","#CC0000","#FF6600","#FFCC33","#FFCC00","#33CC00","#00CCCC","#3366FF","#6633FF","#CC33CC",
"#666666","#990000","#CC6600","#CC9933","#999900","#009900","#339999","#3333FF","#6600CC","#993399",
"#333333","#660000","#993300","#996633","#666600","#006600","#336666","#000099","#333399","#663366",
"#000000","#330000","#663300","#663333","#333300","#003300","#003333","#000066","#330099","#330033",
NULL
};
#if 0
/*
* These colors are the above corrected to fall into the 140 HTML
* colornames defined in lib/xp/xp_rgb.c
*/
static char* corrected_named_shuang_palette[] = {
"white",
"pink",
"salmon",
"red",
"red",
"darkred",
"maroon",
"black",
"lightgrey",
"lemonchiffon",
"khaki",
"yellow",
"gold",
"olive",
"olive",
"darkgreen",
"darkgray",
"lightcyan",
"aquamarine",
"deepskyblue",
"royalblue",
"royalblue",
"darkblue",
"navy",
"dimgray",
"lavender",
"violet",
"orchid",
"mediumorchid",
"darkorchid",
"darkslateblue",
"midnightblue",
"black",
"navajowhite",
"gold",
"orange",
"orangered",
"chocolate",
"saddlebrown",
"saddlebrown",
"black",
"aquamarine",
"lightgreen",
"limegreen",
"limegreen",
"green",
"darkgreen",
"darkgreen",
NULL
};
/*
* These are the 16 color names specified in the HTML 3.2 spec.
*/
static char* html32_named_colors[] = {
"#000000", /*Black = */
"#008000", /*Green = */
"#C0C0C0", /*Silver = */
"#00FF00", /*Lime = */
"#808080", /*Gray = */
"#808000", /*Olive = */
"#FFFFFF", /*White = */
"#FFFF00", /*Yellow = */
"#800000", /*Maroon = */
"#000080", /*Navy = */
"#FF0000", /*Red = */
"#0000FF", /*Blue = */
"#800080", /*Purple = */
"#008080", /*Teal = */
"#FF00FF", /*Fuchsia = */
"#00FFFF", /*Aqua = */
NULL
};
#endif /* end of unused palettes */
/*
* This routine is used throughout this code to create a pixel
* from an RGB value.
*/
static Pixel
fe_color_get_pixel(Widget widget, uint8 red, uint8 green, uint8 blue)
{
MWContext* context = (MWContext *)fe_WidgetToMWContext(widget);
/*
* Make a pixel. I'm hoping Jamie's color stuff will
* know when to release this...djw
*/
return fe_GetPixel(context, red, green, blue);
}
/*
* Code for a simple color swatch:
*
* Widget fe_CreateSwatch(Widget parent, char* name, Arg* args, Cardinal n);
* void fe_SwatchSetColor(Widget widget, LO_Color* color);
*/
static void
fe_swatch_expose_cb(Widget widget, XtPointer closure, XtPointer cbd)
{
XmDrawnButtonWidget db = (XmDrawnButtonWidget)widget;
XmLabelPart* lp = &(db->label);
GC gc;
unsigned offset = db->primitive.highlight_thickness +
db->primitive.shadow_thickness;
XtVaGetValues(widget, XmNuserData, &gc, 0);
XFillRectangle(XtDisplay(widget), XtWindow(widget),
gc,
offset, offset,
_XfeWidth(db) - 2 * offset, _XfeHeight(db) - 2 * offset);
if (lp->label_type == XmSTRING && lp->_label != NULL) {
_XmStringDraw(XtDisplay(widget), XtWindow(widget),
lp->font, lp->_label,
lp->normal_GC,
lp->TextRect.x, lp->TextRect.y,
lp->TextRect.width, lp->alignment,
lp->string_direction, NULL);
}
}
static void
fe_SwatchSetColor(Widget widget, LO_Color* color)
{
GC gc;
XGCValues values;
XtGCMask valueMask;
Pixel pixel;
Pixel foreground;
XtVaGetValues(widget, XmNuserData, &gc, 0);
XtReleaseGC(widget, gc);
pixel = fe_color_get_pixel(widget, color->red, color->green, color->blue);
XmGetColors(XtScreen(widget), XfeColormap(widget), pixel,
&foreground, NULL, NULL, NULL);
valueMask = GCForeground;
values.foreground = pixel;
gc = XtGetGC(widget, valueMask, &values);
XtVaSetValues(widget, XmNuserData, gc, XmNforeground, foreground, 0);
if (XtIsRealized(widget))
fe_swatch_expose_cb(widget, NULL, NULL);
}
static void
fe_swatch_destroy_cb(Widget widget, XtPointer closure, XtPointer cbd)
{
GC gc;
XtVaGetValues(widget, XmNuserData, &gc, 0);
if (gc != 0)
XtReleaseGC(widget, gc);
}
static Widget
fe_CreateSwatch(Widget parent, char* name, Arg* args, Cardinal n)
{
Widget widget;
GC gc;
XGCValues values;
XtGCMask valueMask;
Pixel pixel;
widget = XmCreateDrawnButton(parent, name, args, n);
XtVaGetValues(parent, XmNbackground, &pixel, 0);
valueMask = GCForeground;
values.foreground = pixel;
gc = XtGetGC(widget, valueMask, &values);
XtVaSetValues(widget, XmNuserData, gc, 0);
XtAddCallback(widget, XmNexposeCallback, fe_swatch_expose_cb, NULL);
XtAddCallback(widget, XmNdestroyCallback, fe_swatch_destroy_cb, NULL);
return widget;
}
/*
* Code for a color swatch matrix:
*
* Widget fe_CreateSwatchMatrix(Widget parent, char* name, Arg*, Cardinal);
* use this function in a callback to get the color at x,y
* int fe_SwatchMatrixGetColor(Widget, Position x, Position y, XColor*);
*/
#if 0
static char fe_ColorPickerButtonSize[] = "colorButtonSize";
#endif
static char fe_ColorPickerPalette[] = "colorPalette";
typedef struct ColorInfo {
unsigned long rgb;
Pixel pixel;
} ColorInfo;
typedef struct SwatchesInfo {
ColorInfo* colors;
unsigned ncolors;
GC drawing_gc;
} SwatchesInfo;
static void
fe_swatches_destroy_cb(Widget widget, XtPointer closure, XtPointer cbd)
{
SwatchesInfo* info;
XtVaGetValues(widget, XmNuserData, &info, 0);
if (info != NULL) {
if (info->drawing_gc != 0)
XFreeGC(XtDisplay(widget), info->drawing_gc);
if (info->colors != NULL)
XtFree((char*)info->colors);
XtFree((char*)info);
}
}
int
fe_SwatchMatrixGetColor(Widget widget, Position p_x, Position p_y,
XColor* color_r)
{
char* name = XtName(widget);
uint8 red;
uint8 green;
uint8 blue;
if (name == NULL) {
red = blue = green = 0;
}
else {
if (!LO_ParseRGB(name, &red, &green, &blue)) {
red = blue = green = 0; /* black */
}
}
/*
* NOTE: we could also just get the background pixel from the widget
* - something to look into if this becomes too expensive...
*
*/
color_r->pixel = fe_color_get_pixel(widget, red, green, blue);
color_r->red = red;
color_r->green = green;
color_r->blue = blue;
return 1;
}
typedef enum {
XFE_COLOR_DECIMAL,
XFE_COLOR_HEX,
XFE_COLOR_PERCENT
} fe_ColorUnit;
typedef struct fe_SamplePageInfo fe_SamplePageInfo;
typedef struct fe_ColorUpdateInfo
{
LO_Color color;
Pixel pixel;
fe_ColorUnit units;
fe_SamplePageInfo* list;
} fe_ColorUpdateInfo;
typedef struct fe_SamplePart
{
Widget old;
Widget new;
} fe_SamplePart;
typedef void (*fe_ColorUpdateMethod_t)(void* page_info, Widget, unsigned);
struct fe_SamplePageInfo
{
fe_ColorUpdateInfo* update_info;
fe_ColorUpdateMethod_t update_method;
fe_SamplePageInfo* next;
fe_SamplePart sample;
};
typedef struct fe_RgbPart
{
Widget max;
Widget red_scale;
Widget green_scale;
Widget blue_scale;
Widget red_text;
Widget green_text;
Widget blue_text;
Widget units;
} fe_RgbPart;
typedef struct fe_RgbPageInfo
{
fe_ColorUpdateInfo* update_info;
fe_ColorUpdateMethod_t update_method;
fe_SamplePageInfo* next;
fe_SamplePart sample;
fe_RgbPart rgb;
} fe_RgbPageInfo;
typedef struct fe_SwatchesPart
{
Widget matrix;
} fe_SwatchesPart;
typedef struct fe_SwatchesPageInfo
{
fe_ColorUpdateInfo* update_info;
fe_ColorUpdateMethod_t update_method;
fe_SamplePageInfo* next;
fe_SamplePart sample;
fe_SwatchesPart swatches;
} fe_SwatchesPageInfo;
static void
fe_swatch_matrix_enter_eh(Widget chit, XtPointer closure,
XEvent* event, Boolean* keep_going)
{
XtVaSetValues(chit,
XmNshadowType, XmSHADOW_IN,
0);
}
static void
fe_swatch_matrix_exit_eh(Widget chit, XtPointer closure,
XEvent* event, Boolean* keep_going)
{
XtVaSetValues(chit,
XmNshadowType, XmSHADOW_ETCHED_IN,
0);
}
static void
fe_swatch_matrix_destroy_cb(Widget chit, XtPointer closure, XtPointer cbd)
{
XtRemoveEventHandler(chit, EnterWindowMask, FALSE,
fe_swatch_matrix_enter_eh, NULL);
XtRemoveEventHandler(chit, LeaveWindowMask, FALSE,
fe_swatch_matrix_exit_eh, NULL);
}
#define MAX_ARGS 16
Widget
fe_CreateSwatchMatrix(Widget parent, char* name, Arg* p_args, Cardinal p_nargs)
{
Widget matrix;
unsigned n;
unsigned m;
Dimension shadow;
Dimension highlight;
Arg args[MAX_ARGS];
SwatchesInfo* info;
Pixel bg_pixel = BlackPixelOfScreen(XtScreen(parent));
Pixel nu_pixel = NULL;
char** palette = (char**)&fe_color_picker_standard_palette;
n = 0;
XtSetArg(args[n], XmNpacking, XmPACK_COLUMN); n++;
XtSetArg(args[n], XmNnumColumns, DEFAULT_NROWS); n++;
XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
XtSetArg(args[n], XmNspacing, DEFAULT_SPACE_SIZE); n++;
XtSetArg(args[n], XmNmarginWidth, DEFAULT_MARGIN_SIZE); n++;
XtSetArg(args[n], XmNmarginHeight, DEFAULT_MARGIN_SIZE); n++;
XtSetArg(args[n], XmNtraversalOn, False); n++;
matrix = XmCreateRowColumn(parent, name, args, n);
/*
* Parse args, looking for pallete or background spec
*/
for (m = 0; m < p_nargs ; m++) {
if (strcmp(p_args[m].name, fe_ColorPickerPalette) == 0)
palette = (char**)p_args[m].value;
else if (strcmp(p_args[m].name, XmNbackground) == 0)
bg_pixel = (Pixel)p_args[m].value;
}
/*
* Make the info stuff.
*/
info = XtNew(SwatchesInfo);
info->drawing_gc = 0;
for (n = 0; palette[n] != NULL; n++)
;
info->ncolors = n;
info->colors = NULL;
for (n = 0;n < info->ncolors; n++) {
uint8 red;
uint8 green;
uint8 blue;
unsigned i = 0;
Widget chit = NULL;
if (!LO_ParseRGB(palette[n], &red, &green, &blue)) {
red = blue = green = 0; /* black */
}
nu_pixel = fe_color_get_pixel(matrix, red, green, blue);
i = 0;
XtSetArg(args[i], XmNbackground, nu_pixel); i++;
XtSetArg(args[i], XmNwidth, DEFAULT_BUTTON_SIZE); i++;
XtSetArg(args[i], XmNheight, DEFAULT_BUTTON_SIZE); i++;
XtSetArg(args[i], XmNshadowType, XmSHADOW_ETCHED_IN); i++;
XtSetArg(args[i], XmNhighlightThickness, 0); i++;
XtSetArg(args[i], XmNmarginWidth, DEFAULT_MARGIN_SIZE); i++;
XtSetArg(args[i], XmNmarginHeight, DEFAULT_MARGIN_SIZE); i++;
XtSetArg(args[i], XmNtraversalOn, False); i++;
XtSetArg(args[i], XmNpushButtonEnabled, False); i++;
chit = XmCreateDrawnButton(matrix, palette[n], args, i);
fe_WidgetAddToolTips(chit);
XtAddEventHandler(chit, EnterWindowMask, FALSE,
fe_swatch_matrix_enter_eh, NULL);
XtAddEventHandler(chit, LeaveWindowMask, FALSE,
fe_swatch_matrix_exit_eh, NULL);
XtAddCallback(chit, XmNdestroyCallback,
fe_swatch_matrix_destroy_cb, NULL);
XtManageChild(chit);
}
XtVaSetValues(matrix,
XmNuserData, info,
0);
XtAddCallback(matrix, XmNdestroyCallback, fe_swatches_destroy_cb,
NULL);
return matrix;
}
void
fe_AddSwatchMatrixCallback(Widget matrix,
char* name, XtCallbackProc proc, XtPointer data)
{
WidgetList kids = NULL;
uint32 numKids = 0;
uint32 n = 0;
XtVaGetValues(matrix,
XmNchildren, &kids,
XmNnumChildren, &numKids,
0);
if (numKids > 0) {
for (n = 0; n < numKids; n++) {
XtAddCallback(kids[n], name, proc, data);
}
}
}
static void
fe_color_install_page(fe_ColorUpdateInfo* update,
fe_ColorUpdateMethod_t update_method,
fe_SamplePageInfo* page)
{
page->update_info = update;
page->update_method = update_method;
page->next = update->list;
update->list = page;
}
static void
fe_color_sample_part_update(fe_SamplePart* widgets,
fe_ColorUpdateInfo* update_info,
Widget caller,
unsigned mask)
{
fe_SwatchSetColor(widgets->new, &update_info->color);
if ((mask & XFE_COLOR_INIT) != 0) {
Pixel foreground;
XmGetColors(XtScreen(widgets->old), XfeColormap(widgets->old),
update_info->pixel,
&foreground, NULL, NULL, NULL);
XtVaSetValues(widgets->old,
XmNbackground, update_info->pixel,
XmNforeground, foreground,
0);
}
}
static void
fe_color_rgb_page_update(fe_RgbPageInfo*, Widget, unsigned mask);
static void
fe_color_rgb_max_update_cb(Widget widget, XtPointer closure, XtPointer cb)
{
fe_ColorUpdateInfo* info = (fe_ColorUpdateInfo*)closure;
char* buf;
XmString tmp_string;
switch (info->units) {
case XFE_COLOR_HEX: buf = "0xFF"; break;
case XFE_COLOR_PERCENT: buf = "100%"; break;
case XFE_COLOR_DECIMAL:
default: buf = " 255"; break;
}
tmp_string = XmStringCreateSimple(buf);
XtVaSetValues(widget, XmNlabelString, tmp_string, 0);
XmStringFree(tmp_string);
}
static void
fe_color_rgb_text_cb(Widget widget, XtPointer closure, XtPointer cb)
{
fe_RgbPageInfo* rgb_info = (fe_RgbPageInfo*)closure;
fe_ColorUpdateInfo* info = rgb_info->update_info;
char* string = fe_GetTextField(widget);
unsigned value;
unsigned mask;
char* name = XtName(widget);
if (info->units == XFE_COLOR_HEX) {
value = strtoul(string, NULL, 16);
} else if (info->units == XFE_COLOR_PERCENT) {
value = strtoul(string, NULL, 10);
if (value > 100)
value = 100;
value = (256 * value) / 100;
} else {
value = strtoul(string, NULL, 10);
}
if (value > 255)
value = 255;
if (name[0] == 'r') { /* this sucks */
info->color.red = value;
mask = XFE_COLOR_RED;
} else if (name[0] == 'g') {
info->color.green = value;
mask = XFE_COLOR_GREEN;
} else {
info->color.blue = value;
mask = XFE_COLOR_BLUE;
}
fe_color_rgb_page_update(rgb_info, widget, mask);
}
static void
fe_color_rgb_text_update_cb(Widget widget, XtPointer closure, XtPointer cb)
{
fe_ColorUpdateInfo* info = (fe_ColorUpdateInfo*)closure;
Widget caller = (Widget)cb;
char buf[32];
unsigned big;
unsigned result;
unsigned value;
char* name;
if (caller == widget)
return;
name = XtName(widget);
if (name[0] == 'r') /* this sucks */
value = info->color.red;
else if (name[0] == 'g')
value = info->color.green;
else
value = info->color.blue;
switch (info->units) {
case XFE_COLOR_HEX:
sprintf(buf, "%02X", value);
break;
case XFE_COLOR_PERCENT:
big = 100 * value;
result = big / 256;
if ((big % 256) > 127)
result++;
sprintf(buf, "%03d", result);
break;
case XFE_COLOR_DECIMAL:
default:
sprintf(buf, "%03d", value);
break;
}
fe_TextFieldSetString(widget, buf, False);
}
static void
fe_color_rgb_scale_cb(Widget widget, XtPointer closure, XtPointer cb)
{
fe_RgbPageInfo* rgb_info = (fe_RgbPageInfo*)closure;
fe_ColorUpdateInfo* info = rgb_info->update_info;
XmScaleCallbackStruct* cd = (XmScaleCallbackStruct*)cb;
unsigned value = cd->value;
char* name = XtName(widget);
unsigned mask;
if (value > 255)
value = 255;
if (name[0] == 'r') { /* this sucks */
info->color.red = value;
mask = XFE_COLOR_RED;
} else if (name[0] == 'g') {
info->color.green = value;
mask = XFE_COLOR_GREEN;
} else {
info->color.blue = value;
mask = XFE_COLOR_BLUE;
}
fe_color_rgb_page_update(rgb_info, widget, mask);
}
static void
fe_color_rgb_scale_update_cb(Widget widget, XtPointer closure, XtPointer cb)
{
fe_ColorUpdateInfo* info = (fe_ColorUpdateInfo*)closure;
Widget caller = (Widget)cb;
unsigned value;
char* name;
if (caller == widget)
return;
name = XtName(widget);
if (name[0] == 'r') /* this sucks */
value = info->color.red;
else if (name[0] == 'g')
value = info->color.green;
else
value = info->color.blue;
XtVaSetValues(widget, XmNvalue, value, 0);
}
static void
fe_color_rgb_units_cb(Widget widget, XtPointer closure, XtPointer cb)
{
fe_RgbPageInfo* rgb_info = (fe_RgbPageInfo*)closure;
fe_ColorUpdateInfo* info = rgb_info->update_info;
char* name = XtName(widget);
if (name[0] == 'p') /* percent */
info->units = XFE_COLOR_PERCENT;
else if (name[0] == 'h')
info->units = XFE_COLOR_HEX;
else
info->units = XFE_COLOR_DECIMAL;
fe_color_rgb_page_update(rgb_info, widget, XFE_COLOR_UNITS);
}
static void
fe_color_rgb_page_update(fe_RgbPageInfo* rgb_info, Widget caller, unsigned mask)
{
fe_ColorUpdateInfo* info = rgb_info->update_info;
fe_SamplePart* sample_part = &rgb_info->sample;
fe_RgbPart* rgb_part = &rgb_info->rgb;
if ((mask & (XFE_COLOR_RED|XFE_COLOR_GREEN|XFE_COLOR_BLUE)) != 0) {
info->pixel = fe_color_get_pixel(sample_part->new,
info->color.red,
info->color.green,
info->color.blue);
/*
* Update the sample
*/
fe_color_sample_part_update(&rgb_info->sample, info, caller, mask);
}
if ((mask & XFE_COLOR_RED) != 0)
fe_color_rgb_scale_update_cb(rgb_part->red_scale, info, caller);
if ((mask & XFE_COLOR_GREEN) != 0)
fe_color_rgb_scale_update_cb(rgb_part->green_scale, info, caller);
if ((mask & XFE_COLOR_BLUE) != 0)
fe_color_rgb_scale_update_cb(rgb_part->blue_scale, info, caller);
if ((mask & XFE_COLOR_UNITS) != 0)
fe_color_rgb_max_update_cb(rgb_part->max, info, caller);
if ((mask & (XFE_COLOR_RED|XFE_COLOR_UNITS)) != 0)
fe_color_rgb_text_update_cb(rgb_part->red_text, info, caller);
if ((mask & (XFE_COLOR_GREEN|XFE_COLOR_UNITS)) != 0)
fe_color_rgb_text_update_cb(rgb_part->green_text, info, caller);
if ((mask & (XFE_COLOR_BLUE|XFE_COLOR_UNITS)) != 0)
fe_color_rgb_text_update_cb(rgb_part->blue_text, info, caller);
}
static Widget
fe_create_rgb_group(Widget parent, fe_RgbPageInfo* info)
{
Widget rgb_frame;
Widget form;
Widget red_label;
Widget green_label;
Widget blue_label;
Widget red_scale;
Widget green_scale;
Widget blue_scale;
Widget red_text;
Widget green_text;
Widget blue_text;
Widget min_label;
Widget max_label;
Widget units;
Widget pulldown;
XmString tmp_string;
Widget bottom;
Widget text;
Widget label;
Widget scale;
Widget button;
int i;
Widget children[16];
Cardinal nchildren = 0;
Arg args[16];
Cardinal n;
#define SHOW_VALUE FALSE
#define TEXT_NCOLUMNS 4
n = 0;
rgb_frame = XmCreateFrame(parent, "rgbEditor", args, n);
XtManageChild(rgb_frame);
n = 0;
form = XmCreateForm(rgb_frame, "rgbForm", args, n);
XtManageChild(form);
tmp_string = XmStringCreateSimple("0");
n = 0;
XtSetArg(args[n], XmNlabelType, XmSTRING); n++;
XtSetArg(args[n], XmNlabelString, tmp_string); n++;
min_label = XmCreateLabelGadget(form, "minLabel", args, n);
children[nchildren++] = min_label;
XmStringFree(tmp_string);
tmp_string = XmStringCreateSimple("255");
n = 0;
XtSetArg(args[n], XmNlabelType, XmSTRING); n++;
XtSetArg(args[n], XmNlabelString, tmp_string); n++;
max_label = XmCreateLabelGadget(form, "maxLabel", args, n);
children[nchildren++] = max_label;
XmStringFree(tmp_string);
tmp_string = XmStringCreateSimple("R");
n = 0;
XtSetArg(args[n], XmNlabelType, XmSTRING); n++;
XtSetArg(args[n], XmNlabelString, tmp_string); n++;
red_label = XmCreateLabelGadget(form, "redLabel", args, n);
children[nchildren++] = red_label;
XmStringFree(tmp_string);
n = 0;
XtSetArg(args[n], XmNuserData, (XtPointer)XFE_COLOR_RED); n++;
XtSetArg(args[n], XmNshowValue, SHOW_VALUE); n++;
XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
XtSetArg(args[n], XmNmaximum, 256); n++;
red_scale = XmCreateScale(form, "redScale", args, n);
children[nchildren++] = red_scale;
XtAddCallback(red_scale, XmNdragCallback,
fe_color_rgb_scale_cb, (XtPointer)info);
XtAddCallback(red_scale, XmNvalueChangedCallback,
fe_color_rgb_scale_cb, (XtPointer)info);
n = 0;
XtSetArg(args[n], XmNcolumns, TEXT_NCOLUMNS); n++;
XtSetArg(args[n], XmNuserData, (XtPointer)XFE_COLOR_RED); n++;
red_text = fe_CreateTextField(form, "redText", args, n);
children[nchildren++] = red_text;
XtAddCallback(red_text, XmNvalueChangedCallback,
fe_color_rgb_text_cb, (XtPointer)info);
tmp_string = XmStringCreateSimple("G");
n = 0;
XtSetArg(args[n], XmNlabelType, XmSTRING); n++;
XtSetArg(args[n], XmNlabelString, tmp_string); n++;
green_label = XmCreateLabelGadget(form, "greenLabel", args, n);
children[nchildren++] = green_label;
XmStringFree(tmp_string);
n = 0;
XtSetArg(args[n], XmNuserData, (XtPointer)XFE_COLOR_GREEN); n++;
XtSetArg(args[n], XmNshowValue, SHOW_VALUE); n++;
XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
XtSetArg(args[n], XmNmaximum, 256); n++;
green_scale = XmCreateScale(form, "greenScale", args, n);
children[nchildren++] = green_scale;
XtAddCallback(green_scale, XmNdragCallback,
fe_color_rgb_scale_cb, (XtPointer)info);
XtAddCallback(green_scale, XmNvalueChangedCallback,
fe_color_rgb_scale_cb, (XtPointer)info);
n = 0;
XtSetArg(args[n], XmNuserData, (XtPointer)XFE_COLOR_GREEN); n++;
XtSetArg(args[n], XmNcolumns, TEXT_NCOLUMNS); n++;
green_text = fe_CreateTextField(form, "greenText", args, n);
children[nchildren++] = green_text;
XtAddCallback(green_text, XmNvalueChangedCallback,
fe_color_rgb_text_cb, (XtPointer)info);
tmp_string = XmStringCreateSimple("B");
n = 0;
XtSetArg(args[n], XmNlabelType, XmSTRING); n++;
XtSetArg(args[n], XmNlabelString, tmp_string); n++;
blue_label = XmCreateLabelGadget(form, "blueLabel", args, n);
children[nchildren++] = blue_label;
XmStringFree(tmp_string);
n = 0;
XtSetArg(args[n], XmNuserData, (XtPointer)XFE_COLOR_BLUE); n++;
XtSetArg(args[n], XmNshowValue, SHOW_VALUE); n++;
XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
XtSetArg(args[n], XmNmaximum, 256); n++;
blue_scale = XmCreateScale(form, "blueScale", args, n);
children[nchildren++] = blue_scale;
XtAddCallback(blue_scale, XmNdragCallback,
fe_color_rgb_scale_cb, (XtPointer)info);
XtAddCallback(blue_scale, XmNvalueChangedCallback,
fe_color_rgb_scale_cb, (XtPointer)info);
n = 0;
XtSetArg(args[n], XmNuserData, (XtPointer)XFE_COLOR_BLUE); n++;
XtSetArg(args[n], XmNcolumns, TEXT_NCOLUMNS); n++;
blue_text = fe_CreateTextField(form, "blueText", args, n);
children[nchildren++] = blue_text;
XtAddCallback(blue_text, XmNvalueChangedCallback,
fe_color_rgb_text_cb, (XtPointer)info);
XtManageChildren(children, nchildren);
/*
* Do units option menu.
*/
n = 0;
pulldown = fe_CreatePulldownMenu(form, "unitsMenu", args, n);
nchildren = 0;
n = 0;
XtSetArg(args[n], XmNuserData, (XtPointer)0); n++;
button = XmCreatePushButtonGadget(pulldown, "decimal", args, n);
XtAddCallback(button, XmNactivateCallback, fe_color_rgb_units_cb,
(XtPointer)info);
children[nchildren++] = button;
n = 0;
XtSetArg(args[n], XmNuserData, (XtPointer)1); n++;
button = XmCreatePushButtonGadget(pulldown, "hex", args, n);
XtAddCallback(button, XmNactivateCallback, fe_color_rgb_units_cb,
(XtPointer)info);
children[nchildren++] = button;
n = 0;
XtSetArg(args[n], XmNuserData, (XtPointer)2); n++;
button = XmCreatePushButtonGadget(pulldown, "percent", args, n);
XtAddCallback(button, XmNactivateCallback, fe_color_rgb_units_cb,
(XtPointer)info);
children[nchildren++] = button;
XtManageChildren(children, nchildren);
n = 0;
XtSetArg(args[n], XmNsubMenuId, pulldown); n++;
units = XmCreateOptionMenu(form, "units", args, n);
XtManageChild(units);
/*
* Now do attachments! We actually connect up from the
* bottom.
*/
n = 0;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
XtSetArg(args[n], XmNleftWidget, red_scale); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNbottomWidget, red_scale); n++;
XtSetValues(min_label, args, n);
n = 0;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
XtSetArg(args[n], XmNrightWidget, red_scale); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNbottomWidget, red_scale); n++;
XtSetValues(max_label, args, n);
for (i = 0; i < 3; i++) {
if (i == 0) {
bottom = green_text;
text = red_text;
scale = red_scale;
label = red_label;
} else if (i == 1) {
bottom = blue_text;
text = green_text;
scale = green_scale;
label = green_label;
} else {
bottom = units;
text = blue_text;
scale = blue_scale;
label = blue_label;
}
n = 0;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNbottomWidget, bottom); n++;
XtSetValues(text, args, n);
n = 0;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNbottomWidget, bottom); n++;
XtSetValues(label, args, n);
n = 0;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNrightWidget, text); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNleftWidget, label); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNbottomWidget, bottom); n++;
XtSetValues(scale, args, n);
}
n = 0;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetValues(units, args, n);
info->rgb.max = max_label;
info->rgb.red_scale = red_scale;
info->rgb.green_scale = green_scale;
info->rgb.blue_scale = blue_scale;
info->rgb.red_text = red_text;
info->rgb.green_text = green_text;
info->rgb.blue_text = blue_text;
info->rgb.units = units;
return rgb_frame;
}
static Widget
fe_create_sample_group(Widget parent, fe_SamplePageInfo* info)
{
Widget frame;
Widget row;
Widget old_sample;
Widget new_sample;
Cardinal n;
Arg args[8];
n = 0;
XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
XtSetArg(args[n], XmNpacking, XmPACK_COLUMN); n++;
row = XmCreateRowColumn(parent, "sample", args, n);
XtManageChild(row);
frame = row;
n = 0;
old_sample = XmCreateDrawnButton(row, "oldSample", args, n);
XtManageChild(old_sample);
n = 0;
new_sample = fe_CreateSwatch(row, "newSample", args, n);
XtManageChild(new_sample);
info->sample.old = old_sample;
info->sample.new = new_sample;
return frame;
}
/*
* rgb buttons - unused.
*/
#if 0
static Widget
fe_create_rgb_buttons_group(Widget parent, fe_RgbPageInfo* info)
{
Widget frame;
Widget row;
Cardinal n;
Arg args[8];
XmString xm_string;
Widget grab;
Widget match;
/*
* Standard colors: frame with N color buttons.
*/
n = 0;
frame = XmCreateFrame(parent, "buttonsFrame", args, n);
XtManageChild(frame);
n = 0;
XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
row = XmCreateRowColumn(frame, "buttons", args, n);
XtManageChild(row);
xm_string = XmStringCreateSimple("Dropper...");
n = 0;
XtSetArg(args[n], XmNlabelString, xm_string); n++;
grab = XmCreatePushButtonGadget(row, "grab", args, n);
XtManageChild(grab);
XmStringFree(xm_string);
xm_string = XmStringCreateSimple("Match");
n = 0;
XtSetArg(args[n], XmNlabelString, xm_string); n++;
match = XmCreatePushButtonGadget(row, "match", args, n);
XtManageChild(match);
XmStringFree(xm_string);
#if 0
Widget info_label;
xm_string = XmStringCreateSimple("white");
n = 0;
XtSetArg(args[n], XmNlabelString, xm_string); n++;
info_label = XmCreateLabelGadget(row, "info", args, n);
XtManageChild(info_label);
XmStringFree(xm_string);
#endif
return frame;
}
#endif
static void
fe_color_page_destroy_cb(Widget form, XtPointer closure, XtPointer cbd)
{
#if 0
fprintf(stderr, "detroying page %s\n", XtName(form));
#endif
if (closure)
XtFree((char*)closure);
}
static Widget
fe_create_rgb_page(Widget folder, char* name, fe_ColorUpdateInfo* info)
{
Widget rgb_group;
Widget sample_group;
Widget form;
Arg args[16];
Cardinal n;
fe_RgbPageInfo* rgb_info = XtNew(fe_RgbPageInfo);
rgb_info->update_info = info;
fe_color_install_page(info,
(fe_ColorUpdateMethod_t)fe_color_rgb_page_update,
(fe_SamplePageInfo*)rgb_info);
n = 0;
form = fe_CreateTabForm(folder, name, args, n);
XtAddCallback(form,
XmNdestroyCallback, fe_color_page_destroy_cb, rgb_info);
sample_group = fe_create_sample_group(form, (fe_SamplePageInfo*)rgb_info);
rgb_group = fe_create_rgb_group(form, rgb_info);
#ifdef DO_BUTTONS
Widget buttons_group;
buttons_group = fe_create_rgb_buttons_group(form, rgb_info);
#endif
n = 0;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetValues(sample_group, args, n);
#ifdef DO_BUTTONS
n = 0;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNtopWidget, sample_group); n++;
XtSetValues(buttons_group, args, n);
#endif
n = 0;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNtopWidget, sample_group); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
#ifdef DO_BUTTONS
XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNrightWidget, buttons_group); n++;
#else
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
#endif
XtSetValues(rgb_group, args, n);
return form;
}
static void
fe_color_swatches_page_update(fe_SwatchesPageInfo* page_info,
Widget caller, unsigned mask)
{
fe_ColorUpdateInfo* info = page_info->update_info;
if ((mask & (XFE_COLOR_RED|XFE_COLOR_GREEN|XFE_COLOR_BLUE)) != 0) {
/*
* Update the sample
*/
fe_color_sample_part_update(&page_info->sample, info, caller, mask);
}
}
/*
* reset, load, save, append buttons for matrix page. unused.
*/
#if 0
static Widget
fe_create_swatch_buttons_group(Widget parent, void* notused)
{
Widget frame;
Widget row;
Cardinal n;
Arg args[8];
XmString xm_string;
Widget reset;
Widget load;
Widget save;
Widget append;
/*
* Standard colors: frame with N color buttons.
*/
n = 0;
frame = XmCreateFrame(parent, "buttonsFrame", args, n);
XtManageChild(frame);
n = 0;
XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
row = XmCreateRowColumn(frame, "buttons", args, n);
XtManageChild(row);
xm_string = XmStringCreateSimple("Reset");
n = 0;
XtSetArg(args[n], XmNlabelString, xm_string); n++;
reset = XmCreatePushButtonGadget(row, "reset", args, n);
XtManageChild(reset);
XmStringFree(xm_string);
xm_string = XmStringCreateSimple("Load..");
n = 0;
XtSetArg(args[n], XmNlabelString, xm_string); n++;
load = XmCreatePushButtonGadget(row, "load", args, n);
XtManageChild(load);
XmStringFree(xm_string);
xm_string = XmStringCreateSimple("Append..");
n = 0;
XtSetArg(args[n], XmNlabelString, xm_string); n++;
append = XmCreatePushButtonGadget(row, "append", args, n);
XtManageChild(append);
XmStringFree(xm_string);
xm_string = XmStringCreateSimple("Save..");
n = 0;
XtSetArg(args[n], XmNlabelString, xm_string); n++;
save = XmCreatePushButtonGadget(row, "save", args, n);
XtManageChild(save);
XmStringFree(xm_string);
return frame;
}
#endif
static void
fe_swatches_activate_cb(Widget widget, XtPointer closure, XtPointer cbd)
{
fe_SwatchesPageInfo* swatches_info = (fe_SwatchesPageInfo*) closure;
fe_ColorUpdateInfo* info = swatches_info->update_info;
XmDrawnButtonCallbackStruct* cbs = (XmDrawnButtonCallbackStruct*)cbd;
int colorn;
XColor color;
XButtonEvent* event = (XButtonEvent*)cbs->event;
fe_SwatchMatrixGetColor(widget, event->x, event->y, &color);
info->color.red = color.red;
info->color.green = color.green;
info->color.blue = color.blue;
info->pixel = color.pixel;
fe_color_swatches_page_update(swatches_info, widget,
(XFE_COLOR_RED|XFE_COLOR_GREEN|XFE_COLOR_BLUE));
}
static Widget
fe_create_swatch_group(Widget parent, fe_SwatchesPageInfo* info)
{
fe_SwatchesPart* swatches = &info->swatches;
Widget frame;
Widget matrix;
Arg args[16];
Cardinal n;
n = 0;
frame = XmCreateFrame(parent, "swatchesFrame", args, n);
XtManageChild(frame);
n = 0;
matrix = fe_CreateSwatchMatrix(frame, "swatches", args, n);
fe_AddSwatchMatrixCallback(matrix, XmNactivateCallback,
fe_swatches_activate_cb, info);
XtManageChild(matrix);
swatches->matrix = matrix;
return frame;
}
static Widget
fe_create_swatch_page(Widget folder, char* name, fe_ColorUpdateInfo* info)
{
Widget sample_group;
Widget swatch_group;
Widget form;
Arg args[16];
Cardinal n;
fe_SwatchesPageInfo* swatches_info = XtNew(fe_SwatchesPageInfo);
fe_color_install_page(info,
(fe_ColorUpdateMethod_t)fe_color_swatches_page_update,
(fe_SamplePageInfo*)swatches_info);
n = 0;
form = fe_CreateTabForm(folder, name, args, n);
XtAddCallback(form,
XmNdestroyCallback, fe_color_page_destroy_cb, swatches_info);
sample_group = fe_create_sample_group(form, (fe_SamplePageInfo*)swatches_info);
swatch_group = fe_create_swatch_group(form, swatches_info);
#ifdef DO_BUTTONS
Widget buttons_group;
buttons_group = fe_create_swatch_buttons_group(form, swatches_info);
#endif
n = 0;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetValues(sample_group, args, n);
#ifdef DO_BUTTONS
n = 0;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNtopWidget, sample_group); n++;
XtSetValues(buttons_group, args, n);
#endif
n = 0;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNtopWidget, sample_group); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
#ifdef DO_BUTTONS
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNrightWidget, buttons_group); n++;
#endif
XtSetValues(swatch_group, args, n);
return form;
}
static void
fe_color_page_raised_cb(Widget folder, XtPointer closure, XtPointer cbd)
{
fe_ColorUpdateInfo* info = (fe_ColorUpdateInfo*)closure;
fe_SamplePageInfo* page;
info->pixel = fe_color_get_pixel(folder,
info->color.red,
info->color.green,
info->color.blue);
for (page = info->list; page != NULL; page = page->next) {
if (page->update_method != NULL)
(page->update_method)(page, folder, ~XFE_COLOR_INIT);
}
}
Widget
fe_CreateColorPicker(Widget dialog, char* name, Arg* args, Cardinal nargs)
{
Widget folder;
Widget swatch_form;
Widget rgb_form;
Cardinal n;
fe_ColorUpdateInfo* info;
char* units;
Widget parent = XtParent(dialog);
info = XtNew(fe_ColorUpdateInfo); /* FIXME */
memset(info, 0, sizeof(fe_ColorUpdateInfo));
info->color.red = 0;
info->color.green = 0;
info->color.blue = 0;
info->pixel = 0;
info->units = XFE_COLOR_DECIMAL;
info->list = NULL;
units = XfeSubResourceGetStringValue(parent,
XtName(parent),
"XfeColorPicker",
"rgbUnits",
"RgbUnits",
NULL);
if (units != NULL) {
if (strcmp(units, "percent") == 0)
info->units = XFE_COLOR_PERCENT;
if (strcmp(units, "hexidecimal") == 0)
info->units = XFE_COLOR_HEX;
}
n = 0;
folder = XtVaCreateWidget(name, xmlFolderWidgetClass, dialog,
XmNshadowThickness, 2,
#ifdef ALLOW_TAB_ROTATE
XmNtabPlacement, XmFOLDER_LEFT,
XmNrotateWhenLeftRight, FALSE,
#endif /* ALLOW_TAB_ROTATE */
XmNbottomOffset, 3,
XmNspacing, 1,
NULL);
XtManageChild(folder);
XtAddCallback(folder,
XmNactivateCallback, fe_color_page_raised_cb, info);
XtAddCallback(folder,
XmNdestroyCallback, fe_color_page_destroy_cb, info);
n = 0;
swatch_form = fe_create_swatch_page(folder, "swatches", info);
XtManageChild(swatch_form);
n = 0;
rgb_form = fe_create_rgb_page(folder, "rgb", info);
XtManageChild(rgb_form);
XtVaSetValues(folder, XmNuserData, info, 0);
return folder;
}
void
fe_ColorPickerSetColor(Widget folder, LO_Color* color)
{
fe_ColorUpdateInfo* info;
fe_SamplePageInfo* page;
XtVaGetValues(folder, XmNuserData, &info, 0);
if (info != NULL) {
info->color.red = color->red;
info->color.green = color->green;
info->color.blue = color->blue;
info->pixel = fe_color_get_pixel(folder,
info->color.red,
info->color.green,
info->color.blue);
for (page = info->list; page != NULL; page = page->next) {
if (page->update_method != NULL)
(page->update_method)(page, folder, ~0);
}
}
}
void
fe_ColorPickerGetColor(Widget folder, LO_Color* color)
{
fe_ColorUpdateInfo* info;
XtVaGetValues(folder, XmNuserData, &info, 0);
if (info != NULL) {
color->red = info->color.red;
color->green = info->color.green;
color->blue = info->color.blue;
}
}
void
fe_ColorPickerSetActiveTab(Widget folder, fe_ColorPickerTabType tab_type)
{
unsigned tab_number = 0;
switch (tab_type) {
case XFE_COLOR_PICKER_SWATCHES:
tab_number = 0;
break;
case XFE_COLOR_PICKER_RGB:
tab_number = 1;
break;
case XFE_COLOR_PICKER_LAST:
tab_number = 0; /*FIXME*/
break;
}
XmLFolderSetActiveTab(folder, tab_number, False);
}
Widget
fe_CreateColorPickerDialog(Widget parent, char* name,
Arg* args, Cardinal nargs)
{
MWContext* context = (MWContext *)fe_WidgetToMWContext(parent);
Widget dialog;
Widget folder;
/*
* Make prompt with ok, cancel, no apply, no separator.
*/
dialog = fe_CreatePromptDialog(context, name,
TRUE, TRUE, FALSE, FALSE, TRUE);
folder = fe_CreateColorPicker(dialog, "colorPicker", args, nargs);
XtManageChild(folder);
return dialog;
}
void
fe_ColorPickerDialogGetColor(Widget dialog, LO_Color* color)
{
Widget folder = XtNameToWidget(dialog, "colorPicker");
fe_ColorPickerGetColor(folder, color);
}
void
fe_ColorPickerDialogSetColor(Widget dialog, LO_Color* color)
{
Widget folder = XtNameToWidget(dialog, "colorPicker");
fe_ColorPickerSetColor(folder, color);
}
void
fe_ColorPickerDialogSetActiveTab(Widget dialog, fe_ColorPickerTabType tab_type)
{
Widget folder = XtNameToWidget(dialog, "colorPicker");
fe_ColorPickerSetActiveTab(folder, tab_type);
}