xinput bugfixes, autoload pdf.xoj option, papercolor chooser
[xournal.git] / src / xo-callbacks.c
blob6254ab80aa0110b1adcac86009ea5b0f8d2151ff
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
5 #include <math.h>
6 #include <string.h>
7 #include <gtk/gtk.h>
8 #include <libgnomecanvas/libgnomecanvas.h>
9 #include <time.h>
10 #include <glib/gstdio.h>
11 #include <gdk/gdkkeysyms.h>
13 #include "xournal.h"
14 #include "xo-callbacks.h"
15 #include "xo-interface.h"
16 #include "xo-support.h"
17 #include "xo-misc.h"
18 #include "xo-file.h"
19 #include "xo-paint.h"
20 #include "xo-print.h"
21 #include "xo-shapes.h"
23 void
24 on_fileNew_activate (GtkMenuItem *menuitem,
25 gpointer user_data)
27 end_text();
28 if (close_journal()) {
29 new_journal();
30 ui.zoom = ui.startup_zoom;
31 update_page_stuff();
32 gtk_adjustment_set_value(gtk_layout_get_vadjustment(GTK_LAYOUT(canvas)), 0);
33 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
38 void
39 on_fileNewBackground_activate (GtkMenuItem *menuitem,
40 gpointer user_data)
42 GtkWidget *dialog, *attach_opt;
43 GtkFileFilter *filt_all, *filt_pdf;
44 char *filename;
45 int file_domain;
46 gboolean success;
48 end_text();
49 if (!ok_to_close()) return; // user aborted on save confirmation
51 dialog = gtk_file_chooser_dialog_new(_("Open PDF"), GTK_WINDOW (winMain),
52 GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
53 GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
54 #ifdef FILE_DIALOG_SIZE_BUGFIX
55 gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
56 #endif
58 filt_all = gtk_file_filter_new();
59 gtk_file_filter_set_name(filt_all, _("All files"));
60 gtk_file_filter_add_pattern(filt_all, "*");
61 filt_pdf = gtk_file_filter_new();
62 gtk_file_filter_set_name(filt_pdf, _("PDF files"));
63 gtk_file_filter_add_pattern(filt_pdf, "*.pdf");
64 gtk_file_filter_add_pattern(filt_pdf, "*.PDF");
65 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pdf);
66 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
68 if (ui.default_path!=NULL) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
70 attach_opt = gtk_check_button_new_with_label(_("Attach file to the journal"));
71 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(attach_opt), FALSE);
72 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER (dialog), attach_opt);
74 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
75 gtk_widget_destroy(dialog);
76 return;
78 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
79 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(attach_opt)))
80 file_domain = DOMAIN_ATTACH;
81 else file_domain = DOMAIN_ABSOLUTE;
83 gtk_widget_destroy(dialog);
85 set_cursor_busy(TRUE);
86 ui.saved = TRUE; // force close_journal to work
87 close_journal();
88 while (bgpdf.status != STATUS_NOT_INIT) {
89 // waiting for pdf processes to finish dying
90 gtk_main_iteration();
92 new_journal();
93 ui.zoom = ui.startup_zoom;
94 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
95 update_page_stuff();
96 success = init_bgpdf(filename, TRUE, file_domain);
97 set_cursor_busy(FALSE);
98 if (success) {
99 g_free(filename);
100 return;
103 /* open failed */
104 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
105 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening file '%s'"), filename);
106 gtk_dialog_run(GTK_DIALOG(dialog));
107 gtk_widget_destroy(dialog);
108 g_free(filename);
112 void
113 on_fileOpen_activate (GtkMenuItem *menuitem,
114 gpointer user_data)
116 GtkWidget *dialog;
117 GtkFileFilter *filt_all, *filt_xoj;
118 char *filename;
119 gboolean success;
121 end_text();
122 if (!ok_to_close()) return; // user aborted on save confirmation
124 dialog = gtk_file_chooser_dialog_new(_("Open Journal"), GTK_WINDOW (winMain),
125 GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
126 GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
127 #ifdef FILE_DIALOG_SIZE_BUGFIX
128 gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
129 #endif
131 filt_all = gtk_file_filter_new();
132 gtk_file_filter_set_name(filt_all, _("All files"));
133 gtk_file_filter_add_pattern(filt_all, "*");
134 filt_xoj = gtk_file_filter_new();
135 gtk_file_filter_set_name(filt_xoj, _("Xournal files"));
136 gtk_file_filter_add_pattern(filt_xoj, "*.xoj");
137 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_xoj);
138 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
140 if (ui.default_path!=NULL) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
142 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
143 gtk_widget_destroy(dialog);
144 return;
146 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
147 gtk_widget_destroy(dialog);
149 set_cursor_busy(TRUE);
150 success = open_journal(filename);
151 set_cursor_busy(FALSE);
152 if (success) { g_free(filename); return; }
154 /* open failed */
155 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
156 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening file '%s'"), filename);
157 gtk_dialog_run(GTK_DIALOG(dialog));
158 gtk_widget_destroy(dialog);
159 g_free(filename);
164 void
165 on_fileSave_activate (GtkMenuItem *menuitem,
166 gpointer user_data)
168 GtkWidget *dialog;
170 end_text();
171 if (ui.filename == NULL) {
172 on_fileSaveAs_activate(menuitem, user_data);
173 return;
175 set_cursor_busy(TRUE);
176 if (save_journal(ui.filename)) { // success
177 set_cursor_busy(FALSE);
178 ui.saved = TRUE;
179 return;
181 set_cursor_busy(FALSE);
182 /* save failed */
183 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
184 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error saving file '%s'"), ui.filename);
185 gtk_dialog_run(GTK_DIALOG(dialog));
186 gtk_widget_destroy(dialog);
190 void
191 on_fileSaveAs_activate (GtkMenuItem *menuitem,
192 gpointer user_data)
194 GtkWidget *dialog, *warning_dialog;
195 GtkFileFilter *filt_all, *filt_xoj;
196 char *filename;
197 char stime[30];
198 time_t curtime;
199 gboolean warn;
200 struct stat stat_buf;
202 end_text();
203 dialog = gtk_file_chooser_dialog_new(_("Save Journal"), GTK_WINDOW (winMain),
204 GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
205 GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
206 #ifdef FILE_DIALOG_SIZE_BUGFIX
207 gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
208 #endif
210 if (ui.filename!=NULL) {
211 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), ui.filename);
212 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), g_basename(ui.filename));
214 else
215 if (bgpdf.status!=STATUS_NOT_INIT && bgpdf.file_domain == DOMAIN_ABSOLUTE
216 && bgpdf.filename != NULL) {
217 filename = g_strdup_printf("%s.xoj", bgpdf.filename->s);
218 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), filename);
219 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), g_basename(filename));
220 g_free(filename);
222 else {
223 curtime = time(NULL);
224 strftime(stime, 30, "%F-Note-%H-%M.xoj", localtime(&curtime));
225 if (ui.default_path!=NULL)
226 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
227 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), stime);
230 filt_all = gtk_file_filter_new();
231 gtk_file_filter_set_name(filt_all, _("All files"));
232 gtk_file_filter_add_pattern(filt_all, "*");
233 filt_xoj = gtk_file_filter_new();
234 gtk_file_filter_set_name(filt_xoj, _("Xournal files"));
235 gtk_file_filter_add_pattern(filt_xoj, "*.xoj");
236 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_xoj);
237 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
239 // somehow this doesn't seem to be set by default
240 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
242 do {
243 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
244 gtk_widget_destroy(dialog);
245 return;
247 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
248 warn = g_file_test (filename, G_FILE_TEST_EXISTS);
249 if (warn) { // ok to overwrite an empty file
250 if (!g_stat(filename, &stat_buf))
251 if (stat_buf.st_size == 0) warn=FALSE;
253 if (warn && ui.filename!=NULL) { // ok to overwrite oneself
254 if (ui.filename[0]=='/' && !strcmp(ui.filename, filename)) warn=FALSE;
255 if (ui.filename[0]!='/' && g_str_has_suffix(filename, ui.filename)) warn=FALSE;
257 if (warn) {
258 warning_dialog = gtk_message_dialog_new(GTK_WINDOW(winMain),
259 GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
260 _("Should the file %s be overwritten?"), filename);
261 if (gtk_dialog_run(GTK_DIALOG(warning_dialog)) == GTK_RESPONSE_YES)
262 warn = FALSE;
263 gtk_widget_destroy(warning_dialog);
265 } while (warn);
267 gtk_widget_destroy(dialog);
269 set_cursor_busy(TRUE);
270 if (save_journal(filename)) { // success
271 ui.saved = TRUE;
272 set_cursor_busy(FALSE);
273 update_file_name(filename);
274 return;
276 set_cursor_busy(FALSE);
277 /* save failed */
278 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
279 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error saving file '%s'"), filename);
280 gtk_dialog_run(GTK_DIALOG(dialog));
281 gtk_widget_destroy(dialog);
282 g_free(filename);
286 void
287 on_filePrintOptions_activate (GtkMenuItem *menuitem,
288 gpointer user_data)
293 void
294 on_filePrint_activate (GtkMenuItem *menuitem,
295 gpointer user_data)
297 #if GTK_CHECK_VERSION(2, 10, 0)
298 GtkPrintOperation *print;
299 GtkPrintOperationResult res;
301 int fromPage, toPage;
302 int response;
303 char *in_fn, *p;
305 end_text();
306 if (!gtk_check_version(2, 10, 0)) {
307 print = gtk_print_operation_new();
309 if (!ui.print_settings)
310 ui.print_settings = gtk_print_settings_new();
311 if (ui.filename!=NULL) {
312 if (g_str_has_suffix(ui.filename, ".xoj")) {
313 in_fn = g_strdup(ui.filename);
314 g_strlcpy(g_strrstr(in_fn, "xoj"), "pdf", 4);
316 else in_fn = g_strdup_printf("%s.pdf", ui.filename);
317 gtk_print_settings_set(ui.print_settings, GTK_PRINT_SETTINGS_OUTPUT_URI,
318 g_filename_to_uri(in_fn, NULL, NULL));
319 g_free(in_fn);
322 if (ui.print_settings!=NULL)
323 gtk_print_operation_set_print_settings (print, ui.print_settings);
324 gtk_print_operation_set_n_pages(print, journal.npages);
325 gtk_print_operation_set_current_page(print, ui.pageno);
326 gtk_print_operation_set_show_progress(print, TRUE);
327 if (ui.filename!=NULL) {
328 p = g_utf8_strrchr(ui.filename, -1, '/');
329 if (p==NULL) p = ui.filename;
330 else p++;
331 gtk_print_operation_set_job_name(print, p);
333 g_signal_connect (print, "draw_page", G_CALLBACK (print_job_render_page), NULL);
334 res = gtk_print_operation_run(print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
335 GTK_WINDOW(winMain), NULL);
336 if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
337 if (ui.print_settings!=NULL) g_object_unref(ui.print_settings);
338 ui.print_settings = g_object_ref(gtk_print_operation_get_print_settings(print));
340 g_object_unref(print);
342 #endif
346 void
347 on_filePrintPDF_activate (GtkMenuItem *menuitem,
348 gpointer user_data)
351 GtkWidget *dialog, *warning_dialog;
352 GtkFileFilter *filt_all, *filt_pdf;
353 char *filename, *in_fn;
354 char stime[30];
355 time_t curtime;
356 gboolean warn;
358 end_text();
359 dialog = gtk_file_chooser_dialog_new(_("Export to PDF"), GTK_WINDOW (winMain),
360 GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
361 GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
362 #ifdef FILE_DIALOG_SIZE_BUGFIX
363 gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
364 #endif
366 if (ui.filename!=NULL) {
367 if (g_str_has_suffix(ui.filename, ".xoj")) {
368 in_fn = g_strdup(ui.filename);
369 g_strlcpy(g_strrstr(in_fn, "xoj"), "pdf", 4);
371 else
372 in_fn = g_strdup_printf("%s.pdf", ui.filename);
373 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), in_fn);
374 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), g_basename(in_fn));
375 } else {
376 curtime = time(NULL);
377 strftime(stime, 30, "%F-Note-%H-%M.pdf", localtime(&curtime));
378 if (ui.default_path!=NULL)
379 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
380 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), stime);
381 in_fn = NULL;
384 filt_all = gtk_file_filter_new();
385 gtk_file_filter_set_name(filt_all, _("All files"));
386 gtk_file_filter_add_pattern(filt_all, "*");
387 filt_pdf = gtk_file_filter_new();
388 gtk_file_filter_set_name(filt_pdf, _("PDF files"));
389 gtk_file_filter_add_pattern(filt_pdf, "*.pdf");
390 gtk_file_filter_add_pattern(filt_pdf, "*.PDF");
391 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pdf);
392 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
393 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
394 g_free(in_fn);
396 do {
397 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
398 gtk_widget_destroy(dialog);
399 return;
401 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
402 warn = g_file_test(filename, G_FILE_TEST_EXISTS);
403 if (warn) {
404 warning_dialog = gtk_message_dialog_new(GTK_WINDOW(winMain),
405 GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
406 _("Should the file %s be overwritten?"), filename);
407 if (gtk_dialog_run(GTK_DIALOG(warning_dialog)) == GTK_RESPONSE_YES)
408 warn = FALSE;
409 gtk_widget_destroy(warning_dialog);
411 } while(warn);
413 gtk_widget_destroy(dialog);
415 set_cursor_busy(TRUE);
416 if (!print_to_pdf(filename)) {
417 set_cursor_busy(FALSE);
418 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
419 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error creating file '%s'"), filename);
420 gtk_dialog_run(GTK_DIALOG(dialog));
421 gtk_widget_destroy(dialog);
423 set_cursor_busy(FALSE);
424 g_free(filename);
428 void
429 on_fileQuit_activate (GtkMenuItem *menuitem,
430 gpointer user_data)
432 end_text();
433 if (ok_to_close()) gtk_main_quit ();
437 void
438 on_editUndo_activate (GtkMenuItem *menuitem,
439 gpointer user_data)
441 struct UndoItem *u;
442 GList *list, *itemlist;
443 struct UndoErasureData *erasure;
444 struct Item *it;
445 struct Brush tmp_brush;
446 struct Background *tmp_bg;
447 double tmp_x, tmp_y;
448 gchar *tmpstr;
449 GnomeCanvasGroup *group;
451 end_text();
452 if (undo == NULL) return; // nothing to undo!
453 reset_selection(); // safer
454 reset_recognizer(); // safer
455 if (undo->type == ITEM_STROKE || undo->type == ITEM_TEXT) {
456 // we're keeping the stroke info, but deleting the canvas item
457 gtk_object_destroy(GTK_OBJECT(undo->item->canvas_item));
458 undo->item->canvas_item = NULL;
459 // we also remove the object from its layer!
460 undo->layer->items = g_list_remove(undo->layer->items, undo->item);
461 undo->layer->nitems--;
463 else if (undo->type == ITEM_ERASURE || undo->type == ITEM_RECOGNIZER) {
464 for (list = undo->erasurelist; list!=NULL; list = list->next) {
465 erasure = (struct UndoErasureData *)list->data;
466 // delete all the created items
467 for (itemlist = erasure->replacement_items; itemlist!=NULL; itemlist = itemlist->next) {
468 it = (struct Item *)itemlist->data;
469 gtk_object_destroy(GTK_OBJECT(it->canvas_item));
470 it->canvas_item = NULL;
471 undo->layer->items = g_list_remove(undo->layer->items, it);
472 undo->layer->nitems--;
474 // recreate the deleted one
475 make_canvas_item_one(undo->layer->group, erasure->item);
477 undo->layer->items = g_list_insert(undo->layer->items, erasure->item,
478 erasure->npos);
479 if (erasure->npos == 0)
480 lower_canvas_item_to(undo->layer->group, erasure->item->canvas_item, NULL);
481 else
482 lower_canvas_item_to(undo->layer->group, erasure->item->canvas_item,
483 ((struct Item *)g_list_nth_data(undo->layer->items, erasure->npos-1))->canvas_item);
484 undo->layer->nitems++;
487 else if (undo->type == ITEM_NEW_BG_ONE || undo->type == ITEM_NEW_BG_RESIZE
488 || undo->type == ITEM_PAPER_RESIZE) {
489 if (undo->type != ITEM_PAPER_RESIZE) {
490 // swap the two bg's
491 tmp_bg = undo->page->bg;
492 undo->page->bg = undo->bg;
493 undo->bg = tmp_bg;
494 undo->page->bg->canvas_item = undo->bg->canvas_item;
495 undo->bg->canvas_item = NULL;
497 if (undo->type != ITEM_NEW_BG_ONE) {
498 tmp_x = undo->page->width;
499 tmp_y = undo->page->height;
500 undo->page->width = undo->val_x;
501 undo->page->height = undo->val_y;
502 undo->val_x = tmp_x;
503 undo->val_y = tmp_y;
504 make_page_clipbox(undo->page);
506 update_canvas_bg(undo->page);
507 do_switch_page(g_list_index(journal.pages, undo->page), TRUE, TRUE);
509 else if (undo->type == ITEM_NEW_DEFAULT_BG) {
510 tmp_bg = ui.default_page.bg;
511 ui.default_page.bg = undo->bg;
512 undo->bg = tmp_bg;
513 tmp_x = ui.default_page.width;
514 tmp_y = ui.default_page.height;
515 ui.default_page.width = undo->val_x;
516 ui.default_page.height = undo->val_y;
517 undo->val_x = tmp_x;
518 undo->val_y = tmp_y;
520 else if (undo->type == ITEM_NEW_PAGE) {
521 // unmap the page; keep the page & its empty layer in memory
522 if (undo->page->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->page->group));
523 // also destroys the background and layer's canvas items
524 undo->page->group = NULL;
525 undo->page->bg->canvas_item = NULL;
526 journal.pages = g_list_remove(journal.pages, undo->page);
527 journal.npages--;
528 if (ui.cur_page == undo->page) ui.cur_page = NULL;
529 // so do_switch_page() won't try to remap the layers of the defunct page
530 if (ui.pageno >= undo->val) ui.pageno--;
531 if (ui.pageno < 0) ui.pageno = 0;
532 do_switch_page(ui.pageno, TRUE, TRUE);
534 else if (undo->type == ITEM_DELETE_PAGE) {
535 journal.pages = g_list_insert(journal.pages, undo->page, undo->val);
536 journal.npages++;
537 make_canvas_items(); // re-create the canvas items
538 do_switch_page(undo->val, TRUE, TRUE);
540 else if (undo->type == ITEM_MOVESEL) {
541 for (itemlist = undo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
542 it = (struct Item *)itemlist->data;
543 if (it->canvas_item != NULL) {
544 if (undo->layer != undo->layer2)
545 gnome_canvas_item_reparent(it->canvas_item, undo->layer->group);
546 gnome_canvas_item_move(it->canvas_item, -undo->val_x, -undo->val_y);
549 move_journal_items_by(undo->itemlist, -undo->val_x, -undo->val_y,
550 undo->layer2, undo->layer, undo->auxlist);
552 else if (undo->type == ITEM_RESIZESEL) {
553 resize_journal_items_by(undo->itemlist,
554 1/undo->scaling_x, 1/undo->scaling_y,
555 -undo->val_x/undo->scaling_x, -undo->val_y/undo->scaling_y);
557 else if (undo->type == ITEM_PASTE) {
558 for (itemlist = undo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
559 it = (struct Item *)itemlist->data;
560 gtk_object_destroy(GTK_OBJECT(it->canvas_item));
561 it->canvas_item = NULL;
562 undo->layer->items = g_list_remove(undo->layer->items, it);
563 undo->layer->nitems--;
566 else if (undo->type == ITEM_NEW_LAYER) {
567 // unmap the layer; keep the empty layer in memory
568 if (undo->layer->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->layer->group));
569 undo->layer->group = NULL;
570 undo->page->layers = g_list_remove(undo->page->layers, undo->layer);
571 undo->page->nlayers--;
572 do_switch_page(ui.pageno, FALSE, FALSE); // don't stay with bad cur_layer info
574 else if (undo->type == ITEM_DELETE_LAYER) {
575 // special case of -1: deleted the last layer, created a new one
576 if (undo->val == -1) {
577 if (undo->layer2->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->layer2->group));
578 undo->layer2->group = NULL;
579 undo->page->layers = g_list_remove(undo->page->layers, undo->layer2);
580 undo->page->nlayers--;
582 // re-map the layer
583 undo->layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
584 undo->page->group, gnome_canvas_group_get_type(), NULL);
585 lower_canvas_item_to(undo->page->group, GNOME_CANVAS_ITEM(undo->layer->group),
586 (undo->val >= 1) ? GNOME_CANVAS_ITEM(((struct Layer *)
587 g_list_nth_data(undo->page->layers, undo->val-1))->group) :
588 undo->page->bg->canvas_item);
589 undo->page->layers = g_list_insert(undo->page->layers, undo->layer,
590 (undo->val >= 0) ? undo->val:0);
591 undo->page->nlayers++;
593 for (itemlist = undo->layer->items; itemlist!=NULL; itemlist = itemlist->next)
594 make_canvas_item_one(undo->layer->group, (struct Item *)itemlist->data);
596 do_switch_page(ui.pageno, FALSE, FALSE); // show the restored layer & others...
598 else if (undo->type == ITEM_REPAINTSEL) {
599 for (itemlist = undo->itemlist, list = undo->auxlist; itemlist!=NULL;
600 itemlist = itemlist->next, list = list->next) {
601 it = (struct Item *)itemlist->data;
602 g_memmove(&tmp_brush, &(it->brush), sizeof(struct Brush));
603 g_memmove(&(it->brush), list->data, sizeof(struct Brush));
604 g_memmove(list->data, &tmp_brush, sizeof(struct Brush));
605 if (it->type == ITEM_STROKE && it->canvas_item != NULL) {
606 // remark: a variable-width item might have lost its variable-width
607 group = (GnomeCanvasGroup *) it->canvas_item->parent;
608 gtk_object_destroy(GTK_OBJECT(it->canvas_item));
609 make_canvas_item_one(group, it);
611 if (it->type == ITEM_TEXT && it->canvas_item != NULL)
612 gnome_canvas_item_set(it->canvas_item,
613 "fill-color-rgba", it->brush.color_rgba, NULL);
616 else if (undo->type == ITEM_TEXT_EDIT) {
617 tmpstr = undo->str;
618 undo->str = undo->item->text;
619 undo->item->text = tmpstr;
620 gnome_canvas_item_set(undo->item->canvas_item, "text", tmpstr, NULL);
621 update_item_bbox(undo->item);
623 else if (undo->type == ITEM_TEXT_ATTRIB) {
624 tmpstr = undo->str;
625 undo->str = undo->item->font_name;
626 undo->item->font_name = tmpstr;
627 tmp_x = undo->val_x;
628 undo->val_x = undo->item->font_size;
629 undo->item->font_size = tmp_x;
630 g_memmove(&tmp_brush, undo->brush, sizeof(struct Brush));
631 g_memmove(undo->brush, &(undo->item->brush), sizeof(struct Brush));
632 g_memmove(&(undo->item->brush), &tmp_brush, sizeof(struct Brush));
633 gnome_canvas_item_set(undo->item->canvas_item,
634 "fill-color-rgba", undo->item->brush.color_rgba, NULL);
635 update_text_item_displayfont(undo->item);
636 update_item_bbox(undo->item);
639 // move item from undo to redo stack
640 u = undo;
641 undo = undo->next;
642 u->next = redo;
643 redo = u;
644 ui.saved = FALSE;
645 update_undo_redo_enabled();
646 if (u->multiop & MULTIOP_CONT_UNDO) on_editUndo_activate(NULL,NULL); // loop
650 void
651 on_editRedo_activate (GtkMenuItem *menuitem,
652 gpointer user_data)
654 struct UndoItem *u;
655 GList *list, *itemlist, *target;
656 struct UndoErasureData *erasure;
657 struct Item *it;
658 struct Brush tmp_brush;
659 struct Background *tmp_bg;
660 struct Layer *l;
661 double tmp_x, tmp_y;
662 gchar *tmpstr;
663 GnomeCanvasGroup *group;
665 end_text();
666 if (redo == NULL) return; // nothing to redo!
667 reset_selection(); // safer
668 reset_recognizer(); // safer
669 if (redo->type == ITEM_STROKE || redo->type == ITEM_TEXT) {
670 // re-create the canvas_item
671 make_canvas_item_one(redo->layer->group, redo->item);
672 // reinsert the item on its layer
673 redo->layer->items = g_list_append(redo->layer->items, redo->item);
674 redo->layer->nitems++;
676 else if (redo->type == ITEM_ERASURE || redo->type == ITEM_RECOGNIZER) {
677 for (list = redo->erasurelist; list!=NULL; list = list->next) {
678 erasure = (struct UndoErasureData *)list->data;
679 target = g_list_find(redo->layer->items, erasure->item);
680 // re-create all the created items
681 for (itemlist = erasure->replacement_items; itemlist!=NULL; itemlist = itemlist->next) {
682 it = (struct Item *)itemlist->data;
683 make_canvas_item_one(redo->layer->group, it);
684 redo->layer->items = g_list_insert_before(redo->layer->items, target, it);
685 redo->layer->nitems++;
686 lower_canvas_item_to(redo->layer->group, it->canvas_item, erasure->item->canvas_item);
688 // re-delete the deleted one
689 gtk_object_destroy(GTK_OBJECT(erasure->item->canvas_item));
690 erasure->item->canvas_item = NULL;
691 redo->layer->items = g_list_delete_link(redo->layer->items, target);
692 redo->layer->nitems--;
695 else if (redo->type == ITEM_NEW_BG_ONE || redo->type == ITEM_NEW_BG_RESIZE
696 || redo->type == ITEM_PAPER_RESIZE) {
697 if (redo->type != ITEM_PAPER_RESIZE) {
698 // swap the two bg's
699 tmp_bg = redo->page->bg;
700 redo->page->bg = redo->bg;
701 redo->bg = tmp_bg;
702 redo->page->bg->canvas_item = redo->bg->canvas_item;
703 redo->bg->canvas_item = NULL;
705 if (redo->type != ITEM_NEW_BG_ONE) {
706 tmp_x = redo->page->width;
707 tmp_y = redo->page->height;
708 redo->page->width = redo->val_x;
709 redo->page->height = redo->val_y;
710 redo->val_x = tmp_x;
711 redo->val_y = tmp_y;
712 make_page_clipbox(redo->page);
714 update_canvas_bg(redo->page);
715 do_switch_page(g_list_index(journal.pages, redo->page), TRUE, TRUE);
717 else if (redo->type == ITEM_NEW_DEFAULT_BG) {
718 tmp_bg = ui.default_page.bg;
719 ui.default_page.bg = redo->bg;
720 redo->bg = tmp_bg;
721 tmp_x = ui.default_page.width;
722 tmp_y = ui.default_page.height;
723 ui.default_page.width = redo->val_x;
724 ui.default_page.height = redo->val_y;
725 redo->val_x = tmp_x;
726 redo->val_y = tmp_y;
728 else if (redo->type == ITEM_NEW_PAGE) {
729 // remap the page
730 redo->page->bg->canvas_item = NULL;
731 redo->page->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
732 gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
733 make_page_clipbox(redo->page);
734 update_canvas_bg(redo->page);
735 l = (struct Layer *)redo->page->layers->data;
736 l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
737 redo->page->group, gnome_canvas_group_get_type(), NULL);
739 journal.pages = g_list_insert(journal.pages, redo->page, redo->val);
740 journal.npages++;
741 do_switch_page(redo->val, TRUE, TRUE);
743 else if (redo->type == ITEM_DELETE_PAGE) {
744 // unmap all the canvas items
745 gtk_object_destroy(GTK_OBJECT(redo->page->group));
746 redo->page->group = NULL;
747 redo->page->bg->canvas_item = NULL;
748 for (list = redo->page->layers; list!=NULL; list = list->next) {
749 l = (struct Layer *)list->data;
750 for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next)
751 ((struct Item *)itemlist->data)->canvas_item = NULL;
752 l->group = NULL;
754 journal.pages = g_list_remove(journal.pages, redo->page);
755 journal.npages--;
756 if (ui.pageno > redo->val || ui.pageno == journal.npages) ui.pageno--;
757 ui.cur_page = NULL;
758 // so do_switch_page() won't try to remap the layers of the defunct page
759 do_switch_page(ui.pageno, TRUE, TRUE);
761 else if (redo->type == ITEM_MOVESEL) {
762 for (itemlist = redo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
763 it = (struct Item *)itemlist->data;
764 if (it->canvas_item != NULL) {
765 if (redo->layer != redo->layer2)
766 gnome_canvas_item_reparent(it->canvas_item, redo->layer2->group);
767 gnome_canvas_item_move(it->canvas_item, redo->val_x, redo->val_y);
770 move_journal_items_by(redo->itemlist, redo->val_x, redo->val_y,
771 redo->layer, redo->layer2, NULL);
773 else if (redo->type == ITEM_RESIZESEL) {
774 resize_journal_items_by(redo->itemlist,
775 redo->scaling_x, redo->scaling_y, redo->val_x, redo->val_y);
777 else if (redo->type == ITEM_PASTE) {
778 for (itemlist = redo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
779 it = (struct Item *)itemlist->data;
780 make_canvas_item_one(redo->layer->group, it);
781 redo->layer->items = g_list_append(redo->layer->items, it);
782 redo->layer->nitems++;
785 else if (redo->type == ITEM_NEW_LAYER) {
786 redo->layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
787 redo->page->group, gnome_canvas_group_get_type(), NULL);
788 lower_canvas_item_to(redo->page->group, GNOME_CANVAS_ITEM(redo->layer->group),
789 (redo->val >= 1) ? GNOME_CANVAS_ITEM(((struct Layer *)
790 g_list_nth_data(redo->page->layers, redo->val-1))->group) :
791 redo->page->bg->canvas_item);
792 redo->page->layers = g_list_insert(redo->page->layers, redo->layer, redo->val);
793 redo->page->nlayers++;
794 do_switch_page(ui.pageno, FALSE, FALSE);
796 else if (redo->type == ITEM_DELETE_LAYER) {
797 gtk_object_destroy(GTK_OBJECT(redo->layer->group));
798 redo->layer->group = NULL;
799 for (list=redo->layer->items; list!=NULL; list=list->next)
800 ((struct Item *)list->data)->canvas_item = NULL;
801 redo->page->layers = g_list_remove(redo->page->layers, redo->layer);
802 redo->page->nlayers--;
803 if (redo->val == -1) {
804 redo->layer2->group = (GnomeCanvasGroup *)gnome_canvas_item_new(
805 redo->page->group, gnome_canvas_group_get_type(), NULL);
806 redo->page->layers = g_list_append(redo->page->layers, redo->layer2);
807 redo->page->nlayers++;
809 do_switch_page(ui.pageno, FALSE, FALSE);
811 else if (redo->type == ITEM_REPAINTSEL) {
812 for (itemlist = redo->itemlist, list = redo->auxlist; itemlist!=NULL;
813 itemlist = itemlist->next, list = list->next) {
814 it = (struct Item *)itemlist->data;
815 g_memmove(&tmp_brush, &(it->brush), sizeof(struct Brush));
816 g_memmove(&(it->brush), list->data, sizeof(struct Brush));
817 g_memmove(list->data, &tmp_brush, sizeof(struct Brush));
818 if (it->type == ITEM_STROKE && it->canvas_item != NULL) {
819 // remark: a variable-width item might have lost its variable-width
820 group = (GnomeCanvasGroup *) it->canvas_item->parent;
821 gtk_object_destroy(GTK_OBJECT(it->canvas_item));
822 make_canvas_item_one(group, it);
824 if (it->type == ITEM_TEXT && it->canvas_item != NULL)
825 gnome_canvas_item_set(it->canvas_item,
826 "fill-color-rgba", it->brush.color_rgba, NULL);
829 else if (redo->type == ITEM_TEXT_EDIT) {
830 tmpstr = redo->str;
831 redo->str = redo->item->text;
832 redo->item->text = tmpstr;
833 gnome_canvas_item_set(redo->item->canvas_item, "text", tmpstr, NULL);
834 update_item_bbox(redo->item);
836 else if (redo->type == ITEM_TEXT_ATTRIB) {
837 tmpstr = redo->str;
838 redo->str = redo->item->font_name;
839 redo->item->font_name = tmpstr;
840 tmp_x = redo->val_x;
841 redo->val_x = redo->item->font_size;
842 redo->item->font_size = tmp_x;
843 g_memmove(&tmp_brush, redo->brush, sizeof(struct Brush));
844 g_memmove(redo->brush, &(redo->item->brush), sizeof(struct Brush));
845 g_memmove(&(redo->item->brush), &tmp_brush, sizeof(struct Brush));
846 gnome_canvas_item_set(redo->item->canvas_item,
847 "fill-color-rgba", redo->item->brush.color_rgba, NULL);
848 update_text_item_displayfont(redo->item);
849 update_item_bbox(redo->item);
852 // move item from redo to undo stack
853 u = redo;
854 redo = redo->next;
855 u->next = undo;
856 undo = u;
857 ui.saved = FALSE;
858 update_undo_redo_enabled();
859 if (u->multiop & MULTIOP_CONT_REDO) on_editRedo_activate(NULL,NULL); // loop
863 void
864 on_editCut_activate (GtkMenuItem *menuitem,
865 gpointer user_data)
867 end_text();
868 selection_to_clip();
869 selection_delete();
873 void
874 on_editCopy_activate (GtkMenuItem *menuitem,
875 gpointer user_data)
877 end_text();
878 selection_to_clip();
882 void
883 on_editPaste_activate (GtkMenuItem *menuitem,
884 gpointer user_data)
886 end_text();
887 clipboard_paste();
891 void
892 on_editDelete_activate (GtkMenuItem *menuitem,
893 gpointer user_data)
895 end_text();
896 selection_delete();
900 void
901 on_viewContinuous_activate (GtkMenuItem *menuitem,
902 gpointer user_data)
904 GtkAdjustment *v_adj;
905 double yscroll;
906 struct Page *pg;
908 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
909 if (ui.view_continuous) return;
910 ui.view_continuous = TRUE;
911 v_adj = gtk_layout_get_vadjustment(GTK_LAYOUT(canvas));
912 pg = ui.cur_page;
913 yscroll = gtk_adjustment_get_value(v_adj) - pg->voffset*ui.zoom;
914 update_page_stuff();
915 gtk_adjustment_set_value(v_adj, yscroll + pg->voffset*ui.zoom);
916 // force a refresh
917 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
921 void
922 on_viewOnePage_activate (GtkMenuItem *menuitem,
923 gpointer user_data)
925 GtkAdjustment *v_adj;
926 double yscroll;
928 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
929 if (!ui.view_continuous) return;
930 ui.view_continuous = FALSE;
931 v_adj = gtk_layout_get_vadjustment(GTK_LAYOUT(canvas));
932 yscroll = gtk_adjustment_get_value(v_adj) - ui.cur_page->voffset*ui.zoom;
933 update_page_stuff();
934 gtk_adjustment_set_value(v_adj, yscroll + ui.cur_page->voffset*ui.zoom);
935 // force a refresh
936 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
940 void
941 on_viewZoomIn_activate (GtkMenuItem *menuitem,
942 gpointer user_data)
944 if (ui.zoom > MAX_ZOOM) return;
945 ui.zoom *= ui.zoom_step_factor;
946 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
947 rescale_text_items();
948 rescale_bg_pixmaps();
952 void
953 on_viewZoomOut_activate (GtkMenuItem *menuitem,
954 gpointer user_data)
956 if (ui.zoom < MIN_ZOOM) return;
957 ui.zoom /= ui.zoom_step_factor;
958 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
959 rescale_text_items();
960 rescale_bg_pixmaps();
964 void
965 on_viewNormalSize_activate (GtkMenuItem *menuitem,
966 gpointer user_data)
968 ui.zoom = DEFAULT_ZOOM;
969 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
970 rescale_text_items();
971 rescale_bg_pixmaps();
975 void
976 on_viewPageWidth_activate (GtkMenuItem *menuitem,
977 gpointer user_data)
979 ui.zoom = (GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width;
980 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
981 rescale_text_items();
982 rescale_bg_pixmaps();
986 void
987 on_viewFirstPage_activate (GtkMenuItem *menuitem,
988 gpointer user_data)
990 end_text();
991 do_switch_page(0, TRUE, FALSE);
995 void
996 on_viewPreviousPage_activate (GtkMenuItem *menuitem,
997 gpointer user_data)
999 end_text();
1000 if (ui.pageno == 0) return;
1001 do_switch_page(ui.pageno-1, TRUE, FALSE);
1005 void
1006 on_viewNextPage_activate (GtkMenuItem *menuitem,
1007 gpointer user_data)
1009 end_text();
1010 if (ui.pageno == journal.npages-1) { // create a page at end
1011 on_journalNewPageEnd_activate(menuitem, user_data);
1012 return;
1014 do_switch_page(ui.pageno+1, TRUE, FALSE);
1018 void
1019 on_viewLastPage_activate (GtkMenuItem *menuitem,
1020 gpointer user_data)
1022 end_text();
1023 do_switch_page(journal.npages-1, TRUE, FALSE);
1027 void
1028 on_viewShowLayer_activate (GtkMenuItem *menuitem,
1029 gpointer user_data)
1031 end_text();
1032 if (ui.layerno == ui.cur_page->nlayers-1) return;
1033 reset_selection();
1034 ui.layerno++;
1035 ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
1036 gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group));
1037 update_page_stuff();
1041 void
1042 on_viewHideLayer_activate (GtkMenuItem *menuitem,
1043 gpointer user_data)
1045 end_text();
1046 if (ui.layerno == -1) return;
1047 reset_selection();
1048 gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group));
1049 ui.layerno--;
1050 if (ui.layerno<0) ui.cur_layer = NULL;
1051 else ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
1052 update_page_stuff();
1056 void
1057 on_journalNewPageBefore_activate (GtkMenuItem *menuitem,
1058 gpointer user_data)
1060 struct Page *pg;
1062 end_text();
1063 reset_selection();
1064 pg = new_page(ui.cur_page);
1065 journal.pages = g_list_insert(journal.pages, pg, ui.pageno);
1066 journal.npages++;
1067 do_switch_page(ui.pageno, TRUE, TRUE);
1069 prepare_new_undo();
1070 undo->type = ITEM_NEW_PAGE;
1071 undo->val = ui.pageno;
1072 undo->page = pg;
1076 void
1077 on_journalNewPageAfter_activate (GtkMenuItem *menuitem,
1078 gpointer user_data)
1080 struct Page *pg;
1082 end_text();
1083 reset_selection();
1084 pg = new_page(ui.cur_page);
1085 journal.pages = g_list_insert(journal.pages, pg, ui.pageno+1);
1086 journal.npages++;
1087 do_switch_page(ui.pageno+1, TRUE, TRUE);
1089 prepare_new_undo();
1090 undo->type = ITEM_NEW_PAGE;
1091 undo->val = ui.pageno;
1092 undo->page = pg;
1096 void
1097 on_journalNewPageEnd_activate (GtkMenuItem *menuitem,
1098 gpointer user_data)
1100 struct Page *pg;
1102 end_text();
1103 reset_selection();
1104 pg = new_page((struct Page *)g_list_last(journal.pages)->data);
1105 journal.pages = g_list_append(journal.pages, pg);
1106 journal.npages++;
1107 do_switch_page(journal.npages-1, TRUE, TRUE);
1109 prepare_new_undo();
1110 undo->type = ITEM_NEW_PAGE;
1111 undo->val = ui.pageno;
1112 undo->page = pg;
1116 void
1117 on_journalDeletePage_activate (GtkMenuItem *menuitem,
1118 gpointer user_data)
1120 GList *layerlist, *itemlist;
1121 struct Layer *l;
1123 end_text();
1124 if (journal.npages == 1) return;
1125 reset_selection();
1126 reset_recognizer(); // safer
1127 prepare_new_undo();
1128 undo->type = ITEM_DELETE_PAGE;
1129 undo->val = ui.pageno;
1130 undo->page = ui.cur_page;
1132 // unmap all the canvas items
1133 gtk_object_destroy(GTK_OBJECT(ui.cur_page->group));
1134 ui.cur_page->group = NULL;
1135 ui.cur_page->bg->canvas_item = NULL;
1136 for (layerlist = ui.cur_page->layers; layerlist!=NULL; layerlist = layerlist->next) {
1137 l = (struct Layer *)layerlist->data;
1138 for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next)
1139 ((struct Item *)itemlist->data)->canvas_item = NULL;
1140 l->group = NULL;
1143 journal.pages = g_list_remove(journal.pages, ui.cur_page);
1144 journal.npages--;
1145 if (ui.pageno == journal.npages) ui.pageno--;
1146 ui.cur_page = NULL;
1147 // so do_switch_page() won't try to remap the layers of the defunct page
1148 do_switch_page(ui.pageno, TRUE, TRUE);
1152 void
1153 on_journalNewLayer_activate (GtkMenuItem *menuitem,
1154 gpointer user_data)
1156 struct Layer *l;
1158 end_text();
1159 reset_selection();
1160 l = g_new(struct Layer, 1);
1161 l->items = NULL;
1162 l->nitems = 0;
1163 l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
1164 ui.cur_page->group, gnome_canvas_group_get_type(), NULL);
1165 lower_canvas_item_to(ui.cur_page->group, GNOME_CANVAS_ITEM(l->group),
1166 (ui.cur_layer!=NULL)?(GNOME_CANVAS_ITEM(ui.cur_layer->group)):(ui.cur_page->bg->canvas_item));
1167 ui.cur_page->layers = g_list_insert(ui.cur_page->layers, l, ui.layerno+1);
1168 ui.cur_layer = l;
1169 ui.layerno++;
1170 ui.cur_page->nlayers++;
1171 update_page_stuff();
1173 prepare_new_undo();
1174 undo->type = ITEM_NEW_LAYER;
1175 undo->val = ui.layerno;
1176 undo->layer = l;
1177 undo->page = ui.cur_page;
1181 void
1182 on_journalDeleteLayer_activate (GtkMenuItem *menuitem,
1183 gpointer user_data)
1185 GList *list;
1187 end_text();
1188 if (ui.cur_layer == NULL) return;
1189 reset_selection();
1190 reset_recognizer(); // safer
1191 prepare_new_undo();
1192 undo->type = ITEM_DELETE_LAYER;
1193 undo->val = ui.layerno;
1194 undo->layer = ui.cur_layer;
1195 undo->layer2 = NULL;
1196 undo->page = ui.cur_page;
1197 // delete all the canvas items
1198 gtk_object_destroy(GTK_OBJECT(ui.cur_layer->group));
1199 ui.cur_layer->group = NULL;
1200 for (list=ui.cur_layer->items; list!=NULL; list=list->next)
1201 ((struct Item *)list->data)->canvas_item = NULL;
1203 ui.cur_page->layers = g_list_remove(ui.cur_page->layers, ui.cur_layer);
1205 if (ui.cur_page->nlayers>=2) {
1206 ui.cur_page->nlayers--;
1207 ui.layerno--;
1208 if (ui.layerno<0) ui.cur_layer = NULL;
1209 else ui.cur_layer = (struct Layer *)g_list_nth_data(ui.cur_page->layers, ui.layerno);
1211 else { // special case: can't remove the last layer
1212 ui.cur_layer = g_new(struct Layer, 1);
1213 ui.cur_layer->items = NULL;
1214 ui.cur_layer->nitems = 0;
1215 ui.cur_layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
1216 ui.cur_page->group, gnome_canvas_group_get_type(), NULL);
1217 ui.cur_page->layers = g_list_append(NULL, ui.cur_layer);
1218 undo->val = -1;
1219 undo->layer2 = ui.cur_layer;
1222 update_page_stuff();
1226 void
1227 on_journalFlatten_activate (GtkMenuItem *menuitem,
1228 gpointer user_data)
1234 // the paper sizes dialog
1236 GtkWidget *papersize_dialog;
1237 int papersize_std, papersize_unit;
1238 double papersize_width, papersize_height;
1239 gboolean papersize_need_init, papersize_width_valid, papersize_height_valid;
1241 #define STD_SIZE_A4 0
1242 #define STD_SIZE_A4R 1
1243 #define STD_SIZE_LETTER 2
1244 #define STD_SIZE_LETTER_R 3
1245 #define STD_SIZE_CUSTOM 4
1247 double unit_sizes[4] = {28.346, 72., 72./DISPLAY_DPI_DEFAULT, 1.};
1248 double std_widths[STD_SIZE_CUSTOM] = {595.27, 841.89, 612., 792.};
1249 double std_heights[STD_SIZE_CUSTOM] = {841.89, 595.27, 792., 612.};
1250 double std_units[STD_SIZE_CUSTOM] = {UNIT_CM, UNIT_CM, UNIT_IN, UNIT_IN};
1252 void
1253 on_journalPaperSize_activate (GtkMenuItem *menuitem,
1254 gpointer user_data)
1256 int i, response;
1257 struct Page *pg;
1258 GList *pglist;
1260 end_text();
1261 papersize_dialog = create_papersizeDialog();
1262 papersize_width = ui.cur_page->width;
1263 papersize_height = ui.cur_page->height;
1264 papersize_unit = ui.default_unit;
1265 unit_sizes[UNIT_PX] = 1./DEFAULT_ZOOM;
1266 // if (ui.cur_page->bg->type == BG_PIXMAP) papersize_unit = UNIT_PX;
1267 papersize_std = STD_SIZE_CUSTOM;
1268 for (i=0;i<STD_SIZE_CUSTOM;i++)
1269 if (fabs(papersize_width - std_widths[i])<0.1 &&
1270 fabs(papersize_height - std_heights[i])<0.1)
1271 { papersize_std = i; papersize_unit = std_units[i]; }
1272 papersize_need_init = TRUE;
1273 papersize_width_valid = papersize_height_valid = TRUE;
1275 gtk_widget_show(papersize_dialog);
1276 on_comboStdSizes_changed(GTK_COMBO_BOX(g_object_get_data(
1277 G_OBJECT(papersize_dialog), "comboStdSizes")), NULL);
1278 gtk_dialog_set_default_response(GTK_DIALOG(papersize_dialog), GTK_RESPONSE_OK);
1280 response = gtk_dialog_run(GTK_DIALOG(papersize_dialog));
1281 gtk_widget_destroy(papersize_dialog);
1282 if (response != GTK_RESPONSE_OK) return;
1284 pg = ui.cur_page;
1285 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
1286 if (ui.bg_apply_all_pages) pg = (struct Page *)pglist->data;
1287 prepare_new_undo();
1288 if (ui.bg_apply_all_pages) {
1289 if (pglist->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
1290 if (pglist->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
1292 undo->type = ITEM_PAPER_RESIZE;
1293 undo->page = pg;
1294 undo->val_x = pg->width;
1295 undo->val_y = pg->height;
1296 if (papersize_width_valid) pg->width = papersize_width;
1297 if (papersize_height_valid) pg->height = papersize_height;
1298 make_page_clipbox(pg);
1299 update_canvas_bg(pg);
1300 if (!ui.bg_apply_all_pages) break;
1302 do_switch_page(ui.pageno, TRUE, TRUE);
1306 void
1307 on_papercolorWhite_activate (GtkMenuItem *menuitem,
1308 gpointer user_data)
1310 end_text();
1311 process_papercolor_activate(menuitem, COLOR_WHITE, predef_bgcolors_rgba[COLOR_WHITE]);
1315 void
1316 on_papercolorYellow_activate (GtkMenuItem *menuitem,
1317 gpointer user_data)
1319 end_text();
1320 process_papercolor_activate(menuitem, COLOR_YELLOW, predef_bgcolors_rgba[COLOR_YELLOW]);
1324 void
1325 on_papercolorPink_activate (GtkMenuItem *menuitem,
1326 gpointer user_data)
1328 end_text();
1329 process_papercolor_activate(menuitem, COLOR_RED, predef_bgcolors_rgba[COLOR_RED]);
1333 void
1334 on_papercolorOrange_activate (GtkMenuItem *menuitem,
1335 gpointer user_data)
1337 end_text();
1338 process_papercolor_activate(menuitem, COLOR_ORANGE, predef_bgcolors_rgba[COLOR_ORANGE]);
1342 void
1343 on_papercolorBlue_activate (GtkMenuItem *menuitem,
1344 gpointer user_data)
1346 end_text();
1347 process_papercolor_activate(menuitem, COLOR_BLUE, predef_bgcolors_rgba[COLOR_BLUE]);
1351 void
1352 on_papercolorGreen_activate (GtkMenuItem *menuitem,
1353 gpointer user_data)
1355 end_text();
1356 process_papercolor_activate(menuitem, COLOR_GREEN, predef_bgcolors_rgba[COLOR_GREEN]);
1360 void
1361 on_papercolorOther_activate (GtkMenuItem *menuitem,
1362 gpointer user_data)
1364 GtkWidget *dialog;
1365 GtkColorSelection *colorsel;
1366 gint result;
1367 guint rgba;
1368 GdkColor gdkcolor;
1370 end_text();
1371 dialog = gtk_color_selection_dialog_new(_("Pick a Paper Color"));
1372 colorsel = GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(dialog)->colorsel);
1373 if (ui.cur_page->bg->type == BG_SOLID) rgba = ui.cur_page->bg->color_rgba;
1374 else rgba = ui.default_page.bg->color_rgba;
1375 rgb_to_gdkcolor(rgba, &gdkcolor);
1376 gtk_color_selection_set_current_color(colorsel, &gdkcolor);
1378 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) {
1379 gtk_color_selection_get_current_color(colorsel, &gdkcolor);
1380 process_papercolor_activate(menuitem, COLOR_OTHER, gdkcolor_to_rgba(gdkcolor, 0xffff));
1382 gtk_widget_destroy(dialog);
1386 void
1387 on_paperstylePlain_activate (GtkMenuItem *menuitem,
1388 gpointer user_data)
1390 end_text();
1391 process_paperstyle_activate(menuitem, RULING_NONE);
1395 void
1396 on_paperstyleLined_activate (GtkMenuItem *menuitem,
1397 gpointer user_data)
1399 end_text();
1400 process_paperstyle_activate(menuitem, RULING_LINED);
1404 void
1405 on_paperstyleRuled_activate (GtkMenuItem *menuitem,
1406 gpointer user_data)
1408 end_text();
1409 process_paperstyle_activate(menuitem, RULING_RULED);
1413 void
1414 on_paperstyleGraph_activate (GtkMenuItem *menuitem,
1415 gpointer user_data)
1417 end_text();
1418 process_paperstyle_activate(menuitem, RULING_GRAPH);
1422 void
1423 on_journalLoadBackground_activate (GtkMenuItem *menuitem,
1424 gpointer user_data)
1426 GtkWidget *dialog, *attach_opt;
1427 struct Background *bg;
1428 struct Page *pg;
1429 int pageno;
1430 GList *bglist, *bglistiter;
1431 GtkFileFilter *filt_all, *filt_pix, *filt_pspdf;
1432 char *filename;
1433 gboolean attach;
1435 end_text();
1436 dialog = gtk_file_chooser_dialog_new(_("Open Background"), GTK_WINDOW (winMain),
1437 GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1438 GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
1439 #ifdef FILE_DIALOG_SIZE_BUGFIX
1440 gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400);
1441 #endif
1443 filt_all = gtk_file_filter_new();
1444 gtk_file_filter_set_name(filt_all, _("All files"));
1445 gtk_file_filter_add_pattern(filt_all, "*");
1446 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
1448 #if GTK_CHECK_VERSION(2,6,0)
1450 if (!gtk_check_version(2, 6, 0)) {
1451 filt_pix = gtk_file_filter_new();
1452 gtk_file_filter_set_name(filt_pix, _("Bitmap files"));
1453 gtk_file_filter_add_pixbuf_formats(filt_pix);
1454 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pix);
1457 #endif
1459 filt_pspdf = gtk_file_filter_new();
1460 gtk_file_filter_set_name(filt_pspdf, _("PS/PDF files (as bitmaps)"));
1461 gtk_file_filter_add_pattern(filt_pspdf, "*.ps");
1462 gtk_file_filter_add_pattern(filt_pspdf, "*.PS");
1463 gtk_file_filter_add_pattern(filt_pspdf, "*.pdf");
1464 gtk_file_filter_add_pattern(filt_pspdf, "*.PDF");
1465 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pspdf);
1467 attach_opt = gtk_check_button_new_with_label(_("Attach file to the journal"));
1468 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(attach_opt), FALSE);
1469 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER (dialog), attach_opt);
1471 if (ui.default_path!=NULL) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
1473 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
1474 gtk_widget_destroy(dialog);
1475 return;
1477 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1478 attach = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(attach_opt));
1479 gtk_widget_destroy(dialog);
1481 set_cursor_busy(TRUE);
1482 bg = attempt_load_pix_bg(filename, attach);
1483 if (bg != NULL) bglist = g_list_append(NULL, bg);
1484 else bglist = attempt_load_gv_bg(filename);
1485 set_cursor_busy(FALSE);
1487 if (bglist == NULL) {
1488 dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL,
1489 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
1490 _("Error opening background '%s'"), filename);
1491 gtk_dialog_run(GTK_DIALOG(dialog));
1492 gtk_widget_destroy(dialog);
1493 g_free(filename);
1494 return;
1497 g_free(filename);
1498 reset_selection();
1499 pageno = ui.pageno;
1501 for (bglistiter = bglist, pageno = ui.pageno;
1502 bglistiter!=NULL; bglistiter = bglistiter->next, pageno++) {
1503 prepare_new_undo();
1504 if (bglistiter->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
1505 if (bglistiter->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
1507 bg = (struct Background *)bglistiter->data;
1509 if (pageno == journal.npages) {
1510 undo->type = ITEM_NEW_PAGE;
1511 pg = new_page_with_bg(bg,
1512 gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale,
1513 gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale);
1514 journal.pages = g_list_append(journal.pages, pg);
1515 journal.npages++;
1516 undo->val = pageno;
1517 undo->page = pg;
1518 } else
1520 pg = g_list_nth_data(journal.pages, pageno);
1521 undo->type = ITEM_NEW_BG_RESIZE;
1522 undo->page = pg;
1523 undo->bg = pg->bg;
1524 bg->canvas_item = undo->bg->canvas_item;
1525 undo->bg->canvas_item = NULL;
1526 undo->val_x = pg->width;
1527 undo->val_y = pg->height;
1528 pg->bg = bg;
1529 pg->width = gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale;
1530 pg->height = gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale;
1531 make_page_clipbox(pg);
1532 update_canvas_bg(pg);
1536 g_list_free(bglist);
1537 if (ui.zoom != DEFAULT_ZOOM) {
1538 ui.zoom = DEFAULT_ZOOM;
1539 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
1540 rescale_text_items();
1541 rescale_bg_pixmaps();
1543 do_switch_page(ui.pageno, TRUE, TRUE);
1546 void
1547 on_journalScreenshot_activate (GtkMenuItem *menuitem,
1548 gpointer user_data)
1550 struct Background *bg;
1552 end_text();
1553 reset_selection();
1554 gtk_window_iconify(GTK_WINDOW(winMain)); // hide ourselves
1555 gdk_display_sync(gdk_display_get_default());
1557 if (ui.cursor!=NULL)
1558 gdk_cursor_unref(ui.cursor);
1559 ui.cursor = gdk_cursor_new(GDK_TCROSS);
1561 bg = attempt_screenshot_bg();
1563 gtk_window_deiconify(GTK_WINDOW(winMain));
1564 update_cursor();
1565 if (bg==NULL) return;
1567 prepare_new_undo();
1568 undo->type = ITEM_NEW_BG_RESIZE;
1569 undo->page = ui.cur_page;
1570 undo->bg = ui.cur_page->bg;
1571 bg->canvas_item = undo->bg->canvas_item;
1572 undo->bg->canvas_item = NULL;
1573 undo->val_x = ui.cur_page->width;
1574 undo->val_y = ui.cur_page->height;
1576 ui.cur_page->bg = bg;
1577 ui.cur_page->width = gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale;
1578 ui.cur_page->height = gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale;
1580 make_page_clipbox(ui.cur_page);
1581 update_canvas_bg(ui.cur_page);
1583 if (ui.zoom != DEFAULT_ZOOM) {
1584 ui.zoom = DEFAULT_ZOOM;
1585 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
1586 rescale_text_items();
1587 rescale_bg_pixmaps();
1589 do_switch_page(ui.pageno, TRUE, TRUE);
1593 void
1594 on_journalApplyAllPages_activate (GtkMenuItem *menuitem,
1595 gpointer user_data)
1597 gboolean active;
1599 end_text();
1600 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
1601 if (active == ui.bg_apply_all_pages) return;
1602 ui.bg_apply_all_pages = active;
1603 update_page_stuff();
1605 /* THIS IS THE OLD VERSION OF THE FEATURE -- APPLIED CURRENT BG TO ALL
1606 struct Page *page;
1607 GList *pglist;
1609 if (ui.cur_page->bg->type != BG_SOLID) return;
1610 reset_selection();
1611 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
1612 page = (struct Page *)pglist->data;
1613 prepare_new_undo();
1614 undo->type = ITEM_NEW_BG_RESIZE;
1615 undo->page = page;
1616 undo->bg = page->bg;
1617 undo->val_x = page->width;
1618 undo->val_y = page->height;
1619 if (pglist->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
1620 if (pglist->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
1621 page->bg = (struct Background *)g_memdup(ui.cur_page->bg, sizeof(struct Background));
1622 page->width = ui.cur_page->width;
1623 page->height = ui.cur_page->height;
1624 page->bg->canvas_item = undo->bg->canvas_item;
1625 undo->bg->canvas_item = NULL;
1627 make_page_clipbox(page);
1628 update_canvas_bg(page);
1630 do_switch_page(ui.pageno, TRUE, TRUE);
1636 void
1637 on_toolsPen_activate (GtkMenuItem *menuitem,
1638 gpointer user_data)
1640 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1641 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1642 return;
1643 } else {
1644 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1645 return;
1648 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1649 if (ui.toolno[ui.cur_mapping] == TOOL_PEN) return;
1651 ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1652 end_text();
1653 reset_selection();
1654 ui.toolno[ui.cur_mapping] = TOOL_PEN;
1655 ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
1656 ui.cur_brush->ruler = ui.default_brushes[TOOL_PEN].ruler;
1657 ui.cur_brush->recognizer = ui.default_brushes[TOOL_PEN].recognizer;
1658 update_mapping_linkings(TOOL_PEN);
1659 update_tool_buttons();
1660 update_tool_menu();
1661 update_color_menu();
1662 update_cursor();
1666 void
1667 on_toolsEraser_activate (GtkMenuItem *menuitem,
1668 gpointer user_data)
1670 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1671 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1672 return;
1673 } else {
1674 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1675 return;
1678 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1679 if (ui.toolno[ui.cur_mapping] == TOOL_ERASER) return;
1681 ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1682 end_text();
1683 reset_selection();
1684 ui.toolno[ui.cur_mapping] = TOOL_ERASER;
1685 ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_ERASER]);
1686 update_mapping_linkings(TOOL_ERASER);
1687 update_tool_buttons();
1688 update_tool_menu();
1689 update_color_menu();
1690 update_cursor();
1694 void
1695 on_toolsHighlighter_activate (GtkMenuItem *menuitem,
1696 gpointer user_data)
1698 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1699 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1700 return;
1701 } else {
1702 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1703 return;
1706 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1707 if (ui.toolno[ui.cur_mapping] == TOOL_HIGHLIGHTER) return;
1709 ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1710 end_text();
1711 reset_selection();
1712 ui.toolno[ui.cur_mapping] = TOOL_HIGHLIGHTER;
1713 ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_HIGHLIGHTER]);
1714 ui.cur_brush->ruler = ui.default_brushes[TOOL_HIGHLIGHTER].ruler;
1715 ui.cur_brush->recognizer = ui.default_brushes[TOOL_HIGHLIGHTER].recognizer;
1716 update_mapping_linkings(TOOL_HIGHLIGHTER);
1717 update_tool_buttons();
1718 update_tool_menu();
1719 update_color_menu();
1720 update_cursor();
1724 void
1725 on_toolsText_activate (GtkMenuItem *menuitem,
1726 gpointer user_data)
1728 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1729 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1730 return;
1731 } else {
1732 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1733 return;
1736 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1737 if (ui.toolno[ui.cur_mapping] == TOOL_TEXT) return;
1739 ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1740 reset_selection();
1741 ui.toolno[ui.cur_mapping] = TOOL_TEXT;
1742 ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
1743 update_mapping_linkings(-1);
1744 update_tool_buttons();
1745 update_tool_menu();
1746 update_color_menu();
1747 update_cursor();
1751 void
1752 on_toolsSelectRegion_activate (GtkMenuItem *menuitem,
1753 gpointer user_data)
1759 void
1760 on_toolsSelectRectangle_activate (GtkMenuItem *menuitem,
1761 gpointer user_data)
1763 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1764 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1765 return;
1766 } else {
1767 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1768 return;
1771 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1772 if (ui.toolno[ui.cur_mapping] == TOOL_SELECTRECT) return;
1774 ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1775 end_text();
1776 ui.toolno[ui.cur_mapping] = TOOL_SELECTRECT;
1777 update_mapping_linkings(-1);
1778 update_tool_buttons();
1779 update_tool_menu();
1780 update_color_menu();
1781 update_cursor();
1785 void
1786 on_toolsVerticalSpace_activate (GtkMenuItem *menuitem,
1787 gpointer user_data)
1789 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1790 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1791 return;
1792 } else {
1793 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1794 return;
1797 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return; // not user-generated
1798 if (ui.toolno[ui.cur_mapping] == TOOL_VERTSPACE) return;
1800 ui.cur_mapping = 0; // don't use switch_mapping() (refreshes buttons too soon)
1801 end_text();
1802 reset_selection();
1803 ui.toolno[ui.cur_mapping] = TOOL_VERTSPACE;
1804 update_mapping_linkings(-1);
1805 update_tool_buttons();
1806 update_tool_menu();
1807 update_color_menu();
1808 update_cursor();
1812 void
1813 on_colorBlack_activate (GtkMenuItem *menuitem,
1814 gpointer user_data)
1816 process_color_activate(menuitem, COLOR_BLACK, predef_colors_rgba[COLOR_BLACK]);
1820 void
1821 on_colorBlue_activate (GtkMenuItem *menuitem,
1822 gpointer user_data)
1824 process_color_activate(menuitem, COLOR_BLUE, predef_colors_rgba[COLOR_BLUE]);
1828 void
1829 on_colorRed_activate (GtkMenuItem *menuitem,
1830 gpointer user_data)
1832 process_color_activate(menuitem, COLOR_RED, predef_colors_rgba[COLOR_RED]);
1836 void
1837 on_colorGreen_activate (GtkMenuItem *menuitem,
1838 gpointer user_data)
1840 process_color_activate(menuitem, COLOR_GREEN, predef_colors_rgba[COLOR_GREEN]);
1844 void
1845 on_colorGray_activate (GtkMenuItem *menuitem,
1846 gpointer user_data)
1848 process_color_activate(menuitem, COLOR_GRAY, predef_colors_rgba[COLOR_GRAY]);
1852 void
1853 on_colorLightBlue_activate (GtkMenuItem *menuitem,
1854 gpointer user_data)
1856 process_color_activate(menuitem, COLOR_LIGHTBLUE, predef_colors_rgba[COLOR_LIGHTBLUE]);
1860 void
1861 on_colorLightGreen_activate (GtkMenuItem *menuitem,
1862 gpointer user_data)
1864 process_color_activate(menuitem, COLOR_LIGHTGREEN, predef_colors_rgba[COLOR_LIGHTGREEN]);
1868 void
1869 on_colorMagenta_activate (GtkMenuItem *menuitem,
1870 gpointer user_data)
1872 process_color_activate(menuitem, COLOR_MAGENTA, predef_colors_rgba[COLOR_MAGENTA]);
1876 void
1877 on_colorOrange_activate (GtkMenuItem *menuitem,
1878 gpointer user_data)
1880 process_color_activate(menuitem, COLOR_ORANGE, predef_colors_rgba[COLOR_ORANGE]);
1884 void
1885 on_colorYellow_activate (GtkMenuItem *menuitem,
1886 gpointer user_data)
1888 process_color_activate(menuitem, COLOR_YELLOW, predef_colors_rgba[COLOR_YELLOW]);
1892 void
1893 on_colorWhite_activate (GtkMenuItem *menuitem,
1894 gpointer user_data)
1896 process_color_activate(menuitem, COLOR_WHITE, predef_colors_rgba[COLOR_WHITE]);
1900 void
1901 on_colorOther_activate (GtkMenuItem *menuitem,
1902 gpointer user_data)
1904 gtk_button_clicked(GTK_BUTTON(GET_COMPONENT("buttonColorChooser")));
1908 void
1909 on_penthicknessVeryFine_activate (GtkMenuItem *menuitem,
1910 gpointer user_data)
1912 process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_VERYFINE);
1916 void
1917 on_penthicknessFine_activate (GtkMenuItem *menuitem,
1918 gpointer user_data)
1920 process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_FINE);
1924 void
1925 on_penthicknessMedium_activate (GtkMenuItem *menuitem,
1926 gpointer user_data)
1928 process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_MEDIUM);
1932 void
1933 on_penthicknessThick_activate (GtkMenuItem *menuitem,
1934 gpointer user_data)
1936 process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_THICK);
1940 void
1941 on_penthicknessVeryThick_activate (GtkMenuItem *menuitem,
1942 gpointer user_data)
1944 process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_VERYTHICK);
1948 void
1949 on_eraserFine_activate (GtkMenuItem *menuitem,
1950 gpointer user_data)
1952 process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_FINE);
1956 void
1957 on_eraserMedium_activate (GtkMenuItem *menuitem,
1958 gpointer user_data)
1960 process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_MEDIUM);
1964 void
1965 on_eraserThick_activate (GtkMenuItem *menuitem,
1966 gpointer user_data)
1968 process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_THICK);
1972 void
1973 on_eraserStandard_activate (GtkMenuItem *menuitem,
1974 gpointer user_data)
1976 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
1977 end_text();
1978 ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_STANDARD;
1979 update_mapping_linkings(TOOL_ERASER);
1983 void
1984 on_eraserWhiteout_activate (GtkMenuItem *menuitem,
1985 gpointer user_data)
1987 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
1988 end_text();
1989 ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_WHITEOUT;
1990 update_mapping_linkings(TOOL_ERASER);
1994 void
1995 on_eraserDeleteStrokes_activate (GtkMenuItem *menuitem,
1996 gpointer user_data)
1998 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
1999 end_text();
2000 ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_STROKES;
2001 update_mapping_linkings(TOOL_ERASER);
2005 void
2006 on_highlighterFine_activate (GtkMenuItem *menuitem,
2007 gpointer user_data)
2009 process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_FINE);
2013 void
2014 on_highlighterMedium_activate (GtkMenuItem *menuitem,
2015 gpointer user_data)
2017 process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_MEDIUM);
2021 void
2022 on_highlighterThick_activate (GtkMenuItem *menuitem,
2023 gpointer user_data)
2025 process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_THICK);
2029 void
2030 on_toolsTextFont_activate (GtkMenuItem *menuitem,
2031 gpointer user_data)
2033 GtkWidget *dialog;
2034 gchar *str;
2036 dialog = gtk_font_selection_dialog_new(_("Select Font"));
2037 str = make_cur_font_name();
2038 gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dialog), str);
2039 g_free(str);
2040 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
2041 gtk_widget_destroy(dialog);
2042 return;
2044 str = gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(dialog));
2045 gtk_widget_destroy(dialog);
2046 process_font_sel(str);
2049 void
2050 on_toolsDefaultPen_activate (GtkMenuItem *menuitem,
2051 gpointer user_data)
2053 switch_mapping(0);
2054 end_text();
2055 reset_selection();
2056 g_memmove(&(ui.brushes[0][TOOL_PEN]), ui.default_brushes+TOOL_PEN, sizeof(struct Brush));
2057 ui.toolno[0] = TOOL_PEN;
2058 ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
2059 update_mapping_linkings(TOOL_PEN);
2060 update_tool_buttons();
2061 update_tool_menu();
2062 update_pen_props_menu();
2063 update_color_menu();
2064 update_cursor();
2068 void
2069 on_toolsDefaultEraser_activate (GtkMenuItem *menuitem,
2070 gpointer user_data)
2072 switch_mapping(0);
2073 end_text();
2074 reset_selection();
2075 g_memmove(&(ui.brushes[0][TOOL_ERASER]), ui.default_brushes+TOOL_ERASER, sizeof(struct Brush));
2076 ui.toolno[0] = TOOL_ERASER;
2077 ui.cur_brush = &(ui.brushes[0][TOOL_ERASER]);
2078 update_mapping_linkings(TOOL_ERASER);
2079 update_tool_buttons();
2080 update_tool_menu();
2081 update_eraser_props_menu();
2082 update_color_menu();
2083 update_cursor();
2087 void
2088 on_toolsDefaultHighlighter_activate (GtkMenuItem *menuitem,
2089 gpointer user_data)
2091 switch_mapping(0);
2092 end_text();
2093 reset_selection();
2094 g_memmove(&(ui.brushes[0][TOOL_HIGHLIGHTER]), ui.default_brushes+TOOL_HIGHLIGHTER, sizeof(struct Brush));
2095 ui.toolno[0] = TOOL_HIGHLIGHTER;
2096 ui.cur_brush = &(ui.brushes[0][TOOL_HIGHLIGHTER]);
2097 update_mapping_linkings(TOOL_HIGHLIGHTER);
2098 update_tool_buttons();
2099 update_tool_menu();
2100 update_highlighter_props_menu();
2101 update_color_menu();
2102 update_cursor();
2105 void
2106 on_toolsDefaultText_activate (GtkMenuItem *menuitem,
2107 gpointer user_data)
2109 switch_mapping(0);
2110 if (ui.toolno[0]!=TOOL_TEXT) end_text();
2111 reset_selection();
2112 ui.toolno[0] = TOOL_TEXT;
2113 ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
2114 ui.cur_brush->color_no = ui.default_brushes[TOOL_PEN].color_no;
2115 ui.cur_brush->color_rgba = ui.default_brushes[TOOL_PEN].color_rgba;
2116 g_free(ui.font_name);
2117 ui.font_name = g_strdup(ui.default_font_name);
2118 ui.font_size = ui.default_font_size;
2119 if (ui.cur_item_type == ITEM_TEXT) {
2120 refont_text_item(ui.cur_item, ui.font_name, ui.font_size);
2122 update_font_button();
2123 update_mapping_linkings(-1);
2124 update_tool_buttons();
2125 update_tool_menu();
2126 update_color_menu();
2127 update_cursor();
2131 void
2132 on_toolsSetAsDefault_activate (GtkMenuItem *menuitem,
2133 gpointer user_data)
2135 struct Item *it;
2137 if (ui.cur_mapping!=0 && !ui.button_switch_mapping) return;
2138 if (ui.toolno[ui.cur_mapping] < NUM_STROKE_TOOLS)
2139 g_memmove(ui.default_brushes+ui.toolno[ui.cur_mapping],
2140 &(ui.brushes[ui.cur_mapping][ui.toolno[ui.cur_mapping]]), sizeof(struct Brush));
2141 if (ui.toolno[ui.cur_mapping] == TOOL_TEXT) {
2142 if (ui.cur_item_type == ITEM_TEXT) {
2143 g_free(ui.font_name);
2144 ui.font_name = g_strdup(ui.cur_item->font_name);
2145 ui.font_size = ui.cur_item->font_size;
2147 else if (ui.selection!=NULL && ui.selection->items!=NULL &&
2148 ui.selection->items->next==NULL &&
2149 (it=(struct Item*)ui.selection->items->data)->type == ITEM_TEXT) {
2150 g_free(ui.font_name);
2151 ui.font_name = g_strdup(it->font_name);
2152 ui.font_size = it->font_size;
2154 g_free(ui.default_font_name);
2155 ui.default_font_name = g_strdup(ui.font_name);
2156 ui.default_font_size = ui.font_size;
2158 end_text();
2162 void
2163 on_toolsRuler_activate (GtkMenuItem *menuitem,
2164 gpointer user_data)
2166 gboolean active, current;
2168 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
2169 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2170 else
2171 active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
2173 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2174 current = (ui.toolno[ui.cur_mapping] == TOOL_PEN || ui.toolno[ui.cur_mapping] == TOOL_HIGHLIGHTER) && ui.cur_brush->ruler;
2175 if (active == current) return;
2177 ui.cur_mapping = 0;
2178 end_text();
2179 if (ui.toolno[ui.cur_mapping]!=TOOL_PEN && ui.toolno[ui.cur_mapping]!=TOOL_HIGHLIGHTER) {
2180 reset_selection();
2181 ui.toolno[ui.cur_mapping] = TOOL_PEN;
2182 ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
2183 update_color_menu();
2184 update_tool_buttons();
2185 update_tool_menu();
2186 update_cursor();
2189 ui.cur_brush->ruler = active;
2190 if (active) ui.cur_brush->recognizer = FALSE;
2191 update_mapping_linkings(ui.toolno[ui.cur_mapping]);
2192 update_ruler_indicator();
2196 void
2197 on_toolsReco_activate (GtkMenuItem *menuitem,
2198 gpointer user_data)
2200 gboolean active, current;
2202 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
2203 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2204 else
2205 active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
2207 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2208 current = (ui.toolno[ui.cur_mapping] == TOOL_PEN || ui.toolno[ui.cur_mapping] == TOOL_HIGHLIGHTER) && ui.cur_brush->recognizer;
2209 if (active == current) return;
2211 ui.cur_mapping = 0;
2212 end_text();
2213 if (ui.toolno[ui.cur_mapping]!=TOOL_PEN && ui.toolno[ui.cur_mapping]!=TOOL_HIGHLIGHTER) {
2214 reset_selection();
2215 ui.toolno[ui.cur_mapping] = TOOL_PEN;
2216 ui.cur_brush = &(ui.brushes[ui.cur_mapping][TOOL_PEN]);
2217 update_color_menu();
2218 update_tool_buttons();
2219 update_tool_menu();
2220 update_cursor();
2223 ui.cur_brush->recognizer = active;
2224 if (active) {
2225 ui.cur_brush->ruler = FALSE;
2226 reset_recognizer();
2228 update_mapping_linkings(ui.toolno[ui.cur_mapping]);
2229 update_ruler_indicator();
2233 void
2234 on_optionsSavePreferences_activate (GtkMenuItem *menuitem,
2235 gpointer user_data)
2237 end_text();
2238 save_config_to_file();
2242 void
2243 on_helpIndex_activate (GtkMenuItem *menuitem,
2244 gpointer user_data)
2250 void
2251 on_helpAbout_activate (GtkMenuItem *menuitem,
2252 gpointer user_data)
2254 GtkWidget *aboutDialog;
2255 GtkLabel *labelTitle;
2257 end_text();
2258 aboutDialog = create_aboutDialog ();
2259 labelTitle = GTK_LABEL(g_object_get_data(G_OBJECT(aboutDialog), "labelTitle"));
2260 gtk_label_set_markup(labelTitle,
2261 "<span size=\"xx-large\" weight=\"bold\">Xournal " VERSION "</span>");
2262 gtk_dialog_run (GTK_DIALOG(aboutDialog));
2263 gtk_widget_destroy(aboutDialog);
2267 void
2268 on_buttonToolDefault_clicked (GtkToolButton *toolbutton,
2269 gpointer user_data)
2271 if (ui.toolno[0]==TOOL_TEXT) {
2272 on_toolsDefaultText_activate(NULL, NULL);
2273 return;
2275 end_text();
2276 switch_mapping(0);
2277 if (ui.toolno[0] < NUM_STROKE_TOOLS) {
2278 g_memmove(&(ui.brushes[0][ui.toolno[0]]), ui.default_brushes+ui.toolno[0], sizeof(struct Brush));
2279 update_mapping_linkings(ui.toolno[0]);
2280 update_thickness_buttons();
2281 update_color_buttons();
2282 update_color_menu();
2283 if (ui.toolno[0] == TOOL_PEN) update_pen_props_menu();
2284 if (ui.toolno[0] == TOOL_ERASER) update_eraser_props_menu();
2285 if (ui.toolno[0] == TOOL_HIGHLIGHTER) update_highlighter_props_menu();
2286 update_cursor();
2291 void
2292 on_buttonFine_clicked (GtkToolButton *toolbutton,
2293 gpointer user_data)
2295 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2296 process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[ui.cur_mapping], THICKNESS_FINE);
2300 void
2301 on_buttonMedium_clicked (GtkToolButton *toolbutton,
2302 gpointer user_data)
2304 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2305 process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[ui.cur_mapping], THICKNESS_MEDIUM);
2309 void
2310 on_buttonThick_clicked (GtkToolButton *toolbutton,
2311 gpointer user_data)
2313 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
2314 process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[ui.cur_mapping], THICKNESS_THICK);
2318 gboolean
2319 on_canvas_button_press_event (GtkWidget *widget,
2320 GdkEventButton *event,
2321 gpointer user_data)
2323 double pt[2];
2324 gboolean page_change;
2325 struct Page *tmppage;
2326 GtkWidget *dialog;
2327 int mapping;
2328 gboolean is_core;
2329 struct Item *item;
2330 GdkEvent scroll_event;
2332 #ifdef INPUT_DEBUG
2333 printf("DEBUG: ButtonPress (%s) (x,y)=(%.2f,%.2f), button %d, modifier %x\n",
2334 event->device->name, event->x, event->y, event->button, event->state);
2335 #endif
2337 // abort any page changes pending in the spin button, and take the focus
2338 gtk_spin_button_set_value(GTK_SPIN_BUTTON(GET_COMPONENT("spinPageNo")), ui.pageno+1);
2339 reset_focus();
2341 is_core = (event->device == gdk_device_get_core_pointer());
2342 if (!ui.use_xinput && !is_core) return FALSE;
2343 if (ui.use_xinput && is_core && ui.discard_corepointer) return FALSE;
2344 if (event->type != GDK_BUTTON_PRESS) return FALSE;
2345 // double-clicks may have broken axes member (free'd) due to a bug in GDK
2347 if (event->button > 3) { // scroll wheel events! don't paint...
2348 if (ui.use_xinput && !gtk_check_version(2, 17, 0) && event->button <= 7) {
2349 /* with GTK+ 2.17 and later, the entire widget hierarchy is xinput-aware,
2350 so the core button event gets discarded and the scroll event never
2351 gets processed by the main window. This is arguably a GTK+ bug.
2352 We work around it. */
2353 scroll_event.scroll.type = GDK_SCROLL;
2354 scroll_event.scroll.window = event->window;
2355 scroll_event.scroll.send_event = event->send_event;
2356 scroll_event.scroll.time = event->time;
2357 scroll_event.scroll.x = event->x;
2358 scroll_event.scroll.y = event->y;
2359 scroll_event.scroll.state = event->state;
2360 scroll_event.scroll.device = event->device;
2361 scroll_event.scroll.x_root = event->x_root;
2362 scroll_event.scroll.y_root = event->y_root;
2363 if (event->button == 4) scroll_event.scroll.direction = GDK_SCROLL_UP;
2364 else if (event->button == 5) scroll_event.scroll.direction = GDK_SCROLL_DOWN;
2365 else if (event->button == 6) scroll_event.scroll.direction = GDK_SCROLL_LEFT;
2366 else scroll_event.scroll.direction = GDK_SCROLL_RIGHT;
2367 gtk_widget_event(GET_COMPONENT("scrolledwindowMain"), &scroll_event);
2369 return FALSE;
2371 if ((event->state & (GDK_CONTROL_MASK|GDK_MOD1_MASK)) != 0) return FALSE;
2372 // no control-clicking or alt-clicking
2373 if (!is_core)
2374 fix_xinput_coords((GdkEvent *)event);
2376 if (!finite(event->x) || !finite(event->y)) return FALSE; // Xorg 7.3 bug
2378 if (ui.cur_item_type == ITEM_TEXT) {
2379 if (!is_event_within_textview(event)) end_text();
2380 else return FALSE;
2382 if (ui.cur_item_type == ITEM_STROKE && ui.is_corestroke && !is_core &&
2383 ui.cur_path.num_points == 1) {
2384 // Xorg 7.3+ sent core event before XInput event: fix initial point
2385 ui.is_corestroke = FALSE;
2386 get_pointer_coords((GdkEvent *)event, ui.cur_path.coords);
2388 if (ui.cur_item_type != ITEM_NONE) return FALSE; // we're already doing something
2390 // if button_switch_mapping enabled, button 2 or 3 clicks only switch mapping
2391 if (ui.button_switch_mapping && event->button > 1) {
2392 ui.which_unswitch_button = event->button;
2393 switch_mapping(event->button-1);
2394 return FALSE;
2397 ui.is_corestroke = is_core;
2398 ui.stroke_device = event->device;
2400 if (ui.use_erasertip && event->device->source == GDK_SOURCE_ERASER)
2401 mapping = NUM_BUTTONS;
2402 else if (ui.button_switch_mapping) {
2403 mapping = ui.cur_mapping;
2404 if (!mapping && (event->state & GDK_BUTTON2_MASK)) mapping = 1;
2405 if (!mapping && (event->state & GDK_BUTTON3_MASK)) mapping = 2;
2407 else mapping = event->button-1;
2409 // check whether we're in a page
2410 page_change = FALSE;
2411 tmppage = ui.cur_page;
2412 get_pointer_coords((GdkEvent *)event, pt);
2413 while (ui.view_continuous && (pt[1] < - VIEW_CONTINUOUS_SKIP)) {
2414 if (ui.pageno == 0) break;
2415 page_change = TRUE;
2416 ui.pageno--;
2417 tmppage = g_list_nth_data(journal.pages, ui.pageno);
2418 pt[1] += tmppage->height + VIEW_CONTINUOUS_SKIP;
2420 while (ui.view_continuous && (pt[1] > tmppage->height + VIEW_CONTINUOUS_SKIP)) {
2421 if (ui.pageno == journal.npages-1) break;
2422 pt[1] -= tmppage->height + VIEW_CONTINUOUS_SKIP;
2423 page_change = TRUE;
2424 ui.pageno++;
2425 tmppage = g_list_nth_data(journal.pages, ui.pageno);
2427 if (page_change) do_switch_page(ui.pageno, FALSE, FALSE);
2429 // can't paint on the background...
2431 if (ui.cur_layer == NULL) {
2432 /* warn */
2433 dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL,
2434 GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("Drawing is not allowed on the "
2435 "background layer.\n Switching to Layer 1."));
2436 gtk_dialog_run(GTK_DIALOG(dialog));
2437 gtk_widget_destroy(dialog);
2438 on_viewShowLayer_activate(NULL, NULL);
2439 return FALSE;
2442 // switch mappings if needed
2444 ui.which_mouse_button = event->button;
2445 switch_mapping(mapping);
2447 // in text tool, clicking in a text area edits it
2448 if (ui.toolno[mapping] == TOOL_TEXT) {
2449 item = click_is_in_text(ui.cur_layer, pt[0], pt[1]);
2450 if (item!=NULL) {
2451 reset_selection();
2452 start_text((GdkEvent *)event, item);
2453 return FALSE;
2457 // if this can be a selection move or resize, then it takes precedence over anything else
2458 if (start_resizesel((GdkEvent *)event)) return FALSE;
2459 if (start_movesel((GdkEvent *)event)) return FALSE;
2461 if (ui.toolno[mapping] != TOOL_SELECTREGION && ui.toolno[mapping] != TOOL_SELECTRECT)
2462 reset_selection();
2464 // process the event
2466 if (ui.toolno[mapping] == TOOL_HAND) {
2467 ui.cur_item_type = ITEM_HAND;
2468 get_pointer_coords((GdkEvent *)event, ui.hand_refpt);
2469 ui.hand_refpt[0] += ui.cur_page->hoffset;
2470 ui.hand_refpt[1] += ui.cur_page->voffset;
2472 else if (ui.toolno[mapping] == TOOL_PEN || ui.toolno[mapping] == TOOL_HIGHLIGHTER ||
2473 (ui.toolno[mapping] == TOOL_ERASER && ui.cur_brush->tool_options == TOOLOPT_ERASER_WHITEOUT)) {
2474 create_new_stroke((GdkEvent *)event);
2476 else if (ui.toolno[mapping] == TOOL_ERASER) {
2477 ui.cur_item_type = ITEM_ERASURE;
2478 do_eraser((GdkEvent *)event, ui.cur_brush->thickness/2,
2479 ui.cur_brush->tool_options == TOOLOPT_ERASER_STROKES);
2481 else if (ui.toolno[mapping] == TOOL_SELECTRECT) {
2482 start_selectrect((GdkEvent *)event);
2484 else if (ui.toolno[mapping] == TOOL_VERTSPACE) {
2485 start_vertspace((GdkEvent *)event);
2487 else if (ui.toolno[mapping] == TOOL_TEXT) {
2488 start_text((GdkEvent *)event, NULL);
2490 return FALSE;
2494 gboolean
2495 on_canvas_button_release_event (GtkWidget *widget,
2496 GdkEventButton *event,
2497 gpointer user_data)
2499 gboolean is_core;
2501 #ifdef INPUT_DEBUG
2502 printf("DEBUG: ButtonRelease (%s) (x,y)=(%.2f,%.2f), button %d, modifier %x\n",
2503 event->device->name, event->x, event->y, event->button, event->state);
2504 #endif
2506 is_core = (event->device == gdk_device_get_core_pointer());
2507 if (!ui.use_xinput && !is_core) return FALSE;
2508 if (ui.use_xinput && is_core && !ui.is_corestroke) return FALSE;
2509 if (!is_core) fix_xinput_coords((GdkEvent *)event);
2511 if (event->button != ui.which_mouse_button &&
2512 event->button != ui.which_unswitch_button)
2513 return FALSE;
2515 if (ui.cur_item_type == ITEM_STROKE) {
2516 finalize_stroke();
2517 if (ui.cur_brush->recognizer) recognize_patterns();
2519 else if (ui.cur_item_type == ITEM_ERASURE) {
2520 finalize_erasure();
2522 else if (ui.cur_item_type == ITEM_SELECTRECT) {
2523 finalize_selectrect();
2525 else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2526 finalize_movesel();
2528 else if (ui.cur_item_type == ITEM_RESIZESEL) {
2529 finalize_resizesel();
2531 else if (ui.cur_item_type == ITEM_HAND) {
2532 ui.cur_item_type = ITEM_NONE;
2535 if (!ui.which_unswitch_button || event->button == ui.which_unswitch_button)
2536 switch_mapping(0); // will reset ui.which_unswitch_button
2538 return FALSE;
2542 gboolean
2543 on_canvas_enter_notify_event (GtkWidget *widget,
2544 GdkEventCrossing *event,
2545 gpointer user_data)
2547 GList *dev_list;
2548 GdkDevice *dev;
2550 #ifdef INPUT_DEBUG
2551 printf("DEBUG: enter notify\n");
2552 #endif
2553 /* re-enable input devices after they've been emergency-disabled
2554 by leave_notify */
2555 if (!gtk_check_version(2, 17, 0)) {
2556 for (dev_list = gdk_devices_list(); dev_list != NULL; dev_list = dev_list->next) {
2557 dev = GDK_DEVICE(dev_list->data);
2558 gdk_device_set_mode(dev, GDK_MODE_SCREEN);
2561 return FALSE;
2564 gboolean
2565 on_canvas_leave_notify_event (GtkWidget *widget,
2566 GdkEventCrossing *event,
2567 gpointer user_data)
2569 GList *dev_list;
2570 GdkDevice *dev;
2572 #ifdef INPUT_DEBUG
2573 printf("DEBUG: leave notify (mode=%d, details=%d)\n", event->mode, event->detail);
2574 #endif
2575 /* emergency disable XInput to avoid segfaults (GTK+ 2.17) or
2576 interface non-responsiveness (GTK+ 2.18) */
2577 if (!gtk_check_version(2, 17, 0)) {
2578 for (dev_list = gdk_devices_list(); dev_list != NULL; dev_list = dev_list->next) {
2579 dev = GDK_DEVICE(dev_list->data);
2580 gdk_device_set_mode(dev, GDK_MODE_DISABLED);
2583 return FALSE;
2587 gboolean
2588 on_canvas_expose_event (GtkWidget *widget,
2589 GdkEventExpose *event,
2590 gpointer user_data)
2592 if (ui.view_continuous && ui.progressive_bg) rescale_bg_pixmaps();
2593 return FALSE;
2597 gboolean
2598 on_canvas_key_press_event (GtkWidget *widget,
2599 GdkEventKey *event,
2600 gpointer user_data)
2602 GtkAdjustment *adj;
2603 gint pgheight;
2605 // Esc leaves text edition, or leaves fullscreen mode
2606 if (event->keyval == GDK_Escape) {
2607 if (ui.cur_item_type == ITEM_TEXT) {
2608 end_text();
2609 return TRUE;
2611 else if (ui.fullscreen) {
2612 do_fullscreen(FALSE);
2613 return TRUE;
2615 else return FALSE;
2618 /* In single page mode, switch pages with PgUp/PgDn (or Up/Dn)
2619 when there's nowhere else to go. */
2620 pgheight = GTK_WIDGET(canvas)->allocation.height;
2621 adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(GET_COMPONENT("scrolledwindowMain")));
2623 if (event->keyval == GDK_Page_Down || event->keyval == GDK_Down) {
2624 if (!ui.view_continuous &&
2625 (0.96 * ui.zoom * ui.cur_page->height < pgheight ||
2626 adj->value == adj->upper-pgheight))
2628 end_text();
2629 if (ui.pageno < journal.npages-1)
2630 do_switch_page(ui.pageno+1, TRUE, FALSE);
2631 return TRUE;
2633 if (adj->value == adj->upper-pgheight) return TRUE; // don't send focus away
2636 if (event->keyval == GDK_Page_Up || event->keyval == GDK_Up) {
2637 if (!ui.view_continuous &&
2638 (0.96 * ui.zoom * ui.cur_page->height < pgheight ||
2639 adj->value == adj->lower))
2641 end_text();
2642 if (ui.pageno != 0) {
2643 do_switch_page(ui.pageno-1, TRUE, FALSE);
2644 gtk_adjustment_set_value(adj, adj->upper-pgheight);
2646 return TRUE;
2648 if (adj->value == adj->lower) return TRUE; // don't send focus away
2651 return FALSE;
2655 gboolean
2656 on_canvas_motion_notify_event (GtkWidget *widget,
2657 GdkEventMotion *event,
2658 gpointer user_data)
2660 gboolean looks_wrong, is_core;
2661 double pt[2];
2662 GdkModifierType mask;
2664 /* we don't care about this event unless some operation is in progress;
2665 or if there's a selection (then we might want to change the mouse
2666 cursor to indicate the possibility of resizing) */
2667 if (ui.cur_item_type == ITEM_NONE && ui.selection==NULL) return FALSE;
2668 if (ui.cur_item_type == ITEM_TEXT) return FALSE;
2670 is_core = (event->device == gdk_device_get_core_pointer());
2671 if (!ui.use_xinput && !is_core) return FALSE;
2672 if (!is_core) fix_xinput_coords((GdkEvent *)event);
2673 if (!finite(event->x) || !finite(event->y)) return FALSE; // Xorg 7.3 bug
2675 if (ui.selection!=NULL && ui.cur_item_type == ITEM_NONE) {
2676 get_pointer_coords((GdkEvent *)event, pt);
2677 update_cursor_for_resize(pt);
2678 return FALSE;
2681 if (ui.use_xinput && is_core && !ui.is_corestroke) return FALSE;
2682 if (!is_core) ui.is_corestroke = FALSE;
2684 #ifdef INPUT_DEBUG
2685 printf("DEBUG: MotionNotify (%s) (x,y)=(%.2f,%.2f), modifier %x\n",
2686 is_core?"core":"xinput", event->x, event->y, event->state);
2687 #endif
2689 looks_wrong = !(event->state & (1<<(7+ui.which_mouse_button)));
2690 if (looks_wrong) {
2691 gdk_device_get_state(ui.stroke_device, event->window, NULL, &mask);
2692 looks_wrong = !(mask & (1<<(7+ui.which_mouse_button)));
2695 if (looks_wrong) { /* mouse button shouldn't be up... give up */
2696 if (ui.cur_item_type == ITEM_STROKE) {
2697 finalize_stroke();
2698 if (ui.cur_brush->recognizer) recognize_patterns();
2700 else if (ui.cur_item_type == ITEM_ERASURE) {
2701 finalize_erasure();
2703 else if (ui.cur_item_type == ITEM_SELECTRECT) {
2704 finalize_selectrect();
2706 else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2707 finalize_movesel();
2709 else if (ui.cur_item_type == ITEM_RESIZESEL) {
2710 finalize_resizesel();
2712 switch_mapping(0);
2713 return FALSE;
2716 if (ui.cur_item_type == ITEM_STROKE) {
2717 continue_stroke((GdkEvent *)event);
2719 else if (ui.cur_item_type == ITEM_ERASURE) {
2720 do_eraser((GdkEvent *)event, ui.cur_brush->thickness/2,
2721 ui.cur_brush->tool_options == TOOLOPT_ERASER_STROKES);
2723 else if (ui.cur_item_type == ITEM_SELECTRECT) {
2724 get_pointer_coords((GdkEvent *)event, pt);
2725 ui.selection->bbox.right = pt[0];
2726 ui.selection->bbox.bottom = pt[1];
2727 gnome_canvas_item_set(ui.selection->canvas_item,
2728 "x2", pt[0], "y2", pt[1], NULL);
2730 else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2731 continue_movesel((GdkEvent *)event);
2733 else if (ui.cur_item_type == ITEM_RESIZESEL) {
2734 continue_resizesel((GdkEvent *)event);
2736 else if (ui.cur_item_type == ITEM_HAND) {
2737 do_hand((GdkEvent *)event);
2740 return FALSE;
2743 void
2744 on_comboLayer_changed (GtkComboBox *combobox,
2745 gpointer user_data)
2747 int val;
2749 if (ui.in_update_page_stuff) return; // avoid a bad retroaction
2751 end_text();
2753 val = gtk_combo_box_get_active(combobox);
2754 if (val == -1) return;
2755 val = ui.cur_page->nlayers-1-val;
2756 if (val == ui.layerno) return;
2758 reset_selection();
2759 while (val>ui.layerno) {
2760 ui.layerno++;
2761 ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
2762 gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group));
2764 while (val<ui.layerno) {
2765 gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group));
2766 ui.layerno--;
2767 if (ui.layerno<0) ui.cur_layer = NULL;
2768 else ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
2770 update_page_stuff();
2774 gboolean
2775 on_winMain_delete_event (GtkWidget *widget,
2776 GdkEvent *event,
2777 gpointer user_data)
2779 end_text();
2780 if (ok_to_close()) gtk_main_quit();
2781 return TRUE;
2785 void
2786 on_optionsUseXInput_activate (GtkMenuItem *menuitem,
2787 gpointer user_data)
2789 end_text();
2790 ui.allow_xinput = ui.use_xinput =
2791 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2793 /* HOW THINGS USED TO BE:
2795 We'd like on_canvas_... to get BOTH core and xinput events. Up to
2796 GTK+ 2.16 this is achieved by making only the canvas's parent
2797 GdkWindow xinput-aware, rather than the entire hierarchy.
2798 Otherwise, the proximity detection code in GDK is broken and
2799 we'll lose core events.
2801 Up to GTK+ 2.10, gtk_widget_set_extension_events() only sets
2802 extension events for the widget's main window itself; in GTK+ 2.11
2803 also traverses GDK child windows that belong to the widget
2804 and sets their extension events too. We want to avoid that.
2805 So we use gdk_input_set_extension_events() directly on the canvas.
2807 As much as possible, we'd like to keep doing this, though GTK+ 2.17
2808 is making our life harder (crasher bugs require us to disable XInput
2809 while editing text or using the layers combo box, but disabling
2810 XInput while in a XInput-aware window causes the interface to become
2811 non-responsive).
2814 if (!gtk_check_version(2, 17, 0)) {
2815 /* GTK+ 2.17 and later: everybody shares a single native window,
2816 so we'll never get any core events, and we might as well set
2817 extension events the way we're supposed to. Doing so helps solve
2818 crasher bugs in 2.17, and prevents us from losing two-button
2819 events in 2.18 */
2820 gtk_widget_set_extension_events(GTK_WIDGET (canvas),
2821 ui.use_xinput?GDK_EXTENSION_EVENTS_ALL:GDK_EXTENSION_EVENTS_NONE);
2822 } else {
2823 /* GTK+ 2.16 and earlier: we only activate extension events on the
2824 canvas's parent GdkWindow. This allows us to keep receiving core
2825 events. */
2826 gdk_input_set_extension_events(GTK_WIDGET(canvas)->window,
2827 GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK,
2828 ui.use_xinput?GDK_EXTENSION_EVENTS_ALL:GDK_EXTENSION_EVENTS_NONE);
2831 update_mappings_menu();
2834 void
2835 on_vscroll_changed (GtkAdjustment *adjustment,
2836 gpointer user_data)
2838 gboolean need_update;
2839 double viewport_top, viewport_bottom;
2840 struct Page *tmppage;
2842 if (!ui.view_continuous) return;
2844 if (ui.progressive_bg) rescale_bg_pixmaps();
2845 need_update = FALSE;
2846 viewport_top = adjustment->value / ui.zoom;
2847 viewport_bottom = (adjustment->value + adjustment->page_size) / ui.zoom;
2848 tmppage = ui.cur_page;
2849 while (viewport_top > tmppage->voffset + tmppage->height) {
2850 if (ui.pageno == journal.npages-1) break;
2851 need_update = TRUE;
2852 ui.pageno++;
2853 tmppage = g_list_nth_data(journal.pages, ui.pageno);
2855 while (viewport_bottom < tmppage->voffset) {
2856 if (ui.pageno == 0) break;
2857 need_update = TRUE;
2858 ui.pageno--;
2859 tmppage = g_list_nth_data(journal.pages, ui.pageno);
2861 if (need_update) {
2862 end_text();
2863 do_switch_page(ui.pageno, FALSE, FALSE);
2865 return;
2868 void
2869 on_spinPageNo_value_changed (GtkSpinButton *spinbutton,
2870 gpointer user_data)
2872 int val;
2874 if (ui.in_update_page_stuff) return; // avoid a bad retroaction
2876 /* in preparation for end_text(), send focus to the canvas if it's not ours.
2877 (avoid issues with Gtk trying to send focus to the dead text widget) */
2879 if (!GTK_WIDGET_HAS_FOCUS(spinbutton))
2880 gtk_widget_grab_focus(GTK_WIDGET(canvas));
2881 end_text();
2883 val = gtk_spin_button_get_value_as_int(spinbutton) - 1;
2885 if (val == journal.npages) { // create a page at end
2886 on_journalNewPageEnd_activate(NULL, NULL);
2887 return;
2890 if (val == ui.pageno) return;
2891 if (val < 0) val = 0;
2892 if (val > journal.npages-1) val = journal.npages-1;
2893 do_switch_page(val, TRUE, FALSE);
2897 void
2898 on_journalDefaultBackground_activate (GtkMenuItem *menuitem,
2899 gpointer user_data)
2901 struct Page *pg;
2902 GList *pglist;
2904 end_text();
2905 reset_selection();
2907 pg = ui.cur_page;
2908 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
2909 if (ui.bg_apply_all_pages) pg = (struct Page *)pglist->data;
2910 prepare_new_undo();
2911 if (ui.bg_apply_all_pages) {
2912 if (pglist->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
2913 if (pglist->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
2915 undo->type = ITEM_NEW_BG_RESIZE;
2916 undo->page = pg;
2917 undo->bg = pg->bg;
2918 undo->val_x = pg->width;
2919 undo->val_y = pg->height;
2920 pg->bg = (struct Background *)g_memdup(ui.default_page.bg, sizeof(struct Background));
2921 pg->width = ui.default_page.width;
2922 pg->height = ui.default_page.height;
2923 pg->bg->canvas_item = undo->bg->canvas_item;
2924 undo->bg->canvas_item = NULL;
2926 make_page_clipbox(pg);
2927 update_canvas_bg(pg);
2928 if (!ui.bg_apply_all_pages) break;
2930 do_switch_page(ui.pageno, TRUE, TRUE);
2934 void
2935 on_journalSetAsDefault_activate (GtkMenuItem *menuitem,
2936 gpointer user_data)
2938 if (ui.cur_page->bg->type != BG_SOLID) return;
2940 end_text();
2941 prepare_new_undo();
2942 undo->type = ITEM_NEW_DEFAULT_BG;
2943 undo->val_x = ui.default_page.width;
2944 undo->val_y = ui.default_page.height;
2945 undo->bg = ui.default_page.bg;
2947 ui.default_page.width = ui.cur_page->width;
2948 ui.default_page.height = ui.cur_page->height;
2949 ui.default_page.bg = (struct Background *)g_memdup(ui.cur_page->bg, sizeof(struct Background));
2950 ui.default_page.bg->canvas_item = NULL;
2954 void
2955 on_comboStdSizes_changed (GtkComboBox *combobox,
2956 gpointer user_data)
2958 GtkEntry *entry;
2959 GtkComboBox *comboUnit;
2960 int val;
2961 gchar text[20];
2963 if (papersize_need_init) {
2964 gtk_combo_box_set_active(combobox, papersize_std);
2965 papersize_need_init = FALSE;
2966 } else {
2967 val = gtk_combo_box_get_active(combobox);
2968 if (val == -1 || val == papersize_std) return;
2969 papersize_std = val;
2970 if (val == STD_SIZE_CUSTOM) return;
2971 papersize_unit = std_units[val];
2972 papersize_width = std_widths[val];
2973 papersize_height = std_heights[val];
2975 comboUnit = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboUnit"));
2976 gtk_combo_box_set_active(comboUnit, papersize_unit);
2977 entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryWidth"));
2978 g_snprintf(text, 20, "%.2f", papersize_width/unit_sizes[papersize_unit]);
2979 if (g_str_has_suffix(text, ".00"))
2980 g_snprintf(text, 20, "%d", (int) (papersize_width/unit_sizes[papersize_unit]));
2981 gtk_entry_set_text(entry, text);
2982 entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryHeight"));
2983 g_snprintf(text, 20, "%.2f", papersize_height/unit_sizes[papersize_unit]);
2984 if (g_str_has_suffix(text, ".00"))
2985 g_snprintf(text, 20, "%d", (int) (papersize_height/unit_sizes[papersize_unit]));
2986 gtk_entry_set_text(entry, text);
2990 void
2991 on_entryWidth_changed (GtkEditable *editable,
2992 gpointer user_data)
2994 double val;
2995 const gchar *text;
2996 gchar *ptr;
2997 GtkComboBox *comboStdSizes;
2999 text = gtk_entry_get_text(GTK_ENTRY(editable));
3000 val = strtod(text, &ptr);
3001 papersize_width_valid = (*ptr == 0 && val > 0.);
3002 if (!papersize_width_valid) return; // invalid entry
3003 val *= unit_sizes[papersize_unit];
3004 if (fabs(val - papersize_width) < 0.1) return; // no change
3005 papersize_std = STD_SIZE_CUSTOM;
3006 papersize_width = val;
3007 comboStdSizes = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboStdSizes"));
3008 gtk_combo_box_set_active(comboStdSizes, papersize_std);
3012 void
3013 on_entryHeight_changed (GtkEditable *editable,
3014 gpointer user_data)
3016 double val;
3017 const gchar *text;
3018 gchar *ptr;
3019 GtkComboBox *comboStdSizes;
3021 text = gtk_entry_get_text(GTK_ENTRY(editable));
3022 val = strtod(text, &ptr);
3023 papersize_height_valid = (*ptr == 0 && val > 0.);
3024 if (!papersize_height_valid) return; // invalid entry
3025 val *= unit_sizes[papersize_unit];
3026 if (fabs(val - papersize_height) < 0.1) return; // no change
3027 papersize_std = STD_SIZE_CUSTOM;
3028 papersize_height = val;
3029 comboStdSizes = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboStdSizes"));
3030 gtk_combo_box_set_active(comboStdSizes, papersize_std);
3034 void
3035 on_comboUnit_changed (GtkComboBox *combobox,
3036 gpointer user_data)
3038 GtkEntry *entry;
3039 int val;
3040 gchar text[20];
3042 val = gtk_combo_box_get_active(combobox);
3043 if (val == -1 || val == papersize_unit) return;
3044 papersize_unit = val;
3045 entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryWidth"));
3046 if (papersize_width_valid) {
3047 g_snprintf(text, 20, "%.2f", papersize_width/unit_sizes[papersize_unit]);
3048 if (g_str_has_suffix(text, ".00"))
3049 g_snprintf(text, 20, "%d", (int) (papersize_width/unit_sizes[papersize_unit]));
3050 } else *text = 0;
3051 gtk_entry_set_text(entry, text);
3052 if (papersize_height_valid) {
3053 entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryHeight"));
3054 g_snprintf(text, 20, "%.2f", papersize_height/unit_sizes[papersize_unit]);
3055 if (g_str_has_suffix(text, ".00"))
3056 g_snprintf(text, 20, "%d", (int) (papersize_height/unit_sizes[papersize_unit]));
3057 } else *text = 0;
3058 gtk_entry_set_text(entry, text);
3062 void
3063 on_viewFullscreen_activate (GtkMenuItem *menuitem,
3064 gpointer user_data)
3066 gboolean active;
3068 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
3069 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3070 else
3071 active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
3073 if (active == ui.fullscreen) return;
3074 do_fullscreen(active);
3078 void
3079 on_optionsButtonMappings_activate (GtkMenuItem *menuitem,
3080 gpointer user_data)
3082 end_text();
3083 ui.use_erasertip =
3084 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3085 update_mappings_menu();
3089 void
3090 on_optionsProgressiveBG_activate (GtkMenuItem *menuitem,
3091 gpointer user_data)
3093 gboolean active;
3095 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3096 if (ui.progressive_bg == active) return;
3097 end_text();
3098 ui.progressive_bg = active;
3099 if (!ui.progressive_bg) rescale_bg_pixmaps();
3103 void
3104 on_mru_activate (GtkMenuItem *menuitem,
3105 gpointer user_data)
3107 int which;
3108 gboolean success;
3109 GtkWidget *dialog;
3111 end_text();
3112 if (!ok_to_close()) return; // user aborted on save confirmation
3114 for (which = 0 ; which < MRU_SIZE; which++) {
3115 if (ui.mrumenu[which] == GTK_WIDGET(menuitem)) break;
3117 if (which == MRU_SIZE || ui.mru[which] == NULL) return; // not found...
3119 set_cursor_busy(TRUE);
3120 success = open_journal(ui.mru[which]);
3121 set_cursor_busy(FALSE);
3122 if (success) return;
3124 /* open failed */
3125 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
3126 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Error opening file '%s'"), ui.mru[which]);
3127 gtk_dialog_run(GTK_DIALOG(dialog));
3128 gtk_widget_destroy(dialog);
3129 delete_mru_entry(which);
3133 void
3134 on_button2Pen_activate (GtkMenuItem *menuitem,
3135 gpointer user_data)
3137 process_mapping_activate(menuitem, 1, TOOL_PEN);
3141 void
3142 on_button2Eraser_activate (GtkMenuItem *menuitem,
3143 gpointer user_data)
3145 process_mapping_activate(menuitem, 1, TOOL_ERASER);
3149 void
3150 on_button2Highlighter_activate (GtkMenuItem *menuitem,
3151 gpointer user_data)
3153 process_mapping_activate(menuitem, 1, TOOL_HIGHLIGHTER);
3157 void
3158 on_button2Text_activate (GtkMenuItem *menuitem,
3159 gpointer user_data)
3161 process_mapping_activate(menuitem, 1, TOOL_TEXT);
3165 void
3166 on_button2SelectRegion_activate (GtkMenuItem *menuitem,
3167 gpointer user_data)
3169 process_mapping_activate(menuitem, 1, TOOL_SELECTREGION);
3173 void
3174 on_button2SelectRectangle_activate (GtkMenuItem *menuitem,
3175 gpointer user_data)
3177 process_mapping_activate(menuitem, 1, TOOL_SELECTRECT);
3181 void
3182 on_button2VerticalSpace_activate (GtkMenuItem *menuitem,
3183 gpointer user_data)
3185 process_mapping_activate(menuitem, 1, TOOL_VERTSPACE);
3189 void
3190 on_button2LinkBrush_activate (GtkMenuItem *menuitem,
3191 gpointer user_data)
3193 int i;
3195 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3196 end_text();
3197 ui.linked_brush[1] = BRUSH_LINKED;
3198 for (i=0;i<NUM_STROKE_TOOLS;i++) update_mapping_linkings(i);
3202 void
3203 on_button2CopyBrush_activate (GtkMenuItem *menuitem,
3204 gpointer user_data)
3206 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3207 end_text();
3208 if (ui.toolno[1] >= NUM_STROKE_TOOLS) {
3209 ui.linked_brush[1] = BRUSH_STATIC;
3210 update_mappings_menu_linkings();
3211 return;
3213 ui.linked_brush[1] = BRUSH_COPIED;
3214 g_memmove(&(ui.brushes[1][ui.toolno[1]]), &(ui.brushes[0][ui.toolno[1]]), sizeof(struct Brush));
3218 void
3219 on_button3Pen_activate (GtkMenuItem *menuitem,
3220 gpointer user_data)
3222 process_mapping_activate(menuitem, 2, TOOL_PEN);
3226 void
3227 on_button3Eraser_activate (GtkMenuItem *menuitem,
3228 gpointer user_data)
3230 process_mapping_activate(menuitem, 2, TOOL_ERASER);
3234 void
3235 on_button3Highlighter_activate (GtkMenuItem *menuitem,
3236 gpointer user_data)
3238 process_mapping_activate(menuitem, 2, TOOL_HIGHLIGHTER);
3242 void
3243 on_button3Text_activate (GtkMenuItem *menuitem,
3244 gpointer user_data)
3246 process_mapping_activate(menuitem, 2, TOOL_TEXT);
3250 void
3251 on_button3SelectRegion_activate (GtkMenuItem *menuitem,
3252 gpointer user_data)
3254 process_mapping_activate(menuitem, 2, TOOL_SELECTREGION);
3258 void
3259 on_button3SelectRectangle_activate (GtkMenuItem *menuitem,
3260 gpointer user_data)
3262 process_mapping_activate(menuitem, 2, TOOL_SELECTRECT);
3266 void
3267 on_button3VerticalSpace_activate (GtkMenuItem *menuitem,
3268 gpointer user_data)
3270 process_mapping_activate(menuitem, 2, TOOL_VERTSPACE);
3274 void
3275 on_button3LinkBrush_activate (GtkMenuItem *menuitem,
3276 gpointer user_data)
3278 int i;
3280 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3281 end_text();
3282 ui.linked_brush[2] = BRUSH_LINKED;
3283 for (i=0;i<NUM_STROKE_TOOLS;i++) update_mapping_linkings(i);
3287 void
3288 on_button3CopyBrush_activate (GtkMenuItem *menuitem,
3289 gpointer user_data)
3291 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3292 end_text();
3293 if (ui.toolno[2] >= NUM_STROKE_TOOLS) {
3294 ui.linked_brush[2] = BRUSH_STATIC;
3295 update_mappings_menu_linkings();
3296 return;
3298 ui.linked_brush[2] = BRUSH_COPIED;
3299 g_memmove(&(ui.brushes[2][ui.toolno[2]]), &(ui.brushes[0][ui.toolno[2]]), sizeof(struct Brush));
3302 // the set zoom dialog
3304 GtkWidget *zoom_dialog;
3305 double zoom_percent;
3307 void
3308 on_viewSetZoom_activate (GtkMenuItem *menuitem,
3309 gpointer user_data)
3311 int response;
3312 double test_w, test_h;
3313 GtkSpinButton *spinZoom;
3315 end_text();
3316 zoom_dialog = create_zoomDialog();
3317 zoom_percent = 100*ui.zoom / DEFAULT_ZOOM;
3318 spinZoom = GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(zoom_dialog), "spinZoom"));
3319 gtk_spin_button_set_increments(spinZoom, ui.zoom_step_increment, 5*ui.zoom_step_increment);
3320 gtk_spin_button_set_value(spinZoom, zoom_percent);
3321 test_w = 100*(GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width/DEFAULT_ZOOM;
3322 test_h = 100*(GTK_WIDGET(canvas))->allocation.height/ui.cur_page->height/DEFAULT_ZOOM;
3323 if (zoom_percent > 99.9 && zoom_percent < 100.1)
3324 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3325 G_OBJECT(zoom_dialog), "radioZoom100")), TRUE);
3326 else if (zoom_percent > test_w-0.1 && zoom_percent < test_w+0.1)
3327 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3328 G_OBJECT(zoom_dialog), "radioZoomWidth")), TRUE);
3329 else if (zoom_percent > test_h-0.1 && zoom_percent < test_h+0.1)
3330 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3331 G_OBJECT(zoom_dialog), "radioZoomHeight")), TRUE);
3332 else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3333 G_OBJECT(zoom_dialog), "radioZoom")), TRUE);
3334 gtk_widget_show(zoom_dialog);
3336 do {
3337 response = gtk_dialog_run(GTK_DIALOG(zoom_dialog));
3338 if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY) {
3339 ui.zoom = DEFAULT_ZOOM*zoom_percent/100;
3340 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
3341 rescale_text_items();
3342 rescale_bg_pixmaps();
3344 } while (response == GTK_RESPONSE_APPLY);
3346 gtk_widget_destroy(zoom_dialog);
3350 void
3351 on_spinZoom_value_changed (GtkSpinButton *spinbutton,
3352 gpointer user_data)
3354 double val;
3356 val = gtk_spin_button_get_value(GTK_SPIN_BUTTON(g_object_get_data(
3357 G_OBJECT(zoom_dialog), "spinZoom")));
3358 if (val<1) return;
3359 if (val<10) val=10.;
3360 if (val>1500) val=1500.;
3361 if (val<zoom_percent-1 || val>zoom_percent+1)
3362 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3363 G_OBJECT(zoom_dialog), "radioZoom")), TRUE);
3364 zoom_percent = val;
3368 void
3369 on_radioZoom_toggled (GtkToggleButton *togglebutton,
3370 gpointer user_data)
3372 // nothing to do
3376 void
3377 on_radioZoom100_toggled (GtkToggleButton *togglebutton,
3378 gpointer user_data)
3380 if (!gtk_toggle_button_get_active(togglebutton)) return;
3381 zoom_percent = 100.;
3382 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3383 G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3387 void
3388 on_radioZoomWidth_toggled (GtkToggleButton *togglebutton,
3389 gpointer user_data)
3391 if (!gtk_toggle_button_get_active(togglebutton)) return;
3392 zoom_percent = 100*(GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width/DEFAULT_ZOOM;
3393 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3394 G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3398 void
3399 on_radioZoomHeight_toggled (GtkToggleButton *togglebutton,
3400 gpointer user_data)
3402 if (!gtk_toggle_button_get_active(togglebutton)) return;
3403 zoom_percent = 100*(GTK_WIDGET(canvas))->allocation.height/ui.cur_page->height/DEFAULT_ZOOM;
3404 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3405 G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3409 void
3410 on_toolsHand_activate (GtkMenuItem *menuitem,
3411 gpointer user_data)
3413 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
3414 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
3415 return;
3416 } else {
3417 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
3418 return;
3421 if (ui.cur_mapping != 0 && !ui.button_switch_mapping) return;
3422 if (ui.toolno[ui.cur_mapping] == TOOL_HAND) return;
3424 ui.cur_mapping = 0;
3425 end_text();
3426 reset_selection();
3427 ui.toolno[ui.cur_mapping] = TOOL_HAND;
3428 update_mapping_linkings(-1);
3429 update_tool_buttons();
3430 update_tool_menu();
3431 update_color_menu();
3432 update_cursor();
3436 void
3437 on_button2Hand_activate (GtkMenuItem *menuitem,
3438 gpointer user_data)
3440 process_mapping_activate(menuitem, 1, TOOL_HAND);
3444 void
3445 on_button3Hand_activate (GtkMenuItem *menuitem,
3446 gpointer user_data)
3448 process_mapping_activate(menuitem, 2, TOOL_HAND);
3452 void
3453 on_optionsPrintRuling_activate (GtkMenuItem *menuitem,
3454 gpointer user_data)
3456 end_text();
3457 ui.print_ruling = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3460 void
3461 on_optionsAutoloadPdfXoj_activate (GtkMenuItem *menuitem,
3462 gpointer user_data)
3464 end_text();
3465 ui.autoload_pdf_xoj = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3468 void
3469 on_optionsDiscardCore_activate (GtkMenuItem *menuitem,
3470 gpointer user_data)
3472 end_text();
3473 ui.discard_corepointer =
3474 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3475 update_mappings_menu();
3478 void
3479 on_fontButton_font_set (GtkFontButton *fontbutton,
3480 gpointer user_data)
3482 gchar *str;
3484 str = g_strdup(gtk_font_button_get_font_name(fontbutton));
3485 process_font_sel(str);
3488 void
3489 on_optionsLeftHanded_activate (GtkMenuItem *menuitem,
3490 gpointer user_data)
3492 end_text();
3493 ui.left_handed = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3494 gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW(GET_COMPONENT("scrolledwindowMain")),
3495 ui.left_handed?GTK_CORNER_TOP_RIGHT:GTK_CORNER_TOP_LEFT);
3498 void
3499 on_optionsShortenMenus_activate (GtkMenuItem *menuitem,
3500 gpointer user_data)
3502 gchar *item, *nextptr;
3503 GtkWidget *w;
3505 end_text();
3506 ui.shorten_menus = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3508 /* go over the item list */
3509 item = ui.shorten_menu_items;
3510 while (*item==' ') item++;
3511 while (*item) {
3512 nextptr = strchr(item, ' ');
3513 if (nextptr!=NULL) *nextptr = 0;
3514 // hide or show the item
3515 w = GET_COMPONENT(item);
3516 if (w != NULL) {
3517 if (ui.shorten_menus) gtk_widget_hide(w);
3518 else gtk_widget_show(w);
3520 // next item
3521 if (nextptr==NULL) break;
3522 *nextptr = ' ';
3523 item = nextptr;
3524 while (*item==' ') item++;
3527 // just in case someone tried to unhide stuff they shouldn't be seeing
3528 hide_unimplemented();
3529 // maybe we should also make sure the drawing area stays visible ?
3532 void
3533 on_optionsAutoSavePrefs_activate (GtkMenuItem *menuitem,
3534 gpointer user_data)
3536 end_text();
3537 ui.auto_save_prefs = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3540 void
3541 on_optionsPressureSensitive_activate (GtkMenuItem *menuitem,
3542 gpointer user_data)
3544 int i;
3545 end_text();
3546 ui.pressure_sensitivity =
3547 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3548 for (i=0; i<=NUM_BUTTONS; i++)
3549 ui.brushes[i][TOOL_PEN].variable_width = ui.pressure_sensitivity;
3550 update_mappings_menu();
3554 void
3555 on_buttonColorChooser_set (GtkColorButton *colorbutton,
3556 gpointer user_data)
3558 GdkColor gdkcolor;
3559 guint16 alpha;
3561 gtk_color_button_get_color(colorbutton, &gdkcolor);
3562 alpha = gtk_color_button_get_alpha(colorbutton);
3563 process_color_activate((GtkMenuItem*)colorbutton, COLOR_OTHER, gdkcolor_to_rgba(gdkcolor, alpha));
3567 void
3568 on_optionsButtonsSwitchMappings_activate(GtkMenuItem *menuitem,
3569 gpointer user_data)
3571 end_text();
3572 switch_mapping(0);
3573 ui.button_switch_mapping = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));