1 /* Dia -- an diagram creation/manipulation program
2  * Copyright (C) 1998 Alexander Larsson
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 #include <config.h>
20 #include <string.h>
21 #include "intl.h"
22 #undef GTK_DISABLE_DEPRECATED /* GtkOptionMenu, ... */
23 #include "widgets.h"
24 #include "units.h"
25 #include "message.h"
26 #include "dia_dirs.h"
27 #include "arrows.h"
28 #include "diaarrowchooser.h"
29 #include "dialinechooser.h"
30 #include "persistence.h"
31 #include "dia-lib-icons.h"
32 
33 #include <stdlib.h>
34 #include <glib.h>
35 #include <gdk/gdk.h>
36 #include <gtk/gtk.h>
37 #include <pango/pango.h>
38 #include <stdio.h>
39 #include <time.h>
40 #include <gdk/gdkkeysyms.h>
41 
42 /* hidden internals for two reasosn:
43  * - noone is supposed to mess with the internals
44  * - it uses deprecated stuff
45  */
46 struct _DiaDynamicMenu {
47   GtkOptionMenu parent;
48 
49   GList *default_entries;
50 
51   DDMCreateItemFunc create_func;
52   DDMCallbackFunc activate_func;
53   gpointer userdata;
54 
55   GtkMenuItem *other_item;
56 
57   gchar *persistent_name;
58   gint cols;
59 
60   gchar *active;
61   /** For the list-based versions, these are the options */
62   GList *options;
63 
64 };
65 
66 struct _DiaDynamicMenuClass {
67   GtkOptionMenuClass parent_class;
68 };
69 
70 
71 /************* DiaSizeSelector: ***************/
72 /* A widget that selects two sizes, width and height, optionally keeping
73  * aspect ratio.  When created, aspect ratio is locked, but the user can
74  * unlock it.  The current users do not store aspect ratio, so we have
75  * to give a good default.
76  */
77 struct _DiaSizeSelector
78 {
79   GtkHBox hbox;
80   GtkSpinButton *width, *height;
81   GtkToggleButton *aspect_locked;
82   real ratio;
83   GtkAdjustment *last_adjusted;
84 };
85 
86 struct _DiaSizeSelectorClass
87 {
88   GtkHBoxClass parent_class;
89 };
90 
91 enum {
92     DSS_VALUE_CHANGED,
93     DSS_LAST_SIGNAL
94 };
95 
96 static guint dss_signals[DSS_LAST_SIGNAL] = { 0 };
97 
98 static void
dia_size_selector_unrealize(GtkWidget * widget)99 dia_size_selector_unrealize(GtkWidget *widget)
100 {
101   (* GTK_WIDGET_CLASS (gtk_type_class(gtk_hbox_get_type ()))->unrealize) (widget);
102 }
103 
104 static void
dia_size_selector_class_init(DiaSizeSelectorClass * class)105 dia_size_selector_class_init (DiaSizeSelectorClass *class)
106 {
107   GtkObjectClass *object_class;
108   GtkWidgetClass *widget_class;
109 
110   object_class = (GtkObjectClass*) class;
111   widget_class = (GtkWidgetClass*) class;
112   widget_class->unrealize = dia_size_selector_unrealize;
113 
114   dss_signals[DSS_VALUE_CHANGED]
115       = g_signal_new("value-changed",
116 		     G_TYPE_FROM_CLASS(class),
117 		     G_SIGNAL_RUN_FIRST,
118 		     0, NULL, NULL,
119 		     g_cclosure_marshal_VOID__VOID,
120 		     G_TYPE_NONE, 0);
121 }
122 
123 static void
dia_size_selector_adjust_width(DiaSizeSelector * ss)124 dia_size_selector_adjust_width(DiaSizeSelector *ss)
125 {
126   real height =
127     gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(ss->height));
128   if (fabs(ss->ratio) > 1e-6)
129     gtk_spin_button_set_value(GTK_SPIN_BUTTON(ss->width), height*ss->ratio);
130 }
131 
132 static void
dia_size_selector_adjust_height(DiaSizeSelector * ss)133 dia_size_selector_adjust_height(DiaSizeSelector *ss)
134 {
135   real width =
136     gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(ss->width));
137   if (fabs(ss->ratio) > 1e-6)
138     gtk_spin_button_set_value(GTK_SPIN_BUTTON(ss->height), width/ss->ratio);
139 }
140 
141 static void
dia_size_selector_ratio_callback(GtkAdjustment * limits,gpointer userdata)142 dia_size_selector_ratio_callback(GtkAdjustment *limits, gpointer userdata)
143 {
144   static gboolean in_progress = FALSE;
145   DiaSizeSelector *ss = DIA_SIZE_SELECTOR(userdata);
146 
147   ss->last_adjusted = limits;
148 
149   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ss->aspect_locked))
150       && ss->ratio != 0.0) {
151 
152     if (in_progress)
153       return;
154     in_progress = TRUE;
155 
156     if (limits == gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(ss->width))) {
157       dia_size_selector_adjust_height(ss);
158     } else {
159       dia_size_selector_adjust_width(ss);
160     }
161 
162     in_progress = FALSE;
163   }
164 
165   g_signal_emit(ss, dss_signals[DSS_VALUE_CHANGED], 0);
166 
167 }
168 
169 /** Update the ratio of this DSS to be the ratio of width to height.
170  * If height is 0, ratio becomes 0.0.
171  */
172 static void
dia_size_selector_set_ratio(DiaSizeSelector * ss,real width,real height)173 dia_size_selector_set_ratio(DiaSizeSelector *ss, real width, real height)
174 {
175   if (height > 0.0)
176     ss->ratio = width/height;
177   else
178     ss->ratio = 0.0;
179 }
180 
181 static void
dia_size_selector_lock_pressed(GtkWidget * widget,gpointer data)182 dia_size_selector_lock_pressed(GtkWidget *widget, gpointer data)
183 {
184   DiaSizeSelector *ss = DIA_SIZE_SELECTOR(data);
185 
186   dia_size_selector_set_ratio(ss,
187 			      gtk_spin_button_get_value(GTK_SPIN_BUTTON(ss->width)),
188 			      gtk_spin_button_get_value(GTK_SPIN_BUTTON(ss->height)));
189 }
190 
191 /* Possible args:  Init width, init height, digits */
192 
193 static void
dia_size_selector_init(DiaSizeSelector * ss)194 dia_size_selector_init (DiaSizeSelector *ss)
195 {
196   GtkAdjustment *adj;
197 
198   ss->ratio = 0.0;
199   /* Here's where we set up the real thing */
200   adj = GTK_ADJUSTMENT(gtk_adjustment_new(1.0, 0.01, 10,
201 					  0.1, 1.0, 0));
202   ss->width = GTK_SPIN_BUTTON(gtk_spin_button_new(adj, 1.0, 2));
203   gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(ss->width), TRUE);
204   gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(ss->width), TRUE);
205   gtk_box_pack_start(GTK_BOX(ss), GTK_WIDGET(ss->width), FALSE, TRUE, 0);
206   gtk_widget_show(GTK_WIDGET(ss->width));
207 
208   adj = GTK_ADJUSTMENT(gtk_adjustment_new(1.0, 0.01, 10,
209 					  0.1, 1.0, 0));
210   ss->height = GTK_SPIN_BUTTON(gtk_spin_button_new(adj, 1.0, 2));
211   gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(ss->height), TRUE);
212   gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(ss->height), TRUE);
213   gtk_box_pack_start(GTK_BOX(ss), GTK_WIDGET(ss->height), FALSE, TRUE, 0);
214   gtk_widget_show(GTK_WIDGET(ss->height));
215 
216   /* Replace label with images */
217   /* should make sure they're both unallocated when the widget dies.
218   * That should happen in the "destroy" handler, where both should
219   * be unref'd */
220   ss->aspect_locked =
221     GTK_TOGGLE_BUTTON(dia_toggle_button_new_with_icons
222 		      (dia_unbroken_chain_icon,
223 		       dia_broken_chain_icon));
224 
225   gtk_container_set_border_width(GTK_CONTAINER(ss->aspect_locked), 0);
226 
227   gtk_box_pack_start(GTK_BOX(ss), GTK_WIDGET(ss->aspect_locked), FALSE, TRUE, 0);
228   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ss->aspect_locked), TRUE);
229   gtk_widget_show(GTK_WIDGET(ss->aspect_locked));
230 
231   gtk_signal_connect (GTK_OBJECT (ss->aspect_locked), "clicked",
232                       (GtkSignalFunc) dia_size_selector_lock_pressed,
233                       ss);
234   /* Make sure that the aspect ratio stays the same */
235   g_signal_connect(GTK_OBJECT(gtk_spin_button_get_adjustment(ss->width)),
236 		   "value_changed",
237 		   G_CALLBACK(dia_size_selector_ratio_callback), (gpointer)ss);
238   g_signal_connect(GTK_OBJECT(gtk_spin_button_get_adjustment(ss->height)),
239 		   "value_changed",
240 		   G_CALLBACK(dia_size_selector_ratio_callback), (gpointer)ss);
241 }
242 
243 GtkType
dia_size_selector_get_type(void)244 dia_size_selector_get_type (void)
245 {
246   static GtkType dss_type = 0;
247 
248   if (!dss_type) {
249     static const GtkTypeInfo dss_info = {
250       "DiaSizeSelector",
251       sizeof (DiaSizeSelector),
252       sizeof (DiaSizeSelectorClass),
253       (GtkClassInitFunc) dia_size_selector_class_init,
254       (GtkObjectInitFunc) dia_size_selector_init,
255       NULL,
256       NULL,
257       (GtkClassInitFunc) NULL,
258     };
259 
260     dss_type = gtk_type_unique (gtk_hbox_get_type (), &dss_info);
261 
262   }
263 
264   return dss_type;
265 }
266 
267 GtkWidget *
dia_size_selector_new(real width,real height)268 dia_size_selector_new (real width, real height)
269 {
270   GtkWidget *wid;
271 
272   wid = GTK_WIDGET ( gtk_type_new (dia_size_selector_get_type ()));
273   dia_size_selector_set_size(DIA_SIZE_SELECTOR(wid), width, height);
274   return wid;
275 }
276 
277 void
dia_size_selector_set_size(DiaSizeSelector * ss,real width,real height)278 dia_size_selector_set_size(DiaSizeSelector *ss, real width, real height)
279 {
280   gtk_spin_button_set_value(GTK_SPIN_BUTTON(ss->width), width);
281   gtk_spin_button_set_value(GTK_SPIN_BUTTON(ss->height), height);
282   /*
283   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ss->aspect_locked),
284 			       fabs(width - height) < 0.000001);
285   */
286   dia_size_selector_set_ratio(ss, width, height);
287 }
288 
289 void
dia_size_selector_set_locked(DiaSizeSelector * ss,gboolean locked)290 dia_size_selector_set_locked(DiaSizeSelector *ss, gboolean locked)
291 {
292   if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ss->aspect_locked))
293       && locked) {
294     dia_size_selector_set_ratio(ss,
295 				gtk_spin_button_get_value(GTK_SPIN_BUTTON(ss->width)),
296 				gtk_spin_button_get_value(GTK_SPIN_BUTTON(ss->height)));
297   }
298   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ss->aspect_locked), locked);
299 }
300 
301 gboolean
dia_size_selector_get_size(DiaSizeSelector * ss,real * width,real * height)302 dia_size_selector_get_size(DiaSizeSelector *ss, real *width, real *height)
303 {
304   *width = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(ss->width));
305   *height = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(ss->height));
306   return gtk_toggle_button_get_active(ss->aspect_locked);
307 }
308 
309 /************* DiaFontSelector: ***************/
310 
311 /* Should these structs be in widgets.h instead? :
312  * _no_ they should not, noone is supposed to mess with the internals, ever heard of information hiding?
313  */
314 
315 struct _DiaFontSelector
316 {
317   GtkHBox hbox;
318 
319   GtkOptionMenu *font_omenu;
320   GtkOptionMenu *style_omenu;
321   GtkMenu *style_menu;
322 };
323 
324 struct _DiaFontSelectorClass
325 {
326   GtkHBoxClass parent_class;
327 };
328 
329 enum {
330     DFONTSEL_VALUE_CHANGED,
331     DFONTSEL_LAST_SIGNAL
332 };
333 
334 static guint dfontsel_signals[DFONTSEL_LAST_SIGNAL] = { 0 };
335 
336 
337 /* New and improved font selector:  Contains the three standard fonts
338  * and an 'Other fonts...' entry that opens the font dialog.  The fonts
339  * selected in the font dialog are persistently added to the menu.
340  *
341  * +----------------+
342  * | Sans           |
343  * | Serif          |
344  * | Monospace      |
345  * | -------------- |
346  * | Bodini         |
347  * | CurlyGothic    |
348  * | OldWestern     |
349  * | -------------- |
350  * | Other fonts... |
351  * +----------------+
352  */
353 
354 static void dia_font_selector_fontmenu_callback(DiaDynamicMenu *ddm,
355 						gpointer data);
356 static void dia_font_selector_stylemenu_callback(GtkMenu *menu,
357 						gpointer data);
358 static void dia_font_selector_set_styles(DiaFontSelector *fs,
359 					 const gchar *name,
360 					 DiaFontStyle dia_style);
361 static void dia_font_selector_set_style_menu(DiaFontSelector *fs,
362 					     PangoFontFamily *pff,
363 					     DiaFontStyle dia_style);
364 
365 static void
dia_font_selector_class_init(DiaFontSelectorClass * class)366 dia_font_selector_class_init (DiaFontSelectorClass *class)
367 {
368   GtkObjectClass *object_class;
369 
370   object_class = (GtkObjectClass*) class;
371 
372   dfontsel_signals[DFONTSEL_VALUE_CHANGED]
373       = g_signal_new("value_changed",
374 		     G_TYPE_FROM_CLASS(class),
375 		     G_SIGNAL_RUN_FIRST,
376 		     0, NULL, NULL,
377 		     g_cclosure_marshal_VOID__VOID,
378 		     G_TYPE_NONE, 0);
379 }
380 
381 static int
dia_font_selector_sort_fonts(const void * p1,const void * p2)382 dia_font_selector_sort_fonts(const void *p1, const void *p2)
383 {
384   const gchar *n1 = pango_font_family_get_name(PANGO_FONT_FAMILY(*(void**)p1));
385   const gchar *n2 = pango_font_family_get_name(PANGO_FONT_FAMILY(*(void**)p2));
386   return g_ascii_strcasecmp(n1, n2);
387 }
388 
389 static gchar*
replace_ampersands(gchar * string)390 replace_ampersands(gchar* string)
391 {
392   gchar** pieces = g_strsplit(string, "&", -1);
393   gchar* escaped = g_strjoinv("&amp;", pieces);
394   g_strfreev(pieces);
395   return escaped;
396 }
397 
398 static GtkWidget *
dia_font_selector_create_string_item(DiaDynamicMenu * ddm,gchar * string)399 dia_font_selector_create_string_item(DiaDynamicMenu *ddm, gchar *string)
400 {
401   GtkWidget *item = gtk_menu_item_new_with_label(string);
402   if (strchr(string, '&')) {
403     gchar *escaped = replace_ampersands(string);
404     gchar *label = g_strdup_printf("<span face=\"%s,sans\" size=\"medium\">%s</span>",
405 				   escaped, escaped);
406     gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(item))), label);
407     g_free(label);
408     g_free(escaped);
409   } else {
410     gchar *label = g_strdup_printf("<span face=\"%s,sans\" size=\"medium\">%s</span>",
411 				   string, string);
412     gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(item))), label);
413     g_free(label);
414   }
415   return item;
416 }
417 
418 static void
dia_font_selector_init(DiaFontSelector * fs)419 dia_font_selector_init (DiaFontSelector *fs)
420 {
421   GtkWidget *menu;
422   GtkWidget *omenu;
423 
424   PangoFontFamily **families;
425   int n_families,i;
426   GList *fontnames = NULL;
427 
428   pango_context_list_families (dia_font_get_context(),
429 			       &families, &n_families);
430   qsort(families, n_families, sizeof(PangoFontFamily*),
431 	dia_font_selector_sort_fonts);
432   /* Doing it the slow way until I find a better way */
433   for (i = 0; i < n_families; i++) {
434     fontnames = g_list_append(fontnames,
435 			      g_strdup(pango_font_family_get_name(families[i])));
436   }
437   g_free (families);
438 
439   fs->font_omenu =
440       GTK_OPTION_MENU(dia_dynamic_menu_new_listbased(dia_font_selector_create_string_item,
441 				     fs, _("Other fonts"),
442 				     fontnames, "font-menu"));
443   g_signal_connect(DIA_DYNAMIC_MENU(fs->font_omenu), "value-changed",
444 		   G_CALLBACK(dia_font_selector_fontmenu_callback), fs);
445   dia_dynamic_menu_add_default_entry(DIA_DYNAMIC_MENU(fs->font_omenu),
446 				     "sans");
447   dia_dynamic_menu_add_default_entry(DIA_DYNAMIC_MENU(fs->font_omenu),
448 				     "serif");
449   dia_dynamic_menu_add_default_entry(DIA_DYNAMIC_MENU(fs->font_omenu),
450 				     "monospace");
451   gtk_widget_show(GTK_WIDGET(fs->font_omenu));
452 
453   /* Now build the style menu button */
454   omenu = gtk_option_menu_new();
455   fs->style_omenu = GTK_OPTION_MENU(omenu);
456   menu = gtk_menu_new ();
457   /* No callback needed since fs->style_menu keeps getting replaced. */
458   fs->style_menu = GTK_MENU(menu);
459   gtk_option_menu_set_menu (GTK_OPTION_MENU (fs->style_omenu), menu);
460 
461   gtk_widget_show(menu);
462   gtk_widget_show(omenu);
463 
464   gtk_box_pack_start_defaults(GTK_BOX(fs), GTK_WIDGET(fs->font_omenu));
465   gtk_box_pack_start_defaults(GTK_BOX(fs), GTK_WIDGET(fs->style_omenu));
466 }
467 
468 GtkType
dia_font_selector_get_type(void)469 dia_font_selector_get_type        (void)
470 {
471   static GtkType dfs_type = 0;
472 
473   if (!dfs_type) {
474     static const GtkTypeInfo dfs_info = {
475       "DiaFontSelector",
476       sizeof (DiaFontSelector),
477       sizeof (DiaFontSelectorClass),
478       (GtkClassInitFunc) dia_font_selector_class_init,
479       (GtkObjectInitFunc) dia_font_selector_init,
480       NULL,
481       NULL,
482       (GtkClassInitFunc) NULL
483     };
484 
485     dfs_type = gtk_type_unique (gtk_hbox_get_type (), &dfs_info);
486   }
487 
488   return dfs_type;
489 }
490 
491 GtkWidget *
dia_font_selector_new()492 dia_font_selector_new ()
493 {
494   return GTK_WIDGET ( gtk_type_new (dia_font_selector_get_type ()));
495 }
496 
497 static PangoFontFamily *
dia_font_selector_get_family_from_name(GtkWidget * widget,const gchar * fontname)498 dia_font_selector_get_family_from_name(GtkWidget *widget, const gchar *fontname)
499 {
500   PangoFontFamily **families;
501   int n_families,i;
502 
503   pango_context_list_families (dia_font_get_context(),
504 			       &families, &n_families);
505   /* Doing it the slow way until I find a better way */
506   for (i = 0; i < n_families; i++) {
507     if (!(g_ascii_strcasecmp(pango_font_family_get_name(families[i]), fontname))) {
508       PangoFontFamily *fam = families[i];
509       g_free(families);
510       return fam;
511     }
512   }
513   g_warning(_("Couldn't find font family for %s\n"), fontname);
514   g_free(families);
515   return NULL;
516 }
517 
518 static void
dia_font_selector_fontmenu_callback(DiaDynamicMenu * ddm,gpointer data)519 dia_font_selector_fontmenu_callback(DiaDynamicMenu *ddm, gpointer data)
520 {
521   DiaFontSelector *fs = DIAFONTSELECTOR(data);
522   char *fontname = dia_dynamic_menu_get_entry(ddm);
523   dia_font_selector_set_styles(fs, fontname, -1);
524   g_signal_emit(GTK_OBJECT(fs),
525 		dfontsel_signals[DFONTSEL_VALUE_CHANGED], 0);
526   g_free(fontname);
527 }
528 
529 static void
dia_font_selector_stylemenu_callback(GtkMenu * menu,gpointer data)530 dia_font_selector_stylemenu_callback(GtkMenu *menu, gpointer data)
531 {
532   DiaFontSelector *fs = DIAFONTSELECTOR(data);
533   g_signal_emit(GTK_OBJECT(fs),
534 		dfontsel_signals[DFONTSEL_VALUE_CHANGED], 0);
535 }
536 
537 static char *style_labels[] = {
538   "Normal",
539   "Oblique",
540   "Italic",
541   "Ultralight",
542   "Ultralight-Oblique",
543   "Ultralight-Italic",
544   "Light",
545   "Light-Oblique",
546   "Light-Italic",
547   "Medium",
548   "Medium-Oblique",
549   "Medium-Italic",
550   "Demibold",
551   "Demibold-Oblique",
552   "Demibold-Italic",
553   "Bold",
554   "Bold-Oblique",
555   "Bold-Italic",
556   "Ultrabold",
557   "Ultrabold-Oblique",
558   "Ultrabold-Italic",
559   "Heavy",
560   "Heavy-Oblique",
561   "Heavy-Italic"
562 };
563 
564 static void
dia_font_selector_set_style_menu(DiaFontSelector * fs,PangoFontFamily * pff,DiaFontStyle dia_style)565 dia_font_selector_set_style_menu(DiaFontSelector *fs,
566 				 PangoFontFamily *pff,
567 				 DiaFontStyle dia_style)
568 {
569   int select = 0;
570   PangoFontFace **faces = NULL;
571   guint nfaces = 0;
572   guint i=0;
573   GtkWidget *menu = NULL;
574   long stylebits = 0;
575   int menu_item_nr = 0;
576   GSList *group = NULL;
577 
578   menu = gtk_menu_new ();
579   g_signal_connect(menu, "selection-done",
580 		   G_CALLBACK(dia_font_selector_stylemenu_callback), fs);
581 
582   pango_font_family_list_faces(pff, &faces, &nfaces);
583 
584   for (i = 0; i < nfaces; i++) {
585     PangoFontDescription *pfd = pango_font_face_describe(faces[i]);
586     PangoStyle style = pango_font_description_get_style(pfd);
587     PangoWeight weight = pango_font_description_get_weight(pfd);
588     /**
589      * This is a quick and dirty way to pick the styles present,
590      * sort them and avoid duplicates.
591      * We set a bit for each style present, bit (weight*3+style)
592      * From style_labels, we pick #(weight*3+style)
593      * where weight and style are the Dia types.
594      */
595     /* Account for DIA_WEIGHT_NORMAL hack */
596     int weightnr = (weight-200)/100;
597     if (weightnr < 2) weightnr ++;
598     else if (weightnr == 2) weightnr = 0;
599     stylebits |= 1 << (3*weightnr + style);
600     pango_font_description_free(pfd);
601   }
602 
603   g_free(faces);
604 
605   if (stylebits == 0) {
606     g_warning ("'%s' has no style!",
607                pango_font_family_get_name (pff) ? pango_font_family_get_name (pff) : "(null font)");
608   }
609 
610   for (i = DIA_FONT_NORMAL; i <= (DIA_FONT_HEAVY | DIA_FONT_ITALIC); i+=4) {
611     GtkWidget *menuitem;
612     /**
613      * bad hack continued ...
614      */
615     int weight = DIA_FONT_STYLE_GET_WEIGHT(i) >> 4;
616     int slant = DIA_FONT_STYLE_GET_SLANT(i) >> 2;
617     if (DIA_FONT_STYLE_GET_SLANT(i) > DIA_FONT_ITALIC) continue;
618     if (!(stylebits & (1 << (3*weight + slant)))) continue;
619     menuitem = gtk_radio_menu_item_new_with_label (group, style_labels[3*weight+slant]);
620     group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem));
621     gtk_object_set_user_data(GTK_OBJECT(menuitem), GINT_TO_POINTER(i));
622     if (dia_style == i) {
623       select = menu_item_nr;
624     }
625     menu_item_nr++;
626     gtk_menu_append (GTK_MENU (menu), menuitem);
627     gtk_widget_show (menuitem);
628   }
629   gtk_widget_show(menu);
630   gtk_option_menu_remove_menu(fs->style_omenu);
631   gtk_option_menu_set_menu(fs->style_omenu, menu);
632   fs->style_menu = GTK_MENU(menu);
633   gtk_option_menu_set_history(GTK_OPTION_MENU(fs->style_omenu), select);
634   gtk_menu_set_active(fs->style_menu, select);
635   gtk_widget_set_sensitive(GTK_WIDGET(fs->style_omenu), menu_item_nr > 1);
636   gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_menu_get_active(fs->style_menu)), TRUE);
637 }
638 
639 static void
dia_font_selector_set_styles(DiaFontSelector * fs,const gchar * name,DiaFontStyle dia_style)640 dia_font_selector_set_styles(DiaFontSelector *fs,
641 			     const gchar *name, DiaFontStyle dia_style)
642 {
643   PangoFontFamily *pff;
644   pff = dia_font_selector_get_family_from_name(GTK_WIDGET(fs), name);
645   dia_font_selector_set_style_menu(fs, pff, dia_style);
646 }
647 
648 
649 /* API functions */
650 /** Set a string to be used for preview in the GTK font selector dialog.
651  * The start of this string will be copied.
652  * This function is now obsolete.
653  */
654 void
dia_font_selector_set_preview(DiaFontSelector * fs,gchar * text)655 dia_font_selector_set_preview(DiaFontSelector *fs, gchar *text) {
656 }
657 
658 /** Set the current font to be shown in the font selector.
659  */
660 void
dia_font_selector_set_font(DiaFontSelector * fs,DiaFont * font)661 dia_font_selector_set_font(DiaFontSelector *fs, DiaFont *font)
662 {
663   const gchar *fontname = dia_font_get_family(font);
664   /* side effect: adds fontname to presistence list */
665   dia_dynamic_menu_select_entry(DIA_DYNAMIC_MENU(fs->font_omenu), fontname);
666   g_signal_emit(GTK_OBJECT(fs),
667 		dfontsel_signals[DFONTSEL_VALUE_CHANGED], 0);
668   dia_font_selector_set_styles(fs, fontname, dia_font_get_style (font));
669 }
670 
671 DiaFont *
dia_font_selector_get_font(DiaFontSelector * fs)672 dia_font_selector_get_font(DiaFontSelector *fs)
673 {
674   GtkWidget *menuitem;
675   char *fontname;
676   DiaFontStyle style;
677   DiaFont *font;
678 
679   fontname = dia_dynamic_menu_get_entry(DIA_DYNAMIC_MENU(fs->font_omenu));
680   menuitem = gtk_menu_get_active(fs->style_menu);
681   if (!menuitem) /* FIXME: should not happen ??? (but does if we don't have added a style) */
682     style = 0;
683   else
684     style = GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(menuitem)));
685   font = dia_font_new(fontname, style, 1.0);
686   g_free(fontname);
687   return font;
688 }
689 
690 /************* DiaAlignmentSelector: ***************/
691 struct _DiaAlignmentSelector
692 {
693   GtkOptionMenu omenu;
694 
695   GtkMenu *alignment_menu;
696 };
697 
698 struct _DiaAlignmentSelectorClass
699 {
700   GtkOptionMenuClass parent_class;
701 };
702 
703 static void
dia_alignment_selector_class_init(DiaAlignmentSelectorClass * class)704 dia_alignment_selector_class_init (DiaAlignmentSelectorClass *class)
705 {
706   GtkObjectClass *object_class;
707 
708   object_class = (GtkObjectClass*) class;
709 }
710 
711 static void
dia_alignment_selector_init(DiaAlignmentSelector * fs)712 dia_alignment_selector_init (DiaAlignmentSelector *fs)
713 {
714   GtkWidget *menu;
715   GtkWidget *submenu;
716   GtkWidget *menuitem;
717   GSList *group;
718 
719   menu = gtk_menu_new ();
720   fs->alignment_menu = GTK_MENU(menu);
721   submenu = NULL;
722   group = NULL;
723 
724   menuitem = gtk_radio_menu_item_new_with_label (group, _("Left"));
725   gtk_object_set_user_data(GTK_OBJECT(menuitem), GINT_TO_POINTER(ALIGN_LEFT));
726   group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
727   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
728   gtk_widget_show (menuitem);
729 
730   menuitem = gtk_radio_menu_item_new_with_label (group, _("Center"));
731   gtk_object_set_user_data(GTK_OBJECT(menuitem), GINT_TO_POINTER(ALIGN_CENTER));
732   group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
733   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
734   gtk_widget_show (menuitem);
735 
736   menuitem = gtk_radio_menu_item_new_with_label (group, _("Right"));
737   gtk_object_set_user_data(GTK_OBJECT(menuitem), GINT_TO_POINTER(ALIGN_RIGHT));
738   group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
739   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
740   gtk_widget_show (menuitem);
741 
742   gtk_menu_set_active(GTK_MENU (menu), DEFAULT_ALIGNMENT);
743   gtk_option_menu_set_menu (GTK_OPTION_MENU (fs), menu);
744 }
745 
746 GtkType
dia_alignment_selector_get_type(void)747 dia_alignment_selector_get_type        (void)
748 {
749   static GtkType dfs_type = 0;
750 
751   if (!dfs_type) {
752     static const GtkTypeInfo dfs_info = {
753       "DiaAlignmentSelector",
754       sizeof (DiaAlignmentSelector),
755       sizeof (DiaAlignmentSelectorClass),
756       (GtkClassInitFunc) dia_alignment_selector_class_init,
757       (GtkObjectInitFunc) dia_alignment_selector_init,
758       NULL,
759       NULL,
760       (GtkClassInitFunc) NULL,
761     };
762 
763     dfs_type = gtk_type_unique (gtk_option_menu_get_type (), &dfs_info);
764   }
765 
766   return dfs_type;
767 }
768 
769 GtkWidget *
dia_alignment_selector_new()770 dia_alignment_selector_new ()
771 {
772   return GTK_WIDGET ( gtk_type_new (dia_alignment_selector_get_type ()));
773 }
774 
775 
776 Alignment
dia_alignment_selector_get_alignment(DiaAlignmentSelector * fs)777 dia_alignment_selector_get_alignment(DiaAlignmentSelector *fs)
778 {
779   GtkWidget *menuitem;
780   void *align;
781 
782   menuitem = gtk_menu_get_active(fs->alignment_menu);
783   align = gtk_object_get_user_data(GTK_OBJECT(menuitem));
784 
785   return GPOINTER_TO_INT(align);
786 }
787 
788 void
dia_alignment_selector_set_alignment(DiaAlignmentSelector * as,Alignment align)789 dia_alignment_selector_set_alignment (DiaAlignmentSelector *as,
790 				      Alignment align)
791 {
792   gtk_menu_set_active(GTK_MENU (as->alignment_menu), align);
793   gtk_option_menu_set_history (GTK_OPTION_MENU(as), align);
794 }
795 
796 /************* DiaLineStyleSelector: ***************/
797 struct _DiaLineStyleSelector
798 {
799   GtkVBox vbox;
800 
801   GtkOptionMenu *omenu;
802   GtkMenu *linestyle_menu;
803   GtkLabel *lengthlabel;
804   GtkSpinButton *dashlength;
805 
806 };
807 
808 struct _DiaLineStyleSelectorClass
809 {
810   GtkVBoxClass parent_class;
811 };
812 
813 enum {
814     DLS_VALUE_CHANGED,
815     DLS_LAST_SIGNAL
816 };
817 
818 static guint dls_signals[DLS_LAST_SIGNAL] = { 0 };
819 
820 static void
dia_line_style_selector_class_init(DiaLineStyleSelectorClass * class)821 dia_line_style_selector_class_init (DiaLineStyleSelectorClass *class)
822 {
823   GtkObjectClass *object_class;
824 
825   object_class = (GtkObjectClass*) class;
826 
827   dls_signals[DLS_VALUE_CHANGED]
828       = g_signal_new("value-changed",
829 		     G_TYPE_FROM_CLASS(class),
830 		     G_SIGNAL_RUN_FIRST,
831 		     0, NULL, NULL,
832 		     g_cclosure_marshal_VOID__VOID,
833 		     G_TYPE_NONE, 0);
834 }
835 
836 static void
set_linestyle_sensitivity(DiaLineStyleSelector * fs)837 set_linestyle_sensitivity(DiaLineStyleSelector *fs)
838 {
839   int state;
840   GtkWidget *menuitem;
841   if (!fs->linestyle_menu) return;
842   menuitem = gtk_menu_get_active(fs->linestyle_menu);
843   state = (GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(menuitem)))
844 	   != LINESTYLE_SOLID);
845 
846   gtk_widget_set_sensitive(GTK_WIDGET(fs->lengthlabel), state);
847   gtk_widget_set_sensitive(GTK_WIDGET(fs->dashlength), state);
848 }
849 
850 static void
linestyle_type_change_callback(GtkMenu * menu,gpointer data)851 linestyle_type_change_callback(GtkMenu *menu, gpointer data)
852 {
853   set_linestyle_sensitivity(DIALINESTYLESELECTOR(data));
854   g_signal_emit(DIALINESTYLESELECTOR(data),
855 		dls_signals[DLS_VALUE_CHANGED], 0);
856 }
857 
858 static void
linestyle_dashlength_change_callback(GtkSpinButton * sb,gpointer data)859 linestyle_dashlength_change_callback(GtkSpinButton *sb, gpointer data)
860 {
861   g_signal_emit(DIALINESTYLESELECTOR(data),
862 		dls_signals[DLS_VALUE_CHANGED], 0);
863 }
864 
865 static void
dia_line_style_selector_init(DiaLineStyleSelector * fs)866 dia_line_style_selector_init (DiaLineStyleSelector *fs)
867 {
868   GtkWidget *menu;
869   GtkWidget *submenu;
870   GtkWidget *menuitem, *ln;
871   GtkWidget *label;
872   GtkWidget *length;
873   GtkWidget *box;
874   GSList *group;
875   GtkAdjustment *adj;
876   gint i;
877 
878   menu = gtk_option_menu_new();
879   fs->omenu = GTK_OPTION_MENU(menu);
880 
881   menu = gtk_menu_new ();
882   fs->linestyle_menu = GTK_MENU(menu);
883   submenu = NULL;
884   group = NULL;
885 
886   for (i = 0; i <= LINESTYLE_DOTTED; i++) {
887     menuitem = gtk_menu_item_new();
888     gtk_object_set_user_data(GTK_OBJECT(menuitem), GINT_TO_POINTER(i));
889     ln = dia_line_preview_new(i);
890     gtk_container_add(GTK_CONTAINER(menuitem), ln);
891     gtk_widget_show(ln);
892     gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
893     gtk_widget_show(menuitem);
894   }
895 #if 0
896   menuitem = gtk_radio_menu_item_new_with_label (group, _("Solid"));
897   gtk_object_set_user_data(GTK_OBJECT(menuitem), GINT_TO_POINTER(LINESTYLE_SOLID));
898   group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
899   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
900   gtk_widget_show (menuitem);
901 
902   menuitem = gtk_radio_menu_item_new_with_label (group, _("Dashed"));
903   gtk_object_set_user_data(GTK_OBJECT(menuitem), GINT_TO_POINTER(LINESTYLE_DASHED));
904   group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
905   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
906   gtk_widget_show (menuitem);
907 
908   menuitem = gtk_radio_menu_item_new_with_label (group, _("Dash-Dot"));
909   gtk_object_set_user_data(GTK_OBJECT(menuitem), GINT_TO_POINTER(LINESTYLE_DASH_DOT));
910   group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
911   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
912   gtk_widget_show (menuitem);
913 
914   menuitem = gtk_radio_menu_item_new_with_label (group, _("Dash-Dot-Dot"));
915   gtk_object_set_user_data(GTK_OBJECT(menuitem), GINT_TO_POINTER(LINESTYLE_DASH_DOT_DOT));
916   group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
917   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
918   gtk_widget_show (menuitem);
919 
920   menuitem = gtk_radio_menu_item_new_with_label (group, _("Dotted"));
921   gtk_object_set_user_data(GTK_OBJECT(menuitem), GINT_TO_POINTER(LINESTYLE_DOTTED));
922   group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
923   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
924   gtk_widget_show (menuitem);
925 #endif
926 
927   gtk_menu_set_active(GTK_MENU (menu), DEFAULT_LINESTYLE);
928   gtk_option_menu_set_menu (GTK_OPTION_MENU (fs->omenu), menu);
929   g_signal_connect(GTK_OBJECT(menu), "selection-done",
930 		   G_CALLBACK(linestyle_type_change_callback), fs);
931 
932   gtk_box_pack_start(GTK_BOX(fs), GTK_WIDGET(fs->omenu), FALSE, TRUE, 0);
933   gtk_widget_show(GTK_WIDGET(fs->omenu));
934 
935   box = gtk_hbox_new(FALSE,0);
936   /*  fs->sizebox = GTK_HBOX(box); */
937 
938   label = gtk_label_new(_("Dash length: "));
939   fs->lengthlabel = GTK_LABEL(label);
940   gtk_box_pack_start_defaults(GTK_BOX(box), label);
941   gtk_widget_show(label);
942 
943   adj = (GtkAdjustment *)gtk_adjustment_new(0.1, 0.00, 10.0, 0.1, 1.0, 0);
944   length = gtk_spin_button_new(adj, DEFAULT_LINESTYLE_DASHLEN, 2);
945   gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(length), TRUE);
946   gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(length), TRUE);
947   fs->dashlength = GTK_SPIN_BUTTON(length);
948   gtk_box_pack_start_defaults(GTK_BOX (box), length);
949   gtk_widget_show (length);
950 
951   g_signal_connect(GTK_OBJECT(length), "changed",
952 		   G_CALLBACK(linestyle_dashlength_change_callback), fs);
953 
954   set_linestyle_sensitivity(fs);
955   gtk_box_pack_start_defaults(GTK_BOX(fs), box);
956   gtk_widget_show(box);
957 
958 }
959 
960 GtkType
dia_line_style_selector_get_type(void)961 dia_line_style_selector_get_type        (void)
962 {
963   static GtkType dfs_type = 0;
964 
965   if (!dfs_type) {
966     static const GtkTypeInfo dfs_info = {
967       "DiaLineStyleSelector",
968       sizeof (DiaLineStyleSelector),
969       sizeof (DiaLineStyleSelectorClass),
970       (GtkClassInitFunc) dia_line_style_selector_class_init,
971       (GtkObjectInitFunc) dia_line_style_selector_init,
972       NULL,
973       NULL,
974       (GtkClassInitFunc) NULL,
975     };
976 
977     dfs_type = gtk_type_unique (gtk_vbox_get_type (), &dfs_info);
978   }
979 
980   return dfs_type;
981 }
982 
983 GtkWidget *
dia_line_style_selector_new()984 dia_line_style_selector_new ()
985 {
986   return GTK_WIDGET ( gtk_type_new (dia_line_style_selector_get_type ()));
987 }
988 
989 
990 void
dia_line_style_selector_get_linestyle(DiaLineStyleSelector * fs,LineStyle * ls,real * dl)991 dia_line_style_selector_get_linestyle(DiaLineStyleSelector *fs,
992 				      LineStyle *ls, real *dl)
993 {
994   GtkWidget *menuitem;
995   void *align;
996 
997   menuitem = gtk_menu_get_active(fs->linestyle_menu);
998   align = gtk_object_get_user_data(GTK_OBJECT(menuitem));
999   *ls = GPOINTER_TO_INT(align);
1000   if (dl!=NULL) {
1001     *dl = gtk_spin_button_get_value(fs->dashlength);
1002   }
1003 }
1004 
1005 void
dia_line_style_selector_set_linestyle(DiaLineStyleSelector * as,LineStyle linestyle,real dashlength)1006 dia_line_style_selector_set_linestyle (DiaLineStyleSelector *as,
1007 				       LineStyle linestyle, real dashlength)
1008 {
1009   gtk_menu_set_active(GTK_MENU (as->linestyle_menu), linestyle);
1010   gtk_option_menu_set_history (GTK_OPTION_MENU(as->omenu), linestyle);
1011 /* TODO restore this later */
1012 /*  gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(gtk_menu_get_active(GTK_MENU(as->linestyle_menu))), TRUE);*/
1013   set_linestyle_sensitivity(DIALINESTYLESELECTOR(as));
1014   gtk_spin_button_set_value(GTK_SPIN_BUTTON(as->dashlength), dashlength);
1015 }
1016 
1017 
1018 
1019 /************* DiaColorSelector: ***************/
1020 
1021 static GtkWidget *
dia_color_selector_create_string_item(DiaDynamicMenu * ddm,gchar * string)1022 dia_color_selector_create_string_item(DiaDynamicMenu *ddm, gchar *string)
1023 {
1024   GtkWidget *item = gtk_menu_item_new_with_label(string);
1025   gint r, g, b;
1026   sscanf(string, "#%2x%2x%2x", &r, &g, &b);
1027 
1028   /* See http://web.umr.edu/~rhall/commentary/color_readability.htm for
1029    * explanation of this formula */
1030   if (r*299+g*587+b*114 > 500 * 256) {
1031     gchar *label = g_strdup_printf("<span foreground=\"black\" background=\"%s\">%s</span>", string, string);
1032     gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(item))), label);
1033     g_free(label);
1034   } else {
1035     gchar *label = g_strdup_printf("<span foreground=\"white\" background=\"%s\">%s</span>", string, string);
1036     gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(item))), label);
1037     g_free(label);
1038   }
1039 
1040   return item;
1041 }
1042 
1043 static void
dia_color_selector_more_ok(GtkWidget * ok,gpointer userdata)1044 dia_color_selector_more_ok(GtkWidget *ok, gpointer userdata)
1045 {
1046   DiaDynamicMenu *ddm = g_object_get_data(G_OBJECT(userdata), "ddm");
1047   GtkWidget *colorsel = GTK_WIDGET(userdata);
1048   GdkColor gcol;
1049   gchar *entry;
1050 
1051   gtk_color_selection_get_current_color(
1052 	GTK_COLOR_SELECTION(
1053 	    GTK_COLOR_SELECTION_DIALOG(colorsel)->colorsel),
1054 	&gcol);
1055 
1056   entry = g_strdup_printf("#%02X%02X%02X", gcol.red/256, gcol.green/256, gcol.blue/256);
1057   dia_dynamic_menu_select_entry(ddm, entry);
1058   g_free(entry);
1059 
1060   gtk_widget_destroy(colorsel);
1061 }
1062 
1063 static void
dia_color_selector_more_callback(GtkWidget * widget,gpointer userdata)1064 dia_color_selector_more_callback(GtkWidget *widget, gpointer userdata)
1065 {
1066   GtkColorSelectionDialog *dialog = GTK_COLOR_SELECTION_DIALOG (gtk_color_selection_dialog_new(_("Select color")));
1067   DiaDynamicMenu *ddm = DIA_DYNAMIC_MENU(userdata);
1068   GtkColorSelection *colorsel = GTK_COLOR_SELECTION(dialog->colorsel);
1069   GString *palette = g_string_new ("");
1070 
1071   gchar *old_color = dia_dynamic_menu_get_entry(ddm);
1072   /* Force history to the old place */
1073   dia_dynamic_menu_select_entry(ddm, old_color);
1074 
1075   if (ddm->default_entries != NULL) {
1076     GList *tmplist;
1077     int index = 0;
1078     gboolean advance = TRUE;
1079 
1080     for (tmplist = ddm->default_entries;
1081          tmplist != NULL || advance;
1082          tmplist = g_list_next(tmplist)) {
1083       const gchar* spec;
1084       GdkColor color;
1085 
1086       /* handle both lists */
1087       if (!tmplist && advance) {
1088         advance = FALSE;
1089         tmplist = persistent_list_get_glist(ddm->persistent_name);
1090         if (!tmplist)
1091           break;
1092       }
1093       spec = (gchar *)tmplist->data;
1094 
1095       gdk_color_parse (spec, &color);
1096 #if 0
1097       /* the easy way if the Gtk Team would decide to make it public */
1098       gtk_color_selection_set_palette_color (colorsel, index, &color);
1099 #else
1100       g_string_append (palette, spec);
1101       g_string_append (palette, ":");
1102 #endif
1103       if (0 == strcmp (spec, old_color)) {
1104         gtk_color_selection_set_previous_color (colorsel, &color);
1105         gtk_color_selection_set_current_color (colorsel, &color);
1106       }
1107       index++;
1108     }
1109   }
1110 
1111   g_object_set (gtk_widget_get_settings (GTK_WIDGET (colorsel)), "gtk-color-palette", palette->str, NULL);
1112   gtk_color_selection_set_has_palette (colorsel, TRUE);
1113   g_string_free (palette, TRUE);
1114   g_free(old_color);
1115 
1116   gtk_widget_hide(dialog->help_button);
1117 
1118   gtk_signal_connect (GTK_OBJECT (dialog->ok_button), "clicked",
1119 		      (GtkSignalFunc) dia_color_selector_more_ok,
1120 		      dialog);
1121   gtk_signal_connect_object(GTK_OBJECT (dialog->cancel_button), "clicked",
1122 			    (GtkSignalFunc) gtk_widget_destroy,
1123 			    GTK_OBJECT(dialog));
1124   g_object_set_data(G_OBJECT(dialog), "ddm", ddm);
1125 
1126   gtk_widget_show(GTK_WIDGET(dialog));
1127 }
1128 
1129 GtkWidget *
dia_color_selector_new()1130 dia_color_selector_new ()
1131 {
1132   GtkWidget *otheritem = gtk_menu_item_new_with_label(_("More colors..."));
1133   GtkWidget *ddm = dia_dynamic_menu_new(dia_color_selector_create_string_item,
1134 					NULL,
1135 					GTK_MENU_ITEM(otheritem),
1136 					"color-menu");
1137   dia_dynamic_menu_add_default_entry(DIA_DYNAMIC_MENU(ddm),
1138 				     "#000000");
1139   dia_dynamic_menu_add_default_entry(DIA_DYNAMIC_MENU(ddm),
1140 				     "#FFFFFF");
1141   dia_dynamic_menu_add_default_entry(DIA_DYNAMIC_MENU(ddm),
1142 				     "#FF0000");
1143   dia_dynamic_menu_add_default_entry(DIA_DYNAMIC_MENU(ddm),
1144 				     "#00FF00");
1145   dia_dynamic_menu_add_default_entry(DIA_DYNAMIC_MENU(ddm),
1146 				     "#0000FF");
1147   g_signal_connect(G_OBJECT(otheritem), "activate",
1148 		   G_CALLBACK(dia_color_selector_more_callback), ddm);
1149   gtk_widget_show(otheritem);
1150   return ddm;
1151 }
1152 
1153 
1154 void
dia_color_selector_get_color(GtkWidget * widget,Color * color)1155 dia_color_selector_get_color(GtkWidget *widget, Color *color)
1156 {
1157   gchar *entry = dia_dynamic_menu_get_entry(DIA_DYNAMIC_MENU(widget));
1158   gint r, g, b;
1159 
1160   sscanf(entry, "#%2x%2x%2x", &r, &g, &b);
1161   g_free(entry);
1162   color->red = r / 255.0;
1163   color->green = g / 255.0;
1164   color->blue = b / 255.0;
1165 }
1166 
1167 void
dia_color_selector_set_color(GtkWidget * widget,const Color * color)1168 dia_color_selector_set_color (GtkWidget *widget,
1169 			      const Color *color)
1170 {
1171   gint red, green, blue;
1172   gchar *entry;
1173   red = color->red * 255;
1174   green = color->green * 255;
1175   blue = color->blue * 255;
1176   if (color->red > 1.0 || color->green > 1.0 || color->blue > 1.0) {
1177     printf("Color out of range: r %f, g %f, b %f\n",
1178 	   color->red, color->green, color->blue);
1179     red = MIN(red, 255);
1180     green = MIN(green, 255);
1181     blue = MIN(blue, 255);
1182   }
1183   entry = g_strdup_printf("#%02X%02X%02X", red, green, blue);
1184   dia_dynamic_menu_select_entry(DIA_DYNAMIC_MENU(widget), entry);
1185   g_free (entry);
1186 }
1187 
1188 
1189 /************* DiaArrowSelector: ***************/
1190 
1191 /* FIXME: Should these structs be in widgets.h instead? */
1192 struct _DiaArrowSelector
1193 {
1194   GtkVBox vbox;
1195 
1196   GtkHBox *sizebox;
1197   GtkLabel *sizelabel;
1198   DiaSizeSelector *size;
1199 
1200   GtkOptionMenu *omenu;
1201 };
1202 
1203 struct _DiaArrowSelectorClass
1204 {
1205   GtkVBoxClass parent_class;
1206 };
1207 
1208 enum {
1209     DAS_VALUE_CHANGED,
1210     DAS_LAST_SIGNAL
1211 };
1212 
1213 static guint das_signals[DAS_LAST_SIGNAL] = {0};
1214 
1215 static void
dia_arrow_selector_class_init(DiaArrowSelectorClass * class)1216 dia_arrow_selector_class_init (DiaArrowSelectorClass *class)
1217 {
1218   das_signals[DAS_VALUE_CHANGED]
1219       = g_signal_new("value_changed",
1220 		     G_TYPE_FROM_CLASS(class),
1221 		     G_SIGNAL_RUN_FIRST,
1222 		     0, NULL, NULL,
1223 		     g_cclosure_marshal_VOID__VOID,
1224 		     G_TYPE_NONE, 0);
1225 }
1226 
1227 static void
set_size_sensitivity(DiaArrowSelector * as)1228 set_size_sensitivity(DiaArrowSelector *as)
1229 {
1230   int state;
1231   gchar *entryname = dia_dynamic_menu_get_entry(DIA_DYNAMIC_MENU(as->omenu));
1232 
1233   state = (entryname != NULL) && (0 != g_ascii_strcasecmp(entryname, "None"));
1234   g_free(entryname);
1235 
1236   gtk_widget_set_sensitive(GTK_WIDGET(as->sizelabel), state);
1237   gtk_widget_set_sensitive(GTK_WIDGET(as->size), state);
1238 }
1239 
1240 static void
arrow_type_change_callback(DiaDynamicMenu * ddm,gpointer userdata)1241 arrow_type_change_callback(DiaDynamicMenu *ddm, gpointer userdata)
1242 {
1243   set_size_sensitivity(DIA_ARROW_SELECTOR(userdata));
1244   g_signal_emit(DIA_ARROW_SELECTOR(userdata),
1245 		das_signals[DAS_VALUE_CHANGED], 0);
1246 }
1247 
1248 static void
arrow_size_change_callback(DiaSizeSelector * size,gpointer userdata)1249 arrow_size_change_callback(DiaSizeSelector *size, gpointer userdata)
1250 {
1251   g_signal_emit(DIA_ARROW_SELECTOR(userdata),
1252 		das_signals[DAS_VALUE_CHANGED], 0);
1253 }
1254 
1255 static GtkWidget *
create_arrow_menu_item(DiaDynamicMenu * ddm,gchar * name)1256 create_arrow_menu_item(DiaDynamicMenu *ddm, gchar *name)
1257 {
1258   ArrowType atype = arrow_type_from_name(name);
1259   GtkWidget *item = gtk_menu_item_new();
1260   GtkWidget *preview = dia_arrow_preview_new(atype, FALSE);
1261 
1262   gtk_widget_show(preview);
1263   gtk_container_add(GTK_CONTAINER(item), preview);
1264   gtk_widget_show(item);
1265   return item;
1266 }
1267 
1268 static void
dia_arrow_selector_init(DiaArrowSelector * as,gpointer g_class)1269 dia_arrow_selector_init (DiaArrowSelector *as,
1270 			 gpointer g_class)
1271 {
1272   GtkWidget *omenu;
1273   GtkWidget *box;
1274   GtkWidget *label;
1275   GtkWidget *size;
1276 
1277   GList *arrow_names = get_arrow_names();
1278   omenu = dia_dynamic_menu_new_listbased(create_arrow_menu_item,
1279 					 as,
1280 					 _("More arrows"),
1281 					 arrow_names,
1282 					 "arrow-menu");
1283   dia_dynamic_menu_add_default_entry(DIA_DYNAMIC_MENU(omenu), "None");
1284   dia_dynamic_menu_add_default_entry(DIA_DYNAMIC_MENU(omenu), "Lines");
1285   dia_dynamic_menu_add_default_entry(DIA_DYNAMIC_MENU(omenu), "Filled Concave");
1286   as->omenu = GTK_OPTION_MENU(omenu);
1287   gtk_box_pack_start(GTK_BOX(as), omenu, FALSE, TRUE, 0);
1288   gtk_widget_show(omenu);
1289 
1290   g_signal_connect(DIA_DYNAMIC_MENU(omenu),
1291 		   "value-changed", G_CALLBACK(arrow_type_change_callback),
1292 		   as);
1293 
1294   box = gtk_hbox_new(FALSE,0);
1295   as->sizebox = GTK_HBOX(box);
1296 
1297   label = gtk_label_new(_("Size: "));
1298   as->sizelabel = GTK_LABEL(label);
1299   gtk_box_pack_start_defaults(GTK_BOX(box), label);
1300   gtk_widget_show(label);
1301 
1302   size = dia_size_selector_new(0.0, 0.0);
1303   as->size = DIA_SIZE_SELECTOR(size);
1304   gtk_box_pack_start_defaults(GTK_BOX(box), size);
1305   gtk_widget_show(size);
1306   g_signal_connect(size, "value-changed",
1307 		   G_CALLBACK(arrow_size_change_callback), as);
1308 
1309   set_size_sensitivity(as);
1310   gtk_box_pack_start_defaults(GTK_BOX(as), box);
1311 
1312   gtk_widget_show(box);
1313 }
1314 
1315 GType
dia_arrow_selector_get_type(void)1316 dia_arrow_selector_get_type        (void)
1317 {
1318   static GType dfs_type = 0;
1319 
1320   if (!dfs_type) {
1321     static const GTypeInfo dfs_info = {
1322       /*      sizeof (DiaArrowSelector),*/
1323       sizeof (DiaArrowSelectorClass),
1324       (GBaseInitFunc) NULL,
1325       (GBaseFinalizeFunc) NULL,
1326       (GClassInitFunc) dia_arrow_selector_class_init,
1327       NULL, /* class_finalize */
1328       NULL, /* class_data */
1329       sizeof (DiaArrowSelector),
1330       0,    /* n_preallocs */
1331       (GInstanceInitFunc)dia_arrow_selector_init,  /* init */
1332       /*
1333       (GtkObjectInitFunc) dia_arrow_selector_init,
1334       NULL,
1335       NULL,
1336       (GtkClassInitFunc) NULL,
1337       */
1338     };
1339 
1340     dfs_type = g_type_register_static (GTK_TYPE_VBOX,
1341 				       "DiaArrowSelector",
1342 				       &dfs_info, 0);
1343   }
1344 
1345   return dfs_type;
1346 }
1347 
1348 GtkWidget *
dia_arrow_selector_new()1349 dia_arrow_selector_new ()
1350 {
1351   return GTK_WIDGET ( g_object_new (DIA_TYPE_ARROW_SELECTOR, NULL));
1352 }
1353 
1354 
1355 Arrow
dia_arrow_selector_get_arrow(DiaArrowSelector * as)1356 dia_arrow_selector_get_arrow(DiaArrowSelector *as)
1357 {
1358   Arrow at;
1359   gchar *arrowname = dia_dynamic_menu_get_entry(DIA_DYNAMIC_MENU(as->omenu));
1360 
1361   at.type = arrow_type_from_name(arrowname);
1362   g_free(arrowname);
1363   dia_size_selector_get_size(as->size, &at.width, &at.length);
1364   return at;
1365 }
1366 
1367 void
dia_arrow_selector_set_arrow(DiaArrowSelector * as,Arrow arrow)1368 dia_arrow_selector_set_arrow (DiaArrowSelector *as,
1369 			      Arrow arrow)
1370 {
1371   dia_dynamic_menu_select_entry(DIA_DYNAMIC_MENU(as->omenu),
1372 				arrow_get_name_from_type(arrow.type));
1373   set_size_sensitivity(as);
1374   dia_size_selector_set_size(DIA_SIZE_SELECTOR(as->size), arrow.width, arrow.length);
1375 }
1376 
1377 /************* DiaFileSelector: ***************/
1378 struct _DiaFileSelector
1379 {
1380   GtkHBox hbox;
1381   GtkEntry *entry;
1382   GtkButton *browse;
1383   GtkWidget *dialog;
1384   gchar *sys_filename;
1385 };
1386 
1387 struct _DiaFileSelectorClass
1388 {
1389   GtkHBoxClass parent_class;
1390 };
1391 
1392 enum {
1393     DFILE_VALUE_CHANGED,
1394     DFILE_LAST_SIGNAL
1395 };
1396 
1397 static guint dfile_signals[DFILE_LAST_SIGNAL] = { 0 };
1398 
1399 static void
dia_file_selector_unrealize(GtkWidget * widget)1400 dia_file_selector_unrealize(GtkWidget *widget)
1401 {
1402   DiaFileSelector *fs = DIAFILESELECTOR(widget);
1403 
1404   if (fs->dialog != NULL) {
1405     gtk_widget_destroy(GTK_WIDGET(fs->dialog));
1406     fs->dialog = NULL;
1407   }
1408   if (fs->sys_filename) {
1409     g_free(fs->sys_filename);
1410     fs->sys_filename = NULL;
1411   }
1412 
1413   (* GTK_WIDGET_CLASS (gtk_type_class(gtk_hbox_get_type ()))->unrealize) (widget);
1414 }
1415 
1416 static void
dia_file_selector_class_init(DiaFileSelectorClass * class)1417 dia_file_selector_class_init (DiaFileSelectorClass *class)
1418 {
1419   GtkObjectClass *object_class;
1420   GtkWidgetClass *widget_class;
1421 
1422   object_class = (GtkObjectClass*) class;
1423   widget_class = (GtkWidgetClass*) class;
1424   widget_class->unrealize = dia_file_selector_unrealize;
1425 
1426   dfile_signals[DFILE_VALUE_CHANGED]
1427       = g_signal_new("value-changed",
1428 		     G_TYPE_FROM_CLASS(class),
1429 		     G_SIGNAL_RUN_FIRST,
1430 		     0, NULL, NULL,
1431 		     g_cclosure_marshal_VOID__VOID,
1432 		     G_TYPE_NONE, 0);
1433 }
1434 
1435 static void
dia_file_selector_entry_changed(GtkEditable * editable,gpointer data)1436 dia_file_selector_entry_changed(GtkEditable *editable
1437 				, gpointer data)
1438 {
1439   DiaFileSelector *fs = DIAFILESELECTOR(data);
1440   g_signal_emit(fs, dfile_signals[DFILE_VALUE_CHANGED], 0);
1441 }
1442 
1443 static void
file_open_response_callback(GtkWidget * dialog,gint response,gpointer user_data)1444 file_open_response_callback(GtkWidget *dialog,
1445                             gint       response,
1446                             gpointer   user_data)
1447 {
1448   DiaFileSelector *fs =
1449     DIAFILESELECTOR(gtk_object_get_user_data(GTK_OBJECT(dialog)));
1450 
1451   if (response == GTK_RESPONSE_ACCEPT || response == GTK_RESPONSE_OK) {
1452     gchar *utf8 = g_filename_to_utf8(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)),
1453                             -1, NULL, NULL, NULL);
1454     gtk_entry_set_text(GTK_ENTRY(fs->entry), utf8);
1455     g_free(utf8);
1456   }
1457   gtk_widget_destroy(GTK_WIDGET(dialog));
1458 }
1459 
1460 static void
dia_file_selector_browse_pressed(GtkWidget * widget,gpointer data)1461 dia_file_selector_browse_pressed(GtkWidget *widget, gpointer data)
1462 {
1463   GtkWidget *dialog;
1464   DiaFileSelector *fs = DIAFILESELECTOR(data);
1465   gchar *filename;
1466   GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
1467 
1468   if (!GTK_WIDGET_TOPLEVEL(toplevel) || !GTK_WINDOW(toplevel))
1469     toplevel = NULL;
1470 
1471   if (fs->dialog == NULL) {
1472     GtkFileFilter *filter;
1473 
1474     dialog = fs->dialog =
1475       gtk_file_chooser_dialog_new (_("Select image file"), toplevel ? GTK_WINDOW(toplevel) : NULL,
1476                                    GTK_FILE_CHOOSER_ACTION_OPEN,
1477                                    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1478 				   GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
1479 				   NULL);
1480     gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
1481     g_signal_connect(GTK_OBJECT(dialog), "response",
1482 		     G_CALLBACK(file_open_response_callback), NULL);
1483     gtk_signal_connect (GTK_OBJECT (fs->dialog), "destroy",
1484 			GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1485 			&fs->dialog);
1486 
1487     filter = gtk_file_filter_new ();
1488     gtk_file_filter_set_name (filter, _("Supported Formats"));
1489     gtk_file_filter_add_pixbuf_formats (filter);
1490     gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
1491 
1492     filter = gtk_file_filter_new ();
1493     gtk_file_filter_set_name (filter, _("All Files"));
1494     gtk_file_filter_add_pattern (filter, "*");
1495     gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
1496 
1497     gtk_object_set_user_data(GTK_OBJECT(dialog), fs);
1498   }
1499 
1500   filename = g_filename_from_utf8(gtk_entry_get_text(fs->entry), -1, NULL, NULL, NULL);
1501   /* selecting something in the filechooser officially sucks. See e.g. http://bugzilla.gnome.org/show_bug.cgi?id=307378 */
1502   if (g_path_is_absolute(filename))
1503     gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(fs->dialog), filename);
1504 
1505   g_free(filename);
1506 
1507   gtk_widget_show(GTK_WIDGET(fs->dialog));
1508 }
1509 
1510 static void
dia_file_selector_init(DiaFileSelector * fs)1511 dia_file_selector_init (DiaFileSelector *fs)
1512 {
1513   /* Here's where we set up the real thing */
1514   fs->dialog = NULL;
1515   fs->sys_filename = NULL;
1516 
1517   fs->entry = GTK_ENTRY(gtk_entry_new());
1518   gtk_box_pack_start(GTK_BOX(fs), GTK_WIDGET(fs->entry), FALSE, TRUE, 0);
1519   g_signal_connect(GTK_OBJECT(fs->entry), "changed",
1520 		   G_CALLBACK(dia_file_selector_entry_changed), fs);
1521   gtk_widget_show(GTK_WIDGET(fs->entry));
1522 
1523   fs->browse = GTK_BUTTON(gtk_button_new_with_label(_("Browse")));
1524   gtk_box_pack_start(GTK_BOX(fs), GTK_WIDGET(fs->browse), FALSE, TRUE, 0);
1525   gtk_signal_connect (GTK_OBJECT (fs->browse), "clicked",
1526                       (GtkSignalFunc) dia_file_selector_browse_pressed,
1527                       fs);
1528   gtk_widget_show(GTK_WIDGET(fs->browse));
1529 }
1530 
1531 
1532 GtkType
dia_file_selector_get_type(void)1533 dia_file_selector_get_type (void)
1534 {
1535   static GtkType dfs_type = 0;
1536 
1537   if (!dfs_type) {
1538     static const GtkTypeInfo dfs_info = {
1539       "DiaFileSelector",
1540       sizeof (DiaFileSelector),
1541       sizeof (DiaFileSelectorClass),
1542       (GtkClassInitFunc) dia_file_selector_class_init,
1543       (GtkObjectInitFunc) dia_file_selector_init,
1544       NULL,
1545       NULL,
1546       (GtkClassInitFunc) NULL,
1547     };
1548 
1549     dfs_type = gtk_type_unique (gtk_hbox_get_type (), &dfs_info);
1550 
1551   }
1552 
1553   return dfs_type;
1554 }
1555 
1556 GtkWidget *
dia_file_selector_new()1557 dia_file_selector_new ()
1558 {
1559   return GTK_WIDGET ( gtk_type_new (dia_file_selector_get_type ()));
1560 }
1561 
1562 void
dia_file_selector_set_file(DiaFileSelector * fs,gchar * file)1563 dia_file_selector_set_file(DiaFileSelector *fs, gchar *file)
1564 {
1565   /* filename is in system encoding */
1566   gchar *utf8 = g_filename_to_utf8(file, -1, NULL, NULL, NULL);
1567   gtk_entry_set_text(GTK_ENTRY(fs->entry), utf8);
1568   g_free(utf8);
1569 }
1570 
1571 const gchar *
dia_file_selector_get_file(DiaFileSelector * fs)1572 dia_file_selector_get_file(DiaFileSelector *fs)
1573 {
1574   /* let it behave like gtk_file_selector_get_file */
1575   g_free(fs->sys_filename);
1576   fs->sys_filename = g_filename_from_utf8(gtk_entry_get_text(GTK_ENTRY(fs->entry)),
1577                                           -1, NULL, NULL, NULL);
1578   return fs->sys_filename;
1579 }
1580 
1581 /************* DiaUnitSpinner: ***************/
1582 
1583 /** A Spinner that allows a 'favored' unit to display in.  External access
1584  *  to the value still happens in cm, but display is in the favored unit.
1585  *  Internally, the value is kept in the favored unit to a) allow proper
1586  *  limits, and b) avoid rounding problems while editing.
1587  */
1588 
1589 static void dia_unit_spinner_init(DiaUnitSpinner *self);
1590 
1591 GType
dia_unit_spinner_get_type(void)1592 dia_unit_spinner_get_type(void)
1593 {
1594   static GType us_type = 0;
1595 
1596   if (!us_type) {
1597     static const GTypeInfo us_info = {
1598       sizeof(DiaUnitSpinnerClass),
1599       NULL, /* base_init */
1600       NULL, /* base_finalize */
1601       NULL, /* class_init*/
1602       NULL, /* class_finalize */
1603       NULL, /* class_data */
1604       sizeof(DiaUnitSpinner),
1605       0,    /* n_preallocs */
1606       (GInstanceInitFunc) dia_unit_spinner_init,
1607     };
1608     us_type = g_type_register_static(GTK_TYPE_SPIN_BUTTON,
1609                                      "DiaUnitSpinner",
1610                                      &us_info, 0);
1611   }
1612   return us_type;
1613 }
1614 
1615 
1616 static void
dia_unit_spinner_init(DiaUnitSpinner * self)1617 dia_unit_spinner_init(DiaUnitSpinner *self)
1618 {
1619   self->unit_num = DIA_UNIT_CENTIMETER;
1620 }
1621 
1622 /*
1623   Callback functions for the "input" and "output" signals emitted by
1624   GtkSpinButton. All the normal work is done by the spin button, we
1625   simply modify how the text in the GtkEntry is treated.
1626 */
1627 static gboolean
1628 dia_unit_spinner_input(DiaUnitSpinner *self, gdouble *value);
1629 static gboolean dia_unit_spinner_output(DiaUnitSpinner *self);
1630 
1631 GtkWidget *
dia_unit_spinner_new(GtkAdjustment * adjustment,DiaUnit adj_unit)1632 dia_unit_spinner_new(GtkAdjustment *adjustment, DiaUnit adj_unit)
1633 {
1634   DiaUnitSpinner *self;
1635 
1636   if (adjustment) {
1637     g_return_val_if_fail (GTK_IS_ADJUSTMENT (adjustment), NULL);
1638   }
1639 
1640   self = gtk_type_new(dia_unit_spinner_get_type());
1641   self->unit_num = adj_unit;
1642 
1643   gtk_spin_button_configure(GTK_SPIN_BUTTON(self),
1644                             adjustment, 0.0, units[adj_unit].digits);
1645 
1646   g_signal_connect(GTK_SPIN_BUTTON(self), "output",
1647                    G_CALLBACK(dia_unit_spinner_output),
1648                    NULL);
1649   g_signal_connect(GTK_SPIN_BUTTON(self), "input",
1650                    G_CALLBACK(dia_unit_spinner_input),
1651                    NULL);
1652 
1653   return GTK_WIDGET(self);
1654 }
1655 
1656 static gboolean
dia_unit_spinner_input(DiaUnitSpinner * self,gdouble * value)1657 dia_unit_spinner_input(DiaUnitSpinner *self, gdouble *value)
1658 {
1659   gfloat val, factor = 1.0;
1660   gchar *extra = NULL;
1661 
1662   val = g_strtod(gtk_entry_get_text(GTK_ENTRY(self)), &extra);
1663 
1664   /* get rid of extra white space after number */
1665   while (*extra && g_ascii_isspace(*extra)) extra++;
1666   if (*extra) {
1667     int i;
1668 
1669     for (i = 0; units[i].name != NULL; i++)
1670       if (!g_ascii_strcasecmp(units[i].unit, extra)) {
1671 	factor = units[i].factor / units[self->unit_num].factor;
1672 	break;
1673       }
1674   }
1675   /* convert to prefered units */
1676   val *= factor;
1677 
1678   /* Store value in the location provided by the signal emitter. */
1679   *value = val;
1680 
1681   /* Return true, so that the default input function is not invoked. */
1682   return TRUE;
1683 }
1684 
dia_unit_spinner_output(DiaUnitSpinner * self)1685 static gboolean dia_unit_spinner_output(DiaUnitSpinner *self)
1686 {
1687   char buf[256];
1688 
1689   GtkSpinButton *sbutton = GTK_SPIN_BUTTON(self);
1690   GtkAdjustment *adjustment = gtk_spin_button_get_adjustment(sbutton);
1691 
1692   g_snprintf(buf, sizeof(buf), "%0.*f %s",
1693              gtk_spin_button_get_digits(sbutton),
1694              gtk_adjustment_get_value(adjustment),
1695 	      units[self->unit_num].unit);
1696   gtk_entry_set_text(GTK_ENTRY(self), buf);
1697 
1698   /* Return true, so that the default output function is not invoked. */
1699   return TRUE;
1700 }
1701 
1702 /** Set the value (in cm).
1703  * */
1704 void
dia_unit_spinner_set_value(DiaUnitSpinner * self,gdouble val)1705 dia_unit_spinner_set_value(DiaUnitSpinner *self, gdouble val)
1706 {
1707   GtkSpinButton *sbutton = GTK_SPIN_BUTTON(self);
1708 
1709   gtk_spin_button_set_value(sbutton,
1710                             val /
1711                             (units[self->unit_num].factor /
1712                              units[DIA_UNIT_CENTIMETER].factor));
1713 }
1714 
1715 /** Get the value (in cm) */
1716 gdouble
dia_unit_spinner_get_value(DiaUnitSpinner * self)1717 dia_unit_spinner_get_value(DiaUnitSpinner *self)
1718 {
1719   GtkSpinButton *sbutton = GTK_SPIN_BUTTON(self);
1720 
1721   return gtk_spin_button_get_value(sbutton) *
1722       (units[self->unit_num].factor / units[DIA_UNIT_CENTIMETER].factor);
1723 }
1724 
1725 /* Must manipulate the limit values through this to also consider unit.
1726  * Given value is in centimeter.
1727  */
1728 void
dia_unit_spinner_set_upper(DiaUnitSpinner * self,gdouble val)1729 dia_unit_spinner_set_upper (DiaUnitSpinner *self, gdouble val)
1730 {
1731   val /= (units[self->unit_num].factor / units[DIA_UNIT_CENTIMETER].factor);
1732 
1733   gtk_adjustment_set_upper (
1734     gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(self)), val);
1735 }
1736 GList *
get_units_name_list(void)1737 get_units_name_list(void)
1738 {
1739   int i;
1740   static GList *name_list = NULL;
1741 
1742   if (name_list == NULL) {
1743     for (i = 0; units[i].name != NULL; i++) {
1744       name_list = g_list_append(name_list, units[i].name);
1745     }
1746   }
1747 
1748   return name_list;
1749 }
1750 
1751 /* ************************ Dynamic menus ************************ */
1752 
1753 static void dia_dynamic_menu_class_init(DiaDynamicMenuClass *class);
1754 static void dia_dynamic_menu_init(DiaDynamicMenu *self);
1755 static void dia_dynamic_menu_create_sublist(DiaDynamicMenu *ddm,
1756 					    GList *items,
1757 					    DDMCreateItemFunc create);
1758 static void dia_dynamic_menu_create_menu(DiaDynamicMenu *ddm);
1759 static void dia_dynamic_menu_destroy(GtkObject *object);
1760 
1761 enum {
1762     DDM_VALUE_CHANGED,
1763     DDM_LAST_SIGNAL
1764 };
1765 
1766 static guint ddm_signals[DDM_LAST_SIGNAL] = { 0 };
1767 
1768 GtkType
dia_dynamic_menu_get_type(void)1769 dia_dynamic_menu_get_type(void)
1770 {
1771   static GtkType us_type = 0;
1772 
1773   if (!us_type) {
1774     static const GtkTypeInfo us_info = {
1775       "DiaDynamicMenu",
1776       sizeof(DiaDynamicMenu),
1777       sizeof(DiaDynamicMenuClass),
1778       (GtkClassInitFunc) dia_dynamic_menu_class_init,
1779       (GtkObjectInitFunc) dia_dynamic_menu_init,
1780       NULL,
1781       NULL,
1782       (GtkClassInitFunc) NULL,
1783     };
1784     us_type = gtk_type_unique(gtk_option_menu_get_type(), &us_info);
1785   }
1786   return us_type;
1787 }
1788 
1789 static void
dia_dynamic_menu_class_init(DiaDynamicMenuClass * class)1790 dia_dynamic_menu_class_init(DiaDynamicMenuClass *class)
1791 {
1792   GtkObjectClass *object_class = (GtkObjectClass*)class;
1793 
1794   object_class->destroy = dia_dynamic_menu_destroy;
1795 
1796   ddm_signals[DDM_VALUE_CHANGED]
1797       = g_signal_new("value-changed",
1798 		     G_TYPE_FROM_CLASS(class),
1799 		     G_SIGNAL_RUN_FIRST,
1800 		     0, NULL, NULL,
1801 		     g_cclosure_marshal_VOID__VOID,
1802 		     G_TYPE_NONE, 0);
1803 }
1804 
1805 static void
dia_dynamic_menu_init(DiaDynamicMenu * self)1806 dia_dynamic_menu_init(DiaDynamicMenu *self)
1807 {
1808 }
1809 
1810 void
dia_dynamic_menu_destroy(GtkObject * object)1811 dia_dynamic_menu_destroy(GtkObject *object)
1812 {
1813   DiaDynamicMenu *ddm = DIA_DYNAMIC_MENU(object);
1814   GtkObjectClass *parent_class = GTK_OBJECT_CLASS(g_type_class_peek_parent(GTK_OBJECT_GET_CLASS(object)));
1815 
1816   if (ddm->active)
1817     g_free(ddm->active);
1818   ddm->active = NULL;
1819 
1820   if (parent_class->destroy)
1821     (* parent_class->destroy) (object);
1822 }
1823 
1824 /** Create a new dynamic menu.  The entries are represented with
1825  * gpointers.
1826  * @param create A function that creates menuitems from gpointers.
1827  * @param otheritem A menuitem that can be selected by the user to
1828  * add more entries, for instance making a dialog box or a submenu.
1829  * @param persist A string naming this menu for persistence purposes, or NULL.
1830 
1831  * @return A new menu
1832  */
1833 GtkWidget *
dia_dynamic_menu_new(DDMCreateItemFunc create,gpointer userdata,GtkMenuItem * otheritem,gchar * persist)1834 dia_dynamic_menu_new(DDMCreateItemFunc create,
1835 		     gpointer userdata,
1836 		     GtkMenuItem *otheritem, gchar *persist)
1837 {
1838   DiaDynamicMenu *ddm;
1839 
1840   g_assert(persist != NULL);
1841 
1842   ddm = DIA_DYNAMIC_MENU ( gtk_type_new (dia_dynamic_menu_get_type ()));
1843 
1844   ddm->create_func = create;
1845   ddm->userdata = userdata;
1846   ddm->other_item = otheritem;
1847   ddm->persistent_name = persist;
1848   ddm->cols = 1;
1849 
1850   persistence_register_list(persist);
1851 
1852   dia_dynamic_menu_create_menu(ddm);
1853 
1854   return GTK_WIDGET(ddm);
1855 }
1856 
1857 /** Select the given entry, adding it if necessary */
1858 void
dia_dynamic_menu_select_entry(DiaDynamicMenu * ddm,const gchar * name)1859 dia_dynamic_menu_select_entry(DiaDynamicMenu *ddm, const gchar *name)
1860 {
1861   gint add_result = dia_dynamic_menu_add_entry(ddm, name);
1862   if (add_result == 0) {
1863       GList *tmp;
1864       int i = 0;
1865       for (tmp = ddm->default_entries; tmp != NULL;
1866 	   tmp = g_list_next(tmp), i++) {
1867 	if (!g_ascii_strcasecmp(tmp->data, name))
1868 	  gtk_option_menu_set_history(GTK_OPTION_MENU(ddm), i);
1869       }
1870       /* Not there after all? */
1871   } else {
1872     if (ddm->default_entries != NULL)
1873       gtk_option_menu_set_history(GTK_OPTION_MENU(ddm),
1874 				  g_list_length(ddm->default_entries)+1);
1875     else
1876       gtk_option_menu_set_history(GTK_OPTION_MENU(ddm), 0);
1877   }
1878 
1879   g_free(ddm->active);
1880   ddm->active = g_strdup(name);
1881   g_signal_emit(GTK_OBJECT(ddm), ddm_signals[DDM_VALUE_CHANGED], 0);
1882 }
1883 
1884 static void
dia_dynamic_menu_activate(GtkWidget * item,gpointer userdata)1885 dia_dynamic_menu_activate(GtkWidget *item, gpointer userdata)
1886 {
1887   DiaDynamicMenu *ddm = DIA_DYNAMIC_MENU(userdata);
1888   gchar *name = g_object_get_data(G_OBJECT(item), "ddm_name");
1889   dia_dynamic_menu_select_entry(ddm, name);
1890 }
1891 
1892 static GtkWidget *
dia_dynamic_menu_create_string_item(DiaDynamicMenu * ddm,gchar * string)1893 dia_dynamic_menu_create_string_item(DiaDynamicMenu *ddm, gchar *string)
1894 {
1895   GtkWidget *item = gtk_menu_item_new_with_label(gettext(string));
1896   return item;
1897 }
1898 
1899 /** Utility function for dynamic menus that are entirely based on the
1900  * labels in the menu.
1901  */
1902 GtkWidget *
dia_dynamic_menu_new_stringbased(GtkMenuItem * otheritem,gpointer userdata,gchar * persist)1903 dia_dynamic_menu_new_stringbased(GtkMenuItem *otheritem,
1904 				 gpointer userdata,
1905 				 gchar *persist)
1906 {
1907   GtkWidget *ddm = dia_dynamic_menu_new(dia_dynamic_menu_create_string_item,
1908 					userdata,
1909 					otheritem, persist);
1910   return ddm;
1911 }
1912 
1913 /** Utility function for dynamic menus that are based on a submenu with
1914  * many entries.  This is useful for allowing the user to get a smaller
1915  * subset menu out of a set too large to be easily handled by a menu.
1916  */
1917 GtkWidget *
dia_dynamic_menu_new_listbased(DDMCreateItemFunc create,gpointer userdata,gchar * other_label,GList * items,gchar * persist)1918 dia_dynamic_menu_new_listbased(DDMCreateItemFunc create,
1919 			       gpointer userdata,
1920 			       gchar *other_label, GList *items,
1921 			       gchar *persist)
1922 {
1923   GtkWidget *item = gtk_menu_item_new_with_label(other_label);
1924   GtkWidget *ddm = dia_dynamic_menu_new(create, userdata,
1925 					GTK_MENU_ITEM(item), persist);
1926   dia_dynamic_menu_create_sublist(DIA_DYNAMIC_MENU(ddm), items,  create);
1927 
1928   gtk_widget_show(item);
1929   return ddm;
1930 }
1931 
1932 /** Utility function for dynamic menus that allow selection from a large
1933  * number of strings.
1934  */
1935 GtkWidget *
dia_dynamic_menu_new_stringlistbased(gchar * other_label,GList * items,gpointer userdata,gchar * persist)1936 dia_dynamic_menu_new_stringlistbased(gchar *other_label,
1937 				     GList *items,
1938 				     gpointer userdata,
1939 				     gchar *persist)
1940 {
1941   return dia_dynamic_menu_new_listbased(dia_dynamic_menu_create_string_item,
1942 					userdata,
1943 					other_label, items, persist);
1944 }
1945 
1946 static void
dia_dynamic_menu_create_sublist(DiaDynamicMenu * ddm,GList * items,DDMCreateItemFunc create)1947 dia_dynamic_menu_create_sublist(DiaDynamicMenu *ddm,
1948 				GList *items, DDMCreateItemFunc create)
1949 {
1950   GtkWidget *item = GTK_WIDGET(ddm->other_item);
1951 
1952   GtkWidget *submenu = gtk_menu_new();
1953 
1954   for (; items != NULL; items = g_list_next(items)) {
1955     GtkWidget *submenuitem = (create)(ddm, items->data);
1956     /* Set callback function to cause addition of item */
1957     gtk_menu_shell_append(GTK_MENU_SHELL(submenu), submenuitem);
1958     g_object_set_data(G_OBJECT(submenuitem), "ddm_name", items->data);
1959     g_signal_connect(submenuitem, "activate",
1960 		     G_CALLBACK(dia_dynamic_menu_activate), ddm);
1961     gtk_widget_show(submenuitem);
1962   }
1963 
1964   gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
1965   gtk_widget_show(submenu);
1966 }
1967 
1968 /** Add a new default entry to this menu.
1969  * The default entries are always shown, also after resets, above the
1970  * other entries.  Possible uses are standard fonts or common colors.
1971  * The entry is added at the end of the default entries section.
1972  * Do not add too many default entries.
1973  *
1974  * @param ddm A dynamic menu to add the entry to.
1975  * @param entry An entry for the menu.
1976  */
1977 void
dia_dynamic_menu_add_default_entry(DiaDynamicMenu * ddm,const gchar * entry)1978 dia_dynamic_menu_add_default_entry(DiaDynamicMenu *ddm, const gchar *entry)
1979 {
1980   ddm->default_entries = g_list_append(ddm->default_entries,
1981 				       g_strdup(entry));
1982 
1983   dia_dynamic_menu_create_menu(ddm);
1984 }
1985 
1986 /** Set the number of columns this menu uses (default 1)
1987  * @param cols Desired # of columns (>= 1)
1988  */
1989 void
dia_dynamic_menu_set_columns(DiaDynamicMenu * ddm,gint cols)1990 dia_dynamic_menu_set_columns(DiaDynamicMenu *ddm, gint cols)
1991 {
1992   ddm->cols = cols;
1993 
1994   dia_dynamic_menu_create_menu(ddm);
1995 }
1996 
1997 /** Add a new entry to this menu.  The placement depends on what sorting
1998  * system has been chosen with dia_dynamic_menu_set_sorting_method().
1999  *
2000  * @param ddm A dynamic menu to add the entry to.
2001  * @param entry An entry for the menu.
2002  *
2003  * @returns 0 if the entry was one of the default entries.
2004  * 1 if the entry was already there.
2005  * 2 if the entry got added.
2006  */
2007 gint
dia_dynamic_menu_add_entry(DiaDynamicMenu * ddm,const gchar * entry)2008 dia_dynamic_menu_add_entry(DiaDynamicMenu *ddm, const gchar *entry)
2009 {
2010   GList *tmp;
2011   gboolean existed;
2012 
2013   for (tmp = ddm->default_entries; tmp != NULL; tmp = g_list_next(tmp)) {
2014     if (!g_ascii_strcasecmp(tmp->data, entry))
2015       return 0;
2016   }
2017   existed = persistent_list_add(ddm->persistent_name, entry);
2018 
2019   dia_dynamic_menu_create_menu(ddm);
2020 
2021   return existed?1:2;
2022 }
2023 
2024 /** Returns the currently selected entry.
2025  * @returns The name of the entry that is currently selected.  This
2026  * string should be freed by the caller. */
2027 gchar *
dia_dynamic_menu_get_entry(DiaDynamicMenu * ddm)2028 dia_dynamic_menu_get_entry(DiaDynamicMenu *ddm)
2029 {
2030   return g_strdup(ddm->active);
2031 }
2032 
2033 /** Rebuild the actual menu of a DDM.
2034  * Ignores columns for now.
2035  */
2036 static void
dia_dynamic_menu_create_menu(DiaDynamicMenu * ddm)2037 dia_dynamic_menu_create_menu(DiaDynamicMenu *ddm)
2038 {
2039   GtkWidget *sep;
2040   GList *tmplist;
2041   GtkWidget *menu;
2042   GtkWidget *item;
2043 
2044   g_object_ref(G_OBJECT(ddm->other_item));
2045   menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(ddm));
2046   if (menu != NULL) {
2047     gtk_container_remove(GTK_CONTAINER(menu), GTK_WIDGET(ddm->other_item));
2048     gtk_container_foreach(GTK_CONTAINER(menu),
2049 			  (GtkCallback)gtk_widget_destroy, NULL);
2050     gtk_option_menu_remove_menu(GTK_OPTION_MENU(ddm));
2051   }
2052 
2053   menu = gtk_menu_new();
2054 
2055   if (ddm->default_entries != NULL) {
2056     for (tmplist = ddm->default_entries; tmplist != NULL; tmplist = g_list_next(tmplist)) {
2057       GtkWidget *item =  (ddm->create_func)(ddm, tmplist->data);
2058       g_object_set_data(G_OBJECT(item), "ddm_name", tmplist->data);
2059       g_signal_connect(G_OBJECT(item), "activate",
2060 		       G_CALLBACK(dia_dynamic_menu_activate), ddm);
2061       gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2062       gtk_widget_show(item);
2063     }
2064     sep = gtk_separator_menu_item_new();
2065     gtk_widget_show(sep);
2066     gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
2067   }
2068 
2069   for (tmplist = persistent_list_get_glist(ddm->persistent_name);
2070        tmplist != NULL; tmplist = g_list_next(tmplist)) {
2071     GtkWidget *item = (ddm->create_func)(ddm, tmplist->data);
2072     g_object_set_data(G_OBJECT(item), "ddm_name", tmplist->data);
2073     g_signal_connect(G_OBJECT(item), "activate",
2074 		     G_CALLBACK(dia_dynamic_menu_activate), ddm);
2075     gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2076     gtk_widget_show(item);
2077   }
2078   sep = gtk_separator_menu_item_new();
2079   gtk_widget_show(sep);
2080   gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
2081 
2082   gtk_menu_shell_append(GTK_MENU_SHELL(menu), GTK_WIDGET(ddm->other_item));
2083   g_object_unref(G_OBJECT(ddm->other_item));
2084   /* Eventually reset item here */
2085   gtk_widget_show(menu);
2086 
2087   item = gtk_menu_item_new_with_label(_("Reset menu"));
2088   gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
2089   g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(dia_dynamic_menu_reset), ddm);
2090   gtk_widget_show(item);
2091 
2092   gtk_option_menu_set_menu(GTK_OPTION_MENU(ddm), menu);
2093 
2094   gtk_option_menu_set_history(GTK_OPTION_MENU(ddm), 0);
2095 }
2096 
2097 /** Select the method used for sorting the non-default entries.
2098  * @param ddm A dynamic menu
2099  * @param sort The way the non-default entries in the menu should be sorted.
2100  */
2101 void
dia_dynamic_menu_set_sorting_method(DiaDynamicMenu * ddm,DdmSortType sort)2102 dia_dynamic_menu_set_sorting_method(DiaDynamicMenu *ddm, DdmSortType sort)
2103 {
2104 }
2105 
2106 /** Reset the non-default entries of a menu
2107  */
2108 void
dia_dynamic_menu_reset(GtkWidget * item,gpointer userdata)2109 dia_dynamic_menu_reset(GtkWidget *item, gpointer userdata)
2110 {
2111   DiaDynamicMenu *ddm = DIA_DYNAMIC_MENU(userdata);
2112   PersistentList *plist = persistent_list_get(ddm->persistent_name);
2113   gchar *active = dia_dynamic_menu_get_entry(ddm);
2114   g_list_foreach(plist->glist, (GFunc)g_free, NULL);
2115   g_list_free(plist->glist);
2116   plist->glist = NULL;
2117   dia_dynamic_menu_create_menu(ddm);
2118   if (active)
2119     dia_dynamic_menu_select_entry(ddm, active);
2120   g_free(active);
2121 }
2122 
2123 /** Set the maximum number of non-default entries.
2124  * If more than this number of entries are added, the least recently
2125  * selected ones are removed. */
2126 void
dia_dynamic_menu_set_max_entries(DiaDynamicMenu * ddm,gint max)2127 dia_dynamic_menu_set_max_entries(DiaDynamicMenu *ddm, gint max)
2128 {
2129 }
2130 
2131 
2132 /* ************************ Misc. util functions ************************ */
2133 struct image_pair { GtkWidget *on; GtkWidget *off; };
2134 
2135 static void
dia_toggle_button_swap_images(GtkToggleButton * widget,gpointer data)2136 dia_toggle_button_swap_images(GtkToggleButton *widget,
2137 			      gpointer data)
2138 {
2139   struct image_pair *images = (struct image_pair *)data;
2140   if (gtk_toggle_button_get_active(widget)) {
2141     gtk_container_remove(GTK_CONTAINER(widget),
2142 			 gtk_bin_get_child(GTK_BIN(widget)));
2143     gtk_container_add(GTK_CONTAINER(widget),
2144 		      images->on);
2145 
2146   } else {
2147     gtk_container_remove(GTK_CONTAINER(widget),
2148 			 gtk_bin_get_child(GTK_BIN(widget)));
2149     gtk_container_add(GTK_CONTAINER(widget),
2150 		      images->off);
2151   }
2152 }
2153 
2154 static void
dia_toggle_button_destroy(GtkWidget * widget,gpointer data)2155 dia_toggle_button_destroy(GtkWidget *widget, gpointer data)
2156 {
2157   struct image_pair *images = (struct image_pair *)data;
2158 
2159   if (images->on)
2160     g_object_unref(images->on);
2161   images->on = NULL;
2162   if (images->off)
2163     g_object_unref(images->off);
2164   images->off = NULL;
2165   if (images)
2166     g_free(images);
2167   images = NULL;
2168 }
2169 
2170 /** Create a toggle button given two image widgets for on and off */
2171 static GtkWidget *
dia_toggle_button_new(GtkWidget * on_widget,GtkWidget * off_widget)2172 dia_toggle_button_new(GtkWidget *on_widget, GtkWidget *off_widget)
2173 {
2174   GtkWidget *button = gtk_toggle_button_new();
2175   GtkRcStyle *rcstyle;
2176   GValue *prop;
2177   gint i;
2178   struct image_pair *images;
2179 
2180   images = g_new(struct image_pair, 1);
2181   /* Since these may not be added at any point, make sure to
2182    * sink them. */
2183   images->on = on_widget;
2184   g_object_ref(G_OBJECT(images->on));
2185   gtk_object_sink(GTK_OBJECT(images->on));
2186   gtk_widget_show(images->on);
2187 
2188   images->off = off_widget;
2189   g_object_ref(G_OBJECT(images->off));
2190   gtk_object_sink(GTK_OBJECT(images->off));
2191   gtk_widget_show(images->off);
2192 
2193   /* Make border as small as possible */
2194   gtk_misc_set_padding(GTK_MISC(images->on), 0, 0);
2195   gtk_misc_set_padding(GTK_MISC(images->off), 0, 0);
2196   GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(button), GTK_CAN_FOCUS);
2197   GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(button), GTK_CAN_DEFAULT);
2198 
2199   rcstyle = gtk_rc_style_new ();
2200   rcstyle->xthickness = rcstyle->ythickness = 0;
2201   gtk_widget_modify_style (button, rcstyle);
2202   gtk_rc_style_unref (rcstyle);
2203 
2204   prop = g_new0(GValue, 1);
2205   g_value_init(prop, G_TYPE_INT);
2206   gtk_widget_style_get_property(GTK_WIDGET(button), "focus-padding", prop);
2207   i = g_value_get_int(prop);
2208   g_value_set_int(prop, 0);
2209   g_free(prop);
2210 
2211   gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
2212   /*  gtk_button_set_focus_on_click(GTK_BUTTON(button), FALSE);*/
2213   gtk_container_set_border_width(GTK_CONTAINER(button), 0);
2214 
2215   gtk_container_add(GTK_CONTAINER(button), images->off);
2216 
2217   g_signal_connect(G_OBJECT(button), "toggled",
2218 		   G_CALLBACK(dia_toggle_button_swap_images), images);
2219   g_signal_connect(G_OBJECT(button), "destroy",
2220 		   G_CALLBACK(dia_toggle_button_destroy), images);
2221 
2222   return button;
2223 }
2224 
2225 /** Create a toggle button with two icons (created with gdk-pixbuf-csource,
2226  * for instance).  The icons represent on and off.
2227  */
2228 GtkWidget *
dia_toggle_button_new_with_icons(const guint8 * on_icon,const guint8 * off_icon)2229 dia_toggle_button_new_with_icons(const guint8 *on_icon,
2230 				 const guint8 *off_icon)
2231 {
2232   GdkPixbuf *p1, *p2;
2233 
2234   p1 = gdk_pixbuf_new_from_inline(-1, on_icon, FALSE, NULL);
2235   p2 = gdk_pixbuf_new_from_inline(-1, off_icon, FALSE, NULL);
2236 
2237   return dia_toggle_button_new(gtk_image_new_from_pixbuf(p1),
2238 			       gtk_image_new_from_pixbuf(p2));
2239 }
2240 
2241 
2242