1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 20:38:08 +01:00
Files
wmaker/WINGs/wcolorpanel.c
Christophe CURIS 58862300f9 WINGs: Fix invalid handling of Blue in the HSV conversion in ColorPanel widget
Because of a minor bug, when pure blue was chosen in RGB in the ColorPanel,
the conversion to HSV would mistreat it as white and resets its hue,
leading to possible user annoyance.
2021-05-18 17:49:17 +01:00

3559 lines
107 KiB
C

/*
* ColorPanel for WINGs
*
* by ]d : Original idea and basic initial code
* Pascal Hofstee : Code for wheeldrawing and calculating
* colors from it.
* Primary coder of this Color Panel.
* Alban Hertroys : Optimizations for algorithms for color-
* wheel. Also custom ColorPalettes and
* magnifying glass. Secondary coder ;)
* Alfredo K. Kojima : For pointing out memory-allocation
* problems and similair code-issues
* Marco van Hylckama-Vlieg : For once again doing the artwork ;-)
*
*/
/* TODO:
* - Look at further optimization of colorWheel matrix calculation.
* It appears to be rather symmetric in angles of 60 degrees,
* while it is optimized in angles of 90 degrees.
* - Custom color-lists and custom colors in custom color-lists.
* - Stored colors
* - Resizing
*/
#include "wconfig.h"
#include "WINGsP.h"
#include "rgb.h"
#include <errno.h>
#include <math.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
/* BUG There's something fishy with shaped windows */
/* Whithout shape extension the magnified image is completely broken -Dan */
#ifdef USE_XSHAPE
# include <X11/extensions/shape.h>
#endif
char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
/*
* Bitmaps for magnifying glass cursor
*/
/* Cursor */
#define Cursor_x_hot 11
#define Cursor_y_hot 11
#define Cursor_width 32
#define Cursor_height 32
static unsigned char Cursor_bits[] = {
0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
0x00, 0x08, 0x00, 0x50, 0x00, 0x10, 0x00, 0x88, 0x00, 0x20, 0x00, 0x5c, 0x01, 0xc0, 0x81,
0x3b, 0x02, 0x00, 0x7e, 0x70, 0x05, 0x00, 0x00, 0xe0, 0x08, 0x00, 0x00, 0xc0, 0x15, 0x00,
0x00, 0x80, 0x23, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x5c,
0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x70
};
static unsigned char Cursor_shape_bits[] = {
0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
0x00, 0x08, 0x00, 0x70, 0x00, 0x10, 0x00, 0xf8, 0x00, 0x20, 0x00, 0xfc, 0x01, 0xc0, 0x81,
0xfb, 0x03, 0x00, 0x7e, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xc0, 0x1f, 0x00,
0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfc,
0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x70
};
/* Clip-mask for magnified pixels */
#define Cursor_mask_width 24
#define Cursor_mask_height 24
static unsigned char Cursor_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00
};
typedef struct MovingView {
WMView *view; /* The view this is all about */
XImage *image; /* What's under the view */
XImage *dirtyRect; /* Storage of overlapped image area */
Pixmap magPix; /* Magnified part of pixmap */
RColor color; /* Color of a pixel in the image */
int x, y; /* Position of view */
} MovingView;
typedef struct CPColor {
RColor rgb; /* The RGB values of the color */
RHSVColor hsv; /* The HSV values of the color */
enum { /* Which one was last set ? */
cpNone,
cpRGB,
cpHSV
} set;
} CPColor;
typedef struct WheelMatrix {
unsigned int width, height; /* Size of the colorwheel */
unsigned char *data[3]; /* Wheel data (R,G,B) */
unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
} wheelMatrix;
typedef struct W_ColorPanel {
WMWindow *win;
WMFont *font8;
WMFont *font12;
void *clientData;
WMAction2 *action;
/* Common Stuff */
WMColorWell *colorWell;
WMButton *magnifyBtn;
WMButton *wheelBtn;
WMButton *slidersBtn;
WMButton *customPaletteBtn;
WMButton *colorListBtn;
/* Magnifying Glass */
MovingView *magnifyGlass;
/* ColorWheel Panel */
WMFrame *wheelFrm;
WMSlider *wheelBrightnessS;
WMView *wheelView;
/* Slider Panels */
WMFrame *slidersFrm;
WMFrame *seperatorFrm;
WMButton *grayBtn;
WMButton *rgbBtn;
WMButton *cmykBtn;
WMButton *hsbBtn;
/* Gray Scale Panel */
WMFrame *grayFrm;
WMLabel *grayMinL;
WMLabel *grayMaxL;
WMSlider *grayBrightnessS;
WMTextField *grayBrightnessT;
WMButton *grayPresetBtn[7];
/* RGB Panel */
WMButton *rgbDecB;
WMButton *rgbHexB;
WMFrame *rgbFrm;
WMLabel *rgbMinL;
WMLabel *rgbMaxL;
WMSlider *rgbRedS;
WMSlider *rgbGreenS;
WMSlider *rgbBlueS;
WMTextField *rgbRedT;
WMTextField *rgbGreenT;
WMTextField *rgbBlueT;
enum {
RGBdec,
RGBhex
} rgbState;
/* CMYK Panel */
WMFrame *cmykFrm;
WMLabel *cmykMinL;
WMLabel *cmykMaxL;
WMSlider *cmykCyanS;
WMSlider *cmykMagentaS;
WMSlider *cmykYellowS;
WMSlider *cmykBlackS;
WMTextField *cmykCyanT;
WMTextField *cmykMagentaT;
WMTextField *cmykYellowT;
WMTextField *cmykBlackT;
/* HSB Panel */
WMFrame *hsbFrm;
WMSlider *hsbHueS;
WMSlider *hsbSaturationS;
WMSlider *hsbBrightnessS;
WMTextField *hsbHueT;
WMTextField *hsbSaturationT;
WMTextField *hsbBrightnessT;
/* Custom Palette Panel */
WMFrame *customPaletteFrm;
WMPopUpButton *customPaletteHistoryBtn;
WMFrame *customPaletteContentFrm;
WMPopUpButton *customPaletteMenuBtn;
WMView *customPaletteContentView;
/* Color List Panel */
WMFrame *colorListFrm;
WMPopUpButton *colorListHistoryBtn;
WMList *colorListContentLst;
WMPopUpButton *colorListColorMenuBtn;
WMPopUpButton *colorListListMenuBtn;
/* Look-Up Tables and Images */
wheelMatrix *wheelMtrx;
Pixmap wheelImg;
Pixmap selectionImg;
Pixmap selectionBackImg;
RImage *customPaletteImg;
char *lastBrowseDir;
/* Common Data Fields */
CPColor color; /* Current color */
WMColorPanelMode mode; /* Current color selection mode */
WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
WMColorPanelMode lastChanged; /* Panel that last changed the color */
int colx, coly; /* (x,y) of sel.-marker in WheelMode */
int palx, paly; /* (x,y) of sel.-marker in
CustomPaletteMode */
double palXRatio, palYRatio; /* Ratios in x & y between
original and scaled
palettesize */
int currentPalette;
char *configurationPath;
struct {
unsigned int continuous:1;
unsigned int dragging:1;
} flags;
} W_ColorPanel;
enum {
CPmenuNewFromFile,
CPmenuRename,
CPmenuRemove,
CPmenuCopy,
CPmenuNewFromClipboard
} customPaletteMenuItem;
enum {
CLmenuAdd,
CLmenuRename,
CLmenuRemove
} colorListMenuItem;
#define PWIDTH 194
#define PHEIGHT 266
#define colorWheelSize 150
#define customPaletteWidth 182
#define customPaletteHeight 106
#define knobThickness 8
#define SPECTRUM_WIDTH 511
#define SPECTRUM_HEIGHT 360
#define COLORWHEEL_PART 1
#define CUSTOMPALETTE_PART 2
static char *generateNewFilename(const char *curName);
static void convertCPColor(CPColor * color);
static RColor ulongToRColor(WMScreen * scr, unsigned long value);
static unsigned char getShift(unsigned char value);
static void modeButtonCallback(WMWidget * w, void *data);
static int getPickerPart(W_ColorPanel * panel, int x, int y);
static void readConfiguration(W_ColorPanel * panel);
static void readXColors(W_ColorPanel * panel);
static void closeWindowCallback(WMWidget * w, void *data);
static Cursor magnifyGrabPointer(W_ColorPanel * panel);
static WMPoint magnifyInitialize(W_ColorPanel * panel);
static void magnifyPutCursor(WMWidget * w, void *data);
static Pixmap magnifyCreatePixmap(WMColorPanel * panel);
static void magnifyGetImageStored(W_ColorPanel * panel, int x1, int y1, int x2, int y2);
static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h);
static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height);
static void wheelDestroyMatrix(wheelMatrix * matrix);
static void wheelInitMatrix(W_ColorPanel * panel);
static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue);
static void wheelRender(W_ColorPanel * panel);
static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs);
static void wheelPaint(W_ColorPanel * panel);
static void wheelHandleEvents(XEvent * event, void *data);
static void wheelHandleActionEvents(XEvent * event, void *data);
static void wheelBrightnessSliderCallback(WMWidget * w, void *data);
static void wheelUpdateSelection(W_ColorPanel * panel);
static void wheelUndrawSelection(W_ColorPanel * panel);
static void wheelPositionSelection(W_ColorPanel * panel, int x, int y);
static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel);
static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor);
static void grayBrightnessSliderCallback(WMWidget * w, void *data);
static void grayPresetButtonCallback(WMWidget * w, void *data);
static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification);
static void rgbSliderCallback(WMWidget * w, void *data);
static void rgbTextFieldCallback(void *observerData, WMNotification * notification);
static void rgbDecToHex(WMWidget *w, void *data);
static void cmykSliderCallback(WMWidget * w, void *data);
static void cmykTextFieldCallback(void *observerData, WMNotification * notification);
static void hsbSliderCallback(WMWidget * w, void *data);
static void hsbTextFieldCallback(void *observerData, WMNotification * notification);
static void hsbUpdateBrightnessGradient(W_ColorPanel * panel);
static void hsbUpdateSaturationGradient(W_ColorPanel * panel);
static void hsbUpdateHueGradient(W_ColorPanel * panel);
static void customRenderSpectrum(W_ColorPanel * panel);
static void customSetPalette(W_ColorPanel * panel);
static void customPaletteHandleEvents(XEvent * event, void *data);
static void customPaletteHandleActionEvents(XEvent * event, void *data);
static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y);
static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
static void customPaletteMenuCallback(WMWidget * w, void *data);
static void customPaletteHistoryCallback(WMWidget * w, void *data);
static void customPaletteMenuNewFromFile(W_ColorPanel * panel);
static void customPaletteMenuRename(W_ColorPanel * panel);
static void customPaletteMenuRemove(W_ColorPanel * panel);
static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect);
static void colorListSelect(WMWidget * w, void *data);
static void colorListColorMenuCallback(WMWidget * w, void *data);
static void colorListListMenuCallback(WMWidget * w, void *data);
static void wheelInit(W_ColorPanel * panel);
static void grayInit(W_ColorPanel * panel);
static void rgbInit(W_ColorPanel * panel);
static void cmykInit(W_ColorPanel * panel);
static void hsbInit(W_ColorPanel * panel);
static inline int get_textfield_as_integer(WMTextField *widget)
{
char *str;
int value;
str = WMGetTextFieldText(widget);
value = atoi(str);
wfree(str);
return value;
}
void WMSetColorPanelAction(WMColorPanel * panel, WMAction2 * action, void *data)
{
panel->action = action;
panel->clientData = data;
}
static WMColorPanel *makeColorPanel(WMScreen * scrPtr, const char *name)
{
WMColorPanel *panel;
RImage *image;
WMPixmap *pixmap;
RColor from;
RColor to;
WMColor *textcolor, *graybuttoncolor;
int i;
GC bgc = WMColorGC(scrPtr->black);
GC wgc = WMColorGC(scrPtr->white);
panel = wmalloc(sizeof(WMColorPanel));
panel->color.rgb.red = 0;
panel->color.rgb.green = 0;
panel->color.rgb.blue = 0;
panel->color.hsv.hue = 0;
panel->color.hsv.saturation = 0;
panel->color.hsv.value = 0;
panel->color.set = cpNone; /* Color has not been set yet */
panel->font8 = WMSystemFontOfSize(scrPtr, 8);
panel->font12 = WMSystemFontOfSize(scrPtr, 12);
panel->win = WMCreateWindowWithStyle(scrPtr, name,
WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
WMSetWindowTitle(panel->win, _("Colors"));
WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
/* Set Default ColorPanel Mode(s) */
panel->mode = WMWheelModeColorPanel;
panel->lastChanged = 0;
panel->slidersmode = WMRGBModeColorPanel;
panel->configurationPath = wstrconcat(wusergnusteppath(), "/Library/Colors/");
/* Some General Purpose Widgets */
panel->colorWell = WMCreateColorWell(panel->win);
WMResizeWidget(panel->colorWell, 134, 36);
WSetColorWellBordered(panel->colorWell, False);
WMMoveWidget(panel->colorWell, 56, 4);
panel->magnifyBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
WMResizeWidget(panel->magnifyBtn, 46, 36);
WMMoveWidget(panel->magnifyBtn, 6, 4);
WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
panel->wheelBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
WMResizeWidget(panel->wheelBtn, 46, 32);
WMMoveWidget(panel->wheelBtn, 6, 44);
WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
panel->slidersBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
WMResizeWidget(panel->slidersBtn, 46, 32);
WMMoveWidget(panel->slidersBtn, 52, 44);
WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
panel->customPaletteBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
WMResizeWidget(panel->customPaletteBtn, 46, 32);
WMMoveWidget(panel->customPaletteBtn, 98, 44);
WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
panel->colorListBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
WMResizeWidget(panel->colorListBtn, 46, 32);
WMMoveWidget(panel->colorListBtn, 144, 44);
WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
/* Let's Group some of them together */
WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
/* Widgets for the ColorWheel Panel */
panel->wheelFrm = WMCreateFrame(panel->win);
WMSetFrameRelief(panel->wheelFrm, WRFlat);
WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
WMMoveWidget(panel->wheelFrm, 5, 80);
panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
/* XXX Can we create a view ? */
W_ResizeView(panel->wheelView, colorWheelSize + 4, colorWheelSize + 4);
W_MoveView(panel->wheelView, 0, 0);
/* Create an event handler to handle expose/click events in ColorWheel */
WMCreateEventHandler(panel->wheelView,
ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
LeaveWindowMask | ButtonMotionMask, wheelHandleActionEvents, panel);
WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents, panel);
panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
WMResizeWidget(panel->wheelBrightnessS, 16, 153);
WMMoveWidget(panel->wheelBrightnessS, 5 + colorWheelSize + 14, 1);
WMSetSliderMinValue(panel->wheelBrightnessS, 0);
WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback, panel);
WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
panel->wheelMtrx = wheelCreateMatrix(colorWheelSize + 4, colorWheelSize + 4);
wheelInitMatrix(panel);
/* Widgets for the Slider Panels */
panel->slidersFrm = WMCreateFrame(panel->win);
WMSetFrameRelief(panel->slidersFrm, WRFlat);
WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
WMMoveWidget(panel->slidersFrm, 4, 80);
panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
WMSetFrameRelief(panel->seperatorFrm, WRPushed);
WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
WMMoveWidget(panel->seperatorFrm, 0, 1);
panel->grayBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
WMResizeWidget(panel->grayBtn, 46, 24);
WMMoveWidget(panel->grayBtn, 1, 8);
WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
WMResizeWidget(panel->rgbBtn, 46, 24);
WMMoveWidget(panel->rgbBtn, 47, 8);
WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
WMResizeWidget(panel->cmykBtn, 46, 24);
WMMoveWidget(panel->cmykBtn, 93, 8);
WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
WMResizeWidget(panel->hsbBtn, 46, 24);
WMMoveWidget(panel->hsbBtn, 139, 8);
WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
/* Let's Group the Slider Panel Buttons Together */
WMGroupButtons(panel->grayBtn, panel->rgbBtn);
WMGroupButtons(panel->grayBtn, panel->cmykBtn);
WMGroupButtons(panel->grayBtn, panel->hsbBtn);
textcolor = WMDarkGrayColor(scrPtr);
/* Widgets for GrayScale Panel */
panel->grayFrm = WMCreateFrame(panel->slidersFrm);
WMSetFrameRelief(panel->grayFrm, WRFlat);
WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
WMMoveWidget(panel->grayFrm, 0, 34);
panel->grayMinL = WMCreateLabel(panel->grayFrm);
WMResizeWidget(panel->grayMinL, 20, 10);
WMMoveWidget(panel->grayMinL, 2, 2);
WMSetLabelText(panel->grayMinL, "0");
WMSetLabelTextAlignment(panel->grayMinL, WALeft);
WMSetLabelTextColor(panel->grayMinL, textcolor);
WMSetLabelFont(panel->grayMinL, panel->font8);
panel->grayMaxL = WMCreateLabel(panel->grayFrm);
WMResizeWidget(panel->grayMaxL, 40, 10);
WMMoveWidget(panel->grayMaxL, 104, 2);
WMSetLabelText(panel->grayMaxL, "100");
WMSetLabelTextAlignment(panel->grayMaxL, WARight);
WMSetLabelTextColor(panel->grayMaxL, textcolor);
WMSetLabelFont(panel->grayMaxL, panel->font8);
panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
WMResizeWidget(panel->grayBrightnessS, 141, 16);
WMMoveWidget(panel->grayBrightnessS, 2, 14);
WMSetSliderMinValue(panel->grayBrightnessS, 0);
WMSetSliderMaxValue(panel->grayBrightnessS, 100);
WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback, panel);
from.red = 0;
from.green = 0;
from.blue = 0;
to.red = 255;
to.green = 255;
to.blue = 255;
image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
RReleaseImage(image);
if (pixmap)
W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
panel->font12, 2, 0, 100, WALeft, scrPtr->white,
False, _("Brightness"), strlen(_("Brightness")));
else
wwarning(_("Color Panel: Could not allocate memory"));
WMSetSliderImage(panel->grayBrightnessS, pixmap);
WMReleasePixmap(pixmap);
panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
WMResizeWidget(panel->grayBrightnessT, 40, 18);
WMMoveWidget(panel->grayBrightnessT, 146, 13);
WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->grayBrightnessT);
for (i = 0; i < 7; i++) {
pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
graybuttoncolor = WMCreateRGBColor(scrPtr, (255 / 6) * i << 8,
(255 / 6) * i << 8, (255 / 6) * i << 8, True);
WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
WMReleaseColor(graybuttoncolor);
panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
WMMoveWidget(panel->grayPresetBtn[i], 2 + (i * 20), 34);
WMSetButtonAction(panel->grayPresetBtn[i], grayPresetButtonCallback, panel);
WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
WMReleasePixmap(pixmap);
}
/* End of GrayScale Panel */
/* Widgets for RGB Panel */
panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
WMSetFrameRelief(panel->rgbFrm, WRFlat);
WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
WMMoveWidget(panel->rgbFrm, 0, 34);
panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
WMResizeWidget(panel->rgbMinL, 20, 10);
WMMoveWidget(panel->rgbMinL, 2, 2);
WMSetLabelText(panel->rgbMinL, "0");
WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
WMSetLabelTextColor(panel->rgbMinL, textcolor);
WMSetLabelFont(panel->rgbMinL, panel->font8);
panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
WMResizeWidget(panel->rgbMaxL, 40, 10);
WMMoveWidget(panel->rgbMaxL, 104, 2);
WMSetLabelText(panel->rgbMaxL, "255");
WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
WMSetLabelTextColor(panel->rgbMaxL, textcolor);
WMSetLabelFont(panel->rgbMaxL, panel->font8);
panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
WMResizeWidget(panel->rgbRedS, 141, 16);
WMMoveWidget(panel->rgbRedS, 2, 14);
WMSetSliderMinValue(panel->rgbRedS, 0);
WMSetSliderMaxValue(panel->rgbRedS, 255);
WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
to.red = 255;
to.green = 0;
to.blue = 0;
image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
RReleaseImage(image);
if (pixmap)
W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
2, 0, 100, WALeft, scrPtr->white, False, _("Red"), strlen(_("Red")));
else
wwarning(_("Color Panel: Could not allocate memory"));
WMSetSliderImage(panel->rgbRedS, pixmap);
WMReleasePixmap(pixmap);
panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
WMResizeWidget(panel->rgbRedT, 40, 18);
WMMoveWidget(panel->rgbRedT, 146, 13);
WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbRedT);
panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
WMResizeWidget(panel->rgbGreenS, 141, 16);
WMMoveWidget(panel->rgbGreenS, 2, 36);
WMSetSliderMinValue(panel->rgbGreenS, 0);
WMSetSliderMaxValue(panel->rgbGreenS, 255);
WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
to.red = 0;
to.green = 255;
to.blue = 0;
image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
RReleaseImage(image);
if (pixmap)
W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
2, 0, 100, WALeft, scrPtr->white, False, _("Green"), strlen(_("Green")));
else
wwarning(_("Color Panel: Could not allocate memory"));
WMSetSliderImage(panel->rgbGreenS, pixmap);
WMReleasePixmap(pixmap);
panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
WMResizeWidget(panel->rgbGreenT, 40, 18);
WMMoveWidget(panel->rgbGreenT, 146, 35);
WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbGreenT);
panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
WMResizeWidget(panel->rgbBlueS, 141, 16);
WMMoveWidget(panel->rgbBlueS, 2, 58);
WMSetSliderMinValue(panel->rgbBlueS, 0);
WMSetSliderMaxValue(panel->rgbBlueS, 255);
WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
to.red = 0;
to.green = 0;
to.blue = 255;
image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
RReleaseImage(image);
if (pixmap)
W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
2, 0, 100, WALeft, scrPtr->white, False, _("Blue"), strlen(_("Blue")));
else
wwarning(_("Color Panel: Could not allocate memory"));
WMSetSliderImage(panel->rgbBlueS, pixmap);
WMReleasePixmap(pixmap);
panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
WMResizeWidget(panel->rgbBlueT, 40, 18);
WMMoveWidget(panel->rgbBlueT, 146, 57);
WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbBlueT);
panel->rgbDecB = WMCreateButton(panel->rgbFrm, WBTRadio);
WMSetButtonText(panel->rgbDecB, _("Decimal"));
WMSetButtonSelected(panel->rgbDecB, 1);
panel->rgbState = RGBdec;
WMSetButtonAction(panel->rgbDecB, rgbDecToHex, panel);
WMResizeWidget(panel->rgbDecB, PWIDTH - 8, 23);
WMMoveWidget(panel->rgbDecB, 2, 81);
panel->rgbHexB = WMCreateButton(panel->rgbFrm, WBTRadio);
WMSetButtonText(panel->rgbHexB, _("Hexadecimal"));
WMSetButtonAction(panel->rgbHexB, rgbDecToHex, panel);
WMResizeWidget(panel->rgbHexB, PWIDTH - 8, 23);
WMMoveWidget(panel->rgbHexB, 2, 104);
WMGroupButtons(panel->rgbDecB, panel->rgbHexB);
/* End of RGB Panel */
/* Widgets for CMYK Panel */
panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
WMSetFrameRelief(panel->cmykFrm, WRFlat);
WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
WMMoveWidget(panel->cmykFrm, 0, 34);
panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
WMResizeWidget(panel->cmykMinL, 20, 10);
WMMoveWidget(panel->cmykMinL, 2, 2);
WMSetLabelText(panel->cmykMinL, "0");
WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
WMSetLabelTextColor(panel->cmykMinL, textcolor);
WMSetLabelFont(panel->cmykMinL, panel->font8);
panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
WMResizeWidget(panel->cmykMaxL, 40, 10);
WMMoveWidget(panel->cmykMaxL, 104, 2);
WMSetLabelText(panel->cmykMaxL, "100");
WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
WMSetLabelTextColor(panel->cmykMaxL, textcolor);
WMSetLabelFont(panel->cmykMaxL, panel->font8);
panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
WMResizeWidget(panel->cmykCyanS, 141, 16);
WMMoveWidget(panel->cmykCyanS, 2, 14);
WMSetSliderMinValue(panel->cmykCyanS, 0);
WMSetSliderMaxValue(panel->cmykCyanS, 100);
WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
from.red = 255;
from.green = 255;
from.blue = 255;
to.red = 0;
to.green = 255;
to.blue = 255;
image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
RReleaseImage(image);
if (pixmap)
W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"), strlen(_("Cyan")));
else
wwarning(_("Color Panel: Could not allocate memory"));
WMSetSliderImage(panel->cmykCyanS, pixmap);
WMReleasePixmap(pixmap);
panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
WMResizeWidget(panel->cmykCyanT, 40, 18);
WMMoveWidget(panel->cmykCyanT, 146, 13);
WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
WMAddNotificationObserver(cmykTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->cmykCyanT);
panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
WMResizeWidget(panel->cmykMagentaS, 141, 16);
WMMoveWidget(panel->cmykMagentaS, 2, 36);
WMSetSliderMinValue(panel->cmykMagentaS, 0);
WMSetSliderMaxValue(panel->cmykMagentaS, 100);
WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
to.red = 255;
to.green = 0;
to.blue = 255;
image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
RReleaseImage(image);
if (pixmap)
W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"), strlen(_("Magenta")));
else
wwarning(_("Color Panel: Could not allocate memory"));
WMSetSliderImage(panel->cmykMagentaS, pixmap);
WMReleasePixmap(pixmap);
panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
WMResizeWidget(panel->cmykMagentaT, 40, 18);
WMMoveWidget(panel->cmykMagentaT, 146, 35);
WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
WMAddNotificationObserver(cmykTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->cmykMagentaT);
panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
WMResizeWidget(panel->cmykYellowS, 141, 16);
WMMoveWidget(panel->cmykYellowS, 2, 58);
WMSetSliderMinValue(panel->cmykYellowS, 0);
WMSetSliderMaxValue(panel->cmykYellowS, 100);
WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
to.red = 255;
to.green = 255;
to.blue = 0;
image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
RReleaseImage(image);
if (pixmap)
W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"), strlen(_("Yellow")));
else
wwarning(_("Color Panel: Could not allocate memory"));
WMSetSliderImage(panel->cmykYellowS, pixmap);
WMReleasePixmap(pixmap);
panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
WMResizeWidget(panel->cmykYellowT, 40, 18);
WMMoveWidget(panel->cmykYellowT, 146, 57);
WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
WMAddNotificationObserver(cmykTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->cmykYellowT);
panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
WMResizeWidget(panel->cmykBlackS, 141, 16);
WMMoveWidget(panel->cmykBlackS, 2, 80);
WMSetSliderMinValue(panel->cmykBlackS, 0);
WMSetSliderMaxValue(panel->cmykBlackS, 100);
WMSetSliderValue(panel->cmykBlackS, 0);
WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
to.red = 0;
to.green = 0;
to.blue = 0;
image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
RReleaseImage(image);
if (pixmap)
W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
2, 0, 100, WALeft, scrPtr->black, False, _("Black"), strlen(_("Black")));
else
wwarning(_("Color Panel: Could not allocate memory"));
WMSetSliderImage(panel->cmykBlackS, pixmap);
WMReleasePixmap(pixmap);
panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
WMResizeWidget(panel->cmykBlackT, 40, 18);
WMMoveWidget(panel->cmykBlackT, 146, 79);
WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
WMAddNotificationObserver(cmykTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->cmykBlackT);
/* End of CMYK Panel */
/* Widgets for HSB Panel */
panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
WMSetFrameRelief(panel->hsbFrm, WRFlat);
WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
WMMoveWidget(panel->hsbFrm, 0, 34);
panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
WMResizeWidget(panel->hsbHueS, 141, 16);
WMMoveWidget(panel->hsbHueS, 2, 14);
WMSetSliderMinValue(panel->hsbHueS, 0);
WMSetSliderMaxValue(panel->hsbHueS, 359);
WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
WMResizeWidget(panel->hsbHueT, 40, 18);
WMMoveWidget(panel->hsbHueT, 146, 13);
WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
WMAddNotificationObserver(hsbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->hsbHueT);
panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
WMResizeWidget(panel->hsbSaturationS, 141, 16);
WMMoveWidget(panel->hsbSaturationS, 2, 36);
WMSetSliderMinValue(panel->hsbSaturationS, 0);
WMSetSliderMaxValue(panel->hsbSaturationS, 100);
WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
WMResizeWidget(panel->hsbSaturationT, 40, 18);
WMMoveWidget(panel->hsbSaturationT, 146, 35);
WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
WMAddNotificationObserver(hsbTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->hsbSaturationT);
panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
WMResizeWidget(panel->hsbBrightnessS, 141, 16);
WMMoveWidget(panel->hsbBrightnessS, 2, 58);
WMSetSliderMinValue(panel->hsbBrightnessS, 0);
WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
WMResizeWidget(panel->hsbBrightnessT, 40, 18);
WMMoveWidget(panel->hsbBrightnessT, 146, 57);
WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
WMAddNotificationObserver(hsbTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->hsbBrightnessT);
/* End of HSB Panel */
WMReleaseColor(textcolor);
/* Widgets for the CustomPalette Panel */
panel->customPaletteFrm = WMCreateFrame(panel->win);
WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
WMMoveWidget(panel->customPaletteFrm, 5, 80);
panel->customPaletteHistoryBtn = WMCreatePopUpButton(panel->customPaletteFrm);
WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1);
WMSetPopUpButtonAction(panel->customPaletteHistoryBtn, customPaletteHistoryCallback, panel);
WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
panel->customPaletteContentView = W_CreateView(W_VIEW(panel->customPaletteContentFrm));
/* XXX Test if we can create a view */
W_ResizeView(panel->customPaletteContentView, customPaletteWidth, customPaletteHeight);
W_MoveView(panel->customPaletteContentView, 2, 2);
/* Create event handler to handle expose/click events in CustomPalette */
WMCreateEventHandler(panel->customPaletteContentView,
ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
ButtonMotionMask, customPaletteHandleActionEvents, panel);
WMCreateEventHandler(panel->customPaletteContentView, ExposureMask, customPaletteHandleEvents, panel);
panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
WMSetPopUpButtonAction(panel->customPaletteMenuBtn, customPaletteMenuCallback, panel);
WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuNewFromClipboard, 0);
customRenderSpectrum(panel);
panel->currentPalette = 0;
panel->palx = customPaletteWidth / 2;
panel->paly = customPaletteHeight / 2;
/* Widgets for the ColorList Panel */
panel->colorListFrm = WMCreateFrame(panel->win);
WMSetFrameRelief(panel->colorListFrm, WRFlat);
WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
WMMoveWidget(panel->colorListFrm, 5, 80);
panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn) - 1);
/* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
* colorListHistoryCallback, panel); */
WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
panel->colorListContentLst = WMCreateList(panel->colorListFrm);
WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
WMMoveWidget(panel->colorListContentLst, 0, 23);
WMHangData(panel->colorListContentLst, panel);
panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
WMSetPopUpButtonAction(panel->colorListColorMenuBtn, colorListColorMenuCallback, panel);
WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16) / 2, 20);
WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
WMSetPopUpButtonAction(panel->colorListListMenuBtn, colorListListMenuCallback, panel);
WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2, 20);
WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2 + 8, PHEIGHT - 130);
WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
WMRealizeWidget(panel->win);
WMMapSubwidgets(panel->win);
WMMapSubwidgets(panel->wheelFrm);
WMMapSubwidgets(panel->slidersFrm);
WMMapSubwidgets(panel->grayFrm);
WMMapSubwidgets(panel->rgbFrm);
WMMapSubwidgets(panel->cmykFrm);
WMMapSubwidgets(panel->hsbFrm);
WMMapSubwidgets(panel->customPaletteFrm);
WMMapSubwidgets(panel->customPaletteContentFrm);
WMMapSubwidgets(panel->colorListFrm);
/* Pixmap to indicate selection positions
* wheelframe MUST be mapped.
*/
panel->selectionImg = XCreatePixmap(scrPtr->display, WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
readConfiguration(panel);
readXColors(panel);
return panel;
}
WMColorPanel *WMGetColorPanel(WMScreen * scrPtr)
{
WMColorPanel *panel;
if (scrPtr->sharedColorPanel)
return scrPtr->sharedColorPanel;
panel = makeColorPanel(scrPtr, "colorPanel");
scrPtr->sharedColorPanel = panel;
return panel;
}
void WMFreeColorPanel(WMColorPanel * panel)
{
W_Screen *scr;
if (!panel)
return;
scr = WMWidgetScreen(panel->win);
if (panel == scr->sharedColorPanel) {
scr->sharedColorPanel = NULL;
}
WMRemoveNotificationObserver(panel);
WMUnmapWidget(panel->win);
/* fonts */
WMReleaseFont(panel->font8);
WMReleaseFont(panel->font12);
/* pixmaps */
wheelDestroyMatrix(panel->wheelMtrx);
if (panel->wheelImg)
XFreePixmap(scr->display, panel->wheelImg);
if (panel->selectionImg)
XFreePixmap(scr->display, panel->selectionImg);
if (panel->selectionBackImg)
XFreePixmap(scr->display, panel->selectionBackImg);
RReleaseImage(panel->customPaletteImg);
/* structs */
if (panel->lastBrowseDir)
wfree(panel->lastBrowseDir);
if (panel->configurationPath)
wfree(panel->configurationPath);
WMDestroyWidget(panel->win);
wfree(panel);
}
void WMCloseColorPanel(WMColorPanel * panel)
{
WMFreeColorPanel(panel);
}
void WMShowColorPanel(WMColorPanel * panel)
{
WMScreen *scr = WMWidgetScreen(panel->win);
WMColor *white = WMWhiteColor(scr);
if (panel->color.set == cpNone)
WMSetColorPanelColor(panel, white);
WMReleaseColor(white);
if (panel->mode != WMWheelModeColorPanel)
WMPerformButtonClick(panel->wheelBtn);
WMMapWidget(panel->win);
}
static void closeWindowCallback(WMWidget * w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *) data;
/* Parameter not used, but tell the compiler that it is ok */
(void) w;
WMCloseColorPanel(panel);
}
static void readConfiguration(W_ColorPanel * panel)
{
/* XXX Doesn't take care of "invalid" files */
DIR *dPtr;
struct dirent *dp;
struct stat stat_buf;
int item;
if (stat(panel->configurationPath, &stat_buf) != 0) {
if (mkdir(panel->configurationPath, S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH) != 0) {
werror(_("Color Panel: Could not create directory %s needed"
" to store configurations"), panel->configurationPath);
WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
_("File Error"),
_("Could not create ColorPanel configuration directory"),
_("OK"), NULL, NULL);
}
return;
}
if (!(dPtr = opendir(panel->configurationPath))) {
wwarning("%s: %s", _("Color Panel: Could not find file"), panel->configurationPath);
return;
}
while ((dp = readdir(dPtr)) != NULL) {
unsigned int perm_mask;
char *path = wstrconcat(panel->configurationPath,
dp->d_name);
if (dp->d_name[0] != '.') {
item = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
perm_mask = (access(path, R_OK) == 0);
WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn, item, perm_mask);
}
wfree(path);
}
closedir(dPtr);
}
static void readXColors(W_ColorPanel * panel)
{
WMListItem *item;
const RGBColor *entry;
for (entry = rgbColors; entry->name != NULL; entry++) {
item = WMAddListItem(panel->colorListContentLst, entry->name);
item->clientData = (void *)&(entry->color);
}
}
void WMSetColorPanelPickerMode(WMColorPanel * panel, WMColorPanelMode mode)
{
W_Screen *scr = WMWidgetScreen(panel->win);
if (mode != WMWheelModeColorPanel) {
WMUnmapWidget(panel->wheelFrm);
if (panel->selectionBackImg) {
XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
panel->selectionBackImg = None;
}
}
if (mode != WMGrayModeColorPanel)
WMUnmapWidget(panel->grayFrm);
if (mode != WMRGBModeColorPanel)
WMUnmapWidget(panel->rgbFrm);
if (mode != WMCMYKModeColorPanel)
WMUnmapWidget(panel->cmykFrm);
if (mode != WMHSBModeColorPanel)
WMUnmapWidget(panel->hsbFrm);
if (mode != WMCustomPaletteModeColorPanel) {
WMUnmapWidget(panel->customPaletteFrm);
if (panel->selectionBackImg) {
XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
panel->selectionBackImg = None;
}
}
if (mode != WMColorListModeColorPanel)
WMUnmapWidget(panel->colorListFrm);
if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
(mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
WMUnmapWidget(panel->slidersFrm);
else
panel->slidersmode = mode;
if (mode == WMWheelModeColorPanel) {
WMMapWidget(panel->wheelFrm);
WMSetButtonSelected(panel->wheelBtn, True);
if (panel->lastChanged != WMWheelModeColorPanel)
wheelInit(panel);
wheelRender(panel);
wheelPaint(panel);
} else if (mode == WMGrayModeColorPanel) {
WMMapWidget(panel->slidersFrm);
WMSetButtonSelected(panel->slidersBtn, True);
WMMapWidget(panel->grayFrm);
WMSetButtonSelected(panel->grayBtn, True);
WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
if (panel->lastChanged != WMGrayModeColorPanel)
grayInit(panel);
} else if (mode == WMRGBModeColorPanel) {
WMMapWidget(panel->slidersFrm);
WMSetButtonSelected(panel->slidersBtn, True);
WMMapWidget(panel->rgbFrm);
WMSetButtonSelected(panel->rgbBtn, True);
WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
if (panel->lastChanged != WMRGBModeColorPanel)
rgbInit(panel);
} else if (mode == WMCMYKModeColorPanel) {
WMMapWidget(panel->slidersFrm);
WMSetButtonSelected(panel->slidersBtn, True);
WMMapWidget(panel->cmykFrm);
WMSetButtonSelected(panel->cmykBtn, True);
WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
if (panel->lastChanged != WMCMYKModeColorPanel)
cmykInit(panel);
} else if (mode == WMHSBModeColorPanel) {
WMMapWidget(panel->slidersFrm);
WMSetButtonSelected(panel->slidersBtn, True);
WMMapWidget(panel->hsbFrm);
WMSetButtonSelected(panel->hsbBtn, True);
WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
if (panel->lastChanged != WMHSBModeColorPanel)
hsbInit(panel);
} else if (mode == WMCustomPaletteModeColorPanel) {
WMMapWidget(panel->customPaletteFrm);
WMSetButtonSelected(panel->customPaletteBtn, True);
customSetPalette(panel);
} else if (mode == WMColorListModeColorPanel) {
WMMapWidget(panel->colorListFrm);
WMSetButtonSelected(panel->colorListBtn, True);
}
panel->mode = mode;
}
WMColor *WMGetColorPanelColor(WMColorPanel * panel)
{
return WMGetColorWellColor(panel->colorWell);
}
void WMSetColorPanelColor(WMColorPanel * panel, WMColor * color)
{
WMSetColorWellColor(panel->colorWell, color);
panel->color.rgb.red = color->color.red >> 8;
panel->color.rgb.green = color->color.green >> 8;
panel->color.rgb.blue = color->color.blue >> 8;
panel->color.set = cpRGB;
if (panel->mode == panel->lastChanged)
panel->lastChanged = 0;
WMSetColorPanelPickerMode(panel, panel->mode);
}
static void updateSwatch(WMColorPanel * panel, CPColor color)
{
WMScreen *scr = WMWidgetScreen(panel->win);
WMColor *wellcolor;
if (color.set != cpRGB)
convertCPColor(&color);
panel->color = color;
wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8, color.rgb.green << 8, color.rgb.blue << 8, True);
WMSetColorWellColor(panel->colorWell, wellcolor);
WMReleaseColor(wellcolor);
if (!panel->flags.dragging || panel->flags.continuous) {
if (panel->action)
(*panel->action) (panel, panel->clientData);
WMPostNotificationName(WMColorPanelColorChangedNotification, panel, NULL);
}
}
static void modeButtonCallback(WMWidget * w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *) (data);
if (w == panel->wheelBtn)
WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
else if (w == panel->slidersBtn)
WMSetColorPanelPickerMode(panel, panel->slidersmode);
else if (w == panel->customPaletteBtn)
WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
else if (w == panel->colorListBtn)
WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
else if (w == panel->grayBtn)
WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
else if (w == panel->rgbBtn)
WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
else if (w == panel->cmykBtn)
WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
else if (w == panel->hsbBtn)
WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
}
/****************** Magnifying Cursor Functions *******************/
static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h)
{
int x0 = 0, y0 = 0, w0 = w, h0 = h;
const int displayWidth = DisplayWidth(scr->display, scr->screen),
displayHeight = DisplayHeight(scr->display, scr->screen);
if (!(image && image->data)) {
/* The image in panel->magnifyGlass->image does not exist yet.
* Grab one from the screen (not beyond) and use it from now on.
*/
if (!(image = XGetImage(scr->display, scr->rootWin,
x - Cursor_x_hot, y - Cursor_y_hot, w, h, AllPlanes, ZPixmap)))
wwarning(_("Color Panel: X failed request"));
return image;
}
/* Coordinate correction for back pixmap
* if magnifying glass is at screen-borders
*/
/* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
* Hatched area is beyond screen border.
*
* |<-Cursor_x_hot->|
* ________________|_____
* |/ / / / / / /| | |
* | / / / / / / |(x,y) |
* |/_/_/_/_/_/_/|________|
* |<----x0----->|<--w0-->|
* 0
*/
/* Figure 2: Shifting of rectangle-to-grab at bottom/right
* screen borders
* Hatched area is beyond screen border
*
* |<-Cursor_x_hot->|
* ________________|_______________
* | | | / / / / / /|
* | (x,y)|/ / / / / / |
* |___________________|_/_/_/_/_/_/|
* |<-------w0-------->| |
* |<---------------w--|----------->|
* | |
* x0 Displaywidth-1
*/
if (x < Cursor_x_hot) { /* see fig. 1 */
x0 = Cursor_x_hot - x;
w0 = w - x0;
}
if (displayWidth - 1 < x - Cursor_x_hot + w) { /* see fig. 2 */
w0 = (displayWidth) - (x - Cursor_x_hot);
}
if (y < Cursor_y_hot) { /* see fig. 1 */
y0 = Cursor_y_hot - y;
h0 = h - y0;
}
if (displayHeight - 1 < y - Cursor_y_hot + h) { /* see fig. 2 */
h0 = (displayHeight) - (y - Cursor_y_hot);
}
/* end of coordinate correction */
/* Grab an image from the screen, clipped if necessary,
* and put it in the existing panel->magnifyGlass->image
* with the corresponding clipping offset.
*/
if (!XGetSubImage(scr->display, scr->rootWin,
x - Cursor_x_hot + x0, y - Cursor_y_hot + y0, w0, h0, AllPlanes, ZPixmap, image, x0, y0))
wwarning(_("Color Panel: X failed request"));
return NULL;
}
static void magnifyGetImageStored(WMColorPanel * panel, int x1, int y1, int x2, int y2)
{
/* (x1, y1) = topleft corner of existing rectangle
* (x2, y2) = topleft corner of new position
*/
W_Screen *scr = WMWidgetScreen(panel->win);
int xa = 0, ya = 0, xb = 0, yb = 0;
int width, height;
const int dx = abs(x2 - x1), dy = abs(y2 - y1);
XImage *image;
const int x_min = Cursor_x_hot,
y_min = Cursor_y_hot,
x_max = DisplayWidth(scr->display, scr->screen) - 1 -
(Cursor_mask_width - Cursor_x_hot),
y_max = DisplayHeight(scr->display, scr->screen) - 1 - (Cursor_mask_height - Cursor_y_hot);
if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
return; /* No movement */
if (x1 < x2)
xa = dx;
else
xb = dx;
if (y1 < y2)
ya = dy;
else
yb = dy;
width = Cursor_mask_width - dx;
height = Cursor_mask_height - dy;
/* If the traversed distance is larger than the size of the magnifying
* glass contents, there is no need to do dirty rectangles. A whole new
* rectangle can be grabbed (unless that rectangle falls partially
* off screen).
* Destroying the image and setting it to NULL will achieve that later on.
*
* Of course, grabbing an XImage beyond the borders of the screen will
* cause trouble, this is considdered a special case. Part of the screen
* is grabbed, but there is no need for dirty rectangles.
*/
if ((width <= 0) || (height <= 0)) {
if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
if (panel->magnifyGlass->image)
XDestroyImage(panel->magnifyGlass->image);
panel->magnifyGlass->image = NULL;
}
} else {
if (panel->magnifyGlass->image) {
/* Get dirty rectangle from panel->magnifyGlass->image */
panel->magnifyGlass->dirtyRect =
XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
if (!panel->magnifyGlass->dirtyRect) {
wwarning(_("Color Panel: X failed request"));
return; /* X returned a NULL from XSubImage */
}
}
}
/* Get image from screen */
image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2, Cursor_mask_width, Cursor_mask_height);
if (image) { /* Only reassign if a *new* image was grabbed */
panel->magnifyGlass->image = image;
return;
}
/* Copy previously stored rectangle on covered part of image */
if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
int old_height;
/* "width" and "height" are used as coordinates here,
* and run from [0...width-1] and [0...height-1] respectively.
*/
width--;
height--;
old_height = height;
for (; width >= 0; width--)
for (height = old_height; height >= 0; height--)
XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
XDestroyImage(panel->magnifyGlass->dirtyRect);
panel->magnifyGlass->dirtyRect = NULL;
}
return;
}
static Pixmap magnifyCreatePixmap(WMColorPanel * panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
int u, v;
#ifndef USE_XSHAPE
Pixmap pixmap;
#endif
unsigned long color;
if (!panel->magnifyGlass->image)
return None;
if (!panel->magnifyGlass->magPix)
return None;
/*
* Copy an area of only 5x5 pixels from the center of the image.
*/
for (u = 0; u < 5; u++) {
for (v = 0; v < 5; v++) {
color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
XSetForeground(scr->display, scr->copyGC, color);
if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
panel->magnifyGlass->color = ulongToRColor(scr, color);
/* The center square must eventually be centered around the
* hotspot. The image needs shifting to achieve this. The amount of
* shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
* _ _ _ _ _
* |_|_|_|_|_|
* ^------- center of center square == Cursor_x_hot
*/
XFillRectangle(scr->display, panel->magnifyGlass->magPix,
scr->copyGC,
u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
(u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
}
}
#ifdef USE_XSHAPE
return panel->magnifyGlass->magPix;
#else
pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width, Cursor_mask_height, scr->depth);
if (!pixmap)
return None;
XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
/* Copy the magnified pixmap, with the clip mask, to background pixmap */
XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
/* (2,2) puts center pixel on center of glass */
return pixmap;
#endif
}
static WMView *magnifyCreateView(W_ColorPanel * panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
WMView *magView;
magView = W_CreateTopView(scr);
if (!magView)
return NULL;
magView->self = panel->win;
magView->flags.topLevel = 1;
magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
magView->attribs.override_redirect = True;
magView->attribs.save_under = True;
W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
W_RealizeView(magView);
return magView;
}
static Cursor magnifyGrabPointer(W_ColorPanel * panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
Pixmap magPixmap, magPixmap2;
Cursor magCursor;
XColor fgColor = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 };
XColor bgColor = { 0, 0xbf00, 0xa000, 0x5000, DoRed | DoGreen | DoBlue, 0 };
/* Cursor creation stuff */
magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
(char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
(char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
&fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
XFreePixmap(scr->display, magPixmap);
XFreePixmap(scr->display, magPixmap2);
XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
/* Set up Pointer */
XGrabPointer(scr->display, panel->magnifyGlass->view->window, True,
PointerMotionMask | ButtonPressMask,
GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
return magCursor;
}
static WMPoint magnifyInitialize(W_ColorPanel * panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
int x, y, u, v;
unsigned int mask;
Pixmap pixmap, clip_mask;
WMPoint point;
Window root_return, child_return;
clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
(char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1, 0, 1);
panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
5 * 5 - 1, 5 * 5 - 1, scr->depth);
XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return, &x, &y, &u, &v, &mask);
panel->magnifyGlass->image = NULL;
/* Clipmask to make magnified view-contents circular */
#ifdef USE_XSHAPE
XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
ShapeBounding, 0, 0, clip_mask, ShapeSet);
#else
/* Clip circle in glass cursor */
XSetClipMask(scr->display, scr->clipGC, clip_mask);
XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
#endif
XFreePixmap(scr->display, clip_mask);
/* Draw initial magnifying glass contents */
magnifyGetImageStored(panel, x, y, x, y);
pixmap = magnifyCreatePixmap(panel);
XSetWindowBackgroundPixmap(scr->display, WMViewXID(panel->magnifyGlass->view), pixmap);
XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
XFlush(scr->display);
#ifndef USE_XSHAPE
XFreePixmap(scr->display, pixmap);
#endif
point.x = x;
point.y = y;
return point;
}
static void magnifyPutCursor(WMWidget * w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *) (data);
W_Screen *scr = WMWidgetScreen(panel->win);
Cursor magCursor;
Pixmap pixmap;
XEvent event;
WMPoint initialPosition;
/* Parameter not used, but tell the compiler that it is ok */
(void) w;
/* Destroy wheelBackImg, so it'll update properly */
if (panel->selectionBackImg) {
XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
panel->selectionBackImg = None;
}
/* Create magnifying glass */
panel->magnifyGlass = wmalloc(sizeof(MovingView));
panel->magnifyGlass->view = magnifyCreateView(panel);
if (!panel->magnifyGlass->view)
return;
initialPosition = magnifyInitialize(panel);
panel->magnifyGlass->x = initialPosition.x;
panel->magnifyGlass->y = initialPosition.y;
W_MoveView(panel->magnifyGlass->view,
panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
W_MapView(panel->magnifyGlass->view);
magCursor = magnifyGrabPointer(panel);
while (panel->magnifyGlass->image) {
WMNextEvent(scr->display, &event);
/* Pack motion events */
while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
}
switch (event.type) {
case ButtonPress:
XDestroyImage(panel->magnifyGlass->image);
panel->magnifyGlass->image = NULL;
if (event.xbutton.button == Button1) {
panel->color.rgb = panel->magnifyGlass->color;
panel->color.set = cpRGB;
updateSwatch(panel, panel->color);
}
switch (panel->mode) {
case WMWheelModeColorPanel:
wheelInit(panel);
wheelRender(panel);
wheelPaint(panel);
break;
case WMGrayModeColorPanel:
grayInit(panel);
break;
case WMRGBModeColorPanel:
rgbInit(panel);
break;
case WMCMYKModeColorPanel:
cmykInit(panel);
break;
case WMHSBModeColorPanel:
hsbInit(panel);
break;
default:
break;
}
panel->lastChanged = panel->mode;
WMSetButtonSelected(panel->magnifyBtn, False);
break;
case MotionNotify:
while (XPending(event.xmotion.display)) {
XEvent ev;
XPeekEvent(event.xmotion.display, &ev);
if (ev.type == MotionNotify)
XNextEvent(event.xmotion.display, &event);
else
break;
}
/* Get a "dirty rectangle" */
magnifyGetImageStored(panel,
panel->magnifyGlass->x, panel->magnifyGlass->y,
event.xmotion.x_root, event.xmotion.y_root);
/* Update coordinates */
panel->magnifyGlass->x = event.xmotion.x_root;
panel->magnifyGlass->y = event.xmotion.y_root;
/* Move view */
W_MoveView(panel->magnifyGlass->view,
panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
/* Put new image (with magn.) in view */
pixmap = magnifyCreatePixmap(panel);
if (pixmap != None) {
/* Change the window background */
XSetWindowBackgroundPixmap(scr->display,
WMViewXID(panel->magnifyGlass->view), pixmap);
/* Force an Expose (handled by X) */
XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
/* Synchronize the event queue, so the Expose is handled NOW */
XFlush(scr->display);
#ifndef USE_XSHAPE
XFreePixmap(scr->display, pixmap);
#endif
}
break;
/* Try XQueryPointer for this !!! It returns windows that the pointer
* is over. Note: We found this solving the invisible donkey cap bug
*/
#if 0 /* As it is impossible to make this work in all cases,
* we consider it confusing. Therefore we disabled it.
*/
case FocusOut: /* fall through */
case FocusIn:
/*
* Color Panel window (panel->win) lost or received focus.
* We need to update the pixmap in the magnifying glass.
*
* BUG Doesn't work with focus switches between two windows
* if none of them is the color panel.
*/
XUngrabPointer(scr->display, CurrentTime);
W_UnmapView(panel->magnifyGlass->view);
magnifyInitialize(panel);
W_MapView(panel->magnifyGlass->view);
XGrabPointer(scr->display, panel->magnifyGlass->view->window,
True, PointerMotionMask | ButtonPressMask,
GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
break;
#endif
default:
WMHandleEvent(&event);
break;
} /* of switch */
}
XUngrabPointer(scr->display, CurrentTime);
XFreeCursor(scr->display, magCursor);
XFreePixmap(scr->display, panel->magnifyGlass->magPix);
panel->magnifyGlass->magPix = None;
W_UnmapView(panel->magnifyGlass->view);
W_DestroyView(panel->magnifyGlass->view);
panel->magnifyGlass->view = NULL;
wfree(panel->magnifyGlass);
}
/****************** ColorWheel Functions ************************/
static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height)
{
wheelMatrix *matrix = NULL;
int i;
assert((width > 0) && (height > 0));
matrix = wmalloc(sizeof(wheelMatrix));
matrix->width = width;
matrix->height = height;
for (i = 0; i < 3; i++) {
matrix->data[i] = wmalloc(width * height * sizeof(unsigned char));
}
return matrix;
}
static void wheelDestroyMatrix(wheelMatrix * matrix)
{
int i;
if (!matrix)
return;
for (i = 0; i < 3; i++) {
if (matrix->data[i])
wfree(matrix->data[i]);
}
wfree(matrix);
}
static void wheelInitMatrix(W_ColorPanel * panel)
{
int i;
int x, y;
unsigned char *rp, *gp, *bp;
CPColor cpColor;
long ofs[4];
int xcor, ycor;
unsigned short sat;
int dhue[4];
const int cw_halfsize = (colorWheelSize + 4) / 2,
cw_sqsize = (colorWheelSize + 4) * (colorWheelSize + 4), uchar_shift = getShift(sizeof(unsigned char));
if (!panel->wheelMtrx)
return;
cpColor.hsv.value = 255;
cpColor.set = cpHSV;
ofs[0] = -1;
ofs[1] = -(colorWheelSize + 4);
/* offsets are counterclockwise (in triangles).
*
* ofs[0] ---->
* _______________________________________
* [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
* s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
* f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
* o | | | | | | | | | | | | | | | | | | | | | [3]
*
* <---- ofs[2]
* ____
* |\ /| <-- triangles
* | \/ |
* | /\ |
* |/__\|
*/
for (y = 0; y < cw_halfsize; y++) {
for (x = y; x < (colorWheelSize + 4 - y); x++) {
/* (xcor, ycor) is (x,y) relative to center of matrix */
xcor = 2 * x - 4 - colorWheelSize;
ycor = 2 * y - 4 - colorWheelSize;
/* RColor.saturation is unsigned char and will wrap after 255 */
sat = rint(255.0 * sqrt(xcor * xcor + ycor * ycor) / colorWheelSize);
cpColor.hsv.saturation = (unsigned char)sat;
ofs[0]++; /* top quarter of matrix */
ofs[1] += colorWheelSize + 4; /* left quarter */
ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
if (sat < 256) {
if (xcor != 0)
dhue[0] = rint(atan((double)ycor / (double)xcor) *
(180.0 / WM_PI)) + (xcor < 0 ? 180.0 : 0.0);
else
dhue[0] = 270;
dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
for (i = 0; i < 4; i++) {
rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
cpColor.hsv.hue = dhue[i];
convertCPColor(&cpColor);
*rp = (unsigned char)(cpColor.rgb.red);
*gp = (unsigned char)(cpColor.rgb.green);
*bp = (unsigned char)(cpColor.rgb.blue);
}
} else {
for (i = 0; i < 4; i++) {
rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
*rp = (unsigned char)0;
*gp = (unsigned char)0;
*bp = (unsigned char)0;
}
}
}
ofs[0] += 2 * y + 1;
ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2 * y);
}
}
static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue)
{
unsigned int i;
unsigned int v;
for (i = 0; i < 256; i++) {
/* We divide by 128 in advance, and check whether that number divides
* by 2 properly. If not, we add one to round the number correctly
*/
v = (i * maxvalue) >> 7;
panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 0x01));
}
}
static void wheelRender(W_ColorPanel * panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
int x, y;
RImage *image;
unsigned char *ptr;
RColor gray;
unsigned long ofs = 0;
/*unsigned char shift = getShift(sizeof(unsigned char)); */
image = RCreateImage(colorWheelSize + 4, colorWheelSize + 4, True);
if (!image) {
wwarning(_("Color Panel: Could not allocate memory"));
return;
}
ptr = image->data;
/* TODO Make this transparent istead of gray */
gray.red = gray.blue = 0xae;
gray.green = 0xaa;
for (y = 0; y < colorWheelSize + 4; y++) {
for (x = 0; x < colorWheelSize + 4; x++) {
if (wheelInsideColorWheel(panel, ofs)) {
*(ptr++) =
(unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]]);
*(ptr++) =
(unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]]);
*(ptr++) =
(unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]]);
*(ptr++) = 0;
} else {
*(ptr++) = (unsigned char)(gray.red);
*(ptr++) = (unsigned char)(gray.green);
*(ptr++) = (unsigned char)(gray.blue);
*(ptr++) = 255;
}
ofs++;
}
}
if (panel->wheelImg)
XFreePixmap(scr->display, panel->wheelImg);
RConvertImage(scr->rcontext, image, &panel->wheelImg);
RReleaseImage(image);
/* Check if backimage exists. If it doesn't, allocate and fill it */
if (!panel->selectionBackImg) {
panel->selectionBackImg = XCreatePixmap(scr->display,
W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
/* -2 is hot spot correction */
}
}
static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs)
{
return ((panel->wheelMtrx->data[0][ofs] != 0) &&
(panel->wheelMtrx->data[1][ofs] != 0) && (panel->wheelMtrx->data[2][ofs] != 0));
}
static void wheelPaint(W_ColorPanel * panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
scr->copyGC, 0, 0, colorWheelSize + 4, colorWheelSize + 4, 0, 0);
/* Draw selection image */
XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
}
static void wheelHandleEvents(XEvent * event, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *) data;
switch (event->type) {
case Expose:
if (event->xexpose.count != 0) /* TODO Improve */
break;
wheelPaint(panel);
break;
}
}
static void wheelHandleActionEvents(XEvent * event, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *) data;
switch (event->type) {
case ButtonPress:
if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) == COLORWHEEL_PART) {
panel->lastChanged = WMWheelModeColorPanel;
panel->flags.dragging = 1;
wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
}
break;
case ButtonRelease:
panel->flags.dragging = 0;
if (!panel->flags.continuous) {
if (panel->action)
(*panel->action) (panel, panel->clientData);
}
break;
case MotionNotify:
if (panel->flags.dragging) {
if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) == COLORWHEEL_PART) {
wheelPositionSelection(panel, event->xmotion.x, event->xmotion.y);
} else
wheelPositionSelectionOutBounds(panel, event->xmotion.x, event->xmotion.y);
}
break;
}
}
static int getPickerPart(W_ColorPanel * panel, int x, int y)
{
int lx, ly;
unsigned long ofs;
lx = x;
ly = y;
if (panel->mode == WMWheelModeColorPanel) {
if ((lx >= 2) && (lx <= 2 + colorWheelSize) && (ly >= 2) && (ly <= 2 + colorWheelSize)) {
ofs = ly * panel->wheelMtrx->width + lx;
if (wheelInsideColorWheel(panel, ofs))
return COLORWHEEL_PART;
}
}
if (panel->mode == WMCustomPaletteModeColorPanel) {
if ((lx >= 2) && (lx < customPaletteWidth - 2) && (ly >= 2) && (ly < customPaletteHeight - 2)) {
return CUSTOMPALETTE_PART;
}
}
return 0;
}
static void wheelBrightnessSliderCallback(WMWidget * w, void *data)
{
int value;
W_ColorPanel *panel = (W_ColorPanel *) data;
/* Parameter not used, but tell the compiler that it is ok */
(void) w;
value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
wheelCalculateValues(panel, value);
if (panel->color.set == cpRGB) {
convertCPColor(&panel->color);
panel->color.set = cpHSV;
}
panel->color.hsv.value = value;
wheelRender(panel);
wheelPaint(panel);
wheelUpdateSelection(panel);
}
static void wheelUpdateSelection(W_ColorPanel * panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
updateSwatch(panel, panel->color);
panel->lastChanged = WMWheelModeColorPanel;
/* Redraw color selector (and make a backup of the part it will cover) */
XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
/* "-2" is correction for hotspot location */
XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
/* see above */
}
static void wheelUndrawSelection(W_ColorPanel * panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
/* see above */
}
static void wheelPositionSelection(W_ColorPanel * panel, int x, int y)
{
unsigned long ofs = (y * panel->wheelMtrx->width) + x;
panel->color.rgb.red = panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]];
panel->color.rgb.green = panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]];
panel->color.rgb.blue = panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]];
panel->color.set = cpRGB;
wheelUndrawSelection(panel);
panel->colx = x;
panel->coly = y;
wheelUpdateSelection(panel);
wheelUpdateBrightnessGradientFromLocation(panel);
}
static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
{
int hue;
int xcor, ycor;
CPColor cpColor;
xcor = x * 2 - colorWheelSize - 4;
ycor = y * 2 - colorWheelSize - 4;
panel->color.hsv.saturation = 255;
panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
if (xcor != 0)
hue = rint(atan(-(double)ycor / (double)xcor) * (180.0 / WM_PI));
else {
if (ycor < 0)
hue = 90;
else
hue = 270;
}
if (xcor < 0)
hue += 180;
if ((xcor > 0) && (ycor > 0))
hue += 360;
panel->color.hsv.hue = hue;
panel->color.set = cpHSV;
convertCPColor(&panel->color);
wheelUndrawSelection(panel);
panel->colx = 2 + rint((colorWheelSize * (1.0 + cos(panel->color.hsv.hue * (WM_PI / 180.0)))) / 2.0);
/* "+2" because of "colorWheelSize + 4" */
panel->coly = 2 + rint((colorWheelSize * (1.0 + sin(-panel->color.hsv.hue * (WM_PI / 180.0)))) / 2.0);
wheelUpdateSelection(panel);
cpColor = panel->color;
wheelUpdateBrightnessGradient(panel, cpColor);
}
static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel)
{
CPColor from;
unsigned long ofs;
ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
from.rgb.red = panel->wheelMtrx->data[0][ofs];
from.rgb.green = panel->wheelMtrx->data[1][ofs];
from.rgb.blue = panel->wheelMtrx->data[2][ofs];
from.set = cpRGB;
wheelUpdateBrightnessGradient(panel, from);
}
static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor)
{
RColor to;
RImage *sliderImg;
WMPixmap *sliderPxmp;
to.red = to.green = to.blue = 0;
if (topColor.set == cpHSV)
convertCPColor(&topColor);
sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win), sliderImg, 0);
RReleaseImage(sliderImg);
WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
WMReleasePixmap(sliderPxmp);
}
/****************** Grayscale Panel Functions ***************/
static void grayBrightnessSliderCallback(WMWidget * w, void *data)
{
CPColor cpColor;
int value;
char tmp[4];
W_ColorPanel *panel = (W_ColorPanel *) data;
/* Parameter not used, but tell the compiler that it is ok */
(void) w;
value = WMGetSliderValue(panel->grayBrightnessS);
sprintf(tmp, "%d", value);
WMSetTextFieldText(panel->grayBrightnessT, tmp);
cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55 * value);
cpColor.set = cpRGB;
updateSwatch(panel, cpColor);
panel->lastChanged = WMGrayModeColorPanel;
}
static void grayPresetButtonCallback(WMWidget * w, void *data)
{
CPColor cpColor;
char tmp[4];
int value;
int i = 0;
W_ColorPanel *panel = (W_ColorPanel *) data;
while (i < 7) {
if (w == panel->grayPresetBtn[i])
break;
i++;
}
value = rint((100.0 * i) / 6.0);
sprintf(tmp, "%d", value);
WMSetTextFieldText(panel->grayBrightnessT, tmp);
cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * i) / 6.0);
cpColor.set = cpRGB;
WMSetSliderValue(panel->grayBrightnessS, rint((100.0 * i) / 6.0));
updateSwatch(panel, cpColor);
panel->lastChanged = WMGrayModeColorPanel;
}
static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification)
{
CPColor cpColor;
char tmp[4];
int value;
W_ColorPanel *panel = (W_ColorPanel *) observerData;
/* Parameter not used, but tell the compiler that it is ok */
(void) notification;
value = get_textfield_as_integer(panel->grayBrightnessT);
if (value > 100)
value = 100;
if (value < 0)
value = 0;
sprintf(tmp, "%d", value);
WMSetTextFieldText(panel->grayBrightnessT, tmp);
WMSetSliderValue(panel->grayBrightnessS, value);
cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * value) / 100.0);
cpColor.set = cpRGB;
updateSwatch(panel, cpColor);
panel->lastChanged = WMGrayModeColorPanel;
}
/******************* RGB Panel Functions *****************/
void rgbIntToChar(W_ColorPanel *panel, int *value)
{
char tmp[4];
const char *format;
switch (panel->rgbState) {
case RGBdec:
format = "%d";
break;
case RGBhex:
format = "%0X";
break;
default:
format = "";
}
sprintf(tmp, format, value[0]);
WMSetTextFieldText(panel->rgbRedT, tmp);
sprintf(tmp, format, value[1]);
WMSetTextFieldText(panel->rgbGreenT, tmp);
sprintf(tmp, format, value[2]);
WMSetTextFieldText(panel->rgbBlueT, tmp);
}
int *rgbCharToInt(W_ColorPanel *panel)
{
int base = 0;
static int value[3];
char *str;
switch (panel->rgbState) {
case RGBdec:
base = 10;
break;
case RGBhex:
base = 16;
break;
}
str = WMGetTextFieldText(panel->rgbRedT);
value[0] = strtol(str, NULL, base);
wfree(str);
str = WMGetTextFieldText(panel->rgbGreenT);
value[1] = strtol(str, NULL, base);
wfree(str);
str = WMGetTextFieldText(panel->rgbBlueT);
value[2] = strtol(str, NULL, base);
wfree(str);
return value;
}
static void rgbSliderCallback(WMWidget * w, void *data)
{
CPColor cpColor;
int value[3];
W_ColorPanel *panel = (W_ColorPanel *) data;
/* Parameter not used, but tell the compiler that it is ok */
(void) w;
value[0] = WMGetSliderValue(panel->rgbRedS);
value[1] = WMGetSliderValue(panel->rgbGreenS);
value[2] = WMGetSliderValue(panel->rgbBlueS);
rgbIntToChar(panel, value);
cpColor.rgb.red = value[0];
cpColor.rgb.green = value[1];
cpColor.rgb.blue = value[2];
cpColor.set = cpRGB;
updateSwatch(panel, cpColor);
panel->lastChanged = WMRGBModeColorPanel;
}
static void rgbTextFieldCallback(void *observerData, WMNotification * notification)
{
CPColor cpColor;
int *value;
int n;
W_ColorPanel *panel = (W_ColorPanel *) observerData;
/* Parameter not used, but tell the compiler that it is ok */
(void) notification;
value = rgbCharToInt(panel);
for (n = 0; n < 3; n++) {
if (value[n] > 255)
value[n] = 255;
if (value[n] < 0)
value[n] = 0;
}
rgbIntToChar(panel, value);
WMSetSliderValue(panel->rgbRedS, value[0]);
WMSetSliderValue(panel->rgbGreenS, value[1]);
WMSetSliderValue(panel->rgbBlueS, value[2]);
cpColor.rgb.red = value[0];
cpColor.rgb.green = value[1];
cpColor.rgb.blue = value[2];
cpColor.set = cpRGB;
updateSwatch(panel, cpColor);
panel->lastChanged = WMRGBModeColorPanel;
}
static void rgbDecToHex(WMWidget *w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *) data;
int *value;
(void) w;
switch (panel->rgbState) {
case RGBhex:
if (WMGetButtonSelected(panel->rgbDecB)) {
WMSetLabelText(panel->rgbMaxL, "255");
WMRedisplayWidget(panel->rgbMaxL);
value = rgbCharToInt(panel);
panel->rgbState = RGBdec;
rgbIntToChar(panel, value);
}
break;
case RGBdec:
if (WMGetButtonSelected(panel->rgbHexB)) {
WMSetLabelText(panel->rgbMaxL, "FF");
WMRedisplayWidget(panel->rgbMaxL);
value = rgbCharToInt(panel);
panel->rgbState = RGBhex;
rgbIntToChar(panel, value);
}
break;
}
}
/******************* CMYK Panel Functions *****************/
static void cmykSliderCallback(WMWidget * w, void *data)
{
CPColor cpColor;
int value[4];
char tmp[4];
W_ColorPanel *panel = (W_ColorPanel *) data;
double scale;
/* Parameter not used, but tell the compiler that it is ok */
(void) w;
value[0] = WMGetSliderValue(panel->cmykCyanS);
value[1] = WMGetSliderValue(panel->cmykMagentaS);
value[2] = WMGetSliderValue(panel->cmykYellowS);
value[3] = WMGetSliderValue(panel->cmykBlackS);
sprintf(tmp, "%d", value[0]);
WMSetTextFieldText(panel->cmykCyanT, tmp);
sprintf(tmp, "%d", value[1]);
WMSetTextFieldText(panel->cmykMagentaT, tmp);
sprintf(tmp, "%d", value[2]);
WMSetTextFieldText(panel->cmykYellowT, tmp);
sprintf(tmp, "%d", value[3]);
WMSetTextFieldText(panel->cmykBlackT, tmp);
scale = 2.55 * (1.0 - (value[3] / 100.0));
cpColor.rgb.red = rint((100.0 - value[0]) * scale);
cpColor.rgb.green = rint((100.0 - value[1]) * scale);
cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
cpColor.set = cpRGB;
updateSwatch(panel, cpColor);
panel->lastChanged = WMCMYKModeColorPanel;
}
static void cmykTextFieldCallback(void *observerData, WMNotification * notification)
{
CPColor cpColor;
int value[4];
char tmp[4];
int n;
double scale;
W_ColorPanel *panel = (W_ColorPanel *) observerData;
/* Parameter not used, but tell the compiler that it is ok */
(void) notification;
value[0] = get_textfield_as_integer(panel->cmykCyanT);
value[1] = get_textfield_as_integer(panel->cmykMagentaT);
value[2] = get_textfield_as_integer(panel->cmykYellowT);
value[3] = get_textfield_as_integer(panel->cmykBlackT);
for (n = 0; n < 4; n++) {
if (value[n] > 100)
value[n] = 100;
if (value[n] < 0)
value[n] = 0;
}
sprintf(tmp, "%d", value[0]);
WMSetTextFieldText(panel->cmykCyanT, tmp);
sprintf(tmp, "%d", value[1]);
WMSetTextFieldText(panel->cmykMagentaT, tmp);
sprintf(tmp, "%d", value[2]);
WMSetTextFieldText(panel->cmykYellowT, tmp);
sprintf(tmp, "%d", value[3]);
WMSetTextFieldText(panel->cmykBlackT, tmp);
WMSetSliderValue(panel->cmykCyanS, value[0]);
WMSetSliderValue(panel->cmykMagentaS, value[1]);
WMSetSliderValue(panel->cmykYellowS, value[2]);
WMSetSliderValue(panel->cmykBlackS, value[3]);
scale = 2.55 * (1.0 - (value[3] / 100.0));
cpColor.rgb.red = rint((100.0 - value[0]) * scale);
cpColor.rgb.green = rint((100.0 - value[1]) * scale);
cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
cpColor.set = cpRGB;
updateSwatch(panel, cpColor);
panel->lastChanged = WMCMYKModeColorPanel;
}
/********************** HSB Panel Functions ***********************/
static void hsbSliderCallback(WMWidget * w, void *data)
{
CPColor cpColor;
int value[3];
char tmp[4];
W_ColorPanel *panel = (W_ColorPanel *) data;
value[0] = WMGetSliderValue(panel->hsbHueS);
value[1] = WMGetSliderValue(panel->hsbSaturationS);
value[2] = WMGetSliderValue(panel->hsbBrightnessS);
sprintf(tmp, "%d", value[0]);
WMSetTextFieldText(panel->hsbHueT, tmp);
sprintf(tmp, "%d", value[1]);
WMSetTextFieldText(panel->hsbSaturationT, tmp);
sprintf(tmp, "%d", value[2]);
WMSetTextFieldText(panel->hsbBrightnessT, tmp);
cpColor.hsv.hue = value[0];
cpColor.hsv.saturation = value[1] * 2.55;
cpColor.hsv.value = value[2] * 2.55;
cpColor.set = cpHSV;
convertCPColor(&cpColor);
panel->lastChanged = WMHSBModeColorPanel;
updateSwatch(panel, cpColor);
if (w != panel->hsbBrightnessS)
hsbUpdateBrightnessGradient(panel);
if (w != panel->hsbSaturationS)
hsbUpdateSaturationGradient(panel);
if (w != panel->hsbHueS)
hsbUpdateHueGradient(panel);
}
static void hsbTextFieldCallback(void *observerData, WMNotification * notification)
{
CPColor cpColor;
int value[3];
char tmp[12]; /* We only 4 bytes needed, but compilers cannot know that */
int n;
W_ColorPanel *panel = (W_ColorPanel *) observerData;
/* Parameter not used, but tell the compiler that it is ok */
(void) notification;
value[0] = get_textfield_as_integer(panel->hsbHueT);
value[1] = get_textfield_as_integer(panel->hsbSaturationT);
value[2] = get_textfield_as_integer(panel->hsbBrightnessT);
if (value[0] > 359)
value[0] = 359;
if (value[0] < 0)
value[0] = 0;
for (n = 1; n < 3; n++) {
if (value[n] > 100)
value[n] = 100;
if (value[n] < 0)
value[n] = 0;
}
sprintf(tmp, "%d", value[0]);
WMSetTextFieldText(panel->hsbHueT, tmp);
sprintf(tmp, "%d", value[1]);
WMSetTextFieldText(panel->hsbSaturationT, tmp);
sprintf(tmp, "%d", value[2]);
WMSetTextFieldText(panel->hsbBrightnessT, tmp);
WMSetSliderValue(panel->hsbHueS, value[0]);
WMSetSliderValue(panel->hsbSaturationS, value[1]);
WMSetSliderValue(panel->hsbBrightnessS, value[2]);
cpColor.hsv.hue = value[0];
cpColor.hsv.saturation = value[1] * 2.55;
cpColor.hsv.value = value[2] * 2.55;
cpColor.set = cpHSV;
convertCPColor(&cpColor);
panel->lastChanged = WMHSBModeColorPanel;
updateSwatch(panel, cpColor);
hsbUpdateBrightnessGradient(panel);
hsbUpdateSaturationGradient(panel);
hsbUpdateHueGradient(panel);
}
static void hsbUpdateBrightnessGradient(W_ColorPanel * panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
RColor from;
CPColor to;
RImage *sliderImg;
WMPixmap *sliderPxmp;
from.red = from.green = from.blue = 0;
to.hsv = panel->color.hsv;
to.hsv.value = 255;
to.set = cpHSV;
convertCPColor(&to);
sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
RReleaseImage(sliderImg);
if (sliderPxmp)
W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
panel->font12, 2, 0, 100, WALeft, scr->white,
False, _("Brightness"), strlen(_("Brightness")));
else
wwarning(_("Color Panel: Could not allocate memory"));
WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
WMReleasePixmap(sliderPxmp);
}
static void hsbUpdateSaturationGradient(W_ColorPanel * panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
CPColor from;
CPColor to;
RImage *sliderImg;
WMPixmap *sliderPxmp;
from.hsv = panel->color.hsv;
from.hsv.saturation = 0;
from.set = cpHSV;
convertCPColor(&from);
to.hsv = panel->color.hsv;
to.hsv.saturation = 255;
to.set = cpHSV;
convertCPColor(&to);
sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb), RGRD_HORIZONTAL);
sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
RReleaseImage(sliderImg);
if (sliderPxmp)
W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
panel->font12, 2, 0, 100, WALeft,
from.hsv.value < 128 ? scr->white : scr->black, False,
_("Saturation"), strlen(_("Saturation")));
else
wwarning(_("Color Panel: Could not allocate memory"));
WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
WMReleasePixmap(sliderPxmp);
}
static void hsbUpdateHueGradient(W_ColorPanel * panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
RColor **colors = NULL;
RHSVColor hsvcolor;
RImage *sliderImg;
WMPixmap *sliderPxmp;
int i;
hsvcolor = panel->color.hsv;
colors = wmalloc(sizeof(RColor *) * (8));
for (i = 0; i < 7; i++) {
hsvcolor.hue = (360 * i) / 6;
colors[i] = wmalloc(sizeof(RColor));
RHSVtoRGB(&hsvcolor, colors[i]);
}
colors[7] = NULL;
sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
RReleaseImage(sliderImg);
if (sliderPxmp)
W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
panel->font12, 2, 0, 100, WALeft,
hsvcolor.value < 128 ? scr->white : scr->black, False, _("Hue"), strlen(_("Hue")));
else
wwarning(_("Color Panel: Could not allocate memory"));
WMSetSliderImage(panel->hsbHueS, sliderPxmp);
WMReleasePixmap(sliderPxmp);
for (i = 0; i < 7; i++)
wfree(colors[i]);
wfree(colors);
}
/*************** Custom Palette Functions ****************/
static void customRenderSpectrum(W_ColorPanel * panel)
{
RImage *spectrum;
int x, y;
unsigned char *ptr;
CPColor cpColor;
spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
ptr = spectrum->data;
for (y = 0; y < SPECTRUM_HEIGHT; y++) {
cpColor.hsv.hue = y;
cpColor.hsv.saturation = 0;
cpColor.hsv.value = 255;
cpColor.set = cpHSV;
for (x = 0; x < SPECTRUM_WIDTH; x++) {
convertCPColor(&cpColor);
*(ptr++) = (unsigned char)cpColor.rgb.red;
*(ptr++) = (unsigned char)cpColor.rgb.green;
*(ptr++) = (unsigned char)cpColor.rgb.blue;
if (x < (SPECTRUM_WIDTH / 2))
cpColor.hsv.saturation++;
if (x > (SPECTRUM_WIDTH / 2))
cpColor.hsv.value--;
}
}
if (panel->customPaletteImg) {
RReleaseImage(panel->customPaletteImg);
panel->customPaletteImg = NULL;
}
panel->customPaletteImg = spectrum;
}
static void customSetPalette(W_ColorPanel * panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
RImage *scaledImg;
Pixmap image;
image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth, customPaletteHeight, scr->depth);
scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth, customPaletteHeight);
RConvertImage(scr->rcontext, scaledImg, &image);
RReleaseImage(scaledImg);
XCopyArea(scr->display, image, panel->customPaletteContentView->window,
scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
/* Check backimage exists. If it doesn't, allocate and fill it */
if (!panel->selectionBackImg) {
panel->selectionBackImg = XCreatePixmap(scr->display,
panel->customPaletteContentView->window, 4, 4, scr->depth);
}
XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
panel->palx - 2, panel->paly - 2, 4, 4, 0, 0);
XCopyArea(scr->display, panel->selectionImg,
panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
panel->palx - 2, panel->paly - 2);
XFreePixmap(scr->display, image);
panel->palXRatio = (double)(panel->customPaletteImg->width) / (double)(customPaletteWidth);
panel->palYRatio = (double)(panel->customPaletteImg->height) / (double)(customPaletteHeight);
}
static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y)
{
W_Screen *scr = WMWidgetScreen(panel->win);
unsigned long ofs;
/* undraw selection */
XCopyArea(scr->display, panel->selectionBackImg,
panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
panel->palx - 2, panel->paly - 2);
panel->palx = x;
panel->paly = y;
ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) * panel->customPaletteImg->width) * 3;
panel->color.rgb.red = panel->customPaletteImg->data[ofs];
panel->color.rgb.green = panel->customPaletteImg->data[ofs + 1];
panel->color.rgb.blue = panel->customPaletteImg->data[ofs + 2];
panel->color.set = cpRGB;
updateSwatch(panel, panel->color);
panel->lastChanged = WMCustomPaletteModeColorPanel;
/* Redraw color selector (and make a backup of the part it will cover) */
XCopyArea(scr->display, panel->customPaletteContentView->window, panel->selectionBackImg, scr->copyGC, panel->palx - 2, panel->paly - 2, 4, 4, 0, 0); /* "-2" is correction for hotspot location */
XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx - 2, panel->paly - 2); /* see above */
}
static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
{
if (x < 2)
x = 2;
if (y < 2)
y = 2;
if (x >= customPaletteWidth)
x = customPaletteWidth - 2;
if (y >= customPaletteHeight)
y = customPaletteHeight - 2;
customPalettePositionSelection(panel, x, y);
}
static void customPaletteHandleEvents(XEvent * event, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *) data;
switch (event->type) {
case Expose:
if (event->xexpose.count != 0) /* TODO Improve. */
break;
customSetPalette(panel);
break;
}
}
static void customPaletteHandleActionEvents(XEvent * event, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *) data;
int x, y;
switch (event->type) {
case ButtonPress:
x = event->xbutton.x;
y = event->xbutton.y;
if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
panel->flags.dragging = 1;
customPalettePositionSelection(panel, x, y);
}
break;
case ButtonRelease:
panel->flags.dragging = 0;
if (!panel->flags.continuous) {
if (panel->action)
(*panel->action) (panel, panel->clientData);
}
break;
case MotionNotify:
x = event->xmotion.x;
y = event->xmotion.y;
if (panel->flags.dragging) {
if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
customPalettePositionSelection(panel, x, y);
} else
customPalettePositionSelectionOutBounds(panel, x, y);
}
break;
}
}
static void customPaletteMenuCallback(WMWidget * w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *) data;
int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
/* Parameter not used, but tell the compiler that it is ok */
(void) w;
switch (item) {
case CPmenuNewFromFile:
customPaletteMenuNewFromFile(panel);
break;
case CPmenuRename:
customPaletteMenuRename(panel);
break;
case CPmenuRemove:
customPaletteMenuRemove(panel);
break;
case CPmenuCopy:
break;
case CPmenuNewFromClipboard:
break;
}
}
static void customPaletteMenuNewFromFile(W_ColorPanel * panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
WMOpenPanel *browseP;
char *filepath;
char *filename = NULL;
char *spath;
char *tmp;
int i;
RImage *tmpImg = NULL;
if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir, "\0") == 0))
spath = wexpandpath(wgethomedir());
else
spath = wexpandpath(panel->lastBrowseDir);
browseP = WMGetOpenPanel(scr);
WMSetFilePanelCanChooseDirectories(browseP, 0);
WMSetFilePanelCanChooseFiles(browseP, 1);
/* Get a filename */
if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
_("Open Palette"), RSupportedFileFormats())) {
filepath = WMGetFilePanelFileName(browseP);
/* Get seperation position between path and filename */
i = strrchr(filepath, '/') - filepath + 1;
if (i > strlen(filepath))
i = strlen(filepath);
/* Store last browsed path */
if (panel->lastBrowseDir)
wfree(panel->lastBrowseDir);
panel->lastBrowseDir = wmalloc((i + 1) * sizeof(char));
strncpy(panel->lastBrowseDir, filepath, i);
panel->lastBrowseDir[i] = '\0';
/* Get filename from path */
filename = wstrdup(filepath + i);
/* Check for duplicate files, and rename it if there are any */
tmp = wstrconcat(panel->configurationPath, filename);
while (access(tmp, F_OK) == 0) {
char *newName;
wfree(tmp);
newName = generateNewFilename(filename);
wfree(filename);
filename = newName;
tmp = wstrconcat(panel->configurationPath, filename);
}
wfree(tmp);
/* Copy image to $(gnustepdir)/Library/Colors/ &
* Add filename to history menu */
if (wcopy_file(panel->configurationPath, filepath, filename) == 0) {
/* filepath is a "local" path now the file has been copied */
wfree(filepath);
filepath = wstrconcat(panel->configurationPath, filename);
/* load the image & add menu entries */
tmpImg = RLoadImage(scr->rcontext, filepath, 0);
if (tmpImg) {
if (panel->customPaletteImg)
RReleaseImage(panel->customPaletteImg);
panel->customPaletteImg = tmpImg;
customSetPalette(panel);
WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
panel->currentPalette =
WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1;
WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
panel->currentPalette);
}
} else {
tmp = wstrconcat(panel->configurationPath, filename);
i = remove(tmp); /* Delete the file, it doesn't belong here */
WMRunAlertPanel(scr, panel->win, _("File Error"),
_("Invalid file format !"), _("OK"), NULL, NULL);
if (i != 0) {
werror(_("can't remove file %s"), tmp);
WMRunAlertPanel(scr, panel->win, _("File Error"),
_("Couldn't remove file from Configuration Directory !"),
_("OK"), NULL, NULL);
}
wfree(tmp);
}
wfree(filepath);
wfree(filename);
}
WMFreeFilePanel(browseP);
wfree(spath);
}
static void customPaletteMenuRename(W_ColorPanel * panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
char *toName = NULL;
char *fromName;
char *toPath, *fromPath;
int item;
int index;
item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
fromName, _("OK"), _("Cancel"));
if (toName) {
/* As some people do certain stupid things... */
if (strcmp(toName, fromName) == 0) {
wfree(toName);
return;
}
/* For normal people */
fromPath = wstrconcat(panel->configurationPath, fromName);
toPath = wstrconcat(panel->configurationPath, toName);
if (access(toPath, F_OK) == 0) {
/* Careful, this palette exists already */
if (WMRunAlertPanel(scr, panel->win, _("Warning"),
_("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
NULL) == 1) {
/* "No" = 0, "Yes" = 1 */
int items = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
remove(toPath);
/* Remove from History list too */
index = 1;
while ((index < items)
&&
(strcmp(WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, index), toName)
!= 0))
index++;
if (index < items) {
WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, index);
if (index < item)
item--;
}
} else {
wfree(fromPath);
wfree(toName);
wfree(toPath);
return;
}
}
if (rename(fromPath, toPath) != 0)
werror(_("Couldn't rename palette %s to %s"), fromName, toName);
else {
WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item, toName);
WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
}
wfree(fromPath);
wfree(toPath);
wfree(toName);
}
}
static void customPaletteMenuRemove(W_ColorPanel * panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
char *text;
char *tmp;
int choice;
int item;
item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
tmp = wstrconcat(_("This will permanently remove the palette "),
WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
text = wstrconcat(tmp, _(".\n\nAre you sure you want to remove this palette ?"));
wfree(tmp);
choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"), NULL);
/* returns 0 (= "Yes") or 1 (="No") */
wfree(text);
if (choice == 0) {
tmp = wstrconcat(panel->configurationPath,
WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
if (remove(tmp) == 0) {
/* item-1 always exists */
WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
customSetPalette(panel);
WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
} else {
werror(_("Couldn't remove palette %s"), tmp);
}
wfree(tmp);
}
}
static void customPaletteHistoryCallback(WMWidget * w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *) data;
W_Screen *scr = WMWidgetScreen(panel->win);
int item;
char *filename;
RImage *tmp = NULL;
unsigned char perm_mask;
item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
if (item == panel->currentPalette)
return;
if (item == 0) {
customRenderSpectrum(panel);
WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, False);
WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, False);
} else {
/* Load file from configpath */
filename = wstrconcat(panel->configurationPath,
WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
/* If the file corresponding to the item does not exist,
* remove it from the history list and select the next one.
*/
perm_mask = (access(filename, F_OK) == 0);
if (!perm_mask) {
/* File does not exist */
wfree(filename);
WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
customPaletteHistoryCallback(w, data);
return;
}
/* Get the image */
tmp = RLoadImage(scr->rcontext, filename, 0);
if (tmp) {
if (panel->customPaletteImg) {
RReleaseImage(panel->customPaletteImg);
panel->customPaletteImg = NULL;
}
panel->customPaletteImg = tmp;
}
/* If the image is not writable, don't allow removing/renaming */
perm_mask = (access(filename, W_OK) == 0);
WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, perm_mask);
WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, perm_mask);
wfree(filename);
}
customSetPalette(panel);
panel->currentPalette = item;
}
/************************* ColorList Panel Functions **********************/
static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
{
WMScreen *scr = WMWidgetScreen(lPtr);
Display *dpy = WMScreenDisplay(scr);
WMView *view = W_VIEW(lPtr);
RColor *color = (RColor *) WMGetListItem(lPtr, index)->clientData;
W_ColorPanel *panel = WMGetHangedData(lPtr);
int width, height, x, y;
WMColor *fillColor;
width = rect->size.width;
height = rect->size.height;
x = rect->pos.x;
y = rect->pos.y;
if (state & WLDSSelected)
XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
else
XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
fillColor = WMCreateRGBColor(scr, color->red << 8, color->green << 8, color->blue << 8, True);
XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
WMReleaseColor(fillColor);
WMDrawString(scr, d, scr->black, panel->font12, x + 18, y, text, strlen(text));
}
static void colorListSelect(WMWidget * w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *) data;
CPColor cpColor;
cpColor.rgb = *((RColor *) WMGetListSelectedItem(w)->clientData);
cpColor.set = cpRGB;
panel->lastChanged = WMColorListModeColorPanel;
updateSwatch(panel, cpColor);
}
static void colorListColorMenuCallback(WMWidget * w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *) data;
int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
/* Parameter not used, but tell the compiler that it is ok */
(void) w;
switch (item) {
case CLmenuAdd:
break;
case CLmenuRename:
break;
case CLmenuRemove:
break;
}
}
static void colorListListMenuCallback(WMWidget * w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *) data;
int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
/* Parameter not used, but tell the compiler that it is ok */
(void) w;
switch (item) {
case CLmenuAdd:
break;
case CLmenuRename:
break;
case CLmenuRemove:
break;
}
}
/*************** Panel Initialisation Functions *****************/
static void wheelInit(W_ColorPanel * panel)
{
CPColor cpColor;
if (panel->color.set != cpHSV)
convertCPColor(&panel->color);
WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
panel->colx = 2 + rint((colorWheelSize / 2.0) *
(1 + (panel->color.hsv.saturation / 255.0) *
cos(panel->color.hsv.hue * WM_PI / 180.0)));
panel->coly = 2 + rint((colorWheelSize / 2.0) *
(1 + (panel->color.hsv.saturation / 255.0) *
sin(-panel->color.hsv.hue * WM_PI / 180.0)));
wheelCalculateValues(panel, panel->color.hsv.value);
cpColor = panel->color;
cpColor.hsv.value = 255;
cpColor.set = cpHSV;
wheelUpdateBrightnessGradient(panel, cpColor);
}
static void grayInit(W_ColorPanel * panel)
{
int value;
char tmp[4];
if (panel->color.set != cpHSV)
convertCPColor(&panel->color);
value = rint(panel->color.hsv.value / 2.55);
WMSetSliderValue(panel->grayBrightnessS, value);
sprintf(tmp, "%d", value);
WMSetTextFieldText(panel->grayBrightnessT, tmp);
}
static void rgbInit(W_ColorPanel * panel)
{
char tmp[4];
const char *format;
if (panel->color.set != cpRGB)
convertCPColor(&panel->color);
WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
switch (panel->rgbState) {
case RGBdec:
format = "%d";
break;
case RGBhex:
format = "%0X";
break;
default:
/* Avoid compiler warning */
format = "";
}
sprintf(tmp, format, panel->color.rgb.red);
WMSetTextFieldText(panel->rgbRedT, tmp);
sprintf(tmp, format, panel->color.rgb.green);
WMSetTextFieldText(panel->rgbGreenT, tmp);
sprintf(tmp, format, panel->color.rgb.blue);
WMSetTextFieldText(panel->rgbBlueT, tmp);
}
static void cmykInit(W_ColorPanel * panel)
{
int value[3];
char tmp[4];
if (panel->color.set != cpRGB)
convertCPColor(&panel->color);
value[0] = rint((255 - panel->color.rgb.red) / 2.55);
value[1] = rint((255 - panel->color.rgb.green) / 2.55);
value[2] = rint((255 - panel->color.rgb.blue) / 2.55);
WMSetSliderValue(panel->cmykCyanS, value[0]);
WMSetSliderValue(panel->cmykMagentaS, value[1]);
WMSetSliderValue(panel->cmykYellowS, value[2]);
WMSetSliderValue(panel->cmykBlackS, 0);
sprintf(tmp, "%d", value[0]);
WMSetTextFieldText(panel->cmykCyanT, tmp);
sprintf(tmp, "%d", value[1]);
WMSetTextFieldText(panel->cmykMagentaT, tmp);
sprintf(tmp, "%d", value[2]);
WMSetTextFieldText(panel->cmykYellowT, tmp);
WMSetTextFieldText(panel->cmykBlackT, "0");
}
static void hsbInit(W_ColorPanel * panel)
{
int value[3];
char tmp[4];
if (panel->color.set != cpHSV)
convertCPColor(&panel->color);
value[0] = panel->color.hsv.hue;
value[1] = rint(panel->color.hsv.saturation / 2.55);
value[2] = rint(panel->color.hsv.value / 2.55);
WMSetSliderValue(panel->hsbHueS, value[0]);
WMSetSliderValue(panel->hsbSaturationS, value[1]);
WMSetSliderValue(panel->hsbBrightnessS, value[2]);
sprintf(tmp, "%hu", value[0]);
WMSetTextFieldText(panel->hsbHueT, tmp);
sprintf(tmp, "%d", value[1]);
WMSetTextFieldText(panel->hsbSaturationT, tmp);
sprintf(tmp, "%d", value[2]);
WMSetTextFieldText(panel->hsbBrightnessT, tmp);
hsbUpdateBrightnessGradient(panel);
hsbUpdateSaturationGradient(panel);
hsbUpdateHueGradient(panel);
}
/************************** Common utility functions ************************/
static char *generateNewFilename(const char *curName)
{
int n;
char c;
int baseLen;
const char *ptr;
char *newName;
assert(curName);
ptr = curName;
if (((ptr = strrchr(ptr, '{')) == 0) || sscanf(ptr, "{%i}%c", &n, &c) != 1)
return wstrconcat(curName, " {1}");
baseLen = ptr - curName - 1;
newName = wmalloc(baseLen + 16);
strncpy(newName, curName, baseLen);
snprintf(&newName[baseLen], 16, " {%i}", n + 1);
return newName;
}
static void convertCPColor(CPColor * color)
{
unsigned short old_hue = 0;
switch (color->set) {
case cpNone:
wwarning(_("Color Panel: Color unspecified"));
return;
case cpRGB:
old_hue = color->hsv.hue;
RRGBtoHSV(&(color->rgb), &(color->hsv));
/*
* For pure grey colors, the Hue is generally calculated
* as 0, but in reality the Hue does not matter.
*
* But in an interactive GUI it is interresting to remember
* the previous Hue because if user moves away from perfect
* grey then he could be interrested in finding back his
* previous tint
*/
if ((color->rgb.red == color->rgb.green) &&
(color->rgb.red == color->rgb.blue) )
color->hsv.hue = old_hue;
break;
case cpHSV:
RHSVtoRGB(&(color->hsv), &(color->rgb));
break;
}
}
static RColor ulongToRColor(WMScreen * scr, unsigned long value)
{
RColor color;
XColor *xcolor = NULL;
xcolor = wmalloc(sizeof(XColor));
xcolor->pixel = value;
XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
color.red = xcolor->red >> 8;
color.green = xcolor->green >> 8;
color.blue = xcolor->blue >> 8;
color.alpha = 0;
wfree(xcolor);
return color;
}
static unsigned char getShift(unsigned char value)
{
unsigned char i = -1;
if (value == 0)
return 0;
while (value) {
value >>= 1;
i++;
}
return i;
}