more leaks plugged and more *_OPTIONAL
[dia.git] / app / lineprops_area.c
blob01101fe43c333ed8ccd188a46fdc5e01e148bc49
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"
28 #include "interface.h"
29 #include "render_pixmap.h"
31 #include <gtk/gtk.h>
33 /* --------------- DiaArrowPreview -------------------------------- */
34 typedef struct _DiaArrowPreview DiaArrowPreview;
35 typedef struct _DiaArrowPreviewClass DiaArrowPreviewClass;
37 static GtkType dia_arrow_preview_get_type (void);
38 static GtkWidget *dia_arrow_preview_new (ArrowType atype, gboolean left);
39 static void dia_arrow_preview_set(DiaArrowPreview *arrow,
40 ArrowType atype, gboolean left);
42 #define DIA_ARROW_PREVIEW(obj) (GTK_CHECK_CAST((obj),dia_arrow_preview_get_type(), DiaArrowPreview))
43 #define DIA_ARROW_PREVIEW_CLASS(obj) (GTK_CHECK_CLASS_CAST((obj), dia_arrow_preview_get_type(), DiaArrowPreviewClass))
45 struct _DiaArrowPreview
47 GtkMisc misc;
48 ArrowType atype;
49 gboolean left;
51 struct _DiaArrowPreviewClass
53 GtkMiscClass parent_class;
56 static void dia_arrow_preview_class_init (DiaArrowPreviewClass *klass);
57 static void dia_arrow_preview_init (DiaArrowPreview *arrow);
58 static gint dia_arrow_preview_expose (GtkWidget *widget,
59 GdkEventExpose *event);
61 static GtkType
62 dia_arrow_preview_get_type (void)
64 static GtkType arrow_type = 0;
66 if (!arrow_type) {
67 static const GtkTypeInfo arrow_info = {
68 "DiaArrowPreview",
69 sizeof (DiaArrowPreview),
70 sizeof (DiaArrowPreviewClass),
71 (GtkClassInitFunc) dia_arrow_preview_class_init,
72 (GtkObjectInitFunc) dia_arrow_preview_init,
73 /* reserved_1 */ NULL,
74 /* reserved_2 */ NULL,
75 (GtkClassInitFunc) NULL,
77 arrow_type = gtk_type_unique (GTK_TYPE_MISC, &arrow_info);
79 return arrow_type;
82 static void
83 dia_arrow_preview_class_init (DiaArrowPreviewClass *class)
85 GtkWidgetClass *widget_class;
87 widget_class = (GtkWidgetClass *)class;
88 widget_class->expose_event = dia_arrow_preview_expose;
91 static void
92 dia_arrow_preview_init (DiaArrowPreview *arrow)
94 GTK_WIDGET_SET_FLAGS (arrow, GTK_NO_WINDOW);
96 GTK_WIDGET (arrow)->requisition.width = 30 + GTK_MISC (arrow)->xpad * 2;
97 GTK_WIDGET (arrow)->requisition.height = 20 + GTK_MISC (arrow)->ypad * 2;
99 arrow->atype = ARROW_NONE;
100 arrow->left = TRUE;
103 static GtkWidget *
104 dia_arrow_preview_new (ArrowType atype, gboolean left)
106 DiaArrowPreview *arrow = gtk_type_new (dia_arrow_preview_get_type());
108 arrow->atype = atype;
109 arrow->left = left;
110 return GTK_WIDGET(arrow);
113 static void
114 dia_arrow_preview_set(DiaArrowPreview *arrow, ArrowType atype, gboolean left)
116 if (arrow->atype != atype || arrow->left != left) {
117 arrow->atype = atype;
118 arrow->left = left;
119 if (GTK_WIDGET_DRAWABLE(arrow))
120 gtk_widget_queue_clear(GTK_WIDGET(arrow));
124 static gint
125 dia_arrow_preview_expose(GtkWidget *widget, GdkEventExpose *event)
127 if (GTK_WIDGET_DRAWABLE(widget)) {
128 Point from, to;
129 DiaRenderer *renderer;
130 DiaArrowPreview *arrow = DIA_ARROW_PREVIEW(widget);
131 GtkMisc *misc = GTK_MISC(widget);
132 gint width, height;
133 gint x, y;
134 GdkWindow *win;
135 int linewidth = 2;
136 DiaRendererClass *renderer_ops;
138 width = widget->allocation.width - misc->xpad * 2;
139 height = widget->allocation.height - misc->ypad * 2;
140 x = (widget->allocation.x + misc->xpad);
141 y = (widget->allocation.y + misc->ypad);
143 win = widget->window;
145 to.y = from.y = height/2;
146 if (arrow->left) {
147 from.x = width-linewidth;
148 to.x = 0;
149 } else {
150 from.x = 0;
151 to.x = width-linewidth;
153 renderer = new_pixmap_renderer(win, width, height);
154 renderer_ops = DIA_RENDERER_GET_CLASS (renderer);
155 renderer_pixmap_set_pixmap(renderer, win, x, y, width, height);
156 renderer_ops->begin_render(renderer);
157 renderer_ops->set_linewidth(renderer, linewidth);
158 renderer_ops->draw_line(renderer, &to, &from, &color_black);
159 arrow_draw (renderer, arrow->atype,
160 &to, &from,
161 .75*((real)height-linewidth),
162 .75*((real)height-linewidth),
163 linewidth, &color_black, &color_white);
164 renderer_ops->end_render(renderer);
165 g_object_unref(renderer);
168 return TRUE;
171 /* --------------- DiaLinePreview -------------------------------- */
172 typedef struct _DiaLinePreview DiaLinePreview;
173 typedef struct _DiaLinePreviewClass DiaLinePreviewClass;
175 static GtkType dia_line_preview_get_type (void);
176 static void dia_line_preview_set(DiaLinePreview *line, LineStyle lstyle);
177 static GtkWidget *dia_line_preview_new (LineStyle lstyle);
179 #define DIA_LINE_PREVIEW(obj) (GTK_CHECK_CAST((obj),dia_line_preview_get_type(), DiaLinePreview))
180 #define DIA_LINE_PREVIEW_CLASS(obj) (GTK_CHECK_CLASS_CAST((obj), dia_line_preview_get_type(), DiaLinePreviewClass))
182 struct _DiaLinePreview
184 GtkMisc misc;
185 LineStyle lstyle;
187 struct _DiaLinePreviewClass
189 GtkMiscClass parent_class;
192 static void dia_line_preview_class_init (DiaLinePreviewClass *klass);
193 static void dia_line_preview_init (DiaLinePreview *arrow);
194 static gint dia_line_preview_expose (GtkWidget *widget,
195 GdkEventExpose *event);
197 static GtkType
198 dia_line_preview_get_type (void)
200 static GtkType line_type = 0;
202 if (!line_type) {
203 static const GtkTypeInfo line_info = {
204 "DiaLinePreview",
205 sizeof (DiaLinePreview),
206 sizeof (DiaLinePreviewClass),
207 (GtkClassInitFunc) dia_line_preview_class_init,
208 (GtkObjectInitFunc) dia_line_preview_init,
209 /* reserved_1 */ NULL,
210 /* reserved_2 */ NULL,
211 (GtkClassInitFunc) NULL,
213 line_type = gtk_type_unique (GTK_TYPE_MISC, &line_info);
215 return line_type;
218 static void
219 dia_line_preview_class_init (DiaLinePreviewClass *class)
221 GtkWidgetClass *widget_class;
223 widget_class = (GtkWidgetClass *)class;
224 widget_class->expose_event = dia_line_preview_expose;
227 static void
228 dia_line_preview_init (DiaLinePreview *line)
230 GTK_WIDGET_SET_FLAGS (line, GTK_NO_WINDOW);
232 GTK_WIDGET (line)->requisition.width = 40 + GTK_MISC (line)->xpad * 2;
233 GTK_WIDGET (line)->requisition.height = 15 + GTK_MISC (line)->ypad * 2;
236 line->lstyle = LINESTYLE_SOLID;
239 static GtkWidget *
240 dia_line_preview_new (LineStyle lstyle)
242 DiaLinePreview *line = gtk_type_new (dia_line_preview_get_type());
244 line->lstyle = lstyle;
245 return GTK_WIDGET(line);
248 static void
249 dia_line_preview_set(DiaLinePreview *line, LineStyle lstyle)
251 if (line->lstyle != lstyle) {
252 line->lstyle = lstyle;
253 if (GTK_WIDGET_DRAWABLE(line))
254 gtk_widget_queue_clear(GTK_WIDGET(line));
258 static gint
259 dia_line_preview_expose(GtkWidget *widget, GdkEventExpose *event)
261 DiaLinePreview *line = DIA_LINE_PREVIEW(widget);
262 GtkMisc *misc = GTK_MISC(widget);
263 gint width, height;
264 gint x, y;
265 gint extent;
266 GdkWindow *win;
267 GdkGC *gc;
268 GdkGCValues gcvalues;
269 char dash_list[6];
271 if (GTK_WIDGET_DRAWABLE(widget)) {
272 width = widget->allocation.width - misc->xpad * 2;
273 height = widget->allocation.height - misc->ypad * 2;
274 extent = MIN(width, height);
275 x = (widget->allocation.x + misc->xpad);
276 y = (widget->allocation.y + misc->ypad);
278 win = widget->window;
279 gc = widget->style->fg_gc[widget->state];
281 /* increase line width */
282 gdk_gc_get_values(gc, &gcvalues);
283 switch (line->lstyle) {
284 case LINESTYLE_SOLID:
285 gdk_gc_set_line_attributes(gc, 1, GDK_LINE_SOLID,
286 gcvalues.cap_style, gcvalues.join_style);
287 break;
288 case LINESTYLE_DASHED:
289 gdk_gc_set_line_attributes(gc, 1, GDK_LINE_ON_OFF_DASH,
290 gcvalues.cap_style, gcvalues.join_style);
291 dash_list[0] = 10;
292 dash_list[1] = 10;
293 gdk_gc_set_dashes(gc, 0, dash_list, 2);
294 break;
295 case LINESTYLE_DASH_DOT:
296 gdk_gc_set_line_attributes(gc, 1, GDK_LINE_ON_OFF_DASH,
297 gcvalues.cap_style, gcvalues.join_style);
298 dash_list[0] = 10;
299 dash_list[1] = 4;
300 dash_list[2] = 2;
301 dash_list[3] = 4;
302 gdk_gc_set_dashes(gc, 0, dash_list, 4);
303 break;
304 case LINESTYLE_DASH_DOT_DOT:
305 gdk_gc_set_line_attributes(gc, 1, GDK_LINE_ON_OFF_DASH,
306 gcvalues.cap_style, gcvalues.join_style);
307 dash_list[0] = 10;
308 dash_list[1] = 2;
309 dash_list[2] = 2;
310 dash_list[3] = 2;
311 dash_list[4] = 2;
312 dash_list[5] = 2;
313 gdk_gc_set_dashes(gc, 0, dash_list, 6);
314 break;
315 case LINESTYLE_DOTTED:
316 gdk_gc_set_line_attributes(gc, 1, GDK_LINE_ON_OFF_DASH,
317 gcvalues.cap_style, gcvalues.join_style);
318 dash_list[0] = 2;
319 dash_list[1] = 2;
320 gdk_gc_set_dashes(gc, 0, dash_list, 2);
321 break;
323 gdk_draw_line(win, gc, x, y+height/2, x+width, y+height/2);
324 gdk_gc_set_line_attributes(gc, gcvalues.line_width, gcvalues.line_style,
325 gcvalues.cap_style, gcvalues.join_style);
327 return TRUE;
330 /* ------- Code for DiaArrowChooser ----------------------- */
331 static GtkType dia_arrow_chooser_get_type (void);
333 static gint close_and_hide(GtkWidget *wid, GdkEventAny *event) {
334 gtk_widget_hide(wid);
335 return TRUE;
337 static const char *button_menu_key = "dia-button-menu";
338 static const char *menuitem_enum_key = "dia-menuitem-value";
341 #define DIA_ARROW_CHOOSER(obj) (GTK_CHECK_CAST((obj),dia_arrow_chooser_get_type(), DiaArrowChooser))
342 #define DIA_ARROW_CHOOSER_CLASS(obj) (GTK_CHECK_CLASS_CAST((obj), dia_arrow_chooser_get_type(), DiaArrowChooserClass))
344 typedef struct _DiaArrowChooser DiaArrowChooser;
345 typedef struct _DiaArrowChooserClass DiaArrowChooserClass;
347 struct _DiaArrowChooser
349 GtkButton button;
350 DiaArrowPreview *preview;
351 Arrow arrow;
352 gboolean left;
354 DiaChangeArrowCallback callback;
355 gpointer user_data;
357 GtkWidget *dialog;
358 DiaArrowSelector *selector;
360 struct _DiaArrowChooserClass
362 GtkButtonClass parent_class;
365 static void dia_arrow_chooser_class_init (DiaArrowChooserClass *klass);
366 static void dia_arrow_chooser_init (DiaArrowChooser *arrow);
367 static gint dia_arrow_chooser_event (GtkWidget *widget,
368 GdkEvent *event);
369 static void dia_arrow_chooser_dialog_ok (DiaArrowChooser *arrow);
370 static void dia_arrow_chooser_dialog_cancel (DiaArrowChooser *arrow);
371 static void dia_arrow_chooser_dialog_destroy (DiaArrowChooser *arrow);
372 static void dia_arrow_chooser_change_arrow_type (GtkMenuItem *mi,
373 DiaArrowChooser *arrow);
375 static GtkType
376 dia_arrow_chooser_get_type (void)
378 static GtkType arrow_type = 0;
380 if (!arrow_type) {
381 static const GtkTypeInfo arrow_info = {
382 "DiaArrowChooser",
383 sizeof (DiaArrowChooser),
384 sizeof (DiaArrowChooserClass),
385 (GtkClassInitFunc) dia_arrow_chooser_class_init,
386 (GtkObjectInitFunc) dia_arrow_chooser_init,
387 /* reserved_1 */ NULL,
388 /* reserved_2 */ NULL,
389 (GtkClassInitFunc) NULL,
391 arrow_type = gtk_type_unique (GTK_TYPE_BUTTON, &arrow_info);
393 return arrow_type;
396 static void
397 dia_arrow_chooser_class_init (DiaArrowChooserClass *class)
399 GtkWidgetClass *widget_class;
401 widget_class = (GtkWidgetClass *)class;
402 widget_class->event = dia_arrow_chooser_event;
405 static void
406 dia_arrow_chooser_init (DiaArrowChooser *arrow)
408 GtkWidget *wid;
410 arrow->left = FALSE;
411 arrow->arrow.type = ARROW_NONE;
412 arrow->arrow.length = DEFAULT_ARROW_LENGTH;
413 arrow->arrow.width = DEFAULT_ARROW_WIDTH;
415 wid = dia_arrow_preview_new(ARROW_NONE, arrow->left);
416 gtk_container_add(GTK_CONTAINER(arrow), wid);
417 gtk_widget_show(wid);
418 arrow->preview = DIA_ARROW_PREVIEW(wid);
420 arrow->dialog = NULL;
423 /* Creating the dialog separately so we can handle destroy */
424 void
425 dia_arrow_chooser_dialog_new(GtkWidget *widget, gpointer userdata)
427 DiaArrowChooser *chooser = DIA_ARROW_CHOOSER(userdata);
428 if (chooser->dialog == NULL) {
429 GtkWidget *wid;
430 chooser->dialog = wid = gtk_dialog_new();
431 gtk_window_set_title(GTK_WINDOW(wid), _("Arrow Properties"));
432 g_signal_connect(GTK_OBJECT(wid), "delete_event",
433 G_CALLBACK(close_and_hide), NULL);
434 g_signal_connect(GTK_OBJECT(wid), "destroy",
435 G_CALLBACK(gtk_widget_destroyed),
436 &chooser->dialog);
438 wid = dia_arrow_selector_new();
439 gtk_container_set_border_width(GTK_CONTAINER(wid), 5);
440 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(chooser->dialog)->vbox), wid,
441 TRUE, TRUE, 0);
442 gtk_widget_show(wid);
443 chooser->selector = DIAARROWSELECTOR(wid);
444 dia_arrow_selector_set_arrow(chooser->selector, chooser->arrow);
446 wid = gtk_button_new_with_label(_("OK"));
447 GTK_WIDGET_SET_FLAGS(wid, GTK_CAN_DEFAULT);
448 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(chooser->dialog)->action_area),wid);
449 gtk_widget_grab_default(wid);
450 g_signal_connect_swapped(GTK_OBJECT(wid), "clicked",
451 G_CALLBACK(dia_arrow_chooser_dialog_ok),
452 GTK_OBJECT(chooser));
453 gtk_widget_show(wid);
455 wid = gtk_button_new_with_label(_("Cancel"));
456 GTK_WIDGET_SET_FLAGS(wid, GTK_CAN_DEFAULT);
457 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(chooser->dialog)->action_area),wid);
458 g_signal_connect_swapped(GTK_OBJECT(wid), "clicked",
459 G_CALLBACK(dia_arrow_chooser_dialog_cancel),
460 GTK_OBJECT(chooser));
461 gtk_widget_show(wid);
465 void
466 dia_arrow_chooser_dialog_show(GtkWidget *widget, gpointer userdata)
468 DiaArrowChooser *chooser = DIA_ARROW_CHOOSER(userdata);
469 dia_arrow_chooser_dialog_new(widget, chooser);
470 dia_arrow_selector_set_arrow(chooser->selector, chooser->arrow);
471 gtk_widget_show(chooser->dialog);
474 GtkWidget *
475 dia_arrow_chooser_new(gboolean left, DiaChangeArrowCallback callback,
476 gpointer user_data)
478 DiaArrowChooser *chooser = gtk_type_new(dia_arrow_chooser_get_type());
479 GtkWidget *menu, *mi, *ar;
480 gint i;
482 chooser->left = left;
483 dia_arrow_preview_set(chooser->preview, chooser->preview->atype, left);
484 chooser->callback = callback;
485 chooser->user_data = user_data;
487 dia_arrow_chooser_dialog_new(NULL, chooser);
489 menu = gtk_menu_new();
490 gtk_object_set_data_full(GTK_OBJECT(chooser), button_menu_key, menu,
491 (GtkDestroyNotify)gtk_widget_unref);
492 for (i = 0; arrow_types[i].name != NULL; i++) {
493 mi = gtk_menu_item_new();
494 gtk_object_set_data(GTK_OBJECT(mi), menuitem_enum_key,
495 GINT_TO_POINTER(arrow_types[i].enum_value));
496 gtk_tooltips_set_tip(tool_tips, mi, arrow_types[i].name, NULL);
497 ar = dia_arrow_preview_new(arrow_types[i].enum_value, left);
499 gtk_container_add(GTK_CONTAINER(mi), ar);
500 gtk_widget_show(ar);
501 g_signal_connect(GTK_OBJECT(mi), "activate",
502 G_CALLBACK(dia_arrow_chooser_change_arrow_type),
503 chooser);
504 gtk_container_add(GTK_CONTAINER(menu), mi);
505 gtk_widget_show(mi);
507 mi = gtk_menu_item_new_with_label(_("Details..."));
508 g_signal_connect(GTK_OBJECT(mi), "activate",
509 G_CALLBACK(dia_arrow_chooser_dialog_show),
510 GTK_OBJECT(chooser));
511 gtk_container_add(GTK_CONTAINER(menu), mi);
512 gtk_widget_show(mi);
514 return GTK_WIDGET(chooser);
517 static gint
518 dia_arrow_chooser_event(GtkWidget *widget, GdkEvent *event)
520 if (event->type == GDK_BUTTON_PRESS && event->button.button == 1) {
521 GtkMenu *menu = gtk_object_get_data(GTK_OBJECT(widget), button_menu_key);
522 gtk_menu_popup(menu, NULL, NULL, NULL, NULL,
523 event->button.button, event->button.time);
524 return TRUE;
526 return FALSE;
529 static void
530 dia_arrow_chooser_dialog_ok (DiaArrowChooser *arrow)
532 Arrow new_arrow = dia_arrow_selector_get_arrow(arrow->selector);
534 if (new_arrow.type != arrow->arrow.type ||
535 new_arrow.length != arrow->arrow.length ||
536 new_arrow.width != arrow->arrow.width) {
537 arrow->arrow = new_arrow;
538 dia_arrow_preview_set(arrow->preview, new_arrow.type, arrow->left);
539 if (arrow->callback)
540 (* arrow->callback)(arrow->arrow, arrow->user_data);
542 gtk_widget_hide(arrow->dialog);
545 static void
546 dia_arrow_chooser_dialog_cancel (DiaArrowChooser *arrow)
548 if (arrow->dialog != NULL)
549 dia_arrow_selector_set_arrow(arrow->selector, arrow->arrow);
550 gtk_widget_hide(arrow->dialog);
553 static void
554 dia_arrow_chooser_dialog_destroy (DiaArrowChooser *chooser)
556 /* dia_arrow_selector_set_arrow(arrow->selector, arrow->arrow);*/
557 chooser->dialog = NULL;
558 chooser->selector = NULL;
561 static void
562 dia_arrow_chooser_change_arrow_type(GtkMenuItem *mi, DiaArrowChooser *arrow)
564 ArrowType atype = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(mi),
565 menuitem_enum_key));
567 if (arrow->arrow.type != atype) {
568 dia_arrow_preview_set(arrow->preview, atype, arrow->left);
569 arrow->arrow.type = atype;
570 if (arrow->dialog != NULL)
571 dia_arrow_selector_set_arrow(arrow->selector, arrow->arrow);
572 if (arrow->callback)
573 (* arrow->callback)(arrow->arrow, arrow->user_data);
578 /* ------- Code for DiaLineChooser ---------------------- */
579 static GtkType dia_line_chooser_get_type (void);
581 #define DIA_LINE_CHOOSER(obj) (GTK_CHECK_CAST((obj),dia_line_chooser_get_type(), DiaLineChooser))
582 #define DIA_LINE_CHOOSER_CLASS(obj) (GTK_CHECK_CLASS_CAST((obj), dia_line_chooser_get_type(), DiaLineChooserClass))
584 typedef struct _DiaLineChooser DiaLineChooser;
585 typedef struct _DiaLineChooserClass DiaLineChooserClass;
587 struct _DiaLineChooser
589 GtkButton button;
590 DiaLinePreview *preview;
591 LineStyle lstyle;
592 real dash_length;
594 DiaChangeLineCallback callback;
595 gpointer user_data;
597 GtkWidget *dialog;
598 DiaLineStyleSelector *selector;
600 struct _DiaLineChooserClass
602 GtkButtonClass parent_class;
605 static void dia_line_chooser_class_init (DiaLineChooserClass *klass);
606 static void dia_line_chooser_init (DiaLineChooser *arrow);
607 static gint dia_line_chooser_event (GtkWidget *widget,
608 GdkEvent *event);
609 static void dia_line_chooser_dialog_ok (DiaLineChooser *lchooser);
610 static void dia_line_chooser_dialog_cancel (DiaLineChooser *lchooser);
611 static void dia_line_chooser_change_line_style (GtkMenuItem *mi,
612 DiaLineChooser *lchooser);
614 static GtkType
615 dia_line_chooser_get_type (void)
617 static GtkType arrow_type = 0;
619 if (!arrow_type) {
620 static const GtkTypeInfo arrow_info = {
621 "DiaLineChooser",
622 sizeof (DiaLineChooser),
623 sizeof (DiaLineChooserClass),
624 (GtkClassInitFunc) dia_line_chooser_class_init,
625 (GtkObjectInitFunc) dia_line_chooser_init,
626 /* reserved_1 */ NULL,
627 /* reserved_2 */ NULL,
628 (GtkClassInitFunc) NULL,
630 arrow_type = gtk_type_unique (GTK_TYPE_BUTTON, &arrow_info);
632 return arrow_type;
635 static void
636 dia_line_chooser_class_init (DiaLineChooserClass *class)
638 GtkWidgetClass *widget_class;
640 widget_class = (GtkWidgetClass *)class;
641 widget_class->event = dia_line_chooser_event;
644 static void
645 dia_line_chooser_init (DiaLineChooser *lchooser)
647 GtkWidget *wid;
648 GtkWidget *menu, *mi, *ln;
649 gint i;
651 lchooser->lstyle = LINESTYLE_SOLID;
652 lchooser->dash_length = DEFAULT_LINESTYLE_DASHLEN;
654 wid = dia_line_preview_new(LINESTYLE_SOLID);
655 gtk_container_add(GTK_CONTAINER(lchooser), wid);
656 gtk_widget_show(wid);
657 lchooser->preview = DIA_LINE_PREVIEW(wid);
659 lchooser->dialog = wid = gtk_dialog_new();
660 gtk_window_set_title(GTK_WINDOW(wid), _("Line Style Properties"));
661 g_signal_connect(GTK_OBJECT(wid), "delete_event",
662 G_CALLBACK(close_and_hide), NULL);
664 wid = dia_line_style_selector_new();
665 gtk_container_set_border_width(GTK_CONTAINER(wid), 5);
666 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(lchooser->dialog)->vbox), wid,
667 TRUE, TRUE, 0);
668 gtk_widget_show(wid);
669 lchooser->selector = DIALINESTYLESELECTOR(wid);
671 wid = gtk_button_new_with_label(_("OK"));
672 GTK_WIDGET_SET_FLAGS(wid, GTK_CAN_DEFAULT);
673 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(lchooser->dialog)->action_area),
674 wid);
675 gtk_widget_grab_default(wid);
676 g_signal_connect_swapped(GTK_OBJECT(wid), "clicked",
677 G_CALLBACK(dia_line_chooser_dialog_ok),
678 GTK_OBJECT(lchooser));
679 gtk_widget_show(wid);
681 wid = gtk_button_new_with_label(_("Cancel"));
682 GTK_WIDGET_SET_FLAGS(wid, GTK_CAN_DEFAULT);
683 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(lchooser->dialog)->action_area),
684 wid);
685 g_signal_connect_swapped(GTK_OBJECT(wid), "clicked",
686 G_CALLBACK(dia_line_chooser_dialog_cancel),
687 GTK_OBJECT(lchooser));
689 menu = gtk_menu_new();
690 gtk_object_set_data_full(GTK_OBJECT(lchooser), button_menu_key, menu,
691 (GtkDestroyNotify)gtk_widget_unref);
692 for (i = 0; i <= LINESTYLE_DOTTED; i++) {
693 mi = gtk_menu_item_new();
694 gtk_object_set_data(GTK_OBJECT(mi), menuitem_enum_key, GINT_TO_POINTER(i));
695 ln = dia_line_preview_new(i);
696 gtk_container_add(GTK_CONTAINER(mi), ln);
697 gtk_widget_show(ln);
698 g_signal_connect(GTK_OBJECT(mi), "activate",
699 G_CALLBACK(dia_line_chooser_change_line_style),
700 lchooser);
701 gtk_container_add(GTK_CONTAINER(menu), mi);
702 gtk_widget_show(mi);
704 mi = gtk_menu_item_new_with_label(_("Details..."));
705 g_signal_connect_swapped(GTK_OBJECT(mi), "activate",
706 G_CALLBACK(gtk_widget_show),
707 GTK_OBJECT(lchooser->dialog));
708 gtk_container_add(GTK_CONTAINER(menu), mi);
709 gtk_widget_show(mi);
711 gtk_widget_show(wid);
714 GtkWidget *
715 dia_line_chooser_new(DiaChangeLineCallback callback,
716 gpointer user_data)
718 DiaLineChooser *chooser = gtk_type_new(dia_line_chooser_get_type());
720 chooser->callback = callback;
721 chooser->user_data = user_data;
723 return GTK_WIDGET(chooser);
726 static gint
727 dia_line_chooser_event(GtkWidget *widget, GdkEvent *event)
729 if (event->type == GDK_BUTTON_PRESS && event->button.button == 1) {
730 GtkMenu *menu = gtk_object_get_data(GTK_OBJECT(widget), button_menu_key);
731 gtk_menu_popup(menu, NULL, NULL, NULL, NULL,
732 event->button.button, event->button.time);
733 return TRUE;
735 return FALSE;
738 static void
739 dia_line_chooser_dialog_ok (DiaLineChooser *lchooser)
741 LineStyle new_style;
742 real new_dash;
744 dia_line_style_selector_get_linestyle(lchooser->selector,
745 &new_style, &new_dash);
746 if (new_style != lchooser->lstyle || new_dash != lchooser->dash_length) {
747 lchooser->lstyle = new_style;
748 lchooser->dash_length = new_dash;
749 dia_line_preview_set(lchooser->preview, new_style);
750 if (lchooser->callback)
751 (* lchooser->callback)(new_style, new_dash, lchooser->user_data);
753 gtk_widget_hide(lchooser->dialog);
755 static void
756 dia_line_chooser_dialog_cancel (DiaLineChooser *lchooser)
758 dia_line_style_selector_set_linestyle(lchooser->selector, lchooser->lstyle,
759 lchooser->dash_length);
760 gtk_widget_hide(lchooser->dialog);
763 static void
764 dia_line_chooser_change_line_style(GtkMenuItem *mi, DiaLineChooser *lchooser)
766 LineStyle lstyle = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(mi),
767 menuitem_enum_key));
769 if (lchooser->lstyle != lstyle) {
770 dia_line_preview_set(lchooser->preview, lstyle);
771 lchooser->lstyle = lstyle;
772 dia_line_style_selector_set_linestyle(lchooser->selector, lchooser->lstyle,
773 lchooser->dash_length);
774 if (lchooser->callback)
775 (* lchooser->callback)(lchooser->lstyle, lchooser->dash_length,
776 lchooser->user_data);