2 * WINGs WMRuler nifty ruler widget for WINGs (OK, for WMText ;-)
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 buttonPressed
:1;
46 unsigned int whichMarker
:3;
47 /* 0, 1, 2, 3, 4, 5, 6 */
48 /* none, left, right, first, body, tabstop, first & body */
49 unsigned int RESERVED
:28;
55 /* Marker for left margin
65 drawLeftMarker(Ruler
* rPtr
)
68 int xpos
= (rPtr
->flags
.whichMarker
== 1 ?
69 rPtr
->motion
: rPtr
->margins
.left
);
71 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
72 rPtr
->fg
, xpos
, 8, xpos
, 22);
75 points
[1].x
= points
[0].x
+ 6;
77 points
[2].x
= points
[0].x
+ 6;
79 points
[3].x
= points
[0].x
;
81 XFillPolygon(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
82 rPtr
->fg
, points
, 4, Convex
, CoordModeOrigin
);
86 /* Marker for right margin
95 static void drawRightMarker(Ruler
* rPtr
)
98 int xpos
= (rPtr
->flags
.whichMarker
== 2 ?
99 rPtr
->motion
: rPtr
->margins
.right
);
101 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
102 rPtr
->fg
, xpos
, 8, xpos
, 22);
103 points
[0].x
= xpos
+ 1;
105 points
[1].x
= points
[0].x
- 6;
107 points
[2].x
= points
[0].x
- 6;
109 points
[3].x
= points
[0].x
;
111 XFillPolygon(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
112 rPtr
->fg
, points
, 4, Convex
, CoordModeOrigin
);
116 /* Marker for first line only
122 static void drawFirstMarker(Ruler
* rPtr
)
124 int xpos
= ((rPtr
->flags
.whichMarker
== 3 || rPtr
->flags
.whichMarker
== 6) ?
125 rPtr
->motion
: rPtr
->margins
.first
);
127 XFillRectangle(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
128 rPtr
->fg
, xpos
- 5, 10, 11, 5);
129 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
130 rPtr
->fg
, xpos
, 12, xpos
, 22);
133 /* Marker for rest of body
138 static void drawBodyMarker(Ruler
* rPtr
)
141 int xpos
= ((rPtr
->flags
.whichMarker
== 4 || rPtr
->flags
.whichMarker
== 6) ?
142 rPtr
->motion
: rPtr
->margins
.body
);
144 points
[0].x
= xpos
- 5;
146 points
[1].x
= points
[0].x
+ 11;
148 points
[2].x
= points
[0].x
+ 5;
150 XFillPolygon(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
151 rPtr
->fg
, points
, 3, Convex
, CoordModeOrigin
);
155 static void createDrawBuffer(Ruler
* rPtr
)
157 if (rPtr
->drawBuffer
)
158 XFreePixmap(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
);
159 rPtr
->drawBuffer
= XCreatePixmap(rPtr
->view
->screen
->display
,
160 rPtr
->view
->window
, rPtr
->view
->size
.width
, 40,
161 rPtr
->view
->screen
->depth
);
162 XFillRectangle(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
163 rPtr
->bg
, 0, 0, rPtr
->view
->size
.width
, 40);
167 static void drawRulerOnPixmap(Ruler
* rPtr
)
172 {11, 3, 5, 3, 7, 3, 5, 3};
174 if (!rPtr
->drawBuffer
)
175 createDrawBuffer(rPtr
);
177 XFillRectangle(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
178 rPtr
->bg
, 0, 0, rPtr
->view
->size
.width
, 40);
180 WMDrawString(rPtr
->view
->screen
, rPtr
->drawBuffer
, rPtr
->fg
,
181 rPtr
->font
, rPtr
->margins
.left
+ 2, 26, "0 inches", 10);
185 w
= rPtr
->view
->size
.width
- rPtr
->margins
.left
;
187 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
188 rPtr
->fg
, rPtr
->margins
.left
+ m
, 23,
189 rPtr
->margins
.left
+ m
, marks
[i
% 8] + 23);
190 if (i
!= 0 && i
% 8 == 0) {
192 snprintf(c
, 3, "%d", ++j
);
194 snprintf(c
, 3, "%2d", ++j
);
195 WMDrawString(rPtr
->view
->screen
, rPtr
->drawBuffer
, rPtr
->fg
,
196 rPtr
->font
, rPtr
->margins
.left
+ 2 + m
, 26, c
, 2);
201 rPtr
->end
= rPtr
->margins
.left
+ m
- 10;
202 if (rPtr
->margins
.right
> rPtr
->end
)
203 rPtr
->margins
.right
= rPtr
->end
;
205 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
, rPtr
->fg
,
206 rPtr
->margins
.left
, 22, rPtr
->margins
.left
+ m
- 10, 22);
208 drawLeftMarker(rPtr
);
209 drawRightMarker(rPtr
);
210 drawFirstMarker(rPtr
);
211 drawBodyMarker(rPtr
);
215 static void paintRuler(Ruler
* rPtr
)
217 WMScreen
*screen
= rPtr
->view
->screen
;
219 if (1 || !rPtr
->drawBuffer
) {
220 drawRulerOnPixmap(rPtr
);
222 XCopyArea(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
223 rPtr
->view
->window
, rPtr
->bg
, 0, 0, rPtr
->view
->size
.width
, 40,
229 verifyMarkerMove(Ruler
* rPtr
, int x
)
231 if (rPtr
->flags
.whichMarker
< 1 || rPtr
->flags
.whichMarker
> 6)
234 switch (rPtr
->flags
.whichMarker
) {
236 if (x
> rPtr
->margins
.right
- 10 || x
< rPtr
->offset
||
237 rPtr
->margins
.body
+ x
> rPtr
->margins
.right
- MIN_DOC_WIDTH
||
238 rPtr
->margins
.first
+ x
> rPtr
->margins
.right
- MIN_DOC_WIDTH
)
243 if (x
< rPtr
->margins
.first
+ MIN_DOC_WIDTH
||
244 x
< rPtr
->margins
.body
+ MIN_DOC_WIDTH
||
245 x
< rPtr
->margins
.left
+ MIN_DOC_WIDTH
||
246 x
> rPtr
->end
) /*rPtr->view->size.width) */
251 if (x
>= rPtr
->margins
.right
- MIN_DOC_WIDTH
|| x
< rPtr
->margins
.left
)
256 if (x
>= rPtr
->margins
.right
- MIN_DOC_WIDTH
|| x
< rPtr
->margins
.left
)
261 if (x
>= rPtr
->margins
.right
- MIN_DOC_WIDTH
|| x
< rPtr
->margins
.left
)
274 static int whichMarker(Ruler
* rPtr
, int x
, int y
)
276 if (x
< rPtr
->offset
|| y
> 22)
279 if (rPtr
->margins
.left
- x
>= -6 && y
<= 9
280 && (rPtr
->margins
.left
- x
<= 0) && y
>= 4) {
281 rPtr
->motion
= rPtr
->margins
.left
;
284 if (rPtr
->margins
.right
- x
>= -1 && y
<= 11
285 && rPtr
->margins
.right
- x
<= 5 && y
>= 4) {
286 rPtr
->motion
= rPtr
->margins
.right
;
290 /* both first and body? */
291 if (rPtr
->margins
.first
- x
<= 4 && rPtr
->margins
.first
- x
>= -5
292 && rPtr
->margins
.body
- x
<= 4 && rPtr
->margins
.body
- x
>= -5
293 && y
>= 15 && y
<= 17) {
294 rPtr
->motion
= rPtr
->margins
.first
;
299 if (rPtr
->margins
.first
- x
<= 4 && y
<= 15
300 && rPtr
->margins
.first
- x
>= -5 && y
>= 10) {
301 rPtr
->motion
= rPtr
->margins
.first
;
304 if (rPtr
->margins
.body
- x
<= 4 && y
<= 21 &&
305 rPtr
->margins
.body
- x
>= -5 && y
>= 17) {
306 rPtr
->motion
= rPtr
->margins
.body
;
316 static void handleEvents(XEvent
* event
, void *data
)
318 Ruler
*rPtr
= (Ruler
*) data
;
319 Display
*dpy
= event
->xany
.display
;
321 switch (event
->type
) {
327 if (rPtr
->flags
.buttonPressed
328 && (event
->xmotion
.state
& Button1Mask
)) {
329 if (verifyMarkerMove(rPtr
, event
->xmotion
.x
)) {
330 GC gc
= WMColorGC(WMDarkGrayColor(rPtr
->view
->screen
));
332 if (rPtr
->moveAction
)
333 (rPtr
->moveAction
) (rPtr
, rPtr
->clientData
);
335 XSetLineAttributes(rPtr
->view
->screen
->display
, gc
, 1,
336 LineSolid
, CapNotLast
, JoinMiter
);
337 XDrawLine(rPtr
->pview
->screen
->display
,
339 gc
, rPtr
->motion
+ 1, 40,
340 rPtr
->motion
+ 1, rPtr
->pview
->size
.height
- 5);
346 if (event
->xbutton
.button
!= Button1
)
348 rPtr
->flags
.buttonPressed
= True
;
349 rPtr
->flags
.whichMarker
=
350 whichMarker(rPtr
, event
->xmotion
.x
,
355 if (event
->xbutton
.button
!= Button1
)
357 rPtr
->flags
.buttonPressed
= False
;
358 switch (rPtr
->flags
.whichMarker
) {
360 int change
= rPtr
->margins
.left
- rPtr
->motion
;
362 rPtr
->margins
.first
-= change
;
363 rPtr
->margins
.body
-= change
;
364 rPtr
->margins
.left
= rPtr
->motion
;
369 rPtr
->margins
.right
= rPtr
->motion
;
372 rPtr
->margins
.first
= rPtr
->motion
;
375 rPtr
->margins
.body
= rPtr
->motion
;
378 rPtr
->margins
.first
= rPtr
->margins
.body
382 if (rPtr
->releaseAction
)
383 (rPtr
->releaseAction
) (rPtr
, rPtr
->clientData
);
388 static void rulerDidResize(W_ViewDelegate
* self
, WMView
* view
)
390 Ruler
*rPtr
= (Ruler
*) view
->self
;
392 createDrawBuffer(rPtr
);
398 W_ViewDelegate _RulerViewDelegate
=
409 WMCreateRuler(WMWidget
* parent
)
411 Ruler
*rPtr
= wmalloc(sizeof(Ruler
));
412 unsigned int w
= WMWidgetWidth(parent
);
414 memset(rPtr
, 0, sizeof(Ruler
));
416 rPtr
->widgetClass
= WC_Ruler
;
418 rPtr
->view
= W_CreateView(W_VIEW(parent
));
423 rPtr
->view
->self
= rPtr
;
425 rPtr
->drawBuffer
= (Pixmap
) NULL
;
427 W_ResizeView(rPtr
->view
, w
, 40);
429 WMCreateEventHandler(rPtr
->view
, ExposureMask
| StructureNotifyMask
430 | EnterWindowMask
| LeaveWindowMask
| FocusChangeMask
431 | ButtonReleaseMask
| ButtonPressMask
| KeyReleaseMask
432 | KeyPressMask
| Button1MotionMask
, handleEvents
, rPtr
);
434 rPtr
->view
->delegate
= &_RulerViewDelegate
;
436 rPtr
->bg
= WMColorGC(WMGrayColor(rPtr
->view
->screen
));
437 rPtr
->fg
= WMColorGC(WMBlackColor(rPtr
->view
->screen
));
438 rPtr
->font
= WMSystemFontOfSize(rPtr
->view
->screen
, 8);
441 rPtr
->margins
.left
= 22;
442 rPtr
->margins
.body
= 22;
443 rPtr
->margins
.first
= 42;
444 rPtr
->margins
.right
= (w
< 502 ? w
: 502);
446 rPtr
->flags
.whichMarker
= 0; /* none */
447 rPtr
->flags
.buttonPressed
= False
;
449 rPtr
->moveAction
= NULL
;
450 rPtr
->releaseAction
= NULL
;
452 rPtr
->pview
= W_VIEW(parent
);
458 void WMSetRulerMargins(WMRuler
* rPtr
, WMRulerMargins margins
)
462 rPtr
->margins
.left
= margins
.left
+ rPtr
->offset
;
463 rPtr
->margins
.right
= margins
.right
+ rPtr
->offset
;
464 rPtr
->margins
.first
= margins
.first
+ rPtr
->offset
;
465 rPtr
->margins
.body
= margins
.body
+ rPtr
->offset
;
466 rPtr
->margins
.tabs
= margins
.tabs
; /*for loop */
473 WMGetRulerMargins(WMRuler
* rPtr
)
475 WMRulerMargins margins
;
480 margins
.left
= rPtr
->margins
.left
- rPtr
->offset
;
481 margins
.right
= rPtr
->margins
.right
- rPtr
->offset
;
482 margins
.first
= rPtr
->margins
.first
- rPtr
->offset
;
483 margins
.body
= rPtr
->margins
.body
- rPtr
->offset
;
485 margins
.tabs
= rPtr
->margins
.tabs
;
487 return rPtr
->margins
;
491 void WMSetRulerOffset(WMRuler
* rPtr
, int pixels
)
493 if (!rPtr
|| pixels
< 0 || pixels
+ MIN_DOC_WIDTH
>= rPtr
->view
->size
.width
)
495 rPtr
->offset
= pixels
;
496 /*rulerDidResize(rPtr, rPtr->view); */
500 int WMGetRulerOffset(WMRuler
* rPtr
)
508 void WMSetRulerReleaseAction(WMRuler
* rPtr
, WMAction
* action
, void *clientData
)
513 rPtr
->releaseAction
= action
;
514 rPtr
->clientData
= clientData
;
518 void WMSetRulerMoveAction(WMRuler
* rPtr
, WMAction
* action
, void *clientData
)
523 rPtr
->moveAction
= action
;
524 rPtr
->clientData
= clientData
;
528 /* _which_ one was released */
529 int WMGetReleasedRulerMargin(WMRuler
* rPtr
)
533 return rPtr
->flags
.whichMarker
;
537 /* _which_ one is being grabbed */
538 int WMGetGrabbedRulerMargin(WMRuler
* rPtr
)
542 return rPtr
->flags
.whichMarker
;