1 /* This file is part of EdiTeX, an editor of mathematical
2 * expressions based on TeX syntax.
4 * Copyright (C) 2002-2003 Luca Padovani <lpadovan@cs.unibo.it>,
5 * 2003 Paolo Marinelli <pmarinel@cs.unibo.it>.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library 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 GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * For more information, please visit the project's home page
22 * http://helm.cs.unibo.it/editex/
23 * or send an email to <lpadovan@cs.unibo.it>
29 #include <gdk/gdkkeysyms.h>
33 #define XLINK_NS_URI "http://www.w3.org/1999/xlink"
35 static GtkWidget* window;
36 static GtkWidget* main_area;
37 static GtkWidget* scrolled_area;
39 static gpointer context = NULL;
40 static gchar* doc_name = NULL;
41 static GdomeElement* first_selected = NULL;
42 static GdomeElement* root_selected = NULL;
44 static void create_widget_set(gpointer);
45 static GtkWidget* get_main_menu(void);
46 static void file_open(GtkWidget*, gpointer);
47 static void file_re_open(GtkWidget*, gpointer);
48 static void file_close(GtkWidget*, gpointer);
49 static void file_output_tex(GtkWidget*, gpointer);
50 static void options_set_font_size(GtkWidget*, gpointer);
51 static void options_change_font_size(GtkWidget*, gboolean);
52 static void options_verbosity(GtkWidget*, guint);
53 static void edit_delete_selection(GtkWidget*, gpointer);
54 static void edit_select_parent(GtkWidget*, gpointer);
55 static void edit_reset_selection(GtkWidget*, gpointer);
56 static void edit_reset(GtkWidget*, gpointer);
57 static void edit_insert(GtkWidget*, gpointer);
58 static void help_about(GtkWidget*, gpointer);
60 static GtkItemFactoryEntry menu_items[] = {
61 { "/_File", NULL, NULL, 0, "<Branch>" },
62 { "/File/_Open...", "<control>O", file_open, 0, NULL },
63 { "/File/_Reopen", NULL, file_re_open, 0, NULL },
64 { "/File/_Close", "<control>W", file_close, 0, NULL },
65 { "/File/Output _TeX", NULL, file_output_tex, 0, NULL },
66 { "/File/sep1", NULL, NULL, 0, "<Separator>" },
67 { "/File/_Quit", "<control>Q", gtk_main_quit, 0, NULL },
69 { "/_Edit", NULL, NULL, 0, "<Branch>" },
70 { "/Edit/Reset Selection", NULL, edit_reset_selection, 0, NULL },
71 { "/Edit/Delete Selection", NULL, edit_delete_selection, 0, NULL },
72 { "/Edit/Select Parent", NULL, edit_select_parent, 0, NULL },
73 { "/Edit/sep1", NULL, NULL, 0, "<Separator>" },
74 { "/Edit/_Reset", NULL, edit_reset, 0, NULL },
75 { "/Edit/Insert...", "<control>I", edit_insert, 0, NULL },
77 { "/_Options", NULL, NULL, 0, "<Branch>" },
78 { "/Options/Default _Font Size", NULL, NULL, 0, "<Branch>" },
79 { "/Options/Default Font Size/Set...", NULL, options_set_font_size, 0, NULL },
80 { "/Options/Default Font Size/sep1", NULL, NULL, 0, "<Separator>" },
81 { "/Options/Default Font Size/Larger", NULL, options_change_font_size, TRUE, NULL },
82 { "/Options/Default Font Size/Smaller", NULL, options_change_font_size, FALSE, NULL },
83 { "/Options/Verbosity", NULL, NULL, 0, "<Branch>" },
84 { "/Options/Verbosity/_Errors", NULL, options_verbosity, 0, "<RadioItem>" },
85 { "/Options/Verbosity/_Warnings", NULL, options_verbosity, 1, "/Options/Verbosity/Errors" },
86 { "/Options/Verbosity/_Info", NULL, options_verbosity, 2, "/Options/Verbosity/Errors" },
87 { "/Options/Verbosity/_Debug", NULL, options_verbosity, 3, "/Options/Verbosity/Errors" },
89 { "/_Help" , NULL, NULL, 0, "<LastBranch>" },
90 { "/Help/About...", NULL, help_about, 0, NULL }
94 quick_message(const char* msg)
98 GtkWidget* okay_button;
100 /* Create the widgets */
102 dialog = gtk_dialog_new();
103 label = gtk_label_new (msg);
104 okay_button = gtk_button_new_with_label("OK");
106 gtk_widget_set_usize(dialog, 300, 100);
108 /* Ensure that the dialog box is destroyed when the user clicks ok. */
110 gtk_signal_connect_object (GTK_OBJECT (okay_button), "clicked",
111 GTK_SIGNAL_FUNC (gtk_widget_destroy), dialog);
112 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area),
115 /* Add the label, and show everything we've added to the dialog. */
117 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
118 gtk_widget_show_all (dialog);
122 load_error_msg(const char* name)
124 char* msg = g_strdup_printf("Could not load\n`%s'", name);
129 static guint edit_timeout_id;
130 extern void edit_timeout(gpointer);
133 GUI_init(int* argc, char*** argv, char* title, guint width, guint height, gpointer c)
135 gtk_init(argc, argv);
137 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
138 gtk_window_set_title(GTK_WINDOW(window), title);
139 gtk_window_set_default_size(GTK_WINDOW(window), width, height);
140 gtk_signal_connect(GTK_OBJECT(window), "delete_event", (GtkSignalFunc) gtk_main_quit, NULL);
141 create_widget_set(context);
143 gtk_widget_show(window);
146 /*edit_timeout_id = gtk_timeout_add(50, edit_timeout, context);*/
152 GdomeException exc = 0;
154 if (first_selected != NULL)
156 gdome_el_unref(first_selected, &exc);
158 first_selected = NULL;
161 if (root_selected != NULL)
163 gdome_el_unref(root_selected, &exc);
165 root_selected = NULL;
172 GUI_load_document(GdomeDocument* doc)
174 GtkMathView* math_view;
176 g_return_val_if_fail(doc != NULL, -1);
177 g_return_val_if_fail(main_area != NULL, -1);
178 g_return_val_if_fail(GTK_IS_MATH_VIEW(main_area), -1);
180 math_view = GTK_MATH_VIEW(main_area);
182 if (!gtk_math_view_load_document(math_view, doc)) return -1;
190 gtk_math_view_freeze(GTK_MATH_VIEW(main_area));
196 gtk_math_view_thaw(GTK_MATH_VIEW(main_area));
200 GUI_unload_document()
202 GtkMathView* math_view;
204 g_return_if_fail(main_area != NULL);
205 g_return_if_fail(GTK_IS_MATH_VIEW(main_area));
207 math_view = GTK_MATH_VIEW(main_area);
209 gtk_math_view_unload(math_view);
211 if (doc_name != NULL) g_free(doc_name);
223 GUI_set_font_manager(FontManagerId id)
226 GtkMathView* math_view;
228 g_return_if_fail(id != FONT_MANAGER_UNKNOWN);
229 g_return_if_fail(main_area != NULL);
230 g_return_if_fail(GTK_IS_MATH_VIEW(main_area));
232 t1 = id == FONT_MANAGER_T1;
234 math_view = GTK_MATH_VIEW(main_area);
236 gtk_math_view_freeze(math_view);
238 if (id != gtk_math_view_get_font_manager_type(math_view))
239 gtk_math_view_set_font_manager_type(math_view, id);
241 gtk_widget_set_sensitive(anti_aliasing(math_view, GTK_CHECK_MENU_ITEM(anti_aliasing_item)->active);
242 gtk_math_view_set_transparency(math_view, GTK_CHECK_MENU_ITEM(transparency_item)->active);
245 gtk_math_view_thaw(math_view);
250 store_filename(GtkFileSelection* selector, GtkWidget* user_data)
252 gchar* selected_filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION(user_data));
253 if (selected_filename != NULL)
254 GUI_load_document(selected_filename);
258 file_close(GtkWidget* widget, gpointer data)
260 GUI_unload_document();
264 file_re_open(GtkWidget* widget, gpointer data)
266 if (doc_name != NULL) {
267 GUI_load_document(doc_name);
272 file_open(GtkWidget* widget, gpointer data)
274 GtkWidget* fs = gtk_file_selection_new("Open File");
276 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button),
277 "clicked", GTK_SIGNAL_FUNC (store_filename), (gpointer) fs);
279 /* Ensure that the dialog box is destroyed when the user clicks a button. */
281 gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button),
282 "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
285 gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION(fs)->cancel_button),
286 "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
289 /* Display that dialog */
291 gtk_widget_show (fs);
295 file_output_tex(GtkWidget* widget, gpointer data)
297 g_assert(context != NULL);
298 edit_output_tex(context);
303 options_font_manager(GtkWidget* widget, FontManagerId id)
305 g_return_if_fail(id != FONT_MANAGER_UNKNOWN);
306 GUI_set_font_manager(id);
311 options_verbosity(GtkWidget* widget, guint level)
313 gtk_math_view_set_log_verbosity(GTK_MATH_VIEW(main_area), level);
317 edit_delete_selection(GtkWidget* widget, gpointer data)
319 if (root_selected != NULL)
322 gtk_math_view_freeze(GTK_MATH_VIEW(main_area));
323 printf("about to remove element %p\n", root_selected);
324 delete_element(root_selected);
325 gdome_el_unref(root_selected, &exc);
327 root_selected = NULL;
328 gtk_math_view_thaw(GTK_MATH_VIEW(main_area));
333 edit_select_parent(GtkWidget* widget, gpointer data)
335 if (root_selected != NULL)
337 GdomeException exc = 0;
338 GdomeElement* parent = gdome_n_parentNode(root_selected, &exc);
340 gdome_el_unref(root_selected, &exc);
342 root_selected = parent;
343 /* gtk_math_view_set_selection(GTK_MATH_VIEW(main_area), root_selected); */
348 edit_reset_selection(GtkWidget* widget, gpointer data)
350 if (root_selected != NULL)
352 GdomeException exc = 0;
353 /* gtk_math_view_reset_selection(GTK_MATH_VIEW(main_area), root_selected); */
354 gdome_el_unref(root_selected, &exc);
356 root_selected = NULL;
361 edit_reset(GtkWidget* widget, gpointer data)
363 g_assert(context != NULL);
364 edit_reset_tex(context);
368 insert_tex(GtkWidget* widget, GtkEntry* entry)
371 g_return_if_fail(entry != NULL);
373 text = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
374 edit_push_string(context, text);
379 edit_insert(GtkWidget* widget, gpointer data)
386 dialog = gtk_dialog_new();
387 entry = gtk_entry_new();
388 ok = gtk_button_new_with_label("OK");
389 cancel = gtk_button_new_with_label("Cancel");
391 gtk_signal_connect (GTK_OBJECT (ok), "clicked",
392 GTK_SIGNAL_FUNC (insert_tex), (gpointer) entry);
394 gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
395 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
397 gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
398 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
400 gtk_signal_connect_object (GTK_OBJECT (cancel), "clicked",
401 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
403 gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), 5);
405 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), entry);
406 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), ok);
407 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), cancel);
409 gtk_widget_show_all (dialog);
413 help_about(GtkWidget* widget, gpointer data)
419 dialog = gtk_dialog_new();
420 label = gtk_label_new("\n MathML Editor \n Copyright (C) 2003 Luca Padovani \n");
421 ok = gtk_button_new_with_label("Close");
423 gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
424 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
425 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area),
428 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
430 gtk_widget_show_all (dialog);
434 change_default_font_size(GtkWidget* widget, GtkSpinButton* spin)
436 g_return_if_fail(spin != NULL);
437 gtk_math_view_set_font_size( GTK_MATH_VIEW(main_area), gtk_spin_button_get_value_as_int(spin));
441 options_change_font_size(GtkWidget* widget, gboolean larger)
443 gfloat size = gtk_math_view_get_font_size (GTK_MATH_VIEW(main_area));
444 if (larger) size = size / 0.71;
445 else size = size * 0.71;
446 if (size < 1) size = 1;
447 gtk_math_view_set_font_size (GTK_MATH_VIEW(main_area), (gint) size + 0.5);
451 options_set_font_size(GtkWidget* widget, gpointer data)
460 dialog = gtk_dialog_new();
461 label = gtk_label_new("Default font size:");
462 ok = gtk_button_new_with_label("OK");
463 cancel = gtk_button_new_with_label("Cancel");
465 adj = gtk_adjustment_new (gtk_math_view_get_font_size (GTK_MATH_VIEW(main_area)), 1, 200, 1, 1, 1);
466 spin = gtk_spin_button_new (GTK_ADJUSTMENT(adj), 1, 0);
467 gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin), TRUE);
469 gtk_signal_connect (GTK_OBJECT (ok), "clicked",
470 GTK_SIGNAL_FUNC (change_default_font_size), (gpointer) spin);
472 gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
473 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
475 gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
476 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
478 gtk_signal_connect_object (GTK_OBJECT (cancel), "clicked",
479 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
481 gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), 5);
483 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), ok);
484 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), cancel);
485 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
486 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), spin);
488 gtk_widget_show_all (dialog);
492 select_begin(GtkMathView* math_view, GdomeElement* first, gint state)
494 GdomeException exc = 0;
496 g_return_if_fail(math_view != NULL);
497 g_return_if_fail(GTK_IS_MATH_VIEW(math_view));
498 g_return_if_fail(first != NULL);
500 gtk_math_view_freeze(math_view);
502 if (root_selected != NULL)
504 gtk_math_view_unselect(math_view, root_selected);
505 gdome_el_unref(root_selected, &exc);
509 root_selected = first_selected = find_element_with_ref(first);
511 if (root_selected != NULL)
513 gtk_math_view_select(math_view, root_selected);
514 gdome_el_ref(root_selected, &exc);
518 gtk_math_view_thaw(math_view);
522 select_over(GtkMathView* math_view, GdomeElement* elem, gint state)
524 GdomeElement* new_selected = NULL;
525 GdomeException exc = 0;
527 g_return_if_fail(math_view != NULL);
528 g_return_if_fail(GTK_IS_MATH_VIEW(math_view));
529 g_return_if_fail(elem != NULL);
531 if (first_selected == NULL || elem == NULL)
534 new_selected = find_common_ancestor_with_ref(first_selected, elem);
536 if (new_selected != root_selected)
538 gtk_math_view_freeze(math_view);
539 if (root_selected != NULL)
541 gtk_math_view_unselect(math_view, root_selected);
542 gdome_el_unref(root_selected, &exc);
545 root_selected = new_selected;
546 if (root_selected != NULL)
547 gtk_math_view_select(math_view, root_selected);
548 gtk_math_view_thaw(math_view);
550 else if (new_selected != NULL)
552 gdome_el_unref(new_selected, &exc);
559 key_press_event(gpointer c,
563 g_return_val_if_fail(widget != NULL, FALSE);
564 g_return_val_if_fail(event != NULL, FALSE);
565 g_return_val_if_fail(context != NULL, FALSE);
567 if (event->type != GDK_KEY_PRESS) return FALSE;
569 switch (event->keyval)
572 edit_drop(context, event->state & GDK_MOD1_MASK, event->state & GDK_CONTROL_MASK);
575 edit_complete(context);
578 if ((event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) == 0 && event->keyval < 0x80)
579 edit_push_char(context, event->keyval);
587 create_widget_set(gpointer context)
589 GtkWidget* main_vbox;
592 main_vbox = gtk_vbox_new(FALSE, 1);
593 gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
594 gtk_container_add(GTK_CONTAINER(window), main_vbox);
595 gtk_widget_show(main_vbox);
597 menu_bar = get_main_menu();
598 gtk_box_pack_start(GTK_BOX(main_vbox), menu_bar, FALSE, TRUE, 0);
599 gtk_widget_show(menu_bar);
601 main_area = gtk_math_view_new(NULL, NULL);
602 gtk_widget_show(main_area);
604 //gtk_math_view_set_log_verbosity(GTK_MATH_VIEW(main_area), 3);
606 gtk_signal_connect_object (GTK_OBJECT (main_area),
607 "select_begin", GTK_SIGNAL_FUNC (select_begin),
608 (gpointer) main_area);
610 gtk_signal_connect_object (GTK_OBJECT (main_area),
611 "select_over", GTK_SIGNAL_FUNC (select_over),
612 (gpointer) main_area);
614 gtk_signal_connect_object (GTK_OBJECT(window),
615 "key_press_event", GTK_SIGNAL_FUNC(key_press_event),
618 gtk_widget_add_events(GTK_WIDGET(main_area), GDK_KEY_PRESS_MASK);
620 scrolled_area = gtk_scrolled_window_new(NULL, NULL);
621 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_area),
622 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
624 gtk_widget_show(scrolled_area);
625 gtk_container_add(GTK_CONTAINER(scrolled_area), main_area);
626 gtk_box_pack_start(GTK_BOX(main_vbox), scrolled_area, TRUE, TRUE, 0);
628 gtk_widget_show(main_vbox);
634 GtkItemFactory* item_factory;
635 GtkAccelGroup* accel_group;
636 GtkWidget* menu_item;
638 gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
640 accel_group = gtk_accel_group_new();
642 item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
644 gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, NULL);
646 gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
648 return gtk_item_factory_get_widget(item_factory, "<main>");