WPrefs: Create Turkish translation
[wmaker-crm.git] / WINGs / wcolorpanel.c
blob561c07608d6c5e325b269e4986b3e5086cc59972
1 /*
2 * ColorPanel for WINGs
4 * by ]d : Original idea and basic initial code
5 * Pascal Hofstee : Code for wheeldrawing and calculating
6 * colors from it.
7 * Primary coder of this Color Panel.
8 * Alban Hertroys : Optimizations for algorithms for color-
9 * wheel. Also custom ColorPalettes and
10 * magnifying glass. Secondary coder ;)
11 * Alfredo K. Kojima : For pointing out memory-allocation
12 * problems and similair code-issues
13 * Marco van Hylckama-Vlieg : For once again doing the artwork ;-)
17 /* TODO:
18 * - Look at further optimization of colorWheel matrix calculation.
19 * It appears to be rather symmetric in angles of 60 degrees,
20 * while it is optimized in angles of 90 degrees.
21 * - Custom color-lists and custom colors in custom color-lists.
22 * - Stored colors
23 * - Resizing
26 #include "wconfig.h"
27 #include "WINGsP.h"
28 #include "rgb.h"
30 #include <errno.h>
31 #include <math.h>
32 #include <unistd.h>
33 #include <ctype.h>
34 #include <fcntl.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <dirent.h>
40 /* BUG There's something fishy with shaped windows */
41 /* Whithout shape extension the magnified image is completely broken -Dan */
43 #ifdef USE_XSHAPE
44 # include <X11/extensions/shape.h>
45 #endif
47 char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
50 * Bitmaps for magnifying glass cursor
53 /* Cursor */
54 #define Cursor_x_hot 11
55 #define Cursor_y_hot 11
56 #define Cursor_width 32
57 #define Cursor_height 32
58 static unsigned char Cursor_bits[] = {
59 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
60 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
61 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
62 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
63 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
64 0x00, 0x08, 0x00, 0x50, 0x00, 0x10, 0x00, 0x88, 0x00, 0x20, 0x00, 0x5c, 0x01, 0xc0, 0x81,
65 0x3b, 0x02, 0x00, 0x7e, 0x70, 0x05, 0x00, 0x00, 0xe0, 0x08, 0x00, 0x00, 0xc0, 0x15, 0x00,
66 0x00, 0x80, 0x23, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x5c,
67 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x70
70 static unsigned char Cursor_shape_bits[] = {
71 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
72 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
73 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
74 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
75 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
76 0x00, 0x08, 0x00, 0x70, 0x00, 0x10, 0x00, 0xf8, 0x00, 0x20, 0x00, 0xfc, 0x01, 0xc0, 0x81,
77 0xfb, 0x03, 0x00, 0x7e, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xc0, 0x1f, 0x00,
78 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfc,
79 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x70
82 /* Clip-mask for magnified pixels */
83 #define Cursor_mask_width 24
84 #define Cursor_mask_height 24
85 static unsigned char Cursor_mask_bits[] = {
86 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
87 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
88 0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
89 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
90 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
91 0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00
94 typedef struct MovingView {
95 WMView *view; /* The view this is all about */
96 XImage *image; /* What's under the view */
97 XImage *dirtyRect; /* Storage of overlapped image area */
98 Pixmap magPix; /* Magnified part of pixmap */
99 RColor color; /* Color of a pixel in the image */
100 int x, y; /* Position of view */
101 } MovingView;
103 typedef struct CPColor {
104 RColor rgb; /* The RGB values of the color */
105 RHSVColor hsv; /* The HSV values of the color */
106 enum { /* Which one was last set ? */
107 cpNone,
108 cpRGB,
109 cpHSV
110 } set;
111 } CPColor;
113 typedef struct WheelMatrix {
114 unsigned int width, height; /* Size of the colorwheel */
115 unsigned char *data[3]; /* Wheel data (R,G,B) */
116 unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
117 } wheelMatrix;
119 typedef struct W_ColorPanel {
120 WMWindow *win;
121 WMFont *font8;
122 WMFont *font12;
123 void *clientData;
124 WMAction2 *action;
126 /* Common Stuff */
127 WMColorWell *colorWell;
128 WMButton *magnifyBtn;
129 WMButton *wheelBtn;
130 WMButton *slidersBtn;
131 WMButton *customPaletteBtn;
132 WMButton *colorListBtn;
134 /* Magnifying Glass */
135 MovingView *magnifyGlass;
137 /* ColorWheel Panel */
138 WMFrame *wheelFrm;
139 WMSlider *wheelBrightnessS;
140 WMView *wheelView;
142 /* Slider Panels */
143 WMFrame *slidersFrm;
144 WMFrame *seperatorFrm;
145 WMButton *grayBtn;
146 WMButton *rgbBtn;
147 WMButton *cmykBtn;
148 WMButton *hsbBtn;
149 /* Gray Scale Panel */
150 WMFrame *grayFrm;
151 WMLabel *grayMinL;
152 WMLabel *grayMaxL;
153 WMSlider *grayBrightnessS;
154 WMTextField *grayBrightnessT;
155 WMButton *grayPresetBtn[7];
157 /* RGB Panel */
158 WMButton *rgbDecB;
159 WMButton *rgbHexB;
160 WMFrame *rgbFrm;
161 WMLabel *rgbMinL;
162 WMLabel *rgbMaxL;
163 WMSlider *rgbRedS;
164 WMSlider *rgbGreenS;
165 WMSlider *rgbBlueS;
166 WMTextField *rgbRedT;
167 WMTextField *rgbGreenT;
168 WMTextField *rgbBlueT;
169 enum {
170 RGBdec,
171 RGBhex
172 } rgbState;
174 /* CMYK Panel */
175 WMFrame *cmykFrm;
176 WMLabel *cmykMinL;
177 WMLabel *cmykMaxL;
178 WMSlider *cmykCyanS;
179 WMSlider *cmykMagentaS;
180 WMSlider *cmykYellowS;
181 WMSlider *cmykBlackS;
182 WMTextField *cmykCyanT;
183 WMTextField *cmykMagentaT;
184 WMTextField *cmykYellowT;
185 WMTextField *cmykBlackT;
187 /* HSB Panel */
188 WMFrame *hsbFrm;
189 WMSlider *hsbHueS;
190 WMSlider *hsbSaturationS;
191 WMSlider *hsbBrightnessS;
192 WMTextField *hsbHueT;
193 WMTextField *hsbSaturationT;
194 WMTextField *hsbBrightnessT;
196 /* Custom Palette Panel */
197 WMFrame *customPaletteFrm;
198 WMPopUpButton *customPaletteHistoryBtn;
199 WMFrame *customPaletteContentFrm;
200 WMPopUpButton *customPaletteMenuBtn;
201 WMView *customPaletteContentView;
203 /* Color List Panel */
204 WMFrame *colorListFrm;
205 WMPopUpButton *colorListHistoryBtn;
206 WMList *colorListContentLst;
207 WMPopUpButton *colorListColorMenuBtn;
208 WMPopUpButton *colorListListMenuBtn;
210 /* Look-Up Tables and Images */
211 wheelMatrix *wheelMtrx;
212 Pixmap wheelImg;
213 Pixmap selectionImg;
214 Pixmap selectionBackImg;
215 RImage *customPaletteImg;
216 char *lastBrowseDir;
218 /* Common Data Fields */
219 CPColor color; /* Current color */
220 WMColorPanelMode mode; /* Current color selection mode */
221 WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
222 WMColorPanelMode lastChanged; /* Panel that last changed the color */
223 int colx, coly; /* (x,y) of sel.-marker in WheelMode */
224 int palx, paly; /* (x,y) of sel.-marker in
225 CustomPaletteMode */
226 double palXRatio, palYRatio; /* Ratios in x & y between
227 original and scaled
228 palettesize */
229 int currentPalette;
230 char *configurationPath;
232 struct {
233 unsigned int continuous:1;
234 unsigned int dragging:1;
235 } flags;
236 } W_ColorPanel;
238 enum {
239 CPmenuNewFromFile,
240 CPmenuRename,
241 CPmenuRemove,
242 CPmenuCopy,
243 CPmenuNewFromClipboard
244 } customPaletteMenuItem;
246 enum {
247 CLmenuAdd,
248 CLmenuRename,
249 CLmenuRemove
250 } colorListMenuItem;
252 #define PWIDTH 194
253 #define PHEIGHT 266
254 #define colorWheelSize 150
255 #define customPaletteWidth 182
256 #define customPaletteHeight 106
257 #define knobThickness 8
259 #define SPECTRUM_WIDTH 511
260 #define SPECTRUM_HEIGHT 360
262 #define COLORWHEEL_PART 1
263 #define CUSTOMPALETTE_PART 2
266 static char *generateNewFilename(const char *curName);
267 static void convertCPColor(CPColor * color);
268 static RColor ulongToRColor(WMScreen * scr, unsigned long value);
269 static unsigned char getShift(unsigned char value);
271 static void modeButtonCallback(WMWidget * w, void *data);
272 static int getPickerPart(W_ColorPanel * panel, int x, int y);
273 static void readConfiguration(W_ColorPanel * panel);
274 static void readXColors(W_ColorPanel * panel);
276 static void closeWindowCallback(WMWidget * w, void *data);
278 static Cursor magnifyGrabPointer(W_ColorPanel * panel);
279 static WMPoint magnifyInitialize(W_ColorPanel * panel);
280 static void magnifyPutCursor(WMWidget * w, void *data);
281 static Pixmap magnifyCreatePixmap(WMColorPanel * panel);
282 static void magnifyGetImageStored(W_ColorPanel * panel, int x1, int y1, int x2, int y2);
283 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h);
285 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height);
286 static void wheelDestroyMatrix(wheelMatrix * matrix);
287 static void wheelInitMatrix(W_ColorPanel * panel);
288 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue);
289 static void wheelRender(W_ColorPanel * panel);
290 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs);
291 static void wheelPaint(W_ColorPanel * panel);
293 static void wheelHandleEvents(XEvent * event, void *data);
294 static void wheelHandleActionEvents(XEvent * event, void *data);
295 static void wheelBrightnessSliderCallback(WMWidget * w, void *data);
296 static void wheelUpdateSelection(W_ColorPanel * panel);
297 static void wheelUndrawSelection(W_ColorPanel * panel);
299 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y);
300 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
301 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel);
302 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor);
304 static void grayBrightnessSliderCallback(WMWidget * w, void *data);
305 static void grayPresetButtonCallback(WMWidget * w, void *data);
306 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification);
308 static void rgbSliderCallback(WMWidget * w, void *data);
309 static void rgbTextFieldCallback(void *observerData, WMNotification * notification);
310 static void rgbDecToHex(WMWidget *w, void *data);
312 static void cmykSliderCallback(WMWidget * w, void *data);
313 static void cmykTextFieldCallback(void *observerData, WMNotification * notification);
315 static void hsbSliderCallback(WMWidget * w, void *data);
316 static void hsbTextFieldCallback(void *observerData, WMNotification * notification);
317 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel);
318 static void hsbUpdateSaturationGradient(W_ColorPanel * panel);
319 static void hsbUpdateHueGradient(W_ColorPanel * panel);
321 static void customRenderSpectrum(W_ColorPanel * panel);
322 static void customSetPalette(W_ColorPanel * panel);
323 static void customPaletteHandleEvents(XEvent * event, void *data);
324 static void customPaletteHandleActionEvents(XEvent * event, void *data);
325 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y);
326 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y);
327 static void customPaletteMenuCallback(WMWidget * w, void *data);
328 static void customPaletteHistoryCallback(WMWidget * w, void *data);
330 static void customPaletteMenuNewFromFile(W_ColorPanel * panel);
331 static void customPaletteMenuRename(W_ColorPanel * panel);
332 static void customPaletteMenuRemove(W_ColorPanel * panel);
334 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect);
335 static void colorListSelect(WMWidget * w, void *data);
336 static void colorListColorMenuCallback(WMWidget * w, void *data);
337 static void colorListListMenuCallback(WMWidget * w, void *data);
339 static void wheelInit(W_ColorPanel * panel);
340 static void grayInit(W_ColorPanel * panel);
341 static void rgbInit(W_ColorPanel * panel);
342 static void cmykInit(W_ColorPanel * panel);
343 static void hsbInit(W_ColorPanel * panel);
346 static inline int get_textfield_as_integer(WMTextField *widget)
348 char *str;
349 int value;
351 str = WMGetTextFieldText(widget);
352 value = atoi(str);
353 wfree(str);
354 return value;
357 void WMSetColorPanelAction(WMColorPanel * panel, WMAction2 * action, void *data)
359 panel->action = action;
360 panel->clientData = data;
363 static WMColorPanel *makeColorPanel(WMScreen * scrPtr, const char *name)
365 WMColorPanel *panel;
366 RImage *image;
367 WMPixmap *pixmap;
368 RColor from;
369 RColor to;
370 WMColor *textcolor, *graybuttoncolor;
371 int i;
372 GC bgc = WMColorGC(scrPtr->black);
373 GC wgc = WMColorGC(scrPtr->white);
375 panel = wmalloc(sizeof(WMColorPanel));
376 panel->color.rgb.red = 0;
377 panel->color.rgb.green = 0;
378 panel->color.rgb.blue = 0;
379 panel->color.hsv.hue = 0;
380 panel->color.hsv.saturation = 0;
381 panel->color.hsv.value = 0;
382 panel->color.set = cpNone; /* Color has not been set yet */
384 panel->font8 = WMSystemFontOfSize(scrPtr, 8);
385 panel->font12 = WMSystemFontOfSize(scrPtr, 12);
387 panel->win = WMCreateWindowWithStyle(scrPtr, name,
388 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
389 WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
390 WMSetWindowTitle(panel->win, _("Colors"));
391 WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
393 /* Set Default ColorPanel Mode(s) */
394 panel->mode = WMWheelModeColorPanel;
395 panel->lastChanged = 0;
396 panel->slidersmode = WMRGBModeColorPanel;
397 panel->configurationPath = wstrconcat(wusergnusteppath(), "/Library/Colors/");
399 /* Some General Purpose Widgets */
400 panel->colorWell = WMCreateColorWell(panel->win);
401 WMResizeWidget(panel->colorWell, 134, 36);
402 WSetColorWellBordered(panel->colorWell, False);
403 WMMoveWidget(panel->colorWell, 56, 4);
405 panel->magnifyBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
406 WMResizeWidget(panel->magnifyBtn, 46, 36);
407 WMMoveWidget(panel->magnifyBtn, 6, 4);
408 WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
409 WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
410 WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
412 panel->wheelBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
413 WMResizeWidget(panel->wheelBtn, 46, 32);
414 WMMoveWidget(panel->wheelBtn, 6, 44);
415 WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
416 WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
417 WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
419 panel->slidersBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
420 WMResizeWidget(panel->slidersBtn, 46, 32);
421 WMMoveWidget(panel->slidersBtn, 52, 44);
422 WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
423 WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
424 WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
426 panel->customPaletteBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
427 WMResizeWidget(panel->customPaletteBtn, 46, 32);
428 WMMoveWidget(panel->customPaletteBtn, 98, 44);
429 WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
430 WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
431 WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
433 panel->colorListBtn = WMCreateCustomButton(panel->win, WBBStateLightMask | WBBStateChangeMask);
434 WMResizeWidget(panel->colorListBtn, 46, 32);
435 WMMoveWidget(panel->colorListBtn, 144, 44);
436 WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
437 WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
438 WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
440 /* Let's Group some of them together */
441 WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
442 WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
443 WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
445 /* Widgets for the ColorWheel Panel */
446 panel->wheelFrm = WMCreateFrame(panel->win);
447 WMSetFrameRelief(panel->wheelFrm, WRFlat);
448 WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
449 WMMoveWidget(panel->wheelFrm, 5, 80);
451 panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
452 /* XXX Can we create a view ? */
453 W_ResizeView(panel->wheelView, colorWheelSize + 4, colorWheelSize + 4);
454 W_MoveView(panel->wheelView, 0, 0);
456 /* Create an event handler to handle expose/click events in ColorWheel */
457 WMCreateEventHandler(panel->wheelView,
458 ButtonPressMask | ButtonReleaseMask | EnterWindowMask |
459 LeaveWindowMask | ButtonMotionMask, wheelHandleActionEvents, panel);
461 WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents, panel);
463 panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
464 WMResizeWidget(panel->wheelBrightnessS, 16, 153);
465 WMMoveWidget(panel->wheelBrightnessS, 5 + colorWheelSize + 14, 1);
466 WMSetSliderMinValue(panel->wheelBrightnessS, 0);
467 WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
468 WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback, panel);
469 WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
471 panel->wheelMtrx = wheelCreateMatrix(colorWheelSize + 4, colorWheelSize + 4);
472 wheelInitMatrix(panel);
474 /* Widgets for the Slider Panels */
475 panel->slidersFrm = WMCreateFrame(panel->win);
476 WMSetFrameRelief(panel->slidersFrm, WRFlat);
477 WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
478 WMMoveWidget(panel->slidersFrm, 4, 80);
480 panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
481 WMSetFrameRelief(panel->seperatorFrm, WRPushed);
482 WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
483 WMMoveWidget(panel->seperatorFrm, 0, 1);
485 panel->grayBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
486 WMResizeWidget(panel->grayBtn, 46, 24);
487 WMMoveWidget(panel->grayBtn, 1, 8);
488 WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
489 WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
490 WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
492 panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
493 WMResizeWidget(panel->rgbBtn, 46, 24);
494 WMMoveWidget(panel->rgbBtn, 47, 8);
495 WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
496 WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
497 WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
499 panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
500 WMResizeWidget(panel->cmykBtn, 46, 24);
501 WMMoveWidget(panel->cmykBtn, 93, 8);
502 WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
503 WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
504 WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
506 panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm, WBBStateLightMask | WBBStateChangeMask);
507 WMResizeWidget(panel->hsbBtn, 46, 24);
508 WMMoveWidget(panel->hsbBtn, 139, 8);
509 WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
510 WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
511 WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
513 /* Let's Group the Slider Panel Buttons Together */
514 WMGroupButtons(panel->grayBtn, panel->rgbBtn);
515 WMGroupButtons(panel->grayBtn, panel->cmykBtn);
516 WMGroupButtons(panel->grayBtn, panel->hsbBtn);
518 textcolor = WMDarkGrayColor(scrPtr);
520 /* Widgets for GrayScale Panel */
521 panel->grayFrm = WMCreateFrame(panel->slidersFrm);
522 WMSetFrameRelief(panel->grayFrm, WRFlat);
523 WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
524 WMMoveWidget(panel->grayFrm, 0, 34);
526 panel->grayMinL = WMCreateLabel(panel->grayFrm);
527 WMResizeWidget(panel->grayMinL, 20, 10);
528 WMMoveWidget(panel->grayMinL, 2, 2);
529 WMSetLabelText(panel->grayMinL, "0");
530 WMSetLabelTextAlignment(panel->grayMinL, WALeft);
531 WMSetLabelTextColor(panel->grayMinL, textcolor);
532 WMSetLabelFont(panel->grayMinL, panel->font8);
534 panel->grayMaxL = WMCreateLabel(panel->grayFrm);
535 WMResizeWidget(panel->grayMaxL, 40, 10);
536 WMMoveWidget(panel->grayMaxL, 104, 2);
537 WMSetLabelText(panel->grayMaxL, "100");
538 WMSetLabelTextAlignment(panel->grayMaxL, WARight);
539 WMSetLabelTextColor(panel->grayMaxL, textcolor);
540 WMSetLabelFont(panel->grayMaxL, panel->font8);
542 panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
543 WMResizeWidget(panel->grayBrightnessS, 141, 16);
544 WMMoveWidget(panel->grayBrightnessS, 2, 14);
545 WMSetSliderMinValue(panel->grayBrightnessS, 0);
546 WMSetSliderMaxValue(panel->grayBrightnessS, 100);
547 WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
548 WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback, panel);
550 from.red = 0;
551 from.green = 0;
552 from.blue = 0;
554 to.red = 255;
555 to.green = 255;
556 to.blue = 255;
558 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
559 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
560 RReleaseImage(image);
562 if (pixmap)
563 W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
564 panel->font12, 2, 0, 100, WALeft, scrPtr->white,
565 False, _("Brightness"), strlen(_("Brightness")));
566 else
567 wwarning(_("Color Panel: Could not allocate memory"));
569 WMSetSliderImage(panel->grayBrightnessS, pixmap);
570 WMReleasePixmap(pixmap);
572 panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
573 WMResizeWidget(panel->grayBrightnessT, 40, 18);
574 WMMoveWidget(panel->grayBrightnessT, 146, 13);
575 WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
576 WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
577 WMTextDidEndEditingNotification, panel->grayBrightnessT);
579 for (i = 0; i < 7; i++) {
580 pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
582 graybuttoncolor = WMCreateRGBColor(scrPtr, (255 / 6) * i << 8,
583 (255 / 6) * i << 8, (255 / 6) * i << 8, True);
584 WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
585 WMReleaseColor(graybuttoncolor);
587 panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
588 WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
589 WMMoveWidget(panel->grayPresetBtn[i], 2 + (i * 20), 34);
590 WMSetButtonAction(panel->grayPresetBtn[i], grayPresetButtonCallback, panel);
591 WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
592 WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
593 WMReleasePixmap(pixmap);
597 /* End of GrayScale Panel */
599 /* Widgets for RGB Panel */
600 panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
601 WMSetFrameRelief(panel->rgbFrm, WRFlat);
602 WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
603 WMMoveWidget(panel->rgbFrm, 0, 34);
605 panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
606 WMResizeWidget(panel->rgbMinL, 20, 10);
607 WMMoveWidget(panel->rgbMinL, 2, 2);
608 WMSetLabelText(panel->rgbMinL, "0");
609 WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
610 WMSetLabelTextColor(panel->rgbMinL, textcolor);
611 WMSetLabelFont(panel->rgbMinL, panel->font8);
613 panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
614 WMResizeWidget(panel->rgbMaxL, 40, 10);
615 WMMoveWidget(panel->rgbMaxL, 104, 2);
616 WMSetLabelText(panel->rgbMaxL, "255");
617 WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
618 WMSetLabelTextColor(panel->rgbMaxL, textcolor);
619 WMSetLabelFont(panel->rgbMaxL, panel->font8);
621 panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
622 WMResizeWidget(panel->rgbRedS, 141, 16);
623 WMMoveWidget(panel->rgbRedS, 2, 14);
624 WMSetSliderMinValue(panel->rgbRedS, 0);
625 WMSetSliderMaxValue(panel->rgbRedS, 255);
626 WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
627 WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
629 to.red = 255;
630 to.green = 0;
631 to.blue = 0;
633 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
634 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
635 RReleaseImage(image);
637 if (pixmap)
638 W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
639 2, 0, 100, WALeft, scrPtr->white, False, _("Red"), strlen(_("Red")));
640 else
641 wwarning(_("Color Panel: Could not allocate memory"));
643 WMSetSliderImage(panel->rgbRedS, pixmap);
644 WMReleasePixmap(pixmap);
646 panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
647 WMResizeWidget(panel->rgbRedT, 40, 18);
648 WMMoveWidget(panel->rgbRedT, 146, 13);
649 WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
650 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbRedT);
652 panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
653 WMResizeWidget(panel->rgbGreenS, 141, 16);
654 WMMoveWidget(panel->rgbGreenS, 2, 36);
655 WMSetSliderMinValue(panel->rgbGreenS, 0);
656 WMSetSliderMaxValue(panel->rgbGreenS, 255);
657 WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
658 WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
660 to.red = 0;
661 to.green = 255;
662 to.blue = 0;
664 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
665 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
666 RReleaseImage(image);
668 if (pixmap)
669 W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
670 2, 0, 100, WALeft, scrPtr->white, False, _("Green"), strlen(_("Green")));
671 else
672 wwarning(_("Color Panel: Could not allocate memory"));
674 WMSetSliderImage(panel->rgbGreenS, pixmap);
675 WMReleasePixmap(pixmap);
677 panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
678 WMResizeWidget(panel->rgbGreenT, 40, 18);
679 WMMoveWidget(panel->rgbGreenT, 146, 35);
680 WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
681 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbGreenT);
683 panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
684 WMResizeWidget(panel->rgbBlueS, 141, 16);
685 WMMoveWidget(panel->rgbBlueS, 2, 58);
686 WMSetSliderMinValue(panel->rgbBlueS, 0);
687 WMSetSliderMaxValue(panel->rgbBlueS, 255);
688 WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
689 WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
691 to.red = 0;
692 to.green = 0;
693 to.blue = 255;
695 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
696 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
697 RReleaseImage(image);
699 if (pixmap)
700 W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
701 2, 0, 100, WALeft, scrPtr->white, False, _("Blue"), strlen(_("Blue")));
702 else
703 wwarning(_("Color Panel: Could not allocate memory"));
705 WMSetSliderImage(panel->rgbBlueS, pixmap);
706 WMReleasePixmap(pixmap);
708 panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
709 WMResizeWidget(panel->rgbBlueT, 40, 18);
710 WMMoveWidget(panel->rgbBlueT, 146, 57);
711 WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
712 WMAddNotificationObserver(rgbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->rgbBlueT);
714 panel->rgbDecB = WMCreateButton(panel->rgbFrm, WBTRadio);
715 WMSetButtonText(panel->rgbDecB, _("Decimal"));
716 WMSetButtonSelected(panel->rgbDecB, 1);
717 panel->rgbState = RGBdec;
718 WMSetButtonAction(panel->rgbDecB, rgbDecToHex, panel);
719 WMResizeWidget(panel->rgbDecB, PWIDTH - 8, 23);
720 WMMoveWidget(panel->rgbDecB, 2, 81);
722 panel->rgbHexB = WMCreateButton(panel->rgbFrm, WBTRadio);
723 WMSetButtonText(panel->rgbHexB, _("Hexadecimal"));
724 WMSetButtonAction(panel->rgbHexB, rgbDecToHex, panel);
725 WMResizeWidget(panel->rgbHexB, PWIDTH - 8, 23);
726 WMMoveWidget(panel->rgbHexB, 2, 104);
728 WMGroupButtons(panel->rgbDecB, panel->rgbHexB);
730 /* End of RGB Panel */
732 /* Widgets for CMYK Panel */
733 panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
734 WMSetFrameRelief(panel->cmykFrm, WRFlat);
735 WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
736 WMMoveWidget(panel->cmykFrm, 0, 34);
738 panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
739 WMResizeWidget(panel->cmykMinL, 20, 10);
740 WMMoveWidget(panel->cmykMinL, 2, 2);
741 WMSetLabelText(panel->cmykMinL, "0");
742 WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
743 WMSetLabelTextColor(panel->cmykMinL, textcolor);
744 WMSetLabelFont(panel->cmykMinL, panel->font8);
746 panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
747 WMResizeWidget(panel->cmykMaxL, 40, 10);
748 WMMoveWidget(panel->cmykMaxL, 104, 2);
749 WMSetLabelText(panel->cmykMaxL, "100");
750 WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
751 WMSetLabelTextColor(panel->cmykMaxL, textcolor);
752 WMSetLabelFont(panel->cmykMaxL, panel->font8);
754 panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
755 WMResizeWidget(panel->cmykCyanS, 141, 16);
756 WMMoveWidget(panel->cmykCyanS, 2, 14);
757 WMSetSliderMinValue(panel->cmykCyanS, 0);
758 WMSetSliderMaxValue(panel->cmykCyanS, 100);
759 WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
760 WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
762 from.red = 255;
763 from.green = 255;
764 from.blue = 255;
766 to.red = 0;
767 to.green = 255;
768 to.blue = 255;
770 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
771 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
772 RReleaseImage(image);
774 if (pixmap)
775 W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
776 2, 0, 100, WALeft, scrPtr->black, False, _("Cyan"), strlen(_("Cyan")));
777 else
778 wwarning(_("Color Panel: Could not allocate memory"));
780 WMSetSliderImage(panel->cmykCyanS, pixmap);
781 WMReleasePixmap(pixmap);
783 panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
784 WMResizeWidget(panel->cmykCyanT, 40, 18);
785 WMMoveWidget(panel->cmykCyanT, 146, 13);
786 WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
787 WMAddNotificationObserver(cmykTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->cmykCyanT);
789 panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
790 WMResizeWidget(panel->cmykMagentaS, 141, 16);
791 WMMoveWidget(panel->cmykMagentaS, 2, 36);
792 WMSetSliderMinValue(panel->cmykMagentaS, 0);
793 WMSetSliderMaxValue(panel->cmykMagentaS, 100);
794 WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
795 WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
797 to.red = 255;
798 to.green = 0;
799 to.blue = 255;
801 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
802 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
803 RReleaseImage(image);
805 if (pixmap)
806 W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
807 2, 0, 100, WALeft, scrPtr->black, False, _("Magenta"), strlen(_("Magenta")));
808 else
809 wwarning(_("Color Panel: Could not allocate memory"));
811 WMSetSliderImage(panel->cmykMagentaS, pixmap);
812 WMReleasePixmap(pixmap);
814 panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
815 WMResizeWidget(panel->cmykMagentaT, 40, 18);
816 WMMoveWidget(panel->cmykMagentaT, 146, 35);
817 WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
818 WMAddNotificationObserver(cmykTextFieldCallback, panel,
819 WMTextDidEndEditingNotification, panel->cmykMagentaT);
821 panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
822 WMResizeWidget(panel->cmykYellowS, 141, 16);
823 WMMoveWidget(panel->cmykYellowS, 2, 58);
824 WMSetSliderMinValue(panel->cmykYellowS, 0);
825 WMSetSliderMaxValue(panel->cmykYellowS, 100);
826 WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
827 WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
829 to.red = 255;
830 to.green = 255;
831 to.blue = 0;
833 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
834 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
835 RReleaseImage(image);
837 if (pixmap)
838 W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
839 2, 0, 100, WALeft, scrPtr->black, False, _("Yellow"), strlen(_("Yellow")));
840 else
841 wwarning(_("Color Panel: Could not allocate memory"));
843 WMSetSliderImage(panel->cmykYellowS, pixmap);
844 WMReleasePixmap(pixmap);
846 panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
847 WMResizeWidget(panel->cmykYellowT, 40, 18);
848 WMMoveWidget(panel->cmykYellowT, 146, 57);
849 WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
850 WMAddNotificationObserver(cmykTextFieldCallback, panel,
851 WMTextDidEndEditingNotification, panel->cmykYellowT);
853 panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
854 WMResizeWidget(panel->cmykBlackS, 141, 16);
855 WMMoveWidget(panel->cmykBlackS, 2, 80);
856 WMSetSliderMinValue(panel->cmykBlackS, 0);
857 WMSetSliderMaxValue(panel->cmykBlackS, 100);
858 WMSetSliderValue(panel->cmykBlackS, 0);
859 WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
860 WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
862 to.red = 0;
863 to.green = 0;
864 to.blue = 0;
866 image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
867 pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
868 RReleaseImage(image);
870 if (pixmap)
871 W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
872 2, 0, 100, WALeft, scrPtr->black, False, _("Black"), strlen(_("Black")));
873 else
874 wwarning(_("Color Panel: Could not allocate memory"));
876 WMSetSliderImage(panel->cmykBlackS, pixmap);
877 WMReleasePixmap(pixmap);
879 panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
880 WMResizeWidget(panel->cmykBlackT, 40, 18);
881 WMMoveWidget(panel->cmykBlackT, 146, 79);
882 WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
883 WMAddNotificationObserver(cmykTextFieldCallback, panel,
884 WMTextDidEndEditingNotification, panel->cmykBlackT);
885 /* End of CMYK Panel */
887 /* Widgets for HSB Panel */
888 panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
889 WMSetFrameRelief(panel->hsbFrm, WRFlat);
890 WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
891 WMMoveWidget(panel->hsbFrm, 0, 34);
893 panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
894 WMResizeWidget(panel->hsbHueS, 141, 16);
895 WMMoveWidget(panel->hsbHueS, 2, 14);
896 WMSetSliderMinValue(panel->hsbHueS, 0);
897 WMSetSliderMaxValue(panel->hsbHueS, 359);
898 WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
899 WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
901 panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
902 WMResizeWidget(panel->hsbHueT, 40, 18);
903 WMMoveWidget(panel->hsbHueT, 146, 13);
904 WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
905 WMAddNotificationObserver(hsbTextFieldCallback, panel, WMTextDidEndEditingNotification, panel->hsbHueT);
907 panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
908 WMResizeWidget(panel->hsbSaturationS, 141, 16);
909 WMMoveWidget(panel->hsbSaturationS, 2, 36);
910 WMSetSliderMinValue(panel->hsbSaturationS, 0);
911 WMSetSliderMaxValue(panel->hsbSaturationS, 100);
912 WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
913 WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
915 panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
916 WMResizeWidget(panel->hsbSaturationT, 40, 18);
917 WMMoveWidget(panel->hsbSaturationT, 146, 35);
918 WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
919 WMAddNotificationObserver(hsbTextFieldCallback, panel,
920 WMTextDidEndEditingNotification, panel->hsbSaturationT);
922 panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
923 WMResizeWidget(panel->hsbBrightnessS, 141, 16);
924 WMMoveWidget(panel->hsbBrightnessS, 2, 58);
925 WMSetSliderMinValue(panel->hsbBrightnessS, 0);
926 WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
927 WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
928 WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
930 panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
931 WMResizeWidget(panel->hsbBrightnessT, 40, 18);
932 WMMoveWidget(panel->hsbBrightnessT, 146, 57);
933 WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
934 WMAddNotificationObserver(hsbTextFieldCallback, panel,
935 WMTextDidEndEditingNotification, panel->hsbBrightnessT);
936 /* End of HSB Panel */
938 WMReleaseColor(textcolor);
940 /* Widgets for the CustomPalette Panel */
941 panel->customPaletteFrm = WMCreateFrame(panel->win);
942 WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
943 WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
944 WMMoveWidget(panel->customPaletteFrm, 5, 80);
946 panel->customPaletteHistoryBtn = WMCreatePopUpButton(panel->customPaletteFrm);
947 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, _("Spectrum"));
948 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
949 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1);
950 WMSetPopUpButtonAction(panel->customPaletteHistoryBtn, customPaletteHistoryCallback, panel);
951 WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
952 WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
954 panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
955 WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
956 WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
957 WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
959 panel->customPaletteContentView = W_CreateView(W_VIEW(panel->customPaletteContentFrm));
960 /* XXX Test if we can create a view */
961 W_ResizeView(panel->customPaletteContentView, customPaletteWidth, customPaletteHeight);
962 W_MoveView(panel->customPaletteContentView, 2, 2);
964 /* Create event handler to handle expose/click events in CustomPalette */
965 WMCreateEventHandler(panel->customPaletteContentView,
966 ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
967 ButtonMotionMask, customPaletteHandleActionEvents, panel);
969 WMCreateEventHandler(panel->customPaletteContentView, ExposureMask, customPaletteHandleEvents, panel);
971 panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
972 WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
973 WMSetPopUpButtonText(panel->customPaletteMenuBtn, _("Palette"));
974 WMSetPopUpButtonAction(panel->customPaletteMenuBtn, customPaletteMenuCallback, panel);
975 WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
976 WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
978 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from File..."));
979 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Rename..."));
980 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Remove"));
981 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("Copy"));
982 WMAddPopUpButtonItem(panel->customPaletteMenuBtn, _("New from Clipboard"));
984 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
985 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
986 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
987 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuNewFromClipboard, 0);
989 customRenderSpectrum(panel);
990 panel->currentPalette = 0;
991 panel->palx = customPaletteWidth / 2;
992 panel->paly = customPaletteHeight / 2;
994 /* Widgets for the ColorList Panel */
995 panel->colorListFrm = WMCreateFrame(panel->win);
996 WMSetFrameRelief(panel->colorListFrm, WRFlat);
997 WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
998 WMMoveWidget(panel->colorListFrm, 5, 80);
1000 panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
1001 WMAddPopUpButtonItem(panel->colorListHistoryBtn, _("X11-Colors"));
1002 WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
1003 WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn) - 1);
1004 /* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
1005 * colorListHistoryCallback, panel); */
1006 WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
1007 WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
1009 panel->colorListContentLst = WMCreateList(panel->colorListFrm);
1010 WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
1011 WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
1012 WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
1013 WMMoveWidget(panel->colorListContentLst, 0, 23);
1014 WMHangData(panel->colorListContentLst, panel);
1016 panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1017 WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
1018 WMSetPopUpButtonText(panel->colorListColorMenuBtn, _("Color"));
1019 WMSetPopUpButtonAction(panel->colorListColorMenuBtn, colorListColorMenuCallback, panel);
1020 WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16) / 2, 20);
1021 WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
1023 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Add..."));
1024 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Rename..."));
1025 WMAddPopUpButtonItem(panel->colorListColorMenuBtn, _("Remove"));
1027 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
1028 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
1029 WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
1031 panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
1032 WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
1033 WMSetPopUpButtonText(panel->colorListListMenuBtn, _("List"));
1034 WMSetPopUpButtonAction(panel->colorListListMenuBtn, colorListListMenuCallback, panel);
1035 WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2, 20);
1036 WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16) / 2 + 8, PHEIGHT - 130);
1038 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("New..."));
1039 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Rename..."));
1040 WMAddPopUpButtonItem(panel->colorListListMenuBtn, _("Remove"));
1042 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
1043 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
1044 WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
1046 WMRealizeWidget(panel->win);
1047 WMMapSubwidgets(panel->win);
1049 WMMapSubwidgets(panel->wheelFrm);
1050 WMMapSubwidgets(panel->slidersFrm);
1051 WMMapSubwidgets(panel->grayFrm);
1052 WMMapSubwidgets(panel->rgbFrm);
1053 WMMapSubwidgets(panel->cmykFrm);
1054 WMMapSubwidgets(panel->hsbFrm);
1055 WMMapSubwidgets(panel->customPaletteFrm);
1056 WMMapSubwidgets(panel->customPaletteContentFrm);
1057 WMMapSubwidgets(panel->colorListFrm);
1059 /* Pixmap to indicate selection positions
1060 * wheelframe MUST be mapped.
1062 panel->selectionImg = XCreatePixmap(scrPtr->display, WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
1063 XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
1064 XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
1066 readConfiguration(panel);
1067 readXColors(panel);
1069 return panel;
1072 WMColorPanel *WMGetColorPanel(WMScreen * scrPtr)
1074 WMColorPanel *panel;
1076 if (scrPtr->sharedColorPanel)
1077 return scrPtr->sharedColorPanel;
1079 panel = makeColorPanel(scrPtr, "colorPanel");
1081 scrPtr->sharedColorPanel = panel;
1083 return panel;
1086 void WMFreeColorPanel(WMColorPanel * panel)
1088 W_Screen *scr;
1090 if (!panel)
1091 return;
1093 scr = WMWidgetScreen(panel->win);
1094 if (panel == scr->sharedColorPanel) {
1095 scr->sharedColorPanel = NULL;
1098 WMRemoveNotificationObserver(panel);
1099 WMUnmapWidget(panel->win);
1101 /* fonts */
1102 WMReleaseFont(panel->font8);
1103 WMReleaseFont(panel->font12);
1105 /* pixmaps */
1106 wheelDestroyMatrix(panel->wheelMtrx);
1107 if (panel->wheelImg)
1108 XFreePixmap(scr->display, panel->wheelImg);
1109 if (panel->selectionImg)
1110 XFreePixmap(scr->display, panel->selectionImg);
1111 if (panel->selectionBackImg)
1112 XFreePixmap(scr->display, panel->selectionBackImg);
1113 RReleaseImage(panel->customPaletteImg);
1115 /* structs */
1116 if (panel->lastBrowseDir)
1117 wfree(panel->lastBrowseDir);
1118 if (panel->configurationPath)
1119 wfree(panel->configurationPath);
1121 WMDestroyWidget(panel->win);
1123 wfree(panel);
1126 void WMCloseColorPanel(WMColorPanel * panel)
1128 WMFreeColorPanel(panel);
1131 void WMShowColorPanel(WMColorPanel * panel)
1133 WMScreen *scr = WMWidgetScreen(panel->win);
1134 WMColor *white = WMWhiteColor(scr);
1136 if (panel->color.set == cpNone)
1137 WMSetColorPanelColor(panel, white);
1138 WMReleaseColor(white);
1140 if (panel->mode != WMWheelModeColorPanel)
1141 WMPerformButtonClick(panel->wheelBtn);
1143 WMMapWidget(panel->win);
1146 static void closeWindowCallback(WMWidget * w, void *data)
1148 W_ColorPanel *panel = (W_ColorPanel *) data;
1150 /* Parameter not used, but tell the compiler that it is ok */
1151 (void) w;
1153 WMCloseColorPanel(panel);
1156 static void readConfiguration(W_ColorPanel * panel)
1158 /* XXX Doesn't take care of "invalid" files */
1160 DIR *dPtr;
1161 struct dirent *dp;
1162 struct stat stat_buf;
1163 int item;
1165 if (stat(panel->configurationPath, &stat_buf) != 0) {
1166 if (mkdir(panel->configurationPath, S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH) != 0) {
1167 werror(_("Color Panel: Could not create directory %s needed"
1168 " to store configurations"), panel->configurationPath);
1169 WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
1170 WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
1171 WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
1172 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
1173 _("File Error"),
1174 _("Could not create ColorPanel configuration directory"),
1175 _("OK"), NULL, NULL);
1177 return;
1180 if (!(dPtr = opendir(panel->configurationPath))) {
1181 wwarning("%s: %s", _("Color Panel: Could not find file"), panel->configurationPath);
1182 return;
1185 while ((dp = readdir(dPtr)) != NULL) {
1186 unsigned int perm_mask;
1187 char *path = wstrconcat(panel->configurationPath,
1188 dp->d_name);
1190 if (dp->d_name[0] != '.') {
1191 item = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
1192 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
1194 perm_mask = (access(path, R_OK) == 0);
1195 WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn, item, perm_mask);
1197 wfree(path);
1199 closedir(dPtr);
1202 static void readXColors(W_ColorPanel * panel)
1204 WMListItem *item;
1205 const RGBColor *entry;
1207 for (entry = rgbColors; entry->name != NULL; entry++) {
1208 item = WMAddListItem(panel->colorListContentLst, entry->name);
1209 item->clientData = (void *)&(entry->color);
1213 void WMSetColorPanelPickerMode(WMColorPanel * panel, WMColorPanelMode mode)
1215 W_Screen *scr = WMWidgetScreen(panel->win);
1217 if (mode != WMWheelModeColorPanel) {
1218 WMUnmapWidget(panel->wheelFrm);
1219 if (panel->selectionBackImg) {
1220 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1221 panel->selectionBackImg = None;
1224 if (mode != WMGrayModeColorPanel)
1225 WMUnmapWidget(panel->grayFrm);
1226 if (mode != WMRGBModeColorPanel)
1227 WMUnmapWidget(panel->rgbFrm);
1228 if (mode != WMCMYKModeColorPanel)
1229 WMUnmapWidget(panel->cmykFrm);
1230 if (mode != WMHSBModeColorPanel)
1231 WMUnmapWidget(panel->hsbFrm);
1232 if (mode != WMCustomPaletteModeColorPanel) {
1233 WMUnmapWidget(panel->customPaletteFrm);
1234 if (panel->selectionBackImg) {
1235 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1236 panel->selectionBackImg = None;
1239 if (mode != WMColorListModeColorPanel)
1240 WMUnmapWidget(panel->colorListFrm);
1241 if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
1242 (mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
1243 WMUnmapWidget(panel->slidersFrm);
1244 else
1245 panel->slidersmode = mode;
1247 if (mode == WMWheelModeColorPanel) {
1248 WMMapWidget(panel->wheelFrm);
1249 WMSetButtonSelected(panel->wheelBtn, True);
1250 if (panel->lastChanged != WMWheelModeColorPanel)
1251 wheelInit(panel);
1252 wheelRender(panel);
1253 wheelPaint(panel);
1254 } else if (mode == WMGrayModeColorPanel) {
1255 WMMapWidget(panel->slidersFrm);
1256 WMSetButtonSelected(panel->slidersBtn, True);
1257 WMMapWidget(panel->grayFrm);
1258 WMSetButtonSelected(panel->grayBtn, True);
1259 WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
1260 if (panel->lastChanged != WMGrayModeColorPanel)
1261 grayInit(panel);
1262 } else if (mode == WMRGBModeColorPanel) {
1263 WMMapWidget(panel->slidersFrm);
1264 WMSetButtonSelected(panel->slidersBtn, True);
1265 WMMapWidget(panel->rgbFrm);
1266 WMSetButtonSelected(panel->rgbBtn, True);
1267 WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
1268 if (panel->lastChanged != WMRGBModeColorPanel)
1269 rgbInit(panel);
1270 } else if (mode == WMCMYKModeColorPanel) {
1271 WMMapWidget(panel->slidersFrm);
1272 WMSetButtonSelected(panel->slidersBtn, True);
1273 WMMapWidget(panel->cmykFrm);
1274 WMSetButtonSelected(panel->cmykBtn, True);
1275 WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
1276 if (panel->lastChanged != WMCMYKModeColorPanel)
1277 cmykInit(panel);
1278 } else if (mode == WMHSBModeColorPanel) {
1279 WMMapWidget(panel->slidersFrm);
1280 WMSetButtonSelected(panel->slidersBtn, True);
1281 WMMapWidget(panel->hsbFrm);
1282 WMSetButtonSelected(panel->hsbBtn, True);
1283 WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
1284 if (panel->lastChanged != WMHSBModeColorPanel)
1285 hsbInit(panel);
1286 } else if (mode == WMCustomPaletteModeColorPanel) {
1287 WMMapWidget(panel->customPaletteFrm);
1288 WMSetButtonSelected(panel->customPaletteBtn, True);
1289 customSetPalette(panel);
1290 } else if (mode == WMColorListModeColorPanel) {
1291 WMMapWidget(panel->colorListFrm);
1292 WMSetButtonSelected(panel->colorListBtn, True);
1295 panel->mode = mode;
1298 WMColor *WMGetColorPanelColor(WMColorPanel * panel)
1300 return WMGetColorWellColor(panel->colorWell);
1303 void WMSetColorPanelColor(WMColorPanel * panel, WMColor * color)
1305 WMSetColorWellColor(panel->colorWell, color);
1307 panel->color.rgb.red = color->color.red >> 8;
1308 panel->color.rgb.green = color->color.green >> 8;
1309 panel->color.rgb.blue = color->color.blue >> 8;
1310 panel->color.set = cpRGB;
1312 if (panel->mode == panel->lastChanged)
1313 panel->lastChanged = 0;
1315 WMSetColorPanelPickerMode(panel, panel->mode);
1318 static void updateSwatch(WMColorPanel * panel, CPColor color)
1320 WMScreen *scr = WMWidgetScreen(panel->win);
1321 WMColor *wellcolor;
1323 if (color.set != cpRGB)
1324 convertCPColor(&color);
1326 panel->color = color;
1328 wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8, color.rgb.green << 8, color.rgb.blue << 8, True);
1330 WMSetColorWellColor(panel->colorWell, wellcolor);
1331 WMReleaseColor(wellcolor);
1333 if (!panel->flags.dragging || panel->flags.continuous) {
1334 if (panel->action)
1335 (*panel->action) (panel, panel->clientData);
1337 WMPostNotificationName(WMColorPanelColorChangedNotification, panel, NULL);
1341 static void modeButtonCallback(WMWidget * w, void *data)
1343 W_ColorPanel *panel = (W_ColorPanel *) (data);
1345 if (w == panel->wheelBtn)
1346 WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
1347 else if (w == panel->slidersBtn)
1348 WMSetColorPanelPickerMode(panel, panel->slidersmode);
1349 else if (w == panel->customPaletteBtn)
1350 WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
1351 else if (w == panel->colorListBtn)
1352 WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
1353 else if (w == panel->grayBtn)
1354 WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
1355 else if (w == panel->rgbBtn)
1356 WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
1357 else if (w == panel->cmykBtn)
1358 WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
1359 else if (w == panel->hsbBtn)
1360 WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
1363 /****************** Magnifying Cursor Functions *******************/
1365 static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h)
1367 int x0 = 0, y0 = 0, w0 = w, h0 = h;
1368 const int displayWidth = DisplayWidth(scr->display, scr->screen),
1369 displayHeight = DisplayHeight(scr->display, scr->screen);
1371 if (!(image && image->data)) {
1372 /* The image in panel->magnifyGlass->image does not exist yet.
1373 * Grab one from the screen (not beyond) and use it from now on.
1375 if (!(image = XGetImage(scr->display, scr->rootWin,
1376 x - Cursor_x_hot, y - Cursor_y_hot, w, h, AllPlanes, ZPixmap)))
1377 wwarning(_("Color Panel: X failed request"));
1379 return image;
1382 /* Coordinate correction for back pixmap
1383 * if magnifying glass is at screen-borders
1386 /* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
1387 * Hatched area is beyond screen border.
1389 * |<-Cursor_x_hot->|
1390 * ________________|_____
1391 * |/ / / / / / /| | |
1392 * | / / / / / / |(x,y) |
1393 * |/_/_/_/_/_/_/|________|
1394 * |<----x0----->|<--w0-->|
1398 /* Figure 2: Shifting of rectangle-to-grab at bottom/right
1399 * screen borders
1400 * Hatched area is beyond screen border
1402 * |<-Cursor_x_hot->|
1403 * ________________|_______________
1404 * | | | / / / / / /|
1405 * | (x,y)|/ / / / / / |
1406 * |___________________|_/_/_/_/_/_/|
1407 * |<-------w0-------->| |
1408 * |<---------------w--|----------->|
1409 * | |
1410 * x0 Displaywidth-1
1413 if (x < Cursor_x_hot) { /* see fig. 1 */
1414 x0 = Cursor_x_hot - x;
1415 w0 = w - x0;
1418 if (displayWidth - 1 < x - Cursor_x_hot + w) { /* see fig. 2 */
1419 w0 = (displayWidth) - (x - Cursor_x_hot);
1422 if (y < Cursor_y_hot) { /* see fig. 1 */
1423 y0 = Cursor_y_hot - y;
1424 h0 = h - y0;
1427 if (displayHeight - 1 < y - Cursor_y_hot + h) { /* see fig. 2 */
1428 h0 = (displayHeight) - (y - Cursor_y_hot);
1430 /* end of coordinate correction */
1432 /* Grab an image from the screen, clipped if necessary,
1433 * and put it in the existing panel->magnifyGlass->image
1434 * with the corresponding clipping offset.
1436 if (!XGetSubImage(scr->display, scr->rootWin,
1437 x - Cursor_x_hot + x0, y - Cursor_y_hot + y0, w0, h0, AllPlanes, ZPixmap, image, x0, y0))
1438 wwarning(_("Color Panel: X failed request"));
1440 return NULL;
1443 static void magnifyGetImageStored(WMColorPanel * panel, int x1, int y1, int x2, int y2)
1445 /* (x1, y1) = topleft corner of existing rectangle
1446 * (x2, y2) = topleft corner of new position
1449 W_Screen *scr = WMWidgetScreen(panel->win);
1450 int xa = 0, ya = 0, xb = 0, yb = 0;
1451 int width, height;
1452 const int dx = abs(x2 - x1), dy = abs(y2 - y1);
1453 XImage *image;
1454 const int x_min = Cursor_x_hot,
1455 y_min = Cursor_y_hot,
1456 x_max = DisplayWidth(scr->display, scr->screen) - 1 -
1457 (Cursor_mask_width - Cursor_x_hot),
1458 y_max = DisplayHeight(scr->display, scr->screen) - 1 - (Cursor_mask_height - Cursor_y_hot);
1460 if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
1461 return; /* No movement */
1463 if (x1 < x2)
1464 xa = dx;
1465 else
1466 xb = dx;
1468 if (y1 < y2)
1469 ya = dy;
1470 else
1471 yb = dy;
1473 width = Cursor_mask_width - dx;
1474 height = Cursor_mask_height - dy;
1476 /* If the traversed distance is larger than the size of the magnifying
1477 * glass contents, there is no need to do dirty rectangles. A whole new
1478 * rectangle can be grabbed (unless that rectangle falls partially
1479 * off screen).
1480 * Destroying the image and setting it to NULL will achieve that later on.
1482 * Of course, grabbing an XImage beyond the borders of the screen will
1483 * cause trouble, this is considdered a special case. Part of the screen
1484 * is grabbed, but there is no need for dirty rectangles.
1486 if ((width <= 0) || (height <= 0)) {
1487 if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
1488 if (panel->magnifyGlass->image)
1489 XDestroyImage(panel->magnifyGlass->image);
1490 panel->magnifyGlass->image = NULL;
1492 } else {
1493 if (panel->magnifyGlass->image) {
1494 /* Get dirty rectangle from panel->magnifyGlass->image */
1495 panel->magnifyGlass->dirtyRect =
1496 XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
1497 if (!panel->magnifyGlass->dirtyRect) {
1498 wwarning(_("Color Panel: X failed request"));
1499 return; /* X returned a NULL from XSubImage */
1504 /* Get image from screen */
1505 image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2, Cursor_mask_width, Cursor_mask_height);
1506 if (image) { /* Only reassign if a *new* image was grabbed */
1507 panel->magnifyGlass->image = image;
1508 return;
1511 /* Copy previously stored rectangle on covered part of image */
1512 if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
1513 int old_height;
1515 /* "width" and "height" are used as coordinates here,
1516 * and run from [0...width-1] and [0...height-1] respectively.
1518 width--;
1519 height--;
1520 old_height = height;
1522 for (; width >= 0; width--)
1523 for (height = old_height; height >= 0; height--)
1524 XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
1525 XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
1526 XDestroyImage(panel->magnifyGlass->dirtyRect);
1527 panel->magnifyGlass->dirtyRect = NULL;
1530 return;
1533 static Pixmap magnifyCreatePixmap(WMColorPanel * panel)
1535 W_Screen *scr = WMWidgetScreen(panel->win);
1536 int u, v;
1537 #ifndef USE_XSHAPE
1538 Pixmap pixmap;
1539 #endif
1540 unsigned long color;
1542 if (!panel->magnifyGlass->image)
1543 return None;
1545 if (!panel->magnifyGlass->magPix)
1546 return None;
1549 * Copy an area of only 5x5 pixels from the center of the image.
1551 for (u = 0; u < 5; u++) {
1552 for (v = 0; v < 5; v++) {
1553 color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
1555 XSetForeground(scr->display, scr->copyGC, color);
1557 if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
1558 panel->magnifyGlass->color = ulongToRColor(scr, color);
1560 /* The center square must eventually be centered around the
1561 * hotspot. The image needs shifting to achieve this. The amount of
1562 * shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
1563 * _ _ _ _ _
1564 * |_|_|_|_|_|
1565 * ^------- center of center square == Cursor_x_hot
1567 XFillRectangle(scr->display, panel->magnifyGlass->magPix,
1568 scr->copyGC,
1569 u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
1570 (u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
1574 #ifdef USE_XSHAPE
1575 return panel->magnifyGlass->magPix;
1576 #else
1577 pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width, Cursor_mask_height, scr->depth);
1578 if (!pixmap)
1579 return None;
1581 XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
1582 0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
1584 /* Copy the magnified pixmap, with the clip mask, to background pixmap */
1585 XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
1586 scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
1587 /* (2,2) puts center pixel on center of glass */
1589 return pixmap;
1590 #endif
1594 static WMView *magnifyCreateView(W_ColorPanel * panel)
1596 W_Screen *scr = WMWidgetScreen(panel->win);
1597 WMView *magView;
1599 magView = W_CreateTopView(scr);
1600 if (!magView)
1601 return NULL;
1603 magView->self = panel->win;
1604 magView->flags.topLevel = 1;
1605 magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
1606 magView->attribs.override_redirect = True;
1607 magView->attribs.save_under = True;
1609 W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
1611 W_RealizeView(magView);
1613 return magView;
1616 static Cursor magnifyGrabPointer(W_ColorPanel * panel)
1618 W_Screen *scr = WMWidgetScreen(panel->win);
1619 Pixmap magPixmap, magPixmap2;
1620 Cursor magCursor;
1621 XColor fgColor = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 };
1622 XColor bgColor = { 0, 0xbf00, 0xa000, 0x5000, DoRed | DoGreen | DoBlue, 0 };
1624 /* Cursor creation stuff */
1625 magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1626 (char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
1627 magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1628 (char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
1630 magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
1631 &fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
1633 XFreePixmap(scr->display, magPixmap);
1634 XFreePixmap(scr->display, magPixmap2);
1636 XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
1638 /* Set up Pointer */
1639 XGrabPointer(scr->display, panel->magnifyGlass->view->window, True,
1640 PointerMotionMask | ButtonPressMask,
1641 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1643 return magCursor;
1646 static WMPoint magnifyInitialize(W_ColorPanel * panel)
1648 W_Screen *scr = WMWidgetScreen(panel->win);
1649 int x, y, u, v;
1650 unsigned int mask;
1651 Pixmap pixmap, clip_mask;
1652 WMPoint point;
1653 Window root_return, child_return;
1655 clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
1656 (char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1657 1, 0, 1);
1658 panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
1659 5 * 5 - 1, 5 * 5 - 1, scr->depth);
1661 XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return, &x, &y, &u, &v, &mask);
1663 panel->magnifyGlass->image = NULL;
1665 /* Clipmask to make magnified view-contents circular */
1666 #ifdef USE_XSHAPE
1667 XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
1668 ShapeBounding, 0, 0, clip_mask, ShapeSet);
1669 #else
1670 /* Clip circle in glass cursor */
1671 XSetClipMask(scr->display, scr->clipGC, clip_mask);
1672 XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
1673 #endif
1675 XFreePixmap(scr->display, clip_mask);
1677 /* Draw initial magnifying glass contents */
1678 magnifyGetImageStored(panel, x, y, x, y);
1680 pixmap = magnifyCreatePixmap(panel);
1681 XSetWindowBackgroundPixmap(scr->display, WMViewXID(panel->magnifyGlass->view), pixmap);
1682 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1683 XFlush(scr->display);
1685 #ifndef USE_XSHAPE
1686 XFreePixmap(scr->display, pixmap);
1687 #endif
1689 point.x = x;
1690 point.y = y;
1692 return point;
1695 static void magnifyPutCursor(WMWidget * w, void *data)
1697 W_ColorPanel *panel = (W_ColorPanel *) (data);
1698 W_Screen *scr = WMWidgetScreen(panel->win);
1699 Cursor magCursor;
1700 Pixmap pixmap;
1701 XEvent event;
1702 WMPoint initialPosition;
1704 /* Parameter not used, but tell the compiler that it is ok */
1705 (void) w;
1707 /* Destroy wheelBackImg, so it'll update properly */
1708 if (panel->selectionBackImg) {
1709 XFreePixmap(WMWidgetScreen(panel->win)->display, panel->selectionBackImg);
1710 panel->selectionBackImg = None;
1713 /* Create magnifying glass */
1714 panel->magnifyGlass = wmalloc(sizeof(MovingView));
1715 panel->magnifyGlass->view = magnifyCreateView(panel);
1716 if (!panel->magnifyGlass->view)
1717 return;
1719 initialPosition = magnifyInitialize(panel);
1720 panel->magnifyGlass->x = initialPosition.x;
1721 panel->magnifyGlass->y = initialPosition.y;
1723 W_MoveView(panel->magnifyGlass->view,
1724 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1725 W_MapView(panel->magnifyGlass->view);
1727 magCursor = magnifyGrabPointer(panel);
1729 while (panel->magnifyGlass->image) {
1730 WMNextEvent(scr->display, &event);
1732 /* Pack motion events */
1733 while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
1736 switch (event.type) {
1737 case ButtonPress:
1738 XDestroyImage(panel->magnifyGlass->image);
1739 panel->magnifyGlass->image = NULL;
1741 if (event.xbutton.button == Button1) {
1742 panel->color.rgb = panel->magnifyGlass->color;
1743 panel->color.set = cpRGB;
1744 updateSwatch(panel, panel->color);
1746 switch (panel->mode) {
1747 case WMWheelModeColorPanel:
1748 wheelInit(panel);
1749 wheelRender(panel);
1750 wheelPaint(panel);
1751 break;
1752 case WMGrayModeColorPanel:
1753 grayInit(panel);
1754 break;
1755 case WMRGBModeColorPanel:
1756 rgbInit(panel);
1757 break;
1758 case WMCMYKModeColorPanel:
1759 cmykInit(panel);
1760 break;
1761 case WMHSBModeColorPanel:
1762 hsbInit(panel);
1763 break;
1764 default:
1765 break;
1767 panel->lastChanged = panel->mode;
1769 WMSetButtonSelected(panel->magnifyBtn, False);
1770 break;
1772 case MotionNotify:
1773 while (XPending(event.xmotion.display)) {
1774 XEvent ev;
1775 XPeekEvent(event.xmotion.display, &ev);
1776 if (ev.type == MotionNotify)
1777 XNextEvent(event.xmotion.display, &event);
1778 else
1779 break;
1782 /* Get a "dirty rectangle" */
1783 magnifyGetImageStored(panel,
1784 panel->magnifyGlass->x, panel->magnifyGlass->y,
1785 event.xmotion.x_root, event.xmotion.y_root);
1787 /* Update coordinates */
1788 panel->magnifyGlass->x = event.xmotion.x_root;
1789 panel->magnifyGlass->y = event.xmotion.y_root;
1791 /* Move view */
1792 W_MoveView(panel->magnifyGlass->view,
1793 panel->magnifyGlass->x - Cursor_x_hot, panel->magnifyGlass->y - Cursor_y_hot);
1795 /* Put new image (with magn.) in view */
1796 pixmap = magnifyCreatePixmap(panel);
1797 if (pixmap != None) {
1798 /* Change the window background */
1799 XSetWindowBackgroundPixmap(scr->display,
1800 WMViewXID(panel->magnifyGlass->view), pixmap);
1801 /* Force an Expose (handled by X) */
1802 XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
1803 /* Synchronize the event queue, so the Expose is handled NOW */
1804 XFlush(scr->display);
1805 #ifndef USE_XSHAPE
1806 XFreePixmap(scr->display, pixmap);
1807 #endif
1809 break;
1811 /* Try XQueryPointer for this !!! It returns windows that the pointer
1812 * is over. Note: We found this solving the invisible donkey cap bug
1814 #if 0 /* As it is impossible to make this work in all cases,
1815 * we consider it confusing. Therefore we disabled it.
1817 case FocusOut: /* fall through */
1818 case FocusIn:
1820 * Color Panel window (panel->win) lost or received focus.
1821 * We need to update the pixmap in the magnifying glass.
1823 * BUG Doesn't work with focus switches between two windows
1824 * if none of them is the color panel.
1826 XUngrabPointer(scr->display, CurrentTime);
1827 W_UnmapView(panel->magnifyGlass->view);
1829 magnifyInitialize(panel);
1831 W_MapView(panel->magnifyGlass->view);
1832 XGrabPointer(scr->display, panel->magnifyGlass->view->window,
1833 True, PointerMotionMask | ButtonPressMask,
1834 GrabModeAsync, GrabModeAsync, scr->rootWin, magCursor, CurrentTime);
1835 break;
1836 #endif
1837 default:
1838 WMHandleEvent(&event);
1839 break;
1840 } /* of switch */
1843 XUngrabPointer(scr->display, CurrentTime);
1844 XFreeCursor(scr->display, magCursor);
1846 XFreePixmap(scr->display, panel->magnifyGlass->magPix);
1847 panel->magnifyGlass->magPix = None;
1849 W_UnmapView(panel->magnifyGlass->view);
1850 W_DestroyView(panel->magnifyGlass->view);
1851 panel->magnifyGlass->view = NULL;
1853 wfree(panel->magnifyGlass);
1856 /****************** ColorWheel Functions ************************/
1858 static wheelMatrix *wheelCreateMatrix(unsigned int width, unsigned int height)
1860 wheelMatrix *matrix = NULL;
1861 int i;
1863 assert((width > 0) && (height > 0));
1865 matrix = wmalloc(sizeof(wheelMatrix));
1866 matrix->width = width;
1867 matrix->height = height;
1869 for (i = 0; i < 3; i++) {
1870 matrix->data[i] = wmalloc(width * height * sizeof(unsigned char));
1873 return matrix;
1876 static void wheelDestroyMatrix(wheelMatrix * matrix)
1878 int i;
1880 if (!matrix)
1881 return;
1883 for (i = 0; i < 3; i++) {
1884 if (matrix->data[i])
1885 wfree(matrix->data[i]);
1887 wfree(matrix);
1890 static void wheelInitMatrix(W_ColorPanel * panel)
1892 int i;
1893 int x, y;
1894 unsigned char *rp, *gp, *bp;
1895 CPColor cpColor;
1896 long ofs[4];
1897 int xcor, ycor;
1898 unsigned short sat;
1899 int dhue[4];
1900 const int cw_halfsize = (colorWheelSize + 4) / 2,
1901 cw_sqsize = (colorWheelSize + 4) * (colorWheelSize + 4), uchar_shift = getShift(sizeof(unsigned char));
1903 if (!panel->wheelMtrx)
1904 return;
1906 cpColor.hsv.value = 255;
1907 cpColor.set = cpHSV;
1909 ofs[0] = -1;
1910 ofs[1] = -(colorWheelSize + 4);
1912 /* offsets are counterclockwise (in triangles).
1914 * ofs[0] ---->
1915 * _______________________________________
1916 * [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
1917 * s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
1918 * f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
1919 * o | | | | | | | | | | | | | | | | | | | | | [3]
1921 * <---- ofs[2]
1922 * ____
1923 * |\ /| <-- triangles
1924 * | \/ |
1925 * | /\ |
1926 * |/__\|
1929 for (y = 0; y < cw_halfsize; y++) {
1930 for (x = y; x < (colorWheelSize + 4 - y); x++) {
1931 /* (xcor, ycor) is (x,y) relative to center of matrix */
1932 xcor = 2 * x - 4 - colorWheelSize;
1933 ycor = 2 * y - 4 - colorWheelSize;
1935 /* RColor.saturation is unsigned char and will wrap after 255 */
1936 sat = rint(255.0 * sqrt(xcor * xcor + ycor * ycor) / colorWheelSize);
1938 cpColor.hsv.saturation = (unsigned char)sat;
1940 ofs[0]++; /* top quarter of matrix */
1941 ofs[1] += colorWheelSize + 4; /* left quarter */
1942 ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
1943 ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
1945 if (sat < 256) {
1946 if (xcor != 0)
1947 dhue[0] = rint(atan((double)ycor / (double)xcor) *
1948 (180.0 / WM_PI)) + (xcor < 0 ? 180.0 : 0.0);
1949 else
1950 dhue[0] = 270;
1952 dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
1953 dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
1954 dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
1955 dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
1957 for (i = 0; i < 4; i++) {
1958 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1959 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1960 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1962 cpColor.hsv.hue = dhue[i];
1963 convertCPColor(&cpColor);
1965 *rp = (unsigned char)(cpColor.rgb.red);
1966 *gp = (unsigned char)(cpColor.rgb.green);
1967 *bp = (unsigned char)(cpColor.rgb.blue);
1969 } else {
1970 for (i = 0; i < 4; i++) {
1971 rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
1972 gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
1973 bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
1975 *rp = (unsigned char)0;
1976 *gp = (unsigned char)0;
1977 *bp = (unsigned char)0;
1982 ofs[0] += 2 * y + 1;
1983 ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2 * y);
1987 static void wheelCalculateValues(W_ColorPanel * panel, int maxvalue)
1989 unsigned int i;
1990 unsigned int v;
1992 for (i = 0; i < 256; i++) {
1993 /* We divide by 128 in advance, and check whether that number divides
1994 * by 2 properly. If not, we add one to round the number correctly
1996 v = (i * maxvalue) >> 7;
1997 panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) + (v & 0x01));
2001 static void wheelRender(W_ColorPanel * panel)
2003 W_Screen *scr = WMWidgetScreen(panel->win);
2004 int x, y;
2005 RImage *image;
2006 unsigned char *ptr;
2007 RColor gray;
2008 unsigned long ofs = 0;
2009 /*unsigned char shift = getShift(sizeof(unsigned char)); */
2011 image = RCreateImage(colorWheelSize + 4, colorWheelSize + 4, True);
2012 if (!image) {
2013 wwarning(_("Color Panel: Could not allocate memory"));
2014 return;
2017 ptr = image->data;
2019 /* TODO Make this transparent istead of gray */
2020 gray.red = gray.blue = 0xae;
2021 gray.green = 0xaa;
2023 for (y = 0; y < colorWheelSize + 4; y++) {
2024 for (x = 0; x < colorWheelSize + 4; x++) {
2025 if (wheelInsideColorWheel(panel, ofs)) {
2026 *(ptr++) =
2027 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]]);
2028 *(ptr++) =
2029 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]]);
2030 *(ptr++) =
2031 (unsigned char)(panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]]);
2032 *(ptr++) = 0;
2033 } else {
2034 *(ptr++) = (unsigned char)(gray.red);
2035 *(ptr++) = (unsigned char)(gray.green);
2036 *(ptr++) = (unsigned char)(gray.blue);
2037 *(ptr++) = 255;
2039 ofs++;
2043 if (panel->wheelImg)
2044 XFreePixmap(scr->display, panel->wheelImg);
2046 RConvertImage(scr->rcontext, image, &panel->wheelImg);
2047 RReleaseImage(image);
2049 /* Check if backimage exists. If it doesn't, allocate and fill it */
2050 if (!panel->selectionBackImg) {
2051 panel->selectionBackImg = XCreatePixmap(scr->display,
2052 W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
2053 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2054 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2055 /* -2 is hot spot correction */
2059 static Bool wheelInsideColorWheel(W_ColorPanel * panel, unsigned long ofs)
2061 return ((panel->wheelMtrx->data[0][ofs] != 0) &&
2062 (panel->wheelMtrx->data[1][ofs] != 0) && (panel->wheelMtrx->data[2][ofs] != 0));
2065 static void wheelPaint(W_ColorPanel * panel)
2067 W_Screen *scr = WMWidgetScreen(panel->win);
2069 XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
2070 scr->copyGC, 0, 0, colorWheelSize + 4, colorWheelSize + 4, 0, 0);
2072 /* Draw selection image */
2073 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2074 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2077 static void wheelHandleEvents(XEvent * event, void *data)
2079 W_ColorPanel *panel = (W_ColorPanel *) data;
2081 switch (event->type) {
2082 case Expose:
2083 if (event->xexpose.count != 0) /* TODO Improve */
2084 break;
2085 wheelPaint(panel);
2086 break;
2090 static void wheelHandleActionEvents(XEvent * event, void *data)
2092 W_ColorPanel *panel = (W_ColorPanel *) data;
2094 switch (event->type) {
2095 case ButtonPress:
2096 if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) == COLORWHEEL_PART) {
2098 panel->lastChanged = WMWheelModeColorPanel;
2099 panel->flags.dragging = 1;
2101 wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
2103 break;
2105 case ButtonRelease:
2106 panel->flags.dragging = 0;
2107 if (!panel->flags.continuous) {
2108 if (panel->action)
2109 (*panel->action) (panel, panel->clientData);
2111 break;
2113 case MotionNotify:
2114 if (panel->flags.dragging) {
2115 if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) == COLORWHEEL_PART) {
2116 wheelPositionSelection(panel, event->xmotion.x, event->xmotion.y);
2117 } else
2118 wheelPositionSelectionOutBounds(panel, event->xmotion.x, event->xmotion.y);
2120 break;
2124 static int getPickerPart(W_ColorPanel * panel, int x, int y)
2126 int lx, ly;
2127 unsigned long ofs;
2129 lx = x;
2130 ly = y;
2132 if (panel->mode == WMWheelModeColorPanel) {
2133 if ((lx >= 2) && (lx <= 2 + colorWheelSize) && (ly >= 2) && (ly <= 2 + colorWheelSize)) {
2135 ofs = ly * panel->wheelMtrx->width + lx;
2137 if (wheelInsideColorWheel(panel, ofs))
2138 return COLORWHEEL_PART;
2142 if (panel->mode == WMCustomPaletteModeColorPanel) {
2143 if ((lx >= 2) && (lx < customPaletteWidth - 2) && (ly >= 2) && (ly < customPaletteHeight - 2)) {
2144 return CUSTOMPALETTE_PART;
2148 return 0;
2151 static void wheelBrightnessSliderCallback(WMWidget * w, void *data)
2153 int value;
2155 W_ColorPanel *panel = (W_ColorPanel *) data;
2157 /* Parameter not used, but tell the compiler that it is ok */
2158 (void) w;
2160 value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2162 wheelCalculateValues(panel, value);
2164 if (panel->color.set == cpRGB) {
2165 convertCPColor(&panel->color);
2166 panel->color.set = cpHSV;
2169 panel->color.hsv.value = value;
2171 wheelRender(panel);
2172 wheelPaint(panel);
2173 wheelUpdateSelection(panel);
2176 static void wheelUpdateSelection(W_ColorPanel * panel)
2178 W_Screen *scr = WMWidgetScreen(panel->win);
2180 updateSwatch(panel, panel->color);
2181 panel->lastChanged = WMWheelModeColorPanel;
2183 /* Redraw color selector (and make a backup of the part it will cover) */
2184 XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
2185 scr->copyGC, panel->colx - 2, panel->coly - 2, 4, 4, 0, 0);
2186 /* "-2" is correction for hotspot location */
2187 XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
2188 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2189 /* see above */
2192 static void wheelUndrawSelection(W_ColorPanel * panel)
2194 W_Screen *scr = WMWidgetScreen(panel->win);
2196 XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
2197 scr->copyGC, 0, 0, 4, 4, panel->colx - 2, panel->coly - 2);
2198 /* see above */
2201 static void wheelPositionSelection(W_ColorPanel * panel, int x, int y)
2203 unsigned long ofs = (y * panel->wheelMtrx->width) + x;
2205 panel->color.rgb.red = panel->wheelMtrx->values[panel->wheelMtrx->data[0][ofs]];
2207 panel->color.rgb.green = panel->wheelMtrx->values[panel->wheelMtrx->data[1][ofs]];
2209 panel->color.rgb.blue = panel->wheelMtrx->values[panel->wheelMtrx->data[2][ofs]];
2210 panel->color.set = cpRGB;
2212 wheelUndrawSelection(panel);
2214 panel->colx = x;
2215 panel->coly = y;
2217 wheelUpdateSelection(panel);
2218 wheelUpdateBrightnessGradientFromLocation(panel);
2221 static void wheelPositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2223 int hue;
2224 int xcor, ycor;
2225 CPColor cpColor;
2227 xcor = x * 2 - colorWheelSize - 4;
2228 ycor = y * 2 - colorWheelSize - 4;
2230 panel->color.hsv.saturation = 255;
2231 panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
2233 if (xcor != 0)
2234 hue = rint(atan(-(double)ycor / (double)xcor) * (180.0 / WM_PI));
2235 else {
2236 if (ycor < 0)
2237 hue = 90;
2238 else
2239 hue = 270;
2242 if (xcor < 0)
2243 hue += 180;
2245 if ((xcor > 0) && (ycor > 0))
2246 hue += 360;
2248 panel->color.hsv.hue = hue;
2249 panel->color.set = cpHSV;
2250 convertCPColor(&panel->color);
2252 wheelUndrawSelection(panel);
2254 panel->colx = 2 + rint((colorWheelSize * (1.0 + cos(panel->color.hsv.hue * (WM_PI / 180.0)))) / 2.0);
2255 /* "+2" because of "colorWheelSize + 4" */
2256 panel->coly = 2 + rint((colorWheelSize * (1.0 + sin(-panel->color.hsv.hue * (WM_PI / 180.0)))) / 2.0);
2258 wheelUpdateSelection(panel);
2259 cpColor = panel->color;
2260 wheelUpdateBrightnessGradient(panel, cpColor);
2263 static void wheelUpdateBrightnessGradientFromLocation(W_ColorPanel * panel)
2265 CPColor from;
2266 unsigned long ofs;
2268 ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
2270 from.rgb.red = panel->wheelMtrx->data[0][ofs];
2271 from.rgb.green = panel->wheelMtrx->data[1][ofs];
2272 from.rgb.blue = panel->wheelMtrx->data[2][ofs];
2273 from.set = cpRGB;
2275 wheelUpdateBrightnessGradient(panel, from);
2278 static void wheelUpdateBrightnessGradient(W_ColorPanel * panel, CPColor topColor)
2280 RColor to;
2281 RImage *sliderImg;
2282 WMPixmap *sliderPxmp;
2284 to.red = to.green = to.blue = 0;
2286 if (topColor.set == cpHSV)
2287 convertCPColor(&topColor);
2289 sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
2290 sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win), sliderImg, 0);
2291 RReleaseImage(sliderImg);
2292 WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
2293 WMReleasePixmap(sliderPxmp);
2296 /****************** Grayscale Panel Functions ***************/
2298 static void grayBrightnessSliderCallback(WMWidget * w, void *data)
2300 CPColor cpColor;
2301 int value;
2302 char tmp[4];
2303 W_ColorPanel *panel = (W_ColorPanel *) data;
2305 /* Parameter not used, but tell the compiler that it is ok */
2306 (void) w;
2308 value = WMGetSliderValue(panel->grayBrightnessS);
2310 sprintf(tmp, "%d", value);
2312 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2313 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55 * value);
2314 cpColor.set = cpRGB;
2316 updateSwatch(panel, cpColor);
2317 panel->lastChanged = WMGrayModeColorPanel;
2320 static void grayPresetButtonCallback(WMWidget * w, void *data)
2322 CPColor cpColor;
2323 char tmp[4];
2324 int value;
2325 int i = 0;
2326 W_ColorPanel *panel = (W_ColorPanel *) data;
2328 while (i < 7) {
2329 if (w == panel->grayPresetBtn[i])
2330 break;
2331 i++;
2334 value = rint((100.0 * i) / 6.0);
2335 sprintf(tmp, "%d", value);
2337 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2338 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * i) / 6.0);
2339 cpColor.set = cpRGB;
2341 WMSetSliderValue(panel->grayBrightnessS, rint((100.0 * i) / 6.0));
2343 updateSwatch(panel, cpColor);
2344 panel->lastChanged = WMGrayModeColorPanel;
2347 static void grayBrightnessTextFieldCallback(void *observerData, WMNotification * notification)
2349 CPColor cpColor;
2350 char tmp[4];
2351 int value;
2352 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2354 /* Parameter not used, but tell the compiler that it is ok */
2355 (void) notification;
2357 value = get_textfield_as_integer(panel->grayBrightnessT);
2358 if (value > 100)
2359 value = 100;
2360 if (value < 0)
2361 value = 0;
2363 sprintf(tmp, "%d", value);
2364 WMSetTextFieldText(panel->grayBrightnessT, tmp);
2365 WMSetSliderValue(panel->grayBrightnessS, value);
2367 cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint((255.0 * value) / 100.0);
2368 cpColor.set = cpRGB;
2370 updateSwatch(panel, cpColor);
2371 panel->lastChanged = WMGrayModeColorPanel;
2374 /******************* RGB Panel Functions *****************/
2376 void rgbIntToChar(W_ColorPanel *panel, int *value)
2378 char tmp[4];
2379 const char *format;
2381 switch (panel->rgbState) {
2382 case RGBdec:
2383 format = "%d";
2384 break;
2385 case RGBhex:
2386 format = "%0X";
2387 break;
2388 default:
2389 format = "";
2392 sprintf(tmp, format, value[0]);
2393 WMSetTextFieldText(panel->rgbRedT, tmp);
2394 sprintf(tmp, format, value[1]);
2395 WMSetTextFieldText(panel->rgbGreenT, tmp);
2396 sprintf(tmp, format, value[2]);
2397 WMSetTextFieldText(panel->rgbBlueT, tmp);
2400 int *rgbCharToInt(W_ColorPanel *panel)
2402 int base = 0;
2403 static int value[3];
2404 char *str;
2406 switch (panel->rgbState) {
2407 case RGBdec:
2408 base = 10;
2409 break;
2410 case RGBhex:
2411 base = 16;
2412 break;
2415 str = WMGetTextFieldText(panel->rgbRedT);
2416 value[0] = strtol(str, NULL, base);
2417 wfree(str);
2419 str = WMGetTextFieldText(panel->rgbGreenT);
2420 value[1] = strtol(str, NULL, base);
2421 wfree(str);
2423 str = WMGetTextFieldText(panel->rgbBlueT);
2424 value[2] = strtol(str, NULL, base);
2425 wfree(str);
2427 return value;
2430 static void rgbSliderCallback(WMWidget * w, void *data)
2432 CPColor cpColor;
2433 int value[3];
2434 W_ColorPanel *panel = (W_ColorPanel *) data;
2436 /* Parameter not used, but tell the compiler that it is ok */
2437 (void) w;
2439 value[0] = WMGetSliderValue(panel->rgbRedS);
2440 value[1] = WMGetSliderValue(panel->rgbGreenS);
2441 value[2] = WMGetSliderValue(panel->rgbBlueS);
2443 rgbIntToChar(panel, value);
2445 cpColor.rgb.red = value[0];
2446 cpColor.rgb.green = value[1];
2447 cpColor.rgb.blue = value[2];
2448 cpColor.set = cpRGB;
2450 updateSwatch(panel, cpColor);
2451 panel->lastChanged = WMRGBModeColorPanel;
2454 static void rgbTextFieldCallback(void *observerData, WMNotification * notification)
2456 CPColor cpColor;
2457 int *value;
2458 int n;
2459 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2461 /* Parameter not used, but tell the compiler that it is ok */
2462 (void) notification;
2464 value = rgbCharToInt(panel);
2466 for (n = 0; n < 3; n++) {
2467 if (value[n] > 255)
2468 value[n] = 255;
2469 if (value[n] < 0)
2470 value[n] = 0;
2473 rgbIntToChar(panel, value);
2475 WMSetSliderValue(panel->rgbRedS, value[0]);
2476 WMSetSliderValue(panel->rgbGreenS, value[1]);
2477 WMSetSliderValue(panel->rgbBlueS, value[2]);
2479 cpColor.rgb.red = value[0];
2480 cpColor.rgb.green = value[1];
2481 cpColor.rgb.blue = value[2];
2482 cpColor.set = cpRGB;
2484 updateSwatch(panel, cpColor);
2485 panel->lastChanged = WMRGBModeColorPanel;
2488 static void rgbDecToHex(WMWidget *w, void *data)
2490 W_ColorPanel *panel = (W_ColorPanel *) data;
2491 int *value;
2493 (void) w;
2495 switch (panel->rgbState) {
2496 case RGBhex:
2497 if (WMGetButtonSelected(panel->rgbDecB)) {
2498 WMSetLabelText(panel->rgbMaxL, "255");
2499 WMRedisplayWidget(panel->rgbMaxL);
2500 value = rgbCharToInt(panel);
2501 panel->rgbState = RGBdec;
2502 rgbIntToChar(panel, value);
2504 break;
2506 case RGBdec:
2507 if (WMGetButtonSelected(panel->rgbHexB)) {
2508 WMSetLabelText(panel->rgbMaxL, "FF");
2509 WMRedisplayWidget(panel->rgbMaxL);
2510 value = rgbCharToInt(panel);
2511 panel->rgbState = RGBhex;
2512 rgbIntToChar(panel, value);
2514 break;
2518 /******************* CMYK Panel Functions *****************/
2520 static void cmykSliderCallback(WMWidget * w, void *data)
2522 CPColor cpColor;
2523 int value[4];
2524 char tmp[4];
2525 W_ColorPanel *panel = (W_ColorPanel *) data;
2526 double scale;
2528 /* Parameter not used, but tell the compiler that it is ok */
2529 (void) w;
2531 value[0] = WMGetSliderValue(panel->cmykCyanS);
2532 value[1] = WMGetSliderValue(panel->cmykMagentaS);
2533 value[2] = WMGetSliderValue(panel->cmykYellowS);
2534 value[3] = WMGetSliderValue(panel->cmykBlackS);
2536 sprintf(tmp, "%d", value[0]);
2537 WMSetTextFieldText(panel->cmykCyanT, tmp);
2538 sprintf(tmp, "%d", value[1]);
2539 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2540 sprintf(tmp, "%d", value[2]);
2541 WMSetTextFieldText(panel->cmykYellowT, tmp);
2542 sprintf(tmp, "%d", value[3]);
2543 WMSetTextFieldText(panel->cmykBlackT, tmp);
2545 scale = 2.55 * (1.0 - (value[3] / 100.0));
2546 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2547 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2548 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2549 cpColor.set = cpRGB;
2551 updateSwatch(panel, cpColor);
2552 panel->lastChanged = WMCMYKModeColorPanel;
2555 static void cmykTextFieldCallback(void *observerData, WMNotification * notification)
2557 CPColor cpColor;
2558 int value[4];
2559 char tmp[4];
2560 int n;
2561 double scale;
2562 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2564 /* Parameter not used, but tell the compiler that it is ok */
2565 (void) notification;
2567 value[0] = get_textfield_as_integer(panel->cmykCyanT);
2568 value[1] = get_textfield_as_integer(panel->cmykMagentaT);
2569 value[2] = get_textfield_as_integer(panel->cmykYellowT);
2570 value[3] = get_textfield_as_integer(panel->cmykBlackT);
2572 for (n = 0; n < 4; n++) {
2573 if (value[n] > 100)
2574 value[n] = 100;
2575 if (value[n] < 0)
2576 value[n] = 0;
2579 sprintf(tmp, "%d", value[0]);
2580 WMSetTextFieldText(panel->cmykCyanT, tmp);
2582 sprintf(tmp, "%d", value[1]);
2583 WMSetTextFieldText(panel->cmykMagentaT, tmp);
2585 sprintf(tmp, "%d", value[2]);
2586 WMSetTextFieldText(panel->cmykYellowT, tmp);
2588 sprintf(tmp, "%d", value[3]);
2589 WMSetTextFieldText(panel->cmykBlackT, tmp);
2591 WMSetSliderValue(panel->cmykCyanS, value[0]);
2592 WMSetSliderValue(panel->cmykMagentaS, value[1]);
2593 WMSetSliderValue(panel->cmykYellowS, value[2]);
2594 WMSetSliderValue(panel->cmykBlackS, value[3]);
2596 scale = 2.55 * (1.0 - (value[3] / 100.0));
2597 cpColor.rgb.red = rint((100.0 - value[0]) * scale);
2598 cpColor.rgb.green = rint((100.0 - value[1]) * scale);
2599 cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
2600 cpColor.set = cpRGB;
2602 updateSwatch(panel, cpColor);
2603 panel->lastChanged = WMCMYKModeColorPanel;
2606 /********************** HSB Panel Functions ***********************/
2608 static void hsbSliderCallback(WMWidget * w, void *data)
2610 CPColor cpColor;
2611 int value[3];
2612 char tmp[4];
2613 W_ColorPanel *panel = (W_ColorPanel *) data;
2615 value[0] = WMGetSliderValue(panel->hsbHueS);
2616 value[1] = WMGetSliderValue(panel->hsbSaturationS);
2617 value[2] = WMGetSliderValue(panel->hsbBrightnessS);
2619 sprintf(tmp, "%d", value[0]);
2620 WMSetTextFieldText(panel->hsbHueT, tmp);
2621 sprintf(tmp, "%d", value[1]);
2622 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2623 sprintf(tmp, "%d", value[2]);
2624 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2626 cpColor.hsv.hue = value[0];
2627 cpColor.hsv.saturation = value[1] * 2.55;
2628 cpColor.hsv.value = value[2] * 2.55;
2629 cpColor.set = cpHSV;
2631 convertCPColor(&cpColor);
2633 panel->lastChanged = WMHSBModeColorPanel;
2634 updateSwatch(panel, cpColor);
2636 if (w != panel->hsbBrightnessS)
2637 hsbUpdateBrightnessGradient(panel);
2638 if (w != panel->hsbSaturationS)
2639 hsbUpdateSaturationGradient(panel);
2640 if (w != panel->hsbHueS)
2641 hsbUpdateHueGradient(panel);
2644 static void hsbTextFieldCallback(void *observerData, WMNotification * notification)
2646 CPColor cpColor;
2647 int value[3];
2648 char tmp[4];
2649 int n;
2650 W_ColorPanel *panel = (W_ColorPanel *) observerData;
2652 /* Parameter not used, but tell the compiler that it is ok */
2653 (void) notification;
2655 value[0] = get_textfield_as_integer(panel->hsbHueT);
2656 value[1] = get_textfield_as_integer(panel->hsbSaturationT);
2657 value[2] = get_textfield_as_integer(panel->hsbBrightnessT);
2659 if (value[0] > 359)
2660 value[0] = 359;
2661 if (value[0] < 0)
2662 value[0] = 0;
2664 for (n = 1; n < 3; n++) {
2665 if (value[n] > 100)
2666 value[n] = 100;
2667 if (value[n] < 0)
2668 value[n] = 0;
2671 sprintf(tmp, "%d", value[0]);
2672 WMSetTextFieldText(panel->hsbHueT, tmp);
2673 sprintf(tmp, "%d", value[1]);
2674 WMSetTextFieldText(panel->hsbSaturationT, tmp);
2675 sprintf(tmp, "%d", value[2]);
2676 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
2678 WMSetSliderValue(panel->hsbHueS, value[0]);
2679 WMSetSliderValue(panel->hsbSaturationS, value[1]);
2680 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
2682 cpColor.hsv.hue = value[0];
2683 cpColor.hsv.saturation = value[1] * 2.55;
2684 cpColor.hsv.value = value[2] * 2.55;
2685 cpColor.set = cpHSV;
2687 convertCPColor(&cpColor);
2689 panel->lastChanged = WMHSBModeColorPanel;
2690 updateSwatch(panel, cpColor);
2692 hsbUpdateBrightnessGradient(panel);
2693 hsbUpdateSaturationGradient(panel);
2694 hsbUpdateHueGradient(panel);
2697 static void hsbUpdateBrightnessGradient(W_ColorPanel * panel)
2699 W_Screen *scr = WMWidgetScreen(panel->win);
2700 RColor from;
2701 CPColor to;
2702 RImage *sliderImg;
2703 WMPixmap *sliderPxmp;
2705 from.red = from.green = from.blue = 0;
2706 to.hsv = panel->color.hsv;
2707 to.hsv.value = 255;
2708 to.set = cpHSV;
2710 convertCPColor(&to);
2712 sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
2713 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2714 RReleaseImage(sliderImg);
2716 if (sliderPxmp)
2717 W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
2718 panel->font12, 2, 0, 100, WALeft, scr->white,
2719 False, _("Brightness"), strlen(_("Brightness")));
2720 else
2721 wwarning(_("Color Panel: Could not allocate memory"));
2723 WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
2724 WMReleasePixmap(sliderPxmp);
2727 static void hsbUpdateSaturationGradient(W_ColorPanel * panel)
2729 W_Screen *scr = WMWidgetScreen(panel->win);
2730 CPColor from;
2731 CPColor to;
2732 RImage *sliderImg;
2733 WMPixmap *sliderPxmp;
2735 from.hsv = panel->color.hsv;
2736 from.hsv.saturation = 0;
2737 from.set = cpHSV;
2738 convertCPColor(&from);
2740 to.hsv = panel->color.hsv;
2741 to.hsv.saturation = 255;
2742 to.set = cpHSV;
2743 convertCPColor(&to);
2745 sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb), RGRD_HORIZONTAL);
2746 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2747 RReleaseImage(sliderImg);
2749 if (sliderPxmp)
2750 W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
2751 panel->font12, 2, 0, 100, WALeft,
2752 from.hsv.value < 128 ? scr->white : scr->black, False,
2753 _("Saturation"), strlen(_("Saturation")));
2754 else
2755 wwarning(_("Color Panel: Could not allocate memory"));
2757 WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
2758 WMReleasePixmap(sliderPxmp);
2761 static void hsbUpdateHueGradient(W_ColorPanel * panel)
2763 W_Screen *scr = WMWidgetScreen(panel->win);
2764 RColor **colors = NULL;
2765 RHSVColor hsvcolor;
2766 RImage *sliderImg;
2767 WMPixmap *sliderPxmp;
2768 int i;
2770 hsvcolor = panel->color.hsv;
2772 colors = wmalloc(sizeof(RColor *) * (8));
2773 for (i = 0; i < 7; i++) {
2774 hsvcolor.hue = (360 * i) / 6;
2775 colors[i] = wmalloc(sizeof(RColor));
2776 RHSVtoRGB(&hsvcolor, colors[i]);
2778 colors[7] = NULL;
2780 sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
2781 sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
2782 RReleaseImage(sliderImg);
2784 if (sliderPxmp)
2785 W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
2786 panel->font12, 2, 0, 100, WALeft,
2787 hsvcolor.value < 128 ? scr->white : scr->black, False, _("Hue"), strlen(_("Hue")));
2788 else
2789 wwarning(_("Color Panel: Could not allocate memory"));
2791 WMSetSliderImage(panel->hsbHueS, sliderPxmp);
2792 WMReleasePixmap(sliderPxmp);
2794 for (i = 0; i < 7; i++)
2795 wfree(colors[i]);
2797 wfree(colors);
2800 /*************** Custom Palette Functions ****************/
2802 static void customRenderSpectrum(W_ColorPanel * panel)
2804 RImage *spectrum;
2805 int x, y;
2806 unsigned char *ptr;
2807 CPColor cpColor;
2809 spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
2811 ptr = spectrum->data;
2813 for (y = 0; y < SPECTRUM_HEIGHT; y++) {
2814 cpColor.hsv.hue = y;
2815 cpColor.hsv.saturation = 0;
2816 cpColor.hsv.value = 255;
2817 cpColor.set = cpHSV;
2819 for (x = 0; x < SPECTRUM_WIDTH; x++) {
2820 convertCPColor(&cpColor);
2822 *(ptr++) = (unsigned char)cpColor.rgb.red;
2823 *(ptr++) = (unsigned char)cpColor.rgb.green;
2824 *(ptr++) = (unsigned char)cpColor.rgb.blue;
2826 if (x < (SPECTRUM_WIDTH / 2))
2827 cpColor.hsv.saturation++;
2829 if (x > (SPECTRUM_WIDTH / 2))
2830 cpColor.hsv.value--;
2833 if (panel->customPaletteImg) {
2834 RReleaseImage(panel->customPaletteImg);
2835 panel->customPaletteImg = NULL;
2837 panel->customPaletteImg = spectrum;
2840 static void customSetPalette(W_ColorPanel * panel)
2842 W_Screen *scr = WMWidgetScreen(panel->win);
2843 RImage *scaledImg;
2844 Pixmap image;
2846 image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth, customPaletteHeight, scr->depth);
2847 scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth, customPaletteHeight);
2848 RConvertImage(scr->rcontext, scaledImg, &image);
2849 RReleaseImage(scaledImg);
2851 XCopyArea(scr->display, image, panel->customPaletteContentView->window,
2852 scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
2854 /* Check backimage exists. If it doesn't, allocate and fill it */
2855 if (!panel->selectionBackImg) {
2856 panel->selectionBackImg = XCreatePixmap(scr->display,
2857 panel->customPaletteContentView->window, 4, 4, scr->depth);
2860 XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
2861 panel->palx - 2, panel->paly - 2, 4, 4, 0, 0);
2862 XCopyArea(scr->display, panel->selectionImg,
2863 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2864 panel->palx - 2, panel->paly - 2);
2865 XFreePixmap(scr->display, image);
2867 panel->palXRatio = (double)(panel->customPaletteImg->width) / (double)(customPaletteWidth);
2868 panel->palYRatio = (double)(panel->customPaletteImg->height) / (double)(customPaletteHeight);
2871 static void customPalettePositionSelection(W_ColorPanel * panel, int x, int y)
2873 W_Screen *scr = WMWidgetScreen(panel->win);
2874 unsigned long ofs;
2876 /* undraw selection */
2877 XCopyArea(scr->display, panel->selectionBackImg,
2878 panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
2879 panel->palx - 2, panel->paly - 2);
2881 panel->palx = x;
2882 panel->paly = y;
2884 ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) * panel->customPaletteImg->width) * 3;
2886 panel->color.rgb.red = panel->customPaletteImg->data[ofs];
2887 panel->color.rgb.green = panel->customPaletteImg->data[ofs + 1];
2888 panel->color.rgb.blue = panel->customPaletteImg->data[ofs + 2];
2889 panel->color.set = cpRGB;
2891 updateSwatch(panel, panel->color);
2892 panel->lastChanged = WMCustomPaletteModeColorPanel;
2894 /* Redraw color selector (and make a backup of the part it will cover) */
2895 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 */
2896 XCopyArea(scr->display, panel->selectionImg, panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4, panel->palx - 2, panel->paly - 2); /* see above */
2899 static void customPalettePositionSelectionOutBounds(W_ColorPanel * panel, int x, int y)
2901 if (x < 2)
2902 x = 2;
2903 if (y < 2)
2904 y = 2;
2905 if (x >= customPaletteWidth)
2906 x = customPaletteWidth - 2;
2907 if (y >= customPaletteHeight)
2908 y = customPaletteHeight - 2;
2910 customPalettePositionSelection(panel, x, y);
2913 static void customPaletteHandleEvents(XEvent * event, void *data)
2915 W_ColorPanel *panel = (W_ColorPanel *) data;
2917 switch (event->type) {
2918 case Expose:
2919 if (event->xexpose.count != 0) /* TODO Improve. */
2920 break;
2921 customSetPalette(panel);
2922 break;
2926 static void customPaletteHandleActionEvents(XEvent * event, void *data)
2928 W_ColorPanel *panel = (W_ColorPanel *) data;
2929 int x, y;
2931 switch (event->type) {
2932 case ButtonPress:
2933 x = event->xbutton.x;
2934 y = event->xbutton.y;
2936 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2937 panel->flags.dragging = 1;
2938 customPalettePositionSelection(panel, x, y);
2940 break;
2942 case ButtonRelease:
2943 panel->flags.dragging = 0;
2944 if (!panel->flags.continuous) {
2945 if (panel->action)
2946 (*panel->action) (panel, panel->clientData);
2948 break;
2950 case MotionNotify:
2951 x = event->xmotion.x;
2952 y = event->xmotion.y;
2954 if (panel->flags.dragging) {
2955 if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
2956 customPalettePositionSelection(panel, x, y);
2957 } else
2958 customPalettePositionSelectionOutBounds(panel, x, y);
2960 break;
2964 static void customPaletteMenuCallback(WMWidget * w, void *data)
2966 W_ColorPanel *panel = (W_ColorPanel *) data;
2967 int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
2969 /* Parameter not used, but tell the compiler that it is ok */
2970 (void) w;
2972 switch (item) {
2973 case CPmenuNewFromFile:
2974 customPaletteMenuNewFromFile(panel);
2975 break;
2976 case CPmenuRename:
2977 customPaletteMenuRename(panel);
2978 break;
2979 case CPmenuRemove:
2980 customPaletteMenuRemove(panel);
2981 break;
2982 case CPmenuCopy:
2983 break;
2984 case CPmenuNewFromClipboard:
2985 break;
2989 static void customPaletteMenuNewFromFile(W_ColorPanel * panel)
2991 W_Screen *scr = WMWidgetScreen(panel->win);
2992 WMOpenPanel *browseP;
2993 char *filepath;
2994 char *filename = NULL;
2995 char *spath;
2996 char *tmp;
2997 int i;
2998 RImage *tmpImg = NULL;
3000 if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir, "\0") == 0))
3001 spath = wexpandpath(wgethomedir());
3002 else
3003 spath = wexpandpath(panel->lastBrowseDir);
3005 browseP = WMGetOpenPanel(scr);
3006 WMSetFilePanelCanChooseDirectories(browseP, 0);
3007 WMSetFilePanelCanChooseFiles(browseP, 1);
3009 /* Get a filename */
3010 if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
3011 _("Open Palette"), RSupportedFileFormats())) {
3012 filepath = WMGetFilePanelFileName(browseP);
3014 /* Get seperation position between path and filename */
3015 i = strrchr(filepath, '/') - filepath + 1;
3016 if (i > strlen(filepath))
3017 i = strlen(filepath);
3019 /* Store last browsed path */
3020 if (panel->lastBrowseDir)
3021 wfree(panel->lastBrowseDir);
3022 panel->lastBrowseDir = wmalloc((i + 1) * sizeof(char));
3023 strncpy(panel->lastBrowseDir, filepath, i);
3024 panel->lastBrowseDir[i] = '\0';
3026 /* Get filename from path */
3027 filename = wstrdup(filepath + i);
3029 /* Check for duplicate files, and rename it if there are any */
3030 tmp = wstrconcat(panel->configurationPath, filename);
3031 while (access(tmp, F_OK) == 0) {
3032 char *newName;
3034 wfree(tmp);
3036 newName = generateNewFilename(filename);
3037 wfree(filename);
3038 filename = newName;
3040 tmp = wstrconcat(panel->configurationPath, filename);
3042 wfree(tmp);
3044 /* Copy image to $(gnustepdir)/Library/Colors/ &
3045 * Add filename to history menu */
3046 if (wcopy_file(panel->configurationPath, filepath, filename) == 0) {
3048 /* filepath is a "local" path now the file has been copied */
3049 wfree(filepath);
3050 filepath = wstrconcat(panel->configurationPath, filename);
3052 /* load the image & add menu entries */
3053 tmpImg = RLoadImage(scr->rcontext, filepath, 0);
3054 if (tmpImg) {
3055 if (panel->customPaletteImg)
3056 RReleaseImage(panel->customPaletteImg);
3057 panel->customPaletteImg = tmpImg;
3059 customSetPalette(panel);
3060 WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
3062 panel->currentPalette =
3063 WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn) - 1;
3065 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
3066 panel->currentPalette);
3068 } else {
3069 tmp = wstrconcat(panel->configurationPath, filename);
3071 i = remove(tmp); /* Delete the file, it doesn't belong here */
3072 WMRunAlertPanel(scr, panel->win, _("File Error"),
3073 _("Invalid file format !"), _("OK"), NULL, NULL);
3074 if (i != 0) {
3075 werror(_("can't remove file %s"), tmp);
3076 WMRunAlertPanel(scr, panel->win, _("File Error"),
3077 _("Couldn't remove file from Configuration Directory !"),
3078 _("OK"), NULL, NULL);
3080 wfree(tmp);
3082 wfree(filepath);
3083 wfree(filename);
3085 WMFreeFilePanel(browseP);
3087 wfree(spath);
3090 static void customPaletteMenuRename(W_ColorPanel * panel)
3092 W_Screen *scr = WMWidgetScreen(panel->win);
3093 char *toName = NULL;
3094 char *fromName;
3095 char *toPath, *fromPath;
3096 int item;
3097 int index;
3099 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3100 fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
3102 toName = WMRunInputPanel(scr, panel->win, _("Rename"), _("Rename palette to:"),
3103 fromName, _("OK"), _("Cancel"));
3105 if (toName) {
3107 /* As some people do certain stupid things... */
3108 if (strcmp(toName, fromName) == 0) {
3109 wfree(toName);
3110 return;
3113 /* For normal people */
3114 fromPath = wstrconcat(panel->configurationPath, fromName);
3115 toPath = wstrconcat(panel->configurationPath, toName);
3117 if (access(toPath, F_OK) == 0) {
3118 /* Careful, this palette exists already */
3119 if (WMRunAlertPanel(scr, panel->win, _("Warning"),
3120 _("Palette already exists !\n\nOverwrite ?"), _("No"), _("Yes"),
3121 NULL) == 1) {
3122 /* "No" = 0, "Yes" = 1 */
3123 int items = WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn);
3125 remove(toPath);
3127 /* Remove from History list too */
3128 index = 1;
3129 while ((index < items)
3131 (strcmp(WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, index), toName)
3132 != 0))
3133 index++;
3135 if (index < items) {
3136 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, index);
3137 if (index < item)
3138 item--;
3141 } else {
3142 wfree(fromPath);
3143 wfree(toName);
3144 wfree(toPath);
3146 return;
3150 if (rename(fromPath, toPath) != 0)
3151 werror(_("Couldn't rename palette %s to %s"), fromName, toName);
3152 else {
3153 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3154 WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item, toName);
3156 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
3158 wfree(fromPath);
3159 wfree(toPath);
3160 wfree(toName);
3164 static void customPaletteMenuRemove(W_ColorPanel * panel)
3166 W_Screen *scr = WMWidgetScreen(panel->win);
3167 char *text;
3168 char *tmp;
3169 int choice;
3170 int item;
3172 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3174 tmp = wstrconcat(_("This will permanently remove the palette "),
3175 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3176 text = wstrconcat(tmp, _(".\n\nAre you sure you want to remove this palette ?"));
3177 wfree(tmp);
3179 choice = WMRunAlertPanel(scr, panel->win, _("Remove"), text, _("Yes"), _("No"), NULL);
3180 /* returns 0 (= "Yes") or 1 (="No") */
3181 wfree(text);
3183 if (choice == 0) {
3185 tmp = wstrconcat(panel->configurationPath,
3186 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3188 if (remove(tmp) == 0) {
3189 /* item-1 always exists */
3190 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3192 customPaletteHistoryCallback(panel->customPaletteHistoryBtn, panel);
3193 customSetPalette(panel);
3195 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3197 } else {
3198 werror(_("Couldn't remove palette %s"), tmp);
3201 wfree(tmp);
3205 static void customPaletteHistoryCallback(WMWidget * w, void *data)
3207 W_ColorPanel *panel = (W_ColorPanel *) data;
3208 W_Screen *scr = WMWidgetScreen(panel->win);
3209 int item;
3210 char *filename;
3211 RImage *tmp = NULL;
3212 unsigned char perm_mask;
3214 item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
3215 if (item == panel->currentPalette)
3216 return;
3218 if (item == 0) {
3219 customRenderSpectrum(panel);
3221 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, False);
3222 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, False);
3223 } else {
3224 /* Load file from configpath */
3225 filename = wstrconcat(panel->configurationPath,
3226 WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item));
3228 /* If the file corresponding to the item does not exist,
3229 * remove it from the history list and select the next one.
3231 perm_mask = (access(filename, F_OK) == 0);
3232 if (!perm_mask) {
3233 /* File does not exist */
3234 wfree(filename);
3235 WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item - 1);
3236 WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
3237 customPaletteHistoryCallback(w, data);
3238 return;
3241 /* Get the image */
3242 tmp = RLoadImage(scr->rcontext, filename, 0);
3243 if (tmp) {
3244 if (panel->customPaletteImg) {
3245 RReleaseImage(panel->customPaletteImg);
3246 panel->customPaletteImg = NULL;
3248 panel->customPaletteImg = tmp;
3251 /* If the image is not writable, don't allow removing/renaming */
3252 perm_mask = (access(filename, W_OK) == 0);
3253 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, perm_mask);
3254 WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, perm_mask);
3256 wfree(filename);
3258 customSetPalette(panel);
3260 panel->currentPalette = item;
3263 /************************* ColorList Panel Functions **********************/
3265 static void colorListPaintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
3267 WMScreen *scr = WMWidgetScreen(lPtr);
3268 Display *dpy = WMScreenDisplay(scr);
3269 WMView *view = W_VIEW(lPtr);
3270 RColor *color = (RColor *) WMGetListItem(lPtr, index)->clientData;
3271 W_ColorPanel *panel = WMGetHangedData(lPtr);
3272 int width, height, x, y;
3273 WMColor *fillColor;
3275 width = rect->size.width;
3276 height = rect->size.height;
3277 x = rect->pos.x;
3278 y = rect->pos.y;
3280 if (state & WLDSSelected)
3281 XFillRectangle(dpy, d, WMColorGC(scr->white), x, y, width, height);
3282 else
3283 XFillRectangle(dpy, d, WMColorGC(view->backColor), x, y, width, height);
3285 fillColor = WMCreateRGBColor(scr, color->red << 8, color->green << 8, color->blue << 8, True);
3287 XFillRectangle(dpy, d, WMColorGC(fillColor), x, y, 15, height);
3288 WMReleaseColor(fillColor);
3290 WMDrawString(scr, d, scr->black, panel->font12, x + 18, y, text, strlen(text));
3293 static void colorListSelect(WMWidget * w, void *data)
3295 W_ColorPanel *panel = (W_ColorPanel *) data;
3296 CPColor cpColor;
3298 cpColor.rgb = *((RColor *) WMGetListSelectedItem(w)->clientData);
3299 cpColor.set = cpRGB;
3301 panel->lastChanged = WMColorListModeColorPanel;
3302 updateSwatch(panel, cpColor);
3305 static void colorListColorMenuCallback(WMWidget * w, void *data)
3307 W_ColorPanel *panel = (W_ColorPanel *) data;
3308 int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
3310 /* Parameter not used, but tell the compiler that it is ok */
3311 (void) w;
3313 switch (item) {
3314 case CLmenuAdd:
3315 break;
3316 case CLmenuRename:
3317 break;
3318 case CLmenuRemove:
3319 break;
3323 static void colorListListMenuCallback(WMWidget * w, void *data)
3325 W_ColorPanel *panel = (W_ColorPanel *) data;
3326 int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
3328 /* Parameter not used, but tell the compiler that it is ok */
3329 (void) w;
3331 switch (item) {
3332 case CLmenuAdd:
3333 break;
3334 case CLmenuRename:
3335 break;
3336 case CLmenuRemove:
3337 break;
3341 /*************** Panel Initialisation Functions *****************/
3343 static void wheelInit(W_ColorPanel * panel)
3345 CPColor cpColor;
3347 if (panel->color.set != cpHSV)
3348 convertCPColor(&panel->color);
3350 WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
3352 panel->colx = 2 + rint((colorWheelSize / 2.0) *
3353 (1 + (panel->color.hsv.saturation / 255.0) *
3354 cos(panel->color.hsv.hue * WM_PI / 180.0)));
3355 panel->coly = 2 + rint((colorWheelSize / 2.0) *
3356 (1 + (panel->color.hsv.saturation / 255.0) *
3357 sin(-panel->color.hsv.hue * WM_PI / 180.0)));
3359 wheelCalculateValues(panel, panel->color.hsv.value);
3361 cpColor = panel->color;
3362 cpColor.hsv.value = 255;
3363 cpColor.set = cpHSV;
3364 wheelUpdateBrightnessGradient(panel, cpColor);
3367 static void grayInit(W_ColorPanel * panel)
3369 int value;
3370 char tmp[4];
3372 if (panel->color.set != cpHSV)
3373 convertCPColor(&panel->color);
3375 value = rint(panel->color.hsv.value / 2.55);
3376 WMSetSliderValue(panel->grayBrightnessS, value);
3378 sprintf(tmp, "%d", value);
3379 WMSetTextFieldText(panel->grayBrightnessT, tmp);
3382 static void rgbInit(W_ColorPanel * panel)
3384 char tmp[4];
3385 const char *format;
3387 if (panel->color.set != cpRGB)
3388 convertCPColor(&panel->color);
3390 WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
3391 WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
3392 WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
3394 switch (panel->rgbState) {
3395 case RGBdec:
3396 format = "%d";
3397 break;
3398 case RGBhex:
3399 format = "%0X";
3400 break;
3401 default:
3402 /* Avoid compiler warning */
3403 format = "";
3406 sprintf(tmp, format, panel->color.rgb.red);
3407 WMSetTextFieldText(panel->rgbRedT, tmp);
3408 sprintf(tmp, format, panel->color.rgb.green);
3409 WMSetTextFieldText(panel->rgbGreenT, tmp);
3410 sprintf(tmp, format, panel->color.rgb.blue);
3411 WMSetTextFieldText(panel->rgbBlueT, tmp);
3414 static void cmykInit(W_ColorPanel * panel)
3416 int value[3];
3417 char tmp[4];
3419 if (panel->color.set != cpRGB)
3420 convertCPColor(&panel->color);
3422 value[0] = rint((255 - panel->color.rgb.red) / 2.55);
3423 value[1] = rint((255 - panel->color.rgb.green) / 2.55);
3424 value[2] = rint((255 - panel->color.rgb.blue) / 2.55);
3426 WMSetSliderValue(panel->cmykCyanS, value[0]);
3427 WMSetSliderValue(panel->cmykMagentaS, value[1]);
3428 WMSetSliderValue(panel->cmykYellowS, value[2]);
3429 WMSetSliderValue(panel->cmykBlackS, 0);
3431 sprintf(tmp, "%d", value[0]);
3432 WMSetTextFieldText(panel->cmykCyanT, tmp);
3433 sprintf(tmp, "%d", value[1]);
3434 WMSetTextFieldText(panel->cmykMagentaT, tmp);
3435 sprintf(tmp, "%d", value[2]);
3436 WMSetTextFieldText(panel->cmykYellowT, tmp);
3437 WMSetTextFieldText(panel->cmykBlackT, "0");
3440 static void hsbInit(W_ColorPanel * panel)
3442 int value[3];
3443 char tmp[4];
3445 if (panel->color.set != cpHSV)
3446 convertCPColor(&panel->color);
3448 value[0] = panel->color.hsv.hue;
3449 value[1] = rint(panel->color.hsv.saturation / 2.55);
3450 value[2] = rint(panel->color.hsv.value / 2.55);
3452 WMSetSliderValue(panel->hsbHueS, value[0]);
3453 WMSetSliderValue(panel->hsbSaturationS, value[1]);
3454 WMSetSliderValue(panel->hsbBrightnessS, value[2]);
3456 sprintf(tmp, "%hu", value[0]);
3457 WMSetTextFieldText(panel->hsbHueT, tmp);
3458 sprintf(tmp, "%d", value[1]);
3459 WMSetTextFieldText(panel->hsbSaturationT, tmp);
3460 sprintf(tmp, "%d", value[2]);
3461 WMSetTextFieldText(panel->hsbBrightnessT, tmp);
3463 hsbUpdateBrightnessGradient(panel);
3464 hsbUpdateSaturationGradient(panel);
3465 hsbUpdateHueGradient(panel);
3468 /************************** Common utility functions ************************/
3470 static char *generateNewFilename(const char *curName)
3472 int n;
3473 char c;
3474 int baseLen;
3475 const char *ptr;
3476 char *newName;
3478 assert(curName);
3480 ptr = curName;
3482 if (((ptr = strrchr(ptr, '{')) == 0) || sscanf(ptr, "{%i}%c", &n, &c) != 1)
3483 return wstrconcat(curName, " {1}");
3485 baseLen = ptr - curName - 1;
3487 newName = wmalloc(baseLen + 16);
3488 strncpy(newName, curName, baseLen);
3490 snprintf(&newName[baseLen], 16, " {%i}", n + 1);
3492 return newName;
3495 static void convertCPColor(CPColor * color)
3497 unsigned short old_hue = 0;
3499 switch (color->set) {
3500 case cpNone:
3501 wwarning(_("Color Panel: Color unspecified"));
3502 return;
3503 case cpRGB:
3504 old_hue = color->hsv.hue;
3505 RRGBtoHSV(&(color->rgb), &(color->hsv));
3507 /* In black the hue is undefined, and may change by conversion
3508 * Same for white. */
3509 if (((color->rgb.red == 0) &&
3510 (color->rgb.green == 0) &&
3511 (color->rgb.blue == 0)) ||
3512 ((color->rgb.red == 0) && (color->rgb.green == 0) && (color->rgb.blue == 255))
3514 color->hsv.hue = old_hue;
3515 break;
3516 case cpHSV:
3517 RHSVtoRGB(&(color->hsv), &(color->rgb));
3518 break;
3522 static RColor ulongToRColor(WMScreen * scr, unsigned long value)
3524 RColor color;
3525 XColor *xcolor = NULL;
3527 xcolor = wmalloc(sizeof(XColor));
3528 xcolor->pixel = value;
3529 XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
3531 color.red = xcolor->red >> 8;
3532 color.green = xcolor->green >> 8;
3533 color.blue = xcolor->blue >> 8;
3534 color.alpha = 0;
3536 wfree(xcolor);
3538 return color;
3541 static unsigned char getShift(unsigned char value)
3543 unsigned char i = -1;
3545 if (value == 0)
3546 return 0;
3548 while (value) {
3549 value >>= 1;
3550 i++;
3553 return i;