1 /* Copyright (C) 2000-2007, Luca Padovani <padovani@sti.uniurb.it>.
2 *
3 * This file is part of GtkMathView, a flexible, high-quality rendering
4 * engine for MathML documents.
5 *
6 * GtkMathView is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GtkMathView is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <config.h>
21
22 #include "defs.h"
23 #include <stdio.h>
24 #include <string.h>
25 #include <gtk/gtk.h>
26 #include <gdk/gdkkeysyms.h>
27
28 #include <gdome.h>
29 #include "gtkmathview_gmetadom.h"
30 #include "guiGTK.h"
31
32 extern GdomeDOMString* find_hyperlink(GdomeElement*, const char*, const char*);
33 extern GdomeElement* find_xref_element(GdomeElement*);
34 extern GdomeElement* find_common_ancestor(GdomeElement*, GdomeElement*);
35 extern GdomeElement* find_self_or_ancestor(GdomeElement*, const char*, const char*);
36 extern GdomeElement* find_action_element(GdomeElement*);
37 extern void action_toggle(GdomeElement*);
38 extern void delete_element(GdomeElement*);
39
40 static GtkWidget* window;
41 static GtkWidget* main_area;
42 static GtkWidget* scrolled_area;
43 static GtkWidget* status_bar;
44 static GdkCursor* normal_cursor;
45 static GdkCursor* link_cursor;
46 static gboolean semantic_selection = FALSE;
47
48 static gchar* doc_name = NULL;
49 static GdomeElement* first_selected = NULL;
50 static GdomeElement* root_selected = NULL;
51 static GtkMathViewDefaultCursorDecorator* cursor = NULL;
52
53 static guint statusbar_context;
54
55 static void create_widget_set(void);
56 static GtkWidget* get_main_menu(void);
57 static void file_open(GtkWidget*, gpointer);
58 static void file_re_open(GtkWidget*, gpointer);
59 static void file_close(GtkWidget*, gpointer);
60 static void options_set_font_size(GtkWidget*, gpointer);
61 static void options_change_font_size(GtkWidget*, gboolean);
62 static void options_verbosity(GtkWidget*, guint);
63 static void options_transparent(GtkWidget*, gpointer);
64 static void options_anti_aliased(GtkWidget*, gpointer);
65 static void options_selection(GtkWidget*, gboolean);
66 static void selection_delete(GtkWidget*, gpointer);
67 static void selection_parent(GtkWidget*, gpointer);
68 static void selection_reset(GtkWidget*, gpointer);
69 static void help_about(GtkWidget*, gpointer);
70
71 static GtkItemFactoryEntry menu_items[] = {
72 { "/_File", NULL, NULL, 0, "<Branch>", 0 },
73 { "/File/_Open...", "<control>O", file_open, 0, NULL, 0 },
74 { "/File/_Reopen", NULL, file_re_open, 0, NULL, 0 },
75 { "/File/_Close", "<control>W", file_close, 0, NULL, 0 },
76 { "/File/sep1", NULL, NULL, 0, "<Separator>", 0 },
77 { "/File/_Quit", "<control>Q", gtk_main_quit, 0, NULL, 0 },
78
79 { "/_Selection", NULL, NULL, 0, "<Branch>", 0 },
80 { "/Selection/Reset", NULL, selection_reset, 0, NULL, 0 },
81 { "/Selection/Delete", NULL, selection_delete, 0, NULL, 0 },
82 { "/Selection/Select Parent", NULL, selection_parent, 0, NULL, 0 },
83
84 { "/_Options", NULL, NULL, 0, "<Branch>", 0 },
85 { "/Options/Default _Font Size", NULL, NULL, 0, "<Branch>", 0 },
86 { "/Options/Default Font Size/Set...", NULL, options_set_font_size, 0, NULL, 0 },
87 { "/Options/Default Font Size/sep1", NULL, NULL, 0, "<Separator>", 0 },
88 { "/Options/Default Font Size/Larger", "<control>2", options_change_font_size, TRUE, NULL, 0 },
89 { "/Options/Default Font Size/Smaller", "<control>1", options_change_font_size, FALSE, NULL, 0 },
90 { "/Options/Verbosity", NULL, NULL, 0, "<Branch>", 0 },
91 { "/Options/Verbosity/_Errors", NULL, options_verbosity, 0, "<RadioItem>", 0 },
92 { "/Options/Verbosity/_Warnings", NULL, options_verbosity, 1, "/Options/Verbosity/Errors", 0 },
93 { "/Options/Verbosity/_Info", NULL, options_verbosity, 2, "/Options/Verbosity/Errors", 0 },
94 { "/Options/Verbosity/_Debug", NULL, options_verbosity, 3, "/Options/Verbosity/Errors", 0 },
95 { "/Options/Type 1", NULL, NULL, 0, "<Branch>", 0 },
96 { "/Options/Type 1/_Transparent", NULL, options_transparent, TRUE, "<CheckItem>", 0 },
97 { "/Options/Type 1/_Anti Aliased", NULL, options_anti_aliased, 0, "<CheckItem>", 0 },
98 { "/Options/sep1", NULL, NULL, 0, "<Separator>", 0 },
99 { "/Options/Selection/Structure", NULL, options_selection, 0, "<RadioItem>", 0 },
100 { "/Options/Selection/Semantics", NULL, options_selection, 1, "/Options/Selection/Structure", 0 },
101
102 { "/_Help" , NULL, NULL, 0, "<Branch>", 0 },
103 { "/Help/About...", NULL, help_about, 0, NULL, 0 }
104 };
105
106 #if 0
107 static void
108 quick_message(const char* msg)
109 {
110 GtkWidget* dialog;
111 GtkWidget* label;
112 GtkWidget* okay_button;
113
114 /* Create the widgets */
115
116 dialog = gtk_dialog_new();
117 label = gtk_label_new (msg);
118 okay_button = gtk_button_new_with_label("OK");
119
120 gtk_widget_set_usize(dialog, 300, 100);
121
122 /* Ensure that the dialog box is destroyed when the user clicks ok. */
123
124 /* g_signal_connect_object(GTK_OBJECT (okay_button),
125 "clicked",
126 GTK_SIGNAL_FUNC(gtk_widget_destroy),
127 dialog,0);
128 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area),
129 okay_button);
130 */
131
132 g_signal_connect_swapped(GTK_OBJECT(okay_button),
133 "clicked",
134 G_CALLBACK(gtk_widget_destroy),
135 dialog);
136
137 /* Add the label, and show everything we've added to the dialog. */
138
139 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
140 gtk_widget_show_all (dialog);
141 }
142
143 static void
144 load_error_msg(const char* name)
145 {
146 char* msg = g_strdup_printf("Could not load\n`%s'", name);
147 quick_message(msg);
148 g_free(msg);
149 }
150 #endif
151
152 void
GUI_init(int * argc,const char *** argv,char * title,guint width,guint height,gint logLevel)153 GUI_init(int* argc, const char*** argv, char* title, guint width, guint height, gint logLevel)
154 {
155 gtk_init(argc, argv);
156
157 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
158 gtk_window_set_title(GTK_WINDOW(window), title);
159 gtk_window_set_default_size(GTK_WINDOW(window), width, height);
160
161 g_signal_connect(GTK_OBJECT(window),
162 "delete_event",
163 (GtkSignalFunc) gtk_main_quit, NULL);
164
165 create_widget_set();
166 g_assert(main_area != NULL);
167 g_assert(GTK_IS_MATH_VIEW(main_area));
168 gtk_math_view_set_log_verbosity(GTK_MATH_VIEW(main_area), logLevel);
169
170 gtk_widget_show(window);
171
172 normal_cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW);
173 link_cursor = gdk_cursor_new(GDK_HAND2);
174 }
175
176 void
GUI_uninit()177 GUI_uninit()
178 {
179 /*gtk_widget_unref(GTK_WIDGET(window));*/
180 }
181
182 int
GUI_load_document(const char * name)183 GUI_load_document(const char* name)
184 {
185 GtkMathView* math_view;
186
187 g_return_val_if_fail(name != NULL, -1);
188 g_return_val_if_fail(main_area != NULL, -1);
189 g_return_val_if_fail(GTK_IS_MATH_VIEW(main_area), -1);
190
191 math_view = GTK_MATH_VIEW(main_area);
192
193 gtk_math_view_load_uri(math_view, name);
194
195 if (name != doc_name) {
196 if (doc_name != NULL) g_free(doc_name);
197 doc_name = g_strdup(name);
198 }
199
200 gtk_statusbar_pop(GTK_STATUSBAR(status_bar), statusbar_context);
201 if (strlen(name) > 40) name += strlen(name) - 40;
202 gtk_statusbar_push(GTK_STATUSBAR(status_bar), statusbar_context, name);
203
204 return 0;
205 }
206
207 void
GUI_unload_document()208 GUI_unload_document()
209 {
210 GtkMathView* math_view;
211
212 g_return_if_fail(main_area != NULL);
213 g_return_if_fail(GTK_IS_MATH_VIEW(main_area));
214
215 math_view = GTK_MATH_VIEW(main_area);
216
217 gtk_math_view_unload(math_view);
218
219 if (doc_name != NULL) g_free(doc_name);
220 doc_name = NULL;
221
222 gtk_statusbar_pop(GTK_STATUSBAR(status_bar), statusbar_context);
223 gtk_statusbar_push(GTK_STATUSBAR(status_bar), statusbar_context, "");
224 }
225
226 void
GUI_run()227 GUI_run()
228 {
229 gtk_main();
230 }
231
232 static void
store_filename(GtkFileSelection * selector,GtkWidget * user_data)233 store_filename(GtkFileSelection* selector, GtkWidget* user_data)
234 {
235 const gchar* selected_filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION(user_data));
236 if (selected_filename != NULL)
237 GUI_load_document(selected_filename);
238 }
239
240 static void
file_close(GtkWidget * widget,gpointer data)241 file_close(GtkWidget* widget, gpointer data)
242 {
243 GUI_unload_document();
244 }
245
246 static void
file_re_open(GtkWidget * widget,gpointer data)247 file_re_open(GtkWidget* widget, gpointer data)
248 {
249 if (doc_name != NULL) {
250 GUI_load_document(doc_name);
251 }
252 }
253
254 static void
file_open(GtkWidget * widget,gpointer data)255 file_open(GtkWidget* widget, gpointer data)
256 {
257 GtkWidget* fs = gtk_file_selection_new("Open File");
258
259 g_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button),
260 "clicked",
261 GTK_SIGNAL_FUNC(store_filename), (gpointer) fs);
262
263 /* Ensure that the dialog box is destroyed when the user clicks a button. */
264
265 g_signal_connect_swapped(GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button),
266 "clicked",
267 G_CALLBACK(gtk_widget_destroy),
268 (gpointer) fs);
269
270 /* gtk_signal_connect_object(GTK_OBJECT (GTK_FILE_SELECTION(fs)->cancel_button),
271 "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
272 (gpointer) fs);
273 */
274
275 g_signal_connect_swapped(GTK_OBJECT(GTK_FILE_SELECTION(fs)->cancel_button),
276 "clicked",
277 G_CALLBACK(gtk_widget_destroy),
278 (gpointer) fs);
279
280 /* Display that dialog */
281
282 gtk_widget_show (fs);
283 }
284
285 static void
options_verbosity(GtkWidget * widget,guint level)286 options_verbosity(GtkWidget* widget, guint level)
287 {
288 gtk_math_view_set_log_verbosity(GTK_MATH_VIEW(main_area), level);
289 }
290
291 static void
options_transparent(GtkWidget * widget,gpointer data)292 options_transparent(GtkWidget* widget, gpointer data)
293 {
294 GtkMathView* math_view = GTK_MATH_VIEW(main_area);
295 g_return_if_fail(math_view != NULL);
296 gtk_math_view_set_t1_opaque_mode(math_view, !gtk_math_view_get_t1_opaque_mode(math_view));
297 }
298
299 static void
options_anti_aliased(GtkWidget * widget,gpointer data)300 options_anti_aliased(GtkWidget* widget, gpointer data)
301 {
302 GtkMathView* math_view = GTK_MATH_VIEW(main_area);
303 g_return_if_fail(math_view != NULL);
304 gtk_math_view_set_t1_anti_aliased_mode(math_view, !gtk_math_view_get_t1_anti_aliased_mode(math_view));
305 }
306
307 static void
options_selection(GtkWidget * widget,gboolean semantic)308 options_selection(GtkWidget* widget, gboolean semantic)
309 {
310 semantic_selection = semantic;
311 selection_reset(widget, NULL);
312 }
313
314 static void
selection_delete(GtkWidget * widget,gpointer data)315 selection_delete(GtkWidget* widget, gpointer data)
316 {
317 if (root_selected != NULL)
318 {
319 GdomeException exc;
320 gtk_math_view_freeze(GTK_MATH_VIEW(main_area));
321 delete_element(root_selected);
322 gdome_el_unref(root_selected, &exc);
323 g_assert(exc == 0);
324 root_selected = NULL;
325 gtk_math_view_thaw(GTK_MATH_VIEW(main_area));
326 }
327 }
328
329 static void
selection_parent(GtkWidget * widget,gpointer data)330 selection_parent(GtkWidget* widget, gpointer data)
331 {
332 if (root_selected != NULL)
333 {
334 GdomeException exc = 0;
335 GdomeElement* parent = (GdomeElement*) gdome_n_parentNode((GdomeNode*) root_selected, &exc);
336 g_assert(exc == 0);
337 gdome_el_unref(root_selected, &exc);
338 g_assert(exc == 0);
339 root_selected = parent;
340 gtk_math_view_select(GTK_MATH_VIEW(main_area), root_selected);
341 }
342 }
343
344 static void
selection_reset(GtkWidget * widget,gpointer data)345 selection_reset(GtkWidget* widget, gpointer data)
346 {
347 if (root_selected != NULL)
348 {
349 GdomeException exc = 0;
350 gtk_math_view_unselect(GTK_MATH_VIEW(main_area), root_selected);
351 gdome_el_unref(root_selected, &exc);
352 g_assert(exc == 0);
353 root_selected = NULL;
354 }
355 }
356
357 static void
help_about(GtkWidget * widget,gpointer data)358 help_about(GtkWidget* widget, gpointer data)
359 {
360 GtkWidget* dialog;
361 GtkWidget* label;
362 GtkWidget* ok;
363
364 dialog = gtk_dialog_new();
365 label = gtk_label_new("\n MathML Viewer \n Copyright (C) 2000-2004 Luca Padovani \n");
366 ok = gtk_button_new_with_label("Close");
367
368 /* gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
369 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog); */
370
371 g_signal_connect_swapped(GTK_OBJECT(ok),
372 "clicked",
373 G_CALLBACK(gtk_widget_destroy),
374 (gpointer) dialog);
375
376 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area),
377 ok);
378
379 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
380
381 gtk_widget_show_all (dialog);
382 }
383
384 static void
change_default_font_size(GtkSpinButton * widget,GtkSpinButton * spin)385 change_default_font_size(GtkSpinButton* widget, GtkSpinButton* spin)
386 {
387 g_return_if_fail(spin != NULL);
388 gtk_math_view_set_font_size( GTK_MATH_VIEW(main_area), gtk_spin_button_get_value_as_int(spin));
389 }
390
391 static void
options_change_font_size(GtkWidget * widget,gboolean larger)392 options_change_font_size(GtkWidget* widget, gboolean larger)
393 {
394 gfloat size = gtk_math_view_get_font_size (GTK_MATH_VIEW(main_area));
395 if (larger) size = size / 0.71;
396 else size = size * 0.71;
397 if (size < 1) size = 1;
398 gtk_math_view_set_font_size (GTK_MATH_VIEW(main_area), (gint) size + 0.5);
399 }
400
401 static void
options_set_font_size(GtkWidget * widget,gpointer data)402 options_set_font_size(GtkWidget* widget, gpointer data)
403 {
404 GtkWidget* dialog;
405 GtkWidget* label;
406 GtkWidget* ok;
407 GtkWidget* cancel;
408 GtkWidget* spin;
409 GtkObject* adj;
410
411 dialog = gtk_dialog_new();
412 label = gtk_label_new("Default font size:");
413 ok = gtk_button_new_with_label("OK");
414 cancel = gtk_button_new_with_label("Cancel");
415
416 adj = gtk_adjustment_new (gtk_math_view_get_font_size (GTK_MATH_VIEW(main_area)), 1, 200, 1, 1, 1);
417 spin = gtk_spin_button_new (GTK_ADJUSTMENT(adj), 1, 0);
418 gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin), TRUE);
419
420 /* gtk_signal_connect (GTK_OBJECT (ok), "clicked",
421 GTK_SIGNAL_FUNC (change_default_font_size), (gpointer) spin); */
422
423 g_signal_connect(GTK_OBJECT(ok),
424 "clicked",
425 G_CALLBACK(change_default_font_size),
426 (gpointer) spin);
427
428 /* gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
429 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog); */
430
431 g_signal_connect_swapped(GTK_OBJECT (ok),
432 "clicked",
433 G_CALLBACK(gtk_widget_destroy),
434 (gpointer) dialog);
435
436
437 /* gtk_signal_connect_object (GTK_OBJECT (ok), "clicked",
438 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);*/
439
440 /* gtk_signal_connect_object (GTK_OBJECT (cancel), "clicked",
441 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog); */
442
443 g_signal_connect_swapped(GTK_OBJECT (cancel),
444 "clicked",
445 G_CALLBACK(gtk_widget_destroy),
446 (gpointer) dialog);
447
448
449 gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), 5);
450
451 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), ok);
452 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), cancel);
453 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
454 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), spin);
455
456 gtk_widget_show_all (dialog);
457 }
458
459 #if defined(HAVE_GMETADOM)
460 static void
element_over(GtkMathView * math_view,const GtkMathViewModelEvent * event)461 element_over(GtkMathView* math_view, const GtkMathViewModelEvent* event)
462 {
463 GdomeElement* action = NULL;
464 GdomeDOMString* link = NULL;
465
466 g_return_if_fail(math_view != NULL);
467 g_return_if_fail(GTK_IS_MATH_VIEW(math_view));
468 g_return_if_fail(event != NULL);
469
470 link = find_hyperlink(event->id, XLINK_NS_URI, "href");
471 if (link != NULL)
472 gdk_window_set_cursor(GTK_WIDGET(math_view)->window, link_cursor);
473 else
474 gdk_window_set_cursor(GTK_WIDGET(math_view)->window, normal_cursor);
475
476 if (link != NULL)
477 gdome_str_unref(link);
478
479 action = find_action_element(event->id);
480 #if 0
481 if (action != NULL)
482 {
483 GdomeException exc = 0;
484 gtk_math_view_decor_default_cursor_set(cursor, TRUE, action, TRUE, -1, FALSE);
485 gdome_el_unref(action, &exc);
486 g_assert(exc == 0);
487 }
488 #endif
489 }
490
491 static void
select_begin(GtkMathView * math_view,const GtkMathViewModelEvent * event)492 select_begin(GtkMathView* math_view, const GtkMathViewModelEvent* event)
493 {
494 g_return_if_fail(math_view != NULL);
495 g_return_if_fail(GTK_IS_MATH_VIEW(math_view));
496 g_return_if_fail(event != NULL);
497
498 if (event->id != NULL)
499 {
500 GdomeException exc = 0;
501
502 gtk_math_view_freeze(math_view);
503
504 if (root_selected != NULL)
505 {
506 gtk_math_view_unselect(math_view, root_selected);
507 gdome_el_unref(root_selected, &exc);
508 g_assert(exc == 0);
509 root_selected = NULL;
510 }
511
512 if (semantic_selection)
513 {
514 GdomeElement* new_elem = find_xref_element(event->id);
515 if (new_elem != NULL)
516 {
517 gdome_el_ref(new_elem, &exc);
518 g_assert(exc == 0);
519 }
520 first_selected = root_selected = new_elem;
521 }
522 else
523 {
524 gdome_el_ref(event->id, &exc);
525 g_assert(exc == 0);
526 gdome_el_ref(event->id, &exc);
527 g_assert(exc == 0);
528 first_selected = root_selected = event->id;
529 }
530
531 if (root_selected != NULL)
532 gtk_math_view_select(math_view, root_selected);
533
534 gtk_math_view_thaw(math_view);
535 }
536 }
537
538 static void
select_over(GtkMathView * math_view,const GtkMathViewModelEvent * event)539 select_over(GtkMathView* math_view, const GtkMathViewModelEvent* event)
540 {
541 g_return_if_fail(math_view != NULL);
542 g_return_if_fail(GTK_IS_MATH_VIEW(math_view));
543 g_return_if_fail(event != NULL);
544
545 if (first_selected != NULL && event->id != NULL)
546 {
547 GdomeException exc = 0;
548
549 gtk_math_view_freeze(math_view);
550
551 if (root_selected != NULL)
552 {
553 gtk_math_view_unselect(math_view, root_selected);
554 gdome_el_unref(root_selected, &exc);
555 g_assert(exc == 0);
556 root_selected = NULL;
557 }
558
559 if (semantic_selection)
560 {
561 GdomeElement* new_root = find_common_ancestor(first_selected, event->id);
562 if (new_root != NULL)
563 {
564 root_selected = find_xref_element(new_root);
565 gdome_el_unref(new_root, &exc);
566 g_assert(exc == 0);
567 }
568 else
569 root_selected = NULL;
570 }
571 else
572 root_selected = find_common_ancestor(first_selected, event->id);
573
574 while (root_selected != NULL && !gtk_math_view_select(math_view, root_selected))
575 {
576 GdomeElement* new_root = (GdomeElement*) gdome_el_parentNode(root_selected, &exc);
577 g_assert(exc == 0);
578 gdome_el_unref(root_selected, &exc);
579 g_assert(exc == 0);
580 root_selected = new_root;
581 }
582
583 gtk_math_view_thaw(math_view);
584 }
585 }
586
587 static void
select_end(GtkMathView * math_view,const GtkMathViewModelEvent * event)588 select_end(GtkMathView* math_view, const GtkMathViewModelEvent* event)
589 {
590 g_return_if_fail(math_view != NULL);
591 g_return_if_fail(GTK_IS_MATH_VIEW(math_view));
592 g_return_if_fail(event != NULL);
593
594 if (first_selected != NULL)
595 {
596 GdomeException exc = 0;
597 gdome_el_unref(first_selected, &exc);
598 g_assert(exc == 0);
599 first_selected = NULL;
600 }
601 }
602
603 static void
select_abort(GtkMathView * math_view)604 select_abort(GtkMathView* math_view)
605 {
606 GdomeException exc = 0;
607
608 g_return_if_fail(math_view != NULL);
609 g_return_if_fail(GTK_IS_MATH_VIEW(math_view));
610
611 if (first_selected != NULL)
612 {
613 gdome_el_unref(first_selected, &exc);
614 g_assert(exc == 0);
615 first_selected = NULL;
616 }
617
618 if (root_selected != NULL)
619 {
620 gtk_math_view_freeze(math_view);
621 gtk_math_view_unselect(math_view, root_selected);
622 gtk_math_view_thaw(math_view);
623 gdome_el_unref(root_selected, &exc);
624 g_assert(exc == 0);
625 root_selected = NULL;
626 }
627 }
628
629 static void
click(GtkMathView * math_view,const GtkMathViewModelEvent * event)630 click(GtkMathView* math_view, const GtkMathViewModelEvent* event)
631 {
632 gboolean res;
633 gint index;
634 GdomeElement* elem;
635 GdomeException exc;
636 GdomeDOMString* name;
637 GdomeDOMString* ns_uri;
638 GdomeElement* p;
639
640 gint w, h;
641 gtk_math_view_get_size(math_view, &w, &h);
642 printf("click signal %d %d\n", w, h);
643
644 g_return_if_fail(math_view != NULL);
645 g_return_if_fail(event != NULL);
646
647 #if 1
648 index = -1;
649 if (gtk_math_view_get_char_at(math_view, event->x, event->y, &elem, &index, NULL, NULL))
650 gtk_math_view_decor_default_cursor_set(cursor, TRUE, event->id, TRUE, index, TRUE);
651 else
652 gtk_math_view_decor_default_cursor_set(cursor, FALSE, NULL, FALSE, -1, FALSE);
653 #endif
654
655 if (event->id != NULL)
656 {
657 name = gdome_el_nodeName(event->id, &exc);
658 g_assert(exc == 0);
659 printf("node name: %s\n", name->str);
660 }
661
662 if (event->id != NULL)
663 {
664 GdomeElement* action;
665 GdomeDOMString* href = find_hyperlink(event->id, XLINK_NS_URI, "href");
666 if (href != NULL)
667 {
668 printf("hyperlink %s\n", href->str);
669 gdome_str_unref(href);
670 }
671
672 action = find_action_element(event->id);
673 printf("action? %p\n", action);
674 if (action != NULL)
675 {
676 gtk_math_view_freeze(math_view);
677 action_toggle(action);
678 gtk_math_view_thaw(math_view);
679 gdome_el_unref(action, &exc);
680 g_assert(exc == 0);
681 return;
682 }
683 }
684
685 if (root_selected != NULL)
686 {
687 gtk_math_view_freeze(math_view);
688 gtk_math_view_unselect(math_view, root_selected);
689 gtk_math_view_thaw(math_view);
690 gdome_el_unref(root_selected, &exc);
691 g_assert(exc == 0);
692 root_selected = NULL;
693 }
694 }
695
696 #endif // HAVE_GMETADOM
697
698 static gboolean
cursor_blink(GtkMathViewDefaultCursorDecorator * cursor)699 cursor_blink(GtkMathViewDefaultCursorDecorator* cursor)
700 {
701 gboolean enabled;
702 GdomeElement* focus;
703 gboolean draw_focus;
704 gint index;
705 gboolean char_index;
706 g_return_val_if_fail(cursor != NULL, FALSE);
707
708 gtk_math_view_decor_default_cursor_get(cursor, &enabled, &focus, &draw_focus, &index, &char_index);
709 gtk_math_view_decor_default_cursor_set(cursor, !enabled, focus, draw_focus, index, char_index);
710
711 return TRUE;
712 }
713
714 static void
create_widget_set()715 create_widget_set()
716 {
717 GtkWidget* main_vbox;
718 GtkWidget* menu_bar;
719
720 main_vbox = gtk_vbox_new(FALSE, 1);
721 gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
722 gtk_container_add(GTK_CONTAINER(window), main_vbox);
723 gtk_widget_show(main_vbox);
724
725 menu_bar = get_main_menu();
726 gtk_box_pack_start(GTK_BOX(main_vbox), menu_bar, FALSE, TRUE, 0);
727 gtk_widget_show(menu_bar);
728
729 scrolled_area = gtk_scrolled_window_new(NULL, NULL);
730 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_area),
731 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
732 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_area),
733 GTK_SHADOW_IN);
734 gtk_widget_show(scrolled_area);
735 gtk_box_pack_start(GTK_BOX(main_vbox), scrolled_area, TRUE, TRUE, 0);
736
737 main_area = gtk_math_view_new(NULL, NULL);
738 gtk_widget_show(main_area);
739 gtk_container_add(GTK_CONTAINER(scrolled_area), main_area);
740 gtk_widget_set_double_buffered(main_area, FALSE);
741
742 g_signal_connect(GTK_OBJECT (main_area),
743 "select_begin",
744 G_CALLBACK(select_begin),
745 (gpointer) main_area);
746
747 g_signal_connect(GTK_OBJECT (main_area),
748 "select_over",
749 G_CALLBACK(select_over),
750 (gpointer) main_area);
751
752 g_signal_connect(GTK_OBJECT (main_area),
753 "select_end",
754 G_CALLBACK(select_end),
755 (gpointer) main_area);
756
757 g_signal_connect(GTK_OBJECT (main_area),
758 "select_abort",
759 G_CALLBACK(select_abort),
760 (gpointer) main_area);
761
762 g_signal_connect(GTK_OBJECT (main_area),
763 "element_over",
764 G_CALLBACK(element_over),
765 (gpointer) main_area);
766
767 g_signal_connect(GTK_OBJECT (main_area),
768 "click",
769 G_CALLBACK(click),
770 (gpointer) main_area);
771
772 cursor = gtk_math_view_decor_default_cursor_new(GTK_MATH_VIEW(main_area));
773 g_timeout_add(500, cursor_blink, cursor);
774
775 status_bar = gtk_statusbar_new();
776 gtk_widget_show(status_bar);
777 gtk_box_pack_start(GTK_BOX(main_vbox), status_bar, FALSE, TRUE, 0);
778 statusbar_context = gtk_statusbar_get_context_id(GTK_STATUSBAR(status_bar), "filename");
779
780 gtk_widget_show(main_vbox);
781 }
782
783 GtkWidget*
get_main_menu()784 get_main_menu()
785 {
786 GtkItemFactory* item_factory;
787 GtkAccelGroup* accel_group;
788
789 gint nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
790
791 accel_group = gtk_accel_group_new();
792
793 item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
794
795 gtk_item_factory_create_items(item_factory, nmenu_items, menu_items, NULL);
796
797 gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
798
799 return gtk_item_factory_get_widget(item_factory, "<main>");
800 }
801