Update for 0.51.2-pre2
[wmaker-crm.git] / WINGs / wcolorwell.c
blobbbe3cd8f18616137ab5fc3009f90ac54eec9dd9c
5 #include "WINGsP.h"
8 typedef struct W_ColorWell {
9 W_Class widgetClass;
10 WMView *view;
12 WMView *colorView;
14 WMColor *color;
16 WMAction *action;
17 void *clientData;
19 WMPoint ipoint;
21 struct {
22 unsigned int active:1;
23 unsigned int bordered:1;
24 } flags;
25 } ColorWell;
27 static char *_ColorWellActivatedNotification = "_ColorWellActivatedNotification";
31 static void destroyColorWell(ColorWell *cPtr);
32 static void paintColorWell(ColorWell *cPtr);
34 static void handleEvents(XEvent *event, void *data);
36 static void handleDragEvents(XEvent *event, void *data);
38 static void handleActionEvents(XEvent *event, void *data);
40 static void resizeColorWell();
44 W_ViewProcedureTable _ColorWellViewProcedures = {
45 NULL,
46 resizeColorWell,
47 NULL
51 #if 0
52 static WMDragSourceProcs dragProcs = {
55 #endif
57 #define DEFAULT_WIDTH 60
58 #define DEFAULT_HEIGHT 30
59 #define DEFAULT_BORDER_WIDTH 6
61 #define MIN_WIDTH 16
62 #define MIN_HEIGHT 8
66 static void
67 activatedObserver(void *data, WMNotification *notification)
69 WMColorWell *cPtr = (WMColorWell*)data;
71 if (!cPtr->flags.active || WMGetNotificationObject(notification) == cPtr)
72 return;
74 W_SetViewBackgroundColor(cPtr->view, WMWidgetScreen(cPtr)->gray);
75 paintColorWell(cPtr);
77 cPtr->flags.active = 0;
81 WMColorWell*
82 WMCreateColorWell(WMWidget *parent)
84 ColorWell *cPtr;
86 cPtr = wmalloc(sizeof(ColorWell));
87 memset(cPtr, 0, sizeof(ColorWell));
89 cPtr->widgetClass = WC_ColorWell;
91 cPtr->view = W_CreateView(W_VIEW(parent));
92 if (!cPtr->view) {
93 free(cPtr);
94 return NULL;
96 cPtr->view->self = cPtr;
98 cPtr->colorView = W_CreateView(cPtr->view);
99 if (!cPtr->colorView) {
100 W_DestroyView(cPtr->view);
101 free(cPtr);
102 return NULL;
104 cPtr->colorView->self = cPtr;
106 WMCreateEventHandler(cPtr->view, ExposureMask|StructureNotifyMask
107 |ClientMessageMask, handleEvents, cPtr);
109 WMCreateEventHandler(cPtr->colorView, ExposureMask, handleEvents, cPtr);
111 WMCreateEventHandler(cPtr->colorView, ButtonPressMask|ButtonMotionMask
112 |EnterWindowMask, handleDragEvents, cPtr);
114 WMCreateEventHandler(cPtr->view, ButtonPressMask, handleActionEvents,
115 cPtr);
117 cPtr->colorView->flags.mapWhenRealized = 1;
119 cPtr->flags.bordered = 1;
121 resizeColorWell(cPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
123 WMAddNotificationObserver(activatedObserver, cPtr,
124 _ColorWellActivatedNotification, NULL);
126 cPtr->color = WMBlackColor(WMWidgetScreen(cPtr));
128 return cPtr;
132 void
133 WMSetColorWellColor(WMColorWell *cPtr, WMColor *color)
135 if (cPtr->color)
136 WMReleaseColor(cPtr->color);
138 cPtr->color = WMRetainColor(color);
140 if (cPtr->colorView->flags.realized && cPtr->colorView->flags.mapped)
141 paintColorWell(cPtr);
145 WMColor*
146 WMGetColorWellColor(WMColorWell *cPtr)
148 return cPtr->color;
152 void
153 WSetColorWellBordered(WMColorWell *cPtr, Bool flag)
155 if (cPtr->flags.bordered != flag) {
156 cPtr->flags.bordered = flag;
157 resizeColorWell(cPtr, cPtr->view->size.width, cPtr->view->size.height);
162 #define MIN(a,b) ((a) > (b) ? (b) : (a))
164 static void
165 resizeColorWell(WMColorWell *cPtr, unsigned int width, unsigned int height)
167 int bw;
169 if (cPtr->flags.bordered) {
171 if (width < MIN_WIDTH)
172 width = MIN_WIDTH;
173 if (height < MIN_HEIGHT)
174 height = MIN_HEIGHT;
176 bw = (int)((float)MIN(width, height)*0.24);
178 W_ResizeView(cPtr->view, width, height);
180 W_ResizeView(cPtr->colorView, width-2*bw, height-2*bw);
182 if (cPtr->colorView->pos.x!=bw || cPtr->colorView->pos.y!=bw)
183 W_MoveView(cPtr->colorView, bw, bw);
184 } else {
185 W_ResizeView(cPtr->view, width, height);
187 W_ResizeView(cPtr->colorView, width, height);
189 W_MoveView(cPtr->colorView, 0, 0);
194 static void
195 paintColorWell(ColorWell *cPtr)
197 W_Screen *scr = cPtr->view->screen;
199 W_DrawRelief(scr, cPtr->view->window, 0, 0, cPtr->view->size.width,
200 cPtr->view->size.height, WRRaised);
202 W_DrawRelief(scr, cPtr->colorView->window, 0, 0,
203 cPtr->colorView->size.width, cPtr->colorView->size.height,
204 WRSunken);
206 if (cPtr->color)
207 WMPaintColorSwatch(cPtr->color, cPtr->colorView->window,
208 2, 2, cPtr->colorView->size.width-4,
209 cPtr->colorView->size.height-4);
214 static void
215 handleEvents(XEvent *event, void *data)
217 ColorWell *cPtr = (ColorWell*)data;
219 CHECK_CLASS(data, WC_ColorWell);
222 switch (event->type) {
223 case Expose:
224 if (event->xexpose.count!=0)
225 break;
226 paintColorWell(cPtr);
227 break;
229 case DestroyNotify:
230 destroyColorWell(cPtr);
231 break;
237 static WMPixmap*
238 makeDragPixmap(WMColorWell *cPtr)
240 WMScreen *scr = cPtr->view->screen;
241 Pixmap pix;
243 pix = XCreatePixmap(scr->display, W_DRAWABLE(scr), 16, 16, scr->depth);
245 XFillRectangle(scr->display, pix, WMColorGC(cPtr->color), 0, 0, 15, 15);
247 XDrawRectangle(scr->display, pix, WMColorGC(scr->black), 0, 0, 15, 15);
249 return WMCreatePixmapFromXPixmaps(scr, pix, None, 16, 16, scr->depth);
253 static void
254 slideView(WMView *view, int srcX, int srcY, int dstX, int dstY)
256 double x, y, dx, dy;
257 int i;
259 srcX -= 8;
260 srcY -= 8;
261 dstX -= 8;
262 dstY -= 8;
264 x = srcX;
265 y = srcY;
267 dx = (double)(dstX-srcX)/20.0;
268 dy = (double)(dstY-srcY)/20.0;
270 for (i = 0; i < 20; i++) {
271 W_MoveView(view, x, y);
272 XFlush(view->screen->display);
274 x += dx;
275 y += dy;
280 static void
281 dragColor(ColorWell *cPtr, XEvent *event, WMPixmap *image)
283 WMView *dragView;
284 WMScreen *scr = cPtr->view->screen;
285 Display *dpy = scr->display;
286 XColor black = {0, 0,0,0, DoRed|DoGreen|DoBlue};
287 XColor green = {0, 0x4500,0xb000,0x4500, DoRed|DoGreen|DoBlue};
288 XColor back = {0, 0xffff,0xffff,0xffff, DoRed|DoGreen|DoBlue};
289 Bool done = False;
290 WMColorWell *activeWell = NULL;
292 dragView = W_CreateTopView(scr);
294 W_ResizeView(dragView, 16, 16);
295 dragView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
296 dragView->attribs.event_mask = StructureNotifyMask;
297 dragView->attribs.override_redirect = True;
298 dragView->attribs.save_under = True;
300 W_MoveView(dragView, event->xmotion.x_root-8, event->xmotion.y_root-8);
302 W_RealizeView(dragView);
304 W_MapView(dragView);
306 XSetWindowBackgroundPixmap(dpy, dragView->window, WMGetPixmapXID(image));
307 XClearWindow(dpy, dragView->window);
310 XGrabPointer(dpy, dragView->window, True,
311 ButtonMotionMask|ButtonReleaseMask|EnterWindowMask,
312 GrabModeSync, GrabModeAsync,
313 scr->rootWin, scr->defaultCursor, CurrentTime);
315 while (!done) {
316 XEvent ev;
317 WMView *view;
319 XAllowEvents(dpy, SyncPointer, CurrentTime);
320 WMNextEvent(dpy, &ev);
322 switch (ev.type) {
323 case ButtonRelease:
324 if (activeWell != NULL) {
325 WMSetColorWellColor(activeWell, cPtr->color);
326 } else {
327 slideView(dragView, ev.xbutton.x_root, ev.xbutton.y_root,
328 event->xmotion.x_root, event->xmotion.y_root);
331 done = True;
332 break;
334 case EnterNotify:
335 view = W_GetViewForXWindow(dpy, ev.xcrossing.window);
337 if (view && view->self && W_CLASS(view->self) == WC_ColorWell
338 && view->self != activeWell && view->self != cPtr) {
340 activeWell = view->self;
341 XRecolorCursor(dpy, scr->defaultCursor, &green, &back);
342 } else if (view->self!=NULL && view->self != activeWell) {
343 XRecolorCursor(dpy, scr->defaultCursor, &black, &back);
344 activeWell = NULL;
346 break;
348 case MotionNotify:
349 W_MoveView(dragView, ev.xmotion.x_root-8, ev.xmotion.y_root-8);
350 break;
352 default:
353 WMHandleEvent(&ev);
354 break;
357 XUngrabPointer(dpy, CurrentTime);
358 XRecolorCursor(dpy, scr->defaultCursor, &black, &back);
360 W_DestroyView(dragView);
364 static void
365 handleDragEvents(XEvent *event, void *data)
367 WMColorWell *cPtr = (ColorWell*)data;
369 switch (event->type) {
370 case ButtonPress:
371 if (event->xbutton.button == Button1) {
372 cPtr->ipoint.x = event->xbutton.x;
373 cPtr->ipoint.y = event->xbutton.y;
375 break;
377 case MotionNotify:
378 if (event->xmotion.state & Button1Mask) {
379 if (abs(cPtr->ipoint.x - event->xmotion.x) > 4
380 || abs(cPtr->ipoint.y - event->xmotion.y) > 4) {
381 WMSize offs;
382 WMPixmap *pixmap;
384 offs.width = 2;
385 offs.height = 2;
386 pixmap = makeDragPixmap(cPtr);
389 WMDragImageFromView(cPtr->view, pixmap, cPtr->view->pos,
390 offs, event, True);
391 * */
393 dragColor(cPtr, event, pixmap);
395 WMReleasePixmap(pixmap);
398 break;
404 static void
405 handleActionEvents(XEvent *event, void *data)
407 WMColorWell *cPtr = (ColorWell*)data;
408 WMScreen *scr = WMWidgetScreen(cPtr);
409 WMColorPanel *cpanel;
411 if (cPtr->flags.active)
412 W_SetViewBackgroundColor(cPtr->view, scr->gray);
413 else
414 W_SetViewBackgroundColor(cPtr->view, scr->white);
415 paintColorWell(cPtr);
417 cPtr->flags.active ^= 1;
419 if (cPtr->flags.active) {
420 WMPostNotificationName(_ColorWellActivatedNotification, cPtr, NULL);
423 cpanel = WMGetColorPanel(scr);
424 if (cPtr->color)
425 WMSetColorPanelColor(cpanel, cPtr->color);
426 WMShowColorPanel(cpanel);
430 char *t;
431 WMColor *color;
433 t = WMRunInputPanel(scr, NULL, "Advanced Color Picker",
434 "Type a Color (this is temporary!!! I'm not THAT dumb :P)",
435 NULL, "OK", "Cancel");
437 if (t) {
438 color = WMCreateNamedColor(scr, t, False);
439 if (color) {
440 WMSetColorWellColor(cPtr, color);
441 WMReleaseColor(color);
443 free(t);
450 static void
451 destroyColorWell(ColorWell *cPtr)
453 WMRemoveNotificationObserver(cPtr);
455 if (cPtr->color)
456 WMReleaseColor(cPtr->color);
458 free(cPtr);