mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-18 20:10:29 +01:00
Replace calls to wusergnusteppath() which just append "/Library" by calls to wuserdatapath(). Take opportunity to replace hardcoded "/WindowMaker" directories with the existing PACKAGE_TARNAME macro (which comes from autotools). The choice of 'TARNAME' is because it meant to be used in filename, thus less likely to have problematic characters than PACKAGE_NAME (meant for display purpose) and PACKAGE which is there for historical reason.
3556 lines
107 KiB
C
3556 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
|
|
|
|
const 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(wuserdatapath(), "/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;
|
|
int item;
|
|
|
|
if (!wmkdirhier(panel->configurationPath)) {
|
|
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;
|
|
}
|