0.51.1 pre snapshot. Be careful, it may be buggy. It fixes some bugs though.
[wmaker-crm.git] / WINGs / wcolorpanel.c
blobdd46186afed701918734c35aac832ed515a2128b
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 ;-)
12 * Changes:
13 * fixed absurd wstrdup() uses, gazillion memory leaks, buffer overruns etc etc
20 #include "WINGsP.h"
21 #include <math.h>
22 #include <unistd.h>
23 #include <ctype.h>
24 #include <fcntl.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <dirent.h>
28 #include <errno.h>
31 #ifndef PATH_MAX
32 # define PATH_MAX 1024
33 #endif
35 #define mglass_width 20
36 #define mglass_height 20
38 #define magnify_hotspot_x 17
39 #define magnify_hotspot_y 10
40 #define magnify_cursor_width 46
41 #define magnify_cursor_height 36
42 static char magnify_cursor_bits[] = {
43 0xc0, 0x0f, 0x00, 0x00, 0x00, 0xc0, 0x70, 0x70, 0x00, 0x00, 0x00, 0xc0,
44 0x18, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x04, 0x80, 0x01, 0x00, 0x00, 0xc0,
45 0x06, 0x00, 0x01, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x02, 0x00, 0x00, 0xc0,
46 0x03, 0x00, 0x02, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x06, 0x00, 0x00, 0xc0,
47 0x01, 0x00, 0x04, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0xc0,
48 0x01, 0x00, 0x04, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0xc0,
49 0x01, 0x00, 0x04, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x02, 0x00, 0x00, 0xc0,
50 0x02, 0x00, 0x02, 0x00, 0x00, 0xc0, 0x04, 0x00, 0x03, 0x00, 0x00, 0xc0,
51 0x0c, 0x80, 0x01, 0x00, 0x00, 0xc0, 0x18, 0xc0, 0x03, 0x00, 0x00, 0xc0,
52 0x70, 0x60, 0x04, 0x00, 0x00, 0xc0, 0x80, 0x1f, 0x01, 0x00, 0x00, 0xc0,
53 0x00, 0x00, 0x0a, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x10, 0x00, 0x00, 0xc0,
54 0x00, 0x00, 0x24, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x08, 0x00, 0x00, 0xc0,
55 0x00, 0x00, 0x40, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x90, 0x00, 0x00, 0xc0,
56 0x00, 0x00, 0x20, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x01, 0x00, 0xc0,
57 0x00, 0x00, 0x00, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x80, 0x04, 0x00, 0xc0,
58 0x00, 0x00, 0x00, 0x03, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0};
63 #define magnify_mask_width 46
64 #define magnify_mask_height 36
65 static char magnify_mask_bits[] = {
66 0xc0, 0x0f, 0x00, 0x00, 0x00, 0xc0, 0x70, 0x70, 0x00, 0x00, 0x00, 0xc0,
67 0x18, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x04, 0x80, 0x01, 0x00, 0x00, 0xc0,
68 0x06, 0x00, 0x01, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x02, 0x00, 0x00, 0xc0,
69 0x03, 0x00, 0x02, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x06, 0x00, 0x00, 0xc0,
70 0x01, 0x00, 0x04, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0xc0,
71 0x01, 0x00, 0x04, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x04, 0x00, 0x00, 0xc0,
72 0x01, 0x00, 0x04, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x02, 0x00, 0x00, 0xc0,
73 0x02, 0x00, 0x02, 0x00, 0x00, 0xc0, 0x04, 0x00, 0x03, 0x00, 0x00, 0xc0,
74 0x0c, 0x80, 0x01, 0x00, 0x00, 0xc0, 0x18, 0xc0, 0x03, 0x00, 0x00, 0xc0,
75 0x70, 0x60, 0x07, 0x00, 0x00, 0xc0, 0x80, 0x1f, 0x07, 0x00, 0x00, 0xc0,
76 0x00, 0x00, 0x0e, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xc0,
77 0x00, 0x00, 0x3c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x38, 0x00, 0x00, 0xc0,
78 0x00, 0x00, 0x70, 0x00, 0x00, 0xc0, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0,
79 0x00, 0x00, 0xe0, 0x00, 0x00, 0xc0, 0x00, 0x00, 0xc0, 0x01, 0x00, 0xc0,
80 0x00, 0x00, 0x80, 0x03, 0x00, 0xc0, 0x00, 0x00, 0x80, 0x07, 0x00, 0xc0,
81 0x00, 0x00, 0x00, 0x03, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0};
86 typedef struct MovingView {
87 WMView *view; /* The view this is all about */
88 Pixmap pixmap; /* What's under the view */
89 Pixmap mask; /* Pixmap mask for view-contents */
90 int valid; /* Are contents still valid ? */
91 RColor color; /* Color of a pixel in the image */
92 } MovingView;
94 typedef struct WheelMatrix {
95 unsigned int width, height; /* Size of the colorwheel */
96 unsigned char *data[3]; /* Wheel data (R,G,B) */
97 unsigned char values[256]; /* Precalculated values for R,G & B values 0..255 */
98 } wheelMatrix;
100 typedef struct W_ColorPanel {
101 WMWindow *win;
102 WMFont *font8;
103 WMFont *font12;
105 /* Common Stuff */
106 WMColorWell *colorWell;
107 WMButton *magnifyBtn;
108 WMButton *wheelBtn;
109 WMButton *slidersBtn;
110 WMButton *customPaletteBtn;
111 WMButton *colorListBtn;
113 /* Magnifying Glass */
114 MovingView *magnifyGlass;
116 /* ColorWheel Panel */
117 WMFrame *wheelFrm;
118 WMSlider *wheelBrightnessS;
119 WMView *wheelView;
121 /* Slider Panels */
122 WMFrame *slidersFrm;
123 WMFrame *seperatorFrm;
124 WMButton *grayBtn;
125 WMButton *rgbBtn;
126 WMButton *cmykBtn;
127 WMButton *hsbBtn;
128 /* Gray Scale Panel */
129 WMFrame *grayFrm;
130 WMLabel *grayMinL;
131 WMLabel *grayMaxL;
132 WMSlider *grayBrightnessS;
133 WMTextField *grayBrightnessT;
134 WMButton *grayPresetBtn[7];
136 /* RGB Panel */
137 WMFrame *rgbFrm;
138 WMLabel *rgbMinL;
139 WMLabel *rgbMaxL;
140 WMSlider *rgbRedS;
141 WMSlider *rgbGreenS;
142 WMSlider *rgbBlueS;
143 WMTextField *rgbRedT;
144 WMTextField *rgbGreenT;
145 WMTextField *rgbBlueT;
147 /* CMYK Panel */
148 WMFrame *cmykFrm;
149 WMLabel *cmykMinL;
150 WMLabel *cmykMaxL;
151 WMSlider *cmykCyanS;
152 WMSlider *cmykMagentaS;
153 WMSlider *cmykYellowS;
154 WMSlider *cmykBlackS;
155 WMTextField *cmykCyanT;
156 WMTextField *cmykMagentaT;
157 WMTextField *cmykYellowT;
158 WMTextField *cmykBlackT;
160 /* HSB Panel */
161 WMFrame *hsbFrm;
162 WMSlider *hsbHueS;
163 WMSlider *hsbSaturationS;
164 WMSlider *hsbBrightnessS;
165 WMTextField *hsbHueT;
166 WMTextField *hsbSaturationT;
167 WMTextField *hsbBrightnessT;
169 /* Custom Palette Panel*/
170 WMFrame *customPaletteFrm;
171 WMPopUpButton *customPaletteHistoryBtn;
172 WMFrame *customPaletteContentFrm;
173 WMPopUpButton *customPaletteMenuBtn;
174 WMView *customPaletteContentView;
176 /* Color List Panel */
177 WMFrame *colorListFrm;
178 WMPopUpButton *colorListHistoryBtn;
179 WMList *colorListContentLst;
180 WMPopUpButton *colorListColorMenuBtn;
181 WMPopUpButton *colorListListMenuBtn;
183 /* Look-Up Tables and Images */
184 wheelMatrix *wheelMtrx;
185 Pixmap wheelImg;
186 Pixmap selectionImg;
187 Pixmap selectionBackImg;
188 RImage *customPaletteImg;
189 char *lastBrowseDir;
191 /* Common Data Fields */
192 RColor color; /* Current color */
193 RHSVColor hsvcolor; /* Backup HSV Color */
194 WMColorPanelMode mode; /* Current color selection mode */
195 WMColorPanelMode slidersmode; /* Current color selection mode at sliders panel */
196 WMColorPanelMode lastChanged; /* Panel that last changed the color */
197 int colx, coly; /* (x,y) of selection-marker in WheelMode */
198 int palx, paly; /* (x,y) of selection-marker in CustomPaletteMode */
199 float palXRatio, palYRatio; /* Ratios in x & y between original and scaled palettesize */
200 int currentPalette;
201 char *configurationPath;
203 struct {
204 unsigned int dragging:1;
205 unsigned int done:1;
206 } flags;
207 } W_ColorPanel;
209 enum {
210 menuNewFromFile,
211 menuRename,
212 menuRemove,
213 menuCopy,
214 menuNewFromClipboard
215 } customPaletteMenuItem;
217 #define PWIDTH 194
218 #define PHEIGHT 266
219 #define colorWheelSize 150
220 #define customPaletteWidth 182
221 #define customPaletteHeight 106
222 #define knobThickness 8
224 #define SPECTRUM_WIDTH 511
225 #define SPECTRUM_HEIGHT 360
227 #define COLORWHEEL_PART 1
228 #define CUSTOMPALETTE_PART 2
229 #define BUFSIZE 1024
231 #undef EASTEREGG
233 #define RGBTXT "/usr/X11R6/lib/X11/rgb.txt"
234 #define MAX_LENGTH 1024
236 static void wAbort();
237 static int fetchImageFile(char* toPath, char *imageSrcFile, char *imageDestFileName);
238 char *generateNewFilename(char *curName);
240 static void modeButtonCallback(WMWidget *w, void *data);
241 static int getPickerPart(W_ColorPanel *panel, int x, int y);
242 static void readConfiguration(W_ColorPanel *panel);
243 static void readXColors(W_ColorPanel *panel);
245 static Cursor magnifyGrabPointer(W_ColorPanel *panel);
246 static WMPoint magnifyInitialize(W_ColorPanel *panel);
247 static void magnifyPutCursor(WMWidget *w, void *data);
248 static Pixmap magnifyCreatePixmap(WMColorPanel *panel);
249 static Pixmap magnifyGetStorePixmap(W_ColorPanel *panel, int x1, int y1, int x2, int y2);
250 static Pixmap magnifyGetImage(WMScreen *scr, int x, int y);
252 static wheelMatrix* wheelCreateMatrix(unsigned int width , unsigned int height);
253 static void wheelDestroyMatrix(wheelMatrix *matrix);
254 static wheelMatrix* wheelInitMatrix(W_ColorPanel *panel);
255 static void wheelRender(W_ColorPanel *panel);
256 static Bool wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs);
257 static void wheelPaint(W_ColorPanel *panel);
259 static void wheelHandleEvents(XEvent *event, void *data);
260 static void wheelHandleActionEvents(XEvent *event, void *data);
261 static void wheelBrightnessSliderCallback(WMWidget *w, void *data);
262 static void wheelUpdateSelection(W_ColorPanel *panel);
263 static void wheelUndrawSelection(W_ColorPanel *panel);
265 static void wheelPositionSelection(W_ColorPanel *panel, int x, int y);
266 static void wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y);
267 static void wheelUpdateBrightnessGradientFromHSV (W_ColorPanel *panel, RHSVColor topColor);
268 static void wheelUpdateBrightnessGradientFromLocation (W_ColorPanel *panel);
269 static void wheelUpdateBrightnessGradient(W_ColorPanel *panel, RColor topColor);
271 static void grayBrightnessSliderCallback(WMWidget *w, void *data);
272 static void grayPresetButtonCallback(WMWidget *w, void *data);
273 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification *notification);
275 static void rgbSliderCallback(WMWidget *w, void *data);
276 static void rgbTextFieldCallback(void *observerData, WMNotification *notification);
278 static void cmykSliderCallback(WMWidget *w, void *data);
279 static void cmykTextFieldCallback(void *observerData, WMNotification *notification);
281 static void hsbSliderCallback(WMWidget *w, void *data);
282 static void hsbTextFieldCallback(void *observerData, WMNotification *notification);
283 static void hsbUpdateBrightnessGradient(W_ColorPanel *panel);
284 static void hsbUpdateSaturationGradient(W_ColorPanel *panel);
285 static void hsbUpdateHueGradient(W_ColorPanel *panel);
287 static void customRenderSpectrum(W_ColorPanel *panel);
288 static void customSetPalette(W_ColorPanel *panel);
289 static void customPaletteHandleEvents(XEvent *event, void *data);
290 static void customPaletteHandleActionEvents(XEvent *event, void *data);
291 static void customPalettePositionSelection(W_ColorPanel *panel, int x, int y);
292 static void customPalettePositionSelectionOutBounds(W_ColorPanel *panel, int x, int y);
293 static void customPaletteMenuCallback(WMWidget *w, void *data);
294 static void customPaletteHistoryCallback(WMWidget *w, void *data);
296 static void customPaletteMenuNewFromFile(W_ColorPanel *panel);
297 static void customPaletteMenuRename(W_ColorPanel *panel);
298 static void customPaletteMenuRemove(W_ColorPanel *panel);
300 static void colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text, int state, WMRect *rect);
301 static void colorListSelect(WMWidget *w, void *data);
303 static void wheelInit(W_ColorPanel *panel);
304 static void grayInit(W_ColorPanel *panel);
305 static void rgbInit(W_ColorPanel *panel);
306 static void cmykInit(W_ColorPanel *panel);
307 static void hsbInit(W_ColorPanel *panel);
310 static void
311 wAbort ()
313 exit(1);
316 static WMColorPanel*
317 makeColorPanel(WMScreen *scrPtr, char *name)
319 WMColorPanel *panel;
320 RImage *image;
321 WMPixmap *pixmap;
322 RColor from;
323 RColor to;
324 WMColor *textcolor;
325 int i;
326 int x,y;
329 panel = wmalloc(sizeof(WMColorPanel));
330 memset(panel, 0, sizeof(WMColorPanel));
332 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
333 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
335 panel->win = WMCreateWindowWithStyle(scrPtr, name, WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
336 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
337 WMSetWindowTitle(panel->win, "Colors");
340 /* Set Default ColorPanel Mode(s) */
341 panel->mode = WMWheelModeColorPanel;
342 panel->lastChanged = WMWheelModeColorPanel;
343 panel->slidersmode = WMRGBModeColorPanel;
344 panel->configurationPath = wstrappend(wusergnusteppath(), "/Library/Colors/");
346 /* Some Generic Purpose Widgets */
347 panel->colorWell = WMCreateColorWell(panel->win);
348 WMResizeWidget(panel->colorWell, 134, 36);
349 WSetColorWellBordered(panel->colorWell, False);
350 WMMoveWidget(panel->colorWell, 56, 4);
352 panel->magnifyBtn = WMCreateCommandButton(panel->win);
353 WMResizeWidget(panel->magnifyBtn, 46, 36);
354 WMMoveWidget(panel->magnifyBtn, 6,4);
355 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
356 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
357 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
358 WMSetButtonAltImage(panel->magnifyBtn, scrPtr->altMagnifyIcon);
360 panel->wheelBtn = WMCreateCustomButton(panel->win, WBBStateLightMask|WBBStateChangeMask);
361 WMResizeWidget(panel->wheelBtn, 46, 32);
362 WMMoveWidget(panel->wheelBtn, 6, 44);
363 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
364 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
365 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
367 panel->slidersBtn = WMCreateCustomButton(panel->win, WBBStateLightMask|WBBStateChangeMask);
368 WMResizeWidget(panel->slidersBtn, 46, 32);
369 WMMoveWidget(panel->slidersBtn, 52, 44);
370 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
371 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
372 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
374 panel->customPaletteBtn = WMCreateCustomButton(panel->win, WBBStateLightMask|WBBStateChangeMask);
375 WMResizeWidget(panel->customPaletteBtn, 46, 32);
376 WMMoveWidget(panel->customPaletteBtn, 98, 44);
377 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
378 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
379 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
381 panel->colorListBtn = WMCreateCustomButton(panel->win, WBBStateLightMask|WBBStateChangeMask);
382 WMResizeWidget(panel->colorListBtn, 46, 32);
383 WMMoveWidget(panel->colorListBtn, 144, 44);
384 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
385 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
386 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
388 /* Let's Group some of them together */
389 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
390 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
391 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
393 /* Widgets for the ColorWheel Panel */
394 panel->wheelFrm = WMCreateFrame(panel->win);
395 WMSetFrameRelief(panel->wheelFrm, WRFlat);
396 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
397 WMMoveWidget(panel->wheelFrm, 5, 80);
399 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
400 /* XXX Can we create a view ? */
401 W_ResizeView(panel->wheelView, colorWheelSize+4, colorWheelSize+4);
402 W_MoveView(panel->wheelView, 0, 0);
404 /* Create an event handler to handle expose/click events in the ColorWheel */
405 WMCreateEventHandler(panel->wheelView, ButtonPressMask|ButtonReleaseMask|EnterWindowMask
406 |LeaveWindowMask|ButtonMotionMask, wheelHandleActionEvents, panel);
408 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents, panel);
410 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
411 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
412 WMMoveWidget(panel->wheelBrightnessS, 5+colorWheelSize+14, 1);
413 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
414 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
415 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback, panel);
416 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
419 /* Widgets for the Slider Panels */
420 panel->slidersFrm = WMCreateFrame(panel->win);
421 WMSetFrameRelief(panel->slidersFrm, WRFlat);
422 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
423 WMMoveWidget(panel->slidersFrm, 4, 80);
425 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
426 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
427 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
428 WMMoveWidget(panel->seperatorFrm, 0, 1);
430 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask|WBBStateChangeMask);
431 WMResizeWidget(panel->grayBtn, 46, 24);
432 WMMoveWidget(panel->grayBtn, 1, 8);
433 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
434 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
435 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
437 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask|WBBStateChangeMask);
438 WMResizeWidget(panel->rgbBtn, 46, 24);
439 WMMoveWidget(panel->rgbBtn, 47, 8);
440 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
441 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
442 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
444 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask|WBBStateChangeMask);
445 WMResizeWidget(panel->cmykBtn, 46, 24);
446 WMMoveWidget(panel->cmykBtn, 93, 8);
447 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
448 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
449 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
451 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask|WBBStateChangeMask);
452 WMResizeWidget(panel->hsbBtn, 46, 24);
453 WMMoveWidget(panel->hsbBtn, 139, 8);
454 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
455 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
456 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
458 /* Let's Group the Slider Panel Buttons Together */
459 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
460 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
461 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
463 textcolor = WMDarkGrayColor(scrPtr);
465 /* Widgets for GrayScale Panel */
466 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
467 WMSetFrameRelief(panel->grayFrm, WRFlat);
468 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
469 WMMoveWidget(panel->grayFrm, 0, 34);
471 panel->grayMinL = WMCreateLabel(panel->grayFrm);
472 WMResizeWidget(panel->grayMinL, 20, 10);
473 WMMoveWidget(panel->grayMinL, 2, 2);
474 WMSetLabelText(panel->grayMinL, "0");
475 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
476 WMSetLabelTextColor(panel->grayMinL, textcolor);
477 WMSetLabelFont(panel->grayMinL, panel->font8);
479 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
480 WMResizeWidget(panel->grayMaxL, 40, 10);
481 WMMoveWidget(panel->grayMaxL, 104, 2);
482 WMSetLabelText(panel->grayMaxL, "100");
483 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
484 WMSetLabelTextColor(panel->grayMaxL, textcolor);
485 WMSetLabelFont(panel->grayMaxL, panel->font8);
487 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
488 WMResizeWidget(panel->grayBrightnessS, 141, 16);
489 WMMoveWidget(panel->grayBrightnessS, 2, 14);
490 WMSetSliderMinValue(panel->grayBrightnessS, 0);
491 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
492 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
493 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback, panel);
495 from.red = 0;
496 from.green = 0;
497 from.blue = 0;
499 to.red = 255;
500 to.green = 255;
501 to.blue = 255;
503 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
504 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
505 RDestroyImage(image);
506 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap, panel->font12, 2, 0, 100, WALeft, W_GC(scrPtr->white), False, "Brightness", strlen("Brightness"));
507 WMSetSliderImage(panel->grayBrightnessS, pixmap);
508 WMReleasePixmap(pixmap);
510 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
511 WMResizeWidget(panel->grayBrightnessT, 40, 18);
512 WMMoveWidget(panel->grayBrightnessT, 146, 13);
513 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
514 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel, \
515 WMTextDidEndEditingNotification, panel->grayBrightnessT);
517 image = RCreateImage(13,13,False);
518 for (i=0; i < 7; i++) {
519 for (x=0; x < 13; x++) {
520 for (y=0; y < 13; y++) {
521 image->data[0][y*13+x] = 255/6*i;
522 image->data[1][y*13+x] = 255/6*i;
523 image->data[2][y*13+x] = 255/6*i;
526 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
527 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
528 WMMoveWidget(panel->grayPresetBtn[i], 2+(i*20), 34);
529 WMSetButtonAction(panel->grayPresetBtn[i], grayPresetButtonCallback, panel);
530 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
531 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
532 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
533 WMReleasePixmap(pixmap);
535 RDestroyImage(image);
536 /* End of GrayScale Panel */
538 /* Widgets for RGB Panel */
539 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
540 WMSetFrameRelief(panel->rgbFrm, WRFlat);
541 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
542 WMMoveWidget(panel->rgbFrm, 0, 34);
544 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
545 WMResizeWidget(panel->rgbMinL, 20, 10);
546 WMMoveWidget(panel->rgbMinL, 2, 2);
547 WMSetLabelText(panel->rgbMinL, "0");
548 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
549 WMSetLabelTextColor(panel->rgbMinL, textcolor);
550 WMSetLabelFont(panel->rgbMinL, panel->font8);
552 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
553 WMResizeWidget(panel->rgbMaxL, 40, 10);
554 WMMoveWidget(panel->rgbMaxL, 104, 2);
555 WMSetLabelText(panel->rgbMaxL, "255");
556 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
557 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
558 WMSetLabelFont(panel->rgbMaxL, panel->font8);
560 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
561 WMResizeWidget(panel->rgbRedS, 141, 16);
562 WMMoveWidget(panel->rgbRedS, 2, 14);
563 WMSetSliderMinValue(panel->rgbRedS, 0);
564 WMSetSliderMaxValue(panel->rgbRedS, 255);
565 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
566 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
568 to.red = 255;
569 to.green = 0;
570 to.blue = 0;
572 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
573 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
574 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12, 2, 0, 100, WALeft, W_GC(scrPtr->white), False, "Red", strlen("Red"));
575 RDestroyImage(image);
576 WMSetSliderImage(panel->rgbRedS, pixmap);
577 WMReleasePixmap(pixmap);
579 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
580 WMResizeWidget(panel->rgbRedT, 40, 18);
581 WMMoveWidget(panel->rgbRedT, 146, 13);
582 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
583 WMAddNotificationObserver(rgbTextFieldCallback, panel, \
584 WMTextDidEndEditingNotification, panel->rgbRedT);
587 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
588 WMResizeWidget(panel->rgbGreenS, 141, 16);
589 WMMoveWidget(panel->rgbGreenS, 2, 36);
590 WMSetSliderMinValue(panel->rgbGreenS, 0);
591 WMSetSliderMaxValue(panel->rgbGreenS, 255);
592 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
593 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
595 to.red = 0;
596 to.green = 255;
597 to.blue = 0;
599 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
600 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
601 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12, 2, 0, 100, WALeft, W_GC(scrPtr->white), False, "Green", strlen("Green"));
602 RDestroyImage(image);
603 WMSetSliderImage(panel->rgbGreenS, pixmap);
604 WMReleasePixmap(pixmap);
606 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
607 WMResizeWidget(panel->rgbGreenT, 40, 18);
608 WMMoveWidget(panel->rgbGreenT, 146, 35);
609 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
610 WMAddNotificationObserver(rgbTextFieldCallback, panel, \
611 WMTextDidEndEditingNotification, panel->rgbGreenT);
614 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
615 WMResizeWidget(panel->rgbBlueS, 141, 16);
616 WMMoveWidget(panel->rgbBlueS, 2, 58);
617 WMSetSliderMinValue(panel->rgbBlueS, 0);
618 WMSetSliderMaxValue(panel->rgbBlueS, 255);
619 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
620 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
622 to.red = 0;
623 to.green = 0;
624 to.blue = 255;
626 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
627 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
628 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12, 2, 0, 100, WALeft, W_GC(scrPtr->white), False, "Blue", strlen("Blue"));
629 RDestroyImage(image);
630 WMSetSliderImage(panel->rgbBlueS, pixmap);
631 WMReleasePixmap(pixmap);
633 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
634 WMResizeWidget(panel->rgbBlueT, 40, 18);
635 WMMoveWidget(panel->rgbBlueT, 146, 57);
636 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
637 WMAddNotificationObserver(rgbTextFieldCallback, panel, \
638 WMTextDidEndEditingNotification, panel->rgbBlueT);
639 /* End of RGB Panel */
641 /* Widgets for CMYK Panel */
642 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
643 WMSetFrameRelief(panel->cmykFrm, WRFlat);
644 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
645 WMMoveWidget(panel->cmykFrm, 0, 34);
647 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
648 WMResizeWidget(panel->cmykMinL, 20, 10);
649 WMMoveWidget(panel->cmykMinL, 2, 2);
650 WMSetLabelText(panel->cmykMinL, "0");
651 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
652 WMSetLabelTextColor(panel->cmykMinL, textcolor);
653 WMSetLabelFont(panel->cmykMinL, panel->font8);
655 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
656 WMResizeWidget(panel->cmykMaxL, 40, 10);
657 WMMoveWidget(panel->cmykMaxL, 104, 2);
658 WMSetLabelText(panel->cmykMaxL, "100");
659 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
660 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
661 WMSetLabelFont(panel->cmykMaxL, panel->font8);
663 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
664 WMResizeWidget(panel->cmykCyanS, 141, 16);
665 WMMoveWidget(panel->cmykCyanS, 2, 14);
666 WMSetSliderMinValue(panel->cmykCyanS, 0);
667 WMSetSliderMaxValue(panel->cmykCyanS, 100);
668 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
669 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
671 from.red = 255;
672 from.green = 255;
673 from.blue = 255;
675 to.red = 0;
676 to.green = 255;
677 to.blue = 255;
679 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
680 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
681 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12, 2, 0, 100, WALeft, W_GC(scrPtr->black), False, "Cyan", strlen("Cyan"));
682 RDestroyImage(image);
683 WMSetSliderImage(panel->cmykCyanS, pixmap);
684 WMReleasePixmap(pixmap);
686 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
687 WMResizeWidget(panel->cmykCyanT, 40, 18);
688 WMMoveWidget(panel->cmykCyanT, 146, 13);
689 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
690 WMAddNotificationObserver(cmykTextFieldCallback, panel, \
691 WMTextDidEndEditingNotification, panel->cmykCyanT);
694 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
695 WMResizeWidget(panel->cmykMagentaS, 141, 16);
696 WMMoveWidget(panel->cmykMagentaS, 2, 36);
697 WMSetSliderMinValue(panel->cmykMagentaS, 0);
698 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
699 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
700 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
702 to.red = 255;
703 to.green = 0;
704 to.blue = 255;
706 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
707 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
708 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12, 2, 0, 100, WALeft, W_GC(scrPtr->black), False, "Magenta", strlen("Magenta"));
709 RDestroyImage(image);
710 WMSetSliderImage(panel->cmykMagentaS, pixmap);
711 WMReleasePixmap(pixmap);
713 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
714 WMResizeWidget(panel->cmykMagentaT, 40, 18);
715 WMMoveWidget(panel->cmykMagentaT, 146, 35);
716 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
717 WMAddNotificationObserver(cmykTextFieldCallback, panel, \
718 WMTextDidEndEditingNotification, panel->cmykMagentaT);
721 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
722 WMResizeWidget(panel->cmykYellowS, 141, 16);
723 WMMoveWidget(panel->cmykYellowS, 2, 58);
724 WMSetSliderMinValue(panel->cmykYellowS, 0);
725 WMSetSliderMaxValue(panel->cmykYellowS, 100);
726 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
727 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
729 to.red = 255;
730 to.green = 255;
731 to.blue = 0;
733 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
734 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
735 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12, 2, 0, 100, WALeft, W_GC(scrPtr->black), False, "Yellow", strlen("Yellow"));
736 RDestroyImage(image);
737 WMSetSliderImage(panel->cmykYellowS, pixmap);
738 WMReleasePixmap(pixmap);
740 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
741 WMResizeWidget(panel->cmykYellowT, 40, 18);
742 WMMoveWidget(panel->cmykYellowT, 146, 57);
743 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
744 WMAddNotificationObserver(cmykTextFieldCallback, panel, \
745 WMTextDidEndEditingNotification, panel->cmykYellowT);
748 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
749 WMResizeWidget(panel->cmykBlackS, 141, 16);
750 WMMoveWidget(panel->cmykBlackS, 2, 80);
751 WMSetSliderMinValue(panel->cmykBlackS, 0);
752 WMSetSliderMaxValue(panel->cmykBlackS, 100);
753 WMSetSliderValue(panel->cmykBlackS, 0);
754 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
755 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
757 to.red = 0;
758 to.green = 0;
759 to.blue = 0;
761 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
762 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
763 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12, 2, 0, 100, WALeft, W_GC(scrPtr->black), False, "Black", strlen("Black"));
764 RDestroyImage(image);
765 WMSetSliderImage(panel->cmykBlackS, pixmap);
766 WMReleasePixmap(pixmap);
768 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
769 WMResizeWidget(panel->cmykBlackT, 40, 18);
770 WMMoveWidget(panel->cmykBlackT, 146, 79);
771 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
772 WMAddNotificationObserver(cmykTextFieldCallback, panel, \
773 WMTextDidEndEditingNotification, panel->cmykBlackT);
774 /* End of CMYK Panel */
776 /* Widgets for HSB Panel */
777 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
778 WMSetFrameRelief(panel->hsbFrm, WRFlat);
779 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
780 WMMoveWidget(panel->hsbFrm, 0, 34);
782 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
783 WMResizeWidget(panel->hsbHueS, 141, 16);
784 WMMoveWidget(panel->hsbHueS, 2, 14);
785 WMSetSliderMinValue(panel->hsbHueS, 0);
786 WMSetSliderMaxValue(panel->hsbHueS, 359);
787 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
788 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
790 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
791 WMResizeWidget(panel->hsbHueT, 40, 18);
792 WMMoveWidget(panel->hsbHueT, 146, 13);
793 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
794 WMAddNotificationObserver(hsbTextFieldCallback, panel, \
795 WMTextDidEndEditingNotification, panel->hsbHueT);
798 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
799 WMResizeWidget(panel->hsbSaturationS, 141, 16);
800 WMMoveWidget(panel->hsbSaturationS, 2, 36);
801 WMSetSliderMinValue(panel->hsbSaturationS, 0);
802 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
803 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
804 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
806 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
807 WMResizeWidget(panel->hsbSaturationT, 40, 18);
808 WMMoveWidget(panel->hsbSaturationT, 146, 35);
809 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
810 WMAddNotificationObserver(hsbTextFieldCallback, panel, \
811 WMTextDidEndEditingNotification, panel->hsbSaturationT);
814 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
815 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
816 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
817 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
818 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
819 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
820 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
822 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
823 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
824 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
825 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
826 WMAddNotificationObserver(hsbTextFieldCallback, panel, \
827 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
828 /* End of HSB Panel */
831 WMReleaseColor(textcolor);
833 /* Widgets for the CustomPalette Panel */
834 panel->customPaletteFrm = WMCreateFrame(panel->win);
835 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
836 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
837 WMMoveWidget(panel->customPaletteFrm, 5, 80);
839 panel->customPaletteHistoryBtn = WMCreatePopUpButton(panel->customPaletteFrm);
840 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, "Spectrum");
841 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn)-1);
842 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn, customPaletteHistoryCallback, panel);
843 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
844 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
846 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
847 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
848 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
849 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
851 panel->customPaletteContentView = W_CreateView(W_VIEW(panel->customPaletteContentFrm));
852 /* XXX Can we create a view ? */
853 W_ResizeView(panel->customPaletteContentView, customPaletteWidth, customPaletteHeight);
854 W_MoveView(panel->customPaletteContentView, 2, 2);
856 /* Create an event handler to handle expose/click events in the CustomPalette */
857 WMCreateEventHandler(panel->customPaletteContentView, ButtonPressMask|ButtonReleaseMask|EnterWindowMask
858 |LeaveWindowMask|ButtonMotionMask, customPaletteHandleActionEvents, panel);
860 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask, customPaletteHandleEvents, panel);
862 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
863 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
864 WMSetPopUpButtonText(panel->customPaletteMenuBtn, "Palette");
865 WMSetPopUpButtonAction(panel->customPaletteMenuBtn, customPaletteMenuCallback, panel);
866 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
867 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
869 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "New from File..."); /* item 0 */
870 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Rename..."); /* item 1 */
871 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Remove"); /* item 2 */
872 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Copy"); /* item 3 */
873 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "New from Clipboard"); /* item 4 */
875 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, 1, 0);
876 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, 2, 0);
877 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, 3, 0);
878 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, 4, 0);
880 customRenderSpectrum(panel);
881 panel->currentPalette = 0;
884 /* Widgets for the ColorList Panel */
885 panel->colorListFrm = WMCreateFrame(panel->win);
886 WMSetFrameRelief(panel->colorListFrm, WRFlat);
887 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
888 WMMoveWidget(panel->colorListFrm, 5, 80);
890 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
891 WMAddPopUpButtonItem(panel->colorListHistoryBtn, "X11-Colors");
892 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn, WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn)-1);
893 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn, colorListHistoryCallback, panel); */
894 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
895 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
897 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
898 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
899 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
900 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
901 WMMoveWidget(panel->colorListContentLst, 0, 23);
902 WMHangData(panel->colorListContentLst, panel);
904 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
905 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
906 WMSetPopUpButtonText(panel->colorListColorMenuBtn, "Color");
907 /* WMSetPopUpButtonAction(panel->colorListColorMenuBtn, colorListColorMenuCallback, panel); */
908 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16)/2, 20);
909 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
911 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
912 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
913 WMSetPopUpButtonText(panel->colorListListMenuBtn, "List");
914 /* WMSetPopUpButtonAction(panel->colorListListMenuBtn, colorListListMenuCallback, panel); */
915 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2, 20);
916 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2 + 8, PHEIGHT - 130);
919 WMRealizeWidget(panel->win);
920 WMMapSubwidgets(panel->win);
922 WMMapSubwidgets(panel->wheelFrm);
923 WMMapSubwidgets(panel->slidersFrm);
924 WMMapSubwidgets(panel->grayFrm);
925 WMMapSubwidgets(panel->rgbFrm);
926 WMMapSubwidgets(panel->cmykFrm);
927 WMMapSubwidgets(panel->hsbFrm);
928 WMMapSubwidgets(panel->customPaletteFrm);
929 WMMapSubwidgets(panel->customPaletteContentFrm);
930 WMMapSubwidgets(panel->colorListFrm);
932 readConfiguration(panel);
933 readXColors(panel);
935 return panel;
939 WMColorPanel*
940 WMGetColorPanel(WMScreen *scrPtr)
942 WMColorPanel *panel;
944 if (scrPtr->sharedColorPanel)
945 return scrPtr->sharedColorPanel;
947 panel = makeColorPanel(scrPtr, "colorPanel");
949 scrPtr->sharedColorPanel = panel;
951 return panel;
955 void
956 WMFreeColorPanel(WMColorPanel *panel)
958 W_Screen *scr = WMWidgetScreen(panel->win);
960 if (panel == scr->sharedColorPanel) {
961 WMWidgetScreen(panel->win)->sharedColorPanel = NULL;
963 WMRemoveNotificationObserver(panel);
964 WMUnmapWidget(panel->win);
965 WMDestroyWidget(panel->win);
966 if (panel->font8)
967 WMReleaseFont(panel->font8);
968 if (panel->font12)
969 WMReleaseFont(panel->font12);
970 if (panel->magnifyGlass->pixmap)
971 XFreePixmap(scr->display, panel->magnifyGlass->pixmap);
972 if (panel->wheelMtrx)
973 wheelDestroyMatrix(panel->wheelMtrx);
974 if (panel->wheelImg)
975 XFreePixmap(scr->display, panel->wheelImg);
976 if (panel->selectionImg)
977 XFreePixmap(scr->display, panel->selectionImg);
978 if (panel->selectionBackImg)
979 XFreePixmap(scr->display, panel->selectionBackImg);
980 if (panel->customPaletteImg)
981 RDestroyImage(panel->customPaletteImg);
982 if (panel->lastBrowseDir)
983 free(panel->lastBrowseDir);
984 if (panel->configurationPath)
985 free(panel->configurationPath);
987 free(panel);
992 WMRunColorPanel(WMColorPanel *panel, WMWindow *owner, RColor color)
994 WMScreen *scr = WMWidgetScreen(panel->win);
995 XEvent event;
996 RHSVColor hsvcolor;
997 GC bgc = W_GC(scr->black);
998 GC wgc = W_GC(scr->white);
999 float W_PI = 4*atan(1);
1001 WMChangePanelOwner(panel->win, owner);
1003 WMSetColorPanelColor(panel, color);
1004 panel->wheelMtrx = wheelInitMatrix(panel); /* Needs to be done After Color is set */
1006 /* Maybe put this in sub-function ... Initialising selection images */
1007 RRGBtoHSV(&color, &hsvcolor);
1008 panel->colx = 2 + rint((colorWheelSize / 2.0) * (1 + (hsvcolor.saturation/255.0) * cos( hsvcolor.hue*W_PI/180.0)));
1009 panel->coly = 2 + rint((colorWheelSize / 2.0) * (1 + (hsvcolor.saturation/255.0) * sin(-hsvcolor.hue*W_PI/180.0)));
1010 wheelUpdateBrightnessGradientFromHSV(panel, hsvcolor);
1011 WMSetSliderValue(panel->wheelBrightnessS, 255 - hsvcolor.value);
1013 panel->selectionImg = XCreatePixmap(scr->display, W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
1014 XFillRectangle(scr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1015 XFillRectangle(scr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1016 /* End of initialisation section */
1018 panel->palx = customPaletteWidth/2;
1019 panel->paly = customPaletteHeight/2;
1021 WMSetPickerMode(panel, WMWheelModeColorPanel);
1023 panel->flags.done = 0;
1025 WMMapWidget(panel->win);
1027 while (!panel->flags.done) {
1028 WMNextEvent(scr->display, &event);
1029 WMHandleEvent(&event);
1032 WMCloseWindow(panel->win);
1034 return 0;
1039 static void
1040 readConfiguration(W_ColorPanel *panel)
1042 /* XXX Doesn't take care of "invalid" files */
1044 DIR *dPtr;
1045 struct dirent *dp;
1046 struct stat stat_buf;
1049 if (stat(panel->configurationPath, &stat_buf)!=0) {
1050 if (mkdir(panel->configurationPath, S_IRWXU|S_IRGRP|S_IROTH|S_IXGRP|S_IXOTH)!=0) {
1051 wsyserror("ColorPanel could not create directory %s needed to store configurations", panel->configurationPath);
1052 WMFreeColorPanel(panel);
1053 wAbort();
1055 return;
1058 dPtr = opendir(panel->configurationPath);
1059 while ((dp = readdir(dPtr)) != NULL) {
1060 if (dp->d_name[0] != '.')
1061 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1063 (void)closedir(dPtr);
1067 static void
1068 readXColors(W_ColorPanel *panel)
1070 struct stat stat_buf;
1071 FILE *rgbtxt;
1072 char line[MAX_LENGTH];
1073 int red, green, blue;
1074 char name[48];
1075 RColor *color;
1076 WMListItem *item;
1078 if (stat(RGBTXT, &stat_buf) != 0) {
1079 wwarning("Cannot find file %s", RGBTXT);
1080 return;
1082 else {
1083 rgbtxt = fopen(RGBTXT, "r");
1084 if (rgbtxt) {
1085 while (fgets(line, MAX_LENGTH, rgbtxt)) {
1086 if (sscanf(line, "%d%d%d %[^\n]", &red, &green, &blue, name)) {
1087 color = wmalloc(sizeof(RColor));
1088 color->red = (unsigned char)red;
1089 color->green = (unsigned char)green;
1090 color->blue = (unsigned char)blue;
1091 item = WMAddListItem(panel->colorListContentLst, name);
1092 item->clientData = (void *)color;
1095 fclose(rgbtxt);
1097 else {
1098 wsyserror("Unable to open file %s for reading", RGBTXT);
1104 void
1105 WMSetPickerMode(WMColorPanel *panel, WMColorPanelMode mode)
1107 W_Screen *scr = WMWidgetScreen(panel->win);
1109 if (mode != WMWheelModeColorPanel) {
1110 WMUnmapWidget(panel->wheelFrm);
1111 if (panel->selectionBackImg) {
1112 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1113 panel->selectionBackImg = None;
1116 if (mode != WMGrayModeColorPanel)
1117 WMUnmapWidget(panel->grayFrm);
1118 if (mode != WMRGBModeColorPanel)
1119 WMUnmapWidget(panel->rgbFrm);
1120 if (mode != WMCMYKModeColorPanel)
1121 WMUnmapWidget(panel->cmykFrm);
1122 if (mode != WMHSBModeColorPanel)
1123 WMUnmapWidget(panel->hsbFrm);
1124 if (mode != WMCustomPaletteModeColorPanel) {
1125 WMUnmapWidget(panel->customPaletteFrm);
1126 if (panel->selectionBackImg) {
1127 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1128 panel->selectionBackImg = None;
1131 if (mode != WMColorListModeColorPanel)
1132 WMUnmapWidget(panel->colorListFrm);
1133 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) && \
1134 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1135 WMUnmapWidget(panel->slidersFrm);
1136 else
1137 panel->slidersmode = mode;
1139 if (mode == WMWheelModeColorPanel) {
1140 WMMapWidget(panel->wheelFrm);
1141 WMSetButtonSelected(panel->wheelBtn, True);
1142 if (panel->lastChanged != WMWheelModeColorPanel)
1143 wheelInit(panel);
1144 wheelRender(panel);
1145 wheelPaint(panel);
1146 } else if (mode == WMGrayModeColorPanel) {
1147 WMMapWidget(panel->slidersFrm);
1148 WMSetButtonSelected(panel->slidersBtn, True);
1149 WMMapWidget(panel->grayFrm);
1150 WMSetButtonSelected(panel->grayBtn, True);
1151 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1152 if (panel->lastChanged != WMGrayModeColorPanel)
1153 grayInit(panel);
1154 } else if (mode == WMRGBModeColorPanel) {
1155 WMMapWidget(panel->slidersFrm);
1156 WMSetButtonSelected(panel->slidersBtn, True);
1157 WMMapWidget(panel->rgbFrm);
1158 WMSetButtonSelected(panel->rgbBtn, True);
1159 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1160 if (panel->lastChanged != WMRGBModeColorPanel)
1161 rgbInit(panel);
1162 } else if (mode == WMCMYKModeColorPanel) {
1163 WMMapWidget(panel->slidersFrm);
1164 WMSetButtonSelected(panel->slidersBtn, True);
1165 WMMapWidget(panel->cmykFrm);
1166 WMSetButtonSelected(panel->cmykBtn, True);
1167 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1168 if (panel->lastChanged != WMCMYKModeColorPanel)
1169 cmykInit(panel);
1170 } else if (mode == WMHSBModeColorPanel) {
1171 WMMapWidget(panel->slidersFrm);
1172 WMSetButtonSelected(panel->slidersBtn, True);
1173 WMMapWidget(panel->hsbFrm);
1174 WMSetButtonSelected(panel->hsbBtn, True);
1175 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1176 if (panel->lastChanged != WMHSBModeColorPanel)
1177 hsbInit(panel);
1178 } else if (mode == WMCustomPaletteModeColorPanel) {
1179 WMMapWidget(panel->customPaletteFrm);
1180 WMSetButtonSelected(panel->customPaletteBtn, True);
1181 customSetPalette(panel);
1182 } else if (mode == WMColorListModeColorPanel) {
1183 WMMapWidget(panel->colorListFrm);
1184 WMSetButtonSelected(panel->colorListBtn, True);
1188 panel->mode = mode;
1191 void
1192 WMSetColorPanelColor(WMColorPanel *panel, RColor color)
1194 WMScreen *scr = WMWidgetScreen(panel->win);
1195 WMColor *wellcolor;
1196 int originalHue;
1198 wellcolor = WMCreateRGBColor(scr, color.red << 8, color.green << 8, color.blue << 8, True);
1199 WMSetColorWellColor(panel->colorWell, wellcolor);
1200 WMReleaseColor(wellcolor);
1202 panel->color = color;
1204 /* If color was set by HSB-Panel do not convert back to hsv */
1205 if (panel->lastChanged != WMHSBModeColorPanel) {
1207 /* if color is black, hue is undetermined, so it must be restored */
1208 if ((panel->color.red == 0) &&
1209 (panel->color.green == 0) &&
1210 (panel->color.blue == 0) &&
1211 (panel->hsvcolor.hue <= 359))
1213 originalHue = panel->hsvcolor.hue;
1214 RRGBtoHSV(&panel->color, &panel->hsvcolor);
1215 panel->hsvcolor.hue = originalHue;
1216 } else {
1217 RRGBtoHSV(&panel->color, &panel->hsvcolor);
1222 static void
1223 modeButtonCallback(WMWidget *w, void *data)
1225 W_ColorPanel *panel = (W_ColorPanel*)(data);
1227 if (w == panel->wheelBtn)
1228 WMSetPickerMode(panel, WMWheelModeColorPanel);
1229 else if (w == panel->slidersBtn)
1230 WMSetPickerMode(panel, panel->slidersmode);
1231 else if (w == panel->customPaletteBtn)
1232 WMSetPickerMode(panel, WMCustomPaletteModeColorPanel);
1233 else if (w == panel->colorListBtn)
1234 WMSetPickerMode(panel, WMColorListModeColorPanel);
1235 else if (w == panel->grayBtn)
1236 WMSetPickerMode(panel, WMGrayModeColorPanel);
1237 else if (w == panel->rgbBtn)
1238 WMSetPickerMode(panel, WMRGBModeColorPanel);
1239 else if (w == panel->cmykBtn)
1240 WMSetPickerMode(panel, WMCMYKModeColorPanel);
1241 else if (w == panel->hsbBtn)
1242 WMSetPickerMode(panel, WMHSBModeColorPanel);
1246 /****************** Magnifying Cursor Functions *******************/
1247 static Pixmap
1248 magnifyGetImage(WMScreen *scr, int x, int y)
1250 XImage *image;
1251 Pixmap pixmap;
1252 int x0, y0, w0, h0;
1253 int displayWidth = DisplayWidth(scr->display, scr->screen);
1254 int displayHeight = DisplayHeight(scr->display, scr->screen);
1256 /* Coordinate correction for back pixmap */
1257 x0 = 0; y0 = 0; w0 = mglass_width; h0 = mglass_height;
1259 if (x < mglass_width/2) {
1260 if (x < 0) x = 0;
1261 x0 = mglass_width/2 - x;
1262 w0 = mglass_width - x0;
1265 if (x > displayWidth - (mglass_width+1)/2) {
1266 if (x > displayWidth) x = displayWidth;
1267 w0 = mglass_width - ((mglass_width+1)/2 - (displayWidth - x));
1270 if (y < mglass_height/2) {
1271 if (y < 0) y = 0;
1272 y0 = mglass_height/2 - y;
1273 h0 = mglass_height - y0;
1276 if (y > displayHeight - (mglass_height+1)/2) {
1277 if (y > displayHeight) y = displayHeight;
1278 h0 = mglass_height - ((mglass_height+1)/2 - (displayHeight - y));
1281 image = XGetImage(scr->display, scr->rootWin, x + x0 - mglass_width/2,
1282 y + y0 - mglass_height/2, w0, h0, AllPlanes, ZPixmap);
1284 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1285 mglass_width, mglass_height, scr->depth);
1286 XPutImage(scr->display, pixmap, scr->copyGC, image, 0, 0, x0, y0, w0, h0);
1288 return pixmap;
1292 static Pixmap
1293 magnifyGetStorePixmap(WMColorPanel *panel, int x1, int y1, int x2, int y2)
1296 * (x1, y1) = topleft corner of existing rectangle
1297 * (x2, y2) = topleft corner of new position
1300 W_Screen *scr = WMWidgetScreen(panel->win);
1301 Pixmap pixmap;
1302 int xa, ya, xb, yb, w, h;
1304 if (x1 < x2) {
1305 xa = x2 - x1;
1306 xb = 0;
1307 } else {
1308 xa = 0;
1309 xb = x1 - x2;
1312 if (y1 < y2) {
1313 ya = y2 - y1;
1314 yb = 0;
1315 } else {
1316 ya = 0;
1317 yb = y1 - y2;
1320 w = mglass_width - abs(x1-x2);
1321 h = mglass_height - abs(y1-y2);
1323 /* Get pixmap from screen */
1324 pixmap = magnifyGetImage(scr, x2, y2);
1326 /* Copy previously stored pixmap on covered part of above pixmap */
1327 if (panel->magnifyGlass->valid) {
1328 XCopyArea(scr->display, panel->magnifyGlass->pixmap, pixmap,
1329 scr->copyGC, xa, ya, w, h, xb, yb);
1331 /* Free it, so we can reuse it */
1332 XFreePixmap(scr->display, panel->magnifyGlass->pixmap);
1335 return pixmap;
1339 static Pixmap
1340 magnifyCreatePixmap(WMColorPanel *panel)
1342 W_Screen *scr = WMWidgetScreen(panel->win);
1343 int u, v;
1344 int i, j;
1345 int ofs;
1346 Pixmap magPix;
1347 Pixmap backPix;
1348 RImage *pixelImg;
1351 * Get image
1354 /* Rectangle that's going to be the background */
1355 backPix = XCreatePixmap(scr->display, W_DRAWABLE(scr), mglass_width,
1356 mglass_height, scr->depth);
1357 XCopyArea(scr->display, panel->magnifyGlass->pixmap, backPix, scr->copyGC,
1358 0, 0, mglass_width, mglass_height, 0, 0);
1361 * Magnify image
1364 magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr), mglass_width,
1365 mglass_height, scr->depth);
1367 for (u=0; u<=3; u++)
1368 for (v=0; v<=3; v++)
1369 for (i=u*6; i < (u+1)*6; i++)
1370 for (j=v*6; j < (v+1)*6; j++)
1371 if (((i >= 0) && (i < mglass_width))
1372 && ((j >= 0) && (j < mglass_height)))
1373 XCopyArea(scr->display, backPix, magPix, scr->copyGC,
1374 u + 4, v + 4, 1, 1, i, j);
1376 /* Get color under hotspot */
1377 ofs = mglass_width/2 + (mglass_height/2)*mglass_width;
1378 pixelImg = RCreateImageFromDrawable(scr->rcontext, backPix, backPix);
1379 panel->magnifyGlass->color.red = pixelImg->data[0][ofs];
1380 panel->magnifyGlass->color.green = pixelImg->data[1][ofs];
1381 panel->magnifyGlass->color.blue = pixelImg->data[2][ofs];
1382 RDestroyImage(pixelImg);
1384 /* Copy the magnified pixmap, with the clip mask, to the background pixmap */
1385 XSetClipMask(scr->display, scr->clipGC, panel->magnifyGlass->mask);
1386 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1388 XCopyArea(scr->display, magPix, backPix, scr->clipGC, 0, 0,
1389 mglass_width, mglass_height, 0, 0);
1391 XFreePixmap(scr->display, magPix);
1393 return backPix;
1397 static WMView*
1398 magnifyCreateView(W_ColorPanel *panel)
1400 W_Screen *scr = WMWidgetScreen(panel->win);
1401 WMView *magView;
1403 magView = W_CreateTopView(scr);
1404 magView->self = panel;
1406 W_ResizeView(magView, mglass_width, mglass_height);
1408 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1409 magView->attribs.event_mask = StructureNotifyMask;
1410 magView->attribs.override_redirect = True;
1411 magView->attribs.save_under = True;
1413 W_RealizeView(magView);
1414 W_MapView(magView);
1416 return magView;
1420 static Cursor
1421 magnifyGrabPointer(W_ColorPanel *panel)
1423 W_Screen *scr = WMWidgetScreen(panel->win);
1424 Pixmap magPixmap;
1425 Pixmap magPixmap2;
1426 Cursor magCursor;
1427 XColor fgColor = {0,0,0,0,DoRed|DoGreen|DoBlue};
1428 XColor bgColor = {0,0xbd00,0xa500,0x5200,DoRed|DoGreen|DoBlue};
1430 /* Cursor creation stuff */
1431 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1432 magnify_cursor_bits,
1433 magnify_cursor_width,
1434 magnify_cursor_height, 1, 0, 1);
1435 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1436 magnify_mask_bits,
1437 magnify_mask_width,
1438 magnify_mask_height, 1, 0, 1);
1439 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1440 &fgColor, &bgColor, magnify_hotspot_x,
1441 magnify_hotspot_y);
1442 XFreePixmap(scr->display, magPixmap);
1443 XFreePixmap(scr->display, magPixmap2);
1445 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1447 /* Set up Pointer */
1448 XGrabPointer (scr->display, panel->magnifyGlass->view->window, True,
1449 PointerMotionMask | ButtonPressMask,
1450 GrabModeAsync, GrabModeAsync,
1451 scr->rootWin, magCursor, CurrentTime);
1453 return magCursor;
1456 static WMPoint
1457 magnifyInitialize(W_ColorPanel *panel)
1459 W_Screen *scr = WMWidgetScreen(panel->win);
1460 int x, y, u, v;
1461 unsigned int mask;
1462 Pixmap pixmap;
1463 WMPoint point;
1465 XQueryPointer(scr->display, scr->rootWin, &scr->rootWin,
1466 &W_VIEW(panel->win)->window, &x, &y, &u, &v, &mask);
1469 /* Clipmask to make magnified view-contents circular */
1470 panel->magnifyGlass->mask =
1471 XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1472 magnify_mask_bits, mglass_width,
1473 mglass_height, 1, 0, 1);
1475 /* Draw initial magnified part */
1476 panel->magnifyGlass->valid = False;
1477 /* also free's magnifyGlass->pixmap */
1478 panel->magnifyGlass->pixmap = magnifyGetStorePixmap(panel, x, y, x, y);
1479 panel->magnifyGlass->valid = True;
1481 pixmap = magnifyCreatePixmap(panel);
1482 W_MoveView(panel->magnifyGlass->view, x - magnify_hotspot_x,
1483 y - magnify_hotspot_y);
1485 XSetWindowBackgroundPixmap(scr->display, panel->magnifyGlass->view->window,
1486 pixmap);
1487 XClearWindow(scr->display, panel->magnifyGlass->view->window);
1488 XFlush(scr->display);
1490 XFreePixmap(scr->display, pixmap);
1492 point.x = x;
1493 point.y = y;
1495 return point;
1499 static void
1500 magnifyPutCursor(WMWidget *w, void *data)
1502 W_ColorPanel *panel = (W_ColorPanel*)(data);
1503 W_Screen *scr = WMWidgetScreen(panel->win);
1504 Cursor magCursor;
1505 int x, y;
1506 Pixmap pixmap;
1507 XEvent event;
1508 WMPoint initialPosition;
1510 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1512 panel->magnifyGlass->view = magnifyCreateView(panel);
1513 magCursor = magnifyGrabPointer(panel);
1515 initialPosition = magnifyInitialize(panel);
1516 x = initialPosition.x;
1517 y = initialPosition.y;
1520 while(panel->magnifyGlass->valid)
1522 WMNextEvent(scr->display, &event);
1524 switch (event.type)
1526 case ButtonPress:
1527 if (event.xbutton.button == Button1) {
1528 WMSetColorPanelColor(panel, panel->magnifyGlass->color);
1529 switch (panel->mode) {
1530 case WMWheelModeColorPanel:
1531 wheelInit(panel);
1532 wheelRender(panel);
1533 wheelPaint(panel);
1534 break;
1535 case WMGrayModeColorPanel:
1536 grayInit(panel);
1537 break;
1538 case WMRGBModeColorPanel:
1539 rgbInit(panel);
1540 break;
1541 case WMCMYKModeColorPanel:
1542 cmykInit(panel);
1543 break;
1544 case WMHSBModeColorPanel:
1545 hsbInit(panel);
1546 break;
1547 default:
1548 break;
1550 panel->lastChanged = panel->mode;
1553 panel->magnifyGlass->valid = False;
1554 WMSetButtonSelected(panel->magnifyBtn, False);
1555 break;
1557 case MotionNotify:
1558 /* Get a "dirty rectangle" */
1559 panel->magnifyGlass->pixmap = magnifyGetStorePixmap(
1560 panel, x, y, /* Cool, a circular reference ! */
1561 event.xmotion.x_root,
1562 event.xmotion.y_root); /* also free's magnifyGlass->pixmap */
1564 /* Update coordinates */
1565 x = event.xmotion.x_root;
1566 y = event.xmotion.y_root;
1568 /* Move view */
1569 W_MoveView(panel->magnifyGlass->view, x - magnify_hotspot_x,
1570 y - magnify_hotspot_y);
1572 /* Put new image (with magn.) in view */
1573 pixmap = magnifyCreatePixmap(panel);
1574 XSetWindowBackgroundPixmap(scr->display,
1575 panel->magnifyGlass->view->window,
1576 pixmap);
1577 XClearWindow(scr->display, panel->magnifyGlass->view->window);
1579 XFreePixmap(scr->display, pixmap);
1580 break;
1582 default:
1583 WMHandleEvent(&event);
1584 break;
1585 } /* of switch */
1587 panel->magnifyGlass->valid = False;
1589 XUngrabPointer(scr->display, CurrentTime);
1590 XFreeCursor(scr->display, magCursor);
1591 W_DestroyView(panel->magnifyGlass->view);
1593 XFreePixmap(scr->display, panel->magnifyGlass->mask);
1594 XFreePixmap(scr->display, panel->magnifyGlass->pixmap);
1595 free(panel->magnifyGlass);
1600 /****************** WheelMatrix Functions ************************/
1602 static wheelMatrix*
1603 wheelCreateMatrix(unsigned int width, unsigned int height)
1605 wheelMatrix *matrix = NULL;
1606 int i;
1608 assert((width > 0) && (height > 0));
1610 matrix = malloc(sizeof(wheelMatrix));
1611 if (!matrix) {
1612 RErrorCode = RERR_NOMEMORY;
1613 return NULL;
1616 memset(matrix, 0, sizeof(wheelMatrix));
1617 matrix->width = width;
1618 matrix->height = height;
1619 for (i = 0; i < 3; i++) {
1620 matrix->data[i] = malloc(width*height*sizeof(unsigned char));
1621 if (!matrix->data[i])
1622 goto error;
1625 return matrix;
1627 error:
1628 for (i = 0; i < 3; i++) {
1629 if (matrix->data[i])
1630 free(matrix->data[i]);
1632 if (matrix)
1633 free(matrix);
1634 RErrorCode = RERR_NOMEMORY;
1635 return NULL;
1639 static void
1640 wheelDestroyMatrix(wheelMatrix *matrix)
1642 int i;
1644 assert (matrix!=NULL);
1646 for (i = 0; i < 3; i++) {
1647 if (matrix->data[i])
1648 free(matrix->data[i]);
1650 free(matrix);
1654 static wheelMatrix*
1655 wheelInitMatrix(W_ColorPanel *panel)
1657 int i;
1658 int x,y;
1659 wheelMatrix *matrix;
1660 unsigned char *rp, *gp, *bp;
1661 RHSVColor cur_hsv;
1662 RColor cur_rgb;
1663 long ofs[4];
1664 float hue;
1665 int sat;
1666 float xcor, ycor;
1667 float W_PI = 4 *atan(1);
1668 int dhue[4];
1670 matrix = wheelCreateMatrix(colorWheelSize+4, colorWheelSize+4);
1671 if (!matrix)
1672 return NULL;
1674 RRGBtoHSV(&panel->color, &cur_hsv);
1676 for (i = 0; i < 256; i++)
1677 matrix->values[i] = (unsigned char)(rint(i*cur_hsv.value/255));
1679 cur_hsv.value = 255;
1681 ofs[0] = -1;
1682 ofs[1] = -(colorWheelSize + 4);
1683 /* ofs[2] = 0; superfluous
1684 ofs[3] = 0;
1686 for (y = 0; y < (colorWheelSize+4)/2; y++) {
1687 for (x = y; x < (colorWheelSize+4-y); x++) {
1688 xcor = ((float)(2.0*x - 4.0) / colorWheelSize) - 1;
1689 ycor = ((float)(2.0*y - 4.0) / colorWheelSize) - 1;
1691 sat = rint(255.0 * sqrt((xcor*xcor) + (ycor*ycor)));
1695 /* offsets are counterclockwise (in triangles) */
1696 if (y < (colorWheelSize+4)/2)
1697 ofs[0]++;
1698 /* top quarter */
1699 ofs[1] += colorWheelSize + 4; /* left quarter */
1702 ofs[2] = (colorWheelSize + 4) * (colorWheelSize + 4) - 1 - ofs[0]; /* bottom quarter */
1703 ofs[3] = (colorWheelSize + 4) * (colorWheelSize + 4) - 1 - ofs[1]; /* right quarter */
1705 if (sat < 256) {
1706 cur_hsv.saturation = (unsigned char)sat;
1708 if (xcor != 0)
1709 hue = atan(ycor/xcor);
1710 else {
1711 if (ycor > 0)
1712 hue = W_PI * 0.5;
1713 else
1714 hue = W_PI * 1.5;
1717 if (xcor < 0)
1718 hue += W_PI;
1719 if ((xcor > 0) && (ycor < 0))
1720 hue += W_PI * 2.0;
1722 hue = -hue; /* Reverse direction of ColorWheel */
1724 if (hue < 0)
1725 hue += W_PI * 2.0;
1727 dhue[0] = (hue*360) / (W_PI * 2.0);
1729 for (i = 0; i < 4; i++) {
1731 if (i > 0)
1732 dhue[i] = (dhue[i-1] + 90) % 360;
1734 if ((i == 1) || (i == 3))
1735 dhue[i] = 360 - dhue[i];
1737 if (i == 2)
1738 dhue[i] = 360 - dhue[i] + 180;
1740 rp = matrix->data[0] + (ofs[i] * sizeof(unsigned char));
1741 gp = matrix->data[1] + (ofs[i] * sizeof(unsigned char));
1742 bp = matrix->data[2] + (ofs[i] * sizeof(unsigned char));
1744 cur_hsv.hue = dhue[i];
1745 RHSVtoRGB(&cur_hsv, &cur_rgb);
1747 *rp = (unsigned char)(cur_rgb.red);
1748 *gp = (unsigned char)(cur_rgb.green);
1749 *bp = (unsigned char)(cur_rgb.blue);
1752 else {
1753 for (i = 0; i < 4; i++) {
1754 rp = matrix->data[0] + (ofs[i] * sizeof(unsigned char));
1755 gp = matrix->data[1] + (ofs[i] * sizeof(unsigned char));
1756 bp = matrix->data[2] + (ofs[i] * sizeof(unsigned char));
1758 *rp = (unsigned char)(0);
1759 *gp = (unsigned char)(0);
1760 *bp = (unsigned char)(0);
1764 if (y < (colorWheelSize+4)/2)
1765 ofs[0] += 2*y+1;
1767 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2*y);
1770 return matrix;
1773 /****************** ColorWheel Functions *******************/
1775 static void
1776 wheelRender(W_ColorPanel *panel)
1778 W_Screen *scr = WMWidgetScreen(panel->win);
1779 int x,y;
1780 RImage *image;
1781 unsigned char *rp, *gp, *bp;
1782 RColor gray;
1783 unsigned long ofs;
1785 image = RCreateImage(colorWheelSize+4, colorWheelSize+4, False);
1786 if (!image)
1787 return;
1789 gray.red = gray.green = gray.blue = 0xaa;
1791 for (x = 0; x < colorWheelSize+4; x++) {
1792 for (y = 0; y < colorWheelSize+4; y++) {
1794 ofs = (y * image->width) + x;
1795 rp = image->data[0] + ofs;
1796 gp = image->data[1] + ofs;
1797 bp = image->data[2] + ofs;
1799 if (wheelInsideColorWheel(panel, ofs)) {
1800 *rp = (unsigned int)(panel->wheelMtrx->values[ panel->wheelMtrx->data[0][ofs] ]);
1801 *gp = (unsigned int)(panel->wheelMtrx->values[ panel->wheelMtrx->data[1][ofs] ]);
1802 *bp = (unsigned int)(panel->wheelMtrx->values[ panel->wheelMtrx->data[2][ofs] ]);
1804 else {
1805 *rp = (unsigned char)(gray.red);
1806 *gp = (unsigned char)(gray.green);
1807 *bp = (unsigned char)(gray.blue);
1812 if (panel->wheelImg)
1813 XFreePixmap(scr->display, panel->wheelImg);
1815 panel->wheelImg = XCreatePixmap(scr->display, W_DRAWABLE(scr), colorWheelSize+4, colorWheelSize+4, scr->depth);
1816 RConvertImage(scr->rcontext, image, &panel->wheelImg);
1818 /* Check backimage existence. If it doesn't exist, allocate it and fill it */
1819 if (!panel->selectionBackImg) {
1820 panel->selectionBackImg = XCreatePixmap(scr->display, W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
1821 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg, scr->copyGC,
1822 panel->colx -2, panel->coly -2, 4, 4, 0, 0); /* -2 is for hot spot correction */
1825 RDestroyImage(image);
1828 static Bool
1829 wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs)
1831 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
1832 (panel->wheelMtrx->data[1][ofs] != 0) &&
1833 (panel->wheelMtrx->data[2][ofs] != 0));
1836 static void
1837 wheelPaint (W_ColorPanel *panel)
1839 W_Screen *scr = WMWidgetScreen(panel->win);
1841 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window, scr->copyGC,
1842 0, 0, colorWheelSize+4, colorWheelSize+4, 0, 0);
1844 /* Draw selection image */
1845 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window, scr->copyGC,
1846 0, 0, 4, 4, panel->colx -2, panel->coly -2);
1849 static void
1850 wheelHandleEvents(XEvent *event, void *data)
1852 W_ColorPanel *panel = (W_ColorPanel*)data;
1854 switch (event->type) {
1855 case Expose:
1856 if (event->xexpose.count != 0)
1857 break;
1858 wheelPaint(panel);
1859 break;
1863 static void
1864 wheelHandleActionEvents(XEvent *event, void *data)
1866 W_ColorPanel *panel = (W_ColorPanel*)data;
1868 switch (event->type) {
1869 case ButtonPress:
1870 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) == COLORWHEEL_PART) {
1871 panel->flags.dragging = 1;
1872 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
1874 break;
1876 case ButtonRelease:
1877 panel->flags.dragging = 0;
1878 break;
1880 case MotionNotify:
1881 if (panel->flags.dragging) {
1882 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) == COLORWHEEL_PART) {
1883 wheelPositionSelection(panel, event->xmotion.x, event->xmotion.y);
1885 else
1886 wheelPositionSelectionOutBounds(panel, event->xmotion.x, event->xmotion.y);
1888 break;
1893 static int
1894 getPickerPart(W_ColorPanel *panel, int x, int y)
1896 int lx, ly;
1897 unsigned long ofs;
1899 lx = x;
1900 ly = y;
1902 if (panel->mode == WMWheelModeColorPanel) {
1903 if ((lx >= 2) && (lx <= 2+colorWheelSize) && (ly >= 2) && (ly <= 2+colorWheelSize)) {
1904 ofs = ly*panel->wheelMtrx->width+lx;
1906 if (wheelInsideColorWheel(panel, ofs))
1907 return COLORWHEEL_PART;
1911 if (panel->mode == WMCustomPaletteModeColorPanel) {
1912 if ((lx >= 2) && (lx < customPaletteWidth-2) && (ly >= 2) && (ly < customPaletteHeight-2)) {
1913 return CUSTOMPALETTE_PART;
1917 return 0;
1921 static void
1922 wheelBrightnessSliderCallback(WMWidget *w, void *data)
1924 int i;
1925 unsigned int v;
1926 int value;
1927 unsigned long ofs;
1928 RColor cur_rgb;
1930 W_ColorPanel *panel = (W_ColorPanel*)data;
1932 value = 255-WMGetSliderValue(panel->wheelBrightnessS);
1934 for (i = 0; i < 256; i++) {
1935 /* We divide by 128 in advance, and check whether that number divides
1936 * by 2 properly. If not, we add one to round the number correctly
1938 v = (i*value) >> 7;
1939 #ifdef EASTEREGG
1940 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + v);
1941 #else
1942 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) +(v & 0x01));
1943 #endif
1946 ofs = (panel->coly * panel->wheelMtrx->width) + panel->colx;
1948 if (!wheelInsideColorWheel(panel, ofs)) {
1949 panel->hsvcolor.saturation = 255;
1950 panel->hsvcolor.value = value;
1951 RHSVtoRGB(&panel->hsvcolor, &cur_rgb);
1953 panel->color = cur_rgb;
1955 else {
1956 panel->color.red = panel->wheelMtrx->values[ panel->wheelMtrx->data[0][ofs] ];
1957 panel->color.green = panel->wheelMtrx->values[ panel->wheelMtrx->data[1][ofs] ];
1958 panel->color.blue = panel->wheelMtrx->values[ panel->wheelMtrx->data[2][ofs] ];
1961 wheelRender(panel);
1962 wheelPaint(panel);
1963 wheelUpdateSelection(panel);
1967 static void
1968 wheelUpdateSelection(W_ColorPanel *panel)
1970 W_Screen *scr = WMWidgetScreen(panel->win);
1972 WMSetColorPanelColor(panel, panel->color);
1973 panel->lastChanged = WMWheelModeColorPanel;
1975 /* Redraw color selector (and make a backup of the part it will cover) */
1976 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg, scr->copyGC,
1977 panel->colx -2, panel->coly -2, 4, 4, 0, 0); /* "-2" is correction for hotspot location */
1978 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window, scr->copyGC,
1979 0, 0, 4, 4, panel->colx -2, panel->coly -2); /* see above */
1982 static void
1983 wheelUndrawSelection(W_ColorPanel *panel)
1985 W_Screen *scr = WMWidgetScreen(panel->win);
1987 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window, scr->copyGC,
1988 0, 0, 4, 4, panel->colx -2, panel->coly -2); /* see above */
1991 static void
1992 wheelPositionSelection(W_ColorPanel *panel, int x, int y)
1994 unsigned long ofs = (y * panel->wheelMtrx->width)+ x;
1997 panel->color.red = panel->wheelMtrx->values[ panel->wheelMtrx->data[0][ofs] ];
1998 panel->color.green = panel->wheelMtrx->values[ panel->wheelMtrx->data[1][ofs] ];
1999 panel->color.blue = panel->wheelMtrx->values[ panel->wheelMtrx->data[2][ofs] ];
2001 wheelUndrawSelection(panel);
2003 panel->colx = x;
2004 panel->coly = y;
2006 wheelUpdateSelection(panel);
2007 wheelUpdateBrightnessGradientFromLocation(panel);
2010 static void
2011 wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
2013 RHSVColor cur_hsv;
2014 float hue;
2015 float xcor, ycor;
2016 float W_PI = 4*atan(1);
2018 xcor = ((x*2.0) / (colorWheelSize+4)) - 1.0;
2019 ycor = ((y*2.0) / (colorWheelSize+4)) - 1.0;
2021 cur_hsv.saturation = 255;
2022 cur_hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2024 if (xcor != 0)
2025 hue = atan(ycor/xcor);
2026 else {
2027 if (ycor > 0)
2028 hue = W_PI * 0.5;
2029 else
2030 hue = W_PI * 1.5;
2033 if (xcor < 0)
2034 hue += W_PI;
2035 if ((xcor > 0) && (ycor < 0))
2036 hue += W_PI * 2.0;
2038 hue = -hue;
2040 if (hue < 0)
2041 hue += W_PI * 2.0;
2043 cur_hsv.hue = (hue*360.0)/(W_PI*2.0);
2044 RHSVtoRGB(&cur_hsv, &panel->color);
2046 wheelUndrawSelection(panel);
2048 panel->colx = 2 + rint((colorWheelSize * (1.0 + cos( cur_hsv.hue*W_PI/180))) /2.0); /* "+2" because of "colorWheelSize + 4" */
2049 panel->coly = 2 + rint((colorWheelSize * (1.0 + sin(-cur_hsv.hue*W_PI/180))) /2.0);
2051 wheelUpdateSelection(panel);
2052 wheelUpdateBrightnessGradientFromHSV(panel, cur_hsv);
2055 static void
2056 wheelUpdateBrightnessGradientFromHSV(W_ColorPanel *panel, RHSVColor topColor)
2058 RColor from;
2060 /* Update Brightness-Slider */
2061 topColor.value = 255;
2062 RHSVtoRGB(&topColor, &from);
2064 wheelUpdateBrightnessGradient(panel, from);
2067 static void
2068 wheelUpdateBrightnessGradientFromLocation(W_ColorPanel *panel)
2070 RColor from;
2071 unsigned long ofs;
2073 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2075 from.red = panel->wheelMtrx->data[0][ofs];
2076 from.green = panel->wheelMtrx->data[1][ofs];
2077 from.blue = panel->wheelMtrx->data[2][ofs];
2079 wheelUpdateBrightnessGradient(panel, from);
2082 static void
2083 wheelUpdateBrightnessGradient(W_ColorPanel *panel, RColor topColor)
2085 RColor to;
2086 RImage *sliderImg;
2087 WMPixmap *sliderPxmp;
2089 to.red = to.green = to.blue = 0;
2091 sliderImg = RRenderGradient(16, 153, &topColor, &to, RGRD_VERTICAL);
2092 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win), sliderImg, 0);
2093 RDestroyImage(sliderImg);
2094 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2095 WMReleasePixmap(sliderPxmp);
2098 /****************** Grayscale Panel Functions ***************/
2100 static void
2101 grayBrightnessSliderCallback(WMWidget *w, void *data)
2103 RColor color;
2104 int value;
2105 char tmp[4];
2107 W_ColorPanel *panel = (W_ColorPanel*)data;
2109 value = WMGetSliderValue(panel->grayBrightnessS);
2111 sprintf(tmp, "%d", value);
2113 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2114 color.red = color.green = color.blue = rint(2.55*value);
2116 WMSetColorPanelColor(panel, color);
2117 panel->lastChanged = WMGrayModeColorPanel;
2120 static void
2121 grayPresetButtonCallback(WMWidget *w, void *data)
2123 RColor color;
2124 char tmp[4];
2125 int value;
2126 int i=0;
2128 W_ColorPanel *panel = (W_ColorPanel*)data;
2130 while (i < 7) {
2131 if (w == panel->grayPresetBtn[i])
2132 break;
2133 i++;
2136 value = rint(100.0/6.0*i);
2137 sprintf(tmp, "%d", value);
2139 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2140 color.red = color.green = color.blue = rint(255.0*i/6.0);
2142 WMSetSliderValue(panel->grayBrightnessS, rint(100.0*i/6.0));
2144 WMSetColorPanelColor(panel, color);
2145 panel->lastChanged = WMGrayModeColorPanel;
2148 static void
2149 grayBrightnessTextFieldCallback(void *observerData, WMNotification *notification)
2151 RColor color;
2152 char tmp[4];
2153 int value;
2154 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2156 value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
2157 if (value > 100)
2158 value = 100;
2159 if (value < 0)
2160 value = 0;
2162 sprintf(tmp, "%d", value);
2163 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2164 WMSetSliderValue(panel->grayBrightnessS, value);
2166 color.red = color.green = color.blue = rint(255.0*value/100.0);
2167 WMSetColorPanelColor(panel, color);
2168 panel->lastChanged = WMGrayModeColorPanel;
2171 /******************* RGB Panel Functions *****************/
2173 static void
2174 rgbSliderCallback(WMWidget *w, void *data)
2176 RColor color;
2177 int value[3];
2178 char tmp[4];
2180 W_ColorPanel *panel = (W_ColorPanel*)data;
2182 value[0] = WMGetSliderValue(panel->rgbRedS);
2183 value[1] = WMGetSliderValue(panel->rgbGreenS);
2184 value[2] = WMGetSliderValue(panel->rgbBlueS);
2186 sprintf(tmp, "%d", value[0]);
2187 WMSetTextFieldText(panel->rgbRedT, tmp);
2188 sprintf(tmp, "%d", value[1]);
2189 WMSetTextFieldText(panel->rgbGreenT, tmp);
2190 sprintf(tmp, "%d", value[2]);
2191 WMSetTextFieldText(panel->rgbBlueT, tmp);
2193 color.red = value[0];
2194 color.green = value[1];
2195 color.blue = value[2];
2197 WMSetColorPanelColor(panel, color);
2198 panel->lastChanged = WMRGBModeColorPanel;
2201 static void
2202 rgbTextFieldCallback(void *observerData, WMNotification *notification)
2204 RColor color;
2205 char tmp[4];
2206 int value[3];
2207 int n;
2208 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2210 value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
2211 value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
2212 value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
2214 for (n=0; n < 3; n++) {
2215 if (value[n] > 255)
2216 value[n] = 255;
2217 if (value[n] < 0)
2218 value[n] = 0;
2221 sprintf(tmp, "%d", value[0]);
2222 WMSetTextFieldText(panel->rgbRedT, tmp);
2223 sprintf(tmp, "%d", value[1]);
2224 WMSetTextFieldText(panel->rgbGreenT, tmp);
2225 sprintf(tmp, "%d", value[2]);
2226 WMSetTextFieldText(panel->rgbBlueT, tmp);
2228 WMSetSliderValue(panel->rgbRedS, value[0]);
2229 WMSetSliderValue(panel->rgbGreenS, value[1]);
2230 WMSetSliderValue(panel->rgbBlueS, value[2]);
2232 color.red = value[0];
2233 color.green = value[1];
2234 color.blue = value[2];
2236 WMSetColorPanelColor(panel, color);
2237 panel->lastChanged = WMRGBModeColorPanel;
2241 /******************* CMYK Panel Functions *****************/
2243 static void
2244 cmykSliderCallback(WMWidget *w, void *data)
2246 RColor color;
2247 int value[4];
2248 char tmp[4];
2250 W_ColorPanel *panel = (W_ColorPanel*)data;
2252 value[0] = WMGetSliderValue(panel->cmykCyanS);
2253 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2254 value[2] = WMGetSliderValue(panel->cmykYellowS);
2255 value[3] = WMGetSliderValue(panel->cmykBlackS);
2257 sprintf(tmp, "%d", value[0]);
2258 WMSetTextFieldText(panel->cmykCyanT, tmp);
2259 sprintf(tmp, "%d", value[1]);
2260 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2261 sprintf(tmp, "%d", value[2]);
2262 WMSetTextFieldText(panel->cmykYellowT, tmp);
2263 sprintf(tmp, "%d", value[3]);
2264 WMSetTextFieldText(panel->cmykBlackT, tmp);
2266 color.red = rint((255.0 - (value[0] * 2.55)) * (1.0 - (value[3] / 100.0)));
2267 color.green = rint((255.0 - (value[1] * 2.55)) * (1.0 - (value[3] / 100.0)));
2268 color.blue = rint((255.0 - (value[2] * 2.55)) * (1.0 - (value[3] / 100.0)));
2270 WMSetColorPanelColor(panel, color);
2271 panel->lastChanged = WMCMYKModeColorPanel;
2274 static void
2275 cmykTextFieldCallback(void *observerData, WMNotification *notification)
2277 RColor color;
2278 char tmp[4];
2279 int value[4];
2280 int n;
2281 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2283 value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
2284 value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
2285 value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
2286 value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
2288 for (n=0; n < 4; n++) {
2289 if (value[n] > 100)
2290 value[n] = 100;
2291 if (value[n] < 0)
2292 value[n] = 0;
2295 sprintf(tmp, "%d", value[0]);
2296 WMSetTextFieldText(panel->cmykCyanT, tmp);
2297 sprintf(tmp, "%d", value[1]);
2298 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2299 sprintf(tmp, "%d", value[2]);
2300 WMSetTextFieldText(panel->cmykYellowT, tmp);
2301 sprintf(tmp, "%d", value[3]);
2302 WMSetTextFieldText(panel->cmykBlackT, tmp);
2304 WMSetSliderValue(panel->cmykCyanS, value[0]);
2305 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2306 WMSetSliderValue(panel->cmykYellowS, value[2]);
2307 WMSetSliderValue(panel->cmykBlackS, value[3]);
2309 color.red = rint((255.0 - (value[0] * 2.55)) * (1.0 - (value[3] / 100.0)));
2310 color.green = rint((255.0 - (value[1] * 2.55)) * (1.0 - (value[3] / 100.0)));
2311 color.blue = rint((255.0 - (value[2] * 2.55)) * (1.0 - (value[3] / 100.0)));
2313 WMSetColorPanelColor(panel, color);
2314 panel->lastChanged = WMCMYKModeColorPanel;
2317 /********************** HSB Panel Functions ***********************/
2319 static void
2320 hsbSliderCallback(WMWidget *w, void *data)
2322 RColor color;
2323 int value[3];
2324 char tmp[4];
2326 W_ColorPanel *panel = (W_ColorPanel*)data;
2328 value[0] = WMGetSliderValue(panel->hsbHueS);
2329 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2330 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2332 sprintf(tmp, "%d", value[0]);
2333 WMSetTextFieldText(panel->hsbHueT, tmp);
2334 sprintf(tmp, "%d", value[1]);
2335 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2336 sprintf(tmp, "%d", value[2]);
2337 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2339 panel->hsvcolor.hue = value[0];
2340 panel->hsvcolor.saturation = value[1]*2.55;
2341 panel->hsvcolor.value = value[2]*2.55;
2343 RHSVtoRGB(&panel->hsvcolor, &color);
2345 panel->lastChanged = WMHSBModeColorPanel;
2346 WMSetColorPanelColor(panel, color);
2348 if (w != panel->hsbBrightnessS)
2349 hsbUpdateBrightnessGradient(panel);
2350 if (w != panel->hsbSaturationS)
2351 hsbUpdateSaturationGradient(panel);
2352 if (w != panel->hsbHueS)
2353 hsbUpdateHueGradient(panel);
2356 static void
2357 hsbTextFieldCallback(void *observerData, WMNotification *notification)
2359 RColor color;
2360 char tmp[4];
2361 int value[3];
2362 int n;
2363 W_ColorPanel *panel = (W_ColorPanel*)observerData;
2365 value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
2366 value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
2367 value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
2369 if (value[0] > 359)
2370 value[0] = 359;
2371 if (value[0] < 0)
2372 value[0] = 0;
2374 for (n=1; n < 3; n++) {
2375 if (value[n] > 100)
2376 value[n] = 100;
2377 if (value[n] < 0)
2378 value[n] = 0;
2381 sprintf(tmp, "%d", value[0]);
2382 WMSetTextFieldText(panel->hsbHueT, tmp);
2383 sprintf(tmp, "%d", value[1]);
2384 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2385 sprintf(tmp, "%d", value[2]);
2386 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2388 WMSetSliderValue(panel->hsbHueS, value[0]);
2389 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2390 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2392 panel->hsvcolor.hue = value[0];
2393 panel->hsvcolor.saturation = value[1]*2.55;
2394 panel->hsvcolor.value = value[2]*2.55;
2396 RHSVtoRGB(&panel->hsvcolor, &color);
2398 panel->lastChanged = WMHSBModeColorPanel;
2399 WMSetColorPanelColor(panel, color);
2401 hsbUpdateBrightnessGradient(panel);
2402 hsbUpdateSaturationGradient(panel);
2403 hsbUpdateHueGradient(panel);
2406 static void
2407 hsbUpdateBrightnessGradient(W_ColorPanel *panel)
2409 W_Screen *scr = WMWidgetScreen(panel->win);
2410 RColor from;
2411 RColor to;
2412 RHSVColor hsvcolor;
2413 RImage *sliderImg;
2414 WMPixmap *sliderPxmp;
2416 from.red = from.green = from.blue = 0;
2417 hsvcolor = panel->hsvcolor;
2418 hsvcolor.value = 255;
2420 RHSVtoRGB(&hsvcolor, &to);
2422 sliderImg = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
2423 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2424 RDestroyImage(sliderImg);
2425 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap, panel->font12, 2, 0, 100, WALeft, W_GC(scr->white), False, "Brightness", strlen("Brightness"));
2426 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2427 WMReleasePixmap(sliderPxmp);
2430 static void
2431 hsbUpdateSaturationGradient(W_ColorPanel *panel)
2433 W_Screen *scr = WMWidgetScreen(panel->win);
2434 RColor from;
2435 RColor to;
2436 RHSVColor hsvcolor;
2437 RImage *sliderImg;
2438 WMPixmap *sliderPxmp;
2440 hsvcolor = panel->hsvcolor;
2441 hsvcolor.saturation = 0;
2442 RHSVtoRGB(&hsvcolor, &from);
2444 hsvcolor.saturation = 255;
2445 RHSVtoRGB(&hsvcolor, &to);
2447 sliderImg = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
2448 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2449 RDestroyImage(sliderImg);
2450 if (hsvcolor.value < 128)
2451 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap, panel->font12, 2, 0, 100, WALeft, W_GC(scr->white), False, "Saturation", strlen("Saturation"));
2452 else
2453 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap, panel->font12, 2, 0, 100, WALeft, W_GC(scr->black), False, "Saturation", strlen("Saturation"));
2455 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2456 WMReleasePixmap(sliderPxmp);
2459 static void
2460 hsbUpdateHueGradient(W_ColorPanel *panel)
2462 W_Screen *scr = WMWidgetScreen(panel->win);
2463 RColor **colors = NULL;
2464 RHSVColor hsvcolor;
2465 RImage *sliderImg;
2466 WMPixmap *sliderPxmp;
2467 int i;
2469 hsvcolor = panel->hsvcolor;
2471 colors = malloc(sizeof(RColor*)*(8));
2472 for (i=0; i<7; i++) {
2473 hsvcolor.hue = (360*i)/6;
2474 colors[i] = malloc(sizeof(RColor));
2475 RHSVtoRGB(&hsvcolor, colors[i]);
2477 colors[7] = NULL;
2479 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2480 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2481 RDestroyImage(sliderImg);
2482 if (hsvcolor.value < 128)
2483 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap, panel->font12, 2, 0, 100, WALeft, W_GC(scr->white), False, "Hue", strlen("Hue"));
2484 else
2485 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap, panel->font12, 2, 0, 100, WALeft, W_GC(scr->black), False, "Hue", strlen("Hue"));
2487 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2488 WMReleasePixmap(sliderPxmp);
2490 for (i=0; i<7; i++) {
2491 if (colors[i])
2492 free(colors[i]);
2494 if (colors)
2495 free(colors);
2498 /*************** Custom Palette Functions ****************/
2500 static void
2501 customRenderSpectrum(W_ColorPanel *panel)
2503 RImage *spectrum;
2504 int hue, sat, val;
2505 int x,y;
2506 unsigned long ofs;
2507 unsigned char *rp, *gp, *bp;
2508 RColor color;
2509 RHSVColor cur_hsv;
2511 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, 0);
2513 for (y=0; y<360; y++) {
2514 val = 255;
2515 sat = 0;
2516 hue = y;
2517 for (x=0; x<511; x++) {
2518 ofs = (y * 511) + x;
2520 cur_hsv.hue = hue;
2521 cur_hsv.saturation = sat;
2522 cur_hsv.value = val;
2524 RHSVtoRGB (&cur_hsv, &color);
2526 rp = spectrum->data[0] + ofs;
2527 gp = spectrum->data[1] + ofs;
2528 bp = spectrum->data[2] + ofs;
2530 *rp = (unsigned char)color.red;
2531 *gp = (unsigned char)color.green;
2532 *bp = (unsigned char)color.blue;
2534 if (x<255)
2535 sat++;
2537 if (x>255)
2538 val--;
2541 if (panel->customPaletteImg) {
2542 RDestroyImage(panel->customPaletteImg);
2543 panel->customPaletteImg = NULL;
2545 panel->customPaletteImg = spectrum;
2550 static void
2551 customSetPalette(W_ColorPanel *panel)
2553 W_Screen *scr = WMWidgetScreen(panel->win);
2554 RImage *scaledImg;
2555 Pixmap image;
2556 int item;
2558 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth, customPaletteHeight, scr->depth);
2560 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth, customPaletteHeight);
2561 RConvertImage(scr->rcontext, scaledImg, &image);
2562 RDestroyImage(scaledImg);
2564 XCopyArea(scr->display, image, panel->customPaletteContentView->window, scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2566 /* Check backimage existence. If it doesn't exist, allocate it and fill it */
2567 if (!panel->selectionBackImg) {
2568 panel->selectionBackImg = XCreatePixmap(scr->display, panel->customPaletteContentView->window, 4, 4, scr->depth);
2571 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC, panel->palx-2, panel->paly-2, 4, 4, 0, 0);
2572 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0 , 0, 4, 4, panel->palx-2, panel->paly-2);
2573 XFreePixmap(scr->display, image);
2575 panel->palXRatio = (float)(panel->customPaletteImg->width) / (float)(customPaletteWidth);
2576 panel->palYRatio = (float)(panel->customPaletteImg->height) / (float)(customPaletteHeight);
2578 item = WMGetPopUpButtonSelectedItem (panel->customPaletteHistoryBtn);
2580 /* if palette != "Spectrum", we are allowed to rename and remove it */
2581 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, menuRename, (item > 0) );
2582 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, menuRemove, (item > 0) );
2586 static void
2587 customPalettePositionSelection(W_ColorPanel *panel, int x, int y)
2589 W_Screen *scr = WMWidgetScreen(panel->win);
2590 unsigned long ofs;
2593 /* undraw selection */
2594 XCopyArea(scr->display, panel->selectionBackImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx-2, panel->paly-2);
2596 panel->palx = x;
2597 panel->paly = y;
2599 ofs = rint(x * panel->palXRatio) + rint(y * panel->palYRatio) * panel->customPaletteImg->width;
2601 panel->color.red = panel->customPaletteImg->data[0][ofs];
2602 panel->color.green = panel->customPaletteImg->data[1][ofs];
2603 panel->color.blue = panel->customPaletteImg->data[2][ofs];
2605 WMSetColorPanelColor(panel, panel->color);
2606 panel->lastChanged = WMCustomPaletteModeColorPanel;
2608 /* Redraw color selector (and make a backup of the part it will cover) */
2609 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 */
2610 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx-2, panel->paly-2); /* see above */
2614 static void
2615 customPalettePositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
2617 if (x < 2)
2618 x = 2;
2619 if (y < 2)
2620 y = 2;
2621 if (x >= customPaletteWidth)
2622 x = customPaletteWidth -2;
2623 if (y >= customPaletteHeight)
2624 y = customPaletteHeight -2;
2626 customPalettePositionSelection(panel, x, y);
2630 static void
2631 customPaletteHandleEvents(XEvent *event, void *data)
2633 W_ColorPanel *panel = (W_ColorPanel*)data;
2635 switch (event->type) {
2636 case Expose:
2637 if (event->xexpose.count != 0)
2638 break;
2639 customSetPalette(panel);
2640 break;
2644 static void
2645 customPaletteHandleActionEvents(XEvent *event, void *data)
2647 W_ColorPanel *panel = (W_ColorPanel*)data;
2648 int x, y;
2650 switch (event->type) {
2651 case ButtonPress:
2652 x = event->xbutton.x;
2653 y = event->xbutton.y;
2655 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2656 panel->flags.dragging = 1;
2657 customPalettePositionSelection(panel, x, y);
2659 break;
2661 case ButtonRelease:
2662 panel->flags.dragging = 0;
2663 break;
2665 case MotionNotify:
2666 x = event->xmotion.x;
2667 y = event->xmotion.y;
2669 if (panel->flags.dragging) {
2670 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2671 customPalettePositionSelection(panel, x, y);
2673 else
2674 customPalettePositionSelectionOutBounds(panel, x, y);
2676 break;
2681 static void
2682 customPaletteMenuCallback(WMWidget *w, void *data)
2684 W_ColorPanel *panel = (W_ColorPanel*)data;
2685 int item;
2687 item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2689 switch (item) {
2690 case menuNewFromFile:
2691 customPaletteMenuNewFromFile(panel);
2692 break;
2693 case menuRename:
2694 customPaletteMenuRename(panel);
2695 break;
2696 case menuRemove:
2697 customPaletteMenuRemove(panel);
2698 break;
2699 case menuCopy:
2700 break;
2701 case menuNewFromClipboard:
2702 break;
2707 static void
2708 customPaletteMenuNewFromFile(W_ColorPanel *panel)
2710 W_Screen *scr = WMWidgetScreen(panel->win);
2711 WMOpenPanel *browseP;
2712 char *filepath;
2713 char *filename = NULL;
2714 char *spath;
2715 char *tmp;
2716 int i;
2717 RImage *tmpImg = NULL;
2719 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir,"\0") == 0))
2720 spath = wexpandpath(wgethomedir());
2721 else
2722 spath = wexpandpath(panel->lastBrowseDir);
2724 browseP = WMGetOpenPanel(scr);
2725 WMSetFilePanelCanChooseDirectories(browseP, 0);
2726 WMSetFilePanelCanChooseFiles(browseP, 1);
2728 /* Get a filename */
2729 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
2730 "Open Palette",
2731 RSupportedFileFormats())) {
2732 filepath = WMGetFilePanelFileName(browseP);
2734 /* Get seperation position between path and filename */
2735 i = strrchr(filepath, '/') - filepath + 1;
2736 if (i > strlen(filepath))
2737 i = strlen(filepath);
2739 /* Store last browsed path */
2740 if (panel->lastBrowseDir)
2741 free(panel->lastBrowseDir);
2742 panel->lastBrowseDir = wmalloc((i+1)*sizeof(char));
2743 strncpy(panel->lastBrowseDir, filepath, i);
2744 panel->lastBrowseDir[i] = '\0';
2746 /* Get filename from path */
2747 filename = wstrdup(filepath + i);
2749 /* Check for duplicate files, and rename it if there are any */
2750 tmp = wstrappend(panel->configurationPath, filename);
2751 while (access(tmp, F_OK) == 0) {
2752 char *newName;
2754 free(tmp);
2756 newName = generateNewFilename(filename);
2757 free(filename);
2758 filename = newName;
2760 tmp = wstrappend(panel->configurationPath, filename);
2762 free(tmp);
2764 /* Copy the image to $(gnustepdir)/Library/Colors/ & Add the filename to the history menu */
2765 if (!fetchImageFile (panel->configurationPath, filepath, filename)) { /* error = -1 */
2767 /* filepath is a "local" path now the file has been copied */
2768 free(filepath);
2769 filepath = wstrappend(panel->configurationPath, filename);
2771 /* load the image & add menu entries */
2772 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
2773 if (tmpImg) {
2774 if (panel->customPaletteImg)
2775 RDestroyImage(panel->customPaletteImg);
2776 panel->customPaletteImg = tmpImg;
2778 customSetPalette(panel);
2779 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
2781 panel->currentPalette =
2782 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn)-1;
2784 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
2785 panel->currentPalette);
2787 } else {
2788 tmp = wstrappend(panel->configurationPath, filename);
2790 i = remove(tmp); /* Delete the file, it doesn't belong here */
2791 WMRunAlertPanel(scr, panel->win, "File Error", "Invalid file format !", "OK", NULL, NULL);
2792 if (i != 0) {
2793 wsyserror("can't remove file %s", tmp);
2794 WMRunAlertPanel(scr, panel->win, "File Error", "Couldn't remove file from Configuration Directory !", "OK", NULL, NULL);
2797 free(tmp);
2799 free(filepath);
2800 free(filename);
2802 WMFreeFilePanel(browseP);
2804 free(spath);
2808 static void
2809 customPaletteMenuRename(W_ColorPanel *panel)
2811 W_Screen *scr = WMWidgetScreen(panel->win);
2812 char *toName = NULL;
2813 char *fromName;
2814 char *toPath, *fromPath;
2815 int item;
2816 int index;
2818 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2819 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
2821 toName = WMRunInputPanel(scr, panel->win, "Rename", "Rename palette to:",
2822 fromName, "OK", "Cancel");
2824 if (toName) {
2826 /* As some people do certain stupid things... */
2827 if (strcmp(toName, fromName) == 0) {
2828 free(toName);
2829 return;
2832 /* For normal people */
2833 fromPath = wstrappend(panel->configurationPath, fromName);
2834 toPath = wstrappend(panel->configurationPath, toName);
2836 if (access (toPath, F_OK) == 0) { /* Careful, this palette exists already */
2837 if (WMRunAlertPanel(scr, panel->win, "Warning",
2838 "Palette already exists !\n\nOverwrite ?", "No", "Yes", NULL) == 1) {
2839 /* "No" = 0, "Yes" = 1 */
2840 int items = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
2842 remove(toPath);
2844 /* Remove from History list too */
2845 index = 1;
2846 while ((index < items) &&
2847 (strcmp(WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, index), toName) != 0 ))
2848 index++;
2850 if (index < items) {
2851 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, index);
2852 if (index < item)
2853 item--;
2856 } else {
2857 free(fromPath);
2858 free(toName);
2859 free(toPath);
2861 return;
2865 if ( rename(fromPath, toPath) != 0)
2866 wsyserror("Couldn't rename palette %s to %s\n", fromName, toName);
2867 else {
2868 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
2869 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item, toName);
2871 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
2873 free(fromPath);
2874 free(toPath);
2875 free(toName);
2880 static void
2881 customPaletteMenuRemove(W_ColorPanel *panel)
2883 W_Screen *scr = WMWidgetScreen(panel->win);
2884 char *text;
2885 char *tmp;
2886 int choice;
2887 int item;
2889 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2891 tmp = wstrappend( "This will permanently remove the palette ",
2892 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
2893 text = wstrappend( tmp, ".\n\nAre you sure you want to remove this palette ?");
2894 free(tmp);
2896 choice = WMRunAlertPanel(scr, panel->win, NULL, text, "Yes", "No", NULL);
2897 /* returns 0 (= "Yes") or 1 (="No") */
2898 free(text);
2900 if (choice == 0) {
2902 tmp = wstrappend(panel->configurationPath,
2903 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
2905 if ( remove(tmp) != 0)
2906 wsyserror("Couldn't remove palette %s\n", tmp);
2907 free(tmp);
2909 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item-1); /* item -1 always exists */
2910 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
2911 customSetPalette(panel);
2913 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
2918 static void
2919 customPaletteHistoryCallback(WMWidget *w, void *data)
2921 W_ColorPanel *panel = (W_ColorPanel*)data;
2922 W_Screen *scr = WMWidgetScreen(panel->win);
2923 int item;
2924 char *filename;
2925 RImage *tmp = NULL;
2927 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
2928 if (item == panel->currentPalette)
2929 return;
2931 if (item == 0)
2932 customRenderSpectrum(panel);
2933 else {
2934 /* Load file from configpath */
2935 filename = wstrappend( panel->configurationPath, WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item) );
2937 /* XXX To do: Check existence of file and remove it from the history if it doesn't exist */
2939 tmp = RLoadImage(scr->rcontext, filename, 0);
2940 if (tmp) {
2941 if (panel->customPaletteImg) {
2942 RDestroyImage(panel->customPaletteImg);
2943 panel->customPaletteImg = NULL;
2945 panel->customPaletteImg = tmp;
2947 free(filename);
2949 customSetPalette(panel);
2951 panel->currentPalette = item;
2955 /*************** Panel Initialisation Functions *****************/
2957 static void
2958 wheelInit(W_ColorPanel *panel)
2960 RHSVColor cur_hsv;
2961 float W_PI = 4 * atan(1);
2962 int i;
2963 int v;
2965 RRGBtoHSV(&panel->color, &cur_hsv);
2967 WMSetSliderValue(panel->wheelBrightnessS, 255-cur_hsv.value);
2968 wheelUpdateBrightnessGradientFromHSV(panel, cur_hsv);
2970 panel->colx = 2 + rint((colorWheelSize / 2.0) * (1 + (cur_hsv.saturation/255.0) * cos( cur_hsv.hue*W_PI/180.0)));
2971 panel->coly = 2 + rint((colorWheelSize / 2.0) * (1 + (cur_hsv.saturation/255.0) * sin(-cur_hsv.hue*W_PI/180.0)));
2973 for (i = 0; i < 256; i++) {
2974 /* We divide by 128 in advance, and check whether that number divides
2975 * by 2 properly. If not, we add one to round the number correctly
2977 v = (i*cur_hsv.value) >> 7;
2978 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 1));
2982 static void
2983 grayInit(W_ColorPanel *panel)
2985 RHSVColor cur_hsv;
2986 int value;
2987 char tmp[4];
2989 RRGBtoHSV(&panel->color, &cur_hsv);
2991 value = rint(cur_hsv.value/2.55);
2992 WMSetSliderValue(panel->grayBrightnessS, value);
2994 sprintf(tmp, "%d", value);
2995 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2998 static void
2999 rgbInit(W_ColorPanel *panel)
3001 char tmp[4];
3003 WMSetSliderValue(panel->rgbRedS,panel->color.red);
3004 WMSetSliderValue(panel->rgbGreenS,panel->color.green);
3005 WMSetSliderValue(panel->rgbBlueS,panel->color.blue);
3007 sprintf(tmp, "%d", panel->color.red);
3008 WMSetTextFieldText(panel->rgbRedT, tmp);
3009 sprintf(tmp, "%d", panel->color.green);
3010 WMSetTextFieldText(panel->rgbGreenT, tmp);
3011 sprintf(tmp, "%d", panel->color.blue);
3012 WMSetTextFieldText(panel->rgbBlueT, tmp);
3015 static void
3016 cmykInit(W_ColorPanel *panel)
3018 int value[3];
3019 char tmp[4];
3021 value[0] = rint((255-panel->color.red)/2.55);
3022 value[1] = rint((255-panel->color.green)/2.55);
3023 value[2] = rint((255-panel->color.blue)/2.55);
3025 WMSetSliderValue(panel->cmykCyanS, value[0]);
3026 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3027 WMSetSliderValue(panel->cmykYellowS, value[2]);
3028 WMSetSliderValue(panel->cmykBlackS, 0);
3030 sprintf(tmp, "%d", value[0]);
3031 WMSetTextFieldText(panel->cmykCyanT, tmp);
3032 sprintf(tmp, "%d", value[1]);
3033 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3034 sprintf(tmp, "%d", value[2]);
3035 WMSetTextFieldText(panel->cmykYellowT, tmp);
3036 WMSetTextFieldText(panel->cmykBlackT, "0");
3039 static void
3040 hsbInit(W_ColorPanel *panel)
3042 int value[3];
3043 char tmp[4];
3045 value[0] = panel->hsvcolor.hue;
3046 value[1] = rint(panel->hsvcolor.saturation/2.55);
3047 value[2] = rint(panel->hsvcolor.value/2.55);
3049 WMSetSliderValue(panel->hsbHueS,value[0]);
3050 WMSetSliderValue(panel->hsbSaturationS,value[1]);
3051 WMSetSliderValue(panel->hsbBrightnessS,value[2]);
3053 sprintf(tmp, "%d", value[0]);
3054 WMSetTextFieldText(panel->hsbHueT, tmp);
3055 sprintf(tmp, "%d", value[1]);
3056 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3057 sprintf(tmp, "%d", value[2]);
3058 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3060 hsbUpdateBrightnessGradient(panel);
3061 hsbUpdateSaturationGradient(panel);
3062 hsbUpdateHueGradient(panel);
3068 /************************* ColorList Panel Functions **********************/
3070 static void
3071 colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text, int state, WMRect *rect)
3073 int width, height, x, y;
3074 RColor color = *((RColor *)WMGetListItem(lPtr, index)->clientData);
3075 WMScreen *scr = WMWidgetScreen(lPtr);
3076 Display *dpy = WMScreenDisplay(scr);
3077 RImage *image;
3078 WMPixmap *pixmap;
3079 int i, j;
3080 W_ColorPanel *panel = WMGetHangedData(lPtr);
3081 WMColor *white = WMWhiteColor(scr);
3082 WMColor *black = WMBlackColor(scr);
3084 width = rect->size.width;
3085 height = rect->size.height;
3086 x = rect->pos.x;
3087 y = rect->pos.y;
3089 if (state & WLDSSelected)
3090 XFillRectangle(dpy, d, WMColorGC(white), x, y, width, height);
3091 else
3092 XClearArea(dpy, d, x, y, width, height, False);
3094 image = RCreateImage(15, 15, False);
3095 for (i=0; i < 15 ; i++) {
3096 for (j=0; j < 15; j++) {
3097 image->data[0][j*15+i] = color.red;
3098 image->data[1][j*15+i] = color.green;
3099 image->data[2][j*15+i] = color.blue;
3103 pixmap = WMCreatePixmapFromRImage(scr, image, 0);
3104 RDestroyImage(image);
3105 WMDrawPixmap(pixmap, d, x, y);
3106 WMReleasePixmap(pixmap);
3107 WMDrawString(scr, d, WMColorGC(black), panel->font12, x+18, y, text,
3108 strlen(text));
3110 WMReleaseColor(white);
3111 WMReleaseColor(black);
3115 static void
3116 colorListSelect(WMWidget *w, void *data)
3118 W_ColorPanel *panel = (W_ColorPanel *)data;
3119 RColor color = *((RColor *)WMGetListSelectedItem(w)->clientData);
3121 panel->lastChanged = WMColorListModeColorPanel;
3122 WMSetColorPanelColor(panel, color);
3128 /************************** Common utility functions ************************/
3130 static int
3131 fetchImageFile(char *toPath, char *imageSrcFile, char *imageDestFile)
3133 int src, dest;
3134 int n;
3135 char *tmp;
3136 char buf[BUFSIZE];
3138 if ((src = open(imageSrcFile, O_RDONLY)) < 0) {
3139 wsyserror("Could not open %s", imageSrcFile);
3140 return -1;
3143 tmp = wstrappend(toPath, imageDestFile);
3144 if ((dest = open( tmp, O_RDWR|O_CREAT, S_IRWXU|S_IRGRP|S_IROTH)) < 0) {
3145 wsyserror("Could not create %s", tmp);
3146 free(tmp);
3147 return -1;
3149 free(tmp);
3152 /* Copy the file */
3153 while ((n = read(src, buf, BUFSIZE)) > 0)
3155 if (write(dest, buf, n) != n) {
3156 wsyserror("Write error on file %s", imageDestFile);
3157 return -1;
3161 return 0;
3166 char*
3167 generateNewFilename(char *curName)
3169 #if 1
3170 int n;
3171 int baseLen;
3172 char *ptr;
3173 char *newName;
3175 ptr = strrchr(curName, '{');
3176 if (!ptr || sscanf(ptr, "{%i}", &n)!=1) {
3177 return wstrappend(curName, " {1}");
3180 baseLen = ptr - curName;
3182 newName = wmalloc(baseLen + 16);
3183 strncpy(newName, curName, baseLen);
3184 newName[baseLen] = 0;
3186 sprintf(&newName[baseLen], " {%i}", n+1);
3188 return newName;
3189 #else
3190 char *newName;
3191 char *numStart, *numEnd;
3192 char *pre, *num, *post;
3193 int n, numLength;
3194 char *tmp;
3196 newName = wstrdup(curName);
3198 if (newName == NULL)
3199 return wstrdup("Unnamed");
3202 * Modify the name to contain a number to make it unique
3205 /* Get number-string from filename. */
3206 numStart = strrchr(newName, '-');
3207 if (numStart) {
3208 if (strlen(numStart) > 1)
3209 numStart++; /* Next character, please */
3212 numEnd = strrchr(numStart, '-'); /* Already past "numbers" */
3214 if (numEnd) {
3215 /* Now it gets interesting */
3217 pre = wmalloc((numStart - newName +1) * sizeof(char)); /* a trailing '\0' is useful here */
3218 strncpy (pre, newName, numStart-newName);
3219 pre[numStart - newName] = '\0';
3221 num = wmalloc((numEnd - numStart +1) * sizeof(char));
3222 strncpy (num, numStart, numEnd-numStart);
3223 num[numEnd - numStart] = '\0';
3225 post = wstrdup( numEnd);
3227 free(newName); /* We don't need it anymore */
3229 if (strcspn(num, "0123456789") == 0) {
3230 n = (int)strtol(num, NULL, 10);
3232 /* Increase number between brackets (in filename); This is what it all is about */
3233 n++;
3235 free(num);
3236 num = wmalloc(3 * sizeof(char)); /* Nobody uses more than 999 duplicate filenames, do you ? */
3237 numLength = sprintf(num, "%d", n);
3239 free(num);
3240 num = wmalloc(numLength * sizeof(char));
3241 sprintf(num, "%d", n);
3243 tmp = wstrappend (num, post);
3244 newName = wstrappend (pre, tmp);
3246 free(pre);
3247 free(num);
3248 free(post);
3249 free(tmp);
3254 if (strcmp( curName, newName) == 0) {
3255 /* The name is still unchanged, so there was no number (between brackets) in it.
3256 Add a number 1 to the end.
3258 tmp = wstrdup(newName);
3259 if (newName)
3260 free(newName);
3261 newName = wstrappend(tmp, " -1-");
3262 free(tmp);
3265 return newName;
3266 #endif