2 * WINGs WMRuler: nifty ruler widget for WINGs :-)
4 * Copyright (c) 1999-2000 Nwanua Elumeze
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #define MIN_DOC_WIDTH 10
26 typedef struct W_Ruler
{
29 W_View
*pview
; /* the parent's view (for drawing the line) */
31 WMAction
*moveAction
; /* what to when while moving */
32 WMAction
*releaseAction
; /* what to do when released */
37 WMRulerMargins margins
;
39 int motion
; /* the position of the _moving_ marker(s) */
40 int end
; /* the last tick on the baseline (restrict markers to it) */
45 unsigned int whichMarker
:3;
46 /* 0, 1, 2, 3, 4, 5, 6 */
47 /* none, left, right, first, body, tabstop, first & body */
49 unsigned int buttonPressed
:1;
50 unsigned int redraw
:1;
51 unsigned int RESERVED
:27;
57 /* Marker for left margin
67 drawLeftMarker(Ruler
* rPtr
)
70 int xpos
= (rPtr
->flags
.whichMarker
== 1 ?
71 rPtr
->motion
: rPtr
->margins
.left
);
73 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
74 rPtr
->fg
, xpos
, 8, xpos
, 22);
77 points
[1].x
= points
[0].x
+ 6;
79 points
[2].x
= points
[0].x
+ 6;
81 points
[3].x
= points
[0].x
;
83 XFillPolygon(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
84 rPtr
->fg
, points
, 4, Convex
, CoordModeOrigin
);
88 /* Marker for right margin
97 static void drawRightMarker(Ruler
* rPtr
)
100 int xpos
= (rPtr
->flags
.whichMarker
== 2 ?
101 rPtr
->motion
: rPtr
->margins
.right
);
103 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
104 rPtr
->fg
, xpos
, 8, xpos
, 22);
105 points
[0].x
= xpos
+ 1;
107 points
[1].x
= points
[0].x
- 6;
109 points
[2].x
= points
[0].x
- 6;
111 points
[3].x
= points
[0].x
;
113 XFillPolygon(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
114 rPtr
->fg
, points
, 4, Convex
, CoordModeOrigin
);
118 /* Marker for first line only
124 static void drawFirstMarker(Ruler
* rPtr
)
126 int xpos
= ((rPtr
->flags
.whichMarker
== 3 || rPtr
->flags
.whichMarker
== 6) ?
127 rPtr
->motion
: rPtr
->margins
.first
);
129 XFillRectangle(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
130 rPtr
->fg
, xpos
- 5, 10, 11, 5);
131 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
132 rPtr
->fg
, xpos
, 12, xpos
, 22);
135 /* Marker for rest of body
140 static void drawBodyMarker(Ruler
* rPtr
)
143 int xpos
= ((rPtr
->flags
.whichMarker
== 4 || rPtr
->flags
.whichMarker
== 6) ?
144 rPtr
->motion
: rPtr
->margins
.body
);
146 points
[0].x
= xpos
- 5;
148 points
[1].x
= points
[0].x
+ 11;
150 points
[2].x
= points
[0].x
+ 5;
152 XFillPolygon(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
153 rPtr
->fg
, points
, 3, Convex
, CoordModeOrigin
);
157 static void createDrawBuffer(Ruler
* rPtr
)
159 if(!rPtr
->view
->flags
.realized
)
162 if (rPtr
->drawBuffer
)
163 XFreePixmap(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
);
165 rPtr
->drawBuffer
= XCreatePixmap(rPtr
->view
->screen
->display
,
166 rPtr
->view
->window
, rPtr
->view
->size
.width
, 40,
167 rPtr
->view
->screen
->depth
);
168 XFillRectangle(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
169 rPtr
->bg
, 0, 0, rPtr
->view
->size
.width
, 40);
173 static void drawRulerOnPixmap(Ruler
* rPtr
)
178 {11, 3, 5, 3, 7, 3, 5, 3};
180 if (!rPtr
->drawBuffer
|| !rPtr
->view
->flags
.realized
)
184 XFillRectangle(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
185 rPtr
->bg
, 0, 0, rPtr
->view
->size
.width
, 40);
187 WMDrawString(rPtr
->view
->screen
, rPtr
->drawBuffer
, rPtr
->fg
,
188 rPtr
->font
, rPtr
->margins
.left
+ 2, 26, "0 inches", 10);
192 w
= rPtr
->view
->size
.width
- rPtr
->margins
.left
;
194 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
195 rPtr
->fg
, rPtr
->margins
.left
+ m
, 23,
196 rPtr
->margins
.left
+ m
, marks
[i
% 8] + 23);
197 if (i
!= 0 && i
% 8 == 0) {
199 snprintf(c
, 3, "%d", ++j
);
201 snprintf(c
, 3, "%2d", ++j
);
202 WMDrawString(rPtr
->view
->screen
, rPtr
->drawBuffer
, rPtr
->fg
,
203 rPtr
->font
, rPtr
->margins
.left
+ 2 + m
, 26, c
, 2);
208 rPtr
->end
= rPtr
->margins
.left
+ m
- 10;
209 if (rPtr
->margins
.right
> rPtr
->end
)
210 rPtr
->margins
.right
= rPtr
->end
;
212 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
, rPtr
->fg
,
213 rPtr
->margins
.left
, 22, rPtr
->margins
.left
+ m
- 10, 22);
215 drawLeftMarker(rPtr
);
216 drawRightMarker(rPtr
);
217 drawFirstMarker(rPtr
);
218 drawBodyMarker(rPtr
);
220 rPtr
->flags
.redraw
= False
;
224 static void paintRuler(Ruler
* rPtr
)
226 WMScreen
*screen
= rPtr
->view
->screen
;
228 if (!rPtr
->drawBuffer
|| !rPtr
->view
->flags
.realized
)
231 if (rPtr
->flags
.redraw
)
232 drawRulerOnPixmap(rPtr
);
233 XCopyArea(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
234 rPtr
->view
->window
, rPtr
->bg
, 0, 0, rPtr
->view
->size
.width
, 40,
240 verifyMarkerMove(Ruler
* rPtr
, int x
)
242 if (rPtr
->flags
.whichMarker
< 1 || rPtr
->flags
.whichMarker
> 6)
245 switch (rPtr
->flags
.whichMarker
) {
247 if (x
> rPtr
->margins
.right
- 10 || x
< rPtr
->offset
||
248 rPtr
->margins
.body
+ x
> rPtr
->margins
.right
- MIN_DOC_WIDTH
||
249 rPtr
->margins
.first
+ x
> rPtr
->margins
.right
- MIN_DOC_WIDTH
)
254 if (x
< rPtr
->margins
.first
+ MIN_DOC_WIDTH
||
255 x
< rPtr
->margins
.body
+ MIN_DOC_WIDTH
||
256 x
< rPtr
->margins
.left
+ MIN_DOC_WIDTH
||
257 x
> rPtr
->end
) /*rPtr->view->size.width) */
262 if (x
>= rPtr
->margins
.right
- MIN_DOC_WIDTH
|| x
< rPtr
->margins
.left
)
267 if (x
>= rPtr
->margins
.right
- MIN_DOC_WIDTH
|| x
< rPtr
->margins
.left
)
272 if (x
>= rPtr
->margins
.right
- MIN_DOC_WIDTH
|| x
< rPtr
->margins
.left
)
285 static int whichMarker(Ruler
* rPtr
, int x
, int y
)
287 if (x
< rPtr
->offset
|| y
> 22)
290 if (rPtr
->margins
.left
- x
>= -6 && y
<= 9
291 && (rPtr
->margins
.left
- x
<= 0) && y
>= 4) {
292 rPtr
->motion
= rPtr
->margins
.left
;
295 if (rPtr
->margins
.right
- x
>= -1 && y
<= 11
296 && rPtr
->margins
.right
- x
<= 5 && y
>= 4) {
297 rPtr
->motion
= rPtr
->margins
.right
;
301 /* both first and body? */
302 if (rPtr
->margins
.first
- x
<= 4 && rPtr
->margins
.first
- x
>= -5
303 && rPtr
->margins
.body
- x
<= 4 && rPtr
->margins
.body
- x
>= -5
304 && y
>= 15 && y
<= 17) {
305 rPtr
->motion
= rPtr
->margins
.first
;
310 if (rPtr
->margins
.first
- x
<= 4 && y
<= 15
311 && rPtr
->margins
.first
- x
>= -5 && y
>= 10) {
312 rPtr
->motion
= rPtr
->margins
.first
;
315 if (rPtr
->margins
.body
- x
<= 4 && y
<= 21 &&
316 rPtr
->margins
.body
- x
>= -5 && y
>= 17) {
317 rPtr
->motion
= rPtr
->margins
.body
;
326 static void rulerDidResize(W_ViewDelegate
* self
, WMView
* view
)
328 Ruler
*rPtr
= (Ruler
*) view
->self
;
330 createDrawBuffer(rPtr
);
331 rPtr
->flags
.redraw
= True
;
337 static void handleEvents(XEvent
* event
, void *data
)
339 Ruler
*rPtr
= (Ruler
*) data
;
340 Display
*dpy
= event
->xany
.display
;
342 switch (event
->type
) {
344 rulerDidResize(rPtr
->view
->delegate
, rPtr
->view
);
348 if (rPtr
->flags
.buttonPressed
349 && (event
->xmotion
.state
& Button1Mask
)) {
350 if (verifyMarkerMove(rPtr
, event
->xmotion
.x
)) {
351 GC gc
= WMColorGC(WMDarkGrayColor(rPtr
->view
->screen
));
353 if (rPtr
->moveAction
)
354 (rPtr
->moveAction
) (rPtr
, rPtr
->clientData
);
355 rPtr
->flags
.redraw
= True
;
357 XSetLineAttributes(rPtr
->view
->screen
->display
, gc
, 1,
358 LineSolid
, CapNotLast
, JoinMiter
);
359 XDrawLine(rPtr
->pview
->screen
->display
,
361 gc
, rPtr
->motion
+ 1, 40,
362 rPtr
->motion
+ 1, rPtr
->pview
->size
.height
- 5);
368 if (event
->xbutton
.button
!= Button1
)
370 rPtr
->flags
.buttonPressed
= True
;
371 rPtr
->flags
.whichMarker
=
372 whichMarker(rPtr
, event
->xmotion
.x
,
377 if (event
->xbutton
.button
!= Button1
)
379 rPtr
->flags
.buttonPressed
= False
;
380 switch (rPtr
->flags
.whichMarker
) {
382 int change
= rPtr
->margins
.left
- rPtr
->motion
;
384 rPtr
->margins
.first
-= change
;
385 rPtr
->margins
.body
-= change
;
386 rPtr
->margins
.left
= rPtr
->motion
;
387 rPtr
->flags
.redraw
= True
;
392 rPtr
->margins
.right
= rPtr
->motion
;
395 rPtr
->margins
.first
= rPtr
->motion
;
398 rPtr
->margins
.body
= rPtr
->motion
;
401 rPtr
->margins
.first
= rPtr
->margins
.body
405 if (rPtr
->releaseAction
)
406 (rPtr
->releaseAction
) (rPtr
, rPtr
->clientData
);
412 W_ViewDelegate _RulerViewDelegate
=
423 WMCreateRuler(WMWidget
* parent
)
425 Ruler
*rPtr
= wmalloc(sizeof(Ruler
));
426 unsigned int w
= WMWidgetWidth(parent
);
428 memset(rPtr
, 0, sizeof(Ruler
));
430 rPtr
->widgetClass
= WC_Ruler
;
432 rPtr
->view
= W_CreateView(W_VIEW(parent
));
439 rPtr
->view
->self
= rPtr
;
441 rPtr
->drawBuffer
= (Pixmap
) NULL
;
443 W_ResizeView(rPtr
->view
, w
, 40);
445 WMCreateEventHandler(rPtr
->view
, ExposureMask
| StructureNotifyMask
446 | EnterWindowMask
| LeaveWindowMask
| FocusChangeMask
447 | ButtonReleaseMask
| ButtonPressMask
| KeyReleaseMask
448 | KeyPressMask
| Button1MotionMask
, handleEvents
, rPtr
);
450 rPtr
->view
->delegate
= &_RulerViewDelegate
;
452 rPtr
->bg
= WMColorGC(WMGrayColor(rPtr
->view
->screen
));
453 rPtr
->fg
= WMColorGC(WMBlackColor(rPtr
->view
->screen
));
454 rPtr
->font
= WMSystemFontOfSize(rPtr
->view
->screen
, 8);
457 rPtr
->margins
.left
= 22;
458 rPtr
->margins
.body
= 22;
459 rPtr
->margins
.first
= 42;
460 rPtr
->margins
.right
= (w
< 502 ? w
: 502);
461 rPtr
->margins
.tabs
= NULL
;
463 rPtr
->flags
.whichMarker
= 0; /* none */
464 rPtr
->flags
.buttonPressed
= False
;
465 rPtr
->flags
.redraw
= True
;
467 rPtr
->moveAction
= NULL
;
468 rPtr
->releaseAction
= NULL
;
470 rPtr
->pview
= W_VIEW(parent
);
476 void WMSetRulerMargins(WMRuler
* rPtr
, WMRulerMargins margins
)
480 rPtr
->margins
.left
= margins
.left
+ rPtr
->offset
;
481 rPtr
->margins
.right
= margins
.right
+ rPtr
->offset
;
482 rPtr
->margins
.first
= margins
.first
+ rPtr
->offset
;
483 rPtr
->margins
.body
= margins
.body
+ rPtr
->offset
;
484 rPtr
->margins
.tabs
= margins
.tabs
; /*for loop */
485 rPtr
->flags
.redraw
= True
;
491 WMGetRulerMargins(WMRuler
* rPtr
)
493 WMRulerMargins
*margins
= wmalloc(sizeof(WMRulerMargins
));
496 margins
->first
= margins
->body
= margins
->left
= 0;
497 margins
->right
= 100;
501 margins
->left
= rPtr
->margins
.left
- rPtr
->offset
;
502 margins
->right
= rPtr
->margins
.right
- rPtr
->offset
;
503 margins
->first
= rPtr
->margins
.first
- rPtr
->offset
;
504 margins
->body
= rPtr
->margins
.body
- rPtr
->offset
;
506 margins
->tabs
= rPtr
->margins
.tabs
;
511 WMIsMarginEqualToMargin(WMRulerMargins
*aMargin
, WMRulerMargins
*anotherMargin
)
513 if(aMargin
== anotherMargin
)
515 else if(!aMargin
|| !anotherMargin
)
517 if(aMargin
->left
!= anotherMargin
->left
)
519 if(aMargin
->first
!= anotherMargin
->first
)
521 if(aMargin
->body
!= anotherMargin
->body
)
523 if(aMargin
->right
!= anotherMargin
->right
)
532 void WMSetRulerOffset(WMRuler
* rPtr
, int pixels
)
534 if (!rPtr
|| pixels
< 0 || pixels
+ MIN_DOC_WIDTH
>= rPtr
->view
->size
.width
)
536 rPtr
->offset
= pixels
;
537 /*rulerDidResize(rPtr, rPtr->view); */
541 int WMGetRulerOffset(WMRuler
* rPtr
)
549 void WMSetRulerReleaseAction(WMRuler
* rPtr
, WMAction
* action
, void *clientData
)
554 rPtr
->releaseAction
= action
;
555 rPtr
->clientData
= clientData
;
559 void WMSetRulerMoveAction(WMRuler
* rPtr
, WMAction
* action
, void *clientData
)
564 rPtr
->moveAction
= action
;
565 rPtr
->clientData
= clientData
;
569 /* _which_ one was released */
570 int WMGetReleasedRulerMargin(WMRuler
* rPtr
)
574 return rPtr
->flags
.whichMarker
;
578 /* _which_ one is being grabbed */
579 int WMGetGrabbedRulerMargin(WMRuler
* rPtr
)
583 return rPtr
->flags
.whichMarker
;