1 /* WMRuler: nifty ruler widget for WINGs (OK, for WMText ;-) */
2 /* Copyleft (>) 1999, 2000 Nwanua Elumeze <nwanua@colorado.edu> */
7 #define MIN_DOC_WIDTH 10
9 typedef struct W_Ruler
{
12 W_View
*pview
; /* the parent's view (for drawing the line) */
14 WMAction
*moveAction
; /* what to when while moving */
15 WMAction
*releaseAction
; /* what to do when released */
20 WMRulerMargins margins
;
22 int motion
; /* the position of the _moving_ marker(s) */
23 int end
; /* the last tick on the baseline (restrict markers to it) */
28 unsigned int buttonPressed
:1;
29 /* 0, 1, 2, 3, 4, 5, 6 */
30 unsigned int whichMarker
:3; /* none, left, right, first, body, tabstop, both */
31 unsigned int RESERVED
:28;
37 /* Marker for left margin
47 drawLeftMarker(Ruler
*rPtr
)
50 int xpos
= (rPtr
->flags
.whichMarker
==1?
51 rPtr
->motion
:rPtr
->margins
.left
);
53 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
54 rPtr
->fg
, xpos
, 8, xpos
, 22);
57 points
[1].x
= points
[0].x
+6;
59 points
[2].x
= points
[0].x
+6;
61 points
[3].x
= points
[0].x
;
63 XFillPolygon (rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
64 rPtr
->fg
, points
, 4, Convex
, CoordModeOrigin
);
68 /* Marker for right margin
78 drawRightMarker(Ruler
*rPtr
)
81 int xpos
= (rPtr
->flags
.whichMarker
==2?
82 rPtr
->motion
:rPtr
->margins
.right
);
84 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
85 rPtr
->fg
, xpos
, 8, xpos
, 22);
88 points
[1].x
= points
[0].x
-6;
90 points
[2].x
= points
[0].x
-6;
92 points
[3].x
= points
[0].x
;
94 XFillPolygon (rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
95 rPtr
->fg
, points
, 4, Convex
, CoordModeOrigin
);
99 /* Marker for first line only
106 drawFirstMarker(Ruler
*rPtr
)
108 int xpos
= ((rPtr
->flags
.whichMarker
==3 || rPtr
->flags
.whichMarker
==6)?
109 rPtr
->motion
:rPtr
->margins
.first
);
110 XFillRectangle(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
111 rPtr
->fg
, xpos
-5, 10, 11, 5);
112 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
113 rPtr
->fg
, xpos
, 12, xpos
, 22);
116 /* Marker for rest of body
122 drawBodyMarker(Ruler
*rPtr
)
125 int xpos
= ((rPtr
->flags
.whichMarker
==4 || rPtr
->flags
.whichMarker
==6)?
126 rPtr
->motion
:rPtr
->margins
.body
);
127 points
[0].x
= xpos
-5;
129 points
[1].x
= points
[0].x
+11;
131 points
[2].x
= points
[0].x
+5;
133 XFillPolygon (rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
134 rPtr
->fg
, points
, 3, Convex
, CoordModeOrigin
);
139 createDrawBuffer(Ruler
*rPtr
)
142 XFreePixmap(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
);
143 rPtr
->drawBuffer
= XCreatePixmap(rPtr
->view
->screen
->display
,
144 rPtr
->view
->window
, rPtr
->view
->size
.width
, 40,
145 rPtr
->view
->screen
->depth
);
146 XFillRectangle(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
147 rPtr
->bg
, 0, 0, rPtr
->view
->size
.width
, 40);
152 drawRulerOnPixmap(Ruler
*rPtr
)
156 int marks
[9] = {11, 3, 5, 3, 7, 3, 5, 3};
158 if(!rPtr
->drawBuffer
)
159 createDrawBuffer(rPtr
);
161 XFillRectangle(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
162 rPtr
->bg
, 0, 0, rPtr
->view
->size
.width
, 40);
164 WMDrawString(rPtr
->view
->screen
, rPtr
->drawBuffer
, rPtr
->fg
,
165 rPtr
->font
, rPtr
->margins
.left
+2, 26, "0 inches", 10);
169 w
= rPtr
->view
->size
.width
- rPtr
->margins
.left
;
171 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
172 rPtr
->fg
, rPtr
->margins
.left
+m
, 23,
173 rPtr
->margins
.left
+m
, marks
[i
%8]+23);
176 snprintf(c
,3,"%d",++j
);
178 snprintf(c
,3,"%2d",++j
);
179 WMDrawString(rPtr
->view
->screen
, rPtr
->drawBuffer
, rPtr
->fg
,
180 rPtr
->font
, rPtr
->margins
.left
+2+m
, 26, c
, 2);
185 rPtr
->end
= rPtr
->margins
.left
+m
-10;
186 if(rPtr
->margins
.right
> rPtr
->end
)
187 rPtr
->margins
.right
= rPtr
->end
;
189 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
, rPtr
->fg
,
190 rPtr
->margins
.left
, 22, rPtr
->margins
.left
+m
-10, 22);
192 drawLeftMarker(rPtr
);
193 drawRightMarker(rPtr
);
194 drawFirstMarker(rPtr
);
195 drawBodyMarker(rPtr
);
200 paintRuler(Ruler
*rPtr
)
202 WMScreen
*screen
= rPtr
->view
->screen
;
203 if(1||!rPtr
->drawBuffer
) {
204 drawRulerOnPixmap(rPtr
);
207 XCopyArea(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
208 rPtr
->view
->window
, rPtr
->bg
, 0, 0, rPtr
->view
->size
.width
, 40,
214 verifyMarkerMove(Ruler
*rPtr
, int x
)
216 if(rPtr
->flags
.whichMarker
<1 || rPtr
->flags
.whichMarker
>6)
219 switch(rPtr
->flags
.whichMarker
) {
221 if(x
> rPtr
->margins
.right
- 10 || x
< rPtr
->offset
||
222 rPtr
->margins
.body
+ x
> rPtr
->margins
.right
-MIN_DOC_WIDTH
||
223 rPtr
->margins
.first
+ x
> rPtr
->margins
.right
-MIN_DOC_WIDTH
)
228 if(x
< rPtr
->margins
.first
+MIN_DOC_WIDTH
||
229 x
< rPtr
->margins
.body
+MIN_DOC_WIDTH
||
230 x
< rPtr
->margins
.left
+MIN_DOC_WIDTH
||
231 x
> rPtr
->end
) /*rPtr->view->size.width)*/
236 if(x
>= rPtr
->margins
.right
-MIN_DOC_WIDTH
|| x
< rPtr
->margins
.left
)
241 if(x
>= rPtr
->margins
.right
-MIN_DOC_WIDTH
|| x
< rPtr
->margins
.left
)
246 if(x
>= rPtr
->margins
.right
-MIN_DOC_WIDTH
|| x
< rPtr
->margins
.left
)
260 whichMarker(Ruler
*rPtr
, int x
, int y
)
262 if(x
<rPtr
->offset
|| y
>22)
265 if( rPtr
->margins
.left
-x
>= -6 && y
<= 9
266 && (rPtr
->margins
.left
-x
<=0) && y
>=4) {
267 rPtr
->motion
= rPtr
->margins
.left
;
271 if(rPtr
->margins
.right
-x
>= -1 && y
<= 11
272 && rPtr
->margins
.right
-x
<=5 && y
>=4) {
273 rPtr
->motion
= rPtr
->margins
.right
;
278 /* both first and body? */
279 if( rPtr
->margins
.first
-x
<= 4 && rPtr
->margins
.first
-x
>= -5
280 && rPtr
->margins
.body
-x
<= 4 && rPtr
->margins
.body
-x
>= -5
282 rPtr
->motion
= rPtr
->margins
.first
;
287 if(rPtr
->margins
.first
-x
<= 4 && y
<=15
288 && rPtr
->margins
.first
-x
>= -5 && y
>=10) {
289 rPtr
->motion
= rPtr
->margins
.first
;
293 if( rPtr
->margins
.body
-x
<= 4 && y
<=21 &&
294 rPtr
->margins
.body
-x
>= -5 && y
>=17) {
295 rPtr
->motion
= rPtr
->margins
.body
;
308 handleEvents(XEvent
*event
, void *data
)
310 Ruler
*rPtr
= (Ruler
*)data
;
311 Display
*dpy
= event
->xany
.display
;
313 switch (event
->type
) {
319 if(rPtr
->flags
.buttonPressed
320 && (event
->xmotion
.state
& Button1Mask
)) {
321 if(verifyMarkerMove(rPtr
, event
->xmotion
.x
)){
322 GC gc
= WMColorGC(WMDarkGrayColor(rPtr
->view
->screen
));
325 (rPtr
->moveAction
)(rPtr
, rPtr
->clientData
);
326 XSetLineAttributes(rPtr
->view
->screen
->display
, gc
, 1,
327 LineSolid
, CapNotLast
, JoinMiter
);
328 XDrawLine(rPtr
->pview
->screen
->display
,
330 gc
, rPtr
->motion
+1, 40,
331 rPtr
->motion
+1, rPtr
->pview
->size
.height
-5);
337 if(event
->xbutton
.button
!= Button1
)
339 rPtr
->flags
.buttonPressed
= True
;
340 rPtr
->flags
.whichMarker
=
341 whichMarker(rPtr
, event
->xmotion
.x
,
346 if(event
->xbutton
.button
!= Button1
)
348 rPtr
->flags
.buttonPressed
= False
;
349 switch(rPtr
->flags
.whichMarker
) {
351 int change
= rPtr
->margins
.left
-rPtr
->motion
;
352 rPtr
->margins
.first
-=change
;
353 rPtr
->margins
.body
-= change
;
354 rPtr
->margins
.left
= rPtr
->motion
;
355 paintRuler(rPtr
); break;
357 case 2: rPtr
->margins
.right
= rPtr
->motion
; break;
358 case 3: rPtr
->margins
.first
= rPtr
->motion
; break;
359 case 4: rPtr
->margins
.body
= rPtr
->motion
; break;
360 case 6: rPtr
->margins
.first
= rPtr
->margins
.body
361 = rPtr
->motion
; break;
363 if(rPtr
->releaseAction
)
364 (rPtr
->releaseAction
)(rPtr
, rPtr
->clientData
);
370 rulerDidResize(W_ViewDelegate
*self
, WMView
*view
)
372 Ruler
*rPtr
= (Ruler
*)view
->self
;
374 createDrawBuffer(rPtr
);
380 W_ViewDelegate _RulerViewDelegate
=
391 WMCreateRuler(WMWidget
*parent
)
393 Ruler
*rPtr
= wmalloc(sizeof(Ruler
));
394 unsigned int w
= WMWidgetWidth(parent
);
396 memset(rPtr
, 0, sizeof(Ruler
));
398 rPtr
->widgetClass
= WC_Ruler
;
400 rPtr
->view
= W_CreateView(W_VIEW(parent
));
405 rPtr
->view
->self
= rPtr
;
407 rPtr
->drawBuffer
= (Pixmap
) NULL
;
409 W_ResizeView(rPtr
->view
, w
, 40);
411 WMCreateEventHandler(rPtr
->view
, ExposureMask
|StructureNotifyMask
412 |EnterWindowMask
|LeaveWindowMask
|FocusChangeMask
413 |ButtonReleaseMask
|ButtonPressMask
|KeyReleaseMask
414 |KeyPressMask
|Button1MotionMask
, handleEvents
, rPtr
);
416 rPtr
->view
->delegate
= &_RulerViewDelegate
;
418 rPtr
->bg
= WMColorGC(WMGrayColor(rPtr
->view
->screen
));
419 rPtr
->fg
= WMColorGC(WMBlackColor(rPtr
->view
->screen
));
420 rPtr
->font
= WMSystemFontOfSize(rPtr
->view
->screen
, 8);
423 rPtr
->margins
.left
= 22;
424 rPtr
->margins
.body
= 22;
425 rPtr
->margins
.first
= 42;
426 rPtr
->margins
.right
= (w
<502?w
:502);
428 rPtr
->flags
.whichMarker
= 0; /* none */
429 rPtr
->flags
.buttonPressed
= False
;
431 rPtr
->moveAction
= NULL
;
432 rPtr
->releaseAction
= NULL
;
434 rPtr
->pview
= W_VIEW(parent
);
441 WMSetRulerMargins(WMRuler
*rPtr
, WMRulerMargins margins
)
445 rPtr
->margins
.left
= margins
.left
+ rPtr
->offset
;
446 rPtr
->margins
.right
= margins
.right
+ rPtr
->offset
;
447 rPtr
->margins
.first
= margins
.first
+ rPtr
->offset
;
448 rPtr
->margins
.body
= margins
.body
+ rPtr
->offset
;
449 rPtr
->margins
.tabs
= margins
.tabs
; /*for loop*/
456 WMGetRulerMargins(WMRuler
*rPtr
)
458 WMRulerMargins margins
;
463 margins
.left
= rPtr
->margins
.left
- rPtr
->offset
;
464 margins
.right
= rPtr
->margins
.right
- rPtr
->offset
;
465 margins
.first
= rPtr
->margins
.first
- rPtr
->offset
;
466 margins
.body
= rPtr
->margins
.body
- rPtr
->offset
;
468 margins
.tabs
= rPtr
->margins
.tabs
;
470 return rPtr
->margins
;
475 WMSetRulerOffset(WMRuler
*rPtr
, int pixels
)
477 if(!rPtr
|| pixels
<0 || pixels
+MIN_DOC_WIDTH
>=rPtr
->view
->size
.width
)
479 rPtr
->offset
= pixels
;
480 /*rulerDidResize(rPtr, rPtr->view);*/
485 WMGetRulerOffset(WMRuler
*rPtr
)
494 WMSetRulerReleaseAction(WMRuler
*rPtr
, WMAction
*action
, void *clientData
)
499 rPtr
->releaseAction
= action
;
500 rPtr
->clientData
= clientData
;
505 WMSetRulerMoveAction(WMRuler
*rPtr
, WMAction
*action
, void *clientData
)
510 rPtr
->moveAction
= action
;
511 rPtr
->clientData
= clientData
;
515 /* _which_ one was released */
517 WMGetReleasedRulerMargin(WMRuler
*rPtr
)
521 return rPtr
->flags
.whichMarker
;
525 /* _which_ one is being grabbed */
527 WMGetGrabbedRulerMargin(WMRuler
*rPtr
)
531 return rPtr
->flags
.whichMarker
;