1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 * File: table_dialog.c
19 *
20 * Purpose: This file contains the code the draws and handles the
21 * (databse) table dialog. This is the dialog box that is
22 * displayed when the table Icon is double clicked.
23 */
24
25 /*
26 * The code listed here is very similar to the one for the UML class
27 * dialog. Indeed, I've used it as a template. -- pn
28 */
29
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
33
34 #undef GTK_DISABLE_DEPRECATED /* GtkList, */
35 #include <gtk/gtk.h>
36 #include <string.h>
37 #include "database.h"
38
39 struct _TablePropDialog {
40 GtkWidget * dialog;
41
42 /* general page */
43
44 GtkEntry * table_name;
45 GtkTextView * table_comment;
46 GtkToggleButton * comment_visible;
47 GtkToggleButton * comment_tagging;
48 GtkToggleButton * underline_primary_key;
49 GtkToggleButton * bold_primary_key;
50
51 DiaColorSelector * text_color;
52 DiaColorSelector * line_color;
53 DiaColorSelector * fill_color;
54
55 DiaFontSelector *normal_font;
56 GtkSpinButton *normal_font_height;
57
58 DiaFontSelector *name_font;
59 GtkSpinButton *name_font_height;
60
61 DiaFontSelector *comment_font;
62 GtkSpinButton *comment_font_height;
63
64 GtkSpinButton * border_width;
65
66 /* attributes page */
67
68 GtkList * attributes_list;
69 GtkEntry * attribute_name;
70 GtkEntry * attribute_type;
71 GtkTextView * attribute_comment;
72 GtkToggleButton * attribute_primary_key;
73 GtkToggleButton * attribute_nullable;
74 GtkToggleButton * attribute_unique;
75
76 GtkListItem * cur_attr_list_item;
77 GList * added_connections;
78 GList * deleted_connections;
79 GList * disconnected_connections;
80 };
81
82 void
table_dialog_free(TablePropDialog * dialog)83 table_dialog_free (TablePropDialog *dialog)
84 {
85 gtk_widget_destroy (dialog->dialog);
86 g_free (dialog);
87 }
88
89 /* ----------------------------------------------------------------------- */
90
91 static void destroy_prop_dialog (GtkWidget*, gpointer);
92 static void create_dialog_pages(GtkNotebook *, Table *);
93 static void create_general_page (GtkNotebook *, Table *);
94 static void create_attribute_page (GtkNotebook *, Table *);
95 static void create_style_page (GtkNotebook *, Table *);
96 static void fill_in_dialog (Table *);
97 static void general_page_fill_in_dialog (Table *);
98 static void general_page_props_to_object (Table *, TablePropDialog *);
99 static void attribute_page_props_to_object (Table *, TablePropDialog *);
100 static void attributes_page_values_to_attribute (TablePropDialog *,
101 TableAttribute *);
102 static void create_font_props_row (GtkTable *table,
103 const char *kind,
104 gint row,
105 DiaFont *font,
106 real height,
107 DiaFontSelector **fontsel,
108 GtkSpinButton **heightsel);
109 static const gchar * get_comment(GtkTextView *view);
110 static void set_comment(GtkTextView *view, gchar *text);
111 static void attributes_list_selection_changed_cb (GtkWidget *, Table *);
112 static void attributes_page_set_sensitive (TablePropDialog *, gboolean);
113 static void attributes_page_clear_values(TablePropDialog *);
114 static void attributes_page_set_values (TablePropDialog *, TableAttribute *);
115 static void attributes_page_update_cur_attr_item (TablePropDialog *);
116 static void attribute_list_item_destroy_cb (GtkWidget *, gpointer);
117 static void attributes_list_new_button_clicked_cb (GtkWidget *, Table *);
118 static void attributes_list_delete_button_clicked_cb (GtkWidget *, Table *);
119 static void attributes_list_moveup_button_clicked_cb (GtkWidget *, Table *);
120 static void attributes_list_movedown_button_clicked_cb (GtkWidget *, Table *);
121 static void attributes_list_add_attribute (Table *, TableAttribute *, gboolean);
122 static void current_attribute_update (GtkWidget *, Table *);
123 static int current_attribute_update_event (GtkWidget *,
124 GdkEventFocus *, Table *);
125 static void attributes_page_fill_in_dialog (Table *);
126 static void attribute_primary_key_toggled_cb (GtkToggleButton *, Table *);
127 static void attribute_nullable_toggled_cb (GtkToggleButton *, Table *);
128 static void attribute_unique_toggled_cb (GtkToggleButton *, Table *);
129
130 static void table_dialog_store_disconnects (TablePropDialog *,
131 ConnectionPoint *);
132 static gchar * table_get_attribute_string (TableAttribute *);
133
134 static void table_state_set (TableState *, Table *);
135 static void table_state_free (TableState *);
136 static void table_change_free (TableChange *);
137 static void table_change_revert (TableChange *, DiaObject *);
138 static void table_change_apply (TableChange *, DiaObject *);
139
140
141 /* ----------------------------------------------------------------------- */
142
143 GtkWidget *
table_get_properties_dialog(Table * table,gboolean is_default)144 table_get_properties_dialog (Table * table, gboolean is_default)
145 {
146 TablePropDialog * prop_dialog;
147 GtkWidget * vbox;
148 GtkWidget * notebook;
149
150 if (table->prop_dialog == NULL) {
151 prop_dialog = g_new0 (TablePropDialog, 1);
152 table->prop_dialog = prop_dialog;
153
154 vbox = gtk_vbox_new (FALSE, 0);
155 gtk_object_ref (GTK_OBJECT(vbox));
156 gtk_object_sink (GTK_OBJECT(vbox));
157 prop_dialog->dialog = vbox;
158
159 notebook = gtk_notebook_new ();
160 gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
161 gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
162 gtk_container_set_border_width (GTK_CONTAINER (notebook), 10);
163
164 gtk_object_set_user_data (GTK_OBJECT (notebook), (gpointer) table);
165
166 gtk_signal_connect (GTK_OBJECT (notebook),
167 "destroy",
168 GTK_SIGNAL_FUNC (destroy_prop_dialog),
169 (gpointer) table);
170
171 create_dialog_pages (GTK_NOTEBOOK (notebook), table);
172 /* by default the table name entry is focused */
173 gtk_widget_grab_focus (GTK_WIDGET (table->prop_dialog->table_name));
174 gtk_widget_show (notebook);
175 }
176
177 fill_in_dialog (table);
178 gtk_widget_show (table->prop_dialog->dialog);
179
180 return table->prop_dialog->dialog;
181 }
182
183 ObjectChange *
table_dialog_apply_changes(Table * table,GtkWidget * unused)184 table_dialog_apply_changes (Table * table, GtkWidget * unused)
185 {
186 TableState * state;
187 GList * disconnected;
188 GList * deleted;
189 GList * added;
190 TablePropDialog * prop_dialog;
191
192 prop_dialog = table->prop_dialog;
193
194 state = table_state_new (table);
195
196 general_page_props_to_object (table, prop_dialog);
197 attribute_page_props_to_object (table, prop_dialog);
198
199 table_update_primary_key_font (table);
200 table_compute_width_height (table);
201 table_update_positions (table);
202
203 disconnected = prop_dialog->disconnected_connections;
204 prop_dialog->disconnected_connections = NULL;
205
206 deleted = prop_dialog->deleted_connections;
207 prop_dialog->deleted_connections = NULL;
208
209 added = prop_dialog->added_connections;
210 prop_dialog->added_connections = NULL;
211
212 fill_in_dialog (table);
213 return (ObjectChange *)table_change_new (table, state,
214 added, deleted, disconnected);
215 }
216
217 /* TableState & TableChange functions ------------------------------------- */
218
table_state_new(Table * table)219 TableState * table_state_new (Table * table)
220 {
221 TableState * state = g_new0 (TableState, 1);
222 GList * list;
223
224 state->name = g_strdup (table->name);
225 state->comment = g_strdup (table->comment);
226 state->visible_comment = table->visible_comment;
227 state->tagging_comment = table->tagging_comment;
228 state->underline_primary_key = table->underline_primary_key;
229 state->bold_primary_key = table->bold_primary_key;
230 state->border_width = table->border_width;
231
232 list = table->attributes;
233 while (list != NULL)
234 {
235 TableAttribute * attr = (TableAttribute *) list->data;
236 TableAttribute * copy = table_attribute_copy (attr);
237
238 copy->left_connection = attr->left_connection;
239 copy->right_connection = attr->right_connection;
240
241 state->attributes = g_list_append (state->attributes, copy);
242 list = g_list_next (list);
243 }
244
245 return state;
246 }
247
248 /**
249 * Set the values stored in state to the passed table and reinit the table
250 * object. The table-state object will be free.
251 */
252 static void
table_state_set(TableState * state,Table * table)253 table_state_set (TableState * state, Table * table)
254 {
255 table->name = state->name;
256 table->comment = state->comment;
257 table->visible_comment = state->visible_comment;
258 table->tagging_comment = state->tagging_comment;
259 table->border_width = state->border_width;
260 table->underline_primary_key = state->underline_primary_key;
261 table->bold_primary_key = state->bold_primary_key;
262 table->border_width = state->border_width;
263 table->attributes = state->attributes;
264
265 g_free (state);
266
267 table_update_connectionpoints (table);
268 table_update_primary_key_font (table);
269 table_compute_width_height (table);
270 table_update_positions (table);
271
272 if (table->prop_dialog)
273 gtk_list_clear_items (table->prop_dialog->attributes_list, 0, -1);
274 }
275
276 static void
table_state_free(TableState * state)277 table_state_free (TableState * state)
278 {
279 GList * list;
280
281 g_free (state->name);
282 g_free (state->comment);
283
284 list = state->attributes;
285 while (list != NULL)
286 {
287 TableAttribute * attr = (TableAttribute *) list->data;
288 table_attribute_free (attr);
289 list = g_list_next (list);
290 }
291 g_list_free (state->attributes);
292
293 g_free (state);
294 }
295
table_change_new(Table * table,TableState * saved_state,GList * added,GList * deleted,GList * disconnects)296 TableChange * table_change_new (Table * table, TableState * saved_state,
297 GList * added, GList * deleted,
298 GList * disconnects)
299 {
300 TableChange * change;
301
302 change = g_new (TableChange, 1);
303
304 change->obj_change.apply = (ObjectChangeApplyFunc) table_change_apply;
305 change->obj_change.revert = (ObjectChangeRevertFunc) table_change_revert;
306 change->obj_change.free = (ObjectChangeFreeFunc) table_change_free;
307
308 change->obj = table;
309 change->added_cp = added;
310 change->deleted_cp = deleted;
311 change->disconnected = disconnects;
312 change->applied = TRUE;
313 change->saved_state = saved_state;
314
315 return change;
316 }
317
318 /**
319 * Called to REDO a change on the table object.
320 */
321 static void
table_change_apply(TableChange * change,DiaObject * obj)322 table_change_apply (TableChange * change, DiaObject * obj)
323 {
324 TableState * old_state;
325 GList * lst;
326
327 g_print ("apply (o: 0x%08x) (c: 0x%08x)\n", GPOINTER_TO_UINT(obj), GPOINTER_TO_UINT(change));
328
329 /* first the get the current state for later use */
330 old_state = table_state_new (change->obj);
331 /* now apply the change */
332 table_state_set (change->saved_state, change->obj);
333
334 lst = change->disconnected;
335 while (lst)
336 {
337 Disconnect * dis = (Disconnect *) lst->data;
338 object_unconnect (dis->other_object, dis->other_handle);
339 lst = g_list_next (lst);
340 }
341 change->saved_state = old_state;
342 change->applied = TRUE;
343 }
344
345 /**
346 * Called to UNDO a change on the table object.
347 */
348 static void
table_change_revert(TableChange * change,DiaObject * obj)349 table_change_revert (TableChange *change, DiaObject *obj)
350 {
351 TableState *old_state;
352 GList *list;
353
354 old_state = table_state_new(change->obj);
355
356 table_state_set(change->saved_state, change->obj);
357
358 list = change->disconnected;
359 while (list) {
360 Disconnect *dis = (Disconnect *)list->data;
361
362 object_connect(dis->other_object, dis->other_handle, dis->cp);
363
364 list = g_list_next(list);
365 }
366
367 change->saved_state = old_state;
368 change->applied = FALSE;
369 }
370
371 static void
table_change_free(TableChange * change)372 table_change_free (TableChange *change)
373 {
374 GList * free_list, * lst;
375
376 table_state_free (change->saved_state);
377
378 free_list = (change->applied == TRUE)
379 ? change->deleted_cp
380 : change->added_cp;
381
382 lst = free_list;
383 while (lst)
384 {
385 ConnectionPoint * cp = (ConnectionPoint *) lst->data;
386 g_assert (cp->connected == NULL);
387 object_remove_connections_to (cp);
388 g_free (cp);
389
390 lst = g_list_next (lst);
391 }
392 g_list_free (free_list);
393 }
394
395 /* ------------------------------------------------------------------------ */
396
397 static void
general_page_props_to_object(Table * table,TablePropDialog * prop_dialog)398 general_page_props_to_object (Table * table, TablePropDialog * prop_dialog)
399 {
400 gchar * s;
401
402 /* name of the table */
403 if (table->name != NULL)
404 g_free (table->name);
405 s = (gchar *) gtk_entry_get_text (prop_dialog->table_name);
406 if (s != NULL && s[0] != '\0')
407 table->name = g_strdup (s);
408 else
409 table->name = NULL;
410
411 /* the table's comment */
412 if (table->comment != NULL)
413 g_free (table->comment);
414 s = (gchar *) get_comment (prop_dialog->table_comment);
415 if (s != NULL && s[0] != '\0')
416 table->comment = g_strdup (s);
417 else
418 table->comment = NULL;
419
420 table->visible_comment =
421 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prop_dialog->comment_visible));
422 table->tagging_comment =
423 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prop_dialog->comment_tagging));
424 table->underline_primary_key =
425 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (prop_dialog->underline_primary_key));
426 table->bold_primary_key =
427 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (prop_dialog->bold_primary_key));
428
429 table->border_width =
430 gtk_spin_button_get_value (GTK_SPIN_BUTTON (prop_dialog->border_width));
431
432 table->normal_font = dia_font_selector_get_font (prop_dialog->normal_font);
433 table->name_font = dia_font_selector_get_font (prop_dialog->name_font);
434 table->comment_font = dia_font_selector_get_font (prop_dialog->comment_font);
435
436 table->normal_font_height =
437 gtk_spin_button_get_value_as_float (prop_dialog->normal_font_height);
438 table->name_font_height =
439 gtk_spin_button_get_value_as_float (prop_dialog->name_font_height);
440 table->comment_font_height =
441 gtk_spin_button_get_value_as_float (prop_dialog->comment_font_height);
442
443 dia_color_selector_get_color (GTK_WIDGET (prop_dialog->text_color),
444 &table->text_color);
445 dia_color_selector_get_color (GTK_WIDGET (prop_dialog->line_color),
446 &table->line_color);
447 dia_color_selector_get_color (GTK_WIDGET (prop_dialog->fill_color),
448 &table->fill_color);
449 }
450
451 static void
attribute_page_props_to_object(Table * table,TablePropDialog * prop_dialog)452 attribute_page_props_to_object (Table * table, TablePropDialog * prop_dialog)
453 {
454 GList * list;
455 GList * clear_list = NULL;
456 TableAttribute * attr;
457 GtkWidget * list_item;
458 DiaObject * obj;
459 ConnectionPoint * cp;
460
461 /* if there is any currently edited item ... update its values */
462 attributes_page_update_cur_attr_item (prop_dialog);
463
464 obj = &table->element.object;
465
466 /* free current attributes */
467 list = table->attributes;
468 while (list != NULL)
469 {
470 attr = (TableAttribute *) list->data;
471 table_attribute_free (attr);
472 /* do not free the connection points they are shared by
473 * the corresponding attribute's stored in the gtklist on
474 * the attributes page
475 */
476 list = g_list_next (list);
477 }
478 g_list_free (table->attributes);
479 table->attributes = NULL;
480
481 /* insert new attributes and remove them from gtklist */
482 list = GTK_LIST (prop_dialog->attributes_list)->children;
483 while (list != NULL)
484 {
485 list_item = GTK_WIDGET (list->data);
486
487 clear_list = g_list_prepend (clear_list, list_item);
488 attr = (TableAttribute *)
489 gtk_object_get_user_data (GTK_OBJECT (list_item));
490 /* set to NULL so the attribute get's not freed when list_item is
491 destroyed */
492 gtk_object_set_user_data (GTK_OBJECT (list_item), NULL);
493 table->attributes = g_list_append (table->attributes, attr);
494
495 list = g_list_next (list);
496 }
497
498 table_update_connectionpoints (table);
499
500 if (clear_list != NULL)
501 {
502 clear_list = g_list_reverse (clear_list);
503 gtk_list_remove_items (GTK_LIST (prop_dialog->attributes_list), clear_list);
504 g_list_free (clear_list);
505 }
506
507 list = prop_dialog->deleted_connections;
508 while (list != NULL)
509 {
510 cp = (ConnectionPoint *) list->data;
511
512 table_dialog_store_disconnects (prop_dialog, cp);
513 object_remove_connections_to (cp);
514
515 list = g_list_next (list);
516 }
517 }
518
519 static void
fill_in_dialog(Table * table)520 fill_in_dialog (Table * table)
521 {
522 general_page_fill_in_dialog (table);
523 attributes_page_fill_in_dialog (table);
524 }
525
526 static void
general_page_fill_in_dialog(Table * table)527 general_page_fill_in_dialog (Table * table)
528 {
529 TablePropDialog * prop_dialog = table->prop_dialog;
530
531 if (table->name)
532 gtk_entry_set_text (prop_dialog->table_name, table->name);
533 if (table->comment)
534 set_comment (prop_dialog->table_comment, table->comment);
535 else
536 set_comment (prop_dialog->table_comment, "");
537
538 gtk_toggle_button_set_active (prop_dialog->comment_visible, table->visible_comment);
539 gtk_toggle_button_set_active (prop_dialog->comment_tagging, table->tagging_comment);
540 gtk_toggle_button_set_active (prop_dialog->underline_primary_key, table->underline_primary_key);
541 gtk_toggle_button_set_active (prop_dialog->bold_primary_key, table->bold_primary_key);
542 gtk_spin_button_set_value (prop_dialog->border_width, table->border_width);
543
544 dia_font_selector_set_font (prop_dialog->normal_font, table->normal_font);
545 dia_font_selector_set_font (prop_dialog->name_font, table->name_font);
546 dia_font_selector_set_font (prop_dialog->comment_font, table->comment_font);
547
548 dia_color_selector_set_color(GTK_WIDGET(prop_dialog->text_color), &table->text_color);
549 dia_color_selector_set_color(GTK_WIDGET(prop_dialog->line_color), &table->line_color);
550 dia_color_selector_set_color(GTK_WIDGET(prop_dialog->fill_color), &table->fill_color);
551 }
552
553 static void
attributes_page_fill_in_dialog(Table * table)554 attributes_page_fill_in_dialog (Table * table)
555 {
556 TablePropDialog * prop_dialog;
557 GList * list;
558
559 prop_dialog = table->prop_dialog;
560
561 if (prop_dialog->attributes_list->children == NULL)
562 {
563 list = table->attributes;
564 while (list != NULL)
565 {
566 TableAttribute * attr = (TableAttribute *) list->data;
567 TableAttribute * attr_copy = table_attribute_copy (attr);
568 /* see `attribute_page_props_to_object' why we take over
569 * the original connection-points instead of creating new ones.
570 */
571 attr_copy->left_connection = attr->left_connection;
572 attr_copy->right_connection = attr->right_connection;
573
574 attributes_list_add_attribute (table, attr_copy, FALSE);
575
576 list = g_list_next (list);
577 }
578
579 prop_dialog->cur_attr_list_item = NULL;
580 attributes_page_set_sensitive (prop_dialog, FALSE);
581 attributes_page_clear_values (prop_dialog);
582 }
583 }
584
585 static void
create_dialog_pages(GtkNotebook * notebook,Table * table)586 create_dialog_pages(GtkNotebook * notebook, Table * table)
587 {
588 create_general_page (notebook, table);
589 create_attribute_page (notebook, table);
590 create_style_page (notebook, table);
591 }
592
593 static void
create_attribute_page(GtkNotebook * notebook,Table * table)594 create_attribute_page (GtkNotebook * notebook, Table * table)
595 {
596 TablePropDialog * prop_dialog;
597 GtkWidget * page_label;
598 GtkWidget * vbox;
599 GtkWidget * hbox;
600 GtkWidget * scrolledwindow;
601 GtkWidget * list;
602 GtkWidget * vbox2;
603 GtkWidget * button;
604 GtkWidget * frame;
605 GtkWidget * gtk_table;
606 GtkWidget * label;
607 GtkWidget * entry;
608 GtkWidget * checkbox;
609
610 prop_dialog = table->prop_dialog;
611
612 page_label = gtk_label_new_with_mnemonic (_("_Attributes"));
613
614 vbox = gtk_vbox_new (FALSE, 5);
615 gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
616
617 hbox = gtk_hbox_new (FALSE, 5);
618 scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
619 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
620 GTK_POLICY_AUTOMATIC,
621 GTK_POLICY_AUTOMATIC);
622 gtk_box_pack_start (GTK_BOX (hbox), scrolledwindow, TRUE, TRUE, 0);
623 gtk_widget_show (scrolledwindow);
624
625 list = gtk_list_new ();
626 prop_dialog->attributes_list = GTK_LIST (list);
627 gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_SINGLE);
628 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolledwindow), list);
629 gtk_container_set_focus_vadjustment (GTK_CONTAINER (list),
630 gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolledwindow)));
631 gtk_signal_connect (GTK_OBJECT (list), "selection_changed",
632 GTK_SIGNAL_FUNC (attributes_list_selection_changed_cb),
633 table);
634 gtk_widget_show (list);
635
636 /* vbox for the button on the right side of the attributes list */
637 vbox2 = gtk_vbox_new (FALSE, 5);
638
639 /* the "new" button */
640 button = gtk_button_new_with_mnemonic (_("_New"));
641 gtk_signal_connect (GTK_OBJECT (button), "clicked",
642 GTK_SIGNAL_FUNC (attributes_list_new_button_clicked_cb),
643 table);
644 gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, TRUE, 0);
645 gtk_widget_show (button);
646
647 /* the "delete" button */
648 button = gtk_button_new_with_mnemonic (_("_Delete"));
649 gtk_signal_connect (GTK_OBJECT (button), "clicked",
650 GTK_SIGNAL_FUNC (attributes_list_delete_button_clicked_cb),
651 table);
652 gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, TRUE, 0);
653 gtk_widget_show (button);
654
655 /* the "Move up" button */
656 button = gtk_button_new_with_mnemonic (_("Move up"));
657 gtk_signal_connect (GTK_OBJECT (button), "clicked",
658 GTK_SIGNAL_FUNC (attributes_list_moveup_button_clicked_cb),
659 table);
660 gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, TRUE, 0);
661 gtk_widget_show (button);
662
663 /* the "Move down" button */
664 button = gtk_button_new_with_mnemonic (_("Move down"));
665 gtk_signal_connect (GTK_OBJECT (button), "clicked",
666 GTK_SIGNAL_FUNC (attributes_list_movedown_button_clicked_cb),
667 table);
668 gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, TRUE, 0);
669 gtk_widget_show (button);
670
671 gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, TRUE, 0);
672 gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
673
674 frame = gtk_frame_new (_("Attribute data"));
675 vbox2 = gtk_vbox_new (FALSE, 5);
676 gtk_container_set_border_width (GTK_CONTAINER (vbox2), 10);
677 gtk_container_add (GTK_CONTAINER (frame), vbox2);
678 gtk_widget_show (frame);
679 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
680
681 gtk_table = gtk_table_new (4, 2, FALSE);
682 gtk_box_pack_start (GTK_BOX (vbox2), gtk_table, FALSE, FALSE, 0);
683
684 label = gtk_label_new (_("Name:"));
685 entry = gtk_entry_new ();
686 prop_dialog->attribute_name = GTK_ENTRY (entry);
687 gtk_signal_connect (GTK_OBJECT (entry), "focus_out_event",
688 GTK_SIGNAL_FUNC (current_attribute_update_event), table);
689 gtk_signal_connect (GTK_OBJECT (entry), "activate",
690 GTK_SIGNAL_FUNC (current_attribute_update), table);
691 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
692 gtk_table_attach (GTK_TABLE (gtk_table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);
693 gtk_table_attach (GTK_TABLE (gtk_table), entry, 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 2);
694
695
696 label = gtk_label_new (_("Type:"));
697 entry = gtk_entry_new ();
698 prop_dialog->attribute_type = GTK_ENTRY (entry);
699 gtk_signal_connect (GTK_OBJECT (entry), "focus_out_event",
700 GTK_SIGNAL_FUNC (current_attribute_update_event), table);
701 gtk_signal_connect (GTK_OBJECT (entry), "activate",
702 GTK_SIGNAL_FUNC (current_attribute_update), table);
703 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
704 gtk_table_attach (GTK_TABLE (gtk_table), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
705 gtk_table_attach (GTK_TABLE (gtk_table), entry, 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, 0, 0, 2);
706
707
708 label = gtk_label_new (_("Comment:"));
709 scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
710 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
711 GTK_SHADOW_IN);
712 entry = gtk_text_view_new ();
713 prop_dialog->attribute_comment = GTK_TEXT_VIEW (entry);
714 gtk_container_add (GTK_CONTAINER (scrolledwindow), entry);
715 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (entry), GTK_WRAP_WORD);
716 gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (entry), TRUE);
717 gtk_signal_connect (GTK_OBJECT (entry), "focus_out_event",
718 GTK_SIGNAL_FUNC (current_attribute_update_event), table);
719 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
720 gtk_table_attach (GTK_TABLE (gtk_table), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0);
721 gtk_table_attach (GTK_TABLE (gtk_table), scrolledwindow, 1, 2, 2, 3, GTK_FILL | GTK_EXPAND, 0, 0, 2);
722
723 /* start a new gtk-table */
724 gtk_table = gtk_table_new (2, 2, FALSE);
725 gtk_box_pack_start (GTK_BOX (vbox2), gtk_table, FALSE, FALSE, 0);
726
727 checkbox = gtk_check_button_new_with_mnemonic (_("_Primary key"));
728 gtk_signal_connect (GTK_OBJECT (checkbox), "toggled",
729 GTK_SIGNAL_FUNC (attribute_primary_key_toggled_cb), table);
730 prop_dialog->attribute_primary_key = GTK_TOGGLE_BUTTON (checkbox);
731 gtk_table_attach (GTK_TABLE (gtk_table), checkbox, 0, 1, 0, 1,
732 GTK_FILL | GTK_EXPAND, 0, 0, 0);
733
734 checkbox = gtk_check_button_new_with_mnemonic (_("N_ullable"));
735 gtk_signal_connect (GTK_OBJECT (checkbox), "toggled",
736 GTK_SIGNAL_FUNC (attribute_nullable_toggled_cb), table);
737 prop_dialog->attribute_nullable = GTK_TOGGLE_BUTTON (checkbox);
738 gtk_table_attach (GTK_TABLE (gtk_table), checkbox, 1, 2, 0, 1,
739 GTK_FILL | GTK_EXPAND, 0, 0, 0);
740
741 checkbox = gtk_check_button_new_with_mnemonic (_("Uni_que"));
742 gtk_signal_connect (GTK_OBJECT (checkbox), "toggled",
743 GTK_SIGNAL_FUNC (attribute_unique_toggled_cb), table);
744 prop_dialog->attribute_unique = GTK_TOGGLE_BUTTON (checkbox);
745 gtk_table_attach (GTK_TABLE (gtk_table), checkbox, 1, 2, 1, 2,
746 GTK_FILL | GTK_EXPAND, 0, 0, 0);
747
748 /* show the notebook page */
749 gtk_widget_show_all (vbox);
750 gtk_widget_show (page_label);
751 gtk_notebook_append_page (notebook, vbox, page_label);
752 }
753
754 static void
attributes_page_set_sensitive(TablePropDialog * prop_dialog,gboolean val)755 attributes_page_set_sensitive (TablePropDialog * prop_dialog, gboolean val)
756 {
757 gtk_widget_set_sensitive (GTK_WIDGET (prop_dialog->attribute_name), val);
758 gtk_widget_set_sensitive (GTK_WIDGET (prop_dialog->attribute_type), val);
759 gtk_widget_set_sensitive (GTK_WIDGET (prop_dialog->attribute_comment), val);
760 gtk_widget_set_sensitive (GTK_WIDGET (prop_dialog->attribute_primary_key), val);
761 gtk_widget_set_sensitive (GTK_WIDGET (prop_dialog->attribute_nullable), val);
762 gtk_widget_set_sensitive (GTK_WIDGET (prop_dialog->attribute_unique), val);
763 }
764
765 static void
attributes_page_clear_values(TablePropDialog * prop_dialog)766 attributes_page_clear_values(TablePropDialog * prop_dialog)
767 {
768 gtk_entry_set_text(prop_dialog->attribute_name, "");
769 gtk_entry_set_text(prop_dialog->attribute_type, "");
770 set_comment(prop_dialog->attribute_comment, "");
771 gtk_toggle_button_set_active (prop_dialog->attribute_primary_key, FALSE);
772 gtk_toggle_button_set_active (prop_dialog->attribute_nullable, TRUE);
773 gtk_toggle_button_set_active (prop_dialog->attribute_unique, FALSE);
774 }
775
776 /**
777 * Copy the properties from an attribute to the attribute page.
778 */
779 static void
attributes_page_set_values(TablePropDialog * prop_dialog,TableAttribute * attr)780 attributes_page_set_values (TablePropDialog * prop_dialog, TableAttribute * attr)
781 {
782 gtk_entry_set_text (prop_dialog->attribute_name, attr->name);
783 gtk_entry_set_text (prop_dialog->attribute_type, attr->type);
784 set_comment (prop_dialog->attribute_comment, attr->comment);
785 gtk_toggle_button_set_active (prop_dialog->attribute_primary_key,
786 attr->primary_key);
787 gtk_toggle_button_set_active (prop_dialog->attribute_nullable,
788 attr->nullable);
789 gtk_toggle_button_set_active (prop_dialog->attribute_unique,
790 attr->unique);
791 }
792
793 /**
794 * Copy the properties of an attribute from the attribute page to a
795 * concrete attribute.
796 */
797 static void
attributes_page_values_to_attribute(TablePropDialog * prop_dialog,TableAttribute * attr)798 attributes_page_values_to_attribute (TablePropDialog * prop_dialog,
799 TableAttribute * attr)
800 {
801 if (attr->name) g_free (attr->name);
802 if (attr->type) g_free (attr->type);
803 if (attr->comment) g_free (attr->comment);
804
805 attr->name = g_strdup (gtk_entry_get_text (prop_dialog->attribute_name));
806 attr->type = g_strdup (gtk_entry_get_text (prop_dialog->attribute_type));
807 attr->comment = g_strdup (get_comment (prop_dialog->attribute_comment));
808 attr->primary_key = gtk_toggle_button_get_active (prop_dialog->attribute_primary_key);
809 attr->nullable = gtk_toggle_button_get_active (prop_dialog->attribute_nullable);
810 attr->unique = gtk_toggle_button_get_active (prop_dialog->attribute_unique);
811 }
812
813 /**
814 * Update the current attribute from the attributes page. This involves
815 * copying the new values into the attribute as well as updating the
816 * displayed string in the attributes listbox.
817 */
818 static void
attributes_page_update_cur_attr_item(TablePropDialog * prop_dialog)819 attributes_page_update_cur_attr_item (TablePropDialog * prop_dialog)
820 {
821 TableAttribute * attr;
822 GtkLabel * label;
823 gchar * str;
824
825 if (prop_dialog && prop_dialog->cur_attr_list_item)
826 {
827 attr = (TableAttribute *)
828 gtk_object_get_user_data (GTK_OBJECT (prop_dialog->cur_attr_list_item));
829 if (attr != NULL)
830 {
831 attributes_page_values_to_attribute (prop_dialog, attr);
832 label = GTK_LABEL (GTK_BIN (prop_dialog->cur_attr_list_item)->child);
833 str = table_get_attribute_string (attr);
834 gtk_label_set_text (label, str);
835 g_free (str);
836 }
837 }
838 }
839
840 static void
attribute_primary_key_toggled_cb(GtkToggleButton * button,Table * table)841 attribute_primary_key_toggled_cb (GtkToggleButton * button, Table * table)
842 {
843 gboolean active;
844 TablePropDialog * prop_dialog = table->prop_dialog;
845
846 active = gtk_toggle_button_get_active (prop_dialog->attribute_primary_key);
847
848 if (active)
849 {
850 gtk_toggle_button_set_active (prop_dialog->attribute_nullable, FALSE);
851 gtk_toggle_button_set_active (prop_dialog->attribute_unique, TRUE);
852 }
853 attributes_page_update_cur_attr_item (prop_dialog);
854 gtk_widget_set_sensitive (GTK_WIDGET (prop_dialog->attribute_nullable),
855 !active);
856 gtk_widget_set_sensitive (GTK_WIDGET (prop_dialog->attribute_unique),
857 !active);
858 }
859
860 static void
attribute_nullable_toggled_cb(GtkToggleButton * button,Table * table)861 attribute_nullable_toggled_cb (GtkToggleButton * button, Table * table)
862 {
863 TablePropDialog * prop_dialog = table->prop_dialog;
864
865 attributes_page_update_cur_attr_item (prop_dialog);
866 }
867
868 static void
attribute_unique_toggled_cb(GtkToggleButton * button,Table * table)869 attribute_unique_toggled_cb (GtkToggleButton * button, Table * table)
870 {
871 TablePropDialog * prop_dialog = table->prop_dialog;
872
873 attributes_page_update_cur_attr_item (prop_dialog);
874 }
875
876 static void
attributes_list_selection_changed_cb(GtkWidget * gtklist,Table * table)877 attributes_list_selection_changed_cb (GtkWidget * gtklist, Table * table)
878 {
879 TablePropDialog * prop_dialog;
880 GList * list;
881 TableAttribute * attr;
882 GtkObject * list_item;
883
884 /* Due to GtkList oddities, this may get called during destroy.
885 * But it'll reference things that are already dead and crash.
886 * Thus, we stop it before it gets that bad. See bug #156706 for
887 * one example.
888 */
889 if (table->destroyed || !table->prop_dialog)
890 return;
891
892 prop_dialog = table->prop_dialog;
893 attributes_page_update_cur_attr_item (prop_dialog);
894
895 list = GTK_LIST (gtklist)->selection;
896 if (list == NULL)
897 {
898 prop_dialog->cur_attr_list_item = NULL;
899
900 attributes_page_set_sensitive (prop_dialog, FALSE);
901 attributes_page_clear_values (prop_dialog);
902 }
903 else
904 {
905 list_item = GTK_OBJECT (list->data);
906 attr = (TableAttribute *) gtk_object_get_user_data (list_item);
907 attributes_page_set_sensitive (prop_dialog, TRUE);
908 attributes_page_set_values (prop_dialog, attr);
909
910 prop_dialog->cur_attr_list_item = GTK_LIST_ITEM (list_item);
911 gtk_widget_grab_focus (GTK_WIDGET (prop_dialog->attribute_name));
912 }
913 }
914
915 static void
create_general_page(GtkNotebook * notebook,Table * table)916 create_general_page (GtkNotebook * notebook, Table * table)
917 {
918 TablePropDialog * prop_dialog;
919 GtkWidget * page_label;
920 GtkWidget * vbox;
921 GtkWidget * gtk_table;
922 GtkWidget * label;
923 GtkWidget * entry;
924 GtkWidget * scrolled_window;
925 GtkWidget * checkbox;
926
927 prop_dialog = table->prop_dialog;
928
929 page_label = gtk_label_new_with_mnemonic (_("_Table"));
930
931 vbox = gtk_vbox_new (FALSE, 5);
932 gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
933
934 gtk_table = gtk_table_new (3, 2, FALSE);
935 gtk_box_pack_start (GTK_BOX (vbox), gtk_table, FALSE, FALSE, 0);
936
937 label = gtk_label_new (_("Table name:"));
938 entry = gtk_entry_new ();
939 prop_dialog->table_name = GTK_ENTRY (entry);
940 gtk_widget_grab_focus (entry);
941 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
942 gtk_table_attach (GTK_TABLE (gtk_table), label, 0, 1, 0, 1,
943 GTK_FILL, 0, 0, 0);
944 gtk_table_attach (GTK_TABLE (gtk_table), entry, 1, 2, 0, 1,
945 GTK_FILL | GTK_EXPAND, 0, 0, 2);
946
947 label = gtk_label_new(_("Comment:"));
948 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
949 gtk_table_attach (GTK_TABLE (gtk_table), scrolled_window, 1, 2, 2, 3,
950 (GtkAttachOptions) (GTK_FILL),
951 (GtkAttachOptions) (GTK_FILL), 0, 0);
952 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
953 GTK_SHADOW_IN);
954 entry = gtk_text_view_new ();
955 prop_dialog->table_comment = GTK_TEXT_VIEW(entry);
956 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (entry), GTK_WRAP_WORD);
957 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
958 gtk_table_attach (GTK_TABLE (gtk_table), label, 0,1,2,3, GTK_FILL,0, 0,0);
959 gtk_container_add (GTK_CONTAINER (scrolled_window), entry);
960
961 /* --- table for various checkboxes */
962 gtk_table = gtk_table_new (2, 2, TRUE);
963 gtk_box_pack_start (GTK_BOX (vbox), gtk_table, FALSE, FALSE, 0);
964
965 /* XXX create a handler and disable the 'show documentation tag' checkbox
966 if 'comment visible' is not active. */
967 checkbox = gtk_check_button_new_with_label(_("Comment visible"));
968 prop_dialog->comment_visible = GTK_TOGGLE_BUTTON(checkbox);
969 gtk_table_attach (GTK_TABLE (gtk_table), checkbox, 0, 1, 0, 1,
970 GTK_FILL, 10, 0, 0);
971
972 checkbox = gtk_check_button_new_with_label(_("Show documentation tag"));
973 prop_dialog->comment_tagging = GTK_TOGGLE_BUTTON( checkbox );
974 gtk_table_attach (GTK_TABLE (gtk_table), checkbox, 1, 2, 0, 1,
975 GTK_FILL, 10, 0, 0);
976
977 checkbox = gtk_check_button_new_with_label (_("Underline primary keys"));
978 prop_dialog->underline_primary_key = GTK_TOGGLE_BUTTON (checkbox);
979 gtk_table_attach (GTK_TABLE (gtk_table), checkbox, 0, 1, 1, 2,
980 GTK_FILL, 10, 0, 0);
981
982 checkbox = gtk_check_button_new_with_label (_("Use bold font for primary keys"));
983 prop_dialog->bold_primary_key = GTK_TOGGLE_BUTTON (checkbox);
984 gtk_table_attach (GTK_TABLE (gtk_table), checkbox, 1, 2, 1, 2,
985 GTK_FILL, 10, 0, 0);
986 /* +++ end of the table for various checkboxes */
987
988 /* finally append the created vbox to the notebook */
989 gtk_widget_show_all (vbox);
990 gtk_widget_show (page_label);
991 gtk_notebook_append_page (notebook, vbox, page_label);
992
993 }
994
995 static void
create_style_page(GtkNotebook * notebook,Table * table)996 create_style_page (GtkNotebook * notebook, Table * table)
997 {
998 TablePropDialog * prop_dialog;
999 GtkWidget * page_label;
1000 GtkWidget * vbox;
1001 GtkWidget * gtk_table;
1002 GtkWidget * label;
1003 GtkWidget * hbox;
1004 GtkWidget * text_color;
1005 GtkWidget * fill_color;
1006 GtkWidget * line_color;
1007 GtkObject * adj;
1008
1009 prop_dialog = table->prop_dialog;
1010
1011 page_label = gtk_label_new_with_mnemonic (_("_Style"));
1012
1013 vbox = gtk_vbox_new (FALSE, 5);
1014 gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
1015
1016 hbox = gtk_hbox_new (FALSE, 5);
1017 adj = gtk_adjustment_new (table->border_width, 0.00, 10.0, 0.01, 0.1, 0);
1018 prop_dialog->border_width =
1019 GTK_SPIN_BUTTON (gtk_spin_button_new (GTK_ADJUSTMENT (adj), 0.1, 2));
1020 gtk_spin_button_set_snap_to_ticks (prop_dialog->border_width, TRUE);
1021 gtk_spin_button_set_numeric (prop_dialog->border_width, TRUE);
1022 label = gtk_label_new (_("Border width:"));
1023 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
1024 gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (prop_dialog->border_width),
1025 TRUE, TRUE, 0);
1026 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
1027
1028 gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 3);
1029
1030 /* fonts */
1031 gtk_table = gtk_table_new (5, 6, TRUE);
1032 gtk_box_pack_start (GTK_BOX (vbox), gtk_table, FALSE, TRUE, 0);
1033 gtk_table_set_homogeneous (GTK_TABLE (gtk_table), FALSE);
1034
1035 label = gtk_label_new (_("Kind"));
1036 gtk_table_attach_defaults (GTK_TABLE (gtk_table), label, 0, 1, 0, 1);
1037 label = gtk_label_new (_("Font"));
1038 gtk_table_attach_defaults (GTK_TABLE (gtk_table), label, 1, 2, 0, 1);
1039 label = gtk_label_new (_("Size"));
1040 gtk_table_attach_defaults (GTK_TABLE (gtk_table), label, 2, 3, 0, 1);
1041
1042 create_font_props_row (GTK_TABLE (gtk_table), _("Normal:"), 3,
1043 table->normal_font,
1044 table->normal_font_height,
1045 &(prop_dialog->normal_font),
1046 &(prop_dialog->normal_font_height));
1047 create_font_props_row (GTK_TABLE (gtk_table), _("Name:"), 4,
1048 table->name_font,
1049 table->name_font_height,
1050 &(prop_dialog->name_font),
1051 &(prop_dialog->name_font_height));
1052 create_font_props_row (GTK_TABLE (gtk_table), _("Comment:"), 5,
1053 table->comment_font,
1054 table->comment_font_height,
1055 &(prop_dialog->comment_font),
1056 &(prop_dialog->comment_font_height));
1057
1058 gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 3);
1059
1060 /* colors */
1061 gtk_table = gtk_table_new (2, 3, TRUE);
1062 gtk_box_pack_start (GTK_BOX (vbox), gtk_table, FALSE, TRUE, 0);
1063 label = gtk_label_new(_("Text Color:"));
1064 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
1065 gtk_table_attach (GTK_TABLE (gtk_table), label, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 2);
1066 text_color = dia_color_selector_new();
1067 dia_color_selector_set_color(text_color, &table->text_color);
1068 prop_dialog->text_color = (DiaColorSelector *)text_color;
1069 gtk_table_attach (GTK_TABLE (gtk_table), text_color, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 3, 2);
1070
1071 label = gtk_label_new(_("Foreground Color:"));
1072 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
1073 gtk_table_attach (GTK_TABLE (gtk_table), label, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 2);
1074 line_color = dia_color_selector_new();
1075 dia_color_selector_set_color(line_color, &table->line_color);
1076 prop_dialog->line_color = (DiaColorSelector *)line_color;
1077 gtk_table_attach (GTK_TABLE (gtk_table), line_color, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 3, 2);
1078
1079 label = gtk_label_new(_("Background Color:"));
1080 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
1081 gtk_table_attach (GTK_TABLE (gtk_table), label, 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, 0, 0, 2);
1082 fill_color = dia_color_selector_new();
1083 dia_color_selector_set_color(fill_color, &table->fill_color);
1084 prop_dialog->fill_color = (DiaColorSelector *)fill_color;
1085 gtk_table_attach (GTK_TABLE (gtk_table), fill_color, 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 3, 2);
1086
1087 /* finally append the created vbox to the notebook */
1088 gtk_widget_show_all (vbox);
1089 gtk_widget_show (page_label);
1090 gtk_notebook_append_page (notebook, vbox, page_label);
1091 }
1092
1093 /**
1094 * pn: "Borrowed" from the source code of the UML class object.
1095 */
1096 static void
create_font_props_row(GtkTable * table,const char * kind,gint row,DiaFont * font,real height,DiaFontSelector ** fontsel,GtkSpinButton ** heightsel)1097 create_font_props_row (GtkTable *table,
1098 const char *kind,
1099 gint row,
1100 DiaFont *font,
1101 real height,
1102 DiaFontSelector **fontsel,
1103 GtkSpinButton **heightsel)
1104 {
1105 GtkWidget *label;
1106 GtkObject *adj;
1107
1108 label = gtk_label_new (kind);
1109 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1110 gtk_table_attach_defaults (table, label, 0, 1, row, row+1);
1111 *fontsel = DIAFONTSELECTOR (dia_font_selector_new ());
1112 dia_font_selector_set_font (DIAFONTSELECTOR (*fontsel), font);
1113 gtk_table_attach_defaults (GTK_TABLE (table), GTK_WIDGET(*fontsel), 1, 2, row, row+1);
1114
1115 adj = gtk_adjustment_new (height, 0.1, 10.0, 0.1, 1.0, 0);
1116 *heightsel = GTK_SPIN_BUTTON (gtk_spin_button_new (GTK_ADJUSTMENT(adj), 1.0, 2));
1117 gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (*heightsel), TRUE);
1118 gtk_table_attach_defaults (table, GTK_WIDGET (*heightsel), 2, 3, row, row+1);
1119 }
1120
1121 static void
attributes_list_new_button_clicked_cb(GtkWidget * button,Table * table)1122 attributes_list_new_button_clicked_cb (GtkWidget * button, Table * table)
1123 {
1124 TablePropDialog * prop_dialog;
1125 TableAttribute * attr;
1126
1127 prop_dialog = table->prop_dialog;
1128 attributes_page_update_cur_attr_item (prop_dialog);
1129
1130 attr = table_attribute_new ();
1131 table_attribute_ensure_connection_points (attr, &table->element.object);
1132
1133 prop_dialog->added_connections =
1134 g_list_append (prop_dialog->added_connections, attr->left_connection);
1135 prop_dialog->added_connections =
1136 g_list_append (prop_dialog->added_connections, attr->right_connection);
1137
1138 attributes_list_add_attribute (table, attr, TRUE);
1139 }
1140
1141 /**
1142 * Add the passed attribute into the listbox of attributes. The passed
1143 * attribute should be a copy of the original attribute as it will be
1144 * freed when destroying the attribute listbox. If SELECT is TRUE the
1145 * new list item is selected.
1146 */
1147 static void
attributes_list_add_attribute(Table * table,TableAttribute * attribute,gboolean select)1148 attributes_list_add_attribute (Table * table,
1149 TableAttribute * attribute,
1150 gboolean select)
1151 {
1152 TablePropDialog * prop_dialog;
1153 gchar * attrstr;
1154 GtkWidget * list_item;
1155 GList * list;
1156
1157 prop_dialog = table->prop_dialog;
1158
1159 attrstr = table_get_attribute_string (attribute);
1160 list_item = gtk_list_item_new_with_label (attrstr);
1161 gtk_widget_show (list_item);
1162 g_free (attrstr);
1163
1164 gtk_object_set_user_data (GTK_OBJECT (list_item), attribute);
1165 gtk_signal_connect (GTK_OBJECT (list_item), "destroy",
1166 GTK_SIGNAL_FUNC (attribute_list_item_destroy_cb),
1167 NULL);
1168 list = g_list_append (NULL, list_item);
1169 gtk_list_append_items (prop_dialog->attributes_list, list);
1170 if (select)
1171 {
1172 if (prop_dialog->attributes_list->children != NULL)
1173 gtk_list_unselect_child (prop_dialog->attributes_list,
1174 GTK_WIDGET (prop_dialog->attributes_list->children->data));
1175 gtk_list_select_child (prop_dialog->attributes_list, list_item);
1176 }
1177 }
1178
1179 static void
current_attribute_update(GtkWidget * unused,Table * table)1180 current_attribute_update (GtkWidget * unused, Table * table)
1181 {
1182 attributes_page_update_cur_attr_item (table->prop_dialog);
1183 }
1184
1185 static int
current_attribute_update_event(GtkWidget * unused,GdkEventFocus * unused2,Table * table)1186 current_attribute_update_event (GtkWidget * unused,
1187 GdkEventFocus *unused2,
1188 Table * table)
1189 {
1190 attributes_page_update_cur_attr_item (table->prop_dialog);
1191 return 0;
1192 }
1193
1194
1195 static void
attributes_list_delete_button_clicked_cb(GtkWidget * button,Table * table)1196 attributes_list_delete_button_clicked_cb (GtkWidget * button, Table * table)
1197 {
1198 GList * list;
1199 GtkList * gtklist;
1200 TablePropDialog * prop_dialog;
1201 TableAttribute * attr;
1202
1203 prop_dialog = table->prop_dialog;
1204 gtklist = GTK_LIST (prop_dialog->attributes_list);
1205
1206 if (gtklist->selection != NULL)
1207 {
1208 attr = (TableAttribute *)
1209 gtk_object_get_user_data (GTK_OBJECT (gtklist->selection->data));
1210 prop_dialog->deleted_connections =
1211 g_list_prepend (prop_dialog->deleted_connections,
1212 attr->left_connection);
1213 prop_dialog->deleted_connections =
1214 g_list_prepend (prop_dialog->deleted_connections,
1215 attr->right_connection);
1216
1217 list = g_list_append (NULL, gtklist->selection->data);
1218 gtk_list_remove_items (gtklist, list);
1219 g_list_free (list);
1220 attributes_page_clear_values (prop_dialog);
1221 attributes_page_set_sensitive (prop_dialog, FALSE);
1222 }
1223 }
1224
1225 static void
attributes_list_moveup_button_clicked_cb(GtkWidget * button,Table * table)1226 attributes_list_moveup_button_clicked_cb (GtkWidget * button, Table * table)
1227 {
1228 TablePropDialog * prop_dialog;
1229 GtkList * gtklist;
1230 GList * list;
1231 GtkWidget * list_item;
1232 gint i;
1233
1234 prop_dialog = table->prop_dialog;
1235 gtklist = GTK_LIST (prop_dialog->attributes_list);
1236
1237 if (gtklist->selection != NULL)
1238 {
1239 list_item = GTK_WIDGET (gtklist->selection->data);
1240
1241 i = gtk_list_child_position (gtklist, list_item);
1242 if (i > 0)
1243 {
1244 i--;
1245
1246 gtk_widget_ref (list_item);
1247 list = g_list_prepend (NULL, list_item);
1248 gtk_list_remove_items (gtklist, list);
1249 gtk_list_insert_items (gtklist, list, i);
1250 gtk_widget_unref (list_item);
1251
1252 gtk_list_select_child (gtklist, list_item);
1253 }
1254 }
1255 }
1256
1257 static void
attributes_list_movedown_button_clicked_cb(GtkWidget * button,Table * table)1258 attributes_list_movedown_button_clicked_cb (GtkWidget * button, Table * table)
1259 {
1260 TablePropDialog * prop_dialog;
1261 GtkList * gtklist;
1262 GList * list;
1263 GtkWidget * list_item;
1264 gint i;
1265
1266 prop_dialog = table->prop_dialog;
1267 gtklist = GTK_LIST (prop_dialog->attributes_list);
1268
1269 if (gtklist->selection != NULL)
1270 {
1271 list_item = GTK_WIDGET (gtklist->selection->data);
1272
1273 i = gtk_list_child_position (gtklist, list_item);
1274 if (i < (g_list_length (gtklist->children) - 1))
1275 {
1276 i++;
1277
1278 gtk_widget_ref (list_item);
1279 list = g_list_prepend (NULL, list_item);
1280 gtk_list_remove_items (gtklist, list);
1281 gtk_list_insert_items (gtklist, list, i);
1282 gtk_widget_unref (list_item);
1283
1284 gtk_list_select_child (gtklist, list_item);
1285 }
1286 }
1287 }
1288
1289 static void
attribute_list_item_destroy_cb(GtkWidget * list_item,gpointer data)1290 attribute_list_item_destroy_cb (GtkWidget * list_item, gpointer data)
1291 {
1292 TableAttribute * attr;
1293
1294 attr = (TableAttribute *) gtk_object_get_user_data (GTK_OBJECT (list_item));
1295 if (attr != NULL)
1296 table_attribute_free (attr);
1297 }
1298
1299 static void
destroy_prop_dialog(GtkWidget * widget,gpointer user_data)1300 destroy_prop_dialog (GtkWidget *widget, gpointer user_data)
1301 {
1302 Table * table = (Table *) user_data;
1303
1304 g_free (table->prop_dialog);
1305 table->prop_dialog = NULL;
1306 }
1307
1308 /*
1309 * pn: borrowed from the source code of the UML class.
1310 *
1311 * get the contents of a comment text view.
1312 */
get_comment(GtkTextView * view)1313 const gchar * get_comment(GtkTextView *view)
1314 {
1315 GtkTextBuffer * buffer = gtk_text_view_get_buffer(view);
1316 GtkTextIter start;
1317 GtkTextIter end;
1318
1319 gtk_text_buffer_get_start_iter(buffer, &start);
1320 gtk_text_buffer_get_end_iter(buffer, &end);
1321
1322 return gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
1323 }
1324
1325 /*
1326 * pn: "borrowed" from the source code for the UML class.
1327 */
1328 static void
set_comment(GtkTextView * view,gchar * text)1329 set_comment(GtkTextView *view, gchar *text)
1330 {
1331 GtkTextBuffer * buffer = gtk_text_view_get_buffer(view);
1332 GtkTextIter start;
1333 GtkTextIter end;
1334
1335 gtk_text_buffer_get_start_iter(buffer, &start);
1336 gtk_text_buffer_get_end_iter(buffer, &end);
1337 gtk_text_buffer_delete(buffer,&start,&end);
1338 gtk_text_buffer_get_start_iter(buffer, &start);
1339 gtk_text_buffer_insert( buffer, &start, text, strlen(text));
1340 }
1341
1342 /**
1343 * pn: "borrowed" from the source code for the UML class object.
1344 */
1345 static void
table_dialog_store_disconnects(TablePropDialog * prop_dialog,ConnectionPoint * cp)1346 table_dialog_store_disconnects (TablePropDialog * prop_dialog,
1347 ConnectionPoint * cp)
1348 {
1349 Disconnect *dis;
1350 DiaObject *connected_obj;
1351 GList *list;
1352 gint i;
1353
1354 list = cp->connected;
1355 while (list != NULL) {
1356 connected_obj = (DiaObject *)list->data;
1357
1358 for (i=0;i<connected_obj->num_handles;i++) {
1359 if (connected_obj->handles[i]->connected_to == cp) {
1360 dis = g_new0(Disconnect, 1);
1361 dis->cp = cp;
1362 dis->other_object = connected_obj;
1363 dis->other_handle = connected_obj->handles[i];
1364
1365 prop_dialog->disconnected_connections =
1366 g_list_prepend(prop_dialog->disconnected_connections, dis);
1367 }
1368 }
1369 list = g_list_next(list);
1370 }
1371 }
1372
1373
1374 /**
1375 * Return the string representation of the passed attribute to be
1376 * rendered. The returned string is allocated in memory and its the
1377 * caller's responsibility to free this memory if it's not needed
1378 * anymore.
1379 */
1380 static gchar *
table_get_attribute_string(TableAttribute * attrib)1381 table_get_attribute_string (TableAttribute * attrib)
1382 {
1383 int len = 2; /* two chars at the beginning */
1384 gchar * not_null_str = _("not null");
1385 gchar * null_str = _("null");
1386 gchar * is_unique_str = _("unique");
1387 gchar * str = NULL;
1388 gchar * strp = NULL;
1389 gboolean is_nullable = attrib->nullable;
1390 gboolean is_unique = attrib->unique;
1391
1392 /* first compute how much we need to allocate */
1393
1394 if (IS_NOT_EMPTY (attrib->name))
1395 len += strlen (attrib->name);
1396 if (IS_NOT_EMPTY (attrib->type))
1397 {
1398 len += strlen (attrib->type);
1399 len += 2; /* comma and a blank between the type and "nullable" */
1400 }
1401 len += strlen (is_nullable ? null_str : not_null_str);
1402 if (IS_NOT_EMPTY (attrib->name))
1403 len += 2; /* colon and a blank after the name */
1404 if (is_unique)
1405 {
1406 len += 2; /* command and a blank */
1407 len += strlen (is_unique_str);
1408 }
1409
1410 /* now create the string */
1411
1412 /* add one gchar for the null termaintor */
1413 strp = str = g_malloc (sizeof(gchar) * (len + 1));
1414 strp = g_stpcpy (strp, (attrib->primary_key == TRUE) ? "# " : " ");
1415 if (IS_NOT_EMPTY (attrib->name))
1416 {
1417 strp = g_stpcpy (strp, attrib->name);
1418 strp = g_stpcpy (strp, ": ");
1419 }
1420 if (IS_NOT_EMPTY (attrib->type))
1421 {
1422 strp = g_stpcpy (strp, attrib->type);
1423 strp = g_stpcpy (strp, ", ");
1424 }
1425 strp = g_stpcpy (strp, is_nullable ? null_str : not_null_str);
1426 if (is_unique)
1427 {
1428 strp = g_stpcpy (strp, ", ");
1429 strp = g_stpcpy (strp, is_unique_str);
1430 }
1431
1432 g_assert (strlen (str) == len);
1433
1434 return str;
1435 }
1436