Update for 0.51.0
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob0d89f81b369657ab4320e740feb82c393f1b5fa3
1 /*
2 * ColorPanel for WINGs
4 * by ]d : Original idea and basic initial code
5 * Pascal Hofstee : Code for wheeldrawing and calculating colors from it
6 * Alban Hertroys : Suggesting optimizations for algorithms for color-
7 * wheel, and implementation of final algorithm.
8 * Alfredo K. Kojima : For pointing out some memory-allocation problems.
9 * Marco van Hylckama-Vlieg : For once again doing the artwork ;-)
13 #include "WINGsP.h"
14 #include <math.h>
15 #include <unistd.h>
16 #include <ctype.h>
17 #include <fcntl.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <dirent.h>
21 #include <errno.h>
24 #ifndef PATH_MAX
25 #define PATH_MAX 1024
26 #endif
29 typedef struct WheelMatrix {
30 unsigned int width, height; /* Size of the colorwheel */
31 unsigned char *data[3]; /* Wheel data (R,G,B) */
32 unsigned char values[256]; /* Precalculated values for R,G & B values 0..255 */
33 } wheelMatrix;
35 typedef struct W_ColorPanel {
36 WMWindow *win;
38 /* Common Stuff */
39 WMColorWell *colorWell;
40 WMButton *magnifyBtn;
41 WMButton *wheelBtn;
42 WMButton *slidersBtn;
43 WMButton *customPaletteBtn;
44 WMButton *colorListBtn;
47 /* ColorWheel Panel */
48 WMFrame *wheelFrm;
49 WMSlider *wheelBrightnessS;
50 WMView *wheelView;
52 /* Slider Panels */
53 WMFrame *slidersFrm;
54 WMFrame *seperatorFrm;
55 WMButton *grayBtn;
56 WMButton *rgbBtn;
57 WMButton *cmykBtn;
58 WMButton *hsbBtn;
59 /* Gray Scale Panel */
60 WMFrame *grayFrm;
61 WMLabel *grayMinL;
62 WMLabel *grayMaxL;
63 WMSlider *grayBrightnessS;
64 WMTextField *grayBrightnessT;
65 WMButton *grayPresetBtn[7];
67 /* RGB Panel */
68 WMFrame *rgbFrm;
69 WMLabel *rgbMinL;
70 WMLabel *rgbMaxL;
71 WMSlider *rgbRedS;
72 WMSlider *rgbGreenS;
73 WMSlider *rgbBlueS;
74 WMTextField *rgbRedT;
75 WMTextField *rgbGreenT;
76 WMTextField *rgbBlueT;
78 /* CMYK Panel */
79 WMFrame *cmykFrm;
80 WMLabel *cmykMinL;
81 WMLabel *cmykMaxL;
82 WMSlider *cmykCyanS;
83 WMSlider *cmykMagentaS;
84 WMSlider *cmykYellowS;
85 WMSlider *cmykBlackS;
86 WMTextField *cmykCyanT;
87 WMTextField *cmykMagentaT;
88 WMTextField *cmykYellowT;
89 WMTextField *cmykBlackT;
91 /* HSB Panel */
92 WMFrame *hsbFrm;
93 WMSlider *hsbHueS;
94 WMSlider *hsbSaturationS;
95 WMSlider *hsbBrightnessS;
96 WMTextField *hsbHueT;
97 WMTextField *hsbSaturationT;
98 WMTextField *hsbBrightnessT;
100 /* Custom Palette Panel*/
101 WMFrame *customPaletteFrm;
102 WMPopUpButton *customPaletteHistoryBtn;
103 WMFrame *customPaletteContentFrm;
104 WMPopUpButton *customPaletteMenuBtn;
105 WMView *customPaletteContentView;
107 /* Color List Panel */
108 WMFrame *colorListFrm;
109 WMPopUpButton *colorListHistoryBtn;
110 WMList *colorListContentLst;
111 WMPopUpButton *colorListColorMenuBtn;
112 WMPopUpButton *colorListListMenuBtn;
114 /* Look-Up Tables and Images */
115 wheelMatrix *wheelMtrx;
116 Pixmap wheelImg;
117 Pixmap selectionImg;
118 Pixmap selectionBackImg;
119 RImage *customPaletteImg;
120 char *lastBrowseDir;
122 /* Common Data Fields */
123 RColor color; /* Current color */
124 RHSVColor hsvcolor; /* Backup HSV Color */
125 WMColorPanelMode mode; /* Current color selection mode */
126 WMColorPanelMode slidersmode; /* Current color selection mode at sliders panel */
127 WMColorPanelMode lastChanged; /* Panel that last changed the color */
128 int colx, coly; /* (x,y) of selection-marker in WheelMode */
129 int palx, paly; /* (x,y) of selection-marker in CustomPaletteMode */
130 float palXRatio, palYRatio; /* Ratios in x & y between original and scaled palettesize */
131 int currentPalette;
132 char *configurationPath;
134 struct {
135 unsigned int dragging:1;
136 unsigned int done:1;
137 } flags;
138 } W_ColorPanel;
140 enum {
141 menuNewFromFile,
142 menuRename,
143 menuRemove,
144 menuCopy,
145 menuNewFromClipboard
146 } customPaletteMenuItem;
148 #define PWIDTH 194
149 #define PHEIGHT 266
150 #define colorWheelSize 150
151 #define customPaletteWidth 182
152 #define customPaletteHeight 106
153 #define knobThickness 8
155 #define SPECTRUM_WIDTH 511
156 #define SPECTRUM_HEIGHT 360
158 #define COLORWHEEL_PART 1
159 #define CUSTOMPALETTE_PART 2
160 #define BUFSIZE 1024
162 #undef EASTEREGG
164 #define RGBTXT "/usr/X11R6/lib/X11/rgb.txt"
165 #define MAX_LENGTH 1024
168 WMFont *globalFont;
171 static int fetchImageFile(char* toPath, char *imageSrcFile, char *imageDestFileName);
172 char *generateNewFilename(char *Path, char *curName);
174 static void modeButtonCallback(WMWidget *w, void *data);
175 static int getPickerPart(W_ColorPanel *panel, int x, int y);
176 static void readConfiguration(W_ColorPanel *panel);
177 static void readXColors(W_ColorPanel *panel);
179 static wheelMatrix* wheelCreateMatrix(unsigned int width , unsigned int height);
180 static void wheelDestroyMatrix(wheelMatrix *matrix);
181 static wheelMatrix* wheelInitMatrix(W_ColorPanel *panel);
182 static void wheelRender(W_ColorPanel *panel);
183 static Bool wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs);
184 static void wheelPaint(W_ColorPanel *panel);
186 static void wheelHandleEvents(XEvent *event, void *data);
187 static void wheelHandleActionEvents(XEvent *event, void *data);
188 static void wheelBrightnessSliderCallback(WMWidget *w, void *data);
189 static void wheelUpdateSelection(W_ColorPanel *panel);
190 static void wheelUndrawSelection(W_ColorPanel *panel);
192 static void wheelPositionSelection(W_ColorPanel *panel, int x, int y);
193 static void wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y);
194 static void wheelUpdateBrightnessGradientFromHSV (W_ColorPanel *panel, RHSVColor topColor);
195 static void wheelUpdateBrightnessGradientFromLocation (W_ColorPanel *panel);
196 static void wheelUpdateBrightnessGradient(W_ColorPanel *panel, RColor topColor);
198 static void grayBrightnessSliderCallback(WMWidget *w, void *data);
199 static void grayPresetButtonCallback(WMWidget *w, void *data);
200 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification *notification);
202 static void rgbSliderCallback(WMWidget *w, void *data);
203 static void rgbTextFieldCallback(void *observerData, WMNotification *notification);
205 static void cmykSliderCallback(WMWidget *w, void *data);
206 static void cmykTextFieldCallback(void *observerData, WMNotification *notification);
208 static void hsbSliderCallback(WMWidget *w, void *data);
209 static void hsbTextFieldCallback(void *observerData, WMNotification *notification);
210 static void hsbUpdateBrightnessGradient(W_ColorPanel *panel);
211 static void hsbUpdateSaturationGradient(W_ColorPanel *panel);
212 static void hsbUpdateHueGradient(W_ColorPanel *panel);
214 static void customRenderSpectrum(W_ColorPanel *panel);
215 static void customSetPalette(W_ColorPanel *panel);
216 static void customPaletteHandleEvents(XEvent *event, void *data);
217 static void customPaletteHandleActionEvents(XEvent *event, void *data);
218 static void customPalettePositionSelection(W_ColorPanel *panel, int x, int y);
219 static void customPalettePositionSelectionOutBounds(W_ColorPanel *panel, int x, int y);
220 static void customPaletteMenuCallback(WMWidget *w, void *data);
221 static void customPaletteHistoryCallback(WMWidget *w, void *data);
223 static void customPaletteMenuNewFromFile(W_ColorPanel *panel);
224 static void customPaletteMenuRename(W_ColorPanel *panel);
225 static void customPaletteMenuRemove(W_ColorPanel *panel);
227 static void colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text, int state, WMRect *rect);
228 static void colorListSelect(WMWidget *w, void *data);
230 static void wheelInit(W_ColorPanel *panel);
231 static void grayInit(W_ColorPanel *panel);
232 static void rgbInit(W_ColorPanel *panel);
233 static void cmykInit(W_ColorPanel *panel);
234 static void hsbInit(W_ColorPanel *panel);
237 static WMColorPanel*
238 makeColorPanel(WMScreen *scrPtr, char *name)
240 WMColorPanel *panel;
241 RImage *image;
242 WMPixmap *pixmap;
243 RColor from;
244 RColor to;
245 int i;
246 int x,y;
249 globalFont = WMSystemFontOfSize(scrPtr, 12);
250 panel = wmalloc(sizeof(WMColorPanel));
251 memset(panel, 0, sizeof(WMColorPanel));
253 panel->win = WMCreateWindowWithStyle(scrPtr, name, WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
254 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
255 WMSetWindowTitle(panel->win, "Colors");
258 /* Set Default ColorPanel Mode(s) */
259 panel->mode = WMWheelModeColorPanel;
260 panel->lastChanged = WMWheelModeColorPanel;
261 panel->slidersmode = WMRGBModeColorPanel;
262 panel->configurationPath = wstrappend(wusergnusteppath(), "/Library/Colors/");
264 /* Some Generic Purpose Widgets */
265 panel->colorWell = WMCreateColorWell(panel->win);
266 WMResizeWidget(panel->colorWell, 134, 36);
267 WSetColorWellBordered(panel->colorWell, False);
268 WMMoveWidget(panel->colorWell, 56, 4);
270 panel->magnifyBtn = WMCreateCommandButton(panel->win);
271 WMResizeWidget(panel->magnifyBtn, 46, 36);
272 WMMoveWidget(panel->magnifyBtn, 6,4);
273 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
274 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
275 WMSetButtonAltImage(panel->magnifyBtn, scrPtr->magnifyAltIcon);
277 panel->wheelBtn = WMCreateCustomButton(panel->win, WBBStateLightMask|WBBStateChangeMask);
278 WMResizeWidget(panel->wheelBtn, 46, 32);
279 WMMoveWidget(panel->wheelBtn, 6, 44);
280 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
281 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
282 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
283 WMSetButtonAltImage(panel->wheelBtn, scrPtr->wheelAltIcon);
285 panel->slidersBtn = WMCreateCustomButton(panel->win, WBBStateLightMask|WBBStateChangeMask);
286 WMResizeWidget(panel->slidersBtn, 46, 32);
287 WMMoveWidget(panel->slidersBtn, 52, 44);
288 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
289 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
290 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
291 WMSetButtonAltImage(panel->slidersBtn, scrPtr->rgbAltIcon);
293 panel->customPaletteBtn = WMCreateCustomButton(panel->win, WBBStateLightMask|WBBStateChangeMask);
294 WMResizeWidget(panel->customPaletteBtn, 46, 32);
295 WMMoveWidget(panel->customPaletteBtn, 98, 44);
296 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
297 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
298 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
299 WMSetButtonAltImage(panel->customPaletteBtn, scrPtr->customPaletteAltIcon);
301 panel->colorListBtn = WMCreateCustomButton(panel->win, WBBStateLightMask|WBBStateChangeMask);
302 WMResizeWidget(panel->colorListBtn, 46, 32);
303 WMMoveWidget(panel->colorListBtn, 144, 44);
304 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
305 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
306 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
307 WMSetButtonAltImage(panel->colorListBtn, scrPtr->colorListAltIcon);
309 /* Let's Group some of them together */
310 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
311 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
312 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
314 /* Widgets for the ColorWheel Panel */
315 panel->wheelFrm = WMCreateFrame(panel->win);
316 WMSetFrameRelief(panel->wheelFrm, WRFlat);
317 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
318 WMMoveWidget(panel->wheelFrm, 5, 80);
320 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
321 /* XXX Can we create a view ? */
322 W_ResizeView(panel->wheelView, colorWheelSize+4, colorWheelSize+4);
323 W_MoveView(panel->wheelView, 0, 0);
325 /* Create an event handler to handle expose/click events in the ColorWheel */
326 WMCreateEventHandler(panel->wheelView, ButtonPressMask|ButtonReleaseMask|EnterWindowMask
327 |LeaveWindowMask|ButtonMotionMask, wheelHandleActionEvents, panel);
329 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents, panel);
331 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
332 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
333 WMMoveWidget(panel->wheelBrightnessS, 5+colorWheelSize+14, 1);
334 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
335 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
336 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback, panel);
337 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
340 /* Widgets for the Slider Panels */
341 panel->slidersFrm = WMCreateFrame(panel->win);
342 WMSetFrameRelief(panel->slidersFrm, WRFlat);
343 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
344 WMMoveWidget(panel->slidersFrm, 4, 80);
346 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
347 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
348 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
349 WMMoveWidget(panel->seperatorFrm, 0, 1);
351 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask|WBBStateChangeMask);
352 WMResizeWidget(panel->grayBtn, 46, 24);
353 WMMoveWidget(panel->grayBtn, 1, 8);
354 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
355 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
356 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
357 WMSetButtonAltImage(panel->grayBtn, scrPtr->grayAltIcon);
359 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask|WBBStateChangeMask);
360 WMResizeWidget(panel->rgbBtn, 46, 24);
361 WMMoveWidget(panel->rgbBtn, 47, 8);
362 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
363 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
364 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
365 WMSetButtonAltImage(panel->rgbBtn, scrPtr->rgbAltIcon);
367 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask|WBBStateChangeMask);
368 WMResizeWidget(panel->cmykBtn, 46, 24);
369 WMMoveWidget(panel->cmykBtn, 93, 8);
370 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
371 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
372 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
373 WMSetButtonAltImage(panel->cmykBtn, scrPtr->cmykAltIcon);
375 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask|WBBStateChangeMask);
376 WMResizeWidget(panel->hsbBtn, 46, 24);
377 WMMoveWidget(panel->hsbBtn, 139, 8);
378 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
379 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
380 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
381 WMSetButtonAltImage(panel->hsbBtn, scrPtr->hsbAltIcon);
383 /* Let's Group the Slider Panel Buttons Together */
384 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
385 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
386 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
388 /* Widgets for GrayScale Panel */
389 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
390 WMSetFrameRelief(panel->grayFrm, WRFlat);
391 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
392 WMMoveWidget(panel->grayFrm, 0, 34);
394 panel->grayMinL = WMCreateLabel(panel->grayFrm);
395 WMResizeWidget(panel->grayMinL, 20, 10);
396 WMMoveWidget(panel->grayMinL, 2, 2);
397 WMSetLabelText(panel->grayMinL, "0");
398 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
399 WMSetLabelTextColor(panel->grayMinL, WMDarkGrayColor(scrPtr));
400 WMSetLabelFont(panel->grayMinL, WMSystemFontOfSize(scrPtr, 8));
402 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
403 WMResizeWidget(panel->grayMaxL, 40, 10);
404 WMMoveWidget(panel->grayMaxL, 104, 2);
405 WMSetLabelText(panel->grayMaxL, "100");
406 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
407 WMSetLabelTextColor(panel->grayMaxL, WMDarkGrayColor(scrPtr));
408 WMSetLabelFont(panel->grayMaxL, WMSystemFontOfSize(scrPtr, 8));
410 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
411 WMResizeWidget(panel->grayBrightnessS, 141, 16);
412 WMMoveWidget(panel->grayBrightnessS, 2, 14);
413 WMSetSliderMinValue(panel->grayBrightnessS, 0);
414 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
415 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
416 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback, panel);
418 from.red = 0;
419 from.green = 0;
420 from.blue = 0;
422 to.red = 255;
423 to.green = 255;
424 to.blue = 255;
426 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
427 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
428 RDestroyImage(image);
429 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap, WMSystemFontOfSize(scrPtr, 12), 2, 0, 100, WALeft, W_GC(scrPtr->white), False, "Brightness", strlen("Brightness"));
430 WMSetSliderImage(panel->grayBrightnessS, pixmap);
431 WMReleasePixmap(pixmap);
433 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
434 WMResizeWidget(panel->grayBrightnessT, 40, 18);
435 WMMoveWidget(panel->grayBrightnessT, 146, 13);
436 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
437 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel, \
438 WMTextDidEndEditingNotification, panel->grayBrightnessT);
440 image = RCreateImage(13,13,False);
441 for (i=0; i < 7; i++) {
442 for (x=0; x < 13; x++) {
443 for (y=0; y < 13; y++) {
444 image->data[0][y*13+x] = 255/6*i;
445 image->data[1][y*13+x] = 255/6*i;
446 image->data[2][y*13+x] = 255/6*i;
449 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
450 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
451 WMMoveWidget(panel->grayPresetBtn[i], 2+(i*20), 34);
452 WMSetButtonAction(panel->grayPresetBtn[i], grayPresetButtonCallback, panel);
453 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
454 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
455 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
456 WMReleasePixmap(pixmap);
458 RDestroyImage(image);
459 /* End of GrayScale Panel */
461 /* Widgets for RGB Panel */
462 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
463 WMSetFrameRelief(panel->rgbFrm, WRFlat);
464 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
465 WMMoveWidget(panel->rgbFrm, 0, 34);
467 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
468 WMResizeWidget(panel->rgbMinL, 20, 10);
469 WMMoveWidget(panel->rgbMinL, 2, 2);
470 WMSetLabelText(panel->rgbMinL, "0");
471 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
472 WMSetLabelTextColor(panel->rgbMinL, WMDarkGrayColor(scrPtr));
473 WMSetLabelFont(panel->rgbMinL, WMSystemFontOfSize(scrPtr, 8));
475 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
476 WMResizeWidget(panel->rgbMaxL, 40, 10);
477 WMMoveWidget(panel->rgbMaxL, 104, 2);
478 WMSetLabelText(panel->rgbMaxL, "255");
479 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
480 WMSetLabelTextColor(panel->rgbMaxL, WMDarkGrayColor(scrPtr));
481 WMSetLabelFont(panel->rgbMaxL, WMSystemFontOfSize(scrPtr, 8));
483 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
484 WMResizeWidget(panel->rgbRedS, 141, 16);
485 WMMoveWidget(panel->rgbRedS, 2, 14);
486 WMSetSliderMinValue(panel->rgbRedS, 0);
487 WMSetSliderMaxValue(panel->rgbRedS, 255);
488 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
489 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
491 to.red = 255;
492 to.green = 0;
493 to.blue = 0;
495 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
496 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
497 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, WMSystemFontOfSize(scrPtr, 12), 2, 0, 100, WALeft, W_GC(scrPtr->white), False, "Red", strlen("Red"));
498 RDestroyImage(image);
499 WMSetSliderImage(panel->rgbRedS, pixmap);
500 WMReleasePixmap(pixmap);
502 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
503 WMResizeWidget(panel->rgbRedT, 40, 18);
504 WMMoveWidget(panel->rgbRedT, 146, 13);
505 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
506 WMAddNotificationObserver(rgbTextFieldCallback, panel, \
507 WMTextDidEndEditingNotification, panel->rgbRedT);
510 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
511 WMResizeWidget(panel->rgbGreenS, 141, 16);
512 WMMoveWidget(panel->rgbGreenS, 2, 36);
513 WMSetSliderMinValue(panel->rgbGreenS, 0);
514 WMSetSliderMaxValue(panel->rgbGreenS, 255);
515 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
516 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
518 to.red = 0;
519 to.green = 255;
520 to.blue = 0;
522 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
523 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
524 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, WMSystemFontOfSize(scrPtr, 12), 2, 0, 100, WALeft, W_GC(scrPtr->white), False, "Green", strlen("Green"));
525 RDestroyImage(image);
526 WMSetSliderImage(panel->rgbGreenS, pixmap);
527 WMReleasePixmap(pixmap);
529 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
530 WMResizeWidget(panel->rgbGreenT, 40, 18);
531 WMMoveWidget(panel->rgbGreenT, 146, 35);
532 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
533 WMAddNotificationObserver(rgbTextFieldCallback, panel, \
534 WMTextDidEndEditingNotification, panel->rgbGreenT);
537 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
538 WMResizeWidget(panel->rgbBlueS, 141, 16);
539 WMMoveWidget(panel->rgbBlueS, 2, 58);
540 WMSetSliderMinValue(panel->rgbBlueS, 0);
541 WMSetSliderMaxValue(panel->rgbBlueS, 255);
542 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
543 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
545 to.red = 0;
546 to.green = 0;
547 to.blue = 255;
549 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
550 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
551 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, WMSystemFontOfSize(scrPtr, 12), 2, 0, 100, WALeft, W_GC(scrPtr->white), False, "Blue", strlen("Blue"));
552 RDestroyImage(image);
553 WMSetSliderImage(panel->rgbBlueS, pixmap);
554 WMReleasePixmap(pixmap);
556 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
557 WMResizeWidget(panel->rgbBlueT, 40, 18);
558 WMMoveWidget(panel->rgbBlueT, 146, 57);
559 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
560 WMAddNotificationObserver(rgbTextFieldCallback, panel, \
561 WMTextDidEndEditingNotification, panel->rgbBlueT);
562 /* End of RGB Panel */
564 /* Widgets for CMYK Panel */
565 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
566 WMSetFrameRelief(panel->cmykFrm, WRFlat);
567 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
568 WMMoveWidget(panel->cmykFrm, 0, 34);
570 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
571 WMResizeWidget(panel->cmykMinL, 20, 10);
572 WMMoveWidget(panel->cmykMinL, 2, 2);
573 WMSetLabelText(panel->cmykMinL, "0");
574 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
575 WMSetLabelTextColor(panel->cmykMinL, WMDarkGrayColor(scrPtr));
576 WMSetLabelFont(panel->cmykMinL, WMSystemFontOfSize(scrPtr, 8));
578 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
579 WMResizeWidget(panel->cmykMaxL, 40, 10);
580 WMMoveWidget(panel->cmykMaxL, 104, 2);
581 WMSetLabelText(panel->cmykMaxL, "100");
582 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
583 WMSetLabelTextColor(panel->cmykMaxL, WMDarkGrayColor(scrPtr));
584 WMSetLabelFont(panel->cmykMaxL, WMSystemFontOfSize(scrPtr, 8));
586 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
587 WMResizeWidget(panel->cmykCyanS, 141, 16);
588 WMMoveWidget(panel->cmykCyanS, 2, 14);
589 WMSetSliderMinValue(panel->cmykCyanS, 0);
590 WMSetSliderMaxValue(panel->cmykCyanS, 100);
591 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
592 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
594 from.red = 255;
595 from.green = 255;
596 from.blue = 255;
598 to.red = 0;
599 to.green = 255;
600 to.blue = 255;
602 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
603 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
604 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, WMSystemFontOfSize(scrPtr, 12), 2, 0, 100, WALeft, W_GC(scrPtr->black), False, "Cyan", strlen("Cyan"));
605 RDestroyImage(image);
606 WMSetSliderImage(panel->cmykCyanS, pixmap);
607 WMReleasePixmap(pixmap);
609 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
610 WMResizeWidget(panel->cmykCyanT, 40, 18);
611 WMMoveWidget(panel->cmykCyanT, 146, 13);
612 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
613 WMAddNotificationObserver(cmykTextFieldCallback, panel, \
614 WMTextDidEndEditingNotification, panel->cmykCyanT);
617 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
618 WMResizeWidget(panel->cmykMagentaS, 141, 16);
619 WMMoveWidget(panel->cmykMagentaS, 2, 36);
620 WMSetSliderMinValue(panel->cmykMagentaS, 0);
621 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
622 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
623 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
625 to.red = 255;
626 to.green = 0;
627 to.blue = 255;
629 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
630 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
631 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, WMSystemFontOfSize(scrPtr, 12), 2, 0, 100, WALeft, W_GC(scrPtr->black), False, "Magenta", strlen("Magenta"));
632 RDestroyImage(image);
633 WMSetSliderImage(panel->cmykMagentaS, pixmap);
634 WMReleasePixmap(pixmap);
636 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
637 WMResizeWidget(panel->cmykMagentaT, 40, 18);
638 WMMoveWidget(panel->cmykMagentaT, 146, 35);
639 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
640 WMAddNotificationObserver(cmykTextFieldCallback, panel, \
641 WMTextDidEndEditingNotification, panel->cmykMagentaT);
644 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
645 WMResizeWidget(panel->cmykYellowS, 141, 16);
646 WMMoveWidget(panel->cmykYellowS, 2, 58);
647 WMSetSliderMinValue(panel->cmykYellowS, 0);
648 WMSetSliderMaxValue(panel->cmykYellowS, 100);
649 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
650 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
652 to.red = 255;
653 to.green = 255;
654 to.blue = 0;
656 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
657 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
658 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, WMSystemFontOfSize(scrPtr, 12), 2, 0, 100, WALeft, W_GC(scrPtr->black), False, "Yellow", strlen("Yellow"));
659 RDestroyImage(image);
660 WMSetSliderImage(panel->cmykYellowS, pixmap);
661 WMReleasePixmap(pixmap);
663 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
664 WMResizeWidget(panel->cmykYellowT, 40, 18);
665 WMMoveWidget(panel->cmykYellowT, 146, 57);
666 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
667 WMAddNotificationObserver(cmykTextFieldCallback, panel, \
668 WMTextDidEndEditingNotification, panel->cmykYellowT);
671 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
672 WMResizeWidget(panel->cmykBlackS, 141, 16);
673 WMMoveWidget(panel->cmykBlackS, 2, 80);
674 WMSetSliderMinValue(panel->cmykBlackS, 0);
675 WMSetSliderMaxValue(panel->cmykBlackS, 100);
676 WMSetSliderValue(panel->cmykBlackS, 0);
677 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
678 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
680 to.red = 0;
681 to.green = 0;
682 to.blue = 0;
684 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
685 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
686 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, WMSystemFontOfSize(scrPtr, 12), 2, 0, 100, WALeft, W_GC(scrPtr->black), False, "Black", strlen("Black"));
687 RDestroyImage(image);
688 WMSetSliderImage(panel->cmykBlackS, pixmap);
689 WMReleasePixmap(pixmap);
691 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
692 WMResizeWidget(panel->cmykBlackT, 40, 18);
693 WMMoveWidget(panel->cmykBlackT, 146, 79);
694 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
695 WMAddNotificationObserver(cmykTextFieldCallback, panel, \
696 WMTextDidEndEditingNotification, panel->cmykBlackT);
697 /* End of CMYK Panel */
699 /* Widgets for HSB Panel */
700 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
701 WMSetFrameRelief(panel->hsbFrm, WRFlat);
702 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
703 WMMoveWidget(panel->hsbFrm, 0, 34);
705 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
706 WMResizeWidget(panel->hsbHueS, 141, 16);
707 WMMoveWidget(panel->hsbHueS, 2, 14);
708 WMSetSliderMinValue(panel->hsbHueS, 0);
709 WMSetSliderMaxValue(panel->hsbHueS, 359);
710 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
711 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
713 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
714 WMResizeWidget(panel->hsbHueT, 40, 18);
715 WMMoveWidget(panel->hsbHueT, 146, 13);
716 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
717 WMAddNotificationObserver(hsbTextFieldCallback, panel, \
718 WMTextDidEndEditingNotification, panel->hsbHueT);
721 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
722 WMResizeWidget(panel->hsbSaturationS, 141, 16);
723 WMMoveWidget(panel->hsbSaturationS, 2, 36);
724 WMSetSliderMinValue(panel->hsbSaturationS, 0);
725 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
726 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
727 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
729 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
730 WMResizeWidget(panel->hsbSaturationT, 40, 18);
731 WMMoveWidget(panel->hsbSaturationT, 146, 35);
732 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
733 WMAddNotificationObserver(hsbTextFieldCallback, panel, \
734 WMTextDidEndEditingNotification, panel->hsbSaturationT);
737 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
738 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
739 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
740 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
741 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
742 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
743 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
745 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
746 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
747 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
748 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
749 WMAddNotificationObserver(hsbTextFieldCallback, panel, \
750 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
751 /* End of HSB Panel */
753 /* Widgets for the CustomPalette Panel */
754 panel->customPaletteFrm = WMCreateFrame(panel->win);
755 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
756 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
757 WMMoveWidget(panel->customPaletteFrm, 5, 80);
759 panel->customPaletteHistoryBtn = WMCreatePopUpButton(panel->customPaletteFrm);
760 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, "Spectrum");
761 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn)-1);
762 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn, customPaletteHistoryCallback, panel);
763 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
764 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
766 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
767 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
768 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
769 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
771 panel->customPaletteContentView = W_CreateView(W_VIEW(panel->customPaletteContentFrm));
772 /* XXX Can we create a view ? */
773 W_ResizeView(panel->customPaletteContentView, customPaletteWidth, customPaletteHeight);
774 W_MoveView(panel->customPaletteContentView, 2, 2);
776 /* Create an event handler to handle expose/click events in the CustomPalette */
777 WMCreateEventHandler(panel->customPaletteContentView, ButtonPressMask|ButtonReleaseMask|EnterWindowMask
778 |LeaveWindowMask|ButtonMotionMask, customPaletteHandleActionEvents, panel);
780 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask, customPaletteHandleEvents, panel);
782 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
783 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
784 WMSetPopUpButtonText(panel->customPaletteMenuBtn, "Palette");
785 WMSetPopUpButtonAction(panel->customPaletteMenuBtn, customPaletteMenuCallback, panel);
786 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
787 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
789 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "New from File..."); /* item 0 */
790 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Rename..."); /* item 1 */
791 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Remove"); /* item 2 */
792 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Copy"); /* item 3 */
793 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "New from Clipboard"); /* item 4 */
795 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, 1, 0);
796 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, 2, 0);
797 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, 3, 0);
798 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, 4, 0);
800 customRenderSpectrum(panel);
801 panel->currentPalette = 0;
804 /* Widgets for the ColorList Panel */
805 panel->colorListFrm = WMCreateFrame(panel->win);
806 WMSetFrameRelief(panel->colorListFrm, WRFlat);
807 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
808 WMMoveWidget(panel->colorListFrm, 5, 80);
810 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
811 WMAddPopUpButtonItem(panel->colorListHistoryBtn, "X11-Colors");
812 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn, WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn)-1);
813 // WMSetPopUpButtonAction(panel->colorListHistoryBtn, colorListHistoryCallback, panel);
814 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
815 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
817 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
818 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
819 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
820 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
821 WMMoveWidget(panel->colorListContentLst, 0, 23);
823 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
824 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
825 WMSetPopUpButtonText(panel->colorListColorMenuBtn, "Color");
826 // WMSetPopUpButtonAction(panel->colorListColorMenuBtn, colorListColorMenuCallback, panel);
827 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16)/2, 20);
828 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
830 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
831 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
832 WMSetPopUpButtonText(panel->colorListListMenuBtn, "List");
833 // WMSetPopUpButtonAction(panel->colorListListMenuBtn, colorListListMenuCallback, panel);
834 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2, 20);
835 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2 + 8, PHEIGHT - 130);
838 WMRealizeWidget(panel->win);
839 WMMapSubwidgets(panel->win);
841 WMMapSubwidgets(panel->wheelFrm);
842 WMMapSubwidgets(panel->slidersFrm);
843 WMMapSubwidgets(panel->grayFrm);
844 WMMapSubwidgets(panel->rgbFrm);
845 WMMapSubwidgets(panel->cmykFrm);
846 WMMapSubwidgets(panel->hsbFrm);
847 WMMapSubwidgets(panel->customPaletteFrm);
848 WMMapSubwidgets(panel->customPaletteContentFrm);
849 WMMapSubwidgets(panel->colorListFrm);
851 readConfiguration(panel);
852 readXColors(panel);
854 return panel;
858 WMColorPanel*
859 WMGetColorPanel(WMScreen *scrPtr)
861 WMColorPanel *panel;
863 if (scrPtr->sharedColorPanel)
864 return scrPtr->sharedColorPanel;
866 panel = makeColorPanel(scrPtr, "colorPanel");
868 scrPtr->sharedColorPanel = panel;
870 return panel;
874 void
875 WMFreeColorPanel(WMColorPanel *panel)
877 W_Screen *scr = WMWidgetScreen(panel->win);
879 if (panel == scr->sharedColorPanel) {
880 WMWidgetScreen(panel->win)->sharedColorPanel = NULL;
882 WMRemoveNotificationObserver(panel); /* XXX */
883 WMUnmapWidget(panel->win);
884 WMDestroyWidget(panel->win);
885 if (panel->wheelMtrx)
886 wheelDestroyMatrix(panel->wheelMtrx);
887 if (panel->wheelImg)
888 XFreePixmap(scr->display, panel->wheelImg);
889 if (panel->selectionImg)
890 XFreePixmap(scr->display, panel->selectionImg);
891 if (panel->selectionBackImg)
892 XFreePixmap(scr->display, panel->selectionBackImg);
893 if (panel->customPaletteImg)
894 RDestroyImage(panel->customPaletteImg);
895 if (panel->lastBrowseDir)
896 free(panel->lastBrowseDir);
897 if (panel->configurationPath)
898 free(panel->configurationPath);
900 free(panel);
905 WMRunColorPanel(WMColorPanel *panel, WMWindow *owner, RColor color)
907 WMScreen *scr = WMWidgetScreen(panel->win);
908 XEvent event;
909 RHSVColor hsvcolor;
910 GC bgc = W_GC(scr->black);
911 GC wgc = W_GC(scr->white);
912 float W_PI = 4*atan(1);
914 WMChangePanelOwner(panel->win, owner);
916 WMSetColorPanelColor(panel, color);
917 panel->wheelMtrx = wheelInitMatrix(panel); /* Needs to be done After Color is set */
919 /* Maybe put this in sub-function ... Initialising selection images */
920 RRGBtoHSV(&color, &hsvcolor);
921 panel->colx = 2 + rint((colorWheelSize / 2.0) * (1 + (hsvcolor.saturation/255.0) * cos( hsvcolor.hue*W_PI/180.0)));
922 panel->coly = 2 + rint((colorWheelSize / 2.0) * (1 + (hsvcolor.saturation/255.0) * sin(-hsvcolor.hue*W_PI/180.0)));
923 wheelUpdateBrightnessGradientFromHSV(panel, hsvcolor);
924 WMSetSliderValue(panel->wheelBrightnessS, 255 - hsvcolor.value);
926 panel->selectionImg = XCreatePixmap(scr->display, W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
927 XFillRectangle(scr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
928 XFillRectangle(scr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
929 /* End of initialisation section */
931 panel->palx = customPaletteWidth/2;
932 panel->paly = customPaletteHeight/2;
934 WMSetPickerMode(panel, WMWheelModeColorPanel);
936 panel->flags.done = 0;
938 WMMapWidget(panel->win);
940 while (!panel->flags.done) {
941 WMNextEvent(scr->display, &event);
942 WMHandleEvent(&event);
945 WMCloseWindow(panel->win);
947 return 0;
952 static void
953 readConfiguration(W_ColorPanel *panel)
955 /* XXX Doesn't take care of "invalid" files */
957 DIR *dPtr;
958 struct dirent *dp;
959 struct stat stat_buf;
962 if (stat(panel->configurationPath, &stat_buf)!=0) {
963 if (mkdir(panel->configurationPath, S_IRWXU|S_IRGRP|S_IROTH|S_IXGRP|S_IXOTH)!=0) {
964 wfatal("ColorPanel could not create directory %s needed to store configurations", panel->configurationPath);
965 WMFreeColorPanel(panel);
966 wAbort();
968 return;
971 dPtr = opendir(panel->configurationPath);
972 while ((dp = readdir(dPtr)) != NULL) {
973 if (dp->d_name[0] != '.')
974 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
976 (void)closedir(dPtr);
980 static void
981 readXColors(W_ColorPanel *panel)
983 struct stat stat_buf;
984 FILE *rgbtxt;
985 char line[MAX_LENGTH];
986 int red, green, blue;
987 char name[48];
988 RColor *color;
989 WMListItem *item;
991 if (stat(RGBTXT, &stat_buf) != 0) {
992 wwarning("Cannot find file %s", RGBTXT);
993 return;
995 else {
996 rgbtxt = fopen(RGBTXT, "r");
997 if (rgbtxt) {
998 while (fgets(line, MAX_LENGTH, rgbtxt)) {
999 if (sscanf(line, "%d%d%d %[^\n]", &red, &green, &blue, name)) {
1000 color = wmalloc(sizeof(RColor));
1001 color->red = (unsigned char)red;
1002 color->green = (unsigned char)green;
1003 color->blue = (unsigned char)blue;
1004 item = WMAddListItem(panel->colorListContentLst, name);
1005 item->clientData = (void *)color;
1008 fclose(rgbtxt);
1010 else {
1011 wwarning("Unable to open file %s for reading", RGBTXT);
1017 void
1018 WMSetPickerMode(WMColorPanel *panel, WMColorPanelMode mode)
1020 W_Screen *scr = WMWidgetScreen(panel->win);
1022 if (mode != WMWheelModeColorPanel) {
1023 WMUnmapWidget(panel->wheelFrm);
1024 if (panel->selectionBackImg) {
1025 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1026 panel->selectionBackImg = None;
1029 if (mode != WMGrayModeColorPanel)
1030 WMUnmapWidget(panel->grayFrm);
1031 if (mode != WMRGBModeColorPanel)
1032 WMUnmapWidget(panel->rgbFrm);
1033 if (mode != WMCMYKModeColorPanel)
1034 WMUnmapWidget(panel->cmykFrm);
1035 if (mode != WMHSBModeColorPanel)
1036 WMUnmapWidget(panel->hsbFrm);
1037 if (mode != WMCustomPaletteModeColorPanel) {
1038 WMUnmapWidget(panel->customPaletteFrm);
1039 if (panel->selectionBackImg) {
1040 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1041 panel->selectionBackImg = None;
1044 if (mode != WMColorListModeColorPanel)
1045 WMUnmapWidget(panel->colorListFrm);
1046 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) && \
1047 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1048 WMUnmapWidget(panel->slidersFrm);
1049 else
1050 panel->slidersmode = mode;
1052 if (mode == WMWheelModeColorPanel) {
1053 WMMapWidget(panel->wheelFrm);
1054 WMSetButtonSelected(panel->wheelBtn, True);
1055 if (panel->lastChanged != WMWheelModeColorPanel)
1056 wheelInit(panel);
1057 wheelRender(panel);
1058 wheelPaint(panel);
1059 } else if (mode == WMGrayModeColorPanel) {
1060 WMMapWidget(panel->slidersFrm);
1061 WMSetButtonSelected(panel->slidersBtn, True);
1062 WMMapWidget(panel->grayFrm);
1063 WMSetButtonSelected(panel->grayBtn, True);
1064 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1065 WMSetButtonAltImage(panel->slidersBtn,scr->grayAltIcon);
1066 if (panel->lastChanged != WMGrayModeColorPanel)
1067 grayInit(panel);
1068 } else if (mode == WMRGBModeColorPanel) {
1069 WMMapWidget(panel->slidersFrm);
1070 WMSetButtonSelected(panel->slidersBtn, True);
1071 WMMapWidget(panel->rgbFrm);
1072 WMSetButtonSelected(panel->rgbBtn, True);
1073 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1074 WMSetButtonAltImage(panel->slidersBtn, scr->rgbAltIcon);
1075 if (panel->lastChanged != WMRGBModeColorPanel)
1076 rgbInit(panel);
1077 } else if (mode == WMCMYKModeColorPanel) {
1078 WMMapWidget(panel->slidersFrm);
1079 WMSetButtonSelected(panel->slidersBtn, True);
1080 WMMapWidget(panel->cmykFrm);
1081 WMSetButtonSelected(panel->cmykBtn, True);
1082 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1083 WMSetButtonAltImage(panel->slidersBtn, scr->cmykAltIcon);
1084 if (panel->lastChanged != WMCMYKModeColorPanel)
1085 cmykInit(panel);
1086 } else if (mode == WMHSBModeColorPanel) {
1087 WMMapWidget(panel->slidersFrm);
1088 WMSetButtonSelected(panel->slidersBtn, True);
1089 WMMapWidget(panel->hsbFrm);
1090 WMSetButtonSelected(panel->hsbBtn, True);
1091 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1092 WMSetButtonAltImage(panel->slidersBtn, scr->hsbAltIcon);
1093 if (panel->lastChanged != WMHSBModeColorPanel)
1094 hsbInit(panel);
1095 } else if (mode == WMCustomPaletteModeColorPanel) {
1096 WMMapWidget(panel->customPaletteFrm);
1097 WMSetButtonSelected(panel->customPaletteBtn, True);
1098 customSetPalette(panel);
1099 } else if (mode == WMColorListModeColorPanel) {
1100 WMMapWidget(panel->colorListFrm);
1101 WMSetButtonSelected(panel->colorListBtn, True);
1105 panel->mode = mode;
1108 void
1109 WMSetColorPanelColor(WMColorPanel *panel, RColor color)
1111 WMScreen *scr = WMWidgetScreen(panel->win);
1112 WMColor *wellcolor;
1114 wellcolor = WMCreateRGBColor(scr, color.red << 8, color.green << 8, color.blue << 8, True);
1115 WMSetColorWellColor(panel->colorWell, wellcolor);
1116 WMReleaseColor(wellcolor);
1118 panel->color = color;
1119 if (panel->lastChanged != WMHSBModeColorPanel) /* If color was set by HSB-Panel do not convert back to hsv */
1120 RRGBtoHSV(&panel->color, &panel->hsvcolor);
1123 static void
1124 modeButtonCallback(WMWidget *w, void *data)
1126 W_ColorPanel *panel = (W_ColorPanel*)(data);
1128 if (w == panel->wheelBtn)
1129 WMSetPickerMode(panel, WMWheelModeColorPanel);
1130 else if (w == panel->slidersBtn)
1131 WMSetPickerMode(panel, panel->slidersmode);
1132 else if (w == panel->customPaletteBtn)
1133 WMSetPickerMode(panel, WMCustomPaletteModeColorPanel);
1134 else if (w == panel->colorListBtn)
1135 WMSetPickerMode(panel, WMColorListModeColorPanel);
1136 else if (w == panel->grayBtn)
1137 WMSetPickerMode(panel, WMGrayModeColorPanel);
1138 else if (w == panel->rgbBtn)
1139 WMSetPickerMode(panel, WMRGBModeColorPanel);
1140 else if (w == panel->cmykBtn)
1141 WMSetPickerMode(panel, WMCMYKModeColorPanel);
1142 else if (w == panel->hsbBtn)
1143 WMSetPickerMode(panel, WMHSBModeColorPanel);
1146 /****************** WheelMatrix Functions ************************/
1148 static wheelMatrix*
1149 wheelCreateMatrix(unsigned int width, unsigned int height)
1151 wheelMatrix *matrix = NULL;
1152 int i;
1154 assert((width > 0) && (height > 0));
1156 matrix = malloc(sizeof(wheelMatrix));
1157 if (!matrix) {
1158 RErrorCode = RERR_NOMEMORY;
1159 return NULL;
1162 memset(matrix, 0, sizeof(wheelMatrix));
1163 matrix->width = width;
1164 matrix->height = height;
1165 for (i = 0; i < 3; i++) {
1166 matrix->data[i] = malloc(width*height*sizeof(unsigned char));
1167 if (!matrix->data[i])
1168 goto error;
1171 return matrix;
1173 error:
1174 for (i = 0; i < 3; i++) {
1175 if (matrix->data[i])
1176 free(matrix->data[i]);
1178 if (matrix)
1179 free(matrix);
1180 RErrorCode = RERR_NOMEMORY;
1181 return NULL;
1185 static void
1186 wheelDestroyMatrix(wheelMatrix *matrix)
1188 int i;
1190 assert (matrix!=NULL);
1192 for (i = 0; i < 3; i++) {
1193 if (matrix->data[i])
1194 free(matrix->data[i]);
1196 free(matrix);
1200 static wheelMatrix*
1201 wheelInitMatrix(W_ColorPanel *panel)
1203 int i;
1204 int x,y;
1205 wheelMatrix *matrix;
1206 unsigned char *rp, *gp, *bp;
1207 RHSVColor cur_hsv;
1208 RColor cur_rgb;
1209 long ofs[4];
1210 float hue;
1211 int sat;
1212 float xcor, ycor;
1213 float W_PI = 4 *atan(1);
1214 int dhue[4];
1216 matrix = wheelCreateMatrix(colorWheelSize+4, colorWheelSize+4);
1217 if (!matrix)
1218 return NULL;
1220 RRGBtoHSV(&panel->color, &cur_hsv);
1222 for (i = 0; i < 256; i++)
1223 matrix->values[i] = (unsigned char)(rint(i*cur_hsv.value/255));
1225 cur_hsv.value = 255;
1227 ofs[0] = -1;
1228 ofs[1] = -(colorWheelSize + 4);
1229 /* ofs[2] = 0; superfluous
1230 ofs[3] = 0;
1232 for (y = 0; y < (colorWheelSize+4)/2; y++) {
1233 for (x = y; x < (colorWheelSize+4-y); x++) {
1234 xcor = ((float)(2.0*x - 4.0) / colorWheelSize) - 1;
1235 ycor = ((float)(2.0*y - 4.0) / colorWheelSize) - 1;
1237 sat = rint(255.0 * sqrt((xcor*xcor) + (ycor*ycor)));
1241 /* offsets are counterclockwise (in triangles) */
1242 if (y < (colorWheelSize+4)/2)
1243 ofs[0]++;
1244 /* top quarter */
1245 ofs[1] += colorWheelSize + 4; /* left quarter */
1248 ofs[2] = (colorWheelSize + 4) * (colorWheelSize + 4) - 1 - ofs[0]; /* bottom quarter */
1249 ofs[3] = (colorWheelSize + 4) * (colorWheelSize + 4) - 1 - ofs[1]; /* right quarter */
1251 if (sat < 256) {
1252 cur_hsv.saturation = (unsigned char)sat;
1254 if (xcor != 0)
1255 hue = atan(ycor/xcor);
1256 else {
1257 if (ycor > 0)
1258 hue = W_PI * 0.5;
1259 else
1260 hue = W_PI * 1.5;
1263 if (xcor < 0)
1264 hue += W_PI;
1265 if ((xcor > 0) && (ycor < 0))
1266 hue += W_PI * 2.0;
1268 hue = -hue; /* Reverse direction of ColorWheel */
1270 if (hue < 0)
1271 hue += W_PI * 2.0;
1273 dhue[0] = (hue*360) / (W_PI * 2.0);
1275 for (i = 0; i < 4; i++) {
1277 if (i > 0)
1278 dhue[i] = (dhue[i-1] + 90) % 360;
1280 if ((i == 1) || (i == 3))
1281 dhue[i] = 360 - dhue[i];
1283 if (i == 2)
1284 dhue[i] = 360 - dhue[i] + 180;
1286 rp = matrix->data[0] + (ofs[i] * sizeof(unsigned char));
1287 gp = matrix->data[1] + (ofs[i] * sizeof(unsigned char));
1288 bp = matrix->data[2] + (ofs[i] * sizeof(unsigned char));
1290 cur_hsv.hue = dhue[i];
1291 RHSVtoRGB(&cur_hsv, &cur_rgb);
1293 *rp = (unsigned char)(cur_rgb.red);
1294 *gp = (unsigned char)(cur_rgb.green);
1295 *bp = (unsigned char)(cur_rgb.blue);
1298 else {
1299 for (i = 0; i < 4; i++) {
1300 rp = matrix->data[0] + (ofs[i] * sizeof(unsigned char));
1301 gp = matrix->data[1] + (ofs[i] * sizeof(unsigned char));
1302 bp = matrix->data[2] + (ofs[i] * sizeof(unsigned char));
1304 *rp = (unsigned char)(0);
1305 *gp = (unsigned char)(0);
1306 *bp = (unsigned char)(0);
1310 if (y < (colorWheelSize+4)/2)
1311 ofs[0] += 2*y+1;
1313 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2*y);
1316 return matrix;
1319 /****************** ColorWheel Functions *******************/
1321 static void
1322 wheelRender(W_ColorPanel *panel)
1324 W_Screen *scr = WMWidgetScreen(panel->win);
1325 int x,y;
1326 RImage *image;
1327 unsigned char *rp, *gp, *bp;
1328 RColor gray;
1329 unsigned long ofs;
1331 image = RCreateImage(colorWheelSize+4, colorWheelSize+4, False);
1332 if (!image)
1333 return;
1335 gray.red = gray.green = gray.blue = 0xaa;
1337 for (x = 0; x < colorWheelSize+4; x++) {
1338 for (y = 0; y < colorWheelSize+4; y++) {
1340 ofs = (y * image->width) + x;
1341 rp = image->data[0] + ofs;
1342 gp = image->data[1] + ofs;
1343 bp = image->data[2] + ofs;
1345 if (wheelInsideColorWheel(panel, ofs)) {
1346 *rp = (unsigned int)(panel->wheelMtrx->values[ panel->wheelMtrx->data[0][ofs] ]);
1347 *gp = (unsigned int)(panel->wheelMtrx->values[ panel->wheelMtrx->data[1][ofs] ]);
1348 *bp = (unsigned int)(panel->wheelMtrx->values[ panel->wheelMtrx->data[2][ofs] ]);
1350 else {
1351 *rp = (unsigned char)(gray.red);
1352 *gp = (unsigned char)(gray.green);
1353 *bp = (unsigned char)(gray.blue);
1358 if (panel->wheelImg)
1359 XFreePixmap(scr->display, panel->wheelImg);
1361 panel->wheelImg = XCreatePixmap(scr->display, W_DRAWABLE(scr), colorWheelSize+4, colorWheelSize+4, scr->depth);
1362 RConvertImage(scr->rcontext, image, &panel->wheelImg);
1364 /* Check backimage existence. If it doesn't exist, allocate it and fill it */
1365 if (!panel->selectionBackImg) {
1366 panel->selectionBackImg = XCreatePixmap(scr->display, W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
1367 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg, scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0); /* -2 is for hot spot correction */
1370 RDestroyImage(image);
1373 static Bool
1374 wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs)
1376 if ((panel->wheelMtrx->data[0][ofs] != 0) &&
1377 (panel->wheelMtrx->data[1][ofs] != 0) &&
1378 (panel->wheelMtrx->data[2][ofs] != 0))
1379 return True;
1380 return False;
1383 static void
1384 wheelPaint (W_ColorPanel *panel)
1386 W_Screen *scr = WMWidgetScreen(panel->win);
1388 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window, scr->copyGC, 0, 0, colorWheelSize+4, colorWheelSize+4, 0, 0);
1390 /* Draw selection image */
1391 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window, scr->copyGC, 0 , 0, 4, 4, panel->colx -2, panel->coly -2);
1394 static void
1395 wheelHandleEvents(XEvent *event, void *data)
1397 W_ColorPanel *panel = (W_ColorPanel*)data;
1399 switch (event->type) {
1400 case Expose:
1401 if (event->xexpose.count != 0)
1402 break;
1403 wheelPaint(panel);
1404 break;
1408 static void
1409 wheelHandleActionEvents(XEvent *event, void *data)
1411 W_ColorPanel *panel = (W_ColorPanel*)data;
1413 switch (event->type) {
1414 case ButtonPress:
1415 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) == COLORWHEEL_PART) {
1416 panel->flags.dragging = 1;
1417 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
1419 break;
1421 case ButtonRelease:
1422 panel->flags.dragging = 0;
1423 break;
1425 case MotionNotify:
1426 if (panel->flags.dragging) {
1427 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) == COLORWHEEL_PART) {
1428 wheelPositionSelection(panel, event->xmotion.x, event->xmotion.y);
1430 else
1431 wheelPositionSelectionOutBounds(panel, event->xmotion.x, event->xmotion.y);
1433 break;
1438 static int
1439 getPickerPart(W_ColorPanel *panel, int x, int y)
1441 int lx, ly;
1442 unsigned long ofs;
1444 lx = x;
1445 ly = y;
1447 if (panel->mode == WMWheelModeColorPanel) {
1448 if ((lx >= 2) && (lx <= 2+colorWheelSize) && (ly >= 2) && (ly <= 2+colorWheelSize)) {
1449 ofs = ly*panel->wheelMtrx->width+lx;
1451 if (wheelInsideColorWheel(panel, ofs))
1452 return COLORWHEEL_PART;
1456 if (panel->mode == WMCustomPaletteModeColorPanel) {
1457 if ((lx >= 2) && (lx < customPaletteWidth-2) && (ly >= 2) && (ly < customPaletteHeight-2)) {
1458 return CUSTOMPALETTE_PART;
1462 return 0;
1468 static void
1469 wheelBrightnessSliderCallback(WMWidget *w, void *data)
1471 int i;
1472 unsigned int v;
1473 int value;
1474 unsigned long ofs;
1475 RColor cur_rgb;
1477 W_ColorPanel *panel = (W_ColorPanel*)data;
1479 value = 255-WMGetSliderValue(panel->wheelBrightnessS);
1481 for (i = 0; i < 256; i++) {
1482 /* We divide by 128 in advance, and check whether that number divides
1483 * by 2 properly. If not, we add one to round the number correctly
1485 v = (i*value) >> 7;
1486 #ifdef EASTEREGG
1487 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + v);
1488 #else
1489 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) +(v & 0x01));
1490 #endif
1493 ofs = (panel->coly * panel->wheelMtrx->width) + panel->colx;
1495 if (!wheelInsideColorWheel(panel, ofs)) {
1496 panel->hsvcolor.saturation = 255;
1497 panel->hsvcolor.value = value;
1498 RHSVtoRGB(&panel->hsvcolor, &cur_rgb);
1500 panel->color = cur_rgb;
1502 else {
1503 panel->color.red = panel->wheelMtrx->values[ panel->wheelMtrx->data[0][ofs] ];
1504 panel->color.green = panel->wheelMtrx->values[ panel->wheelMtrx->data[1][ofs] ];
1505 panel->color.blue = panel->wheelMtrx->values[ panel->wheelMtrx->data[2][ofs] ];
1508 wheelRender(panel);
1509 wheelPaint(panel);
1510 wheelUpdateSelection(panel);
1513 static void
1514 wheelUpdateSelection(W_ColorPanel *panel)
1516 W_Screen *scr = WMWidgetScreen(panel->win);
1517 WMSetColorPanelColor(panel, panel->color);
1518 panel->lastChanged = WMWheelModeColorPanel;
1520 /* Redraw color selector (and make a backup of the part it will cover) */
1521 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg, scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0); /* "-2" is correction for hotspot location */
1522 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window, scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2); /* see above */
1525 static void
1526 wheelUndrawSelection(W_ColorPanel *panel)
1528 W_Screen *scr = WMWidgetScreen(panel->win);
1530 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window, scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2); /* see above */
1533 static void
1534 wheelPositionSelection(W_ColorPanel *panel, int x, int y)
1536 unsigned long ofs = (y * panel->wheelMtrx->width)+ x;
1539 panel->color.red = panel->wheelMtrx->values[ panel->wheelMtrx->data[0][ofs] ];
1540 panel->color.green = panel->wheelMtrx->values[ panel->wheelMtrx->data[1][ofs] ];
1541 panel->color.blue = panel->wheelMtrx->values[ panel->wheelMtrx->data[2][ofs] ];
1543 wheelUndrawSelection(panel);
1545 panel->colx = x;
1546 panel->coly = y;
1548 wheelUpdateSelection(panel);
1549 wheelUpdateBrightnessGradientFromLocation(panel);
1552 static void
1553 wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
1555 RHSVColor cur_hsv;
1556 float hue;
1557 float xcor, ycor;
1558 float W_PI = 4*atan(1);
1560 xcor = ((x*2.0) / (colorWheelSize+4)) - 1.0;
1561 ycor = ((y*2.0) / (colorWheelSize+4)) - 1.0;
1563 cur_hsv.saturation = 255;
1564 cur_hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
1566 if (xcor != 0)
1567 hue = atan(ycor/xcor);
1568 else {
1569 if (ycor > 0)
1570 hue = W_PI * 0.5;
1571 else
1572 hue = W_PI * 1.5;
1575 if (xcor < 0)
1576 hue += W_PI;
1577 if ((xcor > 0) && (ycor < 0))
1578 hue += W_PI * 2.0;
1580 hue = -hue;
1582 if (hue < 0)
1583 hue += W_PI * 2.0;
1585 cur_hsv.hue = (hue*360.0)/(W_PI*2.0);
1586 RHSVtoRGB(&cur_hsv, &panel->color);
1588 wheelUndrawSelection(panel);
1590 panel->colx = 2 + rint((colorWheelSize * (1.0 + cos( cur_hsv.hue*W_PI/180))) /2.0); /* "+2" because of "colorWheelSize + 4" */
1591 panel->coly = 2 + rint((colorWheelSize * (1.0 + sin(-cur_hsv.hue*W_PI/180))) /2.0);
1593 wheelUpdateSelection(panel);
1594 wheelUpdateBrightnessGradientFromHSV(panel, cur_hsv);
1597 static void
1598 wheelUpdateBrightnessGradientFromHSV(W_ColorPanel *panel, RHSVColor topColor)
1600 RColor from;
1602 /* Update Brightness-Slider */
1603 topColor.value = 255;
1604 RHSVtoRGB(&topColor, &from);
1606 wheelUpdateBrightnessGradient(panel, from);
1609 static void
1610 wheelUpdateBrightnessGradientFromLocation(W_ColorPanel *panel)
1612 RColor from;
1613 unsigned long ofs;
1615 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
1617 from.red = panel->wheelMtrx->data[0][ofs];
1618 from.green = panel->wheelMtrx->data[1][ofs];
1619 from.blue = panel->wheelMtrx->data[2][ofs];
1621 wheelUpdateBrightnessGradient(panel, from);
1624 static void
1625 wheelUpdateBrightnessGradient(W_ColorPanel *panel, RColor topColor)
1627 RColor to;
1628 RImage *sliderImg;
1629 WMPixmap *sliderPxmp;
1631 to.red = to.green = to.blue = 0;
1633 sliderImg = RRenderGradient(16, 153, &topColor, &to, RGRD_VERTICAL);
1634 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win), sliderImg, 0);
1635 RDestroyImage(sliderImg);
1636 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
1637 WMReleasePixmap(sliderPxmp);
1640 /****************** Grayscale Panel Functions ***************/
1642 static void
1643 grayBrightnessSliderCallback(WMWidget *w, void *data)
1645 RColor color;
1646 int value;
1647 char tmp[3];
1649 W_ColorPanel *panel = (W_ColorPanel*)data;
1651 value = WMGetSliderValue(panel->grayBrightnessS);
1653 sprintf(tmp, "%d", value);
1655 WMSetTextFieldText(panel->grayBrightnessT, tmp);
1656 color.red = color.green = color.blue = rint(2.55*value);
1658 WMSetColorPanelColor(panel, color);
1659 panel->lastChanged = WMGrayModeColorPanel;
1662 static void
1663 grayPresetButtonCallback(WMWidget *w, void *data)
1665 RColor color;
1666 char tmp[3];
1667 int value;
1668 int i=0;
1670 W_ColorPanel *panel = (W_ColorPanel*)data;
1672 while (i < 7) {
1673 if (w == panel->grayPresetBtn[i])
1674 break;
1675 i++;
1678 value = rint(100.0/6.0*i);
1679 sprintf(tmp, "%d", value);
1681 WMSetTextFieldText(panel->grayBrightnessT, tmp);
1682 color.red = color.green = color.blue = rint(255.0*i/6.0);
1684 WMSetSliderValue(panel->grayBrightnessS, rint(100.0*i/6.0));
1686 WMSetColorPanelColor(panel, color);
1687 panel->lastChanged = WMGrayModeColorPanel;
1690 static void
1691 grayBrightnessTextFieldCallback(void *observerData, WMNotification *notification)
1693 RColor color;
1694 char tmp[3];
1695 int value;
1696 W_ColorPanel *panel = (W_ColorPanel*)observerData;
1698 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
1699 if (value > 100)
1700 value = 100;
1701 if (value < 0)
1702 value = 0;
1704 sprintf(tmp, "%d", value);
1705 WMSetTextFieldText(panel->grayBrightnessT, tmp);
1706 WMSetSliderValue(panel->grayBrightnessS, value);
1708 color.red = color.green = color.blue = rint(255.0*value/100.0);
1709 WMSetColorPanelColor(panel, color);
1710 panel->lastChanged = WMGrayModeColorPanel;
1713 /******************* RGB Panel Functions *****************/
1715 static void
1716 rgbSliderCallback(WMWidget *w, void *data)
1718 RColor color;
1719 int value[3];
1720 char tmp[3];
1722 W_ColorPanel *panel = (W_ColorPanel*)data;
1724 value[0] = WMGetSliderValue(panel->rgbRedS);
1725 value[1] = WMGetSliderValue(panel->rgbGreenS);
1726 value[2] = WMGetSliderValue(panel->rgbBlueS);
1728 sprintf(tmp, "%d", value[0]);
1729 WMSetTextFieldText(panel->rgbRedT, tmp);
1730 sprintf(tmp, "%d", value[1]);
1731 WMSetTextFieldText(panel->rgbGreenT, tmp);
1732 sprintf(tmp, "%d", value[2]);
1733 WMSetTextFieldText(panel->rgbBlueT, tmp);
1735 color.red = value[0];
1736 color.green = value[1];
1737 color.blue = value[2];
1739 WMSetColorPanelColor(panel, color);
1740 panel->lastChanged = WMRGBModeColorPanel;
1743 static void
1744 rgbTextFieldCallback(void *observerData, WMNotification *notification)
1746 RColor color;
1747 char tmp[3];
1748 int value[3];
1749 int n;
1750 W_ColorPanel *panel = (W_ColorPanel*)observerData;
1752 value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
1753 value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
1754 value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
1756 for (n=0; n < 3; n++) {
1757 if (value[n] > 255)
1758 value[n] = 255;
1759 if (value[n] < 0)
1760 value[n] = 0;
1763 sprintf(tmp, "%d", value[0]);
1764 WMSetTextFieldText(panel->rgbRedT, tmp);
1765 sprintf(tmp, "%d", value[1]);
1766 WMSetTextFieldText(panel->rgbGreenT, tmp);
1767 sprintf(tmp, "%d", value[2]);
1768 WMSetTextFieldText(panel->rgbBlueT, tmp);
1770 WMSetSliderValue(panel->rgbRedS, value[0]);
1771 WMSetSliderValue(panel->rgbGreenS, value[1]);
1772 WMSetSliderValue(panel->rgbBlueS, value[2]);
1774 color.red = value[0];
1775 color.green = value[1];
1776 color.blue = value[2];
1778 WMSetColorPanelColor(panel, color);
1779 panel->lastChanged = WMRGBModeColorPanel;
1783 /******************* CMYK Panel Functions *****************/
1785 static void
1786 cmykSliderCallback(WMWidget *w, void *data)
1788 RColor color;
1789 int value[4];
1790 char tmp[3];
1792 W_ColorPanel *panel = (W_ColorPanel*)data;
1794 value[0] = WMGetSliderValue(panel->cmykCyanS);
1795 value[1] = WMGetSliderValue(panel->cmykMagentaS);
1796 value[2] = WMGetSliderValue(panel->cmykYellowS);
1797 value[3] = WMGetSliderValue(panel->cmykBlackS);
1799 sprintf(tmp, "%d", value[0]);
1800 WMSetTextFieldText(panel->cmykCyanT, tmp);
1801 sprintf(tmp, "%d", value[1]);
1802 WMSetTextFieldText(panel->cmykMagentaT, tmp);
1803 sprintf(tmp, "%d", value[2]);
1804 WMSetTextFieldText(panel->cmykYellowT, tmp);
1805 sprintf(tmp, "%d", value[3]);
1806 WMSetTextFieldText(panel->cmykBlackT, tmp);
1808 color.red = rint((255.0 - (value[0] * 2.55)) * (1.0 - (value[3] / 100.0)));
1809 color.green = rint((255.0 - (value[1] * 2.55)) * (1.0 - (value[3] / 100.0)));
1810 color.blue = rint((255.0 - (value[2] * 2.55)) * (1.0 - (value[3] / 100.0)));
1812 WMSetColorPanelColor(panel, color);
1813 panel->lastChanged = WMCMYKModeColorPanel;
1816 static void
1817 cmykTextFieldCallback(void *observerData, WMNotification *notification)
1819 RColor color;
1820 char tmp[3];
1821 int value[4];
1822 int n;
1823 W_ColorPanel *panel = (W_ColorPanel*)observerData;
1825 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
1826 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
1827 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
1828 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
1830 for (n=0; n < 4; n++) {
1831 if (value[n] > 100)
1832 value[n] = 100;
1833 if (value[n] < 0)
1834 value[n] = 0;
1837 sprintf(tmp, "%d", value[0]);
1838 WMSetTextFieldText(panel->cmykCyanT, tmp);
1839 sprintf(tmp, "%d", value[1]);
1840 WMSetTextFieldText(panel->cmykMagentaT, tmp);
1841 sprintf(tmp, "%d", value[2]);
1842 WMSetTextFieldText(panel->cmykYellowT, tmp);
1843 sprintf(tmp, "%d", value[3]);
1844 WMSetTextFieldText(panel->cmykBlackT, tmp);
1846 WMSetSliderValue(panel->cmykCyanS, value[0]);
1847 WMSetSliderValue(panel->cmykMagentaS, value[1]);
1848 WMSetSliderValue(panel->cmykYellowS, value[2]);
1849 WMSetSliderValue(panel->cmykBlackS, value[3]);
1851 color.red = rint((255.0 - (value[0] * 2.55)) * (1.0 - (value[3] / 100.0)));
1852 color.green = rint((255.0 - (value[1] * 2.55)) * (1.0 - (value[3] / 100.0)));
1853 color.blue = rint((255.0 - (value[2] * 2.55)) * (1.0 - (value[3] / 100.0)));
1855 WMSetColorPanelColor(panel, color);
1856 panel->lastChanged = WMCMYKModeColorPanel;
1859 /********************** HSB Panel Functions ***********************/
1861 static void
1862 hsbSliderCallback(WMWidget *w, void *data)
1864 RColor color;
1865 int value[3];
1866 char tmp[3];
1868 W_ColorPanel *panel = (W_ColorPanel*)data;
1870 value[0] = WMGetSliderValue(panel->hsbHueS);
1871 value[1] = WMGetSliderValue(panel->hsbSaturationS);
1872 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
1874 sprintf(tmp, "%d", value[0]);
1875 WMSetTextFieldText(panel->hsbHueT, tmp);
1876 sprintf(tmp, "%d", value[1]);
1877 WMSetTextFieldText(panel->hsbSaturationT, tmp);
1878 sprintf(tmp, "%d", value[2]);
1879 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
1881 panel->hsvcolor.hue = value[0];
1882 panel->hsvcolor.saturation = value[1]*2.55;
1883 panel->hsvcolor.value = value[2]*2.55;
1885 RHSVtoRGB(&panel->hsvcolor, &color);
1887 panel->lastChanged = WMHSBModeColorPanel;
1888 WMSetColorPanelColor(panel, color);
1890 if (w != panel->hsbBrightnessS)
1891 hsbUpdateBrightnessGradient(panel);
1892 if (w != panel->hsbSaturationS)
1893 hsbUpdateSaturationGradient(panel);
1894 if (w != panel->hsbHueS)
1895 hsbUpdateHueGradient(panel);
1898 static void
1899 hsbTextFieldCallback(void *observerData, WMNotification *notification)
1901 RColor color;
1902 char tmp[3];
1903 int value[3];
1904 int n;
1905 W_ColorPanel *panel = (W_ColorPanel*)observerData;
1907 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
1908 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
1909 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
1911 if (value[0] > 359)
1912 value[0] = 359;
1913 if (value[0] < 0)
1914 value[0] = 0;
1916 for (n=1; n < 3; n++) {
1917 if (value[n] > 100)
1918 value[n] = 100;
1919 if (value[n] < 0)
1920 value[n] = 0;
1923 sprintf(tmp, "%d", value[0]);
1924 WMSetTextFieldText(panel->hsbHueT, tmp);
1925 sprintf(tmp, "%d", value[1]);
1926 WMSetTextFieldText(panel->hsbSaturationT, tmp);
1927 sprintf(tmp, "%d", value[2]);
1928 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
1930 WMSetSliderValue(panel->hsbHueS, value[0]);
1931 WMSetSliderValue(panel->hsbSaturationS, value[1]);
1932 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
1934 panel->hsvcolor.hue = value[0];
1935 panel->hsvcolor.saturation = value[1]*2.55;
1936 panel->hsvcolor.value = value[2]*2.55;
1938 RHSVtoRGB(&panel->hsvcolor, &color);
1940 panel->lastChanged = WMHSBModeColorPanel;
1941 WMSetColorPanelColor(panel, color);
1943 hsbUpdateBrightnessGradient(panel);
1944 hsbUpdateSaturationGradient(panel);
1945 hsbUpdateHueGradient(panel);
1948 static void
1949 hsbUpdateBrightnessGradient(W_ColorPanel *panel)
1951 W_Screen *scr = WMWidgetScreen(panel->win);
1952 RColor from;
1953 RColor to;
1954 RHSVColor hsvcolor;
1955 RImage *sliderImg;
1956 WMPixmap *sliderPxmp;
1958 from.red = from.green = from.blue = 0;
1959 hsvcolor = panel->hsvcolor;
1960 hsvcolor.value = 255;
1962 RHSVtoRGB(&hsvcolor, &to);
1964 sliderImg = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
1965 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
1966 RDestroyImage(sliderImg);
1967 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap, WMSystemFontOfSize(scr, 12), 2, 0, 100, WALeft, W_GC(scr->white), False, "Brightness", strlen("Brightness"));
1968 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
1969 WMReleasePixmap(sliderPxmp);
1972 static void
1973 hsbUpdateSaturationGradient(W_ColorPanel *panel)
1975 W_Screen *scr = WMWidgetScreen(panel->win);
1976 RColor from;
1977 RColor to;
1978 RHSVColor hsvcolor;
1979 RImage *sliderImg;
1980 WMPixmap *sliderPxmp;
1982 hsvcolor = panel->hsvcolor;
1983 hsvcolor.saturation = 0;
1984 RHSVtoRGB(&hsvcolor, &from);
1986 hsvcolor.saturation = 255;
1987 RHSVtoRGB(&hsvcolor, &to);
1989 sliderImg = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
1990 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
1991 RDestroyImage(sliderImg);
1992 if (hsvcolor.value < 128)
1993 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap, WMSystemFontOfSize(scr, 12), 2, 0, 100, WALeft, W_GC(scr->white), False, "Saturation", strlen("Saturation"));
1994 else
1995 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap, WMSystemFontOfSize(scr, 12), 2, 0, 100, WALeft, W_GC(scr->black), False, "Saturation", strlen("Saturation"));
1997 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
1998 WMReleasePixmap(sliderPxmp);
2001 static void
2002 hsbUpdateHueGradient(W_ColorPanel *panel)
2004 W_Screen *scr = WMWidgetScreen(panel->win);
2005 RColor **colors = NULL;
2006 RHSVColor hsvcolor;
2007 RImage *sliderImg;
2008 WMPixmap *sliderPxmp;
2009 int i;
2011 hsvcolor = panel->hsvcolor;
2013 colors = malloc(sizeof(RColor*)*(8));
2014 for (i=0; i<7; i++) {
2015 hsvcolor.hue = (360*i)/6;
2016 colors[i] = malloc(sizeof(RColor));
2017 RHSVtoRGB(&hsvcolor, colors[i]);
2019 colors[7] = NULL;
2021 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2022 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2023 RDestroyImage(sliderImg);
2024 if (hsvcolor.value < 128)
2025 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap, WMSystemFontOfSize(scr, 12), 2, 0, 100, WALeft, W_GC(scr->white), False, "Hue", strlen("Hue"));
2026 else
2027 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap, WMSystemFontOfSize(scr, 12), 2, 0, 100, WALeft, W_GC(scr->black), False, "Hue", strlen("Hue"));
2029 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2030 WMReleasePixmap(sliderPxmp);
2032 for (i=0; i<7; i++) {
2033 if (colors[i])
2034 free(colors[i]);
2036 if (colors)
2037 free(colors);
2040 /*************** Custom Palette Functions ****************/
2042 static void
2043 customRenderSpectrum(W_ColorPanel *panel)
2045 RImage *spectrum;
2046 int hue, sat, val;
2047 int x,y;
2048 unsigned long ofs;
2049 unsigned char *rp, *gp, *bp;
2050 RColor color;
2051 RHSVColor cur_hsv;
2053 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, 0);
2055 for (y=0; y<360; y++) {
2056 val = 255;
2057 sat = 0;
2058 hue = y;
2059 for (x=0; x<511; x++) {
2060 ofs = (y * 511) + x;
2062 cur_hsv.hue = hue;
2063 cur_hsv.saturation = sat;
2064 cur_hsv.value = val;
2066 RHSVtoRGB (&cur_hsv, &color);
2068 rp = spectrum->data[0] + ofs;
2069 gp = spectrum->data[1] + ofs;
2070 bp = spectrum->data[2] + ofs;
2072 *rp = (unsigned char)color.red;
2073 *gp = (unsigned char)color.green;
2074 *bp = (unsigned char)color.blue;
2076 if (x<255)
2077 sat++;
2079 if (x>255)
2080 val--;
2083 if (panel->customPaletteImg) {
2084 RDestroyImage(panel->customPaletteImg);
2085 panel->customPaletteImg = NULL;
2087 panel->customPaletteImg = spectrum;
2092 static void
2093 customSetPalette(W_ColorPanel *panel)
2095 W_Screen *scr = WMWidgetScreen(panel->win);
2096 RImage *scaledImg;
2097 Pixmap image;
2098 int item;
2100 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth, customPaletteHeight, scr->depth);
2102 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth, customPaletteHeight);
2103 RConvertImage(scr->rcontext, scaledImg, &image);
2104 RDestroyImage(scaledImg);
2106 XCopyArea(scr->display, image, panel->customPaletteContentView->window, scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2108 /* Check backimage existence. If it doesn't exist, allocate it and fill it */
2109 if (!panel->selectionBackImg) {
2110 panel->selectionBackImg = XCreatePixmap(scr->display, panel->customPaletteContentView->window, 4, 4, scr->depth);
2113 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC, panel->palx-2, panel->paly-2, 4, 4, 0, 0);
2114 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0 , 0, 4, 4, panel->palx-2, panel->paly-2);
2115 XFreePixmap(scr->display, image);
2117 panel->palXRatio = (float)(panel->customPaletteImg->width) / (float)(customPaletteWidth);
2118 panel->palYRatio = (float)(panel->customPaletteImg->height) / (float)(customPaletteHeight);
2120 item = WMGetPopUpButtonSelectedItem (panel->customPaletteHistoryBtn);
2122 /* if palette != "Spectrum", we are allowed to rename and remove it */
2123 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, menuRename, (item > 0) );
2124 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, menuRemove, (item > 0) );
2128 static void
2129 customPalettePositionSelection(W_ColorPanel *panel, int x, int y)
2131 W_Screen *scr = WMWidgetScreen(panel->win);
2132 unsigned long ofs;
2135 /* undraw selection */
2136 XCopyArea(scr->display, panel->selectionBackImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx-2, panel->paly-2);
2138 panel->palx = x;
2139 panel->paly = y;
2141 ofs = rint(x * panel->palXRatio) + rint(y * panel->palYRatio) * panel->customPaletteImg->width;
2143 panel->color.red = panel->customPaletteImg->data[0][ofs];
2144 panel->color.green = panel->customPaletteImg->data[1][ofs];
2145 panel->color.blue = panel->customPaletteImg->data[2][ofs];
2147 WMSetColorPanelColor(panel, panel->color);
2148 panel->lastChanged = WMCustomPaletteModeColorPanel;
2150 /* Redraw color selector (and make a backup of the part it will cover) */
2151 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 */
2152 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx-2, panel->paly-2); /* see above */
2156 static void
2157 customPalettePositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
2159 if (x < 2)
2160 x = 2;
2161 if (y < 2)
2162 y = 2;
2163 if (x >= customPaletteWidth)
2164 x = customPaletteWidth -2;
2165 if (y >= customPaletteHeight)
2166 y = customPaletteHeight -2;
2168 customPalettePositionSelection(panel, x, y);
2172 static void
2173 customPaletteHandleEvents(XEvent *event, void *data)
2175 W_ColorPanel *panel = (W_ColorPanel*)data;
2177 switch (event->type) {
2178 case Expose:
2179 if (event->xexpose.count != 0)
2180 break;
2181 customSetPalette(panel);
2182 break;
2186 static void
2187 customPaletteHandleActionEvents(XEvent *event, void *data)
2189 W_ColorPanel *panel = (W_ColorPanel*)data;
2190 int x, y;
2192 switch (event->type) {
2193 case ButtonPress:
2194 x = event->xbutton.x;
2195 y = event->xbutton.y;
2197 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2198 panel->flags.dragging = 1;
2199 customPalettePositionSelection(panel, x, y);
2201 break;
2203 case ButtonRelease:
2204 panel->flags.dragging = 0;
2205 break;
2207 case MotionNotify:
2208 x = event->xmotion.x;
2209 y = event->xmotion.y;
2211 if (panel->flags.dragging) {
2212 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2213 customPalettePositionSelection(panel, x, y);
2215 else
2216 customPalettePositionSelectionOutBounds(panel, x, y);
2218 break;
2223 static void
2224 customPaletteMenuCallback(WMWidget *w, void *data)
2226 W_ColorPanel *panel = (W_ColorPanel*)data;
2227 int item;
2229 item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2231 switch (item) {
2232 case menuNewFromFile:
2233 customPaletteMenuNewFromFile(panel);
2234 break;
2235 case menuRename:
2236 customPaletteMenuRename(panel);
2237 break;
2238 case menuRemove:
2239 customPaletteMenuRemove(panel);
2240 break;
2241 case menuCopy:
2242 break;
2243 case menuNewFromClipboard:
2244 break;
2249 static void
2250 customPaletteMenuNewFromFile(W_ColorPanel *panel)
2252 W_Screen *scr = WMWidgetScreen(panel->win);
2253 WMOpenPanel *browseP;
2254 char *filepath;
2255 char *filename = NULL;
2256 char path[PATH_MAX] = "\0";
2257 char *spath;
2258 char *tmp;
2259 int i;
2260 RImage *tmpImg = NULL;
2262 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir,"\0") == 0)) {
2263 strcpy(path, wgethomedir());
2264 spath = wmalloc(strlen(path)+2);
2265 strcpy(spath, path);
2267 else {
2268 spath = wmalloc(strlen(panel->lastBrowseDir)+2);
2269 strcpy(spath, panel->lastBrowseDir);
2273 browseP = WMGetOpenPanel(scr);
2274 WMSetFilePanelCanChooseDirectories(browseP, 0);
2275 WMSetFilePanelCanChooseFiles(browseP, 1);
2277 /* Get a filename */
2278 if (WMRunModalOpenPanelForDirectory(browseP, panel->win, wexpandpath(spath), "Open Palette", RSupportedFileFormats()) ) {
2279 filepath = WMGetFilePanelFileName(browseP);
2281 /* Get seperation position between path and filename */
2282 i = strrchr(filepath, '/') - filepath + 1;
2283 if (i > strlen(filepath))
2284 i = strlen(filepath);
2286 /* Store last browsed path */
2287 if (panel->lastBrowseDir)
2288 free(panel->lastBrowseDir);
2289 panel->lastBrowseDir = wmalloc((i+1)*sizeof(char));
2290 memset(panel->lastBrowseDir, 0, (i+1)*sizeof(char));
2291 strncpy(panel->lastBrowseDir, filepath, i);
2293 /* Get filename from path */
2294 filename = wstrdup(filepath + i);
2296 /* Check for duplicate files, and rename it if there are any */
2297 tmp = wstrappend(panel->configurationPath, filename);
2298 while (access (tmp, F_OK) == 0) {
2299 free(tmp);
2300 tmp = generateNewFilename(panel->configurationPath, filename);
2301 filename = wstrdup(tmp);
2303 free(tmp);
2304 tmp = wstrappend(panel->configurationPath, filename);
2306 free(tmp);
2308 /* Copy the image to $(gnustepdir)/Library/Colors/ & Add the filename to the history menu */
2309 if (!fetchImageFile (panel->configurationPath, filepath, filename)) { /* error = -1 */
2311 /* filepath is a "local" path now the file has been copied */
2312 free(filepath);
2313 filepath = wstrappend(panel->configurationPath, filename);
2315 /* load the image & add menu entries */
2316 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
2317 if (tmpImg) {
2318 if (panel->customPaletteImg)
2319 RDestroyImage(panel->customPaletteImg);
2320 panel->customPaletteImg = tmpImg;
2322 customSetPalette(panel);
2323 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
2324 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn)-1);
2326 panel->currentPalette = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn)-1;
2329 else
2331 tmp = wstrappend(panel->configurationPath, filename);
2333 i = remove(tmp); /* Delete the file, it doesn't belong here */
2334 WMRunAlertPanel(scr, panel->win, "File Error", "Invalid file format !", "OK", NULL, NULL);
2335 if (i != 0)
2336 WMRunAlertPanel(scr, panel->win, "File Error", "Couldn't remove file from Configuration Directory !", "OK", NULL, NULL);
2338 free(tmp);
2340 free(filepath);
2341 free(filename);
2343 WMFreeFilePanel(browseP);
2347 static void
2348 customPaletteMenuRename(W_ColorPanel *panel)
2350 W_Screen *scr = WMWidgetScreen(panel->win);
2351 char *toName = NULL;
2352 char *fromName;
2353 char *toPath, *fromPath;
2354 int item;
2355 int index;
2357 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2358 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
2360 toName = WMRunInputPanel(scr, panel->win, "Rename", "Rename palette to:",
2361 fromName, "OK", "Cancel");
2363 if (toName) {
2365 /* As some people do certain stupid things... */
2366 if (strcmp(toName, fromName) == 0) {
2367 free(toName);
2368 return;
2371 /* For normal people */
2372 fromPath = wstrappend(panel->configurationPath, fromName);
2373 toPath = wstrappend(panel->configurationPath, toName);
2375 if (access (toPath, F_OK) == 0) { /* Careful, this palette exists already */
2376 if (WMRunAlertPanel(scr, panel->win, "Warning",
2377 "Palette already exists !\n\nOverwrite ?", "No", "Yes", NULL) == 1) {
2378 /* "No" = 0, "Yes" = 1 */
2380 remove(toPath);
2382 /* Remove from History list too */
2385 * XXX This code is not functional yet !!! (And not really necessary)
2389 index = 1;
2390 while ((index < WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn)) &&
2391 (strcmp(WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, index), toName) != 0 ))
2392 index++;
2394 if (index < WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn)) {
2395 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, index);
2396 if (index < item)
2397 item--;
2401 } else {
2402 free(fromPath);
2403 free(toName);
2404 free(toPath);
2406 return;
2410 if ( rename(fromPath, toPath) != 0)
2411 wwarning("Couldn't rename palette %s to %s\n", fromName, toName);
2412 else {
2413 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
2414 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item, toName);
2416 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
2418 free(fromPath);
2419 free(toPath);
2420 free(toName);
2425 static void
2426 customPaletteMenuRemove(W_ColorPanel *panel)
2428 W_Screen *scr = WMWidgetScreen(panel->win);
2429 char *text;
2430 char *tmp;
2431 int choice;
2432 int item;
2434 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2436 tmp = wstrappend( "This will permanently remove the palette ",
2437 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
2438 text = wstrappend( tmp, ".\n\nAre you sure you want to remove this palette ?");
2439 free(tmp);
2441 choice = WMRunAlertPanel(scr, panel->win, NULL, text, "Yes", "No", NULL);
2442 /* returns 0 (= "Yes") or 1 (="No") */
2443 free(text);
2445 if (choice == 0) {
2447 tmp = wstrappend(panel->configurationPath,
2448 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
2450 if ( remove(tmp) != 0)
2451 wwarning("Couldn't remove palette %s\n", tmp);
2452 free(tmp);
2454 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item-1); /* item -1 always exists */
2455 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
2456 customSetPalette(panel);
2458 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
2463 static void
2464 customPaletteHistoryCallback(WMWidget *w, void *data)
2466 W_ColorPanel *panel = (W_ColorPanel*)data;
2467 W_Screen *scr = WMWidgetScreen(panel->win);
2468 int item;
2469 char *filename;
2470 RImage *tmp = NULL;
2472 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2473 if (item == panel->currentPalette)
2474 return;
2476 if (item == 0)
2477 customRenderSpectrum(panel);
2478 else {
2479 /* Load file from configpath */
2480 filename = wstrappend( panel->configurationPath, WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item) );
2482 /* XXX To do: Check existence of file and remove it from the history if it doesn't exist */
2484 tmp = RLoadImage(scr->rcontext, filename, 0);
2485 if (tmp) {
2486 if (panel->customPaletteImg) {
2487 RDestroyImage(panel->customPaletteImg);
2488 panel->customPaletteImg = NULL;
2490 panel->customPaletteImg = tmp;
2492 free(filename);
2494 customSetPalette(panel);
2496 panel->currentPalette = item;
2500 /*************** Panel Initialisation Functions *****************/
2502 static void
2503 wheelInit(W_ColorPanel *panel)
2505 RHSVColor cur_hsv;
2506 float W_PI = 4 * atan(1);
2507 int i;
2508 int v;
2510 RRGBtoHSV(&panel->color, &cur_hsv);
2512 WMSetSliderValue(panel->wheelBrightnessS, 255-cur_hsv.value);
2513 wheelUpdateBrightnessGradientFromHSV(panel, cur_hsv);
2515 panel->colx = 2 + rint((colorWheelSize / 2.0) * (1 + (cur_hsv.saturation/255.0) * cos( cur_hsv.hue*W_PI/180.0)));
2516 panel->coly = 2 + rint((colorWheelSize / 2.0) * (1 + (cur_hsv.saturation/255.0) * sin(-cur_hsv.hue*W_PI/180.0)));
2518 for (i = 0; i < 256; i++) {
2519 /* We divide by 128 in advance, and check whether that number divides
2520 * by 2 properly. If not, we add one to round the number correctly
2522 v = (i*cur_hsv.value) >> 7;
2523 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 1));
2527 static void
2528 grayInit(W_ColorPanel *panel)
2530 RHSVColor cur_hsv;
2531 int value;
2532 char tmp[3];
2534 RRGBtoHSV(&panel->color, &cur_hsv);
2536 value = rint(cur_hsv.value/2.55);
2537 WMSetSliderValue(panel->grayBrightnessS, value);
2539 sprintf(tmp, "%d", value);
2540 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2543 static void
2544 rgbInit(W_ColorPanel *panel)
2546 char tmp[3];
2548 WMSetSliderValue(panel->rgbRedS,panel->color.red);
2549 WMSetSliderValue(panel->rgbGreenS,panel->color.green);
2550 WMSetSliderValue(panel->rgbBlueS,panel->color.blue);
2552 sprintf(tmp, "%d", panel->color.red);
2553 WMSetTextFieldText(panel->rgbRedT, tmp);
2554 sprintf(tmp, "%d", panel->color.green);
2555 WMSetTextFieldText(panel->rgbGreenT, tmp);
2556 sprintf(tmp, "%d", panel->color.blue);
2557 WMSetTextFieldText(panel->rgbBlueT, tmp);
2560 static void
2561 cmykInit(W_ColorPanel *panel)
2563 int value[3];
2564 char tmp[3];
2566 value[0] = rint((255-panel->color.red)/2.55);
2567 value[1] = rint((255-panel->color.green)/2.55);
2568 value[2] = rint((255-panel->color.blue)/2.55);
2570 WMSetSliderValue(panel->cmykCyanS, value[0]);
2571 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2572 WMSetSliderValue(panel->cmykYellowS, value[2]);
2573 WMSetSliderValue(panel->cmykBlackS, 0);
2575 sprintf(tmp, "%d", value[0]);
2576 WMSetTextFieldText(panel->cmykCyanT, tmp);
2577 sprintf(tmp, "%d", value[1]);
2578 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2579 sprintf(tmp, "%d", value[2]);
2580 WMSetTextFieldText(panel->cmykYellowT, tmp);
2581 WMSetTextFieldText(panel->cmykBlackT, "0");
2584 static void
2585 hsbInit(W_ColorPanel *panel)
2587 int value[3];
2588 char tmp[3];
2590 value[0] = panel->hsvcolor.hue;
2591 value[1] = rint(panel->hsvcolor.saturation/2.55);
2592 value[2] = rint(panel->hsvcolor.value/2.55);
2594 WMSetSliderValue(panel->hsbHueS,value[0]);
2595 WMSetSliderValue(panel->hsbSaturationS,value[1]);
2596 WMSetSliderValue(panel->hsbBrightnessS,value[2]);
2598 sprintf(tmp, "%d", value[0]);
2599 WMSetTextFieldText(panel->hsbHueT, tmp);
2600 sprintf(tmp, "%d", value[1]);
2601 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2602 sprintf(tmp, "%d", value[2]);
2603 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2605 hsbUpdateBrightnessGradient(panel);
2606 hsbUpdateSaturationGradient(panel);
2607 hsbUpdateHueGradient(panel);
2613 /************************* ColorList Panel Functions **********************/
2615 static void
2616 colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text, int state, WMRect *rect)
2618 int width, height, x, y;
2619 RColor color = *((RColor *)WMGetListItem(lPtr, index)->clientData);
2620 WMScreen *scr = WMWidgetScreen(lPtr);
2621 Display *dpy = WMScreenDisplay(scr);
2622 RImage *image;
2623 WMPixmap *pixmap;
2624 int i, j;
2626 width = rect->size.width;
2627 height = rect->size.height;
2628 x = rect->pos.x;
2629 y = rect->pos.y;
2631 if (state & WLDSSelected)
2632 XFillRectangle(dpy, d, WMColorGC(WMWhiteColor(scr)), x, y, width, height);
2633 else
2634 XClearArea(dpy, d, x, y, width, height, False);
2636 image = RCreateImage(15, 15, False);
2637 for (i=0; i < 15 ; i++) {
2638 for (j=0; j < 15; j++) {
2639 image->data[0][j*15+i] = color.red;
2640 image->data[1][j*15+i] = color.green;
2641 image->data[2][j*15+i] = color.blue;
2645 pixmap = WMCreatePixmapFromRImage(scr, image, 0);
2646 RDestroyImage(image);
2647 WMDrawPixmap(pixmap, d, x, y);
2648 WMReleasePixmap(pixmap);
2649 WMDrawString(scr, d, WMColorGC(WMBlackColor(scr)), globalFont, x+18, y, text, strlen(text));
2653 static void
2654 colorListSelect(WMWidget *w, void *data)
2656 W_ColorPanel *panel = (W_ColorPanel *)data;
2657 RColor color = *((RColor *)WMGetListSelectedItem(w)->clientData);
2659 panel->lastChanged = WMColorListModeColorPanel;
2660 WMSetColorPanelColor(panel, color);
2666 /************************** Common utility functions ************************/
2668 static int
2669 fetchImageFile(char *toPath, char *imageSrcFile, char *imageDestFile)
2671 int src, dest;
2672 int n;
2673 char *tmp;
2674 char buf[BUFSIZE];
2676 if ((src = open(imageSrcFile, O_RDONLY)) == 0) {
2677 wwarning("Could not open %s", imageSrcFile);
2678 return -1;
2681 tmp = wstrappend(toPath, imageDestFile);
2682 if ((dest = open( tmp, O_RDWR|O_CREAT, S_IRWXU|S_IRGRP|S_IROTH)) == 0) {
2683 wwarning("Could not create %s", tmp);
2684 free(tmp);
2685 return -1;
2687 free(tmp);
2690 /* Copy the file */
2691 while ((n = read(src, buf, BUFSIZE)) > 0)
2693 if (write (dest, buf, n) != n) {
2694 wwarning("Write error on file %s", imageDestFile);
2695 return -1;
2699 return 0;
2704 char*
2705 generateNewFilename(char *Path, char *curName)
2707 char *newName;
2708 char *numStart, *numEnd;
2709 char *pre, *num, *post;
2710 int n, numLength;
2711 char *tmp;
2713 newName = wstrdup(curName);
2715 if (newName == NULL)
2716 return wstrdup("Unnamed");
2719 * Modify the name to contain a number to make it unique
2723 /* Get number-string from filename. */
2724 numStart = strrchr(newName, '(');
2725 if (numStart) {
2726 if (strlen(numStart) > 1)
2727 numStart++; /* Next character, please */
2730 numEnd = strrchr(numStart, ')'); /* Already past "numbers" */
2732 if (numEnd) {
2733 /* Now it gets interesting */
2735 pre = wmalloc((numStart - newName +1) * sizeof(char)); /* a trailing '\0' is useful here */
2736 memset(pre, 0, (numStart - newName +1) * sizeof(char));
2738 strncpy (pre, newName, numStart-newName);
2740 num = wmalloc((numEnd - numStart +1) * sizeof(char));
2741 memset (num, 0, (numEnd - numStart +1) * sizeof(char));
2743 strncpy (num, numStart, numEnd-numStart);
2745 post = wstrdup( numEnd);
2747 free(newName); /* We don't need it anymore */
2749 if (strcspn(num, "0123456789") == 0) {
2750 n = (int)strtol(num, NULL, 10);
2752 /* Increase number between brackets (in filename); This is what it all is about */
2753 n++;
2755 free(num);
2756 num = wmalloc(3 * sizeof(char)); /* Nobody uses more than 999 duplicate filenames, do you ? */
2757 memset(num, 0, 3 * sizeof(char));
2759 numLength = sprintf(num, "%d", n);
2761 free(num);
2762 num = wmalloc(numLength * sizeof(char));
2763 memset(num, 0, numLength * sizeof(char));
2765 sprintf(num, "%d", n);
2767 tmp = wstrappend (num, post);
2768 newName = wstrappend (pre, tmp);
2770 free (pre);
2771 free (num);
2772 free (post);
2773 free (tmp);
2779 if (strcmp( curName, newName) == 0) {
2780 /* The name is still unchanged, so there was no number (between brackets) in it.
2781 Add a number 1 to the end.
2783 tmp = wstrdup(newName);
2784 if (newName)
2785 free(newName);
2786 newName = wstrappend(tmp, " (1)");
2787 free(tmp);
2790 return newName;