Fix for Bug# 1782032: Blank attibute name when attribute value starts with " "
[geda-gaf/whiteaudio.git] / gschem / src / x_dialog.c
blob1c1b9104926bad4bbd75ee8a24b3eb1ead71b61d
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 gEDA Contributors (see ChangeLog for details)
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 USA
20 /*! \todo STILL NEED to clean up line lengths in aa and tr */
21 #include <config.h>
23 #include <stdio.h>
24 #ifdef HAVE_STDLIB_H
25 #include <stdlib.h>
26 #endif
27 #ifdef HAVE_STRING_H
28 #include <string.h>
29 #endif
31 #include <libgeda/libgeda.h>
33 #include "../include/i_vars.h"
34 #include "../include/globals.h"
35 #include "../include/prototype.h"
36 #include "../include/x_dialog.h"
37 #include "../include/gschem_dialog.h"
39 #ifdef HAVE_LIBDMALLOC
40 #include <dmalloc.h>
41 #endif
43 #define GLADE_HOOKUP_OBJECT(component,widget,name) \
44 g_object_set_data_full (G_OBJECT (component), name, \
45 gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)
47 static GtkWidget* create_menu_linetype (TOPLEVEL *w_current);
48 static gint line_type_dialog_linetype_change (GtkWidget *w, gpointer data);
49 static void line_type_dialog_ok (GtkWidget *w, gpointer data);
51 static GtkWidget* create_menu_filltype (TOPLEVEL *w_current);
52 static gint fill_type_dialog_filltype_change(GtkWidget *w, gpointer data);
53 static void fill_type_dialog_ok(GtkWidget *w, gpointer data);
56 struct line_type_data {
57 GtkWidget *dialog;
58 GtkWidget *width_entry;
59 GtkWidget *line_type;
60 GtkWidget *length_entry;
61 GtkWidget *space_entry;
63 TOPLEVEL *toplevel;
64 GList *objects;
67 struct fill_type_data {
68 GtkWidget *dialog;
69 GtkWidget *fill_type;
70 GtkWidget *width_entry;
71 GtkWidget *angle1_entry;
72 GtkWidget *pitch1_entry;
73 GtkWidget *angle2_entry;
74 GtkWidget *pitch2_entry;
76 TOPLEVEL *toplevel;
77 GList *objects;
80 /*! \todo Finish function documentation!!!
81 * \brief
82 * \par Function Description
85 void destroy_window(GtkWidget *widget, GtkWidget **window)
87 *window = NULL;
90 /* TODO: This string is used by the dialogs: show_text, find_text and hide_text
91 * I think it should be removed. (Werner Hoch)
92 */
93 char generic_textstring[256] = "refdes=R";
95 /***************** Start of Text Input dialog box *********************/
97 /*! \brief worker function for the text entry dialog
98 * \par Function Description
99 * This function applies the text from the text entry dialog.
101 void text_input_dialog_apply(GtkWidget *w, TOPLEVEL *w_current)
103 int len;
104 char *string = NULL;
105 GtkWidget *tientry;
106 GtkTextBuffer *textbuffer;
107 GtkTextIter start, end;
109 tientry = gtk_object_get_data(GTK_OBJECT(w_current->tiwindow),"tientry");
111 textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tientry));
112 gtk_text_buffer_get_bounds (textbuffer, &start, &end);
113 string = gtk_text_iter_get_text (&start, &end);
115 if (string[0] != '\0' ) {
116 len = strlen(string);
117 #if DEBUG
118 printf("text was: _%s_ %d\n", string, len);
119 #endif
120 switch(w_current->text_caps) {
121 case(LOWER):
122 string_tolower(string, string);
123 break;
125 case(UPPER):
126 string_toupper(string, string);
127 break;
129 case(BOTH):
130 default:
131 /* do nothing */
132 break;
135 /* select the text, so you can continue immediatly writing the next text */
136 select_all_text_in_textview(GTK_TEXT_VIEW(tientry));
137 gtk_widget_grab_focus(tientry);
139 o_attrib_set_string(w_current, string);
140 w_current->page_current->CHANGED=1;
141 w_current->event_state = DRAWTEXT;
142 w_current->inside_action = 1;
146 /*! \brief response function for the text entry dialog
147 * \par Function Description
148 * Callback function for the text entry dialog.
150 void text_input_dialog_response(GtkWidget * widget, gint response, TOPLEVEL *w_current)
152 switch(response) {
153 case GTK_RESPONSE_ACCEPT:
154 text_input_dialog_apply(widget, w_current);
155 break;
156 case GTK_RESPONSE_REJECT:
157 case GTK_RESPONSE_DELETE_EVENT:
158 i_set_state(w_current, SELECT);
159 i_update_toolbar(w_current);
160 gtk_widget_destroy(w_current->tiwindow);
161 w_current->tiwindow=NULL;
162 break;
163 default:
164 printf("text_edit_dialog_response(): strange signal %d\n", response);
169 /*! \brief create or present the text entry dialog
170 * \par Function Description
171 * This function creates or raises the modal text entry dialog
173 void text_input_dialog (TOPLEVEL *w_current)
175 GtkWidget *label = NULL;
176 GtkWidget *tientry = NULL;
177 GtkWidget *vbox;
178 GtkWidget *viewport1 = NULL;
179 GtkWidget *scrolled_window = NULL;
180 PangoTabArray *tab_array;
181 int real_tab_width;
183 if (!w_current->tiwindow) { /* dialog not created yet */
184 w_current->tiwindow = gschem_dialog_new_with_buttons(_("Text Entry..."),
185 GTK_WINDOW(w_current->main_window),
186 0, /* NON_MODAL */
187 "text-entry", w_current,
188 GTK_STOCK_CLOSE,
189 GTK_RESPONSE_REJECT,
190 GTK_STOCK_APPLY,
191 GTK_RESPONSE_ACCEPT,
192 NULL);
194 #if GTK_CHECK_VERSION (2,6,0)
195 /* Set the alternative button order (ok, cancel, help) for other systems */
196 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->tiwindow),
197 GTK_RESPONSE_ACCEPT,
198 GTK_RESPONSE_REJECT,
199 -1);
200 #endif
202 gtk_window_position(GTK_WINDOW (w_current->tiwindow),
203 GTK_WIN_POS_NONE);
205 gtk_signal_connect(GTK_OBJECT (w_current->tiwindow), "response",
206 GTK_SIGNAL_FUNC(text_input_dialog_response),
207 w_current);
209 gtk_dialog_set_default_response(GTK_DIALOG(w_current->tiwindow),
210 GTK_RESPONSE_ACCEPT);
212 gtk_container_border_width(GTK_CONTAINER (w_current->tiwindow),
213 DIALOG_BORDER_SPACING);
214 vbox = GTK_DIALOG(w_current->tiwindow)->vbox;
215 gtk_box_set_spacing(GTK_BOX(vbox),DIALOG_V_SPACING);
217 label = gtk_label_new (_("Enter text, click apply,\n"
218 "move cursor into window, click to place text.\n"
219 "Middle button to rotate while placing."));
220 gtk_misc_set_alignment(GTK_MISC(label),0,0);
221 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
223 viewport1 = gtk_viewport_new (NULL, NULL);
224 gtk_widget_show (viewport1);
226 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
227 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
228 GTK_POLICY_AUTOMATIC,
229 GTK_POLICY_AUTOMATIC);
230 gtk_container_add (GTK_CONTAINER (viewport1), scrolled_window);
231 gtk_box_pack_start( GTK_BOX(vbox), viewport1, TRUE, TRUE, 0);
233 tientry = gtk_text_view_new();
234 gtk_text_view_set_editable(GTK_TEXT_VIEW(tientry), TRUE);
235 select_all_text_in_textview(GTK_TEXT_VIEW(tientry));
237 /* Set the tab width, using pango tab array */
238 /*! \bug FIXME: This doesn't work. Why? */
239 tab_array = pango_tab_array_new (1, TRUE);
240 real_tab_width = text_view_calculate_real_tab_width(GTK_TEXT_VIEW(tientry),
241 tab_in_chars);
242 if (real_tab_width >= 0) {
243 pango_tab_array_set_tab (tab_array, 0, PANGO_TAB_LEFT, real_tab_width);
244 /* printf("Real tab width: %i\n", real_tab_width);*/
245 gtk_text_view_set_tabs (GTK_TEXT_VIEW (tientry),
246 tab_array);
248 else {
249 g_warning ("text_input_dialog: Impossible to set tab width.\n");
251 pango_tab_array_free (tab_array);
252 gtk_container_add(GTK_CONTAINER(scrolled_window), tientry);
254 gtk_object_set_data(GTK_OBJECT(w_current->tiwindow),
255 "tientry",tientry);
257 gtk_widget_show_all (w_current->tiwindow);
259 else { /* dialog already created */
260 gtk_window_present (GTK_WINDOW(w_current->tiwindow));
263 /* always select the text in the entry */
264 tientry = gtk_object_get_data(GTK_OBJECT(w_current->tiwindow),"tientry");
265 select_all_text_in_textview(GTK_TEXT_VIEW(tientry));
266 gtk_widget_grab_focus(tientry);
269 /***************** End of Text Input dialog box ***********************/
271 /***************** Start of Text Edit dialog box **********************/
272 /*! \brief CAllback for a text aligment change
273 * \par Function Description
274 * This function stores a change of the text alignment in the
275 * <b>TOPLEVEL</b> struct.
276 * \todo Remove that function. Only the OK-Button should set any
277 * properties in the TOPLEVEL struct.
279 gint change_alignment(GtkWidget *w, TOPLEVEL *w_current)
281 char *alignment;
282 alignment = gtk_object_get_data(GTK_OBJECT(w),"alignment");
283 w_current->text_alignment = atoi(alignment);
285 /*w_current->page_current->CHANGED=1; I don't think this belongs */
286 /* o_undo_savestate(w_current, UNDO_ALL); I don't think this belongs */
288 return 0;
291 /*! \brief Create the alignment menu for the text property dialog
292 * \par Function Description
293 * This function creates a GtkMenu with nine different alignment
294 * entries.
296 static GtkWidget *create_menu_alignment (TOPLEVEL *w_current)
298 GtkWidget *menu;
299 GtkWidget *menuitem;
300 GSList *group;
301 char *buf;
303 menu = gtk_menu_new ();
304 group = NULL;
306 buf = g_strdup_printf( _("Lower Left"));
307 menuitem = gtk_radio_menu_item_new_with_label (group, buf);
308 g_free(buf);
309 group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
310 gtk_menu_append (GTK_MENU (menu), menuitem);
311 gtk_object_set_data (GTK_OBJECT(menuitem), "alignment", "0");
312 gtk_signal_connect(GTK_OBJECT (menuitem), "activate",
313 (GtkSignalFunc) change_alignment,
314 w_current);
315 gtk_widget_show (menuitem);
317 buf = g_strdup_printf( _("Middle Left"));
318 menuitem = gtk_radio_menu_item_new_with_label (group, buf);
319 g_free(buf);
320 group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
321 gtk_menu_append (GTK_MENU (menu), menuitem);
322 gtk_object_set_data (GTK_OBJECT(menuitem), "alignment", "1");
323 gtk_signal_connect(GTK_OBJECT (menuitem), "activate",
324 (GtkSignalFunc) change_alignment,
325 w_current);
326 gtk_widget_show (menuitem);
328 buf = g_strdup_printf( _("Upper Left"));
329 menuitem = gtk_radio_menu_item_new_with_label (group, buf);
330 g_free(buf);
331 group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
332 gtk_menu_append (GTK_MENU (menu), menuitem);
333 gtk_object_set_data (GTK_OBJECT(menuitem), "alignment", "2");
334 gtk_signal_connect(GTK_OBJECT (menuitem), "activate",
335 (GtkSignalFunc) change_alignment,
336 w_current);
337 gtk_widget_show (menuitem);
339 buf = g_strdup_printf( _("Lower Middle"));
340 menuitem = gtk_radio_menu_item_new_with_label (group, buf);
341 g_free(buf);
342 group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
343 gtk_menu_append (GTK_MENU (menu), menuitem);
344 gtk_object_set_data (GTK_OBJECT(menuitem), "alignment", "3");
345 gtk_signal_connect(GTK_OBJECT (menuitem), "activate",
346 (GtkSignalFunc) change_alignment,
347 w_current);
348 gtk_widget_show (menuitem);
350 buf = g_strdup_printf( _("Middle Middle"));
351 menuitem = gtk_radio_menu_item_new_with_label (group, buf);
352 g_free(buf);
353 group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
354 gtk_menu_append (GTK_MENU (menu), menuitem);
355 gtk_object_set_data (GTK_OBJECT(menuitem), "alignment", "4");
356 gtk_signal_connect(GTK_OBJECT (menuitem), "activate",
357 (GtkSignalFunc) change_alignment,
358 w_current);
359 gtk_widget_show (menuitem);
361 buf = g_strdup_printf( _("Upper Middle"));
362 menuitem = gtk_radio_menu_item_new_with_label (group, buf);
363 g_free(buf);
364 group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
365 gtk_menu_append (GTK_MENU (menu), menuitem);
366 gtk_object_set_data (GTK_OBJECT(menuitem), "alignment", "5");
367 gtk_signal_connect(GTK_OBJECT (menuitem), "activate",
368 (GtkSignalFunc) change_alignment,
369 w_current);
370 gtk_widget_show (menuitem);
372 buf = g_strdup_printf( _("Lower Right"));
373 menuitem = gtk_radio_menu_item_new_with_label (group, buf);
374 g_free(buf);
375 group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
376 gtk_menu_append (GTK_MENU (menu), menuitem);
377 gtk_object_set_data (GTK_OBJECT(menuitem), "alignment", "6");
378 gtk_signal_connect(GTK_OBJECT (menuitem), "activate",
379 (GtkSignalFunc) change_alignment,
380 w_current);
381 gtk_widget_show (menuitem);
383 buf = g_strdup_printf( _("Middle Right"));
384 menuitem = gtk_radio_menu_item_new_with_label (group, buf);
385 g_free(buf);
386 group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
387 gtk_menu_append (GTK_MENU (menu), menuitem);
388 gtk_object_set_data (GTK_OBJECT(menuitem), "alignment", "7");
389 gtk_signal_connect(GTK_OBJECT (menuitem), "activate",
390 (GtkSignalFunc) change_alignment,
391 w_current);
392 gtk_widget_show (menuitem);
394 buf = g_strdup_printf( _("Upper Right"));
395 menuitem = gtk_radio_menu_item_new_with_label (group, buf);
396 g_free(buf);
397 group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
398 gtk_menu_append (GTK_MENU (menu), menuitem);
399 gtk_object_set_data (GTK_OBJECT(menuitem), "alignment", "8");
400 gtk_signal_connect(GTK_OBJECT (menuitem), "activate",
401 (GtkSignalFunc) change_alignment,
402 w_current);
403 gtk_widget_show (menuitem);
405 return menu;
408 /* we reuse the color menu so we need to declare it */
409 static GtkWidget *create_color_menu(TOPLEVEL * w_current, int * select_index);
411 /*! \brief Apply the settings from the text property dialog
412 * \par Function Description
413 * This function applies the user settings to the selected text objects
414 * and closes the dialog
416 void text_edit_dialog_ok(GtkWidget *w, TOPLEVEL *w_current)
418 int len=0;
419 int text_size=8;
420 char *text_string = NULL;
421 char *text_size_string = NULL;
422 int new_text_alignment;
423 int num_selected;
424 GtkTextBuffer *textbuffer;
425 GtkTextIter start, end;
426 GtkWidget *widget;
428 num_selected = g_list_length( geda_list_get_glist( w_current->page_current->selection_list ));
430 /* text string entry will only show up if one object is selected */
431 if (num_selected == 1) {
432 widget = g_object_get_data (G_OBJECT (w_current->tewindow), "textentry");
433 textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
434 gtk_text_buffer_get_bounds (textbuffer, &start, &end);
435 text_string = gtk_text_iter_get_text (&start, &end);
436 } /* else the string will be null which is okay */
438 widget = g_object_get_data (G_OBJECT (w_current->tewindow), "sizeentry");
439 text_size_string = (char *) gtk_entry_get_text(GTK_ENTRY(widget));
441 if (text_string) {
442 len = strlen(text_string);
445 if (text_size_string) {
446 text_size = atoi(text_size_string);
449 if (text_size == 0) {
450 text_size = default_text_size;
453 new_text_alignment = w_current->text_alignment;
455 o_text_edit_end(w_current, text_string, len, text_size, new_text_alignment);
458 /*! \brief Response function for the text property dialog
459 * \par Function Description
460 * This function receives the user response of the text property dialog.
461 * The response is either <b>OK</b>, <b>Cancel</b> or delete.
464 void text_edit_dialog_response(GtkWidget * widget, gint response, TOPLEVEL *w_current)
466 switch(response) {
467 case GTK_RESPONSE_ACCEPT:
468 text_edit_dialog_ok(widget, w_current);
469 break;
470 case GTK_RESPONSE_REJECT:
471 case GTK_RESPONSE_DELETE_EVENT:
472 /* void */
473 break;
474 default:
475 printf("text_edit_dialog_response(): strange signal %d\n", response);
477 /* clean up */
478 i_set_state(w_current, SELECT);
479 i_update_toolbar(w_current);
480 gtk_widget_destroy(w_current->tewindow);
481 w_current->tewindow = NULL;
484 /*! \brief Create the edit text properties dialog
485 * \par Function Description
486 * This Function creates the dialog to edit text properties.
487 * \todo Check why there's no color in the calling parameters
488 * \todo If more than one text element is selected, add an unchanged option
490 void text_edit_dialog (TOPLEVEL *w_current, char *string, int text_size,
491 int text_alignment)
493 GtkWidget *label = NULL;
494 GtkWidget *table;
495 GtkWidget *vbox;
496 GtkWidget *optionmenu = NULL;
497 GtkWidget *align_menu = NULL;
498 GtkWidget *viewport1 = NULL;
499 GtkWidget *textentry = NULL;
500 GtkWidget *sizeentry = NULL;
501 GtkWidget *alignment;
502 GtkWidget *scrolled_window = NULL;
503 GtkTextBuffer *textbuffer;
504 char *text_size_string;
505 int num_selected=0;
506 int select_index=0;
508 if (!w_current->tewindow) {
509 w_current->tewindow = gschem_dialog_new_with_buttons(_("Edit Text Properties"),
510 GTK_WINDOW(w_current->main_window),
511 GTK_DIALOG_MODAL,
512 "text-edit", w_current,
513 GTK_STOCK_CANCEL,
514 GTK_RESPONSE_REJECT,
515 GTK_STOCK_OK,
516 GTK_RESPONSE_ACCEPT,
517 NULL);
519 #if GTK_CHECK_VERSION (2,6,0)
520 /* Set the alternative button order (ok, cancel, help) for other systems */
521 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->tewindow),
522 GTK_RESPONSE_ACCEPT,
523 GTK_RESPONSE_REJECT,
524 -1);
525 #endif
527 gtk_dialog_set_default_response(GTK_DIALOG(w_current->tewindow),
528 GTK_RESPONSE_ACCEPT);
530 gtk_signal_connect(GTK_OBJECT(w_current->tewindow), "response",
531 GTK_SIGNAL_FUNC(text_edit_dialog_response), w_current);
533 gtk_window_position(GTK_WINDOW (w_current->tewindow),
534 GTK_WIN_POS_MOUSE);
537 vbox = GTK_DIALOG(w_current->tewindow)->vbox;
538 gtk_container_set_border_width(GTK_CONTAINER(w_current->tewindow),DIALOG_BORDER_SPACING);
539 gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
541 /* add a text box if only one object is selected */
542 num_selected = g_list_length( geda_list_get_glist( w_current->page_current->selection_list ));
544 if (num_selected == 1) {
545 label = gtk_label_new (_("<b>Text Content</b>"));
546 gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
547 gtk_misc_set_alignment(GTK_MISC(label),0,0);
548 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
550 alignment = gtk_alignment_new(0,0,1,1);
551 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0,
552 DIALOG_INDENTATION, 0);
553 gtk_box_pack_start(GTK_BOX(vbox), alignment, TRUE, TRUE, 0);
555 viewport1 = gtk_viewport_new (NULL, NULL);
556 gtk_widget_set_size_request(GTK_WIDGET(viewport1),-1,75);
558 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
559 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
560 GTK_POLICY_AUTOMATIC,
561 GTK_POLICY_AUTOMATIC);
562 gtk_container_add (GTK_CONTAINER (viewport1), scrolled_window);
563 gtk_container_add( GTK_CONTAINER(alignment), viewport1);
565 textentry = gtk_text_view_new();
566 gtk_text_view_set_editable(GTK_TEXT_VIEW(textentry), TRUE);
567 select_all_text_in_textview(GTK_TEXT_VIEW(textentry));
569 /*! \bug FIXME: Set tab's width in the textview widget. */
570 /* See first the code in text_input_dialog and get it working before adding it here. */
572 gtk_container_add(GTK_CONTAINER(scrolled_window), textentry);
573 gtk_widget_grab_focus(textentry);
574 GLADE_HOOKUP_OBJECT(w_current->tewindow, textentry,"textentry");
577 label = gtk_label_new(_("<b>Text Properties</b>"));
578 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
579 gtk_misc_set_alignment(GTK_MISC(label),0,0);
580 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
582 alignment = gtk_alignment_new(0,0,1,1);
583 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0,
584 DIALOG_INDENTATION, 0);
585 gtk_box_pack_start(GTK_BOX(vbox), alignment, FALSE, FALSE, 0);
587 table = gtk_table_new (3, 2, FALSE);
588 gtk_table_set_row_spacings(GTK_TABLE(table), DIALOG_V_SPACING);
589 gtk_table_set_col_spacings(GTK_TABLE(table), DIALOG_H_SPACING);
590 gtk_container_add(GTK_CONTAINER(alignment), table);
592 label = gtk_label_new(_("Color:"));
593 gtk_misc_set_alignment(GTK_MISC(label),0,0);
594 gtk_table_attach(GTK_TABLE(table), label, 0,1,0,1, GTK_FILL,0,0,0);
596 optionmenu = gtk_option_menu_new();
597 gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu),
598 create_color_menu(w_current, &select_index));
599 gtk_option_menu_set_history(GTK_OPTION_MENU(optionmenu), select_index);
600 gtk_table_attach_defaults(GTK_TABLE(table), optionmenu, 1,2,0,1);
602 label = gtk_label_new(_("Size:"));
603 gtk_misc_set_alignment(GTK_MISC(label),0,0);
604 gtk_table_attach(GTK_TABLE(table), label, 0,1,1,2, GTK_FILL,0,0,0);
606 sizeentry = gtk_entry_new_with_max_length (10);
607 gtk_editable_select_region(GTK_EDITABLE (sizeentry), 0, -1);
608 gtk_table_attach_defaults(GTK_TABLE(table), sizeentry, 1,2,1,2);
609 gtk_entry_set_activates_default(GTK_ENTRY(sizeentry), TRUE);
611 label = gtk_label_new(_("Alignment:"));
612 gtk_misc_set_alignment(GTK_MISC(label),0,0);
613 gtk_table_attach(GTK_TABLE(table), label, 0,1,2,3, GTK_FILL,0,0,0);
615 optionmenu = gtk_option_menu_new ();
616 align_menu = create_menu_alignment (w_current);
617 gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu),
618 align_menu);
619 gtk_option_menu_set_history(GTK_OPTION_MENU (optionmenu),
620 text_alignment);
621 w_current->text_alignment = text_alignment;
622 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_menu_get_active(GTK_MENU(align_menu))),
623 TRUE);
624 gtk_table_attach_defaults(GTK_TABLE(table), optionmenu, 1,2,2,3);
626 GLADE_HOOKUP_OBJECT(w_current->tewindow, sizeentry,"sizeentry");
627 gtk_widget_show_all(w_current->tewindow);
630 else { /* dialog already there */
631 gtk_window_present(GTK_WINDOW(w_current->tewindow));
634 if (string != NULL) {
635 if (num_selected == 1) { /* only if one thing is selected */
636 textentry = g_object_get_data (G_OBJECT (w_current->tewindow), "textentry");
637 textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textentry));
638 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(textbuffer), string, -1);
639 select_all_text_in_textview(GTK_TEXT_VIEW(textentry));
643 text_size_string = g_strdup_printf("%d", text_size);
644 sizeentry = g_object_get_data (G_OBJECT (w_current->tewindow), "sizeentry");
645 gtk_entry_set_text(GTK_ENTRY(sizeentry),
646 text_size_string);
647 g_free(text_size_string);
650 /***************** End of Text Edit dialog box ************************/
652 /***************** Start of Line Type/width dialog box ****************/
654 /*! \brief Create a line type menu for the line type dialog
655 * \par Function Description
656 * This function creates a GtkMenu with the different linetypes.
658 static GtkWidget *create_menu_linetype (TOPLEVEL *w_current)
660 GtkWidget *menu;
661 GSList *group;
662 struct line_type {
663 gchar *str;
664 OBJECT_TYPE type;
665 } types[] = { { N_("Solid"), TYPE_SOLID },
666 { N_("Dotted"), TYPE_DOTTED },
667 { N_("Dashed"), TYPE_DASHED },
668 { N_("Center"), TYPE_CENTER },
669 { N_("Phantom"), TYPE_PHANTOM } };
670 gint i;
672 menu = gtk_menu_new ();
673 group = NULL;
675 for (i = 0; i < sizeof (types) / sizeof (struct line_type); i++) {
676 GtkWidget *menuitem;
678 menuitem = gtk_radio_menu_item_new_with_label (group, _(types[i].str));
679 group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
680 gtk_menu_append (GTK_MENU (menu), menuitem);
681 gtk_object_set_data (GTK_OBJECT(menuitem), "linetype",
682 GINT_TO_POINTER (types[i].type));
683 gtk_widget_show (menuitem);
686 return(menu);
689 /*! \brief Callback function for the linetype menu item in the line type dialog
690 * \par Function Description
691 * This Function is called when the user changes the line type selection.
692 * It sets the dash space/length entries either active or inactive.
694 static gint line_type_dialog_linetype_change(GtkWidget *w, gpointer data)
696 struct line_type_data *line_type_data = (struct line_type_data*) data;
697 GtkWidget *menuitem;
698 gboolean activate_length_entry, activate_space_entry;
699 gint type;
701 menuitem = gtk_menu_get_active (
702 GTK_MENU (gtk_option_menu_get_menu (
703 GTK_OPTION_MENU (line_type_data->line_type))));
705 type = GPOINTER_TO_INT(
706 gtk_object_get_data (GTK_OBJECT (menuitem), "linetype"));
707 switch(type) {
708 case(TYPE_SOLID):
709 activate_length_entry = FALSE;
710 activate_space_entry = FALSE;
711 break;
712 case(TYPE_DOTTED):
713 activate_length_entry = FALSE;
714 activate_space_entry = TRUE;
715 break;
716 case(TYPE_DASHED):
717 case(TYPE_CENTER):
718 case(TYPE_PHANTOM):
719 activate_length_entry = TRUE;
720 activate_space_entry = TRUE;
721 break;
722 default:
723 activate_length_entry = TRUE;
724 activate_space_entry = TRUE;
727 gtk_widget_set_sensitive (line_type_data->space_entry,
728 activate_space_entry);
729 gtk_widget_set_sensitive (line_type_data->length_entry,
730 activate_length_entry);
732 return(0);
736 /*! \brief Worker function for the line type and width dialog
737 * \par Function Description
738 * The function takes the properties of the dialog and applies
739 * them to the selected objects.
741 static void line_type_dialog_ok(GtkWidget *w, gpointer data)
743 struct line_type_data *line_type_data = (struct line_type_data*)data;
744 TOPLEVEL *toplevel;
745 GList *objects;
746 const gchar *width_str, *length_str, *space_str;
747 OBJECT_TYPE type;
749 /* retrieve the list of objects and the toplevel */
750 objects = line_type_data->objects;
751 toplevel = line_type_data->toplevel;
753 /* get the new values from the text entries of the dialog */
754 width_str = gtk_entry_get_text (GTK_ENTRY (
755 line_type_data->width_entry));
756 length_str = gtk_entry_get_text (GTK_ENTRY (
757 line_type_data->length_entry));
758 space_str = gtk_entry_get_text (GTK_ENTRY (
759 line_type_data->space_entry));
760 type = GPOINTER_TO_INT(
761 gtk_object_get_data (
762 GTK_OBJECT (
763 gtk_menu_get_active (
764 GTK_MENU (gtk_option_menu_get_menu (
765 GTK_OPTION_MENU (
766 line_type_data->line_type))))), "linetype"));
768 /* are there several objects concerned? */
769 if (g_list_next (objects) == NULL) {
770 /* no, there is only one object */
771 OBJECT *o_current = (OBJECT*) objects->data;
772 gint width, length, space;
774 width = atoi (width_str);
775 length = atoi (length_str);
776 space = atoi (space_str);
778 /* apply the new line options to object */
779 o_erase_single (toplevel, o_current);
780 o_set_line_options (toplevel, o_current,
781 o_current->line_end,
782 type,
783 width,
784 length,
785 space);
786 o_redraw_single (toplevel, o_current);
788 } else {
789 /* more than one object in the list */
790 GList *object;
791 gint width, length, space;
793 /* get the new line options */
794 width = g_strcasecmp (width_str,
795 _("*unchanged*")) ? atoi (width_str) : -1;
796 length = g_strcasecmp (length_str,
797 _("*unchanged*")) ? atoi (length_str) : -1;
798 space = g_strcasecmp (space_str,
799 _("*unchanged*")) ? atoi (space_str) : -1;
801 /* apply changes to each object */
802 object = objects;
803 while (object != NULL) {
804 OBJECT *o_current = (OBJECT*)object->data;
806 o_erase_single (toplevel, o_current);
807 o_set_line_options (toplevel, o_current,
808 o_current->line_end,
809 type == -1 ? o_current->line_type : type,
810 width == -1 ? o_current->line_width : width,
811 length == -1 ? o_current->line_length : length,
812 space == -1 ? o_current->line_space : space);
813 o_redraw_single (toplevel, o_current);
815 object = object->next;
819 toplevel->page_current->CHANGED = 1;
822 /*! \brief response function for the line type and width dialog
823 * \par Function Description
824 * This function takes the user input and applies it to selected
825 * objects.
826 * After that it kills the dialog.
828 void line_type_dialog_response(GtkWidget *widget, gint response,
829 struct line_type_data *line_type_data)
831 switch (response) {
832 case GTK_RESPONSE_REJECT:
833 case GTK_RESPONSE_DELETE_EVENT:
834 /* void */
835 break;
836 case GTK_RESPONSE_ACCEPT:
837 line_type_dialog_ok(widget, line_type_data);
838 break;
839 default:
840 printf("line_type_dialog_response(): strange signal %d\n",response);
843 i_set_state (line_type_data->toplevel, SELECT);
844 i_update_toolbar (line_type_data->toplevel);
845 gtk_widget_destroy (line_type_data->dialog);
847 /* get ride of the list of objects but not the objects */
848 g_list_free (line_type_data->objects);
849 g_free (line_type_data);
852 /*! \brief Creates the line type and width dialog
853 * \par Function Description
854 * This function creates and sets up a dialog for manipulating the
855 * line width and the line type setting of objects.
857 void line_type_dialog (TOPLEVEL *w_current, GList *objects)
859 GtkWidget *dialog;
860 GtkWidget *vbox;
861 GtkWidget *optionmenu = NULL;
862 GtkWidget *length_entry = NULL;
863 GtkWidget *space_entry = NULL;
864 GtkWidget *width_entry = NULL;
865 GtkWidget *table;
866 GtkWidget *label;
867 struct line_type_data *line_type_data;
868 gchar *width_str, *space_str, *length_str;
869 gint type;
871 line_type_data = (struct line_type_data*) g_malloc (
872 sizeof (struct line_type_data));
874 dialog = gschem_dialog_new_with_buttons(_("Edit Line Width & Type"),
875 GTK_WINDOW(w_current->main_window),
876 GTK_DIALOG_MODAL,
877 "line-type", w_current,
878 GTK_STOCK_CANCEL,
879 GTK_RESPONSE_REJECT,
880 GTK_STOCK_OK,
881 GTK_RESPONSE_ACCEPT,
882 NULL);
884 #if GTK_CHECK_VERSION (2,6,0)
885 /* Set the alternative button order (ok, cancel, help) for other systems */
886 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog),
887 GTK_RESPONSE_ACCEPT,
888 GTK_RESPONSE_REJECT,
889 -1);
890 #endif
892 gtk_window_position(GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
894 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
896 gtk_signal_connect(GTK_OBJECT(dialog), "response",
897 GTK_SIGNAL_FUNC(line_type_dialog_response),
898 line_type_data);
900 gtk_container_border_width(GTK_CONTAINER(dialog),
901 DIALOG_BORDER_SPACING);
902 vbox = GTK_DIALOG(dialog)->vbox;
903 gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
905 /* Don't know whether to set the headline or not (Werner) */
906 /* label = gtk_label_new(_("Line Properties:"));
907 gtk_misc_set_alignment(GTK_MISC(label),0,0);
908 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); */
910 table = gtk_table_new (4, 2, FALSE);
911 gtk_table_set_row_spacings(GTK_TABLE(table), DIALOG_V_SPACING);
912 gtk_table_set_col_spacings(GTK_TABLE(table), DIALOG_H_SPACING);
913 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
915 label = gtk_label_new (_("Width:"));
916 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
917 gtk_table_attach(GTK_TABLE(table), label, 0,1,0,1, GTK_FILL,0,0,0);
919 label = gtk_label_new (_("Type:"));
920 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
921 gtk_table_attach(GTK_TABLE(table), label, 0,1,1,2, GTK_FILL,0,0,0);
923 label = gtk_label_new (_("Dash Length:"));
924 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
925 gtk_table_attach(GTK_TABLE(table), label, 0,1,2,3, GTK_FILL,0,0,0);
927 label = gtk_label_new (_("Dash Space:"));
928 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
929 gtk_table_attach(GTK_TABLE(table), label, 0,1,3,4, GTK_FILL,0,0,0);
931 width_entry = gtk_entry_new();
932 gtk_entry_set_activates_default (GTK_ENTRY(width_entry), TRUE);
933 gtk_editable_select_region(GTK_EDITABLE(width_entry), 0, -1);
934 gtk_table_attach_defaults(GTK_TABLE(table), width_entry,
935 1,2,0,1);
937 optionmenu = gtk_option_menu_new ();
938 gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu),
939 create_menu_linetype (w_current));
940 gtk_table_attach_defaults(GTK_TABLE(table), optionmenu,
941 1,2,1,2);
943 gtk_signal_connect(GTK_OBJECT (optionmenu), "changed",
944 (GtkSignalFunc) line_type_dialog_linetype_change,
945 line_type_data);
947 length_entry = gtk_entry_new();
948 gtk_entry_set_activates_default (GTK_ENTRY(length_entry), TRUE);
949 gtk_editable_select_region(GTK_EDITABLE(length_entry), 0, -1);
950 gtk_table_attach_defaults(GTK_TABLE(table), length_entry,
951 1,2,2,3);
953 space_entry = gtk_entry_new();
954 gtk_entry_set_activates_default (GTK_ENTRY(space_entry), TRUE);
955 gtk_editable_select_region(GTK_EDITABLE(space_entry), 0, -1);
956 gtk_table_attach_defaults(GTK_TABLE(table), space_entry,
957 1,2,3,4);
959 /* populate the data structure */
960 line_type_data->dialog = dialog;
961 line_type_data->width_entry = width_entry;
962 line_type_data->line_type = optionmenu;
963 line_type_data->length_entry = length_entry;
964 line_type_data->space_entry = space_entry;
966 line_type_data->toplevel = w_current;
967 line_type_data->objects = objects;
969 /* fill in the fields of the dialog */
970 if (g_list_next (objects) == NULL) {
971 /* only one object in object list */
972 OBJECT *o_current = (OBJECT*) objects->data;
974 width_str = g_strdup_printf ("%d", o_current->line_width);
975 space_str = g_strdup_printf ("%d", o_current->line_space);
976 length_str = g_strdup_printf ("%d", o_current->line_length);
977 type = o_current->line_type;
978 } else {
979 GtkWidget *menuitem;
980 GtkWidget *menu;
982 width_str = g_strdup_printf (_("*unchanged*"));
983 space_str = g_strdup_printf (_("*unchanged*"));
984 length_str = g_strdup_printf (_("*unchanged*"));
985 type = TYPE_PHANTOM + 1;
987 /* add a new menuitem to option menu for line type */
988 menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (optionmenu));
989 menuitem = gtk_radio_menu_item_new_with_label (
990 gtk_radio_menu_item_get_group (
991 GTK_RADIO_MENU_ITEM (gtk_menu_get_active (GTK_MENU (menu)))),
992 _("*unchanged*"));
993 gtk_menu_append (menu, menuitem);
994 gtk_object_set_data (GTK_OBJECT (menuitem),
995 "linetype",
996 GINT_TO_POINTER (-1));
997 gtk_widget_show (menuitem);
1000 gtk_entry_set_text (GTK_ENTRY (width_entry), width_str);
1001 gtk_entry_select_region (GTK_ENTRY (width_entry), 0, strlen (width_str));
1002 gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), type);
1003 gtk_entry_set_text (GTK_ENTRY (space_entry), space_str);
1004 gtk_entry_set_text (GTK_ENTRY (length_entry), length_str);
1006 /* calling it once will set the dash space/length activity */
1007 line_type_dialog_linetype_change(optionmenu, line_type_data);
1009 gtk_widget_grab_focus(width_entry);
1010 gtk_widget_show_all (dialog);
1012 g_free (width_str);
1013 g_free (space_str);
1014 g_free (length_str);
1017 /***************** End of Line Type / Width dialog box ****************/
1019 /***************** Start of Fill Type dialog box **********************/
1021 /*! \brief Create a menu with fill types for the line type dialog
1022 * \par Function Description
1023 * This function creates a GtkMenu with the different fill types.
1025 static GtkWidget *create_menu_filltype (TOPLEVEL *w_current)
1027 GtkWidget *menu;
1028 GSList *group;
1029 struct fill_type {
1030 gchar *str;
1031 OBJECT_FILLING type;
1032 } types[] = { { N_("Hollow"), FILLING_HOLLOW },
1033 { N_("Filled"), FILLING_FILL },
1034 { N_("Mesh"), FILLING_MESH },
1035 { N_("Hatch"), FILLING_HATCH } };
1036 gint i;
1038 menu = gtk_menu_new ();
1039 group = NULL;
1041 for (i = 0; i < sizeof (types) / sizeof (struct fill_type); i++) {
1042 GtkWidget *menuitem;
1044 menuitem = gtk_radio_menu_item_new_with_label (group, _(types[i].str));
1045 group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
1046 gtk_menu_append (GTK_MENU (menu), menuitem);
1047 gtk_object_set_data (GTK_OBJECT(menuitem), "filltype",
1048 GINT_TO_POINTER (types[i].type));
1049 gtk_widget_show (menuitem);
1052 return menu;
1055 /*! \brief Callback function for the filltype menu in the filltype dialog
1056 * \par Function Description
1057 * This function sets the entry activity according to the selected
1058 * filltype of the filltype dialog.
1060 static gint fill_type_dialog_filltype_change(GtkWidget *w, gpointer data)
1062 struct fill_type_data *fill_type_data = (struct fill_type_data*) data;
1063 GtkWidget *menuitem;
1064 gboolean activate_width_entry;
1065 gboolean activate_anglepitch1_entries;
1066 gboolean activate_anglepitch2_entries;
1067 gint type;
1069 menuitem = gtk_menu_get_active (
1070 GTK_MENU (gtk_option_menu_get_menu (
1071 GTK_OPTION_MENU (fill_type_data->fill_type))));
1073 type = GPOINTER_TO_INT(
1074 gtk_object_get_data (GTK_OBJECT (menuitem), "filltype"));
1075 switch(type) {
1076 case(FILLING_HOLLOW):
1077 case(FILLING_FILL):
1078 activate_width_entry = FALSE;
1079 activate_anglepitch1_entries = FALSE;
1080 activate_anglepitch2_entries = FALSE;
1081 break;
1082 case(FILLING_HATCH):
1083 activate_width_entry = TRUE;
1084 activate_anglepitch1_entries = TRUE;
1085 activate_anglepitch2_entries = FALSE;
1086 break;
1087 case(FILLING_MESH):
1088 activate_width_entry = TRUE;
1089 activate_anglepitch1_entries = TRUE;
1090 activate_anglepitch2_entries = TRUE;
1091 break;
1092 default:
1093 activate_width_entry = TRUE;
1094 activate_anglepitch1_entries = TRUE;
1095 activate_anglepitch2_entries = TRUE;
1098 gtk_widget_set_sensitive (fill_type_data->width_entry,
1099 activate_width_entry);
1100 gtk_widget_set_sensitive (fill_type_data->angle1_entry,
1101 activate_anglepitch1_entries);
1102 gtk_widget_set_sensitive (fill_type_data->pitch1_entry,
1103 activate_anglepitch1_entries);
1104 gtk_widget_set_sensitive (fill_type_data->angle2_entry,
1105 activate_anglepitch2_entries);
1106 gtk_widget_set_sensitive (fill_type_data->pitch2_entry,
1107 activate_anglepitch2_entries);
1109 return(0);
1112 /*! \brief Apply the settings of the filltype dialog to the selection
1113 * \par Function Description
1114 * This function applies the settings of the filltype dialog to the
1115 * selected objects
1117 static void fill_type_dialog_ok(GtkWidget *w, gpointer data)
1119 struct fill_type_data *fill_type_data = (struct fill_type_data*)data;
1120 TOPLEVEL *toplevel;
1121 GList *objects;
1122 const gchar *width_str, *angle1_str, *pitch1_str, *angle2_str, *pitch2_str;
1123 OBJECT_FILLING type;
1125 /* retrieve the list of objects and the toplevel */
1126 objects = fill_type_data->objects;
1127 toplevel = fill_type_data->toplevel;
1129 /* get the new values from the text entries of the dialog */
1130 width_str = gtk_entry_get_text (GTK_ENTRY (
1131 fill_type_data->width_entry));
1132 angle1_str = gtk_entry_get_text (GTK_ENTRY (
1133 fill_type_data->angle1_entry));
1134 pitch1_str = gtk_entry_get_text (GTK_ENTRY (
1135 fill_type_data->pitch1_entry));
1136 angle2_str = gtk_entry_get_text (GTK_ENTRY (
1137 fill_type_data->angle2_entry));
1138 pitch2_str = gtk_entry_get_text (GTK_ENTRY (
1139 fill_type_data->pitch2_entry));
1140 type = GPOINTER_TO_INT(
1141 gtk_object_get_data (
1142 GTK_OBJECT (
1143 gtk_menu_get_active (
1144 GTK_MENU (gtk_option_menu_get_menu (
1145 GTK_OPTION_MENU (
1146 fill_type_data->fill_type))))), "filltype"));
1148 /* are there several objects concerned? */
1149 if (g_list_next (objects) == NULL) {
1150 /* no, there is only one object */
1151 OBJECT *o_current = (OBJECT*) objects->data;
1152 gint width, angle1, pitch1, angle2, pitch2;
1154 width = atoi (width_str);
1155 angle1 = atoi (angle1_str);
1156 pitch1 = atoi (pitch1_str);
1157 angle2 = atoi (angle2_str);
1158 pitch2 = atoi (pitch2_str);
1160 /* apply the new line options to object */
1161 o_erase_single (toplevel, o_current);
1162 o_set_fill_options(toplevel, o_current,
1163 type, width,
1164 pitch1, angle1,
1165 pitch2, angle2);
1166 o_redraw_single (toplevel, o_current);
1168 } else {
1169 /* more than one object in the list */
1170 GList *object;
1171 gint width, angle1, pitch1, angle2, pitch2;
1173 /* get the new line options */
1174 width = g_strcasecmp (width_str,
1175 _("*unchanged*")) ? atoi (width_str) : -1;
1176 angle1 = g_strcasecmp (angle1_str,
1177 _("*unchanged*")) ? atoi (angle1_str) : -1;
1178 pitch1 = g_strcasecmp (pitch1_str,
1179 _("*unchanged*")) ? atoi (pitch1_str) : -1;
1180 angle2 = g_strcasecmp (angle2_str,
1181 _("*unchanged*")) ? atoi (angle2_str) : -1;
1182 pitch2 = g_strcasecmp (pitch2_str,
1183 _("*unchanged*")) ? atoi (pitch2_str) : -1;
1185 /* apply changes to each object */
1186 object = objects;
1187 while (object != NULL) {
1188 OBJECT *o_current = (OBJECT*)object->data;
1190 o_erase_single (toplevel, o_current);
1191 o_set_fill_options (toplevel, o_current,
1192 type == -1 ? o_current->fill_type : type,
1193 width == -1 ? o_current->fill_width : width,
1194 pitch1 == -1 ? o_current->fill_pitch1 : pitch1,
1195 angle1 == -1 ? o_current->fill_angle1 : angle1,
1196 pitch2 == -1 ? o_current->fill_pitch2 : pitch2,
1197 angle2 == -1 ? o_current->fill_angle2 : angle2);
1198 o_redraw_single (toplevel, o_current);
1200 object = object->next;
1203 toplevel->page_current->CHANGED = 1;
1206 /*! \brief response function for the filltype dialog
1207 * \par Function Description
1208 * This function handles the user response to the filltype dialog.
1209 * It destroys the dialog after that.
1211 void fill_type_dialog_response(GtkWidget *widget, gint response,
1212 struct fill_type_data *fill_type_data)
1214 switch (response) {
1215 case GTK_RESPONSE_REJECT:
1216 case GTK_RESPONSE_DELETE_EVENT:
1217 /* void */
1218 break;
1219 case GTK_RESPONSE_ACCEPT:
1220 fill_type_dialog_ok(widget, fill_type_data);
1221 break;
1222 default:
1223 printf("line_type_dialog_response(): strange signal %d\n",response);
1226 i_set_state (fill_type_data->toplevel, SELECT);
1227 i_update_toolbar (fill_type_data->toplevel);
1229 gtk_grab_remove (fill_type_data->dialog);
1230 gtk_widget_destroy (fill_type_data->dialog);
1232 /* get ride of the list of objects but not the objects */
1233 g_list_free (fill_type_data->objects);
1234 g_free (fill_type_data);
1237 /*! \brief Creates the fill type dialog
1238 * \par Function Description
1239 * This function creates the fill type dialog. It operates on a list
1240 * of objects.
1242 void fill_type_dialog(TOPLEVEL *w_current, GList *objects)
1244 GtkWidget *dialog;
1245 GtkWidget *vbox;
1246 GtkWidget *optionmenu = NULL;
1247 GtkWidget *width_entry = NULL;
1248 GtkWidget *angle1_entry = NULL;
1249 GtkWidget *pitch1_entry = NULL;
1250 GtkWidget *angle2_entry = NULL;
1251 GtkWidget *pitch2_entry = NULL;
1252 GtkWidget *label;
1253 GtkWidget *table;
1254 struct fill_type_data *fill_type_data;
1255 gchar *width_str, *angle1_str, *pitch1_str, *angle2_str, *pitch2_str;
1256 gint type;
1258 fill_type_data = (struct fill_type_data*) g_malloc (
1259 sizeof (struct fill_type_data));
1261 dialog = gschem_dialog_new_with_buttons(_("Edit Fill Type"),
1262 GTK_WINDOW(w_current->main_window),
1263 GTK_DIALOG_MODAL,
1264 "fill-type", w_current,
1265 GTK_STOCK_CANCEL,
1266 GTK_RESPONSE_REJECT,
1267 GTK_STOCK_OK,
1268 GTK_RESPONSE_ACCEPT,
1269 NULL);
1271 #if GTK_CHECK_VERSION (2,6,0)
1272 /* Set the alternative button order (ok, cancel, help) for other systems */
1273 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog),
1274 GTK_RESPONSE_ACCEPT,
1275 GTK_RESPONSE_REJECT,
1276 -1);
1277 #endif
1279 gtk_window_position(GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
1281 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
1282 GTK_RESPONSE_ACCEPT);
1284 gtk_signal_connect(GTK_OBJECT(dialog), "response",
1285 GTK_SIGNAL_FUNC(fill_type_dialog_response), fill_type_data);
1287 gtk_container_border_width(GTK_CONTAINER(dialog), DIALOG_BORDER_SPACING);
1288 vbox = GTK_DIALOG(dialog)->vbox;
1289 gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
1291 /* Don't know whether to use the headline or not (Werner) */
1292 /* label = gtk_label_new(_("Fill Properties:"));
1293 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1294 gtk_box_pack_start(GTK_BOX(vbox),label, FALSE, FALSE, 0); */
1296 table = gtk_table_new (6, 2, FALSE);
1297 gtk_table_set_row_spacings(GTK_TABLE(table), DIALOG_V_SPACING);
1298 gtk_table_set_col_spacings(GTK_TABLE(table), DIALOG_H_SPACING);
1299 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
1301 label = gtk_label_new (_("Fill Type:"));
1302 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1303 gtk_table_attach(GTK_TABLE(table), label, 0,1,0,1, GTK_FILL,0,0,0);
1305 label = gtk_label_new (_("Line Width:"));
1306 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1307 gtk_table_attach(GTK_TABLE(table), label, 0,1,1,2, GTK_FILL,0,0,0);
1309 label = gtk_label_new (_("Angle 1:"));
1310 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1311 gtk_table_attach(GTK_TABLE(table), label, 0,1,2,3, GTK_FILL,0,0,0);
1313 label = gtk_label_new (_("Pitch 1:"));
1314 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1315 gtk_table_attach(GTK_TABLE(table), label, 0,1,3,4, GTK_FILL,0,0,0);
1317 label = gtk_label_new (_("Angle 2:"));
1318 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1319 gtk_table_attach(GTK_TABLE(table), label, 0,1,4,5, GTK_FILL,0,0,0);
1321 label = gtk_label_new (_("Pitch 2:"));
1322 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1323 gtk_table_attach(GTK_TABLE(table), label, 0,1,5,6, GTK_FILL,0,0,0);
1326 optionmenu = gtk_option_menu_new ();
1327 gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu),
1328 create_menu_filltype (w_current));
1329 gtk_table_attach_defaults(GTK_TABLE(table), optionmenu,
1330 1,2,0,1);
1332 gtk_signal_connect(GTK_OBJECT (optionmenu), "changed",
1333 (GtkSignalFunc) fill_type_dialog_filltype_change,
1334 fill_type_data);
1336 width_entry = gtk_entry_new();
1337 gtk_entry_set_activates_default (GTK_ENTRY(width_entry), TRUE);
1338 gtk_table_attach_defaults(GTK_TABLE(table), width_entry,
1339 1,2,1,2);
1341 angle1_entry = gtk_entry_new ();
1342 gtk_entry_set_activates_default (GTK_ENTRY(angle1_entry), TRUE);
1343 gtk_table_attach_defaults(GTK_TABLE(table), angle1_entry,
1344 1,2,2,3);
1346 pitch1_entry = gtk_entry_new ();
1347 gtk_entry_set_activates_default (GTK_ENTRY(pitch1_entry), TRUE);
1348 gtk_table_attach_defaults(GTK_TABLE(table), pitch1_entry,
1349 1,2,3,4);
1351 angle2_entry = gtk_entry_new ();
1352 gtk_entry_set_activates_default (GTK_ENTRY(angle2_entry), TRUE);
1353 gtk_table_attach_defaults(GTK_TABLE(table), angle2_entry,
1354 1,2,4,5);
1356 pitch2_entry = gtk_entry_new ();
1357 gtk_entry_set_activates_default (GTK_ENTRY(pitch2_entry), TRUE);
1358 gtk_table_attach_defaults(GTK_TABLE(table), pitch2_entry,
1359 1,2,5,6);
1361 /* populate the data structure */
1362 fill_type_data->dialog = dialog;
1363 fill_type_data->fill_type = optionmenu;
1364 fill_type_data->width_entry = width_entry;
1365 fill_type_data->angle1_entry = angle1_entry;
1366 fill_type_data->pitch1_entry = pitch1_entry;
1367 fill_type_data->angle2_entry = angle2_entry;
1368 fill_type_data->pitch2_entry = pitch2_entry;
1370 fill_type_data->toplevel = w_current;
1371 fill_type_data->objects = objects;
1373 /* fill in the fields of the dialog */
1374 if (g_list_next (objects) == NULL) {
1375 /* only one object in object list */
1376 OBJECT *o_current = (OBJECT*) objects->data;
1378 type = o_current->fill_type;
1379 width_str = g_strdup_printf ("%d", o_current->fill_width);
1380 angle1_str = g_strdup_printf ("%d", o_current->fill_angle1);
1381 pitch1_str = g_strdup_printf ("%d", o_current->fill_pitch1);
1382 angle2_str = g_strdup_printf ("%d", o_current->fill_angle2);
1383 pitch2_str = g_strdup_printf ("%d", o_current->fill_pitch2);
1384 } else {
1385 GtkWidget *menuitem;
1386 GtkWidget *menu;
1388 width_str = g_strdup_printf (_("*unchanged*"));
1389 angle1_str = g_strdup_printf (_("*unchanged*"));
1390 pitch1_str = g_strdup_printf (_("*unchanged*"));
1391 angle2_str = g_strdup_printf (_("*unchanged*"));
1392 pitch2_str = g_strdup_printf (_("*unchanged*"));
1393 type = FILLING_HATCH + 1;
1395 /* add a new menuitem to option menu for line type */
1396 menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (optionmenu));
1397 menuitem = gtk_radio_menu_item_new_with_label (
1398 gtk_radio_menu_item_get_group (
1399 GTK_RADIO_MENU_ITEM (gtk_menu_get_active (GTK_MENU (menu)))),
1400 _("*unchanged*"));
1401 gtk_menu_append (menu, menuitem);
1402 gtk_object_set_data (GTK_OBJECT (menuitem),
1403 "filltype",
1404 GINT_TO_POINTER (-1));
1405 gtk_widget_show (menuitem);
1408 gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), type);
1409 gtk_entry_set_text (GTK_ENTRY (width_entry), width_str);
1410 gtk_entry_select_region (GTK_ENTRY (width_entry), 0, strlen (width_str));
1411 gtk_entry_set_text (GTK_ENTRY (angle1_entry), angle1_str);
1412 gtk_entry_select_region (GTK_ENTRY (angle1_entry), 0, strlen (angle1_str));
1413 gtk_entry_set_text (GTK_ENTRY (pitch1_entry), pitch1_str);
1414 gtk_entry_select_region (GTK_ENTRY (pitch1_entry), 0, strlen (pitch1_str));
1415 gtk_entry_set_text (GTK_ENTRY (angle2_entry), angle2_str);
1416 gtk_entry_select_region (GTK_ENTRY (angle2_entry), 0, strlen (angle2_str));
1417 gtk_entry_set_text (GTK_ENTRY (pitch2_entry), pitch2_str);
1418 gtk_entry_select_region (GTK_ENTRY (pitch2_entry), 0, strlen (pitch2_str));
1420 /* Set the widget activity according to the current filltype */
1421 fill_type_dialog_filltype_change(optionmenu, fill_type_data);
1423 gtk_widget_grab_focus(width_entry);
1424 gtk_widget_show_all (dialog);
1426 g_free (width_str);
1427 g_free (angle1_str);
1428 g_free (pitch1_str);
1429 g_free (angle2_str);
1430 g_free (pitch2_str);
1433 /***************** End of Fill Type dialog box ***********************/
1435 /***************** Start of Arc dialog box ***************************/
1437 /*! \brief response function for the arc angle dialog
1438 * \par Function Description
1439 * The response function of th arc angle dialog takes the content of
1440 * the dialog and applies it on the current arc.
1441 * If the dialog is closed or canceled the function destroys the dialog.
1443 void arc_angle_dialog_response(GtkWidget *w, gint response,
1444 TOPLEVEL *w_current)
1446 GtkWidget *spinentry;
1447 gint start_angle, sweep_angle;
1449 switch (response) {
1450 case GTK_RESPONSE_REJECT:
1451 case GTK_RESPONSE_DELETE_EVENT:
1452 /* void */
1453 break;
1454 case GTK_RESPONSE_ACCEPT:
1455 spinentry = g_object_get_data(G_OBJECT(w_current->aawindow),"spin_start");
1456 start_angle = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spinentry));
1457 spinentry = g_object_get_data(G_OBJECT(w_current->aawindow),"spin_sweep");
1458 sweep_angle = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spinentry));
1460 o_arc_end4(w_current, start_angle, sweep_angle);
1461 break;
1462 default:
1463 printf("arc_angle_dialog_response(): strange signal %d\n",response);
1466 gtk_widget_destroy(w_current->aawindow);
1467 w_current->aawindow = NULL;
1468 w_current->event_state = DRAWARC;
1471 /*! \brief Creates the arc angle dialog
1472 * \par Function Description
1473 * This function create the arc angle dialog.
1475 void arc_angle_dialog (TOPLEVEL *w_current)
1477 GtkWidget *label = NULL;
1478 GtkWidget *vbox;
1479 GtkWidget *alignment, *table;
1480 GtkWidget *spin_start, *spin_sweep;
1482 if (!w_current->aawindow) {
1483 w_current->aawindow = gschem_dialog_new_with_buttons(_("Arc Params"),
1484 GTK_WINDOW(w_current->main_window),
1485 GTK_DIALOG_MODAL,
1486 "arc-angle", w_current,
1487 GTK_STOCK_CANCEL,
1488 GTK_RESPONSE_REJECT,
1489 GTK_STOCK_OK,
1490 GTK_RESPONSE_ACCEPT,
1491 NULL);
1493 #if GTK_CHECK_VERSION (2,6,0)
1494 /* Set the alternative button order (ok, cancel, help) for other systems */
1495 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->aawindow),
1496 GTK_RESPONSE_ACCEPT,
1497 GTK_RESPONSE_REJECT,
1498 -1);
1499 #endif
1501 gtk_window_position(GTK_WINDOW(w_current->aawindow),
1502 GTK_WIN_POS_MOUSE);
1504 gtk_signal_connect(GTK_OBJECT(w_current->aawindow), "response",
1505 GTK_SIGNAL_FUNC(arc_angle_dialog_response), w_current);
1507 gtk_dialog_set_default_response(GTK_DIALOG(w_current->aawindow),
1508 GTK_RESPONSE_ACCEPT);
1510 gtk_container_border_width(GTK_CONTAINER(w_current->aawindow), DIALOG_BORDER_SPACING);
1511 vbox = GTK_DIALOG(w_current->aawindow)->vbox;
1512 gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
1515 alignment = gtk_alignment_new(0,0,1,1);
1516 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0,
1517 0 /*DIALOG_INDENTATION */, 0);
1518 gtk_box_pack_start(GTK_BOX(vbox), alignment, FALSE, FALSE, 0);
1520 table = gtk_table_new (2, 2, FALSE);
1521 gtk_table_set_row_spacings(GTK_TABLE(table), DIALOG_V_SPACING);
1522 gtk_table_set_col_spacings(GTK_TABLE(table), DIALOG_H_SPACING);
1523 gtk_container_add(GTK_CONTAINER(alignment), table);
1525 label = gtk_label_new (_("Start Angle:"));
1526 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1527 gtk_table_attach(GTK_TABLE(table), label, 0,1,0,1, GTK_FILL,0,0,0);
1529 spin_start = gtk_spin_button_new_with_range(-360,360,1);
1530 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_start),0);
1531 gtk_widget_grab_focus(spin_start);
1532 gtk_entry_set_activates_default(GTK_ENTRY(spin_start), TRUE);
1533 gtk_table_attach_defaults(GTK_TABLE(table), spin_start, 1,2,0,1);
1535 label = gtk_label_new(_("Degrees of Sweep:"));
1536 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1537 gtk_table_attach(GTK_TABLE(table), label, 0,1,1,2, GTK_FILL,0,0,0);
1539 spin_sweep = gtk_spin_button_new_with_range(-360,360,1);
1540 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_sweep), 90);
1541 gtk_widget_grab_focus(spin_sweep);
1542 gtk_entry_set_activates_default(GTK_ENTRY(spin_sweep), TRUE);
1543 gtk_table_attach_defaults(GTK_TABLE(table), spin_sweep, 1,2,1,2);
1545 GLADE_HOOKUP_OBJECT(w_current->aawindow, spin_start,"spin_start");
1546 GLADE_HOOKUP_OBJECT(w_current->aawindow, spin_sweep,"spin_sweep");
1547 gtk_widget_show_all (w_current->aawindow);
1550 else { /* dialog already created */
1551 gtk_window_present (GTK_WINDOW(w_current->aawindow));
1555 /***************** End of Arc dialog box *****************************/
1557 /***************** Start of Translate dialog box *********************/
1559 /*! \brief response function for the translate dialog
1560 * \par Function Description
1561 * This function takes the user action and applies it.
1562 * \todo improve error detection / use a spin button?
1564 void translate_dialog_response(GtkWidget *widget, gint response,
1565 TOPLEVEL *w_current)
1567 GtkWidget *textentry;
1568 gchar *string;
1570 switch (response) {
1571 case GTK_RESPONSE_REJECT:
1572 case GTK_RESPONSE_DELETE_EVENT:
1573 /* void */
1574 break;
1575 case GTK_RESPONSE_ACCEPT:
1576 textentry = g_object_get_data(G_OBJECT(w_current->trwindow),"textentry");
1577 string = (gchar*) gtk_entry_get_text(GTK_ENTRY(textentry));
1578 if (strlen(string) != 0) {
1579 o_complex_translate_all(w_current, atoi(string));
1581 break;
1582 default:
1583 printf("translate_edit_dialog_response(): strange signal %d\n",response);
1586 i_set_state(w_current, SELECT);
1587 i_update_toolbar(w_current);
1588 gtk_widget_destroy(w_current->trwindow);
1589 w_current->trwindow=NULL;
1593 /*! \brief Create the translate dialog
1594 * \par Function Description
1595 * Create the dialog to translate symbols.
1597 void translate_dialog (TOPLEVEL *w_current)
1599 GtkWidget *label;
1600 GtkWidget *textentry;
1601 GtkWidget *vbox;
1603 if (!w_current->trwindow) {
1604 w_current->trwindow = gschem_dialog_new_with_buttons(_("Translate"),
1605 GTK_WINDOW(w_current->main_window),
1606 GTK_DIALOG_MODAL,
1607 "translate", w_current,
1608 GTK_STOCK_CANCEL,
1609 GTK_RESPONSE_REJECT,
1610 GTK_STOCK_OK,
1611 GTK_RESPONSE_ACCEPT,
1612 NULL);
1614 #if GTK_CHECK_VERSION (2,6,0)
1615 /* Set the alternative button order (ok, cancel, help) for other systems */
1616 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->trwindow),
1617 GTK_RESPONSE_ACCEPT,
1618 GTK_RESPONSE_REJECT,
1619 -1);
1620 #endif
1622 gtk_window_position(GTK_WINDOW (w_current->trwindow),
1623 GTK_WIN_POS_MOUSE);
1625 gtk_signal_connect(GTK_OBJECT (w_current->trwindow), "response",
1626 GTK_SIGNAL_FUNC(translate_dialog_response), w_current);
1628 gtk_dialog_set_default_response(GTK_DIALOG(w_current->trwindow),
1629 GTK_RESPONSE_ACCEPT);
1631 gtk_container_border_width(GTK_CONTAINER(w_current->trwindow),
1632 DIALOG_BORDER_SPACING);
1633 vbox = GTK_DIALOG(w_current->trwindow)->vbox;
1634 gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
1636 label = gtk_label_new(_("Offset to translate?\n(0 for origin)"));
1637 gtk_misc_set_alignment(GTK_MISC (label), 0, 0);
1638 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
1640 textentry = gtk_entry_new_with_max_length (10);
1641 gtk_entry_set_text(GTK_ENTRY(textentry), "0");
1642 gtk_editable_select_region(GTK_EDITABLE(textentry), 0, -1);
1643 gtk_entry_set_activates_default(GTK_ENTRY(textentry), TRUE);
1644 gtk_box_pack_start(GTK_BOX(vbox),textentry, FALSE, FALSE, 0);
1646 GLADE_HOOKUP_OBJECT(w_current->trwindow, textentry, "textentry");
1647 gtk_widget_show_all (w_current->trwindow);
1650 else { /* dialog already created */
1651 gtk_window_present(GTK_WINDOW(w_current->trwindow));
1655 /***************** End of Translate dialog box ***********************/
1657 /***************** Start of Text size dialog box *********************/
1659 /*! \brief response function for the text size dialog
1660 * \par Function Description
1661 * This function takes the user input and applies it to gschem
1663 void text_size_dialog_response(GtkWidget *w, gint response,
1664 TOPLEVEL *w_current)
1666 GtkWidget *spin_size;
1667 gint size;
1669 switch (response) {
1670 case GTK_RESPONSE_ACCEPT:
1671 spin_size = g_object_get_data(G_OBJECT(w_current->tswindow),"spin_size");
1672 size = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin_size));
1674 w_current->text_size = size;
1675 w_current->page_current->CHANGED=1;
1676 o_undo_savestate(w_current, UNDO_ALL);
1677 break;
1678 case GTK_RESPONSE_REJECT:
1679 case GTK_RESPONSE_DELETE_EVENT:
1680 /* void */
1681 break;
1682 default:
1683 printf("text_size_dialog_response(): strange signal %d\n",response);
1686 /* clean up */
1687 i_set_state(w_current, SELECT);
1688 i_update_toolbar(w_current);
1689 gtk_widget_destroy(w_current->tswindow);
1690 w_current->tswindow = NULL;
1693 /*! \brief Create the text size dialog
1694 * \par Function Description
1695 * This function creates the text size dialog.
1697 void text_size_dialog (TOPLEVEL *w_current)
1699 GtkWidget *label = NULL;
1700 GtkWidget *vbox;
1701 GtkWidget *spin_size;
1703 if (!w_current->tswindow) {
1704 w_current->tswindow = gschem_dialog_new_with_buttons(_("Text Size"),
1705 GTK_WINDOW(w_current->main_window),
1706 GTK_DIALOG_MODAL,
1707 "text-size", w_current,
1708 GTK_STOCK_CANCEL,
1709 GTK_RESPONSE_REJECT,
1710 GTK_STOCK_OK,
1711 GTK_RESPONSE_ACCEPT,
1712 NULL);
1714 #if GTK_CHECK_VERSION (2,6,0)
1715 /* Set the alternative button order (ok, cancel, help) for other systems */
1716 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->tswindow),
1717 GTK_RESPONSE_ACCEPT,
1718 GTK_RESPONSE_REJECT,
1719 -1);
1720 #endif
1722 gtk_window_position(GTK_WINDOW(w_current->tswindow),
1723 GTK_WIN_POS_MOUSE);
1725 gtk_signal_connect(GTK_OBJECT(w_current->tswindow), "response",
1726 GTK_SIGNAL_FUNC(text_size_dialog_response),
1727 w_current);
1728 gtk_dialog_set_default_response(GTK_DIALOG(w_current->tswindow),
1729 GTK_RESPONSE_ACCEPT);
1731 gtk_container_border_width(GTK_CONTAINER(w_current->tswindow),
1732 DIALOG_BORDER_SPACING);
1733 vbox = GTK_DIALOG(w_current->tswindow)->vbox;
1734 gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
1736 label = gtk_label_new (_("Enter new text size:"));
1737 gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1738 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
1740 spin_size = gtk_spin_button_new_with_range(2,10000,2);
1741 gtk_editable_select_region( GTK_EDITABLE(spin_size), 0, -1);
1742 gtk_box_pack_start(GTK_BOX(vbox), spin_size, FALSE, FALSE, 0);
1743 gtk_entry_set_activates_default(GTK_ENTRY(spin_size), TRUE);
1744 gtk_widget_grab_focus(spin_size);
1746 GLADE_HOOKUP_OBJECT(w_current->tswindow, spin_size, "spin_size");
1747 gtk_widget_show_all(w_current->tswindow);
1750 else { /* dialog already created */
1751 gtk_window_present(GTK_WINDOW(w_current->tswindow));
1754 /* always set the current text size to the dialog */
1755 spin_size = g_object_get_data(G_OBJECT(w_current->tswindow),"spin_size");
1756 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_size), w_current->text_size);
1757 gtk_editable_select_region(GTK_EDITABLE(spin_size), 0, -1);
1760 /***************** End of Text size dialog box ***********************/
1762 /***************** Start of Snap size dialog box *********************/
1764 /*! \brief response function for the snap size dialog
1765 * \par Function Description
1766 * This is the response function for the snap size dialog.
1767 * It sets the given snap size to gschem.
1769 void snap_size_dialog_response(GtkWidget *w, gint response,
1770 TOPLEVEL *w_current)
1772 GtkWidget *spin_size;
1773 gint size;
1775 switch (response) {
1776 case GTK_RESPONSE_ACCEPT:
1777 spin_size = g_object_get_data(G_OBJECT(w_current->tswindow),"spin_size");
1778 size = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin_size));
1780 w_current->snap_size = size;
1781 o_redraw_all(w_current);
1782 w_current->page_current->CHANGED=1; /* maybe remove those two lines */
1783 o_undo_savestate(w_current, UNDO_ALL);
1784 break;
1785 case GTK_RESPONSE_REJECT:
1786 case GTK_RESPONSE_DELETE_EVENT:
1787 /* void */
1788 break;
1789 default:
1790 printf("snap_size_dialog_response(): strange signal %d\n",response);
1793 /* clean up */
1794 i_set_state(w_current, SELECT);
1795 i_update_toolbar(w_current);
1796 gtk_widget_destroy(w_current->tswindow);
1797 w_current->tswindow = NULL;
1800 /*! \brief Create the snap size dialog
1801 * \par Function Description
1802 * This function creates the snap size dialog.
1804 void snap_size_dialog (TOPLEVEL *w_current)
1806 GtkWidget *label = NULL;
1807 GtkWidget *vbox;
1808 GtkWidget *spin_size;
1810 if (!w_current->tswindow) {
1811 w_current->tswindow = gschem_dialog_new_with_buttons(_("Snap Size"),
1812 GTK_WINDOW(w_current->main_window),
1813 GTK_DIALOG_MODAL,
1814 "snap-size", w_current,
1815 GTK_STOCK_CANCEL,
1816 GTK_RESPONSE_REJECT,
1817 GTK_STOCK_OK,
1818 GTK_RESPONSE_ACCEPT,
1819 NULL);
1821 #if GTK_CHECK_VERSION (2,6,0)
1822 /* Set the alternative button order (ok, cancel, help) for other systems */
1823 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->tswindow),
1824 GTK_RESPONSE_ACCEPT,
1825 GTK_RESPONSE_REJECT,
1826 -1);
1827 #endif
1829 gtk_window_position(GTK_WINDOW(w_current->tswindow),
1830 GTK_WIN_POS_MOUSE);
1832 gtk_signal_connect(GTK_OBJECT(w_current->tswindow), "response",
1833 GTK_SIGNAL_FUNC(snap_size_dialog_response),
1834 w_current);
1835 gtk_dialog_set_default_response(GTK_DIALOG(w_current->tswindow),
1836 GTK_RESPONSE_ACCEPT);
1838 gtk_container_border_width(GTK_CONTAINER(w_current->tswindow),
1839 DIALOG_BORDER_SPACING);
1840 vbox = GTK_DIALOG(w_current->tswindow)->vbox;
1841 gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
1843 label = gtk_label_new (_("Enter new snap grid spacing:"));
1844 gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1845 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
1847 spin_size = gtk_spin_button_new_with_range(0,100000,5);
1848 gtk_editable_select_region( GTK_EDITABLE(spin_size), 0, -1);
1849 gtk_box_pack_start(GTK_BOX(vbox), spin_size, FALSE, FALSE, 0);
1850 gtk_entry_set_activates_default(GTK_ENTRY(spin_size), TRUE);
1851 gtk_widget_grab_focus(spin_size);
1853 GLADE_HOOKUP_OBJECT(w_current->tswindow, spin_size, "spin_size");
1854 gtk_widget_show_all(w_current->tswindow);
1857 else { /* dialog already there */
1858 gtk_window_present(GTK_WINDOW(w_current->tswindow));
1861 /* always set the current gschem value to the dialog entry */
1862 spin_size = g_object_get_data(G_OBJECT(w_current->tswindow),"spin_size");
1863 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_size), w_current->snap_size);
1864 gtk_editable_select_region(GTK_EDITABLE(spin_size), 0, -1);
1867 /***************** End of Snap size dialog box ***********************/
1869 /***************** Start of slot edit dialog box *********************/
1871 /*! \brief response function for the slot edit dialog
1872 * \par Function Description
1873 * The function takes the dialog entry and applies the new slot to the
1874 * symbol.
1876 void slot_edit_dialog_response(GtkWidget *widget, gint response, TOPLEVEL *w_current)
1878 GtkWidget *textentry;
1879 int len;
1880 gchar *string = NULL;
1882 switch (response) {
1883 case GTK_RESPONSE_REJECT:
1884 case GTK_RESPONSE_DELETE_EVENT:
1885 /* void */
1886 break;
1887 case GTK_RESPONSE_ACCEPT:
1888 textentry = g_object_get_data(G_OBJECT(w_current->sewindow),"textentry");
1889 string = (gchar*) gtk_entry_get_text(GTK_ENTRY(textentry));
1890 len = strlen(string);
1891 if (len != 0) {
1892 o_slot_end(w_current, string, len);
1894 break;
1895 default:
1896 printf("slot_edit_dialog_response(): strange signal %d\n",response);
1898 i_set_state(w_current, SELECT);
1899 i_update_toolbar(w_current);
1900 gtk_widget_destroy(w_current->sewindow);
1901 w_current->sewindow = NULL;
1905 /*! \brief Create the slot entry dialog
1906 * \par Function Description
1907 * This function creates the slot edit dialog.
1909 void slot_edit_dialog (TOPLEVEL *w_current, char *string)
1911 GtkWidget *label = NULL;
1912 GtkWidget *textentry;
1913 GtkWidget *vbox;
1915 if (!w_current->sewindow) {
1916 w_current->sewindow = gschem_dialog_new_with_buttons(_("Edit slot number"),
1917 GTK_WINDOW(w_current->main_window),
1918 GTK_DIALOG_MODAL,
1919 "slot-edit", w_current,
1920 GTK_STOCK_CANCEL,
1921 GTK_RESPONSE_REJECT,
1922 GTK_STOCK_OK,
1923 GTK_RESPONSE_ACCEPT,
1924 NULL);
1926 #if GTK_CHECK_VERSION (2,6,0)
1927 /* Set the alternative button order (ok, cancel, help) for other systems */
1928 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->sewindow),
1929 GTK_RESPONSE_ACCEPT,
1930 GTK_RESPONSE_REJECT,
1931 -1);
1932 #endif
1934 gtk_window_position(GTK_WINDOW(w_current->sewindow),
1935 GTK_WIN_POS_MOUSE);
1937 gtk_dialog_set_default_response (GTK_DIALOG (w_current->sewindow),
1938 GTK_RESPONSE_ACCEPT);
1940 gtk_signal_connect(GTK_OBJECT(w_current->sewindow), "response",
1941 GTK_SIGNAL_FUNC(slot_edit_dialog_response),
1942 w_current);
1944 gtk_container_border_width(GTK_CONTAINER(w_current->sewindow),
1945 DIALOG_BORDER_SPACING);
1946 vbox = GTK_DIALOG(w_current->sewindow)->vbox;
1947 gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
1949 label = gtk_label_new (_("Edit slot number:"));
1950 gtk_misc_set_alignment(GTK_MISC(label),0,0);
1951 gtk_box_pack_start(GTK_BOX (vbox), label, FALSE, FALSE, 0);
1953 textentry = gtk_entry_new();
1954 gtk_box_pack_start( GTK_BOX(vbox),
1955 textentry, FALSE, FALSE, 0);
1956 gtk_entry_set_max_length(GTK_ENTRY(textentry), 80);
1957 gtk_entry_set_activates_default (GTK_ENTRY(textentry),TRUE);
1959 GLADE_HOOKUP_OBJECT(w_current->sewindow, textentry, "textentry");
1960 gtk_widget_show_all (w_current->sewindow);
1963 else { /* dialog already created */
1964 gtk_window_present (GTK_WINDOW(w_current->sewindow));
1967 /* always set the current text and select the number of the slot */
1968 if (string != NULL) {
1969 textentry = g_object_get_data(G_OBJECT(w_current->sewindow),"textentry");
1970 gtk_entry_set_text(GTK_ENTRY(textentry), string);
1971 gtk_entry_select_region(GTK_ENTRY(textentry),
1972 strlen("slot="), strlen(string));
1976 /***************** End of Slot Edit dialog box ***********************/
1978 /***************** Start of help/about dialog box ********************/
1980 /*! \brief Response function for the about dialog
1981 * \par Function Description
1982 * This function destoys the about dialg.
1984 void about_dialog_response(GtkWidget *w, gint response,
1985 TOPLEVEL *w_current)
1987 switch (response) {
1988 case GTK_RESPONSE_REJECT:
1989 case GTK_RESPONSE_DELETE_EVENT:
1990 /* void */
1991 break;
1992 default:
1993 printf("about_dialog_response(): strange signal %d\n",response);
1996 gtk_widget_destroy(w_current->abwindow);
1997 w_current->abwindow = NULL;
2000 /*! \brief Create the about dialog and show it
2001 * \par Function Description
2002 * This function creates the about dialog.
2004 void about_dialog (TOPLEVEL *w_current)
2006 GtkWidget *label = NULL;
2007 GtkWidget *vbox;
2008 char *string;
2010 if (!w_current->abwindow) {
2011 w_current->abwindow = gschem_dialog_new_with_buttons(_("About..."),
2012 GTK_WINDOW(w_current->main_window),
2013 GTK_DIALOG_MODAL,
2014 "about", w_current,
2015 GTK_STOCK_CLOSE,
2016 GTK_RESPONSE_REJECT,
2017 NULL);
2019 gtk_window_position (GTK_WINDOW (w_current->abwindow),
2020 GTK_WIN_POS_MOUSE);
2022 gtk_signal_connect (GTK_OBJECT (w_current->abwindow), "response",
2023 GTK_SIGNAL_FUNC(about_dialog_response),
2024 w_current);
2026 gtk_container_border_width (GTK_CONTAINER(w_current->abwindow),
2027 DIALOG_BORDER_SPACING);
2028 vbox = GTK_DIALOG(w_current->abwindow)->vbox;
2029 gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
2031 label = gtk_label_new ( _("<b>gEDA: GPL Electronic Design Automation</b>"));
2032 gtk_label_set_use_markup (GTK_LABEL(label), TRUE);
2033 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
2035 string = g_strdup_printf(_("<b>gschem version %s%s.%s</b>"),
2036 PREPEND_VERSION_STRING, DOTTED_VERSION,
2037 DATE_VERSION);
2038 label = gtk_label_new (string);
2039 gtk_label_set_use_markup (GTK_LABEL(label), TRUE);
2040 g_free(string);
2041 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
2043 label = gtk_label_new ( _("Written by:\n"
2044 "Ales Hvezda\n"
2045 "ahvezda@geda.seul.org\n"
2046 "And many others (See AUTHORS file)"));
2047 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
2048 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
2050 gtk_widget_show_all(w_current->abwindow);
2053 else { /* dialog already created */
2054 gtk_window_present(GTK_WINDOW(w_current->abwindow));
2058 /***************** End of help/about dialog box *********************/
2060 /***************** Start of coord dialog box ************************/
2061 /*! \brief Response function for the coord dialog
2062 * \par Function Description
2063 * This function destroys the coord dialog box and does some cleanup.
2065 void coord_dialog_response(GtkWidget *w, gint response, TOPLEVEL *w_current)
2067 gtk_widget_destroy(w_current->cowindow);
2068 w_current->cowindow = NULL;
2069 w_current->coord_world = NULL;
2070 w_current->coord_screen = NULL;
2073 /*! \brief Update the coordinates in the coord dialog box.
2074 * \par Function Description
2075 * This function takes the screen coordinates and prints the
2076 * screen and the world coordinates in the coord dialog.
2078 void coord_display_update(TOPLEVEL *w_current, int x, int y)
2080 char *string;
2081 int world_x, world_y;
2083 string = g_strdup_printf("(%d, %d)", x, y);
2084 gtk_label_set_text(GTK_LABEL(w_current->coord_screen), string );
2085 g_free(string);
2087 SCREENtoWORLD(w_current, x, y, &world_x, &world_y);
2088 /* TODO: Do we want to snap the coordinate display? */
2089 world_x = snap_grid(w_current, world_x);
2090 world_y = snap_grid(w_current, world_y);
2092 string = g_strdup_printf("(%d, %d)", world_x, world_y);
2093 gtk_label_set_text(GTK_LABEL(w_current->coord_world), string );
2094 g_free(string);
2097 /*! \brief Create the coord dialog
2098 * \par Function Description
2099 * This function creates the coord dialog box.
2101 void coord_dialog (TOPLEVEL *w_current, int x, int y)
2103 GtkWidget *frame;
2104 GtkWidget *vbox;
2106 if (!w_current->cowindow) {
2107 w_current->cowindow = gschem_dialog_new_with_buttons(_("Coords"),
2108 GTK_WINDOW(w_current->main_window),
2109 0, /* Not modal GTK_DIALOG_MODAL */
2110 "coord", w_current,
2111 GTK_STOCK_CLOSE,
2112 GTK_RESPONSE_REJECT,
2113 NULL);
2115 gtk_window_position (GTK_WINDOW (w_current->cowindow),
2116 GTK_WIN_POS_NONE);
2118 gtk_signal_connect (GTK_OBJECT (w_current->cowindow), "response",
2119 GTK_SIGNAL_FUNC(coord_dialog_response),
2120 w_current);
2122 gtk_container_border_width (GTK_CONTAINER(w_current->cowindow),
2123 DIALOG_BORDER_SPACING);
2124 vbox = GTK_DIALOG(w_current->cowindow)->vbox;
2125 gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
2128 frame = gtk_frame_new (_("Screen"));
2129 w_current->coord_screen = gtk_label_new("(########, ########)");
2130 gtk_label_set_justify( GTK_LABEL(w_current->coord_screen), GTK_JUSTIFY_LEFT);
2131 gtk_misc_set_padding(GTK_MISC(w_current->coord_screen),
2132 DIALOG_H_SPACING, DIALOG_V_SPACING);
2133 gtk_container_add(GTK_CONTAINER (frame),
2134 w_current->coord_screen);
2135 gtk_box_pack_start(GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2137 frame = gtk_frame_new (_("World"));
2138 w_current->coord_world = gtk_label_new ("(########, ########)");
2139 gtk_misc_set_padding(GTK_MISC(w_current->coord_world),
2140 DIALOG_H_SPACING, DIALOG_V_SPACING);
2141 gtk_label_set_justify(GTK_LABEL(w_current->coord_world),
2142 GTK_JUSTIFY_LEFT);
2143 gtk_container_add(GTK_CONTAINER (frame),
2144 w_current->coord_world);
2145 gtk_box_pack_start(GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2147 gtk_widget_show_all(w_current->cowindow);
2150 else { /* window already creatad */
2151 gtk_window_present(GTK_WINDOW(w_current->cowindow));
2154 /* always update the coords when the dialog is requested */
2155 coord_display_update(w_current, x, y);
2158 /***************** End of coord dialog box **************************/
2160 /***************** Start of color edit dialog box *******************/
2162 /*! \todo Finish function documentation!!!
2163 * \brief
2164 * \par Function Description
2167 gint color_set(GtkWidget *w, gpointer data)
2169 int index;
2172 * here we really are passing an int sized piece of data, the index rather
2173 * than a pointer and we shouldn't have issues as long as
2174 * sizeof(void *) >= sizeof(int)
2176 index = GPOINTER_TO_INT( data );
2178 /* hate to use this here... but I have to... */
2179 global_window_current->edit_color = index;
2180 return(0);
2183 /*! \todo Finish function documentation!!!
2184 * \brief
2185 * \par Function Description
2187 * \warning
2188 * Caller must g_free returned character string.
2191 char *index2functionstring(int index)
2193 char *string;
2195 switch(index) {
2196 case(BACKGROUND_COLOR):
2197 string = g_strdup ("background");
2198 break;
2199 case(PIN_COLOR):
2200 string = g_strdup ("pin");
2201 break;
2202 case(NET_ENDPOINT_COLOR):
2203 string = g_strdup ("net endpoint");
2204 break;
2205 case(GRAPHIC_COLOR):
2206 string = g_strdup ("graphic");
2207 break;
2208 case(NET_COLOR):
2209 string = g_strdup ("net");
2210 break;
2211 case(ATTRIBUTE_COLOR):
2212 string = g_strdup ("attribute");
2213 break;
2214 case(LOGIC_BUBBLE_COLOR):
2215 string = g_strdup ("logic bubble");
2216 break;
2217 case(GRID_COLOR):
2218 string = g_strdup ("grid point");
2219 break;
2220 case(DETACHED_ATTRIBUTE_COLOR):
2221 string = g_strdup ("detached attribute");
2222 break;
2223 case(TEXT_COLOR):
2224 string = g_strdup ("text");
2225 break;
2226 case(BUS_COLOR):
2227 string = g_strdup ("bus");
2228 break;
2229 case(SELECT_COLOR):
2230 string = g_strdup ("select");
2231 break;
2232 case(BOUNDINGBOX_COLOR):
2233 string = g_strdup ("bounding box");
2234 break;
2235 case(ZOOM_BOX_COLOR):
2236 string = g_strdup ("zoom box");
2237 break;
2238 case(STROKE_COLOR):
2239 string = g_strdup ("stroke");
2240 break;
2241 case(LOCK_COLOR):
2242 string = g_strdup ("lock");
2243 break;
2244 case(OUTPUT_BACKGROUND_COLOR):
2245 string = g_strdup ("output background");
2246 break;
2247 default:
2248 string = g_strdup ("unknown");
2249 break;
2251 return(string);
2254 /*! \brief Create a OptionMenu with the gschem colors.
2255 * \par Function Description
2256 * This Function creates a GtkOptionMenu with the color list.
2257 * It selects the color of the first selected object.
2259 static GtkWidget *create_color_menu (TOPLEVEL * w_current, int * select_index)
2261 GtkWidget *menu;
2262 GtkWidget *menuitem;
2263 GSList *group;
2264 int index=0;
2265 char *buf;
2266 char *menu_string;
2267 char *temp=NULL;
2269 /* first lets see if we have a selected object, if so select its color */
2270 int select_col = -1;
2271 int item_index = 0;
2272 GList *s_current = NULL;
2273 OBJECT *object = NULL;
2275 menu = gtk_menu_new ();
2276 group = NULL;
2278 s_current = geda_list_get_glist( w_current->page_current->selection_list );
2280 if (s_current != NULL) {
2282 object = (OBJECT *) s_current->data;
2283 if (object == NULL) {
2284 fprintf(stderr, "no object selected - WHEE!\n");
2285 }else{
2286 select_col = object->saved_color;
2287 /* fprintf(stderr, "setting object color %d\n", select_col); */
2289 }else /*fprintf(stderr, "no object selected\n")*/;
2291 for (index=0; index < MAX_COLORS;index++) {
2293 if ((buf=x_color_get_name(index)) != NULL) {
2294 temp = index2functionstring(index);
2295 menu_string = g_strdup_printf("%d | %s | %s", index,
2296 temp,
2297 buf);
2298 g_free(temp);
2299 temp = NULL;
2300 g_free(buf);
2301 buf = NULL;
2302 menuitem = gtk_radio_menu_item_new_with_label (group,
2303 menu_string);
2304 g_free(menu_string);
2305 menu_string = NULL;
2307 group = gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(
2308 menuitem));
2310 gtk_menu_append (GTK_MENU (menu), menuitem);
2312 gtk_signal_connect (GTK_OBJECT (menuitem),
2313 "activate",
2314 (GtkSignalFunc) color_set,
2315 GINT_TO_POINTER( index ));
2317 /* I have no idea if doing the above cast is valid,
2318 * since index isn't a pointer, it's just being
2319 * treated as one, it's then cast to an int in
2320 * color_set. This should be ok as long as
2321 * sizeof(void *) >= sizeof(int)
2324 if (select_col == -1){
2325 /* set the default to the current color */
2326 if (index == global_window_current->edit_color) {
2327 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE);
2328 /*fprintf(stderr, "checking item %d\n", index); */
2329 *select_index = item_index;
2331 }else{
2332 if (index == select_col){
2333 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE);
2334 /* fprintf(stderr, "checking selected item %d\n", index); */
2335 *select_index = item_index;
2338 gtk_widget_show(menuitem);
2339 item_index++;
2342 return menu;
2345 /*! \brief Apply a color change to selected objects
2346 * \par Function Description
2347 * This function applies a color change to the currently selected objects.
2349 void color_edit_dialog_apply(GtkWidget *w, TOPLEVEL *w_current)
2351 GList *s_current = NULL;
2352 OBJECT *object = NULL;
2354 s_current = geda_list_get_glist( w_current->page_current->selection_list );
2356 while(s_current != NULL) {
2358 object = (OBJECT *) s_current->data;
2359 if (object == NULL) {
2360 fprintf(stderr, _("ERROR: NULL object in color_edit_dialog_apply!\n"));
2361 exit(-1);
2364 switch(object->type) {
2365 case(OBJ_LINE):
2366 case(OBJ_BOX):
2367 case(OBJ_CIRCLE):
2368 case(OBJ_NET):
2369 case(OBJ_BUS):
2370 case(OBJ_PIN):
2371 case(OBJ_ARC):
2372 object->saved_color = w_current->edit_color;
2373 w_current->page_current->CHANGED = 1;
2374 break;
2376 case(OBJ_TEXT):
2377 object->saved_color = w_current->edit_color;
2378 o_complex_set_saved_color_only(
2379 object->text->prim_objs,
2380 w_current->edit_color);
2381 w_current->page_current->CHANGED = 1;
2382 break;
2385 s_current = s_current->next;
2387 o_undo_savestate(w_current, UNDO_ALL);
2390 /*! \brief response function for the color edit dialog
2391 * \par Function Description
2392 * This function takes the user response from the color edit dialog
2394 void color_edit_dialog_response(GtkWidget *widget, gint response, TOPLEVEL *w_current)
2396 switch (response) {
2397 case GTK_RESPONSE_REJECT:
2398 case GTK_RESPONSE_DELETE_EVENT:
2399 gtk_widget_destroy(w_current->clwindow);
2400 w_current->clwindow = NULL;
2401 break;
2402 case GTK_RESPONSE_ACCEPT:
2403 color_edit_dialog_apply(widget, w_current);
2404 break;
2405 default:
2406 printf("ERROR: color_edit_dialog_response(): strange signal %d\n",response);
2411 /*! \brief Create the color edit dialog
2412 * \par Function Description
2413 * This function creates the color edit dialog
2415 void color_edit_dialog (TOPLEVEL *w_current)
2417 GtkWidget *optionmenu;
2418 GtkWidget *label;
2419 GtkWidget *vbox;
2420 int select_index = 0;
2422 if (!w_current->clwindow) {
2423 w_current->clwindow = gschem_dialog_new_with_buttons(_("Color Edit"),
2424 GTK_WINDOW(w_current->main_window),
2425 0, /* nonmodal dialog */
2426 "color-edit", w_current,
2427 GTK_STOCK_CLOSE,
2428 GTK_RESPONSE_REJECT,
2429 GTK_STOCK_APPLY,
2430 GTK_RESPONSE_ACCEPT,
2431 NULL);
2433 #if GTK_CHECK_VERSION (2,6,0)
2434 /* Set the alternative button order (ok, cancel, help) for other systems */
2435 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->clwindow),
2436 GTK_RESPONSE_ACCEPT,
2437 GTK_RESPONSE_REJECT,
2438 -1);
2439 #endif
2441 gtk_window_position (GTK_WINDOW (w_current->clwindow),
2442 GTK_WIN_POS_MOUSE);
2444 gtk_dialog_set_default_response (GTK_DIALOG (w_current->clwindow),
2445 GTK_RESPONSE_ACCEPT);
2447 gtk_signal_connect(GTK_OBJECT(w_current->clwindow), "response",
2448 GTK_SIGNAL_FUNC(color_edit_dialog_response),
2449 w_current);
2451 gtk_container_border_width(GTK_CONTAINER(w_current->clwindow),
2452 DIALOG_BORDER_SPACING);
2453 vbox = GTK_DIALOG(w_current->clwindow)->vbox;
2454 gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
2456 label = gtk_label_new(_("Object color:"));
2457 gtk_misc_set_alignment(GTK_MISC(label),0,0);
2458 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
2460 optionmenu = gtk_option_menu_new ();
2461 gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu),
2462 create_color_menu (w_current, &select_index));
2463 gtk_option_menu_set_history(GTK_OPTION_MENU (optionmenu), select_index);
2464 gtk_box_pack_start(GTK_BOX(vbox),
2465 optionmenu, FALSE, FALSE, 0);
2466 gtk_widget_show_all(w_current->clwindow);
2469 else { /* dialog already created */
2470 gtk_window_present(GTK_WINDOW(w_current->clwindow));
2474 /***************** End of color edit dialog box *********************/
2476 /***************** Start of help/keymapping dialog box **************/
2478 /*! \brief Response function for the hotkey dialog
2479 * \par Function Description
2480 * This function destroys the hotkey dialog and does some cleanup.
2482 void x_dialog_hotkeys_response(GtkWidget *w, gint response,
2483 TOPLEVEL *w_current)
2485 switch(response) {
2486 case GTK_RESPONSE_REJECT:
2487 case GTK_RESPONSE_DELETE_EVENT:
2488 /* void */
2489 break;
2490 default:
2491 printf("x_dialog_hotkeys_response(): strange signal %d\n", response);
2493 /* clean up */
2494 gtk_widget_destroy(w_current->hkwindow);
2495 w_current->hkwindow = NULL;
2498 /*! \brief Creates the hotkeys dialog
2499 * \par Function Description
2500 * This function creates the hotkey dialog and puts the list of hotkeys
2501 * into it.
2503 void x_dialog_hotkeys (TOPLEVEL *w_current)
2505 GtkWidget *vbox, *scrolled_win;
2506 GtkListStore *store;
2507 GtkWidget *treeview;
2508 GtkCellRenderer *renderer;
2509 GtkTreeViewColumn *column;
2510 GArray *keymap;
2511 gint i;
2512 struct keyseq_action_t {
2513 gchar *keyseq, *action;
2516 if (!w_current->hkwindow) {
2517 w_current->hkwindow = gschem_dialog_new_with_buttons(_("Hotkeys"),
2518 GTK_WINDOW(w_current->main_window),
2519 0, /* not modal */
2520 "hotkeys", w_current,
2521 GTK_STOCK_CLOSE,
2522 GTK_RESPONSE_REJECT,
2523 NULL);
2525 gtk_window_position (GTK_WINDOW (w_current->hkwindow),
2526 GTK_WIN_POS_NONE);
2528 gtk_signal_connect (GTK_OBJECT (w_current->hkwindow), "response",
2529 GTK_SIGNAL_FUNC(x_dialog_hotkeys_response),
2530 w_current);
2532 gtk_dialog_set_default_response(GTK_DIALOG(w_current->hkwindow),
2533 GTK_RESPONSE_ACCEPT);
2535 gtk_container_border_width (GTK_CONTAINER (w_current->hkwindow),
2536 DIALOG_BORDER_SPACING);
2537 gtk_widget_set_usize(w_current->hkwindow, 300,300);
2539 vbox = GTK_DIALOG(w_current->hkwindow)->vbox;
2540 gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
2542 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
2543 gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
2544 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
2545 GTK_POLICY_AUTOMATIC,
2546 GTK_POLICY_AUTOMATIC);
2548 /* the model */
2549 store = gtk_list_store_new (2,G_TYPE_STRING, G_TYPE_STRING);
2551 /* retrieve current keymap */
2552 keymap = g_keys_dump_keymap ();
2553 /* add each keymap entry to the list store of the dialog */
2554 for (i = 0; i < keymap->len; i++) {
2555 GtkTreeIter iter;
2556 struct keyseq_action_t *keymap_entry;
2558 keymap_entry = &g_array_index (keymap, struct keyseq_action_t, i);
2559 gtk_list_store_append (store, &iter);
2560 gtk_list_store_set (store, &iter,
2561 0, keymap_entry->action,
2562 1, keymap_entry->keyseq,
2563 -1);
2566 /* finally free the array for keymap */
2567 for (i = 0; i < keymap->len; i++) {
2568 struct keyseq_action_t *keymap_entry;
2569 keymap_entry = &g_array_index (keymap, struct keyseq_action_t, i);
2570 g_free (keymap_entry->keyseq);
2571 g_free (keymap_entry->action);
2573 g_array_free (keymap, TRUE);
2575 /* the tree view */
2576 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
2577 gtk_container_add(GTK_CONTAINER(scrolled_win), treeview);
2579 /* the columns */
2580 renderer = gtk_cell_renderer_text_new ();
2581 column = gtk_tree_view_column_new_with_attributes (_("Function"),
2582 renderer,
2583 "text",
2585 NULL);
2586 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
2587 renderer = gtk_cell_renderer_text_new ();
2588 column = gtk_tree_view_column_new_with_attributes (_("Keystroke(s)"),
2589 renderer,
2590 "text",
2592 NULL);
2593 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
2595 /* show all recursively */
2596 gtk_widget_show_all(w_current->hkwindow);
2599 else { /* dialog already created */
2600 gtk_window_present(GTK_WINDOW(w_current->hkwindow));
2604 /***************** End of help/keymapping dialog box ****************/
2606 /*********** Start of misc support functions for dialog boxes *******/
2607 extern GtkWidget *stwindow;
2609 /*! \todo Finish function documentation!!!
2610 * \brief
2611 * \par Function Description
2614 void x_dialog_raise_all(TOPLEVEL *w_current)
2616 if(w_current->fowindow) {
2617 gdk_window_raise(w_current->fowindow->window);
2619 if(w_current->fswindow) {
2620 gdk_window_raise(w_current->fswindow->window);
2622 if(w_current->sowindow) {
2623 gdk_window_raise(w_current->sowindow->window);
2625 if(w_current->aswindow) {
2626 gdk_window_raise(w_current->aswindow->window);
2628 if(w_current->cswindow) {
2629 gdk_window_raise(w_current->cswindow->window);
2632 if(w_current->iwindow) {
2633 gdk_window_raise(w_current->iwindow->window);
2636 if(w_current->tiwindow) {
2637 gdk_window_raise(w_current->tiwindow->window);
2639 if(w_current->tewindow) {
2640 gdk_window_raise(w_current->tewindow->window);
2642 if(w_current->sewindow) {
2643 gdk_window_raise(w_current->sewindow->window);
2645 if(w_current->exwindow) {
2646 gdk_window_raise(w_current->exwindow->window);
2648 if(w_current->aawindow) {
2649 gdk_window_raise(w_current->aawindow->window);
2651 if(w_current->mawindow) {
2652 gdk_window_raise(w_current->mawindow->window);
2654 if(w_current->aewindow) {
2655 gdk_window_raise(w_current->aewindow->window);
2657 if(w_current->trwindow) {
2658 gdk_window_raise(w_current->trwindow->window);
2660 if(w_current->tswindow) {
2661 gdk_window_raise(w_current->tswindow->window);
2663 if(w_current->abwindow) {
2664 gdk_window_raise(w_current->abwindow->window);
2666 if(w_current->hkwindow) {
2667 gdk_window_raise(w_current->hkwindow->window);
2669 if(w_current->cowindow) {
2670 gdk_window_raise(w_current->cowindow->window);
2672 if(w_current->clwindow) {
2673 gdk_window_raise(w_current->clwindow->window);
2675 if(w_current->ltwindow) {
2676 gdk_window_raise(w_current->ltwindow->window);
2678 if(w_current->ftwindow) {
2679 gdk_window_raise(w_current->ftwindow->window);
2684 /*********** End of misc support functions for dialog boxes *******/
2686 /***************** Start of generic message dialog box *******************/
2688 /*! \todo Finish function documentation!!!
2689 * \brief
2690 * \par Function Description
2693 void generic_msg_dialog (const char *msg)
2695 GtkWidget *dialog;
2697 dialog = gtk_message_dialog_new (NULL,
2700 GTK_DIALOG_MODAL
2701 | GTK_DIALOG_DESTROY_WITH_PARENT,
2702 GTK_MESSAGE_INFO,
2703 GTK_BUTTONS_OK,
2704 msg);
2706 gtk_dialog_run (GTK_DIALOG (dialog));
2707 gtk_widget_destroy (dialog);
2711 /***************** End of generic message dialog box *********************/
2713 /***************** Start of generic confirm dialog box *******************/
2715 /*! \todo Finish function documentation!!!
2716 * \brief
2717 * \par Function Description
2720 int generic_confirm_dialog (const char *msg)
2722 GtkWidget *dialog;
2723 gint r;
2725 dialog = gtk_message_dialog_new (NULL,
2728 GTK_DIALOG_MODAL
2729 | GTK_DIALOG_DESTROY_WITH_PARENT,
2730 GTK_MESSAGE_INFO,
2731 GTK_BUTTONS_OK_CANCEL,
2732 msg);
2734 r = gtk_dialog_run (GTK_DIALOG (dialog));
2735 gtk_widget_destroy (dialog);
2737 if (r == GTK_RESPONSE_OK)
2738 return 1;
2739 else
2740 return 0;
2743 /***************** End of generic confirm dialog box *********************/
2745 /***************** Start of generic file select dialog box ***************/
2746 /*! \todo Finish function documentation!!!
2747 * \brief
2748 * \par Function Description
2750 * \warning
2751 * Caller must g_free returned character string.
2753 char *generic_filesel_dialog (const char *msg, const char *templ, gint flags)
2755 GtkWidget *dialog;
2756 gchar *result = NULL, *folder, *seed;
2757 char *title;
2758 static gchar *path = NULL;
2759 static gchar *shortcuts = NULL;
2761 /* Default to load if not specified. Maybe this should cause an error. */
2762 if (! (flags & (FSB_LOAD | FSB_SAVE))) {
2763 flags = flags | FSB_LOAD;
2766 if (flags & FSB_LOAD) {
2767 title = g_strdup_printf("%s: Open", msg);
2768 dialog = gtk_file_chooser_dialog_new (title,
2769 NULL,
2770 GTK_FILE_CHOOSER_ACTION_OPEN,
2771 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2772 GTK_STOCK_OPEN, GTK_RESPONSE_OK,
2773 NULL);
2774 /* Since this is a load dialog box, the file must exist! */
2775 flags = flags | FSB_MUST_EXIST;
2777 } else {
2778 title = g_strdup_printf("%s: Save", msg);
2779 dialog = gtk_file_chooser_dialog_new (title,
2780 NULL,
2781 GTK_FILE_CHOOSER_ACTION_SAVE,
2782 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2783 GTK_STOCK_OPEN, GTK_RESPONSE_OK,
2784 NULL);
2787 #if GTK_CHECK_VERSION (2,6,0)
2788 /* Set the alternative button order (ok, cancel, help) for other systems */
2789 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog),
2790 GTK_RESPONSE_OK,
2791 GTK_RESPONSE_CANCEL,
2792 -1);
2793 #endif
2795 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
2797 /* Pick the current default folder to look for files in */
2798 if (path && *path) {
2799 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), path);
2803 /* Pick the current template (*.rc) or default file name */
2804 if (templ && *templ) {
2805 if (flags & FSB_SAVE) {
2806 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), templ);
2807 } else {
2808 gtk_file_chooser_select_filename (GTK_FILE_CHOOSER (dialog), templ);
2813 if (shortcuts && *shortcuts) {
2814 printf ("shortcuts = \"%s\"\n", shortcuts);
2815 folder = g_strdup (shortcuts);
2816 seed = folder;
2817 while ((folder = strtok (seed, ":")) != NULL) {
2818 gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog),
2819 folder, NULL);
2820 seed = NULL;
2823 g_free (folder);
2826 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2827 result = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
2828 folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
2829 /*! \bug FIXME
2830 if (folder && path) {
2831 dup_string (path, folder);
2832 g_free (folder);
2836 gtk_widget_destroy (dialog);
2838 g_free (title);
2840 return result;
2844 /***************** End of generic file select dialog box *****************/
2846 /*********** Start of find text dialog box *******/
2848 int start_find;
2849 OBJECT *remember_page;
2851 /*! \brief response function for the find text dialog
2852 * \par Function Description
2853 * This function takes the string the user likes to find and searches it
2854 * in the schematic.
2856 void find_text_dialog_response(GtkWidget *w, gint response,
2857 TOPLEVEL *w_current)
2859 GtkWidget *textentry;
2860 GtkWidget *checkdescend;
2861 gchar *string;
2862 gint done=0, close=0;
2864 switch (response) {
2865 case GTK_RESPONSE_ACCEPT:
2866 textentry = g_object_get_data(G_OBJECT(w_current->tfindwindow),"textentry");
2867 string = (gchar*) gtk_entry_get_text(GTK_ENTRY(textentry));
2868 checkdescend = g_object_get_data(G_OBJECT(w_current->tfindwindow),"checkdescend");
2870 strncpy(generic_textstring, string, 256);
2872 while (remember_page != w_current->page_current->object_head) {
2873 s_hierarchy_up(w_current, w_current->page_current->up);
2875 done =
2876 o_edit_find_text(w_current, remember_page, string,
2877 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
2878 (checkdescend)),
2879 !start_find);
2880 if (done) {
2881 o_redraw_all_fast(w_current);
2882 close = 1;
2884 start_find = 0;
2885 break;
2886 case GTK_RESPONSE_REJECT:
2887 case GTK_RESPONSE_DELETE_EVENT:
2888 close = 1;
2889 break;
2890 default:
2891 printf("find_text_dialog_response(): strange signal %d\n", response);
2893 if (close) {
2894 gtk_widget_destroy(w_current->tfindwindow);
2895 w_current->tfindwindow = NULL;
2899 /*! \brief Create the text find dialog
2900 * \par Function Description
2901 * This function creates the text find dialog.
2903 void find_text_dialog(TOPLEVEL * w_current)
2905 GtkWidget *label = NULL;
2906 GtkWidget *vbox;
2907 GtkWidget *checkdescend;
2908 GtkWidget *textentry;
2909 OBJECT *object = NULL;
2911 start_find = 1;
2912 remember_page = w_current->page_current->object_head;
2913 if ((object = o_select_return_first_object(w_current)) != NULL) {
2914 if (object->type == OBJ_TEXT) {
2915 strncpy(generic_textstring, object->text->string, 256);
2919 if (!w_current->tfindwindow) {
2920 w_current->tfindwindow = gschem_dialog_new_with_buttons(_("Find Text"),
2921 GTK_WINDOW(w_current->main_window),
2922 0, /* not modal GTK_DIALOG_MODAL */
2923 "find-text", w_current,
2924 GTK_STOCK_CLOSE,
2925 GTK_RESPONSE_REJECT,
2926 GTK_STOCK_FIND,
2927 GTK_RESPONSE_ACCEPT,
2928 NULL);
2930 #if GTK_CHECK_VERSION (2,6,0)
2931 /* Set the alternative button order (ok, cancel, help) for other systems */
2932 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->tfindwindow),
2933 GTK_RESPONSE_ACCEPT,
2934 GTK_RESPONSE_REJECT,
2935 -1);
2936 #endif
2938 gtk_window_position(GTK_WINDOW(w_current->tfindwindow),
2939 GTK_WIN_POS_MOUSE);
2941 gtk_signal_connect(GTK_OBJECT(w_current->tfindwindow), "response",
2942 GTK_SIGNAL_FUNC(find_text_dialog_response),
2943 w_current);
2945 gtk_dialog_set_default_response(GTK_DIALOG(w_current->tfindwindow),
2946 GTK_RESPONSE_ACCEPT);
2948 gtk_container_border_width(GTK_CONTAINER(w_current->tfindwindow),
2949 DIALOG_BORDER_SPACING);
2950 vbox = GTK_DIALOG(w_current->tfindwindow)->vbox;
2951 gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
2953 label = gtk_label_new(_("Text to find:"));
2954 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
2955 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
2957 textentry = gtk_entry_new_with_max_length(20);
2958 gtk_editable_select_region(GTK_EDITABLE(textentry), 0, -1);
2959 gtk_box_pack_start(GTK_BOX(vbox), textentry, FALSE, FALSE, 0);
2960 gtk_entry_set_activates_default(GTK_ENTRY(textentry), TRUE);
2961 gtk_widget_grab_focus(textentry);
2963 checkdescend = gtk_check_button_new_with_label(_("descend into hierarchy"));
2964 gtk_box_pack_start(GTK_BOX(vbox), checkdescend, TRUE, TRUE, 0);
2966 GLADE_HOOKUP_OBJECT(w_current->tfindwindow, textentry, "textentry");
2967 GLADE_HOOKUP_OBJECT(w_current->tfindwindow, checkdescend, "checkdescend");
2969 gtk_widget_show_all(w_current->tfindwindow);
2972 else { /* dialog already created */
2973 gtk_window_present(GTK_WINDOW(w_current->tfindwindow));
2976 /* always select the text string in the entry */
2977 textentry = g_object_get_data (G_OBJECT (w_current->tfindwindow), "textentry");
2978 gtk_entry_set_text(GTK_ENTRY(textentry), generic_textstring);
2979 gtk_entry_select_region(GTK_ENTRY(textentry), 0, -1);
2982 /*********** End of find text dialog box *******/
2984 /*********** Start of hide text dialog box *******/
2986 /*! \brief Response function for the hide text dialog
2987 * \par Function Description
2988 * This is the response function of the hide text dialog. It takes the user input
2989 * and hides all text elements that starts with the searchtext.
2991 void hide_text_dialog_response(GtkWidget *w, gint response,
2992 TOPLEVEL *w_current)
2994 GtkWidget *textentry;
2995 gchar *string;
2997 switch (response) {
2998 case GTK_RESPONSE_ACCEPT:
2999 textentry = g_object_get_data(G_OBJECT(w_current->thidewindow),"textentry");
3000 string = (gchar*) gtk_entry_get_text(GTK_ENTRY(textentry));
3002 strncpy(generic_textstring, string, 256);
3003 o_edit_hide_specific_text(w_current,
3004 w_current->page_current->object_head, string);
3005 break;
3006 case GTK_RESPONSE_REJECT:
3007 case GTK_RESPONSE_DELETE_EVENT:
3008 gtk_widget_destroy(w_current->thidewindow);
3009 w_current->thidewindow = NULL;
3010 break;
3011 default:
3012 printf("show_text_dialog_response(): strange signal %d\n",response);
3016 /*! \brief Creates the hide text dialog
3017 * \par Function Description
3018 * This function creates the hide text dialog.
3020 void hide_text_dialog(TOPLEVEL * w_current)
3022 GtkWidget *label = NULL;
3023 GtkWidget *textentry;
3024 GtkWidget *vbox;
3026 if (!w_current->thidewindow) {
3027 w_current->thidewindow = gschem_dialog_new_with_buttons(_("Hide Text"),
3028 GTK_WINDOW(w_current->main_window),
3029 0, /* not modal GTK_DIALOG_MODAL, */
3030 "hide-text", w_current,
3031 GTK_STOCK_CLOSE,
3032 GTK_RESPONSE_REJECT,
3033 GTK_STOCK_APPLY,
3034 GTK_RESPONSE_ACCEPT,
3035 NULL);
3037 #if GTK_CHECK_VERSION (2,6,0)
3038 /* Set the alternative button order (ok, cancel, help) for other systems */
3039 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->thidewindow),
3040 GTK_RESPONSE_ACCEPT,
3041 GTK_RESPONSE_REJECT,
3042 -1);
3043 #endif
3045 gtk_window_position(GTK_WINDOW(w_current->thidewindow),
3046 GTK_WIN_POS_MOUSE);
3048 gtk_signal_connect(GTK_OBJECT(w_current->thidewindow), "response",
3049 GTK_SIGNAL_FUNC(hide_text_dialog_response),
3050 w_current);
3052 gtk_dialog_set_default_response(GTK_DIALOG(w_current->thidewindow),
3053 GTK_RESPONSE_ACCEPT);
3055 gtk_container_border_width(GTK_CONTAINER(w_current->thidewindow),
3056 DIALOG_BORDER_SPACING);
3057 vbox = GTK_DIALOG(w_current->thidewindow)->vbox;
3058 gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
3060 label = gtk_label_new(_("Hide text starting with:"));
3061 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
3062 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
3064 textentry = gtk_entry_new_with_max_length(20);
3065 gtk_box_pack_start(GTK_BOX(vbox), textentry, FALSE, FALSE, 0);
3066 gtk_entry_set_activates_default(GTK_ENTRY(textentry), TRUE);
3067 gtk_widget_grab_focus(textentry);
3069 GLADE_HOOKUP_OBJECT(w_current->thidewindow, textentry, "textentry");
3070 gtk_widget_show_all(w_current->thidewindow);
3073 else { /* dialog already created, just select it */
3074 gtk_window_present(GTK_WINDOW(w_current->thidewindow));
3077 /* always select the text in the search entry */
3078 textentry = g_object_get_data (G_OBJECT (w_current->thidewindow), "textentry");
3079 gtk_entry_set_text(GTK_ENTRY(textentry), generic_textstring);
3080 gtk_entry_select_region(GTK_ENTRY(textentry), 0, -1);
3083 /*********** End of hide text dialog box *******/
3085 /*********** Start of show text dialog box *******/
3087 /*! \brief Response function for the show text dialog
3088 * \par Function Description
3089 * This function takes the users input and searches all strings starting with
3090 * the given search text and hides those text objects.
3092 void show_text_dialog_response(GtkWidget *widget, gint response,
3093 TOPLEVEL *w_current)
3095 GtkWidget *textentry;
3096 gchar *string;
3098 switch (response) {
3099 case GTK_RESPONSE_ACCEPT:
3100 textentry = g_object_get_data(G_OBJECT(w_current->tshowwindow),"textentry");
3101 string = (gchar*) gtk_entry_get_text(GTK_ENTRY(textentry));
3103 strncpy(generic_textstring, string, 256);
3104 o_edit_show_specific_text(w_current,
3105 w_current->page_current->object_head, string);
3106 break;
3107 case GTK_RESPONSE_REJECT:
3108 case GTK_RESPONSE_DELETE_EVENT:
3109 gtk_widget_destroy(w_current->tshowwindow);
3110 w_current->tshowwindow = NULL;
3111 break;
3112 default:
3113 printf("show_text_dialog_response(): strange signal %d\n",response);
3117 /*! \brief Create the show text dialog.
3118 * \par Function Description
3119 * This function creates the show text dialog.
3121 void show_text_dialog(TOPLEVEL * w_current)
3123 GtkWidget *label = NULL;
3124 GtkWidget *textentry;
3125 GtkWidget *vbox;
3127 if (!w_current->tshowwindow) {
3128 w_current->tshowwindow = gschem_dialog_new_with_buttons(_("Show Text"),
3129 GTK_WINDOW(w_current->main_window),
3130 0, /* not modal GTK_DIALOG_MODAL, */
3131 "show-text", w_current,
3132 GTK_STOCK_CLOSE,
3133 GTK_RESPONSE_REJECT,
3134 GTK_STOCK_APPLY,
3135 GTK_RESPONSE_ACCEPT,
3136 NULL);
3138 #if GTK_CHECK_VERSION (2,6,0)
3139 /* Set the alternative button order (ok, cancel, help) for other systems */
3140 gtk_dialog_set_alternative_button_order(GTK_DIALOG(w_current->tshowwindow),
3141 GTK_RESPONSE_ACCEPT,
3142 GTK_RESPONSE_REJECT,
3143 -1);
3144 #endif
3146 gtk_window_position(GTK_WINDOW(w_current->tshowwindow),
3147 GTK_WIN_POS_MOUSE);
3149 gtk_signal_connect(GTK_OBJECT(w_current->tshowwindow), "response",
3150 GTK_SIGNAL_FUNC(show_text_dialog_response),
3151 w_current);
3153 gtk_dialog_set_default_response(GTK_DIALOG(w_current->tshowwindow),
3154 GTK_RESPONSE_ACCEPT);
3156 gtk_container_border_width(GTK_CONTAINER(w_current->tshowwindow),
3157 DIALOG_BORDER_SPACING);
3158 vbox = GTK_DIALOG(w_current->tshowwindow)->vbox;
3159 gtk_box_set_spacing(GTK_BOX(vbox), DIALOG_V_SPACING);
3161 label = gtk_label_new(_("Show text starting with:"));
3162 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
3163 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
3165 textentry = gtk_entry_new_with_max_length(20);
3166 gtk_box_pack_start(GTK_BOX(vbox), textentry, FALSE, FALSE, 0);
3167 gtk_entry_set_activates_default(GTK_ENTRY(textentry), TRUE);
3168 gtk_widget_grab_focus(textentry);
3170 GLADE_HOOKUP_OBJECT(w_current->tshowwindow, textentry, "textentry");
3171 gtk_widget_show_all(w_current->tshowwindow);
3174 else { /* dialog already created. Show it */
3175 gtk_window_present(GTK_WINDOW(w_current->tshowwindow));
3178 /* always select the text in the entry */
3179 textentry = g_object_get_data (G_OBJECT (w_current->tshowwindow), "textentry");
3180 gtk_entry_set_text(GTK_ENTRY(textentry), generic_textstring);
3181 gtk_entry_select_region(GTK_ENTRY(textentry), 0, -1);
3184 /*********** End of show text dialog box *******/
3186 /*********** Start of some Gtk utils *******/
3188 /*! \brief Selects all text in a TextView widget
3189 * \par Function Description
3190 * The function selects all the text in a TextView widget.
3192 void select_all_text_in_textview(GtkTextView *textview)
3194 GtkTextBuffer *textbuffer;
3195 GtkTextIter start, end;
3197 textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
3198 gtk_text_buffer_get_bounds (textbuffer, &start, &end);
3199 gtk_text_buffer_select_range(textbuffer, &start, &end);
3202 /*! \todo Finish function documentation!!!
3203 * \brief
3204 * \par Function Description
3207 int text_view_calculate_real_tab_width(GtkTextView *textview, int tab_size)
3209 PangoLayout *layout;
3210 gchar *tab_string;
3211 gint counter = 0;
3212 gint tab_width = 0;
3214 if (tab_size == 0)
3215 return -1;
3217 tab_string = g_malloc (tab_size + 1);
3219 while (counter < tab_size) {
3220 tab_string [counter] = ' ';
3221 counter++;
3224 tab_string [tab_size] = 0;
3226 layout = gtk_widget_create_pango_layout (
3227 GTK_WIDGET (textview),
3228 tab_string);
3229 g_free (tab_string);
3231 if (layout != NULL) {
3232 pango_layout_get_pixel_size (layout, &tab_width, NULL);
3233 g_object_unref (G_OBJECT (layout));
3234 } else
3235 tab_width = -1;
3237 return tab_width;
3241 /*********** End of some Gtk utils *******/
3243 /*********** Start of major symbol changed dialog box *******/
3245 /*! \todo Finish function documentation!!!
3246 * \brief
3247 * \par Function Description
3250 void major_changed_dialog(TOPLEVEL* w_current)
3252 GtkWidget* dialog;
3253 char* refdes_string = NULL;
3254 char* tmp;
3256 if (w_current->major_changed_refdes) {
3258 GList* current = w_current->major_changed_refdes;
3259 while (current)
3261 char *value = (char*) current->data;
3263 if (!refdes_string)
3265 refdes_string = g_strdup (value);
3266 } else {
3267 tmp = g_strconcat (refdes_string, "\n", value, NULL);
3268 g_free(refdes_string);
3269 refdes_string = tmp;
3272 current = current->next;
3275 tmp = g_strconcat (refdes_string,
3276 "\n\nBe sure to verify each of these symbols!",
3277 NULL);
3278 g_free(refdes_string);
3279 refdes_string = tmp;
3281 dialog = gtk_message_dialog_new ((GtkWindow*) w_current->main_window,
3282 GTK_DIALOG_DESTROY_WITH_PARENT,
3283 GTK_MESSAGE_ERROR,
3284 GTK_BUTTONS_CLOSE,
3285 "Major symbol changes detected in refdes:\n\n%s\n",
3286 refdes_string);
3288 gtk_widget_show(dialog);
3290 g_signal_connect_swapped (dialog, "response",
3291 G_CALLBACK (gtk_widget_destroy),
3292 dialog);
3294 if (refdes_string) g_free(refdes_string);
3298 /*********** End of major symbol changed dialog box *******/
3300 /***************** Start of Close Confirmation dialog box ************/
3302 #define TYPE_CLOSE_CONFIRMATION_DIALOG (close_confirmation_dialog_get_type ())
3303 #define CLOSE_CONFIRMATION_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_CLOSE_CONFIRMATION_DIALOG, CloseConfirmationDialog))
3304 #define CLOSE_CONFIRMATION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_CLOSE_CONFIRMATION_DIALOG, CloseConfirmationDialogClass))
3305 #define IS_CLOSE_CONFIRMATION_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_CLOSE_CONFIRMATION_DIALOG))
3306 #define IS_CLOSE_CONFIRMATION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_CLOSE_CONFIRMATION_DIALOG))
3307 #define CLOSE_CONFIRMATION_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),TYPE_CLOSE_CONFIRMATION_DIALOG, CloseConfirmationDialogClass))
3310 typedef struct _CloseConfirmationDialog CloseConfirmationDialog;
3311 typedef struct _CloseConfirmationDialogClass CloseConfirmationDialogClass;
3313 struct _CloseConfirmationDialog
3315 GtkDialog parent;
3317 GtkListStore *store_unsaved_pages;
3321 struct _CloseConfirmationDialogClass
3323 GtkDialogClass parent_class;
3328 enum {
3329 PROP_UNSAVED_PAGE=1,
3330 PROP_UNSAVED_PAGES,
3331 PROP_SELECTED_PAGES
3334 enum {
3335 COLUMN_SAVE,
3336 COLUMN_PAGE,
3337 NUM_COLUMNS
3341 static gpointer close_confirmation_dialog_parent_class = NULL;
3344 static void close_confirmation_dialog_class_init (CloseConfirmationDialogClass *klass);
3345 static void close_confirmation_dialog_init (CloseConfirmationDialog *self);
3346 static void close_confirmation_dialog_set_property (GObject *object,
3347 guint property_id,
3348 const GValue *value,
3349 GParamSpec *pspec);
3350 static void close_confirmation_dialog_get_property (GObject *object,
3351 guint property_id,
3352 GValue *value,
3353 GParamSpec *pspec);
3354 static GObject* close_confirmation_dialog_constructor (GType type,
3355 guint n_construct_properties,
3356 GObjectConstructParam *construct_params);
3358 GList *close_confirmation_dialog_get_selected_pages (CloseConfirmationDialog *dialog);
3362 GType
3363 close_confirmation_dialog_get_type ()
3365 static GType close_confirmation_dialog_type = 0;
3367 if (!close_confirmation_dialog_type) {
3368 static const GTypeInfo close_confirmation_dialog_info = {
3369 sizeof(CloseConfirmationDialogClass),
3370 NULL, /* base_init */
3371 NULL, /* base_finalize */
3372 (GClassInitFunc) close_confirmation_dialog_class_init,
3373 NULL, /* class_finalize */
3374 NULL, /* class_data */
3375 sizeof(CloseConfirmationDialog),
3376 0, /* n_preallocs */
3377 (GInstanceInitFunc) close_confirmation_dialog_init,
3380 close_confirmation_dialog_type =
3381 g_type_register_static (GTK_TYPE_DIALOG,
3382 "CloseConfirmationDialog",
3383 &close_confirmation_dialog_info, 0);
3386 return close_confirmation_dialog_type;
3389 static void
3390 close_confirmation_dialog_class_init (CloseConfirmationDialogClass *klass)
3392 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
3394 close_confirmation_dialog_parent_class = g_type_class_peek_parent (klass);
3396 gobject_class->constructor = close_confirmation_dialog_constructor;
3397 gobject_class->set_property = close_confirmation_dialog_set_property;
3398 gobject_class->get_property = close_confirmation_dialog_get_property;
3400 g_object_class_install_property (
3401 gobject_class, PROP_UNSAVED_PAGE,
3402 g_param_spec_pointer ("unsaved-page",
3405 G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
3406 g_object_class_install_property (
3407 gobject_class, PROP_UNSAVED_PAGES,
3408 g_param_spec_pointer ("unsaved-pages",
3411 G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
3412 g_object_class_install_property (
3413 gobject_class, PROP_SELECTED_PAGES,
3414 g_param_spec_pointer ("selected-pages",
3417 G_PARAM_READABLE));
3421 static void
3422 close_confirmation_dialog_init (CloseConfirmationDialog *self)
3424 /* create model for treeview and populate */
3425 self->store_unsaved_pages = gtk_list_store_new (NUM_COLUMNS,
3426 G_TYPE_BOOLEAN, /* save? */
3427 G_TYPE_POINTER); /* page */
3431 /*! \brief Returns the number of pages in the model.
3432 * \par Function Description
3433 * This function determines the number of pages with unsaved changes
3434 * from the model.
3436 * \param in model The tree model.
3437 * \returns The number of pages with unsaved changes.
3439 static gint
3440 count_pages (GtkTreeModel *model)
3442 GtkTreeIter iter;
3443 gint n_pages;
3445 gtk_tree_model_get_iter_first (model, &iter);
3446 for (n_pages = 1;
3447 gtk_tree_model_iter_next (model, &iter);
3448 n_pages++);
3450 return n_pages;
3453 /*! \brief Returns the name to use for the given page in the model.
3454 * \par Function Description
3455 * This function determines the text to be used to identify a
3456 * specific page from the model of pages with unsaved changes.
3458 * If <B>piter</B> is NULL, the name for the first page of the model
3459 * is returned. Otherwise, it returns the name for the page defined
3460 * by the pointed iterator.
3462 * The returned value must be freed by caller.
3464 * \param in model The tree model.
3465 * \param in piter A pointer on a GtkTreeIter of model or NULL.
3466 * \returns The name for the page.
3468 static gchar*
3469 get_page_name (GtkTreeModel *model, GtkTreeIter *piter)
3471 GtkTreeIter iter;
3472 PAGE *page;
3474 g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
3476 if (piter == NULL) {
3477 gtk_tree_model_get_iter_first (model, &iter);
3478 } else {
3479 iter = *piter;
3482 gtk_tree_model_get (model, &iter,
3483 COLUMN_PAGE, &page,
3484 -1);
3485 g_assert (page != NULL && page->page_filename != NULL);
3486 return g_path_get_basename (page->page_filename);
3489 /*! \brief Sets the contents of the name cell in the treeview of dialog.
3490 * \par Function Description
3491 * This functions sets the cell of the treeview with the short name
3492 * of the page obtained with <B>get_page_name()</B>.
3494 * \param in tree_column A GtkTreeColumn.
3495 * \param in cell The GtkCellRenderer that is being rendered by
3496 * tree_column.
3497 * \param in tree_model The GtkTreeModel being rendered.
3498 * \param in iter A GtkTreeIter of the current row rendered.
3499 * \param in data .
3501 static void
3502 close_confirmation_dialog_set_page_name (GtkTreeViewColumn *tree_column,
3503 GtkCellRenderer *cell,
3504 GtkTreeModel *tree_model,
3505 GtkTreeIter *iter,
3506 gpointer data)
3508 gchar *page_name;
3510 page_name = get_page_name (tree_model, iter);
3511 g_object_set (cell,
3512 "text", page_name,
3513 NULL);
3514 g_free (page_name);
3518 /*! \brief Callback function for the toggled signal of check box in treeview.
3519 * \par Function Description
3520 * This functions changes the value of the save column in the model
3521 * for the affected row when user toggles the check box in the
3522 * treeview.
3524 * \param in cell_renderer The GtkCellRendererToggle.
3525 * \param in path The GtkTreePath to the concerned row in model.
3526 * \param in user The dialog as user data.
3528 static void
3529 close_confirmation_dialog_callback_renderer_toggled (GtkCellRendererToggle *cell_renderer,
3530 gchar *path,
3531 gpointer user_data)
3533 CloseConfirmationDialog *dialog = CLOSE_CONFIRMATION_DIALOG (user_data);
3534 GtkTreeModel *model;
3535 GtkTreeIter iter;
3536 gboolean save;
3538 model = GTK_TREE_MODEL (dialog->store_unsaved_pages);
3540 gtk_tree_model_get_iter_from_string (model, &iter, path);
3541 gtk_tree_model_get (model, &iter,
3542 COLUMN_SAVE, &save,
3543 -1);
3544 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
3545 COLUMN_SAVE, (save != TRUE),
3546 -1);
3550 /*! \brief Adds a treeview to confirmation dialog for selecting of pages.
3551 * \par Function Description
3552 * This function adds a treeview and caption to display the content
3553 * of the dialog model of pages with unsaved changes.
3555 * The treeview displays the page names with check boxes.
3557 * \param in dialog The dialog.
3558 * \returns A pointer on the GtkVBox to add to dialog.
3560 static GtkWidget*
3561 close_confirmation_dialog_build_page_list (CloseConfirmationDialog *dialog)
3563 GtkWidget *vbox, *scrolled_window, *treeview, *label;
3564 GtkCellRenderer *renderer;
3565 GtkTreeViewColumn *column;
3566 const gchar *text;
3568 /* place the treeview and its caption into their own box */
3569 vbox = GTK_WIDGET (g_object_new (GTK_TYPE_VBOX,
3570 /* GtkBox */
3571 "homogeneous", FALSE,
3572 "spacing", 8,
3573 NULL));
3575 /* the list of pages with changes */
3576 /* - scrolled window as container for the treeview first */
3577 scrolled_window = GTK_WIDGET (g_object_new (GTK_TYPE_SCROLLED_WINDOW,
3578 /* GtkScrolledWindow */
3579 "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
3580 "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
3581 "shadow-type", GTK_SHADOW_IN,
3582 NULL));
3583 /* - then the treeview */
3584 /* create model for treeview and populate */
3585 treeview = GTK_WIDGET (g_object_new (GTK_TYPE_TREE_VIEW,
3586 /* GtkTreeView */
3587 "enable-search", FALSE,
3588 "headers-visible", FALSE,
3589 "model", dialog->store_unsaved_pages,
3590 NULL));
3591 renderer = gtk_cell_renderer_toggle_new ();
3592 g_signal_connect (renderer, "toggled",
3593 G_CALLBACK (
3594 close_confirmation_dialog_callback_renderer_toggled),
3595 dialog);
3596 column = gtk_tree_view_column_new_with_attributes ("Save?",
3597 renderer,
3598 "active", COLUMN_SAVE,
3599 NULL);
3600 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
3602 renderer = gtk_cell_renderer_text_new ();
3603 column = GTK_TREE_VIEW_COLUMN (
3604 g_object_new (GTK_TYPE_TREE_VIEW_COLUMN,
3605 /* GtkTreeViewColumn */
3606 "title", _("Name"),
3607 NULL));
3608 gtk_tree_view_column_pack_start (column, renderer, TRUE);
3609 gtk_tree_view_column_set_cell_data_func (column, renderer,
3610 close_confirmation_dialog_set_page_name,
3611 NULL, NULL);
3612 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
3614 gtk_container_add (GTK_CONTAINER (scrolled_window), treeview);
3616 gtk_box_pack_end (GTK_BOX (vbox), scrolled_window,
3617 TRUE, TRUE, 0);
3619 /* the caption label above the list of pages */
3620 label = GTK_WIDGET (g_object_new (GTK_TYPE_LABEL,
3621 /* GtkMisc */
3622 "xalign", 0.0,
3623 "yalign", 0.0,
3624 /* GtkLabel */
3625 "wrap", TRUE,
3626 "mnemonic-widget", treeview,
3627 NULL));
3628 text = _("S_elect the schematics you want to save:");
3629 gtk_label_set_text_with_mnemonic (GTK_LABEL (label), text);
3630 gtk_label_set_mnemonic_widget (GTK_LABEL (label), treeview);
3631 gtk_box_pack_start (GTK_BOX (vbox), label,
3632 FALSE, FALSE, 0);
3634 return vbox;
3637 static GObject*
3638 close_confirmation_dialog_constructor (GType type,
3639 guint n_construct_properties,
3640 GObjectConstructParam *construct_params)
3642 GObject *object;
3643 CloseConfirmationDialog *dialog;
3644 GtkWidget *hbox, *image, *vbox, *label;
3645 GtkTreeIter iter;
3646 gboolean ret, single_page;
3647 gchar *tmp, *str;
3649 /* chain up to constructor of parent class */
3650 object =
3651 G_OBJECT_CLASS (close_confirmation_dialog_parent_class)->constructor (
3652 type,
3653 n_construct_properties,
3654 construct_params);
3655 dialog = CLOSE_CONFIRMATION_DIALOG (object);
3657 g_object_set (dialog,
3658 /* GtkDialog */
3659 "has-separator", FALSE,
3660 /* GtkWindow */
3661 "resizable", FALSE,
3662 "skip-taskbar-hint", TRUE,
3663 /* GtkContainer */
3664 "border-width", 5,
3665 NULL);
3666 g_object_set (GTK_DIALOG (dialog)->vbox,
3667 /* GtkBox */
3668 "spacing", 14,
3669 NULL);
3670 g_object_set (GTK_DIALOG (dialog)->action_area,
3671 /* GtkBox */
3672 "spacing", 6,
3673 /* GtkContainer */
3674 "border-width", 5,
3675 NULL);
3677 /* check if there is one or more than one page with changes */
3678 ret = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (
3679 dialog->store_unsaved_pages),
3680 &iter);
3681 g_assert (ret);
3682 single_page = !gtk_tree_model_iter_next (GTK_TREE_MODEL (
3683 dialog->store_unsaved_pages),
3684 &iter);
3686 /* here starts the layout of the dialog */
3687 hbox = GTK_WIDGET (g_object_new (GTK_TYPE_HBOX,
3688 /* GtkContainer */
3689 "border-width", 5,
3690 /* GtkBox */
3691 "homogeneous", FALSE,
3692 "spacing", 12,
3693 NULL));
3695 /* warning image */
3696 image = g_object_new (GTK_TYPE_IMAGE,
3697 /* GtkMisc */
3698 "xalign", 0.5,
3699 "yalign", 0.0,
3700 /* GtkImage */
3701 "stock", GTK_STOCK_DIALOG_WARNING,
3702 "icon-size", GTK_ICON_SIZE_DIALOG,
3703 NULL);
3704 gtk_box_pack_start (GTK_BOX (hbox), image,
3705 FALSE, FALSE, 0);
3707 /* vertical box on the right hand side of the dialog */
3708 vbox = GTK_WIDGET (g_object_new (GTK_TYPE_VBOX,
3709 /* GtkBox */
3710 "homogeneous", FALSE,
3711 "spacing", 12,
3712 NULL));
3714 /* primary label */
3715 if (single_page) {
3716 /* single page */
3717 gchar *page_name;
3719 page_name = get_page_name (GTK_TREE_MODEL (dialog->store_unsaved_pages),
3720 NULL);
3721 tmp = g_strdup_printf (
3722 _("Save the changes to schematic \"%s\" before closing?"),
3723 page_name);
3724 g_free (page_name);
3725 } else {
3726 /* multi page */
3727 tmp = g_strdup_printf (
3728 _("There are %d schematics with unsaved changes. "
3729 "Save changes before closing?"),
3730 count_pages (GTK_TREE_MODEL (dialog->store_unsaved_pages)));
3732 str = g_strconcat ("<big><b>", tmp, "</b></big>", NULL);
3733 g_free (tmp);
3734 label = GTK_WIDGET (g_object_new (GTK_TYPE_LABEL,
3735 /* GtkMisc */
3736 "xalign", 0.0,
3737 "yalign", 0.0,
3738 "selectable", TRUE,
3739 /* GtkLabel */
3740 "wrap", TRUE,
3741 "use-markup", TRUE,
3742 "label", str,
3743 NULL));
3744 g_free (str);
3745 gtk_box_pack_start (GTK_BOX (vbox), label,
3746 FALSE, FALSE, 0);
3748 if (!single_page) {
3749 /* more than one page with changes, display each page and offer */
3750 /* the opportunity to save them before exiting */
3751 gtk_box_pack_start (GTK_BOX (vbox),
3752 close_confirmation_dialog_build_page_list (dialog),
3753 FALSE, FALSE, 0);
3756 /* secondary label */
3757 str = _("If you don't save, all your changes will be permanently lost.");
3758 label = GTK_WIDGET (g_object_new (GTK_TYPE_LABEL,
3759 /* GtkMisc */
3760 "xalign", 0.0,
3761 "yalign", 0.0,
3762 "selectable", TRUE,
3763 /* GtkLabel */
3764 "wrap", TRUE,
3765 "label", str,
3766 NULL));
3767 gtk_box_pack_start (GTK_BOX (vbox), label,
3768 FALSE, FALSE, 0);
3771 gtk_box_pack_start (GTK_BOX (hbox), vbox,
3772 FALSE, FALSE, 0);
3775 /* add buttons to dialog action area */
3776 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
3777 _("_Close without saving"), GTK_RESPONSE_NO,
3778 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
3779 GTK_STOCK_SAVE, GTK_RESPONSE_YES,
3780 NULL);
3782 #if GTK_CHECK_VERSION (2,6,0)
3783 /* Set the alternative button order (ok, cancel, help) for other systems */
3784 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog),
3785 GTK_RESPONSE_YES,
3786 GTK_RESPONSE_NO,
3787 GTK_RESPONSE_CANCEL,
3788 -1);
3789 #endif
3791 /* all done, let's show the contents of the dialog */
3792 gtk_widget_show_all (hbox);
3794 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox,
3795 FALSE, FALSE, 0);
3797 return object;
3800 static void
3801 close_confirmation_dialog_set_property (GObject *object,
3802 guint property_id,
3803 const GValue *value,
3804 GParamSpec *pspec)
3806 CloseConfirmationDialog *dialog = CLOSE_CONFIRMATION_DIALOG (object);
3807 GtkTreeIter iter;
3808 gpointer data;
3809 GList *p_current;
3811 switch(property_id) {
3812 case PROP_UNSAVED_PAGE:
3813 data = g_value_get_pointer (value);
3814 if (data != NULL) {
3815 /* add single page to model */
3816 gtk_list_store_append (dialog->store_unsaved_pages,
3817 &iter);
3818 gtk_list_store_set (dialog->store_unsaved_pages,
3819 &iter,
3820 COLUMN_SAVE, TRUE,
3821 COLUMN_PAGE, data,
3822 -1);
3824 break;
3826 case PROP_UNSAVED_PAGES:
3827 data = g_value_get_pointer (value);
3828 /* add set of pages to model */
3829 for (p_current = (GList*)data;
3830 p_current != NULL;
3831 p_current = g_list_next (p_current)) {
3832 gtk_list_store_append (dialog->store_unsaved_pages,
3833 &iter);
3834 gtk_list_store_set (dialog->store_unsaved_pages,
3835 &iter,
3836 COLUMN_SAVE, TRUE,
3837 COLUMN_PAGE, p_current->data,
3838 -1);
3840 break;
3842 default:
3843 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
3848 static void
3849 close_confirmation_dialog_get_property (GObject *object,
3850 guint property_id,
3851 GValue *value,
3852 GParamSpec *pspec)
3854 CloseConfirmationDialog *dialog = CLOSE_CONFIRMATION_DIALOG (object);
3856 switch(property_id) {
3857 case PROP_SELECTED_PAGES:
3858 g_value_set_pointer (
3859 value,
3860 close_confirmation_dialog_get_selected_pages (dialog));
3861 break;
3863 default:
3864 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
3869 /*! \brief Helps building a list of selected page to save.
3870 * \par Function Description
3871 * This is the <B>GtkTreeModelForeachFunc</B> for function
3872 * <B>close_confirmation_dialog_get_selected_pages()</B>.
3874 * It builds from the tree model a list of PAGEs for which a save
3875 * action has been requested. Each selected page is appended to the
3876 * GList pointed by <B>data</B>
3878 * \param in model The tree model.
3879 * \param in path .
3880 * \param in iter .
3881 * \param in data A pointer on a GList* to fill.
3882 * \returns FALSE to continue walking the tree.
3884 static gboolean
3885 get_selected_pages (GtkTreeModel *model,
3886 GtkTreePath *path,
3887 GtkTreeIter *iter,
3888 gpointer data)
3890 PAGE *page;
3891 gboolean save;
3893 gtk_tree_model_get (model, iter,
3894 COLUMN_SAVE, &save,
3895 COLUMN_PAGE, &page,
3896 -1);
3897 if (save) {
3898 g_assert (page != NULL);
3899 *(GList**)data = g_list_append (*(GList**)data, page);
3902 return FALSE;
3905 /*! \brief Returns a list of the selected pages with changes to save.
3906 * \par Function Description
3907 * This function returns the pages that the user has selected in the
3908 * confirmation dialog.
3910 * The returned list must be freed.
3912 * \param in dialog The dialog.
3913 * \returns A GList of selected PAGE* in dialog.
3915 GList*
3916 close_confirmation_dialog_get_selected_pages (CloseConfirmationDialog *dialog)
3918 GList *selected = NULL;
3920 gtk_tree_model_foreach (GTK_TREE_MODEL (dialog->store_unsaved_pages),
3921 (GtkTreeModelForeachFunc)get_selected_pages,
3922 &selected);
3924 return selected;
3928 /*! \brief Asks for confirmation before closing a changed page.
3929 * \par Function Description
3930 * This function asks the user to confirm its closing order for
3931 * page <B>page</B> while it still has unsaved changes.
3933 * It displays a message dialog inviting the user to cancel the
3934 * closing, or to discard the changes or to save the changes to a
3935 * file.
3937 * \param in toplevel The toplevel environment.
3938 * \param in page The page to close.
3940 void
3941 x_dialog_close_changed_page (TOPLEVEL *toplevel, PAGE *page)
3943 GtkWidget *dialog;
3945 g_return_if_fail (page != NULL && page->CHANGED);
3947 dialog = GTK_WIDGET (g_object_new (TYPE_CLOSE_CONFIRMATION_DIALOG,
3948 "unsaved-page", page,
3949 NULL));
3950 /* set default response signal. This is usually triggered by the
3951 "Return" key */
3952 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
3953 GTK_RESPONSE_YES);
3955 switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
3956 case GTK_RESPONSE_NO:
3957 /* action selected: close without saving */
3958 /* close the page, discard changes */
3959 x_window_close_page (toplevel, page);
3960 break;
3963 case GTK_RESPONSE_YES:
3964 /* action selected: save */
3965 /* prompts user for the filename and ultimate confirmation */
3966 s_page_goto (toplevel, page);
3967 x_fileselect_save (toplevel);
3968 /* has the page been really saved? */
3969 if (!page->CHANGED) {
3970 x_window_close_page (toplevel, page);
3972 /* no, user has cancelled the save and page has changes */
3973 /* do not close page */
3974 break;
3976 case GTK_RESPONSE_CANCEL:
3977 /* action selected: cancel */
3978 /* fall through */
3979 default:
3980 /* Hit when the user breaks out of the dialog with the escape key
3981 * or otherwise destroys the dialog window without a proper response */
3982 /* nothing to do */
3983 break;
3985 gtk_widget_destroy (dialog);
3989 /*! \brief Asks for confirmation before closing a window.
3990 * \par Function Description
3991 * This function asks the user to confirm its closing order for
3992 * the given window.
3994 * The user is given the possibility to save the pages that currently
3995 * have unsaved changes, if any.
3997 * It returns TRUE if the user really accepts the close of the
3998 * window. Otherwise the user has somehow cancelled and the window
3999 * must not be closed.
4001 * \param in toplevel The toplevel environment.
4002 * \returns TRUE if the window can be closed, FALSE otherwise.
4004 gboolean
4005 x_dialog_close_window (TOPLEVEL *toplevel)
4007 GtkWidget *dialog;
4008 PAGE *p_current;
4009 GList *unsaved_pages, *p_unsaved;
4010 gboolean ret = FALSE;
4012 /* build a list of unsaved pages */
4013 g_assert (toplevel->page_head != NULL &&
4014 toplevel->page_head->next != NULL);
4015 for (p_current = toplevel->page_head->next, unsaved_pages = NULL;
4016 p_current != NULL;
4017 p_current = p_current->next) {
4018 if (p_current->CHANGED) {
4019 unsaved_pages = g_list_append (unsaved_pages, (gpointer)p_current);
4023 if (unsaved_pages == NULL) {
4024 /* no page with unsaved changes, close window */
4025 return TRUE;
4028 dialog = GTK_WIDGET (g_object_new (TYPE_CLOSE_CONFIRMATION_DIALOG,
4029 "unsaved-pages", unsaved_pages,
4030 NULL));
4032 g_list_free (unsaved_pages);
4033 switch (gtk_dialog_run (GTK_DIALOG (dialog))) {
4034 case GTK_RESPONSE_NO:
4035 /* action selected: close without saving */
4036 /* discard changes, ok to close window */
4037 ret = TRUE;
4038 break;
4040 case GTK_RESPONSE_YES:
4041 /* action selected: save */
4042 /* prompts user for the filename and ultimate confirmation for */
4043 /* each selected page */
4044 g_object_get (dialog,
4045 "selected-pages", &unsaved_pages,
4046 NULL);
4047 for (p_unsaved = unsaved_pages, ret = TRUE;
4048 p_unsaved != NULL;
4049 p_unsaved = g_list_next (p_unsaved)) {
4050 p_current = (PAGE*)p_unsaved->data;
4052 s_page_goto (toplevel, p_current);
4053 x_fileselect_save (toplevel);
4054 /* if user cancelled previous, do not close window */
4055 ret &= !p_current->CHANGED;
4057 g_list_free (unsaved_pages);
4058 break;
4060 case GTK_RESPONSE_CANCEL:
4061 /* action selected: cancel */
4062 /* fall through */
4063 default:
4064 /* Hit when the user breaks out of the dialog with the escape key
4065 * or otherwise destroys the dialog window without a proper response */
4066 ret = FALSE;
4067 break;
4069 gtk_widget_destroy (dialog);
4071 return ret;
4074 /***************** End of Close Confirmation dialog box **************/
4077 /***************** Start of misc helper dialog boxes **************/
4078 /*! \brief Validate the input attribute
4079 * \par Function Description
4080 * This function validates the attribute and if it isn't valid
4081 * pops up an error message box.
4083 * \param parent The parent window which spawned this dialog box.
4084 * \param attribute The attribute to be validated.
4085 * \returns TRUE if the attribute is valid, FALSE otherwise.
4087 int x_dialog_validate_attribute(GtkWindow* parent, char *attribute)
4089 GtkWidget* message_box;
4090 char *name_ptr, *value_ptr;
4092 /* validate the new attribute */
4093 if (!o_attrib_get_name_value(attribute, &name_ptr, &value_ptr)) {
4094 message_box = gtk_message_dialog_new_with_markup (parent,
4095 GTK_DIALOG_DESTROY_WITH_PARENT,
4096 GTK_MESSAGE_ERROR,
4097 GTK_BUTTONS_CLOSE,
4098 _("<span weight=\"bold\" size=\"larger\">The input attribute \"%s\" is invalid\nPlease correct in order to continue</span>\n\nThe name and value must be non-empty.\nThe name cannot end with a space.\nThe value cannot start with a space."),
4099 attribute);
4100 gtk_window_set_title(GTK_WINDOW(message_box), _("Invalid Attribute"));
4101 gtk_dialog_run (GTK_DIALOG (message_box));
4102 gtk_widget_destroy (message_box);
4103 return FALSE;
4105 g_free(name_ptr);
4106 g_free(value_ptr);
4107 return TRUE;
4109 /***************** End of misc helper dialog boxes **************/