1 /* Copyright (C) 2002-2003, Luca Padovani <luca.padovani@cs.unibo.it>,
2 * 2003, Paolo Marinelli <pmarinel@cs.unibo.it>.
4 * This file is part of EdiTeX, an editor of mathematical
5 * expressions based on TeX syntax
7 * EdiTeX is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * EdiTeX is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with EdiTeX; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * For details, see the EdiTeX World-Wide-Web page,
22 * http://helm.cs.unibo.it/editex, or send a mail to
23 * <luca.padovani@cs.unibo.it>
26 * Copyright (C) 2000, Luca Padovani <luca.padovani@cs.unibo.it>.
28 * This file is part of GtkMathView, a Gtk widget for MathML.
30 * GtkMathView is free software; you can redistribute it and/or
31 * modify it under the terms of the GNU General Public License
32 * as published by the Free Software Foundation; either version 2
33 * of the License, or (at your option) any later version.
35 * GtkMathView is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
40 * You should have received a copy of the GNU General Public License
41 * along with GtkMathView; if not, write to the Free Software
42 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
44 * For details, see the GtkMathView World-Wide-Web page,
45 * http://cs.unibo.it/~lpadovan/mml-widget, or send a mail to
46 * <luca.padovani@cs.unibo.it>
52 #include <gdk/gdkkeysyms.h>
54 #include <gtkmathview/gtkmathview.h>
57 #define XLINK_NS_URI "http://www.w3.org/1999/xlink"
59 static GtkWidget* window;
60 static GtkWidget* main_area;
61 static GtkWidget* scrolled_area;
62 static GtkMenuItem* anti_aliasing_item;
63 static GtkMenuItem* transparency_item;
65 static gpointer context = NULL;
66 static gchar* doc_name = NULL;
67 static GdomeElement* first_selected = NULL;
68 static GdomeElement* root_selected = NULL;
70 static void create_widget_set(gpointer);
71 static GtkWidget* get_main_menu(void);
72 static void file_open(GtkWidget*, gpointer);
73 static void file_re_open(GtkWidget*, gpointer);
74 static void file_close(GtkWidget*, gpointer);
75 static void file_output_tex(GtkWidget*, gpointer);
76 static void options_font_manager(GtkWidget*, FontManagerId);
77 static void options_set_font_size(GtkWidget*, gpointer);
78 static void options_change_font_size(GtkWidget*, gboolean);
79 static void options_verbosity(GtkWidget*, guint);
80 static void options_anti_aliasing(GtkWidget*, gpointer);
81 static void options_transparency(GtkWidget*, gpointer);
82 static void edit_delete_selection(GtkWidget*, gpointer);
83 static void edit_select_parent(GtkWidget*, gpointer);
84 static void edit_reset_selection(GtkWidget*, gpointer);
85 static void edit_reset(GtkWidget*, gpointer);
86 static void edit_insert(GtkWidget*, gpointer);
87 static void help_about(GtkWidget*, gpointer);
89 static GtkItemFactoryEntry menu_items[] = {
90 { "/_File", NULL, NULL, 0, "<Branch>" },
91 { "/File/_Open...", "<control>O", file_open, 0, NULL },
92 { "/File/_Reopen", NULL, file_re_open, 0, NULL },
93 { "/File/_Close", "<control>W", file_close, 0, NULL },
94 { "/File/Output _TeX", NULL, file_output_tex, 0, NULL },
95 { "/File/sep1", NULL, NULL, 0, "<Separator>" },
96 { "/File/_Quit", "<control>Q", gtk_main_quit, 0, NULL },
98 { "/_Edit", NULL, NULL, 0, "<Branch>" },
99 { "/Edit/Reset Selection", NULL, edit_reset_selection, 0, NULL },
100 { "/Edit/Delete Selection", NULL, edit_delete_selection, 0, NULL },
101 { "/Edit/Select Parent", NULL, edit_select_parent, 0, NULL },
102 { "/Edit/sep1", NULL, NULL, 0, "<Separator>" },
103 { "/Edit/_Reset", NULL, edit_reset, 0, NULL },
104 { "/Edit/Insert...", "<control>I", edit_insert, 0, NULL },
106 { "/_Options", NULL, NULL, 0, "<Branch>" },
107 { "/Options/Default _Font Size", NULL, NULL, 0, "<Branch>" },
108 { "/Options/Default Font Size/Set...", NULL, options_set_font_size, 0, NULL },
109 { "/Options/Default Font Size/sep1", NULL, NULL, 0, "<Separator>" },
110 { "/Options/Default Font Size/Larger", NULL, options_change_font_size, TRUE, NULL },
111 { "/Options/Default Font Size/Smaller", NULL, options_change_font_size, FALSE, NULL },
112 { "/Options/Font Manager", NULL, NULL, 0, "<Branch>" },
113 { "/Options/Font Manager/_GTK", NULL, options_font_manager, FONT_MANAGER_GTK, "<RadioItem>" },
114 { "/Options/Font Manager/_Type 1", NULL, options_font_manager, FONT_MANAGER_T1, "/Options/Font Manager/GTK" },
115 { "/Options/Verbosity", NULL, NULL, 0, "<Branch>" },
116 { "/Options/Verbosity/_Errors", NULL, options_verbosity, 0, "<RadioItem>" },
117 { "/Options/Verbosity/_Warnings", NULL, options_verbosity, 1, "/Options/Verbosity/Errors" },
118 { "/Options/Verbosity/_Info", NULL, options_verbosity, 2, "/Options/Verbosity/Errors" },
119 { "/Options/Verbosity/_Debug", NULL, options_verbosity, 3, "/Options/Verbosity/Errors" },
120 { "/Options/sep1", NULL, NULL, 0, "<Separator>" },
121 { "/Options/_Anti Aliasing", NULL, options_anti_aliasing, 0, "<ToggleItem>" },
122 { "/Options/_Transparency", NULL, options_transparency, 0, "<ToggleItem>" },
124 { "/_Help" , NULL, NULL, 0, "<LastBranch>" },
125 { "/Help/About...", NULL, help_about, 0, NULL }
129 quick_message(const char* msg)
133 GtkWidget* okay_button;
135 /* Create the widgets */
137 dialog = gtk_dialog_new();
138 label = gtk_label_new (msg);
139 okay_button = gtk_button_new_with_label("OK");
141 gtk_widget_set_usize(dialog, 300, 100);
143 /* Ensure that the dialog box is destroyed when the user clicks ok. */
145 gtk_signal_connect_object (GTK_OBJECT (okay_button), "clicked",
146 GTK_SIGNAL_FUNC (gtk_widget_destroy), dialog);
147 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area),
150 /* Add the label, and show everything we've added to the dialog. */
152 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
153 gtk_widget_show_all (dialog);
157 load_error_msg(const char* name)
159 char* msg = g_strdup_printf("Could not load\n`%s'", name);
164 static guint edit_timeout_id;
165 extern void edit_timeout(gpointer);
168 GUI_init(int* argc, char*** argv, char* title, guint width, guint height, gpointer c)
170 gtk_init(argc, argv);
172 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
173 gtk_window_set_title(GTK_WINDOW(window), title);
174 gtk_window_set_default_size(GTK_WINDOW(window), width, height);
175 gtk_signal_connect(GTK_OBJECT(window), "delete_event", (GtkSignalFunc) gtk_main_quit, NULL);
176 create_widget_set(context);
178 gtk_widget_show(window);
181 /*edit_timeout_id = gtk_timeout_add(50, edit_timeout, context);*/
187 GdomeException exc = 0;
189 if (first_selected != NULL)
191 gdome_el_unref(first_selected, &exc);
193 first_selected = NULL;
196 if (root_selected != NULL)
198 gdome_el_unref(root_selected, &exc);
200 root_selected = NULL;
207 GUI_load_document(GdomeDocument* doc)
209 GtkMathView* math_view;
211 g_return_val_if_fail(doc != NULL, -1);
212 g_return_val_if_fail(main_area != NULL, -1);
213 g_return_val_if_fail(GTK_IS_MATH_VIEW(main_area), -1);
215 math_view = GTK_MATH_VIEW(main_area);
217 if (!gtk_math_view_load_doc(math_view, doc)) return -1;
225 gtk_math_view_freeze(GTK_MATH_VIEW(main_area));
231 gtk_math_view_thaw(GTK_MATH_VIEW(main_area));
235 GUI_unload_document()
237 GtkMathView* math_view;
239 g_return_if_fail(main_area != NULL);
240 g_return_if_fail(GTK_IS_MATH_VIEW(main_area));
242 math_view = GTK_MATH_VIEW(main_area);
244 gtk_math_view_unload(math_view);
246 if (doc_name != NULL) g_free(doc_name);
257 GUI_set_font_manager(FontManagerId id)
260 GtkMathView* math_view;
262 g_return_if_fail(id != FONT_MANAGER_UNKNOWN);
263 g_return_if_fail(main_area != NULL);
264 g_return_if_fail(GTK_IS_MATH_VIEW(main_area));
266 t1 = id == FONT_MANAGER_T1;
268 math_view = GTK_MATH_VIEW(main_area);
270 gtk_math_view_freeze(math_view);
272 if (id != gtk_math_view_get_font_manager_type(math_view))
273 gtk_math_view_set_font_manager_type(math_view, id);
275 gtk_widget_set_sensitive(anti_aliasing_item, t1);
276 gtk_widget_set_sensitive(transparency_item, t1);
280 gtk_math_view_set_anti_aliasing(math_view, GTK_CHECK_MENU_ITEM(anti_aliasing_item)->active);
281 gtk_math_view_set_transparency(math_view, GTK_CHECK_MENU_ITEM(transparency_item)->active);
284 gtk_math_view_thaw(math_view);
288 store_filename(GtkFileSelection* selector, GtkWidget* user_data)
290 gchar* selected_filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION(user_data));
291 if (selected_filename != NULL)
292 GUI_load_document(selected_filename);
296 file_close(GtkWidget* widget, gpointer data)
298 GUI_unload_document();
302 file_re_open(GtkWidget* widget, gpointer data)
304 if (doc_name != NULL) {
305 GUI_load_document(doc_name);
310 file_open(GtkWidget* widget, gpointer data)
312 GtkWidget* fs = gtk_file_selection_new("Open File");
314 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button),
315 "clicked", GTK_SIGNAL_FUNC (store_filename), (gpointer) fs);
317 /* Ensure that the dialog box is destroyed when the user clicks a button. */
319 gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button),
320 "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
323 gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION(fs)->cancel_button),
324 "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
327 /* Display that dialog */
329 gtk_widget_show (fs);
333 file_output_tex(GtkWidget* widget, gpointer data)
335 g_assert(context != NULL);
336 edit_output_tex(context);
340 options_font_manager(GtkWidget* widget, FontManagerId id)
342 g_return_if_fail(id != FONT_MANAGER_UNKNOWN);
343 GUI_set_font_manager(id);
347 options_anti_aliasing(GtkWidget* widget, gpointer data)
349 gboolean aa = gtk_math_view_get_anti_aliasing(GTK_MATH_VIEW(main_area));
350 gtk_math_view_set_anti_aliasing(GTK_MATH_VIEW(main_area), !aa);
354 options_transparency(GtkWidget* widget, gpointer data)
356 gboolean t = gtk_math_view_get_transparency(GTK_MATH_VIEW(main_area));
357 gtk_math_view_set_transparency(GTK_MATH_VIEW(main_area), !t);
361 options_verbosity(GtkWidget* widget, guint level)
363 gtk_math_view_set_log_verbosity(GTK_MATH_VIEW(main_area), level);
367 edit_delete_selection(GtkWidget* widget, gpointer data)
369 if (root_selected != NULL)
372 gtk_math_view_freeze(GTK_MATH_VIEW(main_area));
373 printf("about to remove element %p\n", root_selected);
374 delete_element(root_selected);
375 gdome_el_unref(root_selected, &exc);
377 root_selected = NULL;
378 gtk_math_view_thaw(GTK_MATH_VIEW(main_area));
383 edit_select_parent(GtkWidget* widget, gpointer data)
385 if (root_selected != NULL)
387 GdomeException exc = 0;
388 GdomeElement* parent = gdome_n_parentNode(root_selected, &exc);
390 gdome_el_unref(root_selected, &exc);
392 root_selected = parent;
393 /* gtk_math_view_set_selection(GTK_MATH_VIEW(main_area), root_selected); */
398 edit_reset_selection(GtkWidget* widget, gpointer data)
400 if (root_selected != NULL)
402 GdomeException exc = 0;
403 /* gtk_math_view_reset_selection(GTK_MATH_VIEW(main_area), root_selected); */
404 gdome_el_unref(root_selected, &exc);
406 root_selected = NULL;
411 edit_reset(GtkWidget* widget, gpointer data)
413 g_assert(context != NULL);
414 edit_reset_tex(context);
418 insert_tex(GtkWidget* widget, GtkEntry* entry)
421 g_return_if_fail(entry != NULL);
423 text = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
424 edit_push_string(context, text);
429 edit_insert(GtkWidget* widget, gpointer data)
436 dialog = gtk_dialog_new();
437 entry = gtk_entry_new();
438 ok = gtk_button_new_with_label("OK");
439 cancel = gtk_button_new_with_label("Cancel");
441 gtk_signal_connect (GTK_OBJECT (ok), "clicked",
442 GTK_SIGNAL_FUNC (insert_tex), (gpointer) entry);
444 gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
445 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
447 gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
448 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
450 gtk_signal_connect_object (GTK_OBJECT (cancel), "clicked",
451 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
453 gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), 5);
455 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), entry);
456 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), ok);
457 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), cancel);
459 gtk_widget_show_all (dialog);
463 help_about(GtkWidget* widget, gpointer data)
469 dialog = gtk_dialog_new();
470 label = gtk_label_new("\n MathML Editor \n Copyright (C) 2003 Luca Padovani \n");
471 ok = gtk_button_new_with_label("Close");
473 gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
474 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
475 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area),
478 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
480 gtk_widget_show_all (dialog);
484 change_default_font_size(GtkWidget* widget, GtkSpinButton* spin)
486 g_return_if_fail(spin != NULL);
487 gtk_math_view_set_font_size( GTK_MATH_VIEW(main_area), gtk_spin_button_get_value_as_int(spin));
491 options_change_font_size(GtkWidget* widget, gboolean larger)
493 gfloat size = gtk_math_view_get_font_size (GTK_MATH_VIEW(main_area));
494 if (larger) size = size / 0.71;
495 else size = size * 0.71;
496 if (size < 1) size = 1;
497 gtk_math_view_set_font_size (GTK_MATH_VIEW(main_area), (gint) size + 0.5);
501 options_set_font_size(GtkWidget* widget, gpointer data)
510 dialog = gtk_dialog_new();
511 label = gtk_label_new("Default font size:");
512 ok = gtk_button_new_with_label("OK");
513 cancel = gtk_button_new_with_label("Cancel");
515 adj = gtk_adjustment_new (gtk_math_view_get_font_size (GTK_MATH_VIEW(main_area)), 1, 200, 1, 1, 1);
516 spin = gtk_spin_button_new (GTK_ADJUSTMENT(adj), 1, 0);
517 gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin), TRUE);
519 gtk_signal_connect (GTK_OBJECT (ok), "clicked",
520 GTK_SIGNAL_FUNC (change_default_font_size), (gpointer) spin);
522 gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
523 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
525 gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
526 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
528 gtk_signal_connect_object (GTK_OBJECT (cancel), "clicked",
529 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
531 gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), 5);
533 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), ok);
534 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), cancel);
535 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
536 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), spin);
538 gtk_widget_show_all (dialog);
542 select_begin(GtkMathView* math_view, GdomeElement* first, gint state)
544 GdomeException exc = 0;
546 g_return_if_fail(math_view != NULL);
547 g_return_if_fail(GTK_IS_MATH_VIEW(math_view));
548 g_return_if_fail(first != NULL);
550 gtk_math_view_freeze(math_view);
552 if (root_selected != NULL)
554 gtk_math_view_unselect(math_view, root_selected);
555 gdome_el_unref(root_selected, &exc);
559 root_selected = first_selected = find_element_with_ref(first);
561 if (root_selected != NULL)
563 gtk_math_view_select(math_view, root_selected);
564 gdome_el_ref(root_selected, &exc);
568 gtk_math_view_thaw(math_view);
572 select_over(GtkMathView* math_view, GdomeElement* elem, gint state)
574 GdomeElement* new_selected = NULL;
575 GdomeException exc = 0;
577 g_return_if_fail(math_view != NULL);
578 g_return_if_fail(GTK_IS_MATH_VIEW(math_view));
579 g_return_if_fail(elem != NULL);
581 if (first_selected == NULL || elem == NULL)
584 new_selected = find_common_ancestor_with_ref(first_selected, elem);
586 if (new_selected != root_selected)
588 gtk_math_view_freeze(math_view);
589 if (root_selected != NULL)
591 gtk_math_view_unselect(math_view, root_selected);
592 gdome_el_unref(root_selected, &exc);
595 root_selected = new_selected;
596 if (root_selected != NULL)
597 gtk_math_view_select(math_view, root_selected);
598 gtk_math_view_thaw(math_view);
600 else if (new_selected != NULL)
602 gdome_el_unref(new_selected, &exc);
609 key_press_event(gpointer c,
613 g_return_val_if_fail(widget != NULL, FALSE);
614 g_return_val_if_fail(event != NULL, FALSE);
615 g_return_val_if_fail(context != NULL, FALSE);
617 if (event->type != GDK_KEY_PRESS) return FALSE;
619 switch (event->keyval)
622 edit_drop(context, event->state & GDK_MOD1_MASK);
625 if ((event->state & (~GDK_SHIFT_MASK)) == 0 && event->keyval < 0x80)
626 edit_push_char(context, event->keyval);
634 create_widget_set(gpointer context)
636 GtkWidget* main_vbox;
639 main_vbox = gtk_vbox_new(FALSE, 1);
640 gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
641 gtk_container_add(GTK_CONTAINER(window), main_vbox);
642 gtk_widget_show(main_vbox);
644 menu_bar = get_main_menu();
645 gtk_box_pack_start(GTK_BOX(main_vbox), menu_bar, FALSE, TRUE, 0);
646 gtk_widget_show(menu_bar);
648 main_area = gtk_math_view_new(NULL, NULL);
649 gtk_widget_show(main_area);
651 //gtk_math_view_set_log_verbosity(GTK_MATH_VIEW(main_area), 3);
653 gtk_signal_connect_object (GTK_OBJECT (main_area),
654 "select_begin", GTK_SIGNAL_FUNC (select_begin),
655 (gpointer) main_area);
657 gtk_signal_connect_object (GTK_OBJECT (main_area),
658 "select_over", GTK_SIGNAL_FUNC (select_over),
659 (gpointer) main_area);
661 gtk_signal_connect_object (GTK_OBJECT(window),
662 "key_press_event", GTK_SIGNAL_FUNC(key_press_event),
665 gtk_widget_add_events(GTK_WIDGET(main_area), GDK_KEY_PRESS_MASK);
667 scrolled_area = gtk_scrolled_window_new(NULL, NULL);
668 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_area),
669 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
671 gtk_widget_show(scrolled_area);
672 gtk_container_add(GTK_CONTAINER(scrolled_area), main_area);
673 gtk_box_pack_start(GTK_BOX(main_vbox), scrolled_area, TRUE, TRUE, 0);
675 gtk_widget_show(main_vbox);
677 if (gtk_math_view_get_anti_aliasing(GTK_MATH_VIEW(main_area)))
678 gtk_menu_item_activate(anti_aliasing_item);
684 GtkItemFactory* item_factory;
685 GtkAccelGroup* accel_group;
686 GtkWidget* menu_item;
688 gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
690 accel_group = gtk_accel_group_new();
692 item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
694 gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, NULL);
696 gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
698 menu_item = gtk_item_factory_get_widget(item_factory, "/Options/Anti Aliasing");
699 anti_aliasing_item = GTK_MENU_ITEM(menu_item);
701 menu_item = gtk_item_factory_get_widget(item_factory, "/Options/Transparency");
702 transparency_item = GTK_MENU_ITEM(menu_item);
704 return gtk_item_factory_get_widget(item_factory, "<main>");