2 /* WMRuler: nifty ruler widget for WINGs (OK, for WMText ;-) */
3 /* Copyleft (>) 1999, 2000 Nwanua Elumeze <nwanua@colorado.edu> */
12 #define DEFAULT_X_OFFSET 22
13 #define MIN_DOC_WIDTH 200
14 #define DEFAULT_RULER_WIDTH 240
15 #define DEFAULT_RULER_HEIGHT 40
18 /* a pixel is defined here as 1/8 of an "inch" */
19 /* an "inch" is not the British unit inch... just so you know :-P */
21 typedef struct W_Ruler
{
28 WMAction
*action
, *moveaction
;
31 int left
, body
, first
, right
, dleft
;
40 unsigned int showtabs
:1;
41 unsigned int buttonPressed
:1;
48 resizeRuler(W_ViewDelegate
*self
, WMView
*view
)
50 Ruler
*rPtr
= (Ruler
*)view
->self
;
52 CHECK_CLASS(rPtr
, WC_Ruler
);
54 W_ResizeView(rPtr
->view
, view
->size
.width
,
55 DEFAULT_RULER_HEIGHT
); /* more like DEFACTO_RULER_HEIGHT ;-) */
57 rPtr
->end
= view
->size
.width
;
58 rPtr
->margins
.right
= view
->size
.width
;
62 W_ViewDelegate _RulerViewDelegate
=
72 paintRuler(Ruler
*rPtr
)
81 CHECK_CLASS(rPtr
, WC_Ruler
);
83 if(!rPtr
->view
->flags
.mapped
)
86 gc
= WMColorGC(WMBlackColor(rPtr
->view
->screen
));
87 font
= WMSystemFontOfSize(rPtr
->view
->screen
, 8);
90 WMDrawString(rPtr
->view
->screen
, rPtr
->view
->window
, gc
,
91 font
, rPtr
->margins
.dleft
+2, 25, "0 inches", 10);
95 for(i
=80; i
<rPtr
->view
->size
.width
; i
+=80) {
97 snprintf(c
,3,"%d",++j
);
99 snprintf(c
,3,"%2d",++j
);
100 WMDrawString(rPtr
->view
->screen
, rPtr
->view
->window
, gc
,
101 font
, rPtr
->margins
.dleft
+2+i
, 25, c
, 2);
104 if(rPtr
->flags
.showtabs
){
110 for(i
=0; i
<rPtr
->view
->size
.width
; i
+=40) {
111 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->view
->window
,
112 gc
, rPtr
->margins
.dleft
+i
, 21, rPtr
->margins
.dleft
+i
, 31);
114 if(rPtr
->flags
.showtabs
){
115 points
[0].x
= rPtr
->margins
.dleft
+i
+40;
116 points
[1].x
= points
[0].x
+6;
117 points
[2].x
= points
[0].x
;
118 XFillPolygon (rPtr
->view
->screen
->display
, rPtr
->view
->window
,
119 WMColorGC(WMDarkGrayColor(rPtr
->view
->screen
)),
120 points
, 3, Convex
, CoordModeOrigin
);
122 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->view
->window
,
123 WMColorGC(WMDarkGrayColor(rPtr
->view
->screen
)),
124 rPtr
->margins
.dleft
+i
, 18, rPtr
->margins
.dleft
+i
, 21);
128 for(i
=0; i
<rPtr
->view
->size
.width
; i
+=20)
129 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->view
->window
,
130 gc
, rPtr
->margins
.dleft
+i
, 21, rPtr
->margins
.dleft
+i
, 27);
132 for(i
=0; i
<rPtr
->view
->size
.width
-20; i
+=10)
133 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->view
->window
,
134 gc
, rPtr
->margins
.dleft
+i
, 21, rPtr
->margins
.dleft
+i
, 24);
136 /* guide the end marker in future drawings till next resize */
140 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->view
->window
,
141 gc
, rPtr
->margins
.dleft
, 21, rPtr
->margins
.left
+i
-10, 21);
144 /* Marker for right margin
152 xpos
= rPtr
->margins
.right
;
153 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->view
->window
,
154 WMColorGC(WMDarkGrayColor(rPtr
->view
->screen
)), xpos
, 10, xpos
, 20);
156 points
[0].x
= xpos
+1;
158 points
[1].x
= points
[0].x
-6;
160 points
[2].x
= points
[0].x
-6;
162 points
[3].x
= points
[0].x
;
164 XFillPolygon (rPtr
->view
->screen
->display
, rPtr
->view
->window
,
165 gc
, points
, 4, Convex
, CoordModeOrigin
);
168 /* Marker for left margin
176 xpos
= rPtr
->margins
.left
;
177 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->view
->window
,
178 WMColorGC(WMDarkGrayColor(rPtr
->view
->screen
)), xpos
, 10, xpos
, 20);
182 points
[1].x
= points
[0].x
+6;
184 points
[2].x
= points
[0].x
+6;
186 points
[3].x
= points
[0].x
;
188 XFillPolygon (rPtr
->view
->screen
->display
, rPtr
->view
->window
,
189 gc
, points
, 4, Convex
, CoordModeOrigin
);
194 /* Marker for first line only
201 xpos
= rPtr
->margins
.first
+ rPtr
->margins
.dleft
;
202 XFillRectangle(rPtr
->view
->screen
->display
, rPtr
->view
->window
,
203 gc
, xpos
-5, 7, 11, 5);
205 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->view
->window
,
206 gc
, xpos
, 10, xpos
, 20);
209 /* Marker for rest of body
215 xpos
= rPtr
->margins
.body
+ rPtr
->margins
.dleft
;
216 points
[0].x
= xpos
-5;
218 points
[1].x
= points
[0].x
+11;
220 points
[2].x
= points
[0].x
+5;
222 XFillPolygon (rPtr
->view
->screen
->display
, rPtr
->view
->window
,
223 gc
, points
, 3, Convex
, CoordModeOrigin
);
226 if(!rPtr
->flags
.buttonPressed
)
229 /* actual_x is used as a shortcut is all... */
230 switch(rPtr
->which_marker
){
231 case WRulerLeft
: actual_x
= rPtr
->margins
.left
; break;
233 actual_x
= rPtr
->margins
.body
+ rPtr
->margins
.dleft
;
236 actual_x
= rPtr
->margins
.first
+ rPtr
->margins
.dleft
;
238 case WRulerRight
: actual_x
= rPtr
->margins
.right
; break;
243 gc
= WMColorGC(WMDarkGrayColor(rPtr
->view
->screen
)),
245 XSetLineAttributes(rPtr
->view
->screen
->display
, gc
, 1,
246 LineOnOffDash
, CapNotLast
, JoinMiter
);
248 XDrawLine(rPtr
->pview
->screen
->display
, rPtr
->pview
->window
,
249 gc
, actual_x
+1, 45, actual_x
+1, rPtr
->pview
->size
.height
-5);
251 XSetLineAttributes(rPtr
->view
->screen
->display
, gc
, 1,
252 LineSolid
, CapNotLast
, JoinMiter
);
258 whichMarker(Ruler
*rPtr
, int x
, int y
)
260 CHECK_CLASS(rPtr
, WC_Ruler
);
268 if( rPtr
->margins
.dleft
-x
>= -6 && y
<= 9 &&
269 rPtr
->margins
.dleft
-x
<=0 && y
>=4)
272 if( rPtr
->margins
.right
-x
>= -1 && y
<= 11 &&
273 rPtr
->margins
.right
-x
<=5 && y
>=4)
276 x
-= rPtr
->margins
.dleft
;
280 if( rPtr
->margins
.first
-x
<= 4 && y
<=12 &&
281 rPtr
->margins
.first
-x
>= -5 && y
>=5)
286 if( rPtr
->margins
.body
-x
<= 4 && y
<=19 &&
287 rPtr
->margins
.body
-x
>= -5 && y
>=15)
291 /* both first and body? */
292 if( rPtr
->margins
.first
-x
<= 4 && rPtr
->margins
.first
-x
>= -5
293 && rPtr
->margins
.body
-x
<= 4 && rPtr
->margins
.body
-x
>= -5
301 verifyMarkerMove(Ruler
*rPtr
, int x
)
306 switch(rPtr
->which_marker
){
308 if(x
< rPtr
->margins
.right
-MIN_DOC_WIDTH
&&
309 rPtr
->margins
.body
+ x
<= rPtr
->margins
.right
-MIN_DOC_WIDTH
&&
310 rPtr
->margins
.first
+ x
<= rPtr
->margins
.right
-MIN_DOC_WIDTH
)
311 rPtr
->margins
.left
= x
;
317 if(x
< rPtr
->margins
.right
-MIN_DOC_WIDTH
&& x
>= rPtr
->margins
.left
)
318 rPtr
->margins
.body
= x
- rPtr
->margins
.dleft
;
323 if(x
< rPtr
->margins
.right
-MIN_DOC_WIDTH
&& x
>= rPtr
->margins
.left
)
324 rPtr
->margins
.first
= x
- rPtr
->margins
.dleft
;
329 if( x
>= rPtr
->margins
.first
+MIN_DOC_WIDTH
&&
330 x
>= rPtr
->margins
.body
+MIN_DOC_WIDTH
&&
331 x
>= rPtr
->margins
.left
+MIN_DOC_WIDTH
&&
333 rPtr
->margins
.right
= x
;
338 if( x
< rPtr
->margins
.right
-MIN_DOC_WIDTH
&& x
>= rPtr
->margins
.left
) {
339 rPtr
->margins
.first
= x
- rPtr
->margins
.dleft
;
340 rPtr
->margins
.body
= x
- rPtr
->margins
.dleft
;
344 default : return False
;
352 moveMarker(Ruler
*rPtr
, int x
)
355 CHECK_CLASS(rPtr
, WC_Ruler
);
357 if(x
< rPtr
->offset
|| x
> rPtr
->end
)
360 /* restrictive ticks */
365 if(!verifyMarkerMove(rPtr
, x
))
368 /* clear around the motion area */
370 XClearWindow(rPtr
->view
->screen
->display
, rPtr
->view
->window
);
373 XClearArea(rPtr
->view
->screen
->display
, rPtr
->view
->window
,
374 x
-10, 3, 20, rPtr
->view
->size
.height
-4, False
);
380 if (QLength(rPtr
->view
->screen
->display
) > 0 ) {
382 while(QLength(rPtr
->view
->screen
->display
) > 0 ) {
383 XNextEvent(rPtr
->view
->screen
->display
, event
);
384 if(event
->type
== MotionNotify
||
385 event
->type
== ButtonRelease
)
397 (rPtr
->moveaction
)(rPtr
, rPtr
->clientData
);
403 handleEvents(XEvent
*event
, void *data
)
405 Ruler
*rPtr
= (Ruler
*)data
;
407 CHECK_CLASS(rPtr
, WC_Ruler
);
410 switch (event
->type
) {
413 if(event
->xexpose
.count
)
415 if(rPtr
->view
->flags
.realized
)
420 if(event
->xbutton
.button
!= Button1
)
423 rPtr
->flags
.buttonPressed
= True
;
425 whichMarker(rPtr
, event
->xmotion
.x
,
429 /* clear around the clicked area */
430 if(rPtr
->which_marker
>=0 && rPtr
->which_marker
<= 4) {
432 XClearArea(rPtr
->view
->screen
->display
, rPtr
->view
->window
,
433 WMGetRulerMargin(rPtr
, rPtr
->which_marker
)-10, 2, 20, 21, True
);
442 if(event
->xbutton
.button
!= Button1
)
445 rPtr
->flags
.buttonPressed
= False
;
446 rPtr
->pressed
= event
->xmotion
.x
;
447 if(rPtr
->which_marker
== 0) {
448 rPtr
->margins
.dleft
= rPtr
->margins
.left
;
450 /* clear entire (moved) ruler */
451 XClearArea(rPtr
->view
->screen
->display
,
452 rPtr
->view
->window
, 0, 0, rPtr
->view
->size
.width
,
453 rPtr
->view
->size
.height
, True
);
457 (rPtr
->action
)(rPtr
, rPtr
->clientData
);
463 if(rPtr
->flags
.buttonPressed
&&
464 (event
->xmotion
.state
& Button1Mask
)) {
465 moveMarker(rPtr
, event
->xmotion
.x
);
474 WMCreateRuler(WMWidget
*parent
)
476 Ruler
*rPtr
= wmalloc(sizeof(Ruler
));
478 memset(rPtr
, 0, sizeof(Ruler
));
480 rPtr
->widgetClass
= WC_Ruler
;
482 rPtr
->view
= W_CreateView(W_VIEW(parent
));
487 rPtr
->view
->self
= rPtr
;
489 W_ResizeView(rPtr
->view
, DEFAULT_RULER_WIDTH
, DEFAULT_RULER_HEIGHT
);
491 WMCreateEventHandler(rPtr
->view
, ExposureMask
|StructureNotifyMask
492 |EnterWindowMask
|LeaveWindowMask
|FocusChangeMask
493 |ButtonReleaseMask
|ButtonPressMask
|KeyReleaseMask
494 |KeyPressMask
|Button1MotionMask
, handleEvents
, rPtr
);
496 rPtr
->view
->delegate
= &_RulerViewDelegate
;
498 rPtr
->which_marker
= WRulerLeft
; /* none */
502 rPtr
->offset
= DEFAULT_X_OFFSET
;
503 rPtr
->margins
.left
= DEFAULT_X_OFFSET
;
504 rPtr
->margins
.dleft
= DEFAULT_X_OFFSET
;
505 rPtr
->margins
.body
= 0; /* relative */
506 rPtr
->margins
.first
= 0; /* relative */
507 rPtr
->margins
.right
= 300+DEFAULT_X_OFFSET
;
508 rPtr
->end
= 320+DEFAULT_X_OFFSET
;
510 rPtr
->flags
.showtabs
= False
;
511 rPtr
->flags
.buttonPressed
= False
;
513 rPtr
->pview
= W_VIEW(parent
);
520 WMShowRulerTabs(WMRuler
*rPtr
, Bool show
)
524 CHECK_CLASS(rPtr
, WC_Ruler
);
525 rPtr
->flags
.showtabs
= show
;
529 WMSetRulerMargin(WMRuler
*rPtr
, int which
, int pixels
)
535 if(pixels
<rPtr
->offset
)
536 pixels
= rPtr
->offset
;
538 rPtr
->which_marker
= which
;
539 if(!verifyMarkerMove(rPtr
, pixels
))
542 rPtr
->pressed
= pixels
;
543 if(which
== WRulerLeft
)
544 rPtr
->margins
.dleft
= rPtr
->margins
.left
;
546 if(!rPtr
->view
->flags
.realized
)
549 XClearArea(rPtr
->view
->screen
->display
,
550 rPtr
->view
->window
, 0, 0, rPtr
->view
->size
.width
,
551 rPtr
->view
->size
.height
, True
);
557 WMGetRulerMargin(WMRuler
*rPtr
, int which
)
562 CHECK_CLASS(rPtr
, WC_Ruler
);
565 case WRulerLeft
: return rPtr
->margins
.left
; break;
566 case WRulerBody
: return rPtr
->margins
.body
; break;
567 case WRulerFirst
: return rPtr
->margins
.first
; break;
568 case WRulerRight
: return rPtr
->margins
.right
; break;
569 case WRulerBoth
: return rPtr
->margins
.body
; break;
570 case WRulerDocLeft
: return rPtr
->margins
.dleft
; break;
571 default: return rPtr
->margins
.dleft
;
575 /* _which_ one was released */
577 WMGetReleasedRulerMargin(WMRuler
*rPtr
)
581 CHECK_CLASS(rPtr
, WC_Ruler
);
582 if(rPtr
->which_marker
!= -1)
583 return rPtr
->which_marker
;
588 /* _which_ one is being grabbed */
590 WMGetGrabbedRulerMargin(WMRuler
*rPtr
)
594 CHECK_CLASS(rPtr
, WC_Ruler
);
595 if(rPtr
->which_marker
!= -1)
596 return rPtr
->which_marker
;
604 WMSetRulerOffset(WMRuler
*rPtr
, int pixels
)
606 if(!rPtr
|| pixels
<0)
608 CHECK_CLASS(rPtr
, WC_Ruler
);
609 rPtr
->offset
= pixels
;
613 WMGetRulerOffset(WMRuler
*rPtr
)
617 CHECK_CLASS(rPtr
, WC_Ruler
);
623 WMSetRulerAction(WMRuler
*rPtr
, WMAction
*action
, void *clientData
)
628 CHECK_CLASS(rPtr
, WC_Ruler
);
629 rPtr
->action
= action
;
630 rPtr
->clientData
= clientData
;
634 WMSetRulerMoveAction(WMRuler
*rPtr
, WMAction
*moveaction
, void *clientData
)
639 CHECK_CLASS(rPtr
, WC_Ruler
);
640 rPtr
->moveaction
= moveaction
;
641 rPtr
->clientData
= clientData
;