8 typedef struct W_ColorWell
{
22 unsigned int active
:1;
23 unsigned int bordered
:1;
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
= {
52 static WMDragSourceProcs dragProcs
= {
57 #define DEFAULT_WIDTH 60
58 #define DEFAULT_HEIGHT 30
59 #define DEFAULT_BORDER_WIDTH 6
67 activatedObserver(void *data
, WMNotification
*notification
)
69 WMColorWell
*cPtr
= (WMColorWell
*)data
;
71 if (!cPtr
->flags
.active
|| WMGetNotificationObject(notification
) == cPtr
)
74 W_SetViewBackgroundColor(cPtr
->view
, WMWidgetScreen(cPtr
)->gray
);
77 cPtr
->flags
.active
= 0;
82 WMCreateColorWell(WMWidget
*parent
)
86 cPtr
= wmalloc(sizeof(ColorWell
));
87 memset(cPtr
, 0, sizeof(ColorWell
));
89 cPtr
->widgetClass
= WC_ColorWell
;
91 cPtr
->view
= W_CreateView(W_VIEW(parent
));
96 cPtr
->view
->self
= cPtr
;
98 cPtr
->colorView
= W_CreateView(cPtr
->view
);
99 if (!cPtr
->colorView
) {
100 W_DestroyView(cPtr
->view
);
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
,
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
));
133 WMSetColorWellColor(WMColorWell
*cPtr
, WMColor
*color
)
136 WMReleaseColor(cPtr
->color
);
138 cPtr
->color
= WMRetainColor(color
);
140 if (cPtr
->colorView
->flags
.realized
&& cPtr
->colorView
->flags
.mapped
)
141 paintColorWell(cPtr
);
146 WMGetColorWellColor(WMColorWell
*cPtr
)
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))
165 resizeColorWell(WMColorWell
*cPtr
, unsigned int width
, unsigned int height
)
169 if (cPtr
->flags
.bordered
) {
171 if (width
< MIN_WIDTH
)
173 if (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
);
185 W_ResizeView(cPtr
->view
, width
, height
);
187 W_ResizeView(cPtr
->colorView
, width
, height
);
189 W_MoveView(cPtr
->colorView
, 0, 0);
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
,
207 WMPaintColorSwatch(cPtr
->color
, cPtr
->colorView
->window
,
208 2, 2, cPtr
->colorView
->size
.width
-4,
209 cPtr
->colorView
->size
.height
-4);
215 handleEvents(XEvent
*event
, void *data
)
217 ColorWell
*cPtr
= (ColorWell
*)data
;
219 CHECK_CLASS(data
, WC_ColorWell
);
222 switch (event
->type
) {
224 if (event
->xexpose
.count
!=0)
226 paintColorWell(cPtr
);
230 destroyColorWell(cPtr
);
238 makeDragPixmap(WMColorWell
*cPtr
)
240 WMScreen
*scr
= cPtr
->view
->screen
;
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
);
254 slideView(WMView
*view
, int srcX
, int srcY
, int dstX
, int dstY
)
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
);
281 dragColor(ColorWell
*cPtr
, XEvent
*event
, WMPixmap
*image
)
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
};
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
);
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
);
319 XAllowEvents(dpy
, SyncPointer
, CurrentTime
);
320 WMNextEvent(dpy
, &ev
);
324 if (activeWell
!= NULL
) {
325 WMSetColorWellColor(activeWell
, cPtr
->color
);
327 slideView(dragView
, ev
.xbutton
.x_root
, ev
.xbutton
.y_root
,
328 event
->xmotion
.x_root
, event
->xmotion
.y_root
);
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
);
349 W_MoveView(dragView
, ev
.xmotion
.x_root
-8, ev
.xmotion
.y_root
-8);
357 XUngrabPointer(dpy
, CurrentTime
);
358 XRecolorCursor(dpy
, scr
->defaultCursor
, &black
, &back
);
360 W_DestroyView(dragView
);
365 handleDragEvents(XEvent
*event
, void *data
)
367 WMColorWell
*cPtr
= (ColorWell
*)data
;
369 switch (event
->type
) {
371 if (event
->xbutton
.button
== Button1
) {
372 cPtr
->ipoint
.x
= event
->xbutton
.x
;
373 cPtr
->ipoint
.y
= event
->xbutton
.y
;
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) {
386 pixmap
= makeDragPixmap(cPtr
);
389 WMDragImageFromView(cPtr->view, pixmap, cPtr->view->pos,
393 dragColor(cPtr
, event
, pixmap
);
395 WMReleasePixmap(pixmap
);
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
);
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);
425 WMSetColorPanelColor(cpanel, cPtr->color);
426 WMShowColorPanel(cpanel);
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");
438 color
= WMCreateNamedColor(scr
, t
, False
);
440 WMSetColorWellColor(cPtr
, color
);
441 WMReleaseColor(color
);
451 destroyColorWell(ColorWell
*cPtr
)
453 WMRemoveNotificationObserver(cPtr
);
456 WMReleaseColor(cPtr
->color
);