added gas bottle shape
[dia.git] / app / lineprops_area.c
blobab3b6c4555210d99396fc6840b83a419ae02b05f
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 #define DIA_ARROW_PREVIEW(obj) (GTK_CHECK_CAST((obj),dia_arrow_preview_get_type(), DiaArrowPreview))
34 #define DIA_ARROW_PREVIEW_CLASS(obj) (GTK_CHECK_CLASS_CAST((obj), dia_arrow_preview_get_type(), DiaArrowPreviewClass))
36 typedef struct _DiaArrowPreview DiaArrowPreview;
37 typedef struct _DiaArrowPreviewClass DiaArrowPreviewClass;
39 struct _DiaArrowPreview
41 GtkMisc misc;
42 ArrowType atype;
43 gboolean left;
45 struct _DiaArrowPreviewClass
47 GtkMiscClass parent_class;
50 static void dia_arrow_preview_class_init (DiaArrowPreviewClass *klass);
51 static void dia_arrow_preview_init (DiaArrowPreview *arrow);
52 static gint dia_arrow_preview_expose (GtkWidget *widget,
53 GdkEventExpose *event);
55 GtkType
56 dia_arrow_preview_get_type (void)
58 static GtkType arrow_type = 0;
60 if (!arrow_type) {
61 static const GtkTypeInfo arrow_info = {
62 "DiaArrowPreview",
63 sizeof (DiaArrowPreview),
64 sizeof (DiaArrowPreviewClass),
65 (GtkClassInitFunc) dia_arrow_preview_class_init,
66 (GtkObjectInitFunc) dia_arrow_preview_init,
67 /* reserved_1 */ NULL,
68 /* reserved_2 */ NULL,
69 (GtkClassInitFunc) NULL,
71 arrow_type = gtk_type_unique (GTK_TYPE_MISC, &arrow_info);
73 return arrow_type;
76 static void
77 dia_arrow_preview_class_init (DiaArrowPreviewClass *class)
79 GtkWidgetClass *widget_class;
81 widget_class = (GtkWidgetClass *)class;
82 widget_class->expose_event = dia_arrow_preview_expose;
85 static void
86 dia_arrow_preview_init (DiaArrowPreview *arrow)
88 GTK_WIDGET_SET_FLAGS (arrow, GTK_NO_WINDOW);
90 GTK_WIDGET (arrow)->requisition.width = 30 + GTK_MISC (arrow)->xpad * 2;
91 GTK_WIDGET (arrow)->requisition.height = 20 + GTK_MISC (arrow)->ypad * 2;
93 arrow->atype = ARROW_NONE;
94 arrow->left = TRUE;
97 GtkWidget *
98 dia_arrow_preview_new (ArrowType atype, gboolean left)
100 DiaArrowPreview *arrow = gtk_type_new (dia_arrow_preview_get_type());
102 arrow->atype = atype;
103 arrow->left = left;
104 return GTK_WIDGET(arrow);
107 void
108 dia_arrow_preview_set(DiaArrowPreview *arrow, ArrowType atype, gboolean left)
110 if (arrow->atype != atype || arrow->left != left) {
111 arrow->atype = atype;
112 arrow->left = left;
113 if (GTK_WIDGET_DRAWABLE(arrow))
114 gtk_widget_queue_clear(GTK_WIDGET(arrow));
118 static gint
119 dia_arrow_preview_expose(GtkWidget *widget, GdkEventExpose *event)
121 DiaArrowPreview *arrow = DIA_ARROW_PREVIEW(widget);
122 GtkMisc *misc = GTK_MISC(widget);
123 gint width, height;
124 gint x, y;
125 gint extent;
126 GdkWindow *win;
127 GdkGC *gc;
128 GdkGCValues gcvalues;
129 GdkPoint pts[5];
131 if (GTK_WIDGET_DRAWABLE(widget)) {
132 width = widget->allocation.width - misc->xpad * 2;
133 height = widget->allocation.height - misc->ypad * 2;
134 extent = MIN(width, height);
135 x = (widget->allocation.x + misc->xpad);
136 y = (widget->allocation.y + misc->ypad);
138 win = widget->window;
139 gc = widget->style->fg_gc[widget->state];
141 /* increase line width */
142 gdk_gc_get_values(gc, &gcvalues);
143 gdk_gc_set_line_attributes(gc, 3, gcvalues.line_style,
144 gcvalues.cap_style, gcvalues.join_style);
145 switch (arrow->atype) {
146 case ARROW_NONE:
147 if (arrow->left)
148 gdk_draw_line(win, gc, x+5,y+height/2, x+width,y+height/2);
149 else
150 gdk_draw_line(win, gc, x,y+height/2, x+width-5,y+height/2);
151 break;
152 case ARROW_LINES:
153 if (arrow->left) {
154 gdk_draw_line(win, gc, x+5,y+height/2, x+width,y+height/2);
155 gdk_draw_line(win, gc, x+5,y+height/2, x+5+height/2,y+5);
156 gdk_draw_line(win, gc, x+5,y+height/2, x+5+height/2,y+height-5);
157 } else {
158 gdk_draw_line(win, gc, x,y+height/2, x+width-5,y+height/2);
159 gdk_draw_line(win, gc, x+width-5,y+height/2, x+width-5-height/2,y+5);
160 gdk_draw_line(win, gc, x+width-5,y+height/2, x+width-5-height/2,y+height-5);
162 break;
163 case ARROW_HOLLOW_TRIANGLE:
164 if (arrow->left) {
165 pts[0].x = x+5; pts[0].y = y+height/2;
166 pts[1].x = x+5+height/2; pts[1].y = y+5;
167 pts[2].x = x+5+height/2; pts[2].y = y+height-5;
168 pts[3].x = x+5; pts[3].y = y+height/2;
169 gdk_draw_polygon(win, gc, FALSE, pts, 4);
170 gdk_draw_line(win, gc, x+5+height/2, y+height/2, x+width, y+height/2);
171 } else {
172 pts[0].x = x+width-5; pts[0].y = y+height/2;
173 pts[1].x = x+width-5-height/2; pts[1].y = y+5;
174 pts[2].x = x+width-5-height/2; pts[2].y = y+height-5;
175 pts[3].x = x+width-5; pts[3].y = y+height/2;
176 gdk_draw_polygon(win, gc, FALSE, pts, 4);
177 gdk_draw_line(win, gc, x, y+height/2, x+width-5-height/2, y+height/2);
179 break;
180 case ARROW_FILLED_TRIANGLE:
181 if (arrow->left) {
182 pts[0].x = x+5; pts[0].y = y+height/2;
183 pts[1].x = x+5+height/2; pts[1].y = y+5;
184 pts[2].x = x+5+height/2; pts[2].y = y+height-5;
185 pts[3].x = x+5; pts[3].y = y+height/2;
186 gdk_draw_polygon(win, gc, TRUE, pts, 4);
187 gdk_draw_polygon(win, gc, FALSE, pts, 4);
188 gdk_draw_line(win, gc, x+5+height/2, y+height/2, x+width, y+height/2);
189 } else {
190 pts[0].x = x+width-5; pts[0].y = y+height/2;
191 pts[1].x = x+width-5-height/2; pts[1].y = y+5;
192 pts[2].x = x+width-5-height/2; pts[2].y = y+height-5;
193 pts[3].x = x+width-5; pts[3].y = y+height/2;
194 gdk_draw_polygon(win, gc, TRUE, pts, 4);
195 gdk_draw_polygon(win, gc, FALSE, pts, 4);
196 gdk_draw_line(win, gc, x, y+height/2, x+width-5-height/2, y+height/2);
198 break;
199 case ARROW_HOLLOW_DIAMOND:
200 if (arrow->left) {
201 pts[0].x = x+5; pts[0].y = y+height/2;
202 pts[1].x = x+5+height/2; pts[1].y = y+5;
203 pts[2].x = x+5+height*3/4; pts[2].y = y+height/2;
204 pts[3].x = x+5+height/2; pts[3].y = y+height-5;
205 pts[4].x = x+5; pts[4].y = y+height/2;
206 gdk_draw_polygon(win, gc, FALSE, pts, 5);
207 gdk_draw_line(win, gc, x+5+height*3/4,y+height/2, x+width, y+height/2);
208 } else {
209 pts[0].x = x+width-5; pts[0].y = y+height/2;
210 pts[1].x = x+width-5-height/2; pts[1].y = y+5;
211 pts[2].x = x+width-5-height*3/4; pts[2].y = y+height/2;
212 pts[3].x = x+width-5-height/2; pts[3].y = y+height-5;
213 pts[4].x = x+width-5; pts[4].y = y+height/2;
214 gdk_draw_polygon(win, gc, FALSE, pts, 5);
215 gdk_draw_line(win, gc, x, y+height/2, x+width-5-height*3/4,y+height/2);
217 break;
218 case ARROW_FILLED_DIAMOND:
219 if (arrow->left) {
220 pts[0].x = x+5; pts[0].y = y+height/2;
221 pts[1].x = x+5+height/2; pts[1].y = y+5;
222 pts[2].x = x+5+height*3/4; pts[2].y = y+height/2;
223 pts[3].x = x+5+height/2; pts[3].y = y+height-5;
224 pts[4].x = x+5; pts[4].y = y+height/2;
225 gdk_draw_polygon(win, gc, TRUE, pts, 5);
226 gdk_draw_polygon(win, gc, FALSE, pts, 5);
227 gdk_draw_line(win, gc, x+5+height*3/4,y+height/2, x+width, y+height/2);
228 } else {
229 pts[0].x = x+width-5; pts[0].y = y+height/2;
230 pts[1].x = x+width-5-height/2; pts[1].y = y+5;
231 pts[2].x = x+width-5-height*3/4; pts[2].y = y+height/2;
232 pts[3].x = x+width-5-height/2; pts[3].y = y+height-5;
233 pts[4].x = x+width-5; pts[4].y = y+height/2;
234 gdk_draw_polygon(win, gc, TRUE, pts, 5);
235 gdk_draw_polygon(win, gc, FALSE, pts, 5);
236 gdk_draw_line(win, gc, x, y+height/2, x+width-5-height*3/4,y+height/2);
238 break;
239 case ARROW_SLASHED_CROSS:
240 if (arrow->left) {
241 gdk_draw_line(win, gc, x+5,y+height/2, x+width,y+height/2); /*line*/
242 gdk_draw_line(win, gc, x+5,y+height-5, x+height-5,y+5); /*slash*/
243 gdk_draw_line(win, gc, x+height/2,y+height-5, x+height/2,y+5);
244 /*cross */
245 } else {
246 gdk_draw_line(win, gc, x,y+height/2, x+width-5,y+height/2); /*line*/
247 gdk_draw_line(win, gc, x+width-height/2-5,y+height-5, x+width-5,y+5);
248 /*slash*/
249 gdk_draw_line(win, gc, x+width-height/2,y+height-5, x+width-height/2,
250 y+5); /*cross*/
252 break;
253 case ARROW_HALF_HEAD:
254 if (arrow->left) {
255 gdk_draw_line(win, gc, x+5,y+height/2, x+width,y+height/2);
256 gdk_draw_line(win, gc, x+5,y+height/2, x+5+height/2,y+5);
257 } else {
258 gdk_draw_line(win, gc, x,y+height/2, x+width-5,y+height/2);
259 gdk_draw_line(win, gc, x+width-5,y+height/2, x+width-5-height/2,
260 y+height-5);
262 break;
263 case ARROW_FILLED_ELLIPSE:
264 if (arrow->left) {
265 gdk_draw_line(win,gc,x+5+8,y+height/2,x+width,y+height/2);
266 gdk_draw_arc(win,gc,TRUE,x+5,y+height/2-6,12,12,0,64*360);
267 } else {
268 gdk_draw_line(win,gc,x,y+height/2,x+width-5-8,y+height/2);
269 gdk_draw_arc(win,gc,TRUE,x+width-5-12,y+height/2-6,12,12,0,64*360);
271 break;
272 case ARROW_HOLLOW_ELLIPSE:
273 if (arrow->left) {
274 gdk_draw_line(win,gc,x+5+8,y+height/2,x+width,y+height/2);
275 gdk_draw_arc(win,gc,FALSE,x+5,y+height/2-4,8,8,0,64*360);
276 } else {
277 gdk_draw_line(win,gc,x,y+height/2,x+width-5-8,y+height/2);
278 gdk_draw_arc(win,gc,FALSE,x+width-5-8,y+height/2-4,8,8,0,64*360);
280 break;
282 gdk_gc_set_line_attributes(gc, gcvalues.line_width, gcvalues.line_style,
283 gcvalues.cap_style, gcvalues.join_style);
285 return TRUE;
289 /* --------------- DiaLinePreview -------------------------------- */
291 #define DIA_LINE_PREVIEW(obj) (GTK_CHECK_CAST((obj),dia_line_preview_get_type(), DiaLinePreview))
292 #define DIA_LINE_PREVIEW_CLASS(obj) (GTK_CHECK_CLASS_CAST((obj), dia_line_preview_get_type(), DiaLinePreviewClass))
294 typedef struct _DiaLinePreview DiaLinePreview;
295 typedef struct _DiaLinePreviewClass DiaLinePreviewClass;
297 struct _DiaLinePreview
299 GtkMisc misc;
300 LineStyle lstyle;
302 struct _DiaLinePreviewClass
304 GtkMiscClass parent_class;
307 static void dia_line_preview_class_init (DiaLinePreviewClass *klass);
308 static void dia_line_preview_init (DiaLinePreview *arrow);
309 static gint dia_line_preview_expose (GtkWidget *widget,
310 GdkEventExpose *event);
312 GtkType
313 dia_line_preview_get_type (void)
315 static GtkType line_type = 0;
317 if (!line_type) {
318 static const GtkTypeInfo line_info = {
319 "DiaLinePreview",
320 sizeof (DiaLinePreview),
321 sizeof (DiaLinePreviewClass),
322 (GtkClassInitFunc) dia_line_preview_class_init,
323 (GtkObjectInitFunc) dia_line_preview_init,
324 /* reserved_1 */ NULL,
325 /* reserved_2 */ NULL,
326 (GtkClassInitFunc) NULL,
328 line_type = gtk_type_unique (GTK_TYPE_MISC, &line_info);
330 return line_type;
333 static void
334 dia_line_preview_class_init (DiaLinePreviewClass *class)
336 GtkWidgetClass *widget_class;
338 widget_class = (GtkWidgetClass *)class;
339 widget_class->expose_event = dia_line_preview_expose;
342 static void
343 dia_line_preview_init (DiaLinePreview *line)
345 GTK_WIDGET_SET_FLAGS (line, GTK_NO_WINDOW);
347 GTK_WIDGET (line)->requisition.width = 40 + GTK_MISC (line)->xpad * 2;
348 GTK_WIDGET (line)->requisition.height = 20 + GTK_MISC (line)->ypad * 2;
351 line->lstyle = LINESTYLE_SOLID;
354 GtkWidget *
355 dia_line_preview_new (LineStyle lstyle)
357 DiaLinePreview *line = gtk_type_new (dia_line_preview_get_type());
359 line->lstyle = lstyle;
360 return GTK_WIDGET(line);
363 void
364 dia_line_preview_set(DiaLinePreview *line, LineStyle lstyle)
366 if (line->lstyle != lstyle) {
367 line->lstyle = lstyle;
368 if (GTK_WIDGET_DRAWABLE(line))
369 gtk_widget_queue_clear(GTK_WIDGET(line));
373 static gint
374 dia_line_preview_expose(GtkWidget *widget, GdkEventExpose *event)
376 DiaLinePreview *line = DIA_LINE_PREVIEW(widget);
377 GtkMisc *misc = GTK_MISC(widget);
378 gint width, height;
379 gint x, y;
380 gint extent;
381 GdkWindow *win;
382 GdkGC *gc;
383 GdkGCValues gcvalues;
384 char dash_list[6];
386 if (GTK_WIDGET_DRAWABLE(widget)) {
387 width = widget->allocation.width - misc->xpad * 2;
388 height = widget->allocation.height - misc->ypad * 2;
389 extent = MIN(width, height);
390 x = (widget->allocation.x + misc->xpad);
391 y = (widget->allocation.y + misc->ypad);
393 win = widget->window;
394 gc = widget->style->fg_gc[widget->state];
396 /* increase line width */
397 gdk_gc_get_values(gc, &gcvalues);
398 switch (line->lstyle) {
399 case LINESTYLE_SOLID:
400 gdk_gc_set_line_attributes(gc, 3, GDK_LINE_SOLID,
401 gcvalues.cap_style, gcvalues.join_style);
402 break;
403 case LINESTYLE_DASHED:
404 gdk_gc_set_line_attributes(gc, 3, GDK_LINE_ON_OFF_DASH,
405 gcvalues.cap_style, gcvalues.join_style);
406 dash_list[0] = 10;
407 dash_list[1] = 10;
408 gdk_gc_set_dashes(gc, 0, dash_list, 2);
409 break;
410 case LINESTYLE_DASH_DOT:
411 gdk_gc_set_line_attributes(gc, 3, GDK_LINE_ON_OFF_DASH,
412 gcvalues.cap_style, gcvalues.join_style);
413 dash_list[0] = 10;
414 dash_list[1] = 4;
415 dash_list[2] = 2;
416 dash_list[3] = 4;
417 gdk_gc_set_dashes(gc, 0, dash_list, 4);
418 break;
419 case LINESTYLE_DASH_DOT_DOT:
420 gdk_gc_set_line_attributes(gc, 3, GDK_LINE_ON_OFF_DASH,
421 gcvalues.cap_style, gcvalues.join_style);
422 dash_list[0] = 10;
423 dash_list[1] = 2;
424 dash_list[2] = 2;
425 dash_list[3] = 2;
426 dash_list[4] = 2;
427 dash_list[5] = 2;
428 gdk_gc_set_dashes(gc, 0, dash_list, 6);
429 break;
430 case LINESTYLE_DOTTED:
431 gdk_gc_set_line_attributes(gc, 3, GDK_LINE_ON_OFF_DASH,
432 gcvalues.cap_style, gcvalues.join_style);
433 dash_list[0] = 2;
434 dash_list[1] = 2;
435 gdk_gc_set_dashes(gc, 0, dash_list, 2);
436 break;
438 gdk_draw_line(win, gc, x, y+height/2, x+width, y+height/2);
439 gdk_gc_set_line_attributes(gc, gcvalues.line_width, gcvalues.line_style,
440 gcvalues.cap_style, gcvalues.join_style);
442 return TRUE;
445 /* ------- Code for DiaArrowChooser ----------------------- */
446 gint close_and_hide(GtkWidget *wid, GdkEventAny *event) {
447 gtk_widget_hide(wid);
448 return TRUE;
450 static const char *button_menu_key = "dia-button-menu";
451 static const char *menuitem_enum_key = "dia-menuitem-value";
454 #define DIA_ARROW_CHOOSER(obj) (GTK_CHECK_CAST((obj),dia_arrow_chooser_get_type(), DiaArrowChooser))
455 #define DIA_ARROW_CHOOSER_CLASS(obj) (GTK_CHECK_CLASS_CAST((obj), dia_arrow_chooser_get_type(), DiaArrowChooserClass))
457 typedef struct _DiaArrowChooser DiaArrowChooser;
458 typedef struct _DiaArrowChooserClass DiaArrowChooserClass;
460 struct _DiaArrowChooser
462 GtkButton button;
463 DiaArrowPreview *preview;
464 Arrow arrow;
465 gboolean left;
467 DiaChangeArrowCallback callback;
468 gpointer user_data;
470 GtkWidget *dialog;
471 DiaArrowSelector *selector;
473 struct _DiaArrowChooserClass
475 GtkButtonClass parent_class;
478 static void dia_arrow_chooser_class_init (DiaArrowChooserClass *klass);
479 static void dia_arrow_chooser_init (DiaArrowChooser *arrow);
480 static gint dia_arrow_chooser_event (GtkWidget *widget,
481 GdkEvent *event);
482 static void dia_arrow_chooser_dialog_ok (DiaArrowChooser *arrow);
483 static void dia_arrow_chooser_dialog_cancel (DiaArrowChooser *arrow);
484 static void dia_arrow_chooser_change_arrow_type (GtkMenuItem *mi,
485 DiaArrowChooser *arrow);
487 GtkType
488 dia_arrow_chooser_get_type (void)
490 static GtkType arrow_type = 0;
492 if (!arrow_type) {
493 static const GtkTypeInfo arrow_info = {
494 "DiaArrowChooser",
495 sizeof (DiaArrowChooser),
496 sizeof (DiaArrowChooserClass),
497 (GtkClassInitFunc) dia_arrow_chooser_class_init,
498 (GtkObjectInitFunc) dia_arrow_chooser_init,
499 /* reserved_1 */ NULL,
500 /* reserved_2 */ NULL,
501 (GtkClassInitFunc) NULL,
503 arrow_type = gtk_type_unique (GTK_TYPE_BUTTON, &arrow_info);
505 return arrow_type;
508 static void
509 dia_arrow_chooser_class_init (DiaArrowChooserClass *class)
511 GtkWidgetClass *widget_class;
513 widget_class = (GtkWidgetClass *)class;
514 widget_class->event = dia_arrow_chooser_event;
517 static void
518 dia_arrow_chooser_init (DiaArrowChooser *arrow)
520 GtkWidget *wid;
522 arrow->left = FALSE;
523 arrow->arrow.type = ARROW_NONE;
524 arrow->arrow.length = DEFAULT_ARROW_LENGTH;
525 arrow->arrow.width = DEFAULT_ARROW_WIDTH;
527 wid = dia_arrow_preview_new(ARROW_NONE, arrow->left);
528 gtk_container_add(GTK_CONTAINER(arrow), wid);
529 gtk_widget_show(wid);
530 arrow->preview = DIA_ARROW_PREVIEW(wid);
532 arrow->dialog = wid = gtk_dialog_new();
533 gtk_window_set_title(GTK_WINDOW(wid), _("Arrow Properties"));
534 gtk_signal_connect(GTK_OBJECT(wid), "delete_event",
535 GTK_SIGNAL_FUNC(close_and_hide), NULL);
537 wid = dia_arrow_selector_new();
538 gtk_container_set_border_width(GTK_CONTAINER(wid), 5);
539 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(arrow->dialog)->vbox), wid,
540 TRUE, TRUE, 0);
541 gtk_widget_show(wid);
542 arrow->selector = DIAARROWSELECTOR(wid);
544 wid = gtk_button_new_with_label(_("OK"));
545 GTK_WIDGET_SET_FLAGS(wid, GTK_CAN_DEFAULT);
546 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(arrow->dialog)->action_area),wid);
547 gtk_widget_grab_default(wid);
548 gtk_signal_connect_object(GTK_OBJECT(wid), "clicked",
549 GTK_SIGNAL_FUNC(dia_arrow_chooser_dialog_ok),
550 GTK_OBJECT(arrow));
551 gtk_widget_show(wid);
553 wid = gtk_button_new_with_label(_("Cancel"));
554 GTK_WIDGET_SET_FLAGS(wid, GTK_CAN_DEFAULT);
555 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(arrow->dialog)->action_area),wid);
556 gtk_signal_connect_object(GTK_OBJECT(wid), "clicked",
557 GTK_SIGNAL_FUNC(dia_arrow_chooser_dialog_cancel),
558 GTK_OBJECT(arrow));
559 gtk_widget_show(wid);
562 GtkWidget *
563 dia_arrow_chooser_new(gboolean left, DiaChangeArrowCallback callback,
564 gpointer user_data)
566 DiaArrowChooser *chooser = gtk_type_new(dia_arrow_chooser_get_type());
567 GtkWidget *menu, *mi, *ar;
568 gint i;
570 chooser->left = left;
571 dia_arrow_preview_set(chooser->preview, chooser->preview->atype, left);
572 chooser->callback = callback;
573 chooser->user_data = user_data;
575 menu = gtk_menu_new();
576 gtk_object_set_data_full(GTK_OBJECT(chooser), button_menu_key, menu,
577 (GtkDestroyNotify)gtk_widget_unref);
578 for (i = 0; i <= ARROW_HOLLOW_ELLIPSE; i++) {
579 mi = gtk_menu_item_new();
580 gtk_object_set_data(GTK_OBJECT(mi), menuitem_enum_key, GINT_TO_POINTER(i));
581 ar = dia_arrow_preview_new(i, left);
582 gtk_container_add(GTK_CONTAINER(mi), ar);
583 gtk_widget_show(ar);
584 gtk_signal_connect(GTK_OBJECT(mi), "activate",
585 GTK_SIGNAL_FUNC(dia_arrow_chooser_change_arrow_type),
586 chooser);
587 gtk_container_add(GTK_CONTAINER(menu), mi);
588 gtk_widget_show(mi);
590 mi = gtk_menu_item_new_with_label(_("Details..."));
591 gtk_signal_connect_object(GTK_OBJECT(mi), "activate",
592 GTK_SIGNAL_FUNC(gtk_widget_show),
593 GTK_OBJECT(chooser->dialog));
594 gtk_container_add(GTK_CONTAINER(menu), mi);
595 gtk_widget_show(mi);
597 return GTK_WIDGET(chooser);
600 static gint
601 dia_arrow_chooser_event(GtkWidget *widget, GdkEvent *event)
603 if (event->type == GDK_BUTTON_PRESS && event->button.button == 1) {
604 GtkMenu *menu = gtk_object_get_data(GTK_OBJECT(widget), button_menu_key);
605 gtk_menu_popup(menu, NULL, NULL, NULL, NULL,
606 event->button.button, event->button.time);
607 return TRUE;
609 return FALSE;
612 static void
613 dia_arrow_chooser_dialog_ok (DiaArrowChooser *arrow)
615 Arrow new_arrow = dia_arrow_selector_get_arrow(arrow->selector);
617 if (new_arrow.type != arrow->arrow.type ||
618 new_arrow.length != arrow->arrow.length ||
619 new_arrow.width != arrow->arrow.width) {
620 arrow->arrow = new_arrow;
621 dia_arrow_preview_set(arrow->preview, new_arrow.type, arrow->left);
622 if (arrow->callback)
623 (* arrow->callback)(arrow->arrow, arrow->user_data);
625 gtk_widget_hide(arrow->dialog);
627 static void
628 dia_arrow_chooser_dialog_cancel (DiaArrowChooser *arrow)
630 dia_arrow_selector_set_arrow(arrow->selector, arrow->arrow);
631 gtk_widget_hide(arrow->dialog);
634 static void
635 dia_arrow_chooser_change_arrow_type(GtkMenuItem *mi, DiaArrowChooser *arrow)
637 ArrowType atype = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(mi),
638 menuitem_enum_key));
640 if (arrow->arrow.type != atype) {
641 dia_arrow_preview_set(arrow->preview, atype, arrow->left);
642 arrow->arrow.type = atype;
643 dia_arrow_selector_set_arrow(arrow->selector, arrow->arrow);
644 if (arrow->callback)
645 (* arrow->callback)(arrow->arrow, arrow->user_data);
650 /* ------- Code for DiaLineChooser ---------------------- */
651 #define DIA_LINE_CHOOSER(obj) (GTK_CHECK_CAST((obj),dia_line_chooser_get_type(), DiaLineChooser))
652 #define DIA_LINE_CHOOSER_CLASS(obj) (GTK_CHECK_CLASS_CAST((obj), dia_line_chooser_get_type(), DiaLineChooserClass))
654 typedef struct _DiaLineChooser DiaLineChooser;
655 typedef struct _DiaLineChooserClass DiaLineChooserClass;
657 struct _DiaLineChooser
659 GtkButton button;
660 DiaLinePreview *preview;
661 LineStyle lstyle;
662 real dash_length;
664 DiaChangeLineCallback callback;
665 gpointer user_data;
667 GtkWidget *dialog;
668 DiaLineStyleSelector *selector;
670 struct _DiaLineChooserClass
672 GtkButtonClass parent_class;
675 static void dia_line_chooser_class_init (DiaLineChooserClass *klass);
676 static void dia_line_chooser_init (DiaLineChooser *arrow);
677 static gint dia_line_chooser_event (GtkWidget *widget,
678 GdkEvent *event);
679 static void dia_line_chooser_dialog_ok (DiaLineChooser *lchooser);
680 static void dia_line_chooser_dialog_cancel (DiaLineChooser *lchooser);
681 static void dia_line_chooser_change_line_style (GtkMenuItem *mi,
682 DiaLineChooser *lchooser);
684 GtkType
685 dia_line_chooser_get_type (void)
687 static GtkType arrow_type = 0;
689 if (!arrow_type) {
690 static const GtkTypeInfo arrow_info = {
691 "DiaLineChooser",
692 sizeof (DiaLineChooser),
693 sizeof (DiaLineChooserClass),
694 (GtkClassInitFunc) dia_line_chooser_class_init,
695 (GtkObjectInitFunc) dia_line_chooser_init,
696 /* reserved_1 */ NULL,
697 /* reserved_2 */ NULL,
698 (GtkClassInitFunc) NULL,
700 arrow_type = gtk_type_unique (GTK_TYPE_BUTTON, &arrow_info);
702 return arrow_type;
705 static void
706 dia_line_chooser_class_init (DiaLineChooserClass *class)
708 GtkWidgetClass *widget_class;
710 widget_class = (GtkWidgetClass *)class;
711 widget_class->event = dia_line_chooser_event;
714 static void
715 dia_line_chooser_init (DiaLineChooser *lchooser)
717 GtkWidget *wid;
718 GtkWidget *menu, *mi, *ln;
719 gint i;
721 lchooser->lstyle = LINESTYLE_SOLID;
722 lchooser->dash_length = DEFAULT_LINESTYLE_DASHLEN;
724 wid = dia_line_preview_new(LINESTYLE_SOLID);
725 gtk_container_add(GTK_CONTAINER(lchooser), wid);
726 gtk_widget_show(wid);
727 lchooser->preview = DIA_LINE_PREVIEW(wid);
729 lchooser->dialog = wid = gtk_dialog_new();
730 gtk_window_set_title(GTK_WINDOW(wid), _("Line Style Properties"));
731 gtk_signal_connect(GTK_OBJECT(wid), "delete_event",
732 GTK_SIGNAL_FUNC(close_and_hide), NULL);
734 wid = dia_line_style_selector_new();
735 gtk_container_set_border_width(GTK_CONTAINER(wid), 5);
736 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(lchooser->dialog)->vbox), wid,
737 TRUE, TRUE, 0);
738 gtk_widget_show(wid);
739 lchooser->selector = DIALINESTYLESELECTOR(wid);
741 wid = gtk_button_new_with_label(_("OK"));
742 GTK_WIDGET_SET_FLAGS(wid, GTK_CAN_DEFAULT);
743 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(lchooser->dialog)->action_area),
744 wid);
745 gtk_widget_grab_default(wid);
746 gtk_signal_connect_object(GTK_OBJECT(wid), "clicked",
747 GTK_SIGNAL_FUNC(dia_line_chooser_dialog_ok),
748 GTK_OBJECT(lchooser));
749 gtk_widget_show(wid);
751 wid = gtk_button_new_with_label(_("Cancel"));
752 GTK_WIDGET_SET_FLAGS(wid, GTK_CAN_DEFAULT);
753 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(lchooser->dialog)->action_area),
754 wid);
755 gtk_signal_connect_object(GTK_OBJECT(wid), "clicked",
756 GTK_SIGNAL_FUNC(dia_line_chooser_dialog_cancel),
757 GTK_OBJECT(lchooser));
759 menu = gtk_menu_new();
760 gtk_object_set_data_full(GTK_OBJECT(lchooser), button_menu_key, menu,
761 (GtkDestroyNotify)gtk_widget_unref);
762 for (i = 0; i <= LINESTYLE_DOTTED; i++) {
763 mi = gtk_menu_item_new();
764 gtk_object_set_data(GTK_OBJECT(mi), menuitem_enum_key, GINT_TO_POINTER(i));
765 ln = dia_line_preview_new(i);
766 gtk_container_add(GTK_CONTAINER(mi), ln);
767 gtk_widget_show(ln);
768 gtk_signal_connect(GTK_OBJECT(mi), "activate",
769 GTK_SIGNAL_FUNC(dia_line_chooser_change_line_style),
770 lchooser);
771 gtk_container_add(GTK_CONTAINER(menu), mi);
772 gtk_widget_show(mi);
774 mi = gtk_menu_item_new_with_label(_("Details..."));
775 gtk_signal_connect_object(GTK_OBJECT(mi), "activate",
776 GTK_SIGNAL_FUNC(gtk_widget_show),
777 GTK_OBJECT(lchooser->dialog));
778 gtk_container_add(GTK_CONTAINER(menu), mi);
779 gtk_widget_show(mi);
781 gtk_widget_show(wid);
784 GtkWidget *
785 dia_line_chooser_new(DiaChangeLineCallback callback,
786 gpointer user_data)
788 DiaLineChooser *chooser = gtk_type_new(dia_line_chooser_get_type());
790 chooser->callback = callback;
791 chooser->user_data = user_data;
793 return GTK_WIDGET(chooser);
796 static gint
797 dia_line_chooser_event(GtkWidget *widget, GdkEvent *event)
799 if (event->type == GDK_BUTTON_PRESS && event->button.button == 1) {
800 GtkMenu *menu = gtk_object_get_data(GTK_OBJECT(widget), button_menu_key);
801 gtk_menu_popup(menu, NULL, NULL, NULL, NULL,
802 event->button.button, event->button.time);
803 return TRUE;
805 return FALSE;
808 static void
809 dia_line_chooser_dialog_ok (DiaLineChooser *lchooser)
811 LineStyle new_style;
812 real new_dash;
814 dia_line_style_selector_get_linestyle(lchooser->selector,
815 &new_style, &new_dash);
816 if (new_style != lchooser->lstyle || new_dash != lchooser->dash_length) {
817 lchooser->lstyle = new_style;
818 lchooser->dash_length = new_dash;
819 dia_line_preview_set(lchooser->preview, new_style);
820 if (lchooser->callback)
821 (* lchooser->callback)(new_style, new_dash, lchooser->user_data);
823 gtk_widget_hide(lchooser->dialog);
825 static void
826 dia_line_chooser_dialog_cancel (DiaLineChooser *lchooser)
828 dia_line_style_selector_set_linestyle(lchooser->selector, lchooser->lstyle,
829 lchooser->dash_length);
830 gtk_widget_hide(lchooser->dialog);
833 static void
834 dia_line_chooser_change_line_style(GtkMenuItem *mi, DiaLineChooser *lchooser)
836 LineStyle lstyle = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(mi),
837 menuitem_enum_key));
839 if (lchooser->lstyle != lstyle) {
840 dia_line_preview_set(lchooser->preview, lstyle);
841 lchooser->lstyle = lstyle;
842 dia_line_style_selector_set_linestyle(lchooser->selector, lchooser->lstyle,
843 lchooser->dash_length);
844 if (lchooser->callback)
845 (* lchooser->callback)(lchooser->lstyle, lchooser->dash_length,
846 lchooser->user_data);