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., 51 Franklin St, Fifth Floor, Boston,
25 #define MIN_DOC_WIDTH 10
27 typedef struct W_Ruler
{
30 W_View
*pview
; /* the parent's view (for drawing the line) */
32 WMAction
*moveAction
; /* what to when while moving */
33 WMAction
*releaseAction
; /* what to do when released */
39 WMRulerMargins margins
;
41 int motion
; /* the position of the _moving_ marker(s) */
42 int end
; /* the last tick on the baseline (restrict markers to it) */
47 unsigned int whichMarker
:3;
48 /* 0, 1, 2, 3, 4, 5, 6 */
49 /* none, left, right, first, body, tabstop, first & body */
51 unsigned int buttonPressed
:1;
52 unsigned int redraw
:1;
53 unsigned int RESERVED
:27;
57 /* Marker for left margin
66 static void drawLeftMarker(Ruler
* rPtr
)
69 int xpos
= (rPtr
->flags
.whichMarker
== 1 ? rPtr
->motion
: rPtr
->margins
.left
);
71 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
, rPtr
->fgGC
, xpos
, 8, xpos
, 22);
74 points
[1].x
= points
[0].x
+ 6;
76 points
[2].x
= points
[0].x
+ 6;
78 points
[3].x
= points
[0].x
;
80 XFillPolygon(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
, rPtr
->fgGC
,
81 points
, 4, Convex
, CoordModeOrigin
);
84 /* Marker for right margin
93 static void drawRightMarker(Ruler
* rPtr
)
96 int xpos
= (rPtr
->flags
.whichMarker
== 2 ? rPtr
->motion
: rPtr
->margins
.right
);
98 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
, rPtr
->fgGC
, xpos
, 8, xpos
, 22);
99 points
[0].x
= xpos
+ 1;
101 points
[1].x
= points
[0].x
- 6;
103 points
[2].x
= points
[0].x
- 6;
105 points
[3].x
= points
[0].x
;
107 XFillPolygon(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
, rPtr
->fgGC
,
108 points
, 4, Convex
, CoordModeOrigin
);
111 /* Marker for first line only
117 static void drawFirstMarker(Ruler
* rPtr
)
119 int xpos
= ((rPtr
->flags
.whichMarker
== 3 || rPtr
->flags
.whichMarker
== 6) ?
120 rPtr
->motion
: rPtr
->margins
.first
);
122 XFillRectangle(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
, rPtr
->fgGC
, xpos
- 5, 10, 11, 5);
123 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
, rPtr
->fgGC
, xpos
, 12, xpos
, 22);
126 /* Marker for rest of body
131 static void drawBodyMarker(Ruler
* rPtr
)
134 int xpos
= ((rPtr
->flags
.whichMarker
== 4 || rPtr
->flags
.whichMarker
== 6) ?
135 rPtr
->motion
: rPtr
->margins
.body
);
137 points
[0].x
= xpos
- 5;
139 points
[1].x
= points
[0].x
+ 11;
141 points
[2].x
= points
[0].x
+ 5;
143 XFillPolygon(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
, rPtr
->fgGC
,
144 points
, 3, Convex
, CoordModeOrigin
);
147 static void createDrawBuffer(Ruler
* rPtr
)
149 if (!rPtr
->view
->flags
.realized
)
152 if (rPtr
->drawBuffer
)
153 XFreePixmap(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
);
155 rPtr
->drawBuffer
= XCreatePixmap(rPtr
->view
->screen
->display
,
156 rPtr
->view
->window
, rPtr
->view
->size
.width
, 40,
157 rPtr
->view
->screen
->depth
);
158 XFillRectangle(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
159 rPtr
->bgGC
, 0, 0, rPtr
->view
->size
.width
, 40);
162 static void drawRulerOnPixmap(Ruler
* rPtr
)
166 int marks
[9] = { 11, 3, 5, 3, 7, 3, 5, 3 };
168 if (!rPtr
->drawBuffer
|| !rPtr
->view
->flags
.realized
)
171 XFillRectangle(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
172 rPtr
->bgGC
, 0, 0, rPtr
->view
->size
.width
, 40);
174 WMDrawString(rPtr
->view
->screen
, rPtr
->drawBuffer
, rPtr
->fg
,
175 rPtr
->font
, rPtr
->margins
.left
+ 2, 26, _("0 inches"), 10);
179 w
= rPtr
->view
->size
.width
- rPtr
->margins
.left
;
181 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
182 rPtr
->fgGC
, rPtr
->margins
.left
+ m
, 23, rPtr
->margins
.left
+ m
, marks
[i
% 8] + 23);
183 if (i
!= 0 && i
% 8 == 0) {
185 snprintf(c
, 3, "%d", ++j
);
187 snprintf(c
, 3, "%2d", ++j
);
188 WMDrawString(rPtr
->view
->screen
, rPtr
->drawBuffer
, rPtr
->fg
,
189 rPtr
->font
, rPtr
->margins
.left
+ 2 + m
, 26, c
, 2);
194 rPtr
->end
= rPtr
->margins
.left
+ m
- 10;
195 if (rPtr
->margins
.right
> rPtr
->end
)
196 rPtr
->margins
.right
= rPtr
->end
;
198 XDrawLine(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
, rPtr
->fgGC
,
199 rPtr
->margins
.left
, 22, rPtr
->margins
.left
+ m
- 10, 22);
201 drawLeftMarker(rPtr
);
202 drawRightMarker(rPtr
);
203 drawFirstMarker(rPtr
);
204 drawBodyMarker(rPtr
);
206 rPtr
->flags
.redraw
= False
;
209 static void paintRuler(Ruler
* rPtr
)
211 if (!rPtr
->drawBuffer
|| !rPtr
->view
->flags
.realized
)
214 if (rPtr
->flags
.redraw
)
215 drawRulerOnPixmap(rPtr
);
216 XCopyArea(rPtr
->view
->screen
->display
, rPtr
->drawBuffer
,
217 rPtr
->view
->window
, rPtr
->bgGC
, 0, 0, rPtr
->view
->size
.width
, 40, 0, 0);
220 static Bool
verifyMarkerMove(Ruler
* rPtr
, int x
)
222 if (rPtr
->flags
.whichMarker
< 1 || rPtr
->flags
.whichMarker
> 6)
225 switch (rPtr
->flags
.whichMarker
) {
227 if (x
> rPtr
->margins
.right
- 10 || x
< rPtr
->offset
||
228 rPtr
->margins
.body
+ x
> rPtr
->margins
.right
- MIN_DOC_WIDTH
||
229 rPtr
->margins
.first
+ x
> rPtr
->margins
.right
- MIN_DOC_WIDTH
)
234 if (x
< rPtr
->margins
.first
+ MIN_DOC_WIDTH
|| x
< rPtr
->margins
.body
+ MIN_DOC_WIDTH
|| x
< rPtr
->margins
.left
+ MIN_DOC_WIDTH
|| x
> rPtr
->end
) /*rPtr->view->size.width) */
239 if (x
>= rPtr
->margins
.right
- MIN_DOC_WIDTH
|| x
< rPtr
->margins
.left
)
244 if (x
>= rPtr
->margins
.right
- MIN_DOC_WIDTH
|| x
< rPtr
->margins
.left
)
249 if (x
>= rPtr
->margins
.right
- MIN_DOC_WIDTH
|| x
< rPtr
->margins
.left
)
261 static int whichMarker(Ruler
* rPtr
, int x
, int y
)
263 if (x
< rPtr
->offset
|| y
> 22)
266 if (rPtr
->margins
.left
- x
>= -6 && y
<= 9 && (rPtr
->margins
.left
- x
<= 0) && y
>= 4) {
267 rPtr
->motion
= rPtr
->margins
.left
;
270 if (rPtr
->margins
.right
- x
>= -1 && y
<= 11 && rPtr
->margins
.right
- x
<= 5 && y
>= 4) {
271 rPtr
->motion
= rPtr
->margins
.right
;
275 /* both first and body? */
276 if (rPtr
->margins
.first
- x
<= 4 && rPtr
->margins
.first
- x
>= -5
277 && rPtr
->margins
.body
- x
<= 4 && rPtr
->margins
.body
- x
>= -5 && y
>= 15 && y
<= 17) {
278 rPtr
->motion
= rPtr
->margins
.first
;
283 if (rPtr
->margins
.first
- x
<= 4 && y
<= 15 && rPtr
->margins
.first
- x
>= -5 && y
>= 10) {
284 rPtr
->motion
= rPtr
->margins
.first
;
287 if (rPtr
->margins
.body
- x
<= 4 && y
<= 21 && rPtr
->margins
.body
- x
>= -5 && y
>= 17) {
288 rPtr
->motion
= rPtr
->margins
.body
;
296 static void rulerDidResize(W_ViewDelegate
* self
, WMView
* view
)
298 Ruler
*rPtr
= (Ruler
*) view
->self
;
300 /* Parameter not used, but tell the compiler that it is ok */
303 createDrawBuffer(rPtr
);
304 rPtr
->flags
.redraw
= True
;
309 static void handleEvents(XEvent
* event
, void *data
)
311 Ruler
*rPtr
= (Ruler
*) data
;
313 switch (event
->type
) {
315 rulerDidResize(rPtr
->view
->delegate
, rPtr
->view
);
319 if (rPtr
->flags
.buttonPressed
&& (event
->xmotion
.state
& Button1Mask
)) {
320 if (verifyMarkerMove(rPtr
, event
->xmotion
.x
)) {
321 GC gc
= WMColorGC(WMDarkGrayColor(rPtr
->view
->screen
));
323 if (rPtr
->moveAction
)
324 (rPtr
->moveAction
) (rPtr
, rPtr
->clientData
);
325 rPtr
->flags
.redraw
= True
;
327 XSetLineAttributes(rPtr
->view
->screen
->display
, gc
, 1,
328 LineSolid
, CapNotLast
, JoinMiter
);
329 XDrawLine(rPtr
->pview
->screen
->display
,
331 gc
, rPtr
->motion
+ 1, 40,
332 rPtr
->motion
+ 1, rPtr
->pview
->size
.height
- 5);
338 if (event
->xbutton
.button
!= Button1
)
340 rPtr
->flags
.buttonPressed
= True
;
341 rPtr
->flags
.whichMarker
= whichMarker(rPtr
, event
->xmotion
.x
, event
->xmotion
.y
);
345 if (event
->xbutton
.button
!= Button1
)
347 rPtr
->flags
.buttonPressed
= False
;
348 switch (rPtr
->flags
.whichMarker
) {
350 int change
= rPtr
->margins
.left
- rPtr
->motion
;
352 rPtr
->margins
.first
-= change
;
353 rPtr
->margins
.body
-= change
;
354 rPtr
->margins
.left
= rPtr
->motion
;
355 rPtr
->flags
.redraw
= True
;
360 rPtr
->margins
.right
= rPtr
->motion
;
363 rPtr
->margins
.first
= rPtr
->motion
;
366 rPtr
->margins
.body
= rPtr
->motion
;
369 rPtr
->margins
.first
= rPtr
->margins
.body
= rPtr
->motion
;
372 if (rPtr
->releaseAction
)
373 (rPtr
->releaseAction
) (rPtr
, rPtr
->clientData
);
378 W_ViewDelegate _RulerViewDelegate
= {
386 WMRuler
*WMCreateRuler(WMWidget
* parent
)
388 Ruler
*rPtr
= wmalloc(sizeof(Ruler
));
389 unsigned int w
= WMWidgetWidth(parent
);
391 rPtr
->widgetClass
= WC_Ruler
;
393 rPtr
->view
= W_CreateView(W_VIEW(parent
));
400 rPtr
->view
->self
= rPtr
;
402 rPtr
->drawBuffer
= (Pixmap
) NULL
;
404 W_ResizeView(rPtr
->view
, w
, 40);
406 WMCreateEventHandler(rPtr
->view
, ExposureMask
| StructureNotifyMask
407 | EnterWindowMask
| LeaveWindowMask
| FocusChangeMask
408 | ButtonReleaseMask
| ButtonPressMask
| KeyReleaseMask
409 | KeyPressMask
| Button1MotionMask
, handleEvents
, rPtr
);
411 rPtr
->view
->delegate
= &_RulerViewDelegate
;
413 rPtr
->fg
= WMBlackColor(rPtr
->view
->screen
);
414 rPtr
->fgGC
= WMColorGC(rPtr
->fg
);
415 rPtr
->bgGC
= WMColorGC(WMGrayColor(rPtr
->view
->screen
));
416 rPtr
->font
= WMSystemFontOfSize(rPtr
->view
->screen
, 8);
419 rPtr
->margins
.left
= 22;
420 rPtr
->margins
.body
= 22;
421 rPtr
->margins
.first
= 42;
422 rPtr
->margins
.right
= (w
< 502 ? w
: 502);
423 rPtr
->margins
.tabs
= NULL
;
425 rPtr
->flags
.whichMarker
= 0; /* none */
426 rPtr
->flags
.buttonPressed
= False
;
427 rPtr
->flags
.redraw
= True
;
429 rPtr
->moveAction
= NULL
;
430 rPtr
->releaseAction
= NULL
;
432 rPtr
->pview
= W_VIEW(parent
);
437 void WMSetRulerMargins(WMRuler
* rPtr
, WMRulerMargins margins
)
441 rPtr
->margins
.left
= margins
.left
+ rPtr
->offset
;
442 rPtr
->margins
.right
= margins
.right
+ rPtr
->offset
;
443 rPtr
->margins
.first
= margins
.first
+ rPtr
->offset
;
444 rPtr
->margins
.body
= margins
.body
+ rPtr
->offset
;
445 rPtr
->margins
.tabs
= margins
.tabs
; /*for loop */
446 rPtr
->flags
.redraw
= True
;
451 WMRulerMargins
*WMGetRulerMargins(WMRuler
* rPtr
)
453 WMRulerMargins
*margins
= wmalloc(sizeof(WMRulerMargins
));
456 margins
->first
= margins
->body
= margins
->left
= 0;
457 margins
->right
= 100;
461 margins
->left
= rPtr
->margins
.left
- rPtr
->offset
;
462 margins
->right
= rPtr
->margins
.right
- rPtr
->offset
;
463 margins
->first
= rPtr
->margins
.first
- rPtr
->offset
;
464 margins
->body
= rPtr
->margins
.body
- rPtr
->offset
;
466 margins
->tabs
= rPtr
->margins
.tabs
;
471 Bool
WMIsMarginEqualToMargin(WMRulerMargins
* aMargin
, WMRulerMargins
* anotherMargin
)
473 if (aMargin
== anotherMargin
)
475 else if (!aMargin
|| !anotherMargin
)
477 if (aMargin
->left
!= anotherMargin
->left
)
479 if (aMargin
->first
!= anotherMargin
->first
)
481 if (aMargin
->body
!= anotherMargin
->body
)
483 if (aMargin
->right
!= anotherMargin
->right
)
489 void WMSetRulerOffset(WMRuler
* rPtr
, int pixels
)
491 if (!rPtr
|| pixels
< 0 || pixels
+ MIN_DOC_WIDTH
>= rPtr
->view
->size
.width
)
493 rPtr
->offset
= pixels
;
494 /*rulerDidResize(rPtr, rPtr->view); */
497 int WMGetRulerOffset(WMRuler
* rPtr
)
500 return 0; /* what value should return if no ruler? -1 or 0? */
504 void WMSetRulerReleaseAction(WMRuler
* rPtr
, WMAction
* action
, void *clientData
)
509 rPtr
->releaseAction
= action
;
510 rPtr
->clientData
= clientData
;
513 void WMSetRulerMoveAction(WMRuler
* rPtr
, WMAction
* action
, void *clientData
)
518 rPtr
->moveAction
= action
;
519 rPtr
->clientData
= clientData
;
522 /* _which_ one was released */
523 int WMGetReleasedRulerMargin(WMRuler
* rPtr
)
527 return rPtr
->flags
.whichMarker
;
530 /* _which_ one is being grabbed */
531 int WMGetGrabbedRulerMargin(WMRuler
* rPtr
)
535 return rPtr
->flags
.whichMarker
;