Coding style cleanup in dock.c
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob05867662dce8e751ac8b54318c0031998bc74454
1 /*
2 * ColorPanel for WINGs
4 * by ]d : Original idea and basic initial code
5 * Pascal Hofstee : Code for wheeldrawing and calculating
6 * colors from it.
7 * Primary coder of this Color Panel.
8 * Alban Hertroys : Optimizations for algorithms for color-
9 * wheel. Also custom ColorPalettes and
10 * magnifying glass. Secondary coder ;)
11 * Alfredo K. Kojima : For pointing out memory-allocation
12 * problems and similair code-issues
13 * Marco van Hylckama-Vlieg : For once again doing the artwork ;-)
17 /* TODO:
18 * - Look at further optimization of colorWheel matrix calculation.
19 * It appears to be rather symmetric in angles of 60 degrees,
20 * while it is optimized in angles of 90 degrees.
21 * - Custom color-lists and custom colors in custom color-lists.
22 * - Stored colors
23 * - Resizing
26 #include "wconfig.h"
27 #include "WINGsP.h"
28 #include "rgb.h"
30 #include <errno.h>
31 #include <math.h>
32 #include <unistd.h>
33 #include <ctype.h>
34 #include <fcntl.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <dirent.h>
39 #define RETRY( x ) do { \
40 x; \
41 } while (errno == EINTR);
43 /* BUG There's something fishy with shaped windows */
44 /* Whithout shape extension the magnified image is completely broken -Dan */
45 #if 0
46 # ifdef SHAPE
47 # define SHAPE_WAS_DEFINED
48 # undef SHAPE
49 # endif
50 #endif
52 #ifdef SHAPE
53 # include <X11/extensions/shape.h>
54 #endif
56 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
59 * Bitmaps for magnifying glass cursor
62 /* Cursor */
63 #define Cursor_x_hot 11
64 #define Cursor_y_hot 11
65 #define Cursor_width 32
66 #define Cursor_height 32
67 static unsigned char Cursor_bits[] = {
68 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
69 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
70 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
71 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
72 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
73 0x00, 0x08, 0x00, 0x50, 0x00, 0x10, 0x00, 0x88, 0x00, 0x20, 0x00, 0x5c, 0x01, 0xc0, 0x81,
74 0x3b, 0x02, 0x00, 0x7e, 0x70, 0x05, 0x00, 0x00, 0xe0, 0x08, 0x00, 0x00, 0xc0, 0x15, 0x00,
75 0x00, 0x80, 0x23, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x5c,
76 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x70
79 /* Cursor shape-mask */
80 #define Cursor_shape_width 32
81 #define Cursor_shape_height 32
82 static unsigned char Cursor_shape_bits[] = {
83 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
84 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
85 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
86 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
87 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
88 0x00, 0x08, 0x00, 0x70, 0x00, 0x10, 0x00, 0xf8, 0x00, 0x20, 0x00, 0xfc, 0x01, 0xc0, 0x81,
89 0xfb, 0x03, 0x00, 0x7e, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xc0, 0x1f, 0x00,
90 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfc,
91 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x70
94 /* Clip-mask for magnified pixels */
95 #define Cursor_mask_width 24
96 #define Cursor_mask_height 24
97 static unsigned char Cursor_mask_bits[] = {
98 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
99 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
100 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
101 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
102 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
103 0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00
106 typedef struct MovingView {
107 WMView *view; /* The view this is all about */
108 XImage *image; /* What's under the view */
109 XImage *dirtyRect; /* Storage of overlapped image area */
110 Pixmap magPix; /* Magnified part of pixmap */
111 RColor color; /* Color of a pixel in the image */
112 int x, y; /* Position of view */
113 } MovingView;
115 typedef struct CPColor {
116 RColor rgb; /* The RGB values of the color */
117 RHSVColor hsv; /* The HSV values of the color */
118 enum { /* Which one was last set ? */
119 cpNone,
120 cpRGB,
121 cpHSV
122 } set;
123 } CPColor;
125 typedef struct WheelMatrix {
126 unsigned int width, height; /* Size of the colorwheel */
127 unsigned char *data[3]; /* Wheel data (R,G,B) */
128 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
129 } wheelMatrix;
131 typedef struct W_ColorPanel {
132 WMWindow *win;
133 WMFont *font8;
134 WMFont *font12;
135 void *clientData;
136 WMAction2 *action;
138 /* Common Stuff */
139 WMColorWell *colorWell;
140 WMButton *magnifyBtn;
141 WMButton *wheelBtn;
142 WMButton *slidersBtn;
143 WMButton *customPaletteBtn;
144 WMButton *colorListBtn;
146 /* Magnifying Glass */
147 MovingView *magnifyGlass;
149 /* ColorWheel Panel */
150 WMFrame *wheelFrm;
151 WMSlider *wheelBrightnessS;
152 WMView *wheelView;
154 /* Slider Panels */
155 WMFrame *slidersFrm;
156 WMFrame *seperatorFrm;
157 WMButton *grayBtn;
158 WMButton *rgbBtn;
159 WMButton *cmykBtn;
160 WMButton *hsbBtn;
161 /* Gray Scale Panel */
162 WMFrame *grayFrm;
163 WMLabel *grayMinL;
164 WMLabel *grayMaxL;
165 WMSlider *grayBrightnessS;
166 WMTextField *grayBrightnessT;
167 WMButton *grayPresetBtn[7];
169 /* RGB Panel */
170 WMFrame *rgbFrm;
171 WMLabel *rgbMinL;
172 WMLabel *rgbMaxL;
173 WMSlider *rgbRedS;
174 WMSlider *rgbGreenS;
175 WMSlider *rgbBlueS;
176 WMTextField *rgbRedT;
177 WMTextField *rgbGreenT;
178 WMTextField *rgbBlueT;
180 /* CMYK Panel */
181 WMFrame *cmykFrm;
182 WMLabel *cmykMinL;
183 WMLabel *cmykMaxL;
184 WMSlider *cmykCyanS;
185 WMSlider *cmykMagentaS;
186 WMSlider *cmykYellowS;
187 WMSlider *cmykBlackS;
188 WMTextField *cmykCyanT;
189 WMTextField *cmykMagentaT;
190 WMTextField *cmykYellowT;
191 WMTextField *cmykBlackT;
193 /* HSB Panel */
194 WMFrame *hsbFrm;
195 WMSlider *hsbHueS;
196 WMSlider *hsbSaturationS;
197 WMSlider *hsbBrightnessS;
198 WMTextField *hsbHueT;
199 WMTextField *hsbSaturationT;
200 WMTextField *hsbBrightnessT;
202 /* Custom Palette Panel */
203 WMFrame *customPaletteFrm;
204 WMPopUpButton *customPaletteHistoryBtn;
205 WMFrame *customPaletteContentFrm;
206 WMPopUpButton *customPaletteMenuBtn;
207 WMView *customPaletteContentView;
209 /* Color List Panel */
210 WMFrame *colorListFrm;
211 WMPopUpButton *colorListHistoryBtn;
212 WMList *colorListContentLst;
213 WMPopUpButton *colorListColorMenuBtn;
214 WMPopUpButton *colorListListMenuBtn;
216 /* Look-Up Tables and Images */
217 wheelMatrix *wheelMtrx;
218 Pixmap wheelImg;
219 Pixmap selectionImg;
220 Pixmap selectionBackImg;
221 RImage *customPaletteImg;
222 char *lastBrowseDir;
224 /* Common Data Fields */
225 CPColor color; /* Current color */
226 WMColorPanelMode mode; /* Current color selection mode */
227 WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
228 WMColorPanelMode lastChanged; /* Panel that last changed the color */
229 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
230 int palx, paly; /* (x,y) of sel.-marker in
231 CustomPaletteMode */
232 double palXRatio, palYRatio; /* Ratios in x & y between
233 original and scaled
234 palettesize */
235 int currentPalette;
236 char *configurationPath;
238 struct {
239 unsigned int continuous:1;
240 unsigned int dragging:1;
241 } flags;
242 } W_ColorPanel;
244 enum {
245 CPmenuNewFromFile,
246 CPmenuRename,
247 CPmenuRemove,
248 CPmenuCopy,
249 CPmenuNewFromClipboard
250 } customPaletteMenuItem;
252 enum {
253 CLmenuAdd,
254 CLmenuRename,
255 CLmenuRemove
256 } colorListMenuItem;
258 #define PWIDTH 194
259 #define PHEIGHT 266
260 #define colorWheelSize 150
261 #define customPaletteWidth 182
262 #define customPaletteHeight 106
263 #define knobThickness 8
265 #define SPECTRUM_WIDTH 511
266 #define SPECTRUM_HEIGHT 360
268 #define COLORWHEEL_PART 1
269 #define CUSTOMPALETTE_PART 2
270 #define BUFSIZE 1024
272 #define MAX_LENGTH 1024
274 #ifndef M_PI
275 #define M_PI 3.14159265358979323846
276 #endif
278 char *generateNewFilename(char *curName);
279 void convertCPColor(CPColor * color);
280 RColor ulongToRColor(WMScreen * scr, unsigned long value);
281 unsigned char getShift(unsigned char value);
283 static void modeButtonCallback(WMWidget * w, void *data);
284 static int getPickerPart(W_ColorPanel * panel, int x, int y);
285 static void readConfiguration(W_ColorPanel * panel);
286 static void readXColors(W_ColorPanel * panel);
288 static void closeWindowCallback(WMWidget * w, void *data);
290 static Cursor magnifyGrabPointer(W_ColorPanel * panel);
291 static WMPoint magnifyInitialize(W_ColorPanel * panel);
292 static void magnifyPutCursor(WMWidget * w, void *data);
293 static Pixmap magnifyCreatePixmap(WMColorPanel * panel);
294 static void magnifyGetImageStored(W_ColorPanel * panel, int x1, int y1, int x2, int y2);
295 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h);
297 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height);
298 static void wheelDestroyMatrix(wheelMatrix * matrix);
299 static void wheelInitMatrix(W_ColorPanel * panel);
300 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue);
301 static void wheelRender(W_ColorPanel * panel);
302 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs);
303 static void wheelPaint(W_ColorPanel * panel);
305 static void wheelHandleEvents(XEvent * event, void *data);
306 static void wheelHandleActionEvents(XEvent * event, void *data);
307 static void wheelBrightnessSliderCallback(WMWidget * w, void *data);
308 static void wheelUpdateSelection(W_ColorPanel * panel);
309 static void wheelUndrawSelection(W_ColorPanel * panel);
311 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y);
312 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
313 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel);
314 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor);
316 static void grayBrightnessSliderCallback(WMWidget * w, void *data);
317 static void grayPresetButtonCallback(WMWidget * w, void *data);
318 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification);
320 static void rgbSliderCallback(WMWidget * w, void *data);
321 static void rgbTextFieldCallback(void *observerData, WMNotification * notification);
323 static void cmykSliderCallback(WMWidget * w, void *data);
324 static void cmykTextFieldCallback(void *observerData, WMNotification * notification);
326 static void hsbSliderCallback(WMWidget * w, void *data);
327 static void hsbTextFieldCallback(void *observerData, WMNotification * notification);
328 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel);
329 static void hsbUpdateSaturationGradient(W_ColorPanel * panel);
330 static void hsbUpdateHueGradient(W_ColorPanel * panel);
332 static void customRenderSpectrum(W_ColorPanel * panel);
333 static void customSetPalette(W_ColorPanel * panel);
334 static void customPaletteHandleEvents(XEvent * event, void *data);
335 static void customPaletteHandleActionEvents(XEvent * event, void *data);
336 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y);
337 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
338 static void customPaletteMenuCallback(WMWidget * w, void *data);
339 static void customPaletteHistoryCallback(WMWidget * w, void *data);
341 static void customPaletteMenuNewFromFile(W_ColorPanel * panel);
342 static void customPaletteMenuRename(W_ColorPanel * panel);
343 static void customPaletteMenuRemove(W_ColorPanel * panel);
345 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect);
346 static void colorListSelect(WMWidget * w, void *data);
347 static void colorListColorMenuCallback(WMWidget * w, void *data);
348 static void colorListListMenuCallback(WMWidget * w, void *data);
349 static void colorListListMenuNew(W_ColorPanel * panel);
351 static void wheelInit(W_ColorPanel * panel);
352 static void grayInit(W_ColorPanel * panel);
353 static void rgbInit(W_ColorPanel * panel);
354 static void cmykInit(W_ColorPanel * panel);
355 static void hsbInit(W_ColorPanel * panel);
357 void WMSetColorPanelAction(WMColorPanel * panel, WMAction2 * action, void *data)
359 panel->action = action;
360 panel->clientData = data;
363 static WMColorPanel *makeColorPanel(WMScreen * scrPtr, char *name)
365 WMColorPanel *panel;
366 RImage *image;
367 WMPixmap *pixmap;
368 RColor from;
369 RColor to;
370 WMColor *textcolor, *graybuttoncolor;
371 int i;
372 GC bgc = WMColorGC(scrPtr->black);
373 GC wgc = WMColorGC(scrPtr->white);
375 panel = wmalloc(sizeof(WMColorPanel));
376 panel->color.rgb.red = 0;
377 panel->color.rgb.green = 0;
378 panel->color.rgb.blue = 0;
379 panel->color.hsv.hue = 0;
380 panel->color.hsv.saturation = 0;
381 panel->color.hsv.value = 0;
382 panel->color.set = cpNone; /* Color has not been set yet */
384 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
385 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
387 panel->win = WMCreateWindowWithStyle(scrPtr, name,
388 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
389 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
390 WMSetWindowTitle(panel->win, _("Colors"));
391 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
393 /* Set Default ColorPanel Mode(s) */
394 panel->mode = WMWheelModeColorPanel;
395 panel->lastChanged = 0;
396 panel->slidersmode = WMRGBModeColorPanel;
397 panel->configurationPath = wstrconcat(wusergnusteppath(), "/Library/Colors/");
399 /* Some General Purpose Widgets */
400 panel->colorWell = WMCreateColorWell(panel->win);
401 WMResizeWidget(panel->colorWell, 134, 36);
402 WSetColorWellBordered(panel->colorWell, False);
403 WMMoveWidget(panel->colorWell, 56, 4);
405 panel->magnifyBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
406 WMResizeWidget(panel->magnifyBtn, 46, 36);
407 WMMoveWidget(panel->magnifyBtn, 6, 4);
408 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
409 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
410 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
412 panel->wheelBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
413 WMResizeWidget(panel->wheelBtn, 46, 32);
414 WMMoveWidget(panel->wheelBtn, 6, 44);
415 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
416 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
417 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
419 panel->slidersBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
420 WMResizeWidget(panel->slidersBtn, 46, 32);
421 WMMoveWidget(panel->slidersBtn, 52, 44);
422 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
423 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
424 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
426 panel->customPaletteBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
427 WMResizeWidget(panel->customPaletteBtn, 46, 32);
428 WMMoveWidget(panel->customPaletteBtn, 98, 44);
429 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
430 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
431 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
433 panel->colorListBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
434 WMResizeWidget(panel->colorListBtn, 46, 32);
435 WMMoveWidget(panel->colorListBtn, 144, 44);
436 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
437 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
438 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
440 /* Let's Group some of them together */
441 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
442 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
443 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
445 /* Widgets for the ColorWheel Panel */
446 panel->wheelFrm = WMCreateFrame(panel->win);
447 WMSetFrameRelief(panel->wheelFrm, WRFlat);
448 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
449 WMMoveWidget(panel->wheelFrm, 5, 80);
451 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
452 /* XXX Can we create a view ? */
453 W_ResizeView(panel->wheelView, colorWheelSize + 4, colorWheelSize + 4);
454 W_MoveView(panel->wheelView, 0, 0);
456 /* Create an event handler to handle expose/click events in ColorWheel */
457 WMCreateEventHandler(panel->wheelView,
458 ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
459 LeaveWindowMask | ButtonMotionMask, wheelHandleActionEvents, panel);
461 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents, panel);
463 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
464 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
465 WMMoveWidget(panel->wheelBrightnessS, 5 + colorWheelSize + 14, 1);
466 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
467 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
468 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback, panel);
469 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
471 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize + 4, colorWheelSize + 4);
472 wheelInitMatrix(panel);
474 /* Widgets for the Slider Panels */
475 panel->slidersFrm = WMCreateFrame(panel->win);
476 WMSetFrameRelief(panel->slidersFrm, WRFlat);
477 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
478 WMMoveWidget(panel->slidersFrm, 4, 80);
480 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
481 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
482 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
483 WMMoveWidget(panel->seperatorFrm, 0, 1);
485 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
486 WMResizeWidget(panel->grayBtn, 46, 24);
487 WMMoveWidget(panel->grayBtn, 1, 8);
488 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
489 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
490 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
492 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
493 WMResizeWidget(panel->rgbBtn, 46, 24);
494 WMMoveWidget(panel->rgbBtn, 47, 8);
495 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
496 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
497 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
499 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
500 WMResizeWidget(panel->cmykBtn, 46, 24);
501 WMMoveWidget(panel->cmykBtn, 93, 8);
502 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
503 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
504 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
506 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
507 WMResizeWidget(panel->hsbBtn, 46, 24);
508 WMMoveWidget(panel->hsbBtn, 139, 8);
509 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
510 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
511 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
513 /* Let's Group the Slider Panel Buttons Together */
514 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
515 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
516 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
518 textcolor = WMDarkGrayColor(scrPtr);
520 /* Widgets for GrayScale Panel */
521 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
522 WMSetFrameRelief(panel->grayFrm, WRFlat);
523 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
524 WMMoveWidget(panel->grayFrm, 0, 34);
526 panel->grayMinL = WMCreateLabel(panel->grayFrm);
527 WMResizeWidget(panel->grayMinL, 20, 10);
528 WMMoveWidget(panel->grayMinL, 2, 2);
529 WMSetLabelText(panel->grayMinL, "0");
530 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
531 WMSetLabelTextColor(panel->grayMinL, textcolor);
532 WMSetLabelFont(panel->grayMinL, panel->font8);
534 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
535 WMResizeWidget(panel->grayMaxL, 40, 10);
536 WMMoveWidget(panel->grayMaxL, 104, 2);
537 WMSetLabelText(panel->grayMaxL, "100");
538 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
539 WMSetLabelTextColor(panel->grayMaxL, textcolor);
540 WMSetLabelFont(panel->grayMaxL, panel->font8);
542 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
543 WMResizeWidget(panel->grayBrightnessS, 141, 16);
544 WMMoveWidget(panel->grayBrightnessS, 2, 14);
545 WMSetSliderMinValue(panel->grayBrightnessS, 0);
546 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
547 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
548 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback, panel);
550 from.red = 0;
551 from.green = 0;
552 from.blue = 0;
554 to.red = 255;
555 to.green = 255;
556 to.blue = 255;
558 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
559 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
560 RReleaseImage(image);
562 if (pixmap)
563 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
564 panel->font12, 2, 0, 100, WALeft, scrPtr->white,
565 False, _("Brightness"), strlen(_("Brightness")));
566 else
567 wwarning(_("Color Panel: Could not allocate memory"));
569 WMSetSliderImage(panel->grayBrightnessS, pixmap);
570 WMReleasePixmap(pixmap);
572 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
573 WMResizeWidget(panel->grayBrightnessT, 40, 18);
574 WMMoveWidget(panel->grayBrightnessT, 146, 13);
575 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
576 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
577 WMTextDidEndEditingNotification, panel->grayBrightnessT);
579 for (i = 0; i < 7; i++) {
580 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
582 graybuttoncolor = WMCreateRGBColor(scrPtr, (255 / 6) * i << 8,
583 (255 / 6) * i << 8, (255 / 6) * i << 8, True);
584 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
585 WMReleaseColor(graybuttoncolor);
587 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
588 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
589 WMMoveWidget(panel->grayPresetBtn[i], 2 + (i * 20), 34);
590 WMSetButtonAction(panel->grayPresetBtn[i], grayPresetButtonCallback, panel);
591 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
592 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
593 WMReleasePixmap(pixmap);
597 /* End of GrayScale Panel */
599 /* Widgets for RGB Panel */
600 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
601 WMSetFrameRelief(panel->rgbFrm, WRFlat);
602 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
603 WMMoveWidget(panel->rgbFrm, 0, 34);
605 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
606 WMResizeWidget(panel->rgbMinL, 20, 10);
607 WMMoveWidget(panel->rgbMinL, 2, 2);
608 WMSetLabelText(panel->rgbMinL, "0");
609 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
610 WMSetLabelTextColor(panel->rgbMinL, textcolor);
611 WMSetLabelFont(panel->rgbMinL, panel->font8);
613 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
614 WMResizeWidget(panel->rgbMaxL, 40, 10);
615 WMMoveWidget(panel->rgbMaxL, 104, 2);
616 WMSetLabelText(panel->rgbMaxL, "255");
617 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
618 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
619 WMSetLabelFont(panel->rgbMaxL, panel->font8);
621 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
622 WMResizeWidget(panel->rgbRedS, 141, 16);
623 WMMoveWidget(panel->rgbRedS, 2, 14);
624 WMSetSliderMinValue(panel->rgbRedS, 0);
625 WMSetSliderMaxValue(panel->rgbRedS, 255);
626 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
627 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
629 to.red = 255;
630 to.green = 0;
631 to.blue = 0;
633 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
634 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
635 RReleaseImage(image);
637 if (pixmap)
638 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
639 2, 0, 100, WALeft, scrPtr->white, False, _("Red"), strlen(_("Red")));
640 else
641 wwarning(_("Color Panel: Could not allocate memory"));
643 WMSetSliderImage(panel->rgbRedS, pixmap);
644 WMReleasePixmap(pixmap);
646 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
647 WMResizeWidget(panel->rgbRedT, 40, 18);
648 WMMoveWidget(panel->rgbRedT, 146, 13);
649 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
650 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbRedT);
652 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
653 WMResizeWidget(panel->rgbGreenS, 141, 16);
654 WMMoveWidget(panel->rgbGreenS, 2, 36);
655 WMSetSliderMinValue(panel->rgbGreenS, 0);
656 WMSetSliderMaxValue(panel->rgbGreenS, 255);
657 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
658 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
660 to.red = 0;
661 to.green = 255;
662 to.blue = 0;
664 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
665 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
666 RReleaseImage(image);
668 if (pixmap)
669 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
670 2, 0, 100, WALeft, scrPtr->white, False, _("Green"), strlen(_("Green")));
671 else
672 wwarning(_("Color Panel: Could not allocate memory"));
674 WMSetSliderImage(panel->rgbGreenS, pixmap);
675 WMReleasePixmap(pixmap);
677 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
678 WMResizeWidget(panel->rgbGreenT, 40, 18);
679 WMMoveWidget(panel->rgbGreenT, 146, 35);
680 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
681 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbGreenT);
683 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
684 WMResizeWidget(panel->rgbBlueS, 141, 16);
685 WMMoveWidget(panel->rgbBlueS, 2, 58);
686 WMSetSliderMinValue(panel->rgbBlueS, 0);
687 WMSetSliderMaxValue(panel->rgbBlueS, 255);
688 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
689 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
691 to.red = 0;
692 to.green = 0;
693 to.blue = 255;
695 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
696 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
697 RReleaseImage(image);
699 if (pixmap)
700 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
701 2, 0, 100, WALeft, scrPtr->white, False, _("Blue"), strlen(_("Blue")));
702 else
703 wwarning(_("Color Panel: Could not allocate memory"));
705 WMSetSliderImage(panel->rgbBlueS, pixmap);
706 WMReleasePixmap(pixmap);
708 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
709 WMResizeWidget(panel->rgbBlueT, 40, 18);
710 WMMoveWidget(panel->rgbBlueT, 146, 57);
711 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
712 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbBlueT);
713 /* End of RGB Panel */
715 /* Widgets for CMYK Panel */
716 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
717 WMSetFrameRelief(panel->cmykFrm, WRFlat);
718 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
719 WMMoveWidget(panel->cmykFrm, 0, 34);
721 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
722 WMResizeWidget(panel->cmykMinL, 20, 10);
723 WMMoveWidget(panel->cmykMinL, 2, 2);
724 WMSetLabelText(panel->cmykMinL, "0");
725 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
726 WMSetLabelTextColor(panel->cmykMinL, textcolor);
727 WMSetLabelFont(panel->cmykMinL, panel->font8);
729 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
730 WMResizeWidget(panel->cmykMaxL, 40, 10);
731 WMMoveWidget(panel->cmykMaxL, 104, 2);
732 WMSetLabelText(panel->cmykMaxL, "100");
733 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
734 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
735 WMSetLabelFont(panel->cmykMaxL, panel->font8);
737 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
738 WMResizeWidget(panel->cmykCyanS, 141, 16);
739 WMMoveWidget(panel->cmykCyanS, 2, 14);
740 WMSetSliderMinValue(panel->cmykCyanS, 0);
741 WMSetSliderMaxValue(panel->cmykCyanS, 100);
742 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
743 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
745 from.red = 255;
746 from.green = 255;
747 from.blue = 255;
749 to.red = 0;
750 to.green = 255;
751 to.blue = 255;
753 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
754 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
755 RReleaseImage(image);
757 if (pixmap)
758 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
759 2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"), strlen(_("Cyan")));
760 else
761 wwarning(_("Color Panel: Could not allocate memory"));
763 WMSetSliderImage(panel->cmykCyanS, pixmap);
764 WMReleasePixmap(pixmap);
766 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
767 WMResizeWidget(panel->cmykCyanT, 40, 18);
768 WMMoveWidget(panel->cmykCyanT, 146, 13);
769 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
770 WMAddNotificationObserver(cmykTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->cmykCyanT);
772 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
773 WMResizeWidget(panel->cmykMagentaS, 141, 16);
774 WMMoveWidget(panel->cmykMagentaS, 2, 36);
775 WMSetSliderMinValue(panel->cmykMagentaS, 0);
776 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
777 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
778 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
780 to.red = 255;
781 to.green = 0;
782 to.blue = 255;
784 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
785 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
786 RReleaseImage(image);
788 if (pixmap)
789 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
790 2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"), strlen(_("Magenta")));
791 else
792 wwarning(_("Color Panel: Could not allocate memory"));
794 WMSetSliderImage(panel->cmykMagentaS, pixmap);
795 WMReleasePixmap(pixmap);
797 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
798 WMResizeWidget(panel->cmykMagentaT, 40, 18);
799 WMMoveWidget(panel->cmykMagentaT, 146, 35);
800 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
801 WMAddNotificationObserver(cmykTextFieldCallback, panel,
802 WMTextDidEndEditingNotification, panel->cmykMagentaT);
804 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
805 WMResizeWidget(panel->cmykYellowS, 141, 16);
806 WMMoveWidget(panel->cmykYellowS, 2, 58);
807 WMSetSliderMinValue(panel->cmykYellowS, 0);
808 WMSetSliderMaxValue(panel->cmykYellowS, 100);
809 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
810 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
812 to.red = 255;
813 to.green = 255;
814 to.blue = 0;
816 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
817 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
818 RReleaseImage(image);
820 if (pixmap)
821 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
822 2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"), strlen(_("Yellow")));
823 else
824 wwarning(_("Color Panel: Could not allocate memory"));
826 WMSetSliderImage(panel->cmykYellowS, pixmap);
827 WMReleasePixmap(pixmap);
829 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
830 WMResizeWidget(panel->cmykYellowT, 40, 18);
831 WMMoveWidget(panel->cmykYellowT, 146, 57);
832 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
833 WMAddNotificationObserver(cmykTextFieldCallback, panel,
834 WMTextDidEndEditingNotification, panel->cmykYellowT);
836 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
837 WMResizeWidget(panel->cmykBlackS, 141, 16);
838 WMMoveWidget(panel->cmykBlackS, 2, 80);
839 WMSetSliderMinValue(panel->cmykBlackS, 0);
840 WMSetSliderMaxValue(panel->cmykBlackS, 100);
841 WMSetSliderValue(panel->cmykBlackS, 0);
842 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
843 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
845 to.red = 0;
846 to.green = 0;
847 to.blue = 0;
849 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
850 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
851 RReleaseImage(image);
853 if (pixmap)
854 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
855 2, 0, 100, WALeft, scrPtr->black, False, _("Black"), strlen(_("Black")));
856 else
857 wwarning(_("Color Panel: Could not allocate memory"));
859 WMSetSliderImage(panel->cmykBlackS, pixmap);
860 WMReleasePixmap(pixmap);
862 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
863 WMResizeWidget(panel->cmykBlackT, 40, 18);
864 WMMoveWidget(panel->cmykBlackT, 146, 79);
865 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
866 WMAddNotificationObserver(cmykTextFieldCallback, panel,
867 WMTextDidEndEditingNotification, panel->cmykBlackT);
868 /* End of CMYK Panel */
870 /* Widgets for HSB Panel */
871 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
872 WMSetFrameRelief(panel->hsbFrm, WRFlat);
873 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
874 WMMoveWidget(panel->hsbFrm, 0, 34);
876 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
877 WMResizeWidget(panel->hsbHueS, 141, 16);
878 WMMoveWidget(panel->hsbHueS, 2, 14);
879 WMSetSliderMinValue(panel->hsbHueS, 0);
880 WMSetSliderMaxValue(panel->hsbHueS, 359);
881 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
882 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
884 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
885 WMResizeWidget(panel->hsbHueT, 40, 18);
886 WMMoveWidget(panel->hsbHueT, 146, 13);
887 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
888 WMAddNotificationObserver(hsbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->hsbHueT);
890 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
891 WMResizeWidget(panel->hsbSaturationS, 141, 16);
892 WMMoveWidget(panel->hsbSaturationS, 2, 36);
893 WMSetSliderMinValue(panel->hsbSaturationS, 0);
894 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
895 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
896 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
898 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
899 WMResizeWidget(panel->hsbSaturationT, 40, 18);
900 WMMoveWidget(panel->hsbSaturationT, 146, 35);
901 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
902 WMAddNotificationObserver(hsbTextFieldCallback, panel,
903 WMTextDidEndEditingNotification, panel->hsbSaturationT);
905 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
906 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
907 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
908 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
909 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
910 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
911 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
913 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
914 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
915 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
916 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
917 WMAddNotificationObserver(hsbTextFieldCallback, panel,
918 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
919 /* End of HSB Panel */
921 WMReleaseColor(textcolor);
923 /* Widgets for the CustomPalette Panel */
924 panel->customPaletteFrm = WMCreateFrame(panel->win);
925 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
926 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
927 WMMoveWidget(panel->customPaletteFrm, 5, 80);
929 panel->customPaletteHistoryBtn = WMCreatePopUpButton(panel->customPaletteFrm);
930 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
931 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
932 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1);
933 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn, customPaletteHistoryCallback, panel);
934 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
935 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
937 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
938 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
939 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
940 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
942 panel->customPaletteContentView = W_CreateView(W_VIEW(panel->customPaletteContentFrm));
943 /* XXX Test if we can create a view */
944 W_ResizeView(panel->customPaletteContentView, customPaletteWidth, customPaletteHeight);
945 W_MoveView(panel->customPaletteContentView, 2, 2);
947 /* Create event handler to handle expose/click events in CustomPalette */
948 WMCreateEventHandler(panel->customPaletteContentView,
949 ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
950 ButtonMotionMask, customPaletteHandleActionEvents, panel);
952 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask, customPaletteHandleEvents, panel);
954 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
955 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
956 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
957 WMSetPopUpButtonAction(panel->customPaletteMenuBtn, customPaletteMenuCallback, panel);
958 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
959 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
961 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
962 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
963 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
964 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
965 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
967 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
968 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
969 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
970 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuNewFromClipboard, 0);
972 customRenderSpectrum(panel);
973 panel->currentPalette = 0;
974 panel->palx = customPaletteWidth / 2;
975 panel->paly = customPaletteHeight / 2;
977 /* Widgets for the ColorList Panel */
978 panel->colorListFrm = WMCreateFrame(panel->win);
979 WMSetFrameRelief(panel->colorListFrm, WRFlat);
980 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
981 WMMoveWidget(panel->colorListFrm, 5, 80);
983 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
984 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
985 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
986 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn) - 1);
987 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
988 * colorListHistoryCallback, panel); */
989 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
990 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
992 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
993 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
994 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
995 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
996 WMMoveWidget(panel->colorListContentLst, 0, 23);
997 WMHangData(panel->colorListContentLst, panel);
999 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1000 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1001 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
1002 WMSetPopUpButtonAction(panel->colorListColorMenuBtn, colorListColorMenuCallback, panel);
1003 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16) / 2, 20);
1004 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1006 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1007 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1008 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1010 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1011 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1012 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1014 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1015 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1016 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1017 WMSetPopUpButtonAction(panel->colorListListMenuBtn, colorListListMenuCallback, panel);
1018 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2, 20);
1019 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2 + 8, PHEIGHT - 130);
1021 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1022 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1023 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1025 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1026 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1027 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1029 WMRealizeWidget(panel->win);
1030 WMMapSubwidgets(panel->win);
1032 WMMapSubwidgets(panel->wheelFrm);
1033 WMMapSubwidgets(panel->slidersFrm);
1034 WMMapSubwidgets(panel->grayFrm);
1035 WMMapSubwidgets(panel->rgbFrm);
1036 WMMapSubwidgets(panel->cmykFrm);
1037 WMMapSubwidgets(panel->hsbFrm);
1038 WMMapSubwidgets(panel->customPaletteFrm);
1039 WMMapSubwidgets(panel->customPaletteContentFrm);
1040 WMMapSubwidgets(panel->colorListFrm);
1042 /* Pixmap to indicate selection positions
1043 * wheelframe MUST be mapped.
1045 panel->selectionImg = XCreatePixmap(scrPtr->display, WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1046 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1047 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1049 readConfiguration(panel);
1050 readXColors(panel);
1052 return panel;
1055 WMColorPanel *WMGetColorPanel(WMScreen * scrPtr)
1057 WMColorPanel *panel;
1059 if (scrPtr->sharedColorPanel)
1060 return scrPtr->sharedColorPanel;
1062 panel = makeColorPanel(scrPtr, "colorPanel");
1064 scrPtr->sharedColorPanel = panel;
1066 return panel;
1069 void WMFreeColorPanel(WMColorPanel * panel)
1071 W_Screen *scr = WMWidgetScreen(panel->win);
1073 if (panel == scr->sharedColorPanel) {
1074 scr->sharedColorPanel = NULL;
1077 if (!panel)
1078 return;
1080 WMRemoveNotificationObserver(panel);
1081 WMUnmapWidget(panel->win);
1083 /* fonts */
1084 WMReleaseFont(panel->font8);
1085 WMReleaseFont(panel->font12);
1087 /* pixmaps */
1088 wheelDestroyMatrix(panel->wheelMtrx);
1089 if (panel->wheelImg)
1090 XFreePixmap(scr->display, panel->wheelImg);
1091 if (panel->selectionImg)
1092 XFreePixmap(scr->display, panel->selectionImg);
1093 if (panel->selectionBackImg)
1094 XFreePixmap(scr->display, panel->selectionBackImg);
1095 RReleaseImage(panel->customPaletteImg);
1097 /* structs */
1098 if (panel->lastBrowseDir)
1099 wfree(panel->lastBrowseDir);
1100 if (panel->configurationPath)
1101 wfree(panel->configurationPath);
1103 WMDestroyWidget(panel->win);
1105 wfree(panel);
1108 void WMCloseColorPanel(WMColorPanel * panel)
1110 WMFreeColorPanel(panel);
1113 void WMShowColorPanel(WMColorPanel * panel)
1115 WMScreen *scr = WMWidgetScreen(panel->win);
1116 WMColor *white = WMWhiteColor(scr);
1118 if (panel->color.set == cpNone)
1119 WMSetColorPanelColor(panel, white);
1120 WMReleaseColor(white);
1122 if (panel->mode != WMWheelModeColorPanel)
1123 WMPerformButtonClick(panel->wheelBtn);
1125 WMMapWidget(panel->win);
1128 static void closeWindowCallback(WMWidget * w, void *data)
1130 W_ColorPanel *panel = (W_ColorPanel *) data;
1132 WMCloseColorPanel(panel);
1135 static void readConfiguration(W_ColorPanel * panel)
1137 /* XXX Doesn't take care of "invalid" files */
1139 DIR *dPtr;
1140 struct dirent *dp;
1141 struct stat stat_buf;
1142 int item;
1144 if (stat(panel->configurationPath, &stat_buf) != 0) {
1145 if (mkdir(panel->configurationPath, S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH) != 0) {
1146 werror(_("Color Panel: Could not create directory %s needed"
1147 " to store configurations"), panel->configurationPath);
1148 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1149 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1150 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1151 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1152 _("File Error"),
1153 _("Could not create ColorPanel configuration directory"),
1154 _("OK"), NULL, NULL);
1156 return;
1159 if (!(dPtr = opendir(panel->configurationPath))) {
1160 wwarning("%s: %s", _("Color Panel: Could not find file"), panel->configurationPath);
1161 return;
1164 while ((dp = readdir(dPtr)) != NULL) {
1165 unsigned int perm_mask;
1166 char *path = wstrconcat(panel->configurationPath,
1167 dp->d_name);
1169 if (dp->d_name[0] != '.') {
1170 item = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
1171 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1173 perm_mask = (access(path, R_OK) == 0);
1174 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn, item, perm_mask);
1176 wfree(path);
1178 closedir(dPtr);
1181 static void readXColors(W_ColorPanel * panel)
1183 WMListItem *item;
1184 RGBColor *entry;
1186 for (entry = rgbColors; entry->name != NULL; entry++) {
1187 item = WMAddListItem(panel->colorListContentLst, entry->name);
1188 item->clientData = (void *)&(entry->color);
1192 void WMSetColorPanelPickerMode(WMColorPanel * panel, WMColorPanelMode mode)
1194 W_Screen *scr = WMWidgetScreen(panel->win);
1196 if (mode != WMWheelModeColorPanel) {
1197 WMUnmapWidget(panel->wheelFrm);
1198 if (panel->selectionBackImg) {
1199 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1200 panel->selectionBackImg = None;
1203 if (mode != WMGrayModeColorPanel)
1204 WMUnmapWidget(panel->grayFrm);
1205 if (mode != WMRGBModeColorPanel)
1206 WMUnmapWidget(panel->rgbFrm);
1207 if (mode != WMCMYKModeColorPanel)
1208 WMUnmapWidget(panel->cmykFrm);
1209 if (mode != WMHSBModeColorPanel)
1210 WMUnmapWidget(panel->hsbFrm);
1211 if (mode != WMCustomPaletteModeColorPanel) {
1212 WMUnmapWidget(panel->customPaletteFrm);
1213 if (panel->selectionBackImg) {
1214 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1215 panel->selectionBackImg = None;
1218 if (mode != WMColorListModeColorPanel)
1219 WMUnmapWidget(panel->colorListFrm);
1220 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1221 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1222 WMUnmapWidget(panel->slidersFrm);
1223 else
1224 panel->slidersmode = mode;
1226 if (mode == WMWheelModeColorPanel) {
1227 WMMapWidget(panel->wheelFrm);
1228 WMSetButtonSelected(panel->wheelBtn, True);
1229 if (panel->lastChanged != WMWheelModeColorPanel)
1230 wheelInit(panel);
1231 wheelRender(panel);
1232 wheelPaint(panel);
1233 } else if (mode == WMGrayModeColorPanel) {
1234 WMMapWidget(panel->slidersFrm);
1235 WMSetButtonSelected(panel->slidersBtn, True);
1236 WMMapWidget(panel->grayFrm);
1237 WMSetButtonSelected(panel->grayBtn, True);
1238 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1239 if (panel->lastChanged != WMGrayModeColorPanel)
1240 grayInit(panel);
1241 } else if (mode == WMRGBModeColorPanel) {
1242 WMMapWidget(panel->slidersFrm);
1243 WMSetButtonSelected(panel->slidersBtn, True);
1244 WMMapWidget(panel->rgbFrm);
1245 WMSetButtonSelected(panel->rgbBtn, True);
1246 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1247 if (panel->lastChanged != WMRGBModeColorPanel)
1248 rgbInit(panel);
1249 } else if (mode == WMCMYKModeColorPanel) {
1250 WMMapWidget(panel->slidersFrm);
1251 WMSetButtonSelected(panel->slidersBtn, True);
1252 WMMapWidget(panel->cmykFrm);
1253 WMSetButtonSelected(panel->cmykBtn, True);
1254 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1255 if (panel->lastChanged != WMCMYKModeColorPanel)
1256 cmykInit(panel);
1257 } else if (mode == WMHSBModeColorPanel) {
1258 WMMapWidget(panel->slidersFrm);
1259 WMSetButtonSelected(panel->slidersBtn, True);
1260 WMMapWidget(panel->hsbFrm);
1261 WMSetButtonSelected(panel->hsbBtn, True);
1262 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1263 if (panel->lastChanged != WMHSBModeColorPanel)
1264 hsbInit(panel);
1265 } else if (mode == WMCustomPaletteModeColorPanel) {
1266 WMMapWidget(panel->customPaletteFrm);
1267 WMSetButtonSelected(panel->customPaletteBtn, True);
1268 customSetPalette(panel);
1269 } else if (mode == WMColorListModeColorPanel) {
1270 WMMapWidget(panel->colorListFrm);
1271 WMSetButtonSelected(panel->colorListBtn, True);
1274 panel->mode = mode;
1277 WMColor *WMGetColorPanelColor(WMColorPanel * panel)
1279 return WMGetColorWellColor(panel->colorWell);
1282 void WMSetColorPanelColor(WMColorPanel * panel, WMColor * color)
1284 WMSetColorWellColor(panel->colorWell, color);
1286 panel->color.rgb.red = color->color.red >> 8;
1287 panel->color.rgb.green = color->color.green >> 8;
1288 panel->color.rgb.blue = color->color.blue >> 8;
1289 panel->color.set = cpRGB;
1291 if (panel->mode == panel->lastChanged)
1292 panel->lastChanged = 0;
1294 WMSetColorPanelPickerMode(panel, panel->mode);
1297 static void updateSwatch(WMColorPanel * panel, CPColor color)
1299 WMScreen *scr = WMWidgetScreen(panel->win);
1300 WMColor *wellcolor;
1302 if (color.set != cpRGB)
1303 convertCPColor(&color);
1305 panel->color = color;
1307 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8, color.rgb.green << 8, color.rgb.blue << 8, True);
1309 WMSetColorWellColor(panel->colorWell, wellcolor);
1310 WMReleaseColor(wellcolor);
1312 if (!panel->flags.dragging || panel->flags.continuous) {
1313 if (panel->action)
1314 (*panel->action) (panel, panel->clientData);
1316 WMPostNotificationName(WMColorPanelColorChangedNotification, panel, NULL);
1320 static void modeButtonCallback(WMWidget * w, void *data)
1322 W_ColorPanel *panel = (W_ColorPanel *) (data);
1324 if (w == panel->wheelBtn)
1325 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1326 else if (w == panel->slidersBtn)
1327 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1328 else if (w == panel->customPaletteBtn)
1329 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1330 else if (w == panel->colorListBtn)
1331 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1332 else if (w == panel->grayBtn)
1333 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1334 else if (w == panel->rgbBtn)
1335 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1336 else if (w == panel->cmykBtn)
1337 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1338 else if (w == panel->hsbBtn)
1339 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1342 /****************** Magnifying Cursor Functions *******************/
1344 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h)
1346 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1347 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1348 displayHeight = DisplayHeight(scr->display, scr->screen);
1350 if (!(image && image->data)) {
1351 /* The image in panel->magnifyGlass->image does not exist yet.
1352 * Grab one from the screen (not beyond) and use it from now on.
1354 if (!(image = XGetImage(scr->display, scr->rootWin,
1355 x - Cursor_x_hot, y - Cursor_y_hot, w, h, AllPlanes, ZPixmap)))
1356 wwarning(_("Color Panel: X failed request"));
1358 return image;
1361 /* Coordinate correction for back pixmap
1362 * if magnifying glass is at screen-borders
1365 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1366 * Hatched area is beyond screen border.
1368 * |<-Cursor_x_hot->|
1369 * ________________|_____
1370 * |/ / / / / / /| | |
1371 * | / / / / / / |(x,y) |
1372 * |/_/_/_/_/_/_/|________|
1373 * |<----x0----->|<--w0-->|
1377 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1378 * screen borders
1379 * Hatched area is beyond screen border
1381 * |<-Cursor_x_hot->|
1382 * ________________|_______________
1383 * | | | / / / / / /|
1384 * | (x,y)|/ / / / / / |
1385 * |___________________|_/_/_/_/_/_/|
1386 * |<-------w0-------->| |
1387 * |<---------------w--|----------->|
1388 * | |
1389 * x0 Displaywidth-1
1392 if (x < Cursor_x_hot) { /* see fig. 1 */
1393 x0 = Cursor_x_hot - x;
1394 w0 = w - x0;
1397 if (displayWidth - 1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1398 w0 = (displayWidth) - (x - Cursor_x_hot);
1401 if (y < Cursor_y_hot) { /* see fig. 1 */
1402 y0 = Cursor_y_hot - y;
1403 h0 = h - y0;
1406 if (displayHeight - 1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1407 h0 = (displayHeight) - (y - Cursor_y_hot);
1409 /* end of coordinate correction */
1411 /* Grab an image from the screen, clipped if necessary,
1412 * and put it in the existing panel->magnifyGlass->image
1413 * with the corresponding clipping offset.
1415 if (!XGetSubImage(scr->display, scr->rootWin,
1416 x - Cursor_x_hot + x0, y - Cursor_y_hot + y0, w0, h0, AllPlanes, ZPixmap, image, x0, y0))
1417 wwarning(_("Color Panel: X failed request"));
1419 return NULL;
1422 static void magnifyGetImageStored(WMColorPanel * panel, int x1, int y1, int x2, int y2)
1424 /* (x1, y1) = topleft corner of existing rectangle
1425 * (x2, y2) = topleft corner of new position
1428 W_Screen *scr = WMWidgetScreen(panel->win);
1429 int xa = 0, ya = 0, xb = 0, yb = 0;
1430 int width, height;
1431 const int dx = abs(x2 - x1), dy = abs(y2 - y1);
1432 XImage *image;
1433 const int x_min = Cursor_x_hot,
1434 y_min = Cursor_y_hot,
1435 x_max = DisplayWidth(scr->display, scr->screen) - 1 -
1436 (Cursor_mask_width - Cursor_x_hot),
1437 y_max = DisplayHeight(scr->display, scr->screen) - 1 - (Cursor_mask_height - Cursor_y_hot);
1439 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1440 return; /* No movement */
1442 if (x1 < x2)
1443 xa = dx;
1444 else
1445 xb = dx;
1447 if (y1 < y2)
1448 ya = dy;
1449 else
1450 yb = dy;
1452 width = Cursor_mask_width - dx;
1453 height = Cursor_mask_height - dy;
1455 /* If the traversed distance is larger than the size of the magnifying
1456 * glass contents, there is no need to do dirty rectangles. A whole new
1457 * rectangle can be grabbed (unless that rectangle falls partially
1458 * off screen).
1459 * Destroying the image and setting it to NULL will achieve that later on.
1461 * Of course, grabbing an XImage beyond the borders of the screen will
1462 * cause trouble, this is considdered a special case. Part of the screen
1463 * is grabbed, but there is no need for dirty rectangles.
1465 if ((width <= 0) || (height <= 0)) {
1466 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1467 if (panel->magnifyGlass->image)
1468 XDestroyImage(panel->magnifyGlass->image);
1469 panel->magnifyGlass->image = NULL;
1471 } else {
1472 if (panel->magnifyGlass->image) {
1473 /* Get dirty rectangle from panel->magnifyGlass->image */
1474 panel->magnifyGlass->dirtyRect =
1475 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1476 if (!panel->magnifyGlass->dirtyRect) {
1477 wwarning(_("Color Panel: X failed request"));
1478 return; /* X returned a NULL from XSubImage */
1483 /* Get image from screen */
1484 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2, Cursor_mask_width, Cursor_mask_height);
1485 if (image) { /* Only reassign if a *new* image was grabbed */
1486 panel->magnifyGlass->image = image;
1487 return;
1490 /* Copy previously stored rectangle on covered part of image */
1491 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1492 int old_height;
1494 /* "width" and "height" are used as coordinates here,
1495 * and run from [0...width-1] and [0...height-1] respectively.
1497 width--;
1498 height--;
1499 old_height = height;
1501 for (; width >= 0; width--)
1502 for (height = old_height; height >= 0; height--)
1503 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1504 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1505 XDestroyImage(panel->magnifyGlass->dirtyRect);
1506 panel->magnifyGlass->dirtyRect = NULL;
1509 return;
1512 static Pixmap magnifyCreatePixmap(WMColorPanel * panel)
1514 W_Screen *scr = WMWidgetScreen(panel->win);
1515 int u, v;
1516 #ifndef SHAPE
1517 Pixmap pixmap;
1518 #endif
1519 unsigned long color;
1521 if (!panel->magnifyGlass->image)
1522 return None;
1524 if (!panel->magnifyGlass->magPix)
1525 return None;
1528 * Copy an area of only 5x5 pixels from the center of the image.
1530 for (u = 0; u < 5; u++) {
1531 for (v = 0; v < 5; v++) {
1532 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1534 XSetForeground(scr->display, scr->copyGC, color);
1536 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1537 panel->magnifyGlass->color = ulongToRColor(scr, color);
1539 /* The center square must eventually be centered around the
1540 * hotspot. The image needs shifting to achieve this. The amount of
1541 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1542 * _ _ _ _ _
1543 * |_|_|_|_|_|
1544 * ^------- center of center square == Cursor_x_hot
1546 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1547 scr->copyGC,
1548 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1549 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1553 #ifdef SHAPE
1554 return panel->magnifyGlass->magPix;
1555 #else
1556 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width, Cursor_mask_height, scr->depth);
1557 if (!pixmap)
1558 return None;
1560 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1561 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1563 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1564 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1565 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1566 /* (2,2) puts center pixel on center of glass */
1568 return pixmap;
1569 #endif
1573 static WMView *magnifyCreateView(W_ColorPanel * panel)
1575 W_Screen *scr = WMWidgetScreen(panel->win);
1576 WMView *magView;
1578 magView = W_CreateTopView(scr);
1579 if (!magView)
1580 return NULL;
1582 magView->self = panel->win;
1583 magView->flags.topLevel = 1;
1584 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1585 magView->attribs.override_redirect = True;
1586 magView->attribs.save_under = True;
1588 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1590 W_RealizeView(magView);
1592 return magView;
1595 static Cursor magnifyGrabPointer(W_ColorPanel * panel)
1597 W_Screen *scr = WMWidgetScreen(panel->win);
1598 Pixmap magPixmap, magPixmap2;
1599 Cursor magCursor;
1600 XColor fgColor = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 };
1601 XColor bgColor = { 0, 0xbf00, 0xa000, 0x5000, DoRed | DoGreen | DoBlue, 0 };
1603 /* Cursor creation stuff */
1604 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1605 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1606 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1607 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1609 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1610 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1612 XFreePixmap(scr->display, magPixmap);
1613 XFreePixmap(scr->display, magPixmap2);
1615 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1617 /* Set up Pointer */
1618 XGrabPointer(scr->display, panel->magnifyGlass->view->window, True,
1619 PointerMotionMask | ButtonPressMask,
1620 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1622 return magCursor;
1625 static WMPoint magnifyInitialize(W_ColorPanel * panel)
1627 W_Screen *scr = WMWidgetScreen(panel->win);
1628 int x, y, u, v;
1629 unsigned int mask;
1630 Pixmap pixmap, clip_mask;
1631 WMPoint point;
1632 Window root_return, child_return;
1634 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1635 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1636 1, 0, 1);
1637 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1638 5 * 5 - 1, 5 * 5 - 1, scr->depth);
1640 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return, &x, &y, &u, &v, &mask);
1642 panel->magnifyGlass->image = NULL;
1644 /* Clipmask to make magnified view-contents circular */
1645 #ifdef SHAPE
1646 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1647 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1648 #else
1649 /* Clip circle in glass cursor */
1650 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1651 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1652 #endif
1654 XFreePixmap(scr->display, clip_mask);
1656 /* Draw initial magnifying glass contents */
1657 magnifyGetImageStored(panel, x, y, x, y);
1659 pixmap = magnifyCreatePixmap(panel);
1660 XSetWindowBackgroundPixmap(scr->display, WMViewXID(panel->magnifyGlass->view), pixmap);
1661 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1662 XFlush(scr->display);
1664 #ifndef SHAPE
1665 XFreePixmap(scr->display, pixmap);
1666 #endif
1668 point.x = x;
1669 point.y = y;
1671 return point;
1674 static void magnifyPutCursor(WMWidget * w, void *data)
1676 W_ColorPanel *panel = (W_ColorPanel *) (data);
1677 W_Screen *scr = WMWidgetScreen(panel->win);
1678 Cursor magCursor;
1679 Pixmap pixmap;
1680 XEvent event;
1681 WMPoint initialPosition;
1683 /* Destroy wheelBackImg, so it'll update properly */
1684 if (panel->selectionBackImg) {
1685 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1686 panel->selectionBackImg = None;
1689 /* Create magnifying glass */
1690 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1691 panel->magnifyGlass->view = magnifyCreateView(panel);
1692 if (!panel->magnifyGlass->view)
1693 return;
1695 initialPosition = magnifyInitialize(panel);
1696 panel->magnifyGlass->x = initialPosition.x;
1697 panel->magnifyGlass->y = initialPosition.y;
1699 W_MoveView(panel->magnifyGlass->view,
1700 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1701 W_MapView(panel->magnifyGlass->view);
1703 magCursor = magnifyGrabPointer(panel);
1705 while (panel->magnifyGlass->image) {
1706 WMNextEvent(scr->display, &event);
1708 /* Pack motion events */
1709 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1712 switch (event.type) {
1713 case ButtonPress:
1714 XDestroyImage(panel->magnifyGlass->image);
1715 panel->magnifyGlass->image = NULL;
1717 if (event.xbutton.button == Button1) {
1718 panel->color.rgb = panel->magnifyGlass->color;
1719 panel->color.set = cpRGB;
1720 updateSwatch(panel, panel->color);
1722 switch (panel->mode) {
1723 case WMWheelModeColorPanel:
1724 wheelInit(panel);
1725 wheelRender(panel);
1726 wheelPaint(panel);
1727 break;
1728 case WMGrayModeColorPanel:
1729 grayInit(panel);
1730 break;
1731 case WMRGBModeColorPanel:
1732 rgbInit(panel);
1733 break;
1734 case WMCMYKModeColorPanel:
1735 cmykInit(panel);
1736 break;
1737 case WMHSBModeColorPanel:
1738 hsbInit(panel);
1739 break;
1740 default:
1741 break;
1743 panel->lastChanged = panel->mode;
1745 WMSetButtonSelected(panel->magnifyBtn, False);
1746 break;
1748 case MotionNotify:
1749 while (XPending(event.xmotion.display)) {
1750 XEvent ev;
1751 XPeekEvent(event.xmotion.display, &ev);
1752 if (ev.type == MotionNotify)
1753 XNextEvent(event.xmotion.display, &event);
1754 else
1755 break;
1758 /* Get a "dirty rectangle" */
1759 magnifyGetImageStored(panel,
1760 panel->magnifyGlass->x, panel->magnifyGlass->y,
1761 event.xmotion.x_root, event.xmotion.y_root);
1763 /* Update coordinates */
1764 panel->magnifyGlass->x = event.xmotion.x_root;
1765 panel->magnifyGlass->y = event.xmotion.y_root;
1767 /* Move view */
1768 W_MoveView(panel->magnifyGlass->view,
1769 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1771 /* Put new image (with magn.) in view */
1772 pixmap = magnifyCreatePixmap(panel);
1773 if (pixmap != None) {
1774 /* Change the window background */
1775 XSetWindowBackgroundPixmap(scr->display,
1776 WMViewXID(panel->magnifyGlass->view), pixmap);
1777 /* Force an Expose (handled by X) */
1778 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1779 /* Synchronize the event queue, so the Expose is handled NOW */
1780 XFlush(scr->display);
1781 #ifndef SHAPE
1782 XFreePixmap(scr->display, pixmap);
1783 #endif
1785 break;
1787 /* Try XQueryPointer for this !!! It returns windows that the pointer
1788 * is over. Note: We found this solving the invisible donkey cap bug
1790 #if 0 /* As it is impossible to make this work in all cases,
1791 * we consider it confusing. Therefore we disabled it.
1793 case FocusOut: /* fall through */
1794 case FocusIn:
1796 * Color Panel window (panel->win) lost or received focus.
1797 * We need to update the pixmap in the magnifying glass.
1799 * BUG Doesn't work with focus switches between two windows
1800 * if none of them is the color panel.
1802 XUngrabPointer(scr->display, CurrentTime);
1803 W_UnmapView(panel->magnifyGlass->view);
1805 magnifyInitialize(panel);
1807 W_MapView(panel->magnifyGlass->view);
1808 XGrabPointer(scr->display, panel->magnifyGlass->view->window,
1809 True, PointerMotionMask | ButtonPressMask,
1810 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1811 break;
1812 #endif
1813 default:
1814 WMHandleEvent(&event);
1815 break;
1816 } /* of switch */
1819 XUngrabPointer(scr->display, CurrentTime);
1820 XFreeCursor(scr->display, magCursor);
1822 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1823 panel->magnifyGlass->magPix = None;
1825 W_UnmapView(panel->magnifyGlass->view);
1826 W_DestroyView(panel->magnifyGlass->view);
1827 panel->magnifyGlass->view = NULL;
1829 wfree(panel->magnifyGlass);
1832 /****************** ColorWheel Functions ************************/
1834 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height)
1836 wheelMatrix *matrix = NULL;
1837 int i;
1839 assert((width > 0) && (height > 0));
1841 matrix = wmalloc(sizeof(wheelMatrix));
1842 matrix->width = width;
1843 matrix->height = height;
1845 for (i = 0; i < 3; i++) {
1846 matrix->data[i] = wmalloc(width * height * sizeof(unsigned char));
1849 return matrix;
1852 static void wheelDestroyMatrix(wheelMatrix * matrix)
1854 int i;
1856 if (!matrix)
1857 return;
1859 for (i = 0; i < 3; i++) {
1860 if (matrix->data[i])
1861 wfree(matrix->data[i]);
1863 wfree(matrix);
1866 static void wheelInitMatrix(W_ColorPanel * panel)
1868 int i;
1869 int x, y;
1870 unsigned char *rp, *gp, *bp;
1871 CPColor cpColor;
1872 long ofs[4];
1873 int xcor, ycor;
1874 unsigned short sat;
1875 int dhue[4];
1876 const int cw_halfsize = (colorWheelSize + 4) / 2,
1877 cw_sqsize = (colorWheelSize + 4) * (colorWheelSize + 4), uchar_shift = getShift(sizeof(unsigned char));
1879 if (!panel->wheelMtrx)
1880 return;
1882 cpColor.hsv.value = 255;
1883 cpColor.set = cpHSV;
1885 ofs[0] = -1;
1886 ofs[1] = -(colorWheelSize + 4);
1888 /* offsets are counterclockwise (in triangles).
1890 * ofs[0] ---->
1891 * _______________________________________
1892 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
1893 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
1894 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
1895 * o | | | | | | | | | | | | | | | | | | | | | [3]
1897 * <---- ofs[2]
1898 * ____
1899 * |\ /| <-- triangles
1900 * | \/ |
1901 * | /\ |
1902 * |/__\|
1905 for (y = 0; y < cw_halfsize; y++) {
1906 for (x = y; x < (colorWheelSize + 4 - y); x++) {
1907 /* (xcor, ycor) is (x,y) relative to center of matrix */
1908 xcor = 2 * x - 4 - colorWheelSize;
1909 ycor = 2 * y - 4 - colorWheelSize;
1911 /* RColor.saturation is unsigned char and will wrap after 255 */
1912 sat = rint(255.0 * sqrt(xcor * xcor + ycor * ycor) / colorWheelSize);
1914 cpColor.hsv.saturation = (unsigned char)sat;
1916 ofs[0]++; /* top quarter of matrix */
1917 ofs[1] += colorWheelSize + 4; /* left quarter */
1918 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
1919 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
1921 if (sat < 256) {
1922 if (xcor != 0)
1923 dhue[0] = rint(atan((double)ycor / (double)xcor) *
1924 (180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
1925 else
1926 dhue[0] = 270;
1928 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
1929 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
1930 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
1931 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
1933 for (i = 0; i < 4; i++) {
1934 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1935 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1936 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1938 cpColor.hsv.hue = dhue[i];
1939 convertCPColor(&cpColor);
1941 *rp = (unsigned char)(cpColor.rgb.red);
1942 *gp = (unsigned char)(cpColor.rgb.green);
1943 *bp = (unsigned char)(cpColor.rgb.blue);
1945 } else {
1946 for (i = 0; i < 4; i++) {
1947 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1948 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1949 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1951 *rp = (unsigned char)0;
1952 *gp = (unsigned char)0;
1953 *bp = (unsigned char)0;
1958 ofs[0] += 2 * y + 1;
1959 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2 * y);
1963 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue)
1965 unsigned int i;
1966 unsigned int v;
1968 for (i = 0; i < 256; i++) {
1969 /* We divide by 128 in advance, and check whether that number divides
1970 * by 2 properly. If not, we add one to round the number correctly
1972 v = (i * maxvalue) >> 7;
1973 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 0x01));
1977 static void wheelRender(W_ColorPanel * panel)
1979 W_Screen *scr = WMWidgetScreen(panel->win);
1980 int x, y;
1981 RImage *image;
1982 unsigned char *ptr;
1983 RColor gray;
1984 unsigned long ofs = 0;
1985 /*unsigned char shift = getShift(sizeof(unsigned char)); */
1987 image = RCreateImage(colorWheelSize + 4, colorWheelSize + 4, True);
1988 if (!image) {
1989 wwarning(_("Color Panel: Could not allocate memory"));
1990 return;
1993 ptr = image->data;
1995 /* TODO Make this transparent istead of gray */
1996 gray.red = gray.blue = 0xae;
1997 gray.green = 0xaa;
1999 for (y = 0; y < colorWheelSize + 4; y++) {
2000 for (x = 0; x < colorWheelSize + 4; x++) {
2001 if (wheelInsideColorWheel(panel, ofs)) {
2002 *(ptr++) =
2003 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]]);
2004 *(ptr++) =
2005 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]]);
2006 *(ptr++) =
2007 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]]);
2008 *(ptr++) = 0;
2009 } else {
2010 *(ptr++) = (unsigned char)(gray.red);
2011 *(ptr++) = (unsigned char)(gray.green);
2012 *(ptr++) = (unsigned char)(gray.blue);
2013 *(ptr++) = 255;
2015 ofs++;
2019 if (panel->wheelImg)
2020 XFreePixmap(scr->display, panel->wheelImg);
2022 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2023 RReleaseImage(image);
2025 /* Check if backimage exists. If it doesn't, allocate and fill it */
2026 if (!panel->selectionBackImg) {
2027 panel->selectionBackImg = XCreatePixmap(scr->display,
2028 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2029 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2030 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2031 /* -2 is hot spot correction */
2035 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs)
2037 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2038 (panel->wheelMtrx->data[1][ofs] != 0) && (panel->wheelMtrx->data[2][ofs] != 0));
2041 static void wheelPaint(W_ColorPanel * panel)
2043 W_Screen *scr = WMWidgetScreen(panel->win);
2045 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2046 scr->copyGC, 0, 0, colorWheelSize + 4, colorWheelSize + 4, 0, 0);
2048 /* Draw selection image */
2049 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2050 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2053 static void wheelHandleEvents(XEvent * event, void *data)
2055 W_ColorPanel *panel = (W_ColorPanel *) data;
2057 switch (event->type) {
2058 case Expose:
2059 if (event->xexpose.count != 0) /* TODO Improve */
2060 break;
2061 wheelPaint(panel);
2062 break;
2066 static void wheelHandleActionEvents(XEvent * event, void *data)
2068 W_ColorPanel *panel = (W_ColorPanel *) data;
2070 switch (event->type) {
2071 case ButtonPress:
2072 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) == COLORWHEEL_PART) {
2074 panel->lastChanged = WMWheelModeColorPanel;
2075 panel->flags.dragging = 1;
2077 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2079 break;
2081 case ButtonRelease:
2082 panel->flags.dragging = 0;
2083 if (!panel->flags.continuous) {
2084 if (panel->action)
2085 (*panel->action) (panel, panel->clientData);
2087 break;
2089 case MotionNotify:
2090 if (panel->flags.dragging) {
2091 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) == COLORWHEEL_PART) {
2092 wheelPositionSelection(panel, event->xmotion.x, event->xmotion.y);
2093 } else
2094 wheelPositionSelectionOutBounds(panel, event->xmotion.x, event->xmotion.y);
2096 break;
2100 static int getPickerPart(W_ColorPanel * panel, int x, int y)
2102 int lx, ly;
2103 unsigned long ofs;
2105 lx = x;
2106 ly = y;
2108 if (panel->mode == WMWheelModeColorPanel) {
2109 if ((lx >= 2) && (lx <= 2 + colorWheelSize) && (ly >= 2) && (ly <= 2 + colorWheelSize)) {
2111 ofs = ly * panel->wheelMtrx->width + lx;
2113 if (wheelInsideColorWheel(panel, ofs))
2114 return COLORWHEEL_PART;
2118 if (panel->mode == WMCustomPaletteModeColorPanel) {
2119 if ((lx >= 2) && (lx < customPaletteWidth - 2) && (ly >= 2) && (ly < customPaletteHeight - 2)) {
2120 return CUSTOMPALETTE_PART;
2124 return 0;
2127 static void wheelBrightnessSliderCallback(WMWidget * w, void *data)
2129 int value;
2131 W_ColorPanel *panel = (W_ColorPanel *) data;
2133 value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2135 wheelCalculateValues(panel, value);
2137 if (panel->color.set == cpRGB) {
2138 convertCPColor(&panel->color);
2139 panel->color.set = cpHSV;
2142 panel->color.hsv.value = value;
2144 wheelRender(panel);
2145 wheelPaint(panel);
2146 wheelUpdateSelection(panel);
2149 static void wheelUpdateSelection(W_ColorPanel * panel)
2151 W_Screen *scr = WMWidgetScreen(panel->win);
2153 updateSwatch(panel, panel->color);
2154 panel->lastChanged = WMWheelModeColorPanel;
2156 /* Redraw color selector (and make a backup of the part it will cover) */
2157 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2158 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2159 /* "-2" is correction for hotspot location */
2160 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2161 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2162 /* see above */
2165 static void wheelUndrawSelection(W_ColorPanel * panel)
2167 W_Screen *scr = WMWidgetScreen(panel->win);
2169 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2170 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2171 /* see above */
2174 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y)
2176 unsigned long ofs = (y * panel->wheelMtrx->width) + x;
2178 panel->color.rgb.red = panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]];
2180 panel->color.rgb.green = panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]];
2182 panel->color.rgb.blue = panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]];
2183 panel->color.set = cpRGB;
2185 wheelUndrawSelection(panel);
2187 panel->colx = x;
2188 panel->coly = y;
2190 wheelUpdateSelection(panel);
2191 wheelUpdateBrightnessGradientFromLocation(panel);
2194 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2196 int hue;
2197 int xcor, ycor;
2198 CPColor cpColor;
2200 xcor = x * 2 - colorWheelSize - 4;
2201 ycor = y * 2 - colorWheelSize - 4;
2203 panel->color.hsv.saturation = 255;
2204 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2206 if (xcor != 0)
2207 hue = rint(atan(-(double)ycor / (double)xcor) * (180.0 / M_PI));
2208 else {
2209 if (ycor < 0)
2210 hue = 90;
2211 else
2212 hue = 270;
2215 if (xcor < 0)
2216 hue += 180;
2218 if ((xcor > 0) && (ycor > 0))
2219 hue += 360;
2221 panel->color.hsv.hue = hue;
2222 panel->color.set = cpHSV;
2223 convertCPColor(&panel->color);
2225 wheelUndrawSelection(panel);
2227 panel->colx = 2 + rint((colorWheelSize * (1.0 + cos(panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2228 /* "+2" because of "colorWheelSize + 4" */
2229 panel->coly = 2 + rint((colorWheelSize * (1.0 + sin(-panel->color.hsv.hue * (M_PI / 180.0)))) / 2.0);
2231 wheelUpdateSelection(panel);
2232 cpColor = panel->color;
2233 wheelUpdateBrightnessGradient(panel, cpColor);
2236 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel)
2238 CPColor from;
2239 unsigned long ofs;
2241 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2243 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2244 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2245 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2246 from.set = cpRGB;
2248 wheelUpdateBrightnessGradient(panel, from);
2251 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor)
2253 RColor to;
2254 RImage *sliderImg;
2255 WMPixmap *sliderPxmp;
2257 to.red = to.green = to.blue = 0;
2259 if (topColor.set == cpHSV)
2260 convertCPColor(&topColor);
2262 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2263 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win), sliderImg, 0);
2264 RReleaseImage(sliderImg);
2265 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2266 WMReleasePixmap(sliderPxmp);
2269 /****************** Grayscale Panel Functions ***************/
2271 static void grayBrightnessSliderCallback(WMWidget * w, void *data)
2273 CPColor cpColor;
2274 int value;
2275 char tmp[4];
2276 W_ColorPanel *panel = (W_ColorPanel *) data;
2278 value = WMGetSliderValue(panel->grayBrightnessS);
2280 sprintf(tmp, "%d", value);
2282 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2283 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55 * value);
2284 cpColor.set = cpRGB;
2286 updateSwatch(panel, cpColor);
2287 panel->lastChanged = WMGrayModeColorPanel;
2290 static void grayPresetButtonCallback(WMWidget * w, void *data)
2292 CPColor cpColor;
2293 char tmp[4];
2294 int value;
2295 int i = 0;
2296 W_ColorPanel *panel = (W_ColorPanel *) data;
2298 while (i < 7) {
2299 if (w == panel->grayPresetBtn[i])
2300 break;
2301 i++;
2304 value = rint((100.0 * i) / 6.0);
2305 sprintf(tmp, "%d", value);
2307 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2308 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * i) / 6.0);
2309 cpColor.set = cpRGB;
2311 WMSetSliderValue(panel->grayBrightnessS, rint((100.0 * i) / 6.0));
2313 updateSwatch(panel, cpColor);
2314 panel->lastChanged = WMGrayModeColorPanel;
2317 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification)
2319 CPColor cpColor;
2320 char tmp[4];
2321 int value;
2322 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2324 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
2325 if (value > 100)
2326 value = 100;
2327 if (value < 0)
2328 value = 0;
2330 sprintf(tmp, "%d", value);
2331 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2332 WMSetSliderValue(panel->grayBrightnessS, value);
2334 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * value) / 100.0);
2335 cpColor.set = cpRGB;
2337 updateSwatch(panel, cpColor);
2338 panel->lastChanged = WMGrayModeColorPanel;
2341 /******************* RGB Panel Functions *****************/
2343 static void rgbSliderCallback(WMWidget * w, void *data)
2345 CPColor cpColor;
2346 int value[3];
2347 char tmp[4];
2348 W_ColorPanel *panel = (W_ColorPanel *) data;
2350 value[0] = WMGetSliderValue(panel->rgbRedS);
2351 value[1] = WMGetSliderValue(panel->rgbGreenS);
2352 value[2] = WMGetSliderValue(panel->rgbBlueS);
2354 sprintf(tmp, "%d", value[0]);
2355 WMSetTextFieldText(panel->rgbRedT, tmp);
2356 sprintf(tmp, "%d", value[1]);
2357 WMSetTextFieldText(panel->rgbGreenT, tmp);
2358 sprintf(tmp, "%d", value[2]);
2359 WMSetTextFieldText(panel->rgbBlueT, tmp);
2361 cpColor.rgb.red = value[0];
2362 cpColor.rgb.green = value[1];
2363 cpColor.rgb.blue = value[2];
2364 cpColor.set = cpRGB;
2366 updateSwatch(panel, cpColor);
2367 panel->lastChanged = WMRGBModeColorPanel;
2370 static void rgbTextFieldCallback(void *observerData, WMNotification * notification)
2372 CPColor cpColor;
2373 int value[3];
2374 char tmp[4];
2375 int n;
2376 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2378 value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
2379 value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
2380 value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
2382 for (n = 0; n < 3; n++) {
2383 if (value[n] > 255)
2384 value[n] = 255;
2385 if (value[n] < 0)
2386 value[n] = 0;
2389 sprintf(tmp, "%d", value[0]);
2390 WMSetTextFieldText(panel->rgbRedT, tmp);
2391 sprintf(tmp, "%d", value[1]);
2392 WMSetTextFieldText(panel->rgbGreenT, tmp);
2393 sprintf(tmp, "%d", value[2]);
2394 WMSetTextFieldText(panel->rgbBlueT, tmp);
2396 WMSetSliderValue(panel->rgbRedS, value[0]);
2397 WMSetSliderValue(panel->rgbGreenS, value[1]);
2398 WMSetSliderValue(panel->rgbBlueS, value[2]);
2400 cpColor.rgb.red = value[0];
2401 cpColor.rgb.green = value[1];
2402 cpColor.rgb.blue = value[2];
2403 cpColor.set = cpRGB;
2405 updateSwatch(panel, cpColor);
2406 panel->lastChanged = WMRGBModeColorPanel;
2409 /******************* CMYK Panel Functions *****************/
2411 static void cmykSliderCallback(WMWidget * w, void *data)
2413 CPColor cpColor;
2414 int value[4];
2415 char tmp[4];
2416 W_ColorPanel *panel = (W_ColorPanel *) data;
2417 double scale;
2419 value[0] = WMGetSliderValue(panel->cmykCyanS);
2420 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2421 value[2] = WMGetSliderValue(panel->cmykYellowS);
2422 value[3] = WMGetSliderValue(panel->cmykBlackS);
2424 sprintf(tmp, "%d", value[0]);
2425 WMSetTextFieldText(panel->cmykCyanT, tmp);
2426 sprintf(tmp, "%d", value[1]);
2427 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2428 sprintf(tmp, "%d", value[2]);
2429 WMSetTextFieldText(panel->cmykYellowT, tmp);
2430 sprintf(tmp, "%d", value[3]);
2431 WMSetTextFieldText(panel->cmykBlackT, tmp);
2433 scale = 2.55 * (1.0 - (value[3] / 100.0));
2434 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2435 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2436 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2437 cpColor.set = cpRGB;
2439 updateSwatch(panel, cpColor);
2440 panel->lastChanged = WMCMYKModeColorPanel;
2443 static void cmykTextFieldCallback(void *observerData, WMNotification * notification)
2445 CPColor cpColor;
2446 int value[4];
2447 char tmp[4];
2448 int n;
2449 double scale;
2450 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2452 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
2453 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
2454 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
2455 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
2457 for (n = 0; n < 4; n++) {
2458 if (value[n] > 100)
2459 value[n] = 100;
2460 if (value[n] < 0)
2461 value[n] = 0;
2464 sprintf(tmp, "%d", value[0]);
2465 WMSetTextFieldText(panel->cmykCyanT, tmp);
2467 sprintf(tmp, "%d", value[1]);
2468 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2470 sprintf(tmp, "%d", value[2]);
2471 WMSetTextFieldText(panel->cmykYellowT, tmp);
2473 sprintf(tmp, "%d", value[3]);
2474 WMSetTextFieldText(panel->cmykBlackT, tmp);
2476 WMSetSliderValue(panel->cmykCyanS, value[0]);
2477 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2478 WMSetSliderValue(panel->cmykYellowS, value[2]);
2479 WMSetSliderValue(panel->cmykBlackS, value[3]);
2481 scale = 2.55 * (1.0 - (value[3] / 100.0));
2482 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2483 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2484 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2485 cpColor.set = cpRGB;
2487 updateSwatch(panel, cpColor);
2488 panel->lastChanged = WMCMYKModeColorPanel;
2491 /********************** HSB Panel Functions ***********************/
2493 static void hsbSliderCallback(WMWidget * w, void *data)
2495 CPColor cpColor;
2496 int value[3];
2497 char tmp[4];
2498 W_ColorPanel *panel = (W_ColorPanel *) data;
2500 value[0] = WMGetSliderValue(panel->hsbHueS);
2501 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2502 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2504 sprintf(tmp, "%d", value[0]);
2505 WMSetTextFieldText(panel->hsbHueT, tmp);
2506 sprintf(tmp, "%d", value[1]);
2507 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2508 sprintf(tmp, "%d", value[2]);
2509 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2511 cpColor.hsv.hue = value[0];
2512 cpColor.hsv.saturation = value[1] * 2.55;
2513 cpColor.hsv.value = value[2] * 2.55;
2514 cpColor.set = cpHSV;
2516 convertCPColor(&cpColor);
2518 panel->lastChanged = WMHSBModeColorPanel;
2519 updateSwatch(panel, cpColor);
2521 if (w != panel->hsbBrightnessS)
2522 hsbUpdateBrightnessGradient(panel);
2523 if (w != panel->hsbSaturationS)
2524 hsbUpdateSaturationGradient(panel);
2525 if (w != panel->hsbHueS)
2526 hsbUpdateHueGradient(panel);
2529 static void hsbTextFieldCallback(void *observerData, WMNotification * notification)
2531 CPColor cpColor;
2532 int value[3];
2533 char tmp[4];
2534 int n;
2535 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2537 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
2538 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
2539 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
2541 if (value[0] > 359)
2542 value[0] = 359;
2543 if (value[0] < 0)
2544 value[0] = 0;
2546 for (n = 1; n < 3; n++) {
2547 if (value[n] > 100)
2548 value[n] = 100;
2549 if (value[n] < 0)
2550 value[n] = 0;
2553 sprintf(tmp, "%d", value[0]);
2554 WMSetTextFieldText(panel->hsbHueT, tmp);
2555 sprintf(tmp, "%d", value[1]);
2556 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2557 sprintf(tmp, "%d", value[2]);
2558 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2560 WMSetSliderValue(panel->hsbHueS, value[0]);
2561 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2562 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2564 cpColor.hsv.hue = value[0];
2565 cpColor.hsv.saturation = value[1] * 2.55;
2566 cpColor.hsv.value = value[2] * 2.55;
2567 cpColor.set = cpHSV;
2569 convertCPColor(&cpColor);
2571 panel->lastChanged = WMHSBModeColorPanel;
2572 updateSwatch(panel, cpColor);
2574 hsbUpdateBrightnessGradient(panel);
2575 hsbUpdateSaturationGradient(panel);
2576 hsbUpdateHueGradient(panel);
2579 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel)
2581 W_Screen *scr = WMWidgetScreen(panel->win);
2582 RColor from;
2583 CPColor to;
2584 RImage *sliderImg;
2585 WMPixmap *sliderPxmp;
2587 from.red = from.green = from.blue = 0;
2588 to.hsv = panel->color.hsv;
2589 to.hsv.value = 255;
2590 to.set = cpHSV;
2592 convertCPColor(&to);
2594 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2595 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2596 RReleaseImage(sliderImg);
2598 if (sliderPxmp)
2599 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2600 panel->font12, 2, 0, 100, WALeft, scr->white,
2601 False, _("Brightness"), strlen(_("Brightness")));
2602 else
2603 wwarning(_("Color Panel: Could not allocate memory"));
2605 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2606 WMReleasePixmap(sliderPxmp);
2609 static void hsbUpdateSaturationGradient(W_ColorPanel * panel)
2611 W_Screen *scr = WMWidgetScreen(panel->win);
2612 CPColor from;
2613 CPColor to;
2614 RImage *sliderImg;
2615 WMPixmap *sliderPxmp;
2617 from.hsv = panel->color.hsv;
2618 from.hsv.saturation = 0;
2619 from.set = cpHSV;
2620 convertCPColor(&from);
2622 to.hsv = panel->color.hsv;
2623 to.hsv.saturation = 255;
2624 to.set = cpHSV;
2625 convertCPColor(&to);
2627 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb), RGRD_HORIZONTAL);
2628 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2629 RReleaseImage(sliderImg);
2631 if (sliderPxmp)
2632 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2633 panel->font12, 2, 0, 100, WALeft,
2634 from.hsv.value < 128 ? scr->white : scr->black, False,
2635 _("Saturation"), strlen(_("Saturation")));
2636 else
2637 wwarning(_("Color Panel: Could not allocate memory"));
2639 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2640 WMReleasePixmap(sliderPxmp);
2643 static void hsbUpdateHueGradient(W_ColorPanel * panel)
2645 W_Screen *scr = WMWidgetScreen(panel->win);
2646 RColor **colors = NULL;
2647 RHSVColor hsvcolor;
2648 RImage *sliderImg;
2649 WMPixmap *sliderPxmp;
2650 int i;
2652 hsvcolor = panel->color.hsv;
2654 colors = wmalloc(sizeof(RColor *) * (8));
2655 for (i = 0; i < 7; i++) {
2656 hsvcolor.hue = (360 * i) / 6;
2657 colors[i] = wmalloc(sizeof(RColor));
2658 RHSVtoRGB(&hsvcolor, colors[i]);
2660 colors[7] = NULL;
2662 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2663 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2664 RReleaseImage(sliderImg);
2666 if (sliderPxmp)
2667 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2668 panel->font12, 2, 0, 100, WALeft,
2669 hsvcolor.value < 128 ? scr->white : scr->black, False, _("Hue"), strlen(_("Hue")));
2670 else
2671 wwarning(_("Color Panel: Could not allocate memory"));
2673 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2674 WMReleasePixmap(sliderPxmp);
2676 for (i = 0; i < 7; i++)
2677 wfree(colors[i]);
2679 wfree(colors);
2682 /*************** Custom Palette Functions ****************/
2684 static void customRenderSpectrum(W_ColorPanel * panel)
2686 RImage *spectrum;
2687 int x, y;
2688 unsigned char *ptr;
2689 CPColor cpColor;
2691 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2693 ptr = spectrum->data;
2695 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2696 cpColor.hsv.hue = y;
2697 cpColor.hsv.saturation = 0;
2698 cpColor.hsv.value = 255;
2699 cpColor.set = cpHSV;
2701 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2702 convertCPColor(&cpColor);
2704 *(ptr++) = (unsigned char)cpColor.rgb.red;
2705 *(ptr++) = (unsigned char)cpColor.rgb.green;
2706 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2708 if (x < (SPECTRUM_WIDTH / 2))
2709 cpColor.hsv.saturation++;
2711 if (x > (SPECTRUM_WIDTH / 2))
2712 cpColor.hsv.value--;
2715 if (panel->customPaletteImg) {
2716 RReleaseImage(panel->customPaletteImg);
2717 panel->customPaletteImg = NULL;
2719 panel->customPaletteImg = spectrum;
2722 static void customSetPalette(W_ColorPanel * panel)
2724 W_Screen *scr = WMWidgetScreen(panel->win);
2725 RImage *scaledImg;
2726 Pixmap image;
2728 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth, customPaletteHeight, scr->depth);
2729 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth, customPaletteHeight);
2730 RConvertImage(scr->rcontext, scaledImg, &image);
2731 RReleaseImage(scaledImg);
2733 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2734 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2736 /* Check backimage exists. If it doesn't, allocate and fill it */
2737 if (!panel->selectionBackImg) {
2738 panel->selectionBackImg = XCreatePixmap(scr->display,
2739 panel->customPaletteContentView->window, 4, 4, scr->depth);
2742 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2743 panel->palx - 2, panel->paly - 2, 4, 4, 0, 0);
2744 XCopyArea(scr->display, panel->selectionImg,
2745 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2746 panel->palx - 2, panel->paly - 2);
2747 XFreePixmap(scr->display, image);
2749 panel->palXRatio = (double)(panel->customPaletteImg->width) / (double)(customPaletteWidth);
2750 panel->palYRatio = (double)(panel->customPaletteImg->height) / (double)(customPaletteHeight);
2752 WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2755 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y)
2757 W_Screen *scr = WMWidgetScreen(panel->win);
2758 unsigned long ofs;
2760 /* undraw selection */
2761 XCopyArea(scr->display, panel->selectionBackImg,
2762 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2763 panel->palx - 2, panel->paly - 2);
2765 panel->palx = x;
2766 panel->paly = y;
2768 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) * panel->customPaletteImg->width) * 3;
2770 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
2771 panel->color.rgb.green = panel->customPaletteImg->data[ofs + 1];
2772 panel->color.rgb.blue = panel->customPaletteImg->data[ofs + 2];
2773 panel->color.set = cpRGB;
2775 updateSwatch(panel, panel->color);
2776 panel->lastChanged = WMCustomPaletteModeColorPanel;
2778 /* Redraw color selector (and make a backup of the part it will cover) */
2779 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 */
2780 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx - 2, panel->paly - 2); /* see above */
2783 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2785 if (x < 2)
2786 x = 2;
2787 if (y < 2)
2788 y = 2;
2789 if (x >= customPaletteWidth)
2790 x = customPaletteWidth - 2;
2791 if (y >= customPaletteHeight)
2792 y = customPaletteHeight - 2;
2794 customPalettePositionSelection(panel, x, y);
2797 static void customPaletteHandleEvents(XEvent * event, void *data)
2799 W_ColorPanel *panel = (W_ColorPanel *) data;
2801 switch (event->type) {
2802 case Expose:
2803 if (event->xexpose.count != 0) /* TODO Improve. */
2804 break;
2805 customSetPalette(panel);
2806 break;
2810 static void customPaletteHandleActionEvents(XEvent * event, void *data)
2812 W_ColorPanel *panel = (W_ColorPanel *) data;
2813 int x, y;
2815 switch (event->type) {
2816 case ButtonPress:
2817 x = event->xbutton.x;
2818 y = event->xbutton.y;
2820 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2821 panel->flags.dragging = 1;
2822 customPalettePositionSelection(panel, x, y);
2824 break;
2826 case ButtonRelease:
2827 panel->flags.dragging = 0;
2828 if (!panel->flags.continuous) {
2829 if (panel->action)
2830 (*panel->action) (panel, panel->clientData);
2832 break;
2834 case MotionNotify:
2835 x = event->xmotion.x;
2836 y = event->xmotion.y;
2838 if (panel->flags.dragging) {
2839 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2840 customPalettePositionSelection(panel, x, y);
2841 } else
2842 customPalettePositionSelectionOutBounds(panel, x, y);
2844 break;
2848 static void customPaletteMenuCallback(WMWidget * w, void *data)
2850 W_ColorPanel *panel = (W_ColorPanel *) data;
2851 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2853 switch (item) {
2854 case CPmenuNewFromFile:
2855 customPaletteMenuNewFromFile(panel);
2856 break;
2857 case CPmenuRename:
2858 customPaletteMenuRename(panel);
2859 break;
2860 case CPmenuRemove:
2861 customPaletteMenuRemove(panel);
2862 break;
2863 case CPmenuCopy:
2864 break;
2865 case CPmenuNewFromClipboard:
2866 break;
2870 static void customPaletteMenuNewFromFile(W_ColorPanel * panel)
2872 W_Screen *scr = WMWidgetScreen(panel->win);
2873 WMOpenPanel *browseP;
2874 char *filepath;
2875 char *filename = NULL;
2876 char *spath;
2877 char *tmp;
2878 int i;
2879 RImage *tmpImg = NULL;
2881 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir, "\0") == 0))
2882 spath = wexpandpath(wgethomedir());
2883 else
2884 spath = wexpandpath(panel->lastBrowseDir);
2886 browseP = WMGetOpenPanel(scr);
2887 WMSetFilePanelCanChooseDirectories(browseP, 0);
2888 WMSetFilePanelCanChooseFiles(browseP, 1);
2890 /* Get a filename */
2891 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
2892 _("Open Palette"), RSupportedFileFormats())) {
2893 filepath = WMGetFilePanelFileName(browseP);
2895 /* Get seperation position between path and filename */
2896 i = strrchr(filepath, '/') - filepath + 1;
2897 if (i > strlen(filepath))
2898 i = strlen(filepath);
2900 /* Store last browsed path */
2901 if (panel->lastBrowseDir)
2902 wfree(panel->lastBrowseDir);
2903 panel->lastBrowseDir = wmalloc((i + 1) * sizeof(char));
2904 strncpy(panel->lastBrowseDir, filepath, i);
2905 panel->lastBrowseDir[i] = '\0';
2907 /* Get filename from path */
2908 filename = wstrdup(filepath + i);
2910 /* Check for duplicate files, and rename it if there are any */
2911 tmp = wstrconcat(panel->configurationPath, filename);
2912 while (access(tmp, F_OK) == 0) {
2913 char *newName;
2915 wfree(tmp);
2917 newName = generateNewFilename(filename);
2918 wfree(filename);
2919 filename = newName;
2921 tmp = wstrconcat(panel->configurationPath, filename);
2923 wfree(tmp);
2925 /* Copy image to $(gnustepdir)/Library/Colors/ &
2926 * Add filename to history menu */
2927 if (wcopy_file(panel->configurationPath, filepath, filename) == 0) {
2929 /* filepath is a "local" path now the file has been copied */
2930 wfree(filepath);
2931 filepath = wstrconcat(panel->configurationPath, filename);
2933 /* load the image & add menu entries */
2934 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
2935 if (tmpImg) {
2936 if (panel->customPaletteImg)
2937 RReleaseImage(panel->customPaletteImg);
2938 panel->customPaletteImg = tmpImg;
2940 customSetPalette(panel);
2941 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
2943 panel->currentPalette =
2944 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1;
2946 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
2947 panel->currentPalette);
2949 } else {
2950 tmp = wstrconcat(panel->configurationPath, filename);
2952 i = remove(tmp); /* Delete the file, it doesn't belong here */
2953 WMRunAlertPanel(scr, panel->win, _("File Error"),
2954 _("Invalid file format !"), _("OK"), NULL, NULL);
2955 if (i != 0) {
2956 werror(_("can't remove file %s"), tmp);
2957 WMRunAlertPanel(scr, panel->win, _("File Error"),
2958 _("Couldn't remove file from Configuration Directory !"),
2959 _("OK"), NULL, NULL);
2961 wfree(tmp);
2963 wfree(filepath);
2964 wfree(filename);
2966 WMFreeFilePanel(browseP);
2968 wfree(spath);
2971 static void customPaletteMenuRename(W_ColorPanel * panel)
2973 W_Screen *scr = WMWidgetScreen(panel->win);
2974 char *toName = NULL;
2975 char *fromName;
2976 char *toPath, *fromPath;
2977 int item;
2978 int index;
2980 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2981 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
2983 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
2984 fromName, _("OK"), _("Cancel"));
2986 if (toName) {
2988 /* As some people do certain stupid things... */
2989 if (strcmp(toName, fromName) == 0) {
2990 wfree(toName);
2991 return;
2994 /* For normal people */
2995 fromPath = wstrconcat(panel->configurationPath, fromName);
2996 toPath = wstrconcat(panel->configurationPath, toName);
2998 if (access(toPath, F_OK) == 0) {
2999 /* Careful, this palette exists already */
3000 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3001 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3002 NULL) == 1) {
3003 /* "No" = 0, "Yes" = 1 */
3004 int items = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
3006 remove(toPath);
3008 /* Remove from History list too */
3009 index = 1;
3010 while ((index < items)
3012 (strcmp(WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, index), toName)
3013 != 0))
3014 index++;
3016 if (index < items) {
3017 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, index);
3018 if (index < item)
3019 item--;
3022 } else {
3023 wfree(fromPath);
3024 wfree(toName);
3025 wfree(toPath);
3027 return;
3031 if (rename(fromPath, toPath) != 0)
3032 werror(_("Couldn't rename palette %s to %s"), fromName, toName);
3033 else {
3034 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3035 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item, toName);
3037 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3039 wfree(fromPath);
3040 wfree(toPath);
3041 wfree(toName);
3045 static void customPaletteMenuRemove(W_ColorPanel * panel)
3047 W_Screen *scr = WMWidgetScreen(panel->win);
3048 char *text;
3049 char *tmp;
3050 int choice;
3051 int item;
3053 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3055 tmp = wstrconcat(_("This will permanently remove the palette "),
3056 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3057 text = wstrconcat(tmp, _(".\n\nAre you sure you want to remove this palette ?"));
3058 wfree(tmp);
3060 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"), NULL);
3061 /* returns 0 (= "Yes") or 1 (="No") */
3062 wfree(text);
3064 if (choice == 0) {
3066 tmp = wstrconcat(panel->configurationPath,
3067 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3069 if (remove(tmp) == 0) {
3070 /* item-1 always exists */
3071 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3073 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
3074 customSetPalette(panel);
3076 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3078 } else {
3079 werror(_("Couldn't remove palette %s"), tmp);
3082 wfree(tmp);
3086 static void customPaletteHistoryCallback(WMWidget * w, void *data)
3088 W_ColorPanel *panel = (W_ColorPanel *) data;
3089 W_Screen *scr = WMWidgetScreen(panel->win);
3090 int item;
3091 char *filename;
3092 RImage *tmp = NULL;
3093 unsigned char perm_mask;
3095 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3096 if (item == panel->currentPalette)
3097 return;
3099 if (item == 0) {
3100 customRenderSpectrum(panel);
3102 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, False);
3103 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, False);
3104 } else {
3105 /* Load file from configpath */
3106 filename = wstrconcat(panel->configurationPath,
3107 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3109 /* If the file corresponding to the item does not exist,
3110 * remove it from the history list and select the next one.
3112 perm_mask = (access(filename, F_OK) == 0);
3113 if (!perm_mask) {
3114 /* File does not exist */
3115 wfree(filename);
3116 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3117 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3118 customPaletteHistoryCallback(w, data);
3119 return;
3122 /* Get the image */
3123 tmp = RLoadImage(scr->rcontext, filename, 0);
3124 if (tmp) {
3125 if (panel->customPaletteImg) {
3126 RReleaseImage(panel->customPaletteImg);
3127 panel->customPaletteImg = NULL;
3129 panel->customPaletteImg = tmp;
3132 /* If the image is not writable, don't allow removing/renaming */
3133 perm_mask = (access(filename, W_OK) == 0);
3134 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, perm_mask);
3135 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, perm_mask);
3137 wfree(filename);
3139 customSetPalette(panel);
3141 panel->currentPalette = item;
3144 /************************* ColorList Panel Functions **********************/
3146 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
3148 WMScreen *scr = WMWidgetScreen(lPtr);
3149 Display *dpy = WMScreenDisplay(scr);
3150 WMView *view = W_VIEW(lPtr);
3151 RColor *color = (RColor *) WMGetListItem(lPtr, index)->clientData;
3152 W_ColorPanel *panel = WMGetHangedData(lPtr);
3153 int width, height, x, y;
3154 WMColor *fillColor;
3156 width = rect->size.width;
3157 height = rect->size.height;
3158 x = rect->pos.x;
3159 y = rect->pos.y;
3161 if (state & WLDSSelected)
3162 XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
3163 else
3164 XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
3166 fillColor = WMCreateRGBColor(scr, color->red << 8, color->green << 8, color->blue << 8, True);
3168 XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
3169 WMReleaseColor(fillColor);
3171 WMDrawString(scr, d, scr->black, panel->font12, x + 18, y, text, strlen(text));
3174 static void colorListSelect(WMWidget * w, void *data)
3176 W_ColorPanel *panel = (W_ColorPanel *) data;
3177 CPColor cpColor;
3179 cpColor.rgb = *((RColor *) WMGetListSelectedItem(w)->clientData);
3180 cpColor.set = cpRGB;
3182 panel->lastChanged = WMColorListModeColorPanel;
3183 updateSwatch(panel, cpColor);
3186 static void colorListColorMenuCallback(WMWidget * w, void *data)
3188 W_ColorPanel *panel = (W_ColorPanel *) data;
3189 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3191 switch (item) {
3192 case CLmenuAdd:
3193 break;
3194 case CLmenuRename:
3195 break;
3196 case CLmenuRemove:
3197 break;
3201 static void colorListListMenuCallback(WMWidget * w, void *data)
3203 W_ColorPanel *panel = (W_ColorPanel *) data;
3204 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3206 switch (item) {
3207 case CLmenuAdd:
3208 /* New Color List */
3209 colorListListMenuNew(panel);
3210 break;
3211 case CLmenuRename:
3212 break;
3213 case CLmenuRemove:
3214 break;
3218 static void colorListListMenuNew(W_ColorPanel * panel)
3223 /*************** Panel Initialisation Functions *****************/
3225 static void wheelInit(W_ColorPanel * panel)
3227 CPColor cpColor;
3229 if (panel->color.set != cpHSV)
3230 convertCPColor(&panel->color);
3232 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3234 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3235 (1 + (panel->color.hsv.saturation / 255.0) *
3236 cos(panel->color.hsv.hue * M_PI / 180.0)));
3237 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3238 (1 + (panel->color.hsv.saturation / 255.0) *
3239 sin(-panel->color.hsv.hue * M_PI / 180.0)));
3241 wheelCalculateValues(panel, panel->color.hsv.value);
3243 cpColor = panel->color;
3244 cpColor.hsv.value = 255;
3245 cpColor.set = cpHSV;
3246 wheelUpdateBrightnessGradient(panel, cpColor);
3249 static void grayInit(W_ColorPanel * panel)
3251 int value;
3252 char tmp[4];
3254 if (panel->color.set != cpHSV)
3255 convertCPColor(&panel->color);
3257 value = rint(panel->color.hsv.value / 2.55);
3258 WMSetSliderValue(panel->grayBrightnessS, value);
3260 sprintf(tmp, "%d", value);
3261 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3264 static void rgbInit(W_ColorPanel * panel)
3266 char tmp[4];
3268 if (panel->color.set != cpRGB)
3269 convertCPColor(&panel->color);
3271 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3272 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3273 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3275 sprintf(tmp, "%d", panel->color.rgb.red);
3276 WMSetTextFieldText(panel->rgbRedT, tmp);
3277 sprintf(tmp, "%d", panel->color.rgb.green);
3278 WMSetTextFieldText(panel->rgbGreenT, tmp);
3279 sprintf(tmp, "%d", panel->color.rgb.blue);
3280 WMSetTextFieldText(panel->rgbBlueT, tmp);
3283 static void cmykInit(W_ColorPanel * panel)
3285 int value[3];
3286 char tmp[4];
3288 if (panel->color.set != cpRGB)
3289 convertCPColor(&panel->color);
3291 value[0] = rint((255 - panel->color.rgb.red) / 2.55);
3292 value[1] = rint((255 - panel->color.rgb.green) / 2.55);
3293 value[2] = rint((255 - panel->color.rgb.blue) / 2.55);
3295 WMSetSliderValue(panel->cmykCyanS, value[0]);
3296 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3297 WMSetSliderValue(panel->cmykYellowS, value[2]);
3298 WMSetSliderValue(panel->cmykBlackS, 0);
3300 sprintf(tmp, "%d", value[0]);
3301 WMSetTextFieldText(panel->cmykCyanT, tmp);
3302 sprintf(tmp, "%d", value[1]);
3303 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3304 sprintf(tmp, "%d", value[2]);
3305 WMSetTextFieldText(panel->cmykYellowT, tmp);
3306 WMSetTextFieldText(panel->cmykBlackT, "0");
3309 static void hsbInit(W_ColorPanel * panel)
3311 int value[3];
3312 char tmp[4];
3314 if (panel->color.set != cpHSV)
3315 convertCPColor(&panel->color);
3317 value[0] = panel->color.hsv.hue;
3318 value[1] = rint(panel->color.hsv.saturation / 2.55);
3319 value[2] = rint(panel->color.hsv.value / 2.55);
3321 WMSetSliderValue(panel->hsbHueS, value[0]);
3322 WMSetSliderValue(panel->hsbSaturationS, value[1]);
3323 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
3325 sprintf(tmp, "%d", value[0]);
3326 WMSetTextFieldText(panel->hsbHueT, tmp);
3327 sprintf(tmp, "%d", value[1]);
3328 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3329 sprintf(tmp, "%d", value[2]);
3330 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3332 hsbUpdateBrightnessGradient(panel);
3333 hsbUpdateSaturationGradient(panel);
3334 hsbUpdateHueGradient(panel);
3337 /************************** Common utility functions ************************/
3339 char *generateNewFilename(char *curName)
3341 int n;
3342 char c;
3343 int baseLen;
3344 char *ptr;
3345 char *newName;
3347 assert(curName);
3349 ptr = curName;
3351 if (((ptr = strrchr(ptr, '{')) == 0) || sscanf(ptr, "{%i}%c", &n, &c) != 1)
3352 return wstrconcat(curName, " {1}");
3354 baseLen = ptr - curName - 1;
3356 newName = wmalloc(baseLen + 16);
3357 strncpy(newName, curName, baseLen);
3359 snprintf(&newName[baseLen], 16, " {%i}", n + 1);
3361 return newName;
3364 void convertCPColor(CPColor * color)
3366 unsigned short old_hue = 0;
3368 switch (color->set) {
3369 case cpNone:
3370 wwarning(_("Color Panel: Color unspecified"));
3371 return;
3372 case cpRGB:
3373 old_hue = color->hsv.hue;
3374 RRGBtoHSV(&(color->rgb), &(color->hsv));
3376 /* In black the hue is undefined, and may change by conversion
3377 * Same for white. */
3378 if (((color->rgb.red == 0) &&
3379 (color->rgb.green == 0) &&
3380 (color->rgb.blue == 0)) ||
3381 ((color->rgb.red == 0) && (color->rgb.green == 0) && (color->rgb.blue == 255))
3383 color->hsv.hue = old_hue;
3384 break;
3385 case cpHSV:
3386 RHSVtoRGB(&(color->hsv), &(color->rgb));
3387 break;
3391 #define ABS_SHIFT(val, shift) \
3392 (((shift) > 0) ? (val) >> (shift) : (val) << -(shift))