Update for 0.52.0. This is a test version, which brings the Appearance
[wmaker-crm.git] / WINGs / wcolorwell.c
blobf79111e4bd3a9aff5c402d301acb32f71656eaf1
5 #include "WINGsP.h"
8 char *WMColorWellDidChangeNotification = "WMColorWellDidChangeNotification";
11 typedef struct W_ColorWell {
12 W_Class widgetClass;
13 WMView *view;
15 WMView *colorView;
17 WMColor *color;
19 WMAction *action;
20 void *clientData;
22 WMPoint ipoint;
24 struct {
25 unsigned int active:1;
26 unsigned int bordered:1;
27 } flags;
28 } ColorWell;
30 static char *_ColorWellActivatedNotification = "_ColorWellActivatedNotification";
34 static void destroyColorWell(ColorWell *cPtr);
35 static void paintColorWell(ColorWell *cPtr);
37 static void handleEvents(XEvent *event, void *data);
39 static void handleDragEvents(XEvent *event, void *data);
41 static void handleActionEvents(XEvent *event, void *data);
43 static void resizeColorWell();
47 W_ViewProcedureTable _ColorWellViewProcedures = {
48 NULL,
49 resizeColorWell,
50 NULL
54 #if 0
55 static WMDragSourceProcs dragProcs = {
58 #endif
60 #define DEFAULT_WIDTH 60
61 #define DEFAULT_HEIGHT 30
62 #define DEFAULT_BORDER_WIDTH 6
64 #define MIN_WIDTH 16
65 #define MIN_HEIGHT 8
69 static void
70 activatedObserver(void *data, WMNotification *notification)
72 WMColorWell *cPtr = (WMColorWell*)data;
74 if (!cPtr->flags.active || WMGetNotificationObject(notification) == cPtr)
75 return;
77 W_SetViewBackgroundColor(cPtr->view, WMWidgetScreen(cPtr)->gray);
78 paintColorWell(cPtr);
80 cPtr->flags.active = 0;
84 WMColorWell*
85 WMCreateColorWell(WMWidget *parent)
87 ColorWell *cPtr;
89 cPtr = wmalloc(sizeof(ColorWell));
90 memset(cPtr, 0, sizeof(ColorWell));
92 cPtr->widgetClass = WC_ColorWell;
94 cPtr->view = W_CreateView(W_VIEW(parent));
95 if (!cPtr->view) {
96 free(cPtr);
97 return NULL;
99 cPtr->view->self = cPtr;
101 cPtr->colorView = W_CreateView(cPtr->view);
102 if (!cPtr->colorView) {
103 W_DestroyView(cPtr->view);
104 free(cPtr);
105 return NULL;
107 cPtr->colorView->self = cPtr;
109 WMCreateEventHandler(cPtr->view, ExposureMask|StructureNotifyMask
110 |ClientMessageMask, handleEvents, cPtr);
112 WMCreateEventHandler(cPtr->colorView, ExposureMask, handleEvents, cPtr);
114 WMCreateEventHandler(cPtr->colorView, ButtonPressMask|ButtonMotionMask
115 |EnterWindowMask, handleDragEvents, cPtr);
117 WMCreateEventHandler(cPtr->view, ButtonPressMask, handleActionEvents,
118 cPtr);
120 cPtr->colorView->flags.mapWhenRealized = 1;
122 cPtr->flags.bordered = 1;
124 resizeColorWell(cPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
126 WMAddNotificationObserver(activatedObserver, cPtr,
127 _ColorWellActivatedNotification, NULL);
129 cPtr->color = WMBlackColor(WMWidgetScreen(cPtr));
131 return cPtr;
135 void
136 WMSetColorWellColor(WMColorWell *cPtr, WMColor *color)
138 if (cPtr->color)
139 WMReleaseColor(cPtr->color);
141 cPtr->color = WMRetainColor(color);
143 if (cPtr->colorView->flags.realized && cPtr->colorView->flags.mapped)
144 paintColorWell(cPtr);
148 WMColor*
149 WMGetColorWellColor(WMColorWell *cPtr)
151 return cPtr->color;
155 void
156 WSetColorWellBordered(WMColorWell *cPtr, Bool flag)
158 if (cPtr->flags.bordered != flag) {
159 cPtr->flags.bordered = flag;
160 resizeColorWell(cPtr, cPtr->view->size.width, cPtr->view->size.height);
165 #define MIN(a,b) ((a) > (b) ? (b) : (a))
167 static void
168 resizeColorWell(WMColorWell *cPtr, unsigned int width, unsigned int height)
170 int bw;
172 if (cPtr->flags.bordered) {
174 if (width < MIN_WIDTH)
175 width = MIN_WIDTH;
176 if (height < MIN_HEIGHT)
177 height = MIN_HEIGHT;
179 bw = (int)((float)MIN(width, height)*0.24);
181 W_ResizeView(cPtr->view, width, height);
183 W_ResizeView(cPtr->colorView, width-2*bw, height-2*bw);
185 if (cPtr->colorView->pos.x!=bw || cPtr->colorView->pos.y!=bw)
186 W_MoveView(cPtr->colorView, bw, bw);
187 } else {
188 W_ResizeView(cPtr->view, width, height);
190 W_ResizeView(cPtr->colorView, width, height);
192 W_MoveView(cPtr->colorView, 0, 0);
197 static void
198 paintColorWell(ColorWell *cPtr)
200 W_Screen *scr = cPtr->view->screen;
202 W_DrawRelief(scr, cPtr->view->window, 0, 0, cPtr->view->size.width,
203 cPtr->view->size.height, WRRaised);
205 W_DrawRelief(scr, cPtr->colorView->window, 0, 0,
206 cPtr->colorView->size.width, cPtr->colorView->size.height,
207 WRSunken);
209 if (cPtr->color)
210 WMPaintColorSwatch(cPtr->color, cPtr->colorView->window,
211 2, 2, cPtr->colorView->size.width-4,
212 cPtr->colorView->size.height-4);
217 static void
218 handleEvents(XEvent *event, void *data)
220 ColorWell *cPtr = (ColorWell*)data;
222 CHECK_CLASS(data, WC_ColorWell);
225 switch (event->type) {
226 case Expose:
227 if (event->xexpose.count!=0)
228 break;
229 paintColorWell(cPtr);
230 break;
232 case DestroyNotify:
233 destroyColorWell(cPtr);
234 break;
240 static WMPixmap*
241 makeDragPixmap(WMColorWell *cPtr)
243 WMScreen *scr = cPtr->view->screen;
244 Pixmap pix;
246 pix = XCreatePixmap(scr->display, W_DRAWABLE(scr), 16, 16, scr->depth);
248 XFillRectangle(scr->display, pix, WMColorGC(cPtr->color), 0, 0, 15, 15);
250 XDrawRectangle(scr->display, pix, WMColorGC(scr->black), 0, 0, 15, 15);
252 return WMCreatePixmapFromXPixmaps(scr, pix, None, 16, 16, scr->depth);
256 static void
257 slideView(WMView *view, int srcX, int srcY, int dstX, int dstY)
259 double x, y, dx, dy;
260 int i;
262 srcX -= 8;
263 srcY -= 8;
264 dstX -= 8;
265 dstY -= 8;
267 x = srcX;
268 y = srcY;
270 dx = (double)(dstX-srcX)/20.0;
271 dy = (double)(dstY-srcY)/20.0;
273 for (i = 0; i < 20; i++) {
274 W_MoveView(view, x, y);
275 XFlush(view->screen->display);
277 x += dx;
278 y += dy;
283 static void
284 dragColor(ColorWell *cPtr, XEvent *event, WMPixmap *image)
286 WMView *dragView;
287 WMScreen *scr = cPtr->view->screen;
288 Display *dpy = scr->display;
289 XColor black = {0, 0,0,0, DoRed|DoGreen|DoBlue};
290 XColor green = {0, 0x4500,0xb000,0x4500, DoRed|DoGreen|DoBlue};
291 XColor back = {0, 0xffff,0xffff,0xffff, DoRed|DoGreen|DoBlue};
292 Bool done = False;
293 WMColorWell *activeWell = NULL;
295 dragView = W_CreateTopView(scr);
297 W_ResizeView(dragView, 16, 16);
298 dragView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
299 dragView->attribs.event_mask = StructureNotifyMask;
300 dragView->attribs.override_redirect = True;
301 dragView->attribs.save_under = True;
303 W_MoveView(dragView, event->xmotion.x_root-8, event->xmotion.y_root-8);
305 W_RealizeView(dragView);
307 W_MapView(dragView);
309 XSetWindowBackgroundPixmap(dpy, dragView->window, WMGetPixmapXID(image));
310 XClearWindow(dpy, dragView->window);
313 XGrabPointer(dpy, dragView->window, True,
314 ButtonMotionMask|ButtonReleaseMask|EnterWindowMask,
315 GrabModeSync, GrabModeAsync,
316 scr->rootWin, scr->defaultCursor, CurrentTime);
318 while (!done) {
319 XEvent ev;
320 WMView *view;
322 XAllowEvents(dpy, SyncPointer, CurrentTime);
323 WMNextEvent(dpy, &ev);
325 switch (ev.type) {
326 case ButtonRelease:
327 if (activeWell != NULL) {
328 WMSetColorWellColor(activeWell, cPtr->color);
329 WMPostNotificationName(WMColorWellDidChangeNotification,
330 activeWell, NULL);
331 } else {
332 slideView(dragView, ev.xbutton.x_root, ev.xbutton.y_root,
333 event->xmotion.x_root, event->xmotion.y_root);
336 done = True;
337 break;
339 case EnterNotify:
340 view = W_GetViewForXWindow(dpy, ev.xcrossing.window);
342 if (view && view->self && W_CLASS(view->self) == WC_ColorWell
343 && view->self != activeWell && view->self != cPtr) {
345 activeWell = view->self;
346 XRecolorCursor(dpy, scr->defaultCursor, &green, &back);
347 } else if (view->self!=NULL && view->self != activeWell) {
348 XRecolorCursor(dpy, scr->defaultCursor, &black, &back);
349 activeWell = NULL;
351 break;
353 case MotionNotify:
354 W_MoveView(dragView, ev.xmotion.x_root-8, ev.xmotion.y_root-8);
355 break;
357 default:
358 WMHandleEvent(&ev);
359 break;
362 XUngrabPointer(dpy, CurrentTime);
363 XRecolorCursor(dpy, scr->defaultCursor, &black, &back);
365 W_DestroyView(dragView);
369 static void
370 handleDragEvents(XEvent *event, void *data)
372 WMColorWell *cPtr = (ColorWell*)data;
374 switch (event->type) {
375 case ButtonPress:
376 if (event->xbutton.button == Button1) {
377 cPtr->ipoint.x = event->xbutton.x;
378 cPtr->ipoint.y = event->xbutton.y;
380 break;
382 case MotionNotify:
383 if (event->xmotion.state & Button1Mask) {
384 if (abs(cPtr->ipoint.x - event->xmotion.x) > 4
385 || abs(cPtr->ipoint.y - event->xmotion.y) > 4) {
386 WMSize offs;
387 WMPixmap *pixmap;
389 offs.width = 2;
390 offs.height = 2;
391 pixmap = makeDragPixmap(cPtr);
394 WMDragImageFromView(cPtr->view, pixmap, cPtr->view->pos,
395 offs, event, True);
396 * */
398 dragColor(cPtr, event, pixmap);
400 WMReleasePixmap(pixmap);
403 break;
409 static void
410 handleActionEvents(XEvent *event, void *data)
412 WMColorWell *cPtr = (ColorWell*)data;
413 WMScreen *scr = WMWidgetScreen(cPtr);
414 WMColorPanel *cpanel;
416 if (cPtr->flags.active)
417 W_SetViewBackgroundColor(cPtr->view, scr->gray);
418 else
419 W_SetViewBackgroundColor(cPtr->view, scr->white);
420 paintColorWell(cPtr);
422 cPtr->flags.active ^= 1;
424 if (cPtr->flags.active) {
425 WMPostNotificationName(_ColorWellActivatedNotification, cPtr, NULL);
428 cpanel = WMGetColorPanel(scr);
429 if (cPtr->color)
430 WMSetColorPanelColor(cpanel, cPtr->color);
431 WMShowColorPanel(cpanel);
435 char *t;
436 WMColor *color;
438 t = WMRunInputPanel(scr, NULL, "Advanced Color Picker",
439 "Type a Color (this is temporary!!! I'm not THAT dumb :P)",
440 NULL, "OK", "Cancel");
442 if (t) {
443 color = WMCreateNamedColor(scr, t, False);
444 if (color) {
445 WMSetColorWellColor(cPtr, color);
446 WMPostNotificationName(WMColorWellDidChangeNotification,
447 cPtr, NULL);
448 WMReleaseColor(color);
450 free(t);
457 static void
458 destroyColorWell(ColorWell *cPtr)
460 WMRemoveNotificationObserver(cPtr);
462 if (cPtr->color)
463 WMReleaseColor(cPtr->color);
465 free(cPtr);