svg text alignment
[dia.git] / app / lineprops_area.c
blob66d7c977204774f05a7b0655aacc2ce794337786
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * lineprops_area.h -- Copyright (C) 1999 James Henstridge.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include "intl.h"
26 #include "widgets.h"
27 #include "lineprops_area.h"
29 #include <gtk/gtk.h>
31 /* --------------- DiaArrowPreview -------------------------------- */
33 typedef struct _DiaArrowPreview DiaArrowPreview;
34 typedef struct _DiaArrowPreviewClass DiaArrowPreviewClass;
36 static GtkType dia_arrow_preview_get_type (void);
37 static GtkWidget *dia_arrow_preview_new (ArrowType atype, gboolean left);
38 static void dia_arrow_preview_set(DiaArrowPreview *arrow,
39 ArrowType atype, gboolean left);
41 #define DIA_ARROW_PREVIEW(obj) (GTK_CHECK_CAST((obj),dia_arrow_preview_get_type(), DiaArrowPreview))
42 #define DIA_ARROW_PREVIEW_CLASS(obj) (GTK_CHECK_CLASS_CAST((obj), dia_arrow_preview_get_type(), DiaArrowPreviewClass))
44 struct _DiaArrowPreview
46 GtkMisc misc;
47 ArrowType atype;
48 gboolean left;
50 struct _DiaArrowPreviewClass
52 GtkMiscClass parent_class;
55 static void dia_arrow_preview_class_init (DiaArrowPreviewClass *klass);
56 static void dia_arrow_preview_init (DiaArrowPreview *arrow);
57 static gint dia_arrow_preview_expose (GtkWidget *widget,
58 GdkEventExpose *event);
60 static GtkType
61 dia_arrow_preview_get_type (void)
63 static GtkType arrow_type = 0;
65 if (!arrow_type) {
66 static const GtkTypeInfo arrow_info = {
67 "DiaArrowPreview",
68 sizeof (DiaArrowPreview),
69 sizeof (DiaArrowPreviewClass),
70 (GtkClassInitFunc) dia_arrow_preview_class_init,
71 (GtkObjectInitFunc) dia_arrow_preview_init,
72 /* reserved_1 */ NULL,
73 /* reserved_2 */ NULL,
74 (GtkClassInitFunc) NULL,
76 arrow_type = gtk_type_unique (GTK_TYPE_MISC, &arrow_info);
78 return arrow_type;
81 static void
82 dia_arrow_preview_class_init (DiaArrowPreviewClass *class)
84 GtkWidgetClass *widget_class;
86 widget_class = (GtkWidgetClass *)class;
87 widget_class->expose_event = dia_arrow_preview_expose;
90 static void
91 dia_arrow_preview_init (DiaArrowPreview *arrow)
93 GTK_WIDGET_SET_FLAGS (arrow, GTK_NO_WINDOW);
95 GTK_WIDGET (arrow)->requisition.width = 30 + GTK_MISC (arrow)->xpad * 2;
96 GTK_WIDGET (arrow)->requisition.height = 20 + GTK_MISC (arrow)->ypad * 2;
98 arrow->atype = ARROW_NONE;
99 arrow->left = TRUE;
102 static GtkWidget *
103 dia_arrow_preview_new (ArrowType atype, gboolean left)
105 DiaArrowPreview *arrow = gtk_type_new (dia_arrow_preview_get_type());
107 arrow->atype = atype;
108 arrow->left = left;
109 return GTK_WIDGET(arrow);
112 static void
113 dia_arrow_preview_set(DiaArrowPreview *arrow, ArrowType atype, gboolean left)
115 if (arrow->atype != atype || arrow->left != left) {
116 arrow->atype = atype;
117 arrow->left = left;
118 if (GTK_WIDGET_DRAWABLE(arrow))
119 gtk_widget_queue_clear(GTK_WIDGET(arrow));
123 static gint
124 dia_arrow_preview_expose(GtkWidget *widget, GdkEventExpose *event)
126 DiaArrowPreview *arrow = DIA_ARROW_PREVIEW(widget);
127 GtkMisc *misc = GTK_MISC(widget);
128 gint width, height;
129 gint x, y;
130 gint extent;
131 GdkWindow *win;
132 GdkGC *gc;
133 GdkGCValues gcvalues;
134 GdkPoint pts[5];
136 if (GTK_WIDGET_DRAWABLE(widget)) {
137 width = widget->allocation.width - misc->xpad * 2;
138 height = widget->allocation.height - misc->ypad * 2;
139 extent = MIN(width, height);
140 x = (widget->allocation.x + misc->xpad);
141 y = (widget->allocation.y + misc->ypad);
143 win = widget->window;
144 gc = widget->style->fg_gc[widget->state];
146 /* increase line width */
147 gdk_gc_get_values(gc, &gcvalues);
148 gdk_gc_set_line_attributes(gc, 3, gcvalues.line_style,
149 gcvalues.cap_style, gcvalues.join_style);
150 switch (arrow->atype) {
151 case ARROW_NONE:
152 if (arrow->left)
153 gdk_draw_line(win, gc, x+5,y+height/2, x+width,y+height/2);
154 else
155 gdk_draw_line(win, gc, x,y+height/2, x+width-5,y+height/2);
156 break;
157 case ARROW_LINES:
158 if (arrow->left) {
159 gdk_draw_line(win, gc, x+5,y+height/2, x+width,y+height/2);
160 gdk_draw_line(win, gc, x+5,y+height/2, x+5+height/2,y+5);
161 gdk_draw_line(win, gc, x+5,y+height/2, x+5+height/2,y+height-5);
162 } else {
163 gdk_draw_line(win, gc, x,y+height/2, x+width-5,y+height/2);
164 gdk_draw_line(win, gc, x+width-5,y+height/2, x+width-5-height/2,y+5);
165 gdk_draw_line(win, gc, x+width-5,y+height/2, x+width-5-height/2,y+height-5);
167 break;
168 case ARROW_HOLLOW_TRIANGLE:
169 if (arrow->left) {
170 pts[0].x = x+5; pts[0].y = y+height/2;
171 pts[1].x = x+5+height/2; pts[1].y = y+5;
172 pts[2].x = x+5+height/2; pts[2].y = y+height-5;
173 pts[3].x = x+5; pts[3].y = y+height/2;
174 gdk_draw_polygon(win, gc, FALSE, pts, 4);
175 gdk_draw_line(win, gc, x+5+height/2, y+height/2, x+width, y+height/2);
176 } else {
177 pts[0].x = x+width-5; pts[0].y = y+height/2;
178 pts[1].x = x+width-5-height/2; pts[1].y = y+5;
179 pts[2].x = x+width-5-height/2; pts[2].y = y+height-5;
180 pts[3].x = x+width-5; pts[3].y = y+height/2;
181 gdk_draw_polygon(win, gc, FALSE, pts, 4);
182 gdk_draw_line(win, gc, x, y+height/2, x+width-5-height/2, y+height/2);
184 break;
185 case ARROW_UNFILLED_TRIANGLE:
186 if (arrow->left) {
187 pts[0].x = x+5; pts[0].y = y+height/2;
188 pts[1].x = x+5+height/2; pts[1].y = y+5;
189 pts[2].x = x+5+height/2; pts[2].y = y+height-5;
190 pts[3].x = x+5; pts[3].y = y+height/2;
191 gdk_draw_polygon(win, gc, FALSE, pts, 4);
192 gdk_draw_line(win, gc, x+5, y+height/2, x+width, y+height/2);
193 } else {
194 pts[0].x = x+width-5; pts[0].y = y+height/2;
195 pts[1].x = x+width-5-height/2; pts[1].y = y+5;
196 pts[2].x = x+width-5-height/2; pts[2].y = y+height-5;
197 pts[3].x = x+width-5; pts[3].y = y+height/2;
198 gdk_draw_polygon(win, gc, FALSE, pts, 4);
199 gdk_draw_line(win, gc, x, y+height/2, x+width-5, y+height/2);
201 break;
202 case ARROW_FILLED_TRIANGLE:
203 if (arrow->left) {
204 pts[0].x = x+5; pts[0].y = y+height/2;
205 pts[1].x = x+5+height/2; pts[1].y = y+5;
206 pts[2].x = x+5+height/2; pts[2].y = y+height-5;
207 pts[3].x = x+5; pts[3].y = y+height/2;
208 gdk_draw_polygon(win, gc, TRUE, pts, 4);
209 gdk_draw_polygon(win, gc, FALSE, pts, 4);
210 gdk_draw_line(win, gc, x+5+height/2, y+height/2, x+width, y+height/2);
211 } else {
212 pts[0].x = x+width-5; pts[0].y = y+height/2;
213 pts[1].x = x+width-5-height/2; pts[1].y = y+5;
214 pts[2].x = x+width-5-height/2; pts[2].y = y+height-5;
215 pts[3].x = x+width-5; pts[3].y = y+height/2;
216 gdk_draw_polygon(win, gc, TRUE, pts, 4);
217 gdk_draw_polygon(win, gc, FALSE, pts, 4);
218 gdk_draw_line(win, gc, x, y+height/2, x+width-5-height/2, y+height/2);
220 break;
221 case ARROW_HOLLOW_DIAMOND:
222 if (arrow->left) {
223 pts[0].x = x+5; pts[0].y = y+height/2;
224 pts[1].x = x+5+height/2; pts[1].y = y+5;
225 pts[2].x = x+5+height*3/4; pts[2].y = y+height/2;
226 pts[3].x = x+5+height/2; pts[3].y = y+height-5;
227 pts[4].x = x+5; pts[4].y = y+height/2;
228 gdk_draw_polygon(win, gc, FALSE, pts, 5);
229 gdk_draw_line(win, gc, x+5+height*3/4,y+height/2, x+width, y+height/2);
230 } else {
231 pts[0].x = x+width-5; pts[0].y = y+height/2;
232 pts[1].x = x+width-5-height/2; pts[1].y = y+5;
233 pts[2].x = x+width-5-height*3/4; pts[2].y = y+height/2;
234 pts[3].x = x+width-5-height/2; pts[3].y = y+height-5;
235 pts[4].x = x+width-5; pts[4].y = y+height/2;
236 gdk_draw_polygon(win, gc, FALSE, pts, 5);
237 gdk_draw_line(win, gc, x, y+height/2, x+width-5-height*3/4,y+height/2);
239 break;
240 case ARROW_FILLED_DIAMOND:
241 if (arrow->left) {
242 pts[0].x = x+5; pts[0].y = y+height/2;
243 pts[1].x = x+5+height/2; pts[1].y = y+5;
244 pts[2].x = x+5+height*3/4; pts[2].y = y+height/2;
245 pts[3].x = x+5+height/2; pts[3].y = y+height-5;
246 pts[4].x = x+5; pts[4].y = y+height/2;
247 gdk_draw_polygon(win, gc, TRUE, pts, 5);
248 gdk_draw_polygon(win, gc, FALSE, pts, 5);
249 gdk_draw_line(win, gc, x+5+height*3/4,y+height/2, x+width, y+height/2);
250 } else {
251 pts[0].x = x+width-5; pts[0].y = y+height/2;
252 pts[1].x = x+width-5-height/2; pts[1].y = y+5;
253 pts[2].x = x+width-5-height*3/4; pts[2].y = y+height/2;
254 pts[3].x = x+width-5-height/2; pts[3].y = y+height-5;
255 pts[4].x = x+width-5; pts[4].y = y+height/2;
256 gdk_draw_polygon(win, gc, TRUE, pts, 5);
257 gdk_draw_polygon(win, gc, FALSE, pts, 5);
258 gdk_draw_line(win, gc, x, y+height/2, x+width-5-height*3/4,y+height/2);
260 break;
261 case ARROW_SLASHED_CROSS:
262 if (arrow->left) {
263 gdk_draw_line(win, gc, x+5,y+height/2, x+width,y+height/2); /*line*/
264 gdk_draw_line(win, gc, x+5,y+height-5, x+height-5,y+5); /*slash*/
265 gdk_draw_line(win, gc, x+height/2,y+height-5, x+height/2,y+5);
266 /*cross */
267 } else {
268 gdk_draw_line(win, gc, x,y+height/2, x+width-5,y+height/2); /*line*/
269 gdk_draw_line(win, gc, x+width-height/2-5,y+height-5, x+width-5,y+5);
270 /*slash*/
271 gdk_draw_line(win, gc, x+width-height/2,y+height-5, x+width-height/2,
272 y+5); /*cross*/
274 break;
275 case ARROW_HALF_HEAD:
276 if (arrow->left) {
277 gdk_draw_line(win, gc, x+5,y+height/2, x+width,y+height/2);
278 gdk_draw_line(win, gc, x+5,y+height/2, x+5+height/2,y+5);
279 } else {
280 gdk_draw_line(win, gc, x,y+height/2, x+width-5,y+height/2);
281 gdk_draw_line(win, gc, x+width-5,y+height/2, x+width-5-height/2,
282 y+height-5);
284 break;
285 case ARROW_FILLED_ELLIPSE:
286 if (arrow->left) {
287 gdk_draw_line(win,gc,x+5+8,y+height/2,x+width,y+height/2);
288 gdk_draw_arc(win,gc,TRUE,x+5,y+height/2-6,12,12,0,64*360);
289 } else {
290 gdk_draw_line(win,gc,x,y+height/2,x+width-5-8,y+height/2);
291 gdk_draw_arc(win,gc,TRUE,x+width-5-12,y+height/2-6,12,12,0,64*360);
293 break;
294 case ARROW_HOLLOW_ELLIPSE:
295 if (arrow->left) {
296 gdk_draw_line(win,gc,x+5+8,y+height/2,x+width,y+height/2);
297 gdk_draw_arc(win,gc,FALSE,x+5,y+height/2-4,8,8,0,64*360);
298 } else {
299 gdk_draw_line(win,gc,x,y+height/2,x+width-5-8,y+height/2);
300 gdk_draw_arc(win,gc,FALSE,x+width-5-8,y+height/2-4,8,8,0,64*360);
302 break;
303 case ARROW_DOUBLE_HOLLOW_TRIANGLE:
304 if(arrow->left) {
305 pts[0].x = x+5; pts[0].y = y+height/2;
306 pts[1].x = x+5+height/2; pts[1].y = y+5;
307 pts[2].x = x+5+height/2; pts[2].y = y+height-5;
308 pts[3].x = x+5; pts[3].y = y+height/2;
309 gdk_draw_polygon(win, gc, FALSE, pts, 4);
310 pts[0].x = x+5+height/2; pts[0].y = y+height/2;
311 pts[1].x = x+5+height; pts[1].y = y+5;
312 pts[2].x = x+5+height; pts[2].y = y+height-5;
313 pts[3].x = x+5+height/2; pts[3].y = y+height/2;
314 gdk_draw_polygon(win, gc, FALSE, pts, 4);
315 gdk_draw_line(win, gc, x+5+height, y+height/2, x+width, y+height/2);
316 } else {
317 pts[0].x = x+width-5; pts[0].y = y+height/2;
318 pts[1].x = x+width-5-height/2; pts[1].y = y+5;
319 pts[2].x = x+width-5-height/2; pts[2].y = y+height-5;
320 pts[3].x = x+width-5; pts[3].y = y+height/2;
321 gdk_draw_polygon(win, gc, FALSE, pts, 4);
322 pts[0].x = x+width-5-height/2; pts[0].y = y+height/2;
323 pts[1].x = x+width-5-height; pts[1].y = y+5;
324 pts[2].x = x+width-5-height; pts[2].y = y+height-5;
325 pts[3].x = x+width-5-height/2; pts[3].y = y+height/2;
326 gdk_draw_polygon(win, gc, FALSE, pts, 4);
327 gdk_draw_line(win, gc, x, y+height/2, x+width-5-height, y+height/2);
329 break;
330 case ARROW_DOUBLE_FILLED_TRIANGLE:
331 if(arrow->left) {
332 pts[0].x = x+5; pts[0].y = y+height/2;
333 pts[1].x = x+5+height/2; pts[1].y = y+5;
334 pts[2].x = x+5+height/2; pts[2].y = y+height-5;
335 pts[3].x = x+5; pts[3].y = y+height/2;
336 gdk_draw_polygon(win, gc, TRUE, pts, 4);
337 gdk_draw_polygon(win, gc, FALSE, pts, 4);
338 pts[0].x = x+5+height/2; pts[0].y = y+height/2;
339 pts[1].x = x+5+height; pts[1].y = y+5;
340 pts[2].x = x+5+height; pts[2].y = y+height-5;
341 pts[3].x = x+5+height/2; pts[3].y = y+height/2;
342 gdk_draw_polygon(win, gc, TRUE, pts, 4);
343 gdk_draw_polygon(win, gc, FALSE, pts, 4);
344 gdk_draw_line(win, gc, x+5+height, y+height/2, x+width, y+height/2);
345 } else {
346 pts[0].x = x+width-5; pts[0].y = y+height/2;
347 pts[1].x = x+width-5-height/2; pts[1].y = y+5;
348 pts[2].x = x+width-5-height/2; pts[2].y = y+height-5;
349 pts[3].x = x+width-5; pts[3].y = y+height/2;
350 gdk_draw_polygon(win, gc, TRUE, pts, 4);
351 gdk_draw_polygon(win, gc, FALSE, pts, 4);
352 pts[0].x = x+width-5-height/2; pts[0].y = y+height/2;
353 pts[1].x = x+width-5-height; pts[1].y = y+5;
354 pts[2].x = x+width-5-height; pts[2].y = y+height-5;
355 pts[3].x = x+width-5-height/2; pts[3].y = y+height/2;
356 gdk_draw_polygon(win, gc, TRUE, pts, 4);
357 gdk_draw_polygon(win, gc, FALSE, pts, 4);
358 gdk_draw_line(win, gc, x, y+height/2, x+width-5-height, y+height/2);
360 break;
361 case ARROW_FILLED_DOT:
362 if (arrow->left) {
363 gdk_draw_line(win,gc,x+5+6,y+height/2,x+width,y+height/2);
364 gdk_draw_line(win,gc,x+5+6,y,x+5+6,y+height);
365 gdk_draw_arc(win,gc,TRUE,x+5,y+height/2-6,12,12,0,64*360);
366 } else {
367 gdk_draw_line(win,gc,x,y+height/2,x+width-5-6,y+height/2);
368 gdk_draw_line(win,gc,x+width-5-6,y,x+width-5-6,y+height);
369 gdk_draw_arc(win,gc,TRUE,x+width-5-12,y+height/2-6,12,12,0,64*360);
371 break;
372 case ARROW_BLANKED_DOT:
373 if (arrow->left) {
374 gdk_draw_line(win,gc,x+5+6,y+height/2,x+width,y+height/2);
375 gdk_draw_line(win,gc,x+5+6,y,x+5+6,y+height);
376 gdk_draw_arc(win,gc,FALSE,x+5,y+height/2-6,12,12,0,64*360);
377 } else {
378 gdk_draw_line(win,gc,x,y+height/2,x+width-5-6,y+height/2);
379 gdk_draw_line(win,gc,x+width-5-6,y,x+width-5-6,y+height);
380 gdk_draw_arc(win,gc,FALSE,x+width-5-12,y+height/2-6,12,12,0,64*360);
382 break;
383 case ARROW_DIMENSION_ORIGIN:
384 if (arrow->left) {
385 gdk_draw_line(win,gc,x+5+12,y+height/2,x+width,y+height/2);
386 gdk_draw_line(win,gc,x+5+6,y,x+5+6,y+height);
387 gdk_draw_arc(win,gc,FALSE,x+5,y+height/2-6,12,12,0,64*360);
388 } else {
389 gdk_draw_line(win,gc,x,y+height/2,x+width-5-12,y+height/2);
390 gdk_draw_line(win,gc,x+width-5-6,y,x+width-5-6,y+height);
391 gdk_draw_arc(win,gc,FALSE,x+width-5-12,y+height/2-6,12,12,0,64*360);
393 break;
394 case ARROW_FILLED_BOX:
395 if (arrow->left) {
396 pts[0].x = x+5; pts[0].y = y+height/2-6;
397 pts[1].x = x+5; pts[1].y = y+height/2+6;
398 pts[2].x = x+5+12; pts[2].y = y+height/2+6;
399 pts[3].x = x+5+12; pts[3].y = y+height/2-6;
400 gdk_draw_line(win,gc,x+5+12,y+height/2,x+width,y+height/2);
401 gdk_draw_line(win,gc,x+5+6,y,x+5+6,y+height);
402 gdk_draw_polygon(win, gc, TRUE, pts, 4);
403 } else {
404 pts[0].x = x+width-5; pts[0].y = y+height/2-6;
405 pts[1].x = x+width-5; pts[1].y = y+height/2+6;
406 pts[2].x = x+width-5-12; pts[2].y = y+height/2+6;
407 pts[3].x = x+width-5-12; pts[3].y = y+height/2-6;
408 gdk_draw_line(win,gc,x,y+height/2,x+width-5-12,y+height/2);
409 gdk_draw_line(win,gc,x+width-5-6,y,x+width-5-6,y+height);
410 gdk_draw_polygon(win, gc, TRUE, pts, 4);
412 break;
413 case ARROW_BLANKED_BOX:
414 if (arrow->left) {
415 pts[0].x = x+5; pts[0].y = y+height/2-6;
416 pts[1].x = x+5; pts[1].y = y+height/2+6;
417 pts[2].x = x+5+12; pts[2].y = y+height/2+6;
418 pts[3].x = x+5+12; pts[3].y = y+height/2-6;
419 gdk_draw_line(win,gc,x+5+12,y+height/2,x+width,y+height/2);
420 gdk_draw_line(win,gc,x+5+6,y,x+5+6,y+height);
421 gdk_draw_polygon(win, gc, FALSE, pts, 4);
422 } else {
423 pts[0].x = x+width-5; pts[0].y = y+height/2-6;
424 pts[1].x = x+width-5; pts[1].y = y+height/2+6;
425 pts[2].x = x+width-5-12; pts[2].y = y+height/2+6;
426 pts[3].x = x+width-5-12; pts[3].y = y+height/2-6;
427 gdk_draw_line(win,gc,x,y+height/2,x+width-5-12,y+height/2);
428 gdk_draw_line(win,gc,x+width-5-6,y,x+width-5-6,y+height);
429 gdk_draw_polygon(win, gc, FALSE, pts, 4);
431 break;
432 case ARROW_SLASH_ARROW:
433 if (arrow->left) {
434 gdk_draw_line(win, gc, x+height/2,y+height/2, x+width,y+height/2); /*line*/
435 gdk_draw_line(win, gc, x+5,y+height-5, x+height-5,y+5); /*slash*/
436 gdk_draw_line(win, gc, x+height/2,y+height-4, x+height/2,y+4);
437 /*cross */
438 } else {
439 gdk_draw_line(win, gc, x,y+height/2, x+width-height/2,y+height/2); /*line*/
440 gdk_draw_line(win, gc, x+width-height/2-5,y+height-5, x+width-5,y+5);
441 /*slash*/
442 gdk_draw_line(win, gc, x+width-height/2,y+height-4, x+width-height/2,
443 y+4); /*cross*/
445 break;
446 case ARROW_INTEGRAL_SYMBOL:
447 if (arrow->left) {
448 gdk_draw_line(win, gc, x+height/2,y+height/2, x+width,y+height/2); /*line*/
449 gdk_draw_arc(win,gc,FALSE,x+height/2-12,y+height/2-9,
450 12,12,64*270,64*60);
451 gdk_draw_arc(win,gc,FALSE,x+height/2+1,y+height/2-5,
452 12,12,64*90,64*60);
453 gdk_draw_line(win, gc, x+height/2,y+height-4, x+height/2,y+4);
454 } else {
455 gdk_draw_line(win, gc, x,y+height/2, x+width-height/2,y+height/2); /*line*/
456 gdk_draw_arc(win,gc,FALSE,x+width-height/2-13,y+height/2-8,
457 12,12,64*270,64*60);
458 gdk_draw_arc(win,gc,FALSE,x+width-height/2-0,y+height/2-5,
459 12,12,64*90,64*60);
460 gdk_draw_line(win, gc, x+width-height/2,y+height-4, x+width-height/2,
461 y+4); /*cross*/
463 break;
465 gdk_gc_set_line_attributes(gc, gcvalues.line_width, gcvalues.line_style,
466 gcvalues.cap_style, gcvalues.join_style);
468 return TRUE;
472 /* --------------- DiaLinePreview -------------------------------- */
473 typedef struct _DiaLinePreview DiaLinePreview;
474 typedef struct _DiaLinePreviewClass DiaLinePreviewClass;
476 static GtkType dia_line_preview_get_type (void);
477 static void dia_line_preview_set(DiaLinePreview *line, LineStyle lstyle);
478 static GtkWidget *dia_line_preview_new (LineStyle lstyle);
480 #define DIA_LINE_PREVIEW(obj) (GTK_CHECK_CAST((obj),dia_line_preview_get_type(), DiaLinePreview))
481 #define DIA_LINE_PREVIEW_CLASS(obj) (GTK_CHECK_CLASS_CAST((obj), dia_line_preview_get_type(), DiaLinePreviewClass))
483 struct _DiaLinePreview
485 GtkMisc misc;
486 LineStyle lstyle;
488 struct _DiaLinePreviewClass
490 GtkMiscClass parent_class;
493 static void dia_line_preview_class_init (DiaLinePreviewClass *klass);
494 static void dia_line_preview_init (DiaLinePreview *arrow);
495 static gint dia_line_preview_expose (GtkWidget *widget,
496 GdkEventExpose *event);
498 static GtkType
499 dia_line_preview_get_type (void)
501 static GtkType line_type = 0;
503 if (!line_type) {
504 static const GtkTypeInfo line_info = {
505 "DiaLinePreview",
506 sizeof (DiaLinePreview),
507 sizeof (DiaLinePreviewClass),
508 (GtkClassInitFunc) dia_line_preview_class_init,
509 (GtkObjectInitFunc) dia_line_preview_init,
510 /* reserved_1 */ NULL,
511 /* reserved_2 */ NULL,
512 (GtkClassInitFunc) NULL,
514 line_type = gtk_type_unique (GTK_TYPE_MISC, &line_info);
516 return line_type;
519 static void
520 dia_line_preview_class_init (DiaLinePreviewClass *class)
522 GtkWidgetClass *widget_class;
524 widget_class = (GtkWidgetClass *)class;
525 widget_class->expose_event = dia_line_preview_expose;
528 static void
529 dia_line_preview_init (DiaLinePreview *line)
531 GTK_WIDGET_SET_FLAGS (line, GTK_NO_WINDOW);
533 GTK_WIDGET (line)->requisition.width = 40 + GTK_MISC (line)->xpad * 2;
534 GTK_WIDGET (line)->requisition.height = 20 + GTK_MISC (line)->ypad * 2;
537 line->lstyle = LINESTYLE_SOLID;
540 static GtkWidget *
541 dia_line_preview_new (LineStyle lstyle)
543 DiaLinePreview *line = gtk_type_new (dia_line_preview_get_type());
545 line->lstyle = lstyle;
546 return GTK_WIDGET(line);
549 static void
550 dia_line_preview_set(DiaLinePreview *line, LineStyle lstyle)
552 if (line->lstyle != lstyle) {
553 line->lstyle = lstyle;
554 if (GTK_WIDGET_DRAWABLE(line))
555 gtk_widget_queue_clear(GTK_WIDGET(line));
559 static gint
560 dia_line_preview_expose(GtkWidget *widget, GdkEventExpose *event)
562 DiaLinePreview *line = DIA_LINE_PREVIEW(widget);
563 GtkMisc *misc = GTK_MISC(widget);
564 gint width, height;
565 gint x, y;
566 gint extent;
567 GdkWindow *win;
568 GdkGC *gc;
569 GdkGCValues gcvalues;
570 char dash_list[6];
572 if (GTK_WIDGET_DRAWABLE(widget)) {
573 width = widget->allocation.width - misc->xpad * 2;
574 height = widget->allocation.height - misc->ypad * 2;
575 extent = MIN(width, height);
576 x = (widget->allocation.x + misc->xpad);
577 y = (widget->allocation.y + misc->ypad);
579 win = widget->window;
580 gc = widget->style->fg_gc[widget->state];
582 /* increase line width */
583 gdk_gc_get_values(gc, &gcvalues);
584 switch (line->lstyle) {
585 case LINESTYLE_SOLID:
586 gdk_gc_set_line_attributes(gc, 3, GDK_LINE_SOLID,
587 gcvalues.cap_style, gcvalues.join_style);
588 break;
589 case LINESTYLE_DASHED:
590 gdk_gc_set_line_attributes(gc, 3, GDK_LINE_ON_OFF_DASH,
591 gcvalues.cap_style, gcvalues.join_style);
592 dash_list[0] = 10;
593 dash_list[1] = 10;
594 gdk_gc_set_dashes(gc, 0, dash_list, 2);
595 break;
596 case LINESTYLE_DASH_DOT:
597 gdk_gc_set_line_attributes(gc, 3, GDK_LINE_ON_OFF_DASH,
598 gcvalues.cap_style, gcvalues.join_style);
599 dash_list[0] = 10;
600 dash_list[1] = 4;
601 dash_list[2] = 2;
602 dash_list[3] = 4;
603 gdk_gc_set_dashes(gc, 0, dash_list, 4);
604 break;
605 case LINESTYLE_DASH_DOT_DOT:
606 gdk_gc_set_line_attributes(gc, 3, GDK_LINE_ON_OFF_DASH,
607 gcvalues.cap_style, gcvalues.join_style);
608 dash_list[0] = 10;
609 dash_list[1] = 2;
610 dash_list[2] = 2;
611 dash_list[3] = 2;
612 dash_list[4] = 2;
613 dash_list[5] = 2;
614 gdk_gc_set_dashes(gc, 0, dash_list, 6);
615 break;
616 case LINESTYLE_DOTTED:
617 gdk_gc_set_line_attributes(gc, 3, GDK_LINE_ON_OFF_DASH,
618 gcvalues.cap_style, gcvalues.join_style);
619 dash_list[0] = 2;
620 dash_list[1] = 2;
621 gdk_gc_set_dashes(gc, 0, dash_list, 2);
622 break;
624 gdk_draw_line(win, gc, x, y+height/2, x+width, y+height/2);
625 gdk_gc_set_line_attributes(gc, gcvalues.line_width, gcvalues.line_style,
626 gcvalues.cap_style, gcvalues.join_style);
628 return TRUE;
631 /* ------- Code for DiaArrowChooser ----------------------- */
632 static GtkType dia_arrow_chooser_get_type (void);
634 static gint close_and_hide(GtkWidget *wid, GdkEventAny *event) {
635 gtk_widget_hide(wid);
636 return TRUE;
638 static const char *button_menu_key = "dia-button-menu";
639 static const char *menuitem_enum_key = "dia-menuitem-value";
642 #define DIA_ARROW_CHOOSER(obj) (GTK_CHECK_CAST((obj),dia_arrow_chooser_get_type(), DiaArrowChooser))
643 #define DIA_ARROW_CHOOSER_CLASS(obj) (GTK_CHECK_CLASS_CAST((obj), dia_arrow_chooser_get_type(), DiaArrowChooserClass))
645 typedef struct _DiaArrowChooser DiaArrowChooser;
646 typedef struct _DiaArrowChooserClass DiaArrowChooserClass;
648 struct _DiaArrowChooser
650 GtkButton button;
651 DiaArrowPreview *preview;
652 Arrow arrow;
653 gboolean left;
655 DiaChangeArrowCallback callback;
656 gpointer user_data;
658 GtkWidget *dialog;
659 DiaArrowSelector *selector;
661 struct _DiaArrowChooserClass
663 GtkButtonClass parent_class;
666 static void dia_arrow_chooser_class_init (DiaArrowChooserClass *klass);
667 static void dia_arrow_chooser_init (DiaArrowChooser *arrow);
668 static gint dia_arrow_chooser_event (GtkWidget *widget,
669 GdkEvent *event);
670 static void dia_arrow_chooser_dialog_ok (DiaArrowChooser *arrow);
671 static void dia_arrow_chooser_dialog_cancel (DiaArrowChooser *arrow);
672 static void dia_arrow_chooser_change_arrow_type (GtkMenuItem *mi,
673 DiaArrowChooser *arrow);
675 static GtkType
676 dia_arrow_chooser_get_type (void)
678 static GtkType arrow_type = 0;
680 if (!arrow_type) {
681 static const GtkTypeInfo arrow_info = {
682 "DiaArrowChooser",
683 sizeof (DiaArrowChooser),
684 sizeof (DiaArrowChooserClass),
685 (GtkClassInitFunc) dia_arrow_chooser_class_init,
686 (GtkObjectInitFunc) dia_arrow_chooser_init,
687 /* reserved_1 */ NULL,
688 /* reserved_2 */ NULL,
689 (GtkClassInitFunc) NULL,
691 arrow_type = gtk_type_unique (GTK_TYPE_BUTTON, &arrow_info);
693 return arrow_type;
696 static void
697 dia_arrow_chooser_class_init (DiaArrowChooserClass *class)
699 GtkWidgetClass *widget_class;
701 widget_class = (GtkWidgetClass *)class;
702 widget_class->event = dia_arrow_chooser_event;
705 static void
706 dia_arrow_chooser_init (DiaArrowChooser *arrow)
708 GtkWidget *wid;
710 arrow->left = FALSE;
711 arrow->arrow.type = ARROW_NONE;
712 arrow->arrow.length = DEFAULT_ARROW_LENGTH;
713 arrow->arrow.width = DEFAULT_ARROW_WIDTH;
715 wid = dia_arrow_preview_new(ARROW_NONE, arrow->left);
716 gtk_container_add(GTK_CONTAINER(arrow), wid);
717 gtk_widget_show(wid);
718 arrow->preview = DIA_ARROW_PREVIEW(wid);
720 arrow->dialog = wid = gtk_dialog_new();
721 gtk_window_set_title(GTK_WINDOW(wid), _("Arrow Properties"));
722 gtk_signal_connect(GTK_OBJECT(wid), "delete_event",
723 GTK_SIGNAL_FUNC(close_and_hide), NULL);
725 wid = dia_arrow_selector_new();
726 gtk_container_set_border_width(GTK_CONTAINER(wid), 5);
727 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(arrow->dialog)->vbox), wid,
728 TRUE, TRUE, 0);
729 gtk_widget_show(wid);
730 arrow->selector = DIAARROWSELECTOR(wid);
732 wid = gtk_button_new_with_label(_("OK"));
733 GTK_WIDGET_SET_FLAGS(wid, GTK_CAN_DEFAULT);
734 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(arrow->dialog)->action_area),wid);
735 gtk_widget_grab_default(wid);
736 gtk_signal_connect_object(GTK_OBJECT(wid), "clicked",
737 GTK_SIGNAL_FUNC(dia_arrow_chooser_dialog_ok),
738 GTK_OBJECT(arrow));
739 gtk_widget_show(wid);
741 wid = gtk_button_new_with_label(_("Cancel"));
742 GTK_WIDGET_SET_FLAGS(wid, GTK_CAN_DEFAULT);
743 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(arrow->dialog)->action_area),wid);
744 gtk_signal_connect_object(GTK_OBJECT(wid), "clicked",
745 GTK_SIGNAL_FUNC(dia_arrow_chooser_dialog_cancel),
746 GTK_OBJECT(arrow));
747 gtk_widget_show(wid);
750 GtkWidget *
751 dia_arrow_chooser_new(gboolean left, DiaChangeArrowCallback callback,
752 gpointer user_data)
754 DiaArrowChooser *chooser = gtk_type_new(dia_arrow_chooser_get_type());
755 GtkWidget *menu, *mi, *ar;
756 gint i;
758 chooser->left = left;
759 dia_arrow_preview_set(chooser->preview, chooser->preview->atype, left);
760 chooser->callback = callback;
761 chooser->user_data = user_data;
763 menu = gtk_menu_new();
764 gtk_object_set_data_full(GTK_OBJECT(chooser), button_menu_key, menu,
765 (GtkDestroyNotify)gtk_widget_unref);
766 for (i = 0; i <= ARROW_INTEGRAL_SYMBOL; i++) {
767 mi = gtk_menu_item_new();
768 gtk_object_set_data(GTK_OBJECT(mi), menuitem_enum_key, GINT_TO_POINTER(i));
769 ar = dia_arrow_preview_new(i, left);
770 gtk_container_add(GTK_CONTAINER(mi), ar);
771 gtk_widget_show(ar);
772 gtk_signal_connect(GTK_OBJECT(mi), "activate",
773 GTK_SIGNAL_FUNC(dia_arrow_chooser_change_arrow_type),
774 chooser);
775 gtk_container_add(GTK_CONTAINER(menu), mi);
776 gtk_widget_show(mi);
778 mi = gtk_menu_item_new_with_label(_("Details..."));
779 gtk_signal_connect_object(GTK_OBJECT(mi), "activate",
780 GTK_SIGNAL_FUNC(gtk_widget_show),
781 GTK_OBJECT(chooser->dialog));
782 gtk_container_add(GTK_CONTAINER(menu), mi);
783 gtk_widget_show(mi);
785 return GTK_WIDGET(chooser);
788 static gint
789 dia_arrow_chooser_event(GtkWidget *widget, GdkEvent *event)
791 if (event->type == GDK_BUTTON_PRESS && event->button.button == 1) {
792 GtkMenu *menu = gtk_object_get_data(GTK_OBJECT(widget), button_menu_key);
793 gtk_menu_popup(menu, NULL, NULL, NULL, NULL,
794 event->button.button, event->button.time);
795 return TRUE;
797 return FALSE;
800 static void
801 dia_arrow_chooser_dialog_ok (DiaArrowChooser *arrow)
803 Arrow new_arrow = dia_arrow_selector_get_arrow(arrow->selector);
805 if (new_arrow.type != arrow->arrow.type ||
806 new_arrow.length != arrow->arrow.length ||
807 new_arrow.width != arrow->arrow.width) {
808 arrow->arrow = new_arrow;
809 dia_arrow_preview_set(arrow->preview, new_arrow.type, arrow->left);
810 if (arrow->callback)
811 (* arrow->callback)(arrow->arrow, arrow->user_data);
813 gtk_widget_hide(arrow->dialog);
815 static void
816 dia_arrow_chooser_dialog_cancel (DiaArrowChooser *arrow)
818 dia_arrow_selector_set_arrow(arrow->selector, arrow->arrow);
819 gtk_widget_hide(arrow->dialog);
822 static void
823 dia_arrow_chooser_change_arrow_type(GtkMenuItem *mi, DiaArrowChooser *arrow)
825 ArrowType atype = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(mi),
826 menuitem_enum_key));
828 if (arrow->arrow.type != atype) {
829 dia_arrow_preview_set(arrow->preview, atype, arrow->left);
830 arrow->arrow.type = atype;
831 dia_arrow_selector_set_arrow(arrow->selector, arrow->arrow);
832 if (arrow->callback)
833 (* arrow->callback)(arrow->arrow, arrow->user_data);
838 /* ------- Code for DiaLineChooser ---------------------- */
839 static GtkType dia_line_chooser_get_type (void);
841 #define DIA_LINE_CHOOSER(obj) (GTK_CHECK_CAST((obj),dia_line_chooser_get_type(), DiaLineChooser))
842 #define DIA_LINE_CHOOSER_CLASS(obj) (GTK_CHECK_CLASS_CAST((obj), dia_line_chooser_get_type(), DiaLineChooserClass))
844 typedef struct _DiaLineChooser DiaLineChooser;
845 typedef struct _DiaLineChooserClass DiaLineChooserClass;
847 struct _DiaLineChooser
849 GtkButton button;
850 DiaLinePreview *preview;
851 LineStyle lstyle;
852 real dash_length;
854 DiaChangeLineCallback callback;
855 gpointer user_data;
857 GtkWidget *dialog;
858 DiaLineStyleSelector *selector;
860 struct _DiaLineChooserClass
862 GtkButtonClass parent_class;
865 static void dia_line_chooser_class_init (DiaLineChooserClass *klass);
866 static void dia_line_chooser_init (DiaLineChooser *arrow);
867 static gint dia_line_chooser_event (GtkWidget *widget,
868 GdkEvent *event);
869 static void dia_line_chooser_dialog_ok (DiaLineChooser *lchooser);
870 static void dia_line_chooser_dialog_cancel (DiaLineChooser *lchooser);
871 static void dia_line_chooser_change_line_style (GtkMenuItem *mi,
872 DiaLineChooser *lchooser);
874 static GtkType
875 dia_line_chooser_get_type (void)
877 static GtkType arrow_type = 0;
879 if (!arrow_type) {
880 static const GtkTypeInfo arrow_info = {
881 "DiaLineChooser",
882 sizeof (DiaLineChooser),
883 sizeof (DiaLineChooserClass),
884 (GtkClassInitFunc) dia_line_chooser_class_init,
885 (GtkObjectInitFunc) dia_line_chooser_init,
886 /* reserved_1 */ NULL,
887 /* reserved_2 */ NULL,
888 (GtkClassInitFunc) NULL,
890 arrow_type = gtk_type_unique (GTK_TYPE_BUTTON, &arrow_info);
892 return arrow_type;
895 static void
896 dia_line_chooser_class_init (DiaLineChooserClass *class)
898 GtkWidgetClass *widget_class;
900 widget_class = (GtkWidgetClass *)class;
901 widget_class->event = dia_line_chooser_event;
904 static void
905 dia_line_chooser_init (DiaLineChooser *lchooser)
907 GtkWidget *wid;
908 GtkWidget *menu, *mi, *ln;
909 gint i;
911 lchooser->lstyle = LINESTYLE_SOLID;
912 lchooser->dash_length = DEFAULT_LINESTYLE_DASHLEN;
914 wid = dia_line_preview_new(LINESTYLE_SOLID);
915 gtk_container_add(GTK_CONTAINER(lchooser), wid);
916 gtk_widget_show(wid);
917 lchooser->preview = DIA_LINE_PREVIEW(wid);
919 lchooser->dialog = wid = gtk_dialog_new();
920 gtk_window_set_title(GTK_WINDOW(wid), _("Line Style Properties"));
921 gtk_signal_connect(GTK_OBJECT(wid), "delete_event",
922 GTK_SIGNAL_FUNC(close_and_hide), NULL);
924 wid = dia_line_style_selector_new();
925 gtk_container_set_border_width(GTK_CONTAINER(wid), 5);
926 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(lchooser->dialog)->vbox), wid,
927 TRUE, TRUE, 0);
928 gtk_widget_show(wid);
929 lchooser->selector = DIALINESTYLESELECTOR(wid);
931 wid = gtk_button_new_with_label(_("OK"));
932 GTK_WIDGET_SET_FLAGS(wid, GTK_CAN_DEFAULT);
933 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(lchooser->dialog)->action_area),
934 wid);
935 gtk_widget_grab_default(wid);
936 gtk_signal_connect_object(GTK_OBJECT(wid), "clicked",
937 GTK_SIGNAL_FUNC(dia_line_chooser_dialog_ok),
938 GTK_OBJECT(lchooser));
939 gtk_widget_show(wid);
941 wid = gtk_button_new_with_label(_("Cancel"));
942 GTK_WIDGET_SET_FLAGS(wid, GTK_CAN_DEFAULT);
943 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(lchooser->dialog)->action_area),
944 wid);
945 gtk_signal_connect_object(GTK_OBJECT(wid), "clicked",
946 GTK_SIGNAL_FUNC(dia_line_chooser_dialog_cancel),
947 GTK_OBJECT(lchooser));
949 menu = gtk_menu_new();
950 gtk_object_set_data_full(GTK_OBJECT(lchooser), button_menu_key, menu,
951 (GtkDestroyNotify)gtk_widget_unref);
952 for (i = 0; i <= LINESTYLE_DOTTED; i++) {
953 mi = gtk_menu_item_new();
954 gtk_object_set_data(GTK_OBJECT(mi), menuitem_enum_key, GINT_TO_POINTER(i));
955 ln = dia_line_preview_new(i);
956 gtk_container_add(GTK_CONTAINER(mi), ln);
957 gtk_widget_show(ln);
958 gtk_signal_connect(GTK_OBJECT(mi), "activate",
959 GTK_SIGNAL_FUNC(dia_line_chooser_change_line_style),
960 lchooser);
961 gtk_container_add(GTK_CONTAINER(menu), mi);
962 gtk_widget_show(mi);
964 mi = gtk_menu_item_new_with_label(_("Details..."));
965 gtk_signal_connect_object(GTK_OBJECT(mi), "activate",
966 GTK_SIGNAL_FUNC(gtk_widget_show),
967 GTK_OBJECT(lchooser->dialog));
968 gtk_container_add(GTK_CONTAINER(menu), mi);
969 gtk_widget_show(mi);
971 gtk_widget_show(wid);
974 GtkWidget *
975 dia_line_chooser_new(DiaChangeLineCallback callback,
976 gpointer user_data)
978 DiaLineChooser *chooser = gtk_type_new(dia_line_chooser_get_type());
980 chooser->callback = callback;
981 chooser->user_data = user_data;
983 return GTK_WIDGET(chooser);
986 static gint
987 dia_line_chooser_event(GtkWidget *widget, GdkEvent *event)
989 if (event->type == GDK_BUTTON_PRESS && event->button.button == 1) {
990 GtkMenu *menu = gtk_object_get_data(GTK_OBJECT(widget), button_menu_key);
991 gtk_menu_popup(menu, NULL, NULL, NULL, NULL,
992 event->button.button, event->button.time);
993 return TRUE;
995 return FALSE;
998 static void
999 dia_line_chooser_dialog_ok (DiaLineChooser *lchooser)
1001 LineStyle new_style;
1002 real new_dash;
1004 dia_line_style_selector_get_linestyle(lchooser->selector,
1005 &new_style, &new_dash);
1006 if (new_style != lchooser->lstyle || new_dash != lchooser->dash_length) {
1007 lchooser->lstyle = new_style;
1008 lchooser->dash_length = new_dash;
1009 dia_line_preview_set(lchooser->preview, new_style);
1010 if (lchooser->callback)
1011 (* lchooser->callback)(new_style, new_dash, lchooser->user_data);
1013 gtk_widget_hide(lchooser->dialog);
1015 static void
1016 dia_line_chooser_dialog_cancel (DiaLineChooser *lchooser)
1018 dia_line_style_selector_set_linestyle(lchooser->selector, lchooser->lstyle,
1019 lchooser->dash_length);
1020 gtk_widget_hide(lchooser->dialog);
1023 static void
1024 dia_line_chooser_change_line_style(GtkMenuItem *mi, DiaLineChooser *lchooser)
1026 LineStyle lstyle = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(mi),
1027 menuitem_enum_key));
1029 if (lchooser->lstyle != lstyle) {
1030 dia_line_preview_set(lchooser->preview, lstyle);
1031 lchooser->lstyle = lstyle;
1032 dia_line_style_selector_set_linestyle(lchooser->selector, lchooser->lstyle,
1033 lchooser->dash_length);
1034 if (lchooser->callback)
1035 (* lchooser->callback)(lchooser->lstyle, lchooser->dash_length,
1036 lchooser->user_data);