Update to version 0.4.2.
[xournal.git] / src / xo-callbacks.c
blob9b1e85b9bdfecdfd9fba9d6837f6a974057da68f
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 <libgnomeprintui/gnome-print-dialog.h>
11 #include <glib/gstdio.h>
12 #include <gdk/gdkkeysyms.h>
14 #include "xournal.h"
15 #include "xo-callbacks.h"
16 #include "xo-interface.h"
17 #include "xo-support.h"
18 #include "xo-misc.h"
19 #include "xo-file.h"
20 #include "xo-paint.h"
21 #include "xo-print.h"
22 #include "xo-shapes.h"
24 void
25 on_fileNew_activate (GtkMenuItem *menuitem,
26 gpointer user_data)
28 end_text();
29 reset_focus();
30 if (close_journal()) {
31 new_journal();
32 ui.zoom = ui.startup_zoom;
33 update_page_stuff();
34 gtk_adjustment_set_value(gtk_layout_get_vadjustment(GTK_LAYOUT(canvas)), 0);
35 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
40 void
41 on_fileNewBackground_activate (GtkMenuItem *menuitem,
42 gpointer user_data)
44 GtkWidget *dialog, *attach_opt;
45 GtkFileFilter *filt_all, *filt_pdf;
46 char *filename;
47 int file_domain;
48 gboolean success;
50 end_text();
51 reset_focus();
52 if (!ok_to_close()) return; // user aborted on save confirmation
54 dialog = gtk_file_chooser_dialog_new("Open PDF", GTK_WINDOW (winMain),
55 GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
56 GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
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 reset_focus();
123 if (!ok_to_close()) return; // user aborted on save confirmation
125 dialog = gtk_file_chooser_dialog_new("Open Journal", GTK_WINDOW (winMain),
126 GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
127 GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
129 filt_all = gtk_file_filter_new();
130 gtk_file_filter_set_name(filt_all, "All files");
131 gtk_file_filter_add_pattern(filt_all, "*");
132 filt_xoj = gtk_file_filter_new();
133 gtk_file_filter_set_name(filt_xoj, "Xournal files");
134 gtk_file_filter_add_pattern(filt_xoj, "*.xoj");
135 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_xoj);
136 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
138 if (ui.default_path!=NULL) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
140 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
141 gtk_widget_destroy(dialog);
142 return;
144 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
145 gtk_widget_destroy(dialog);
147 set_cursor_busy(TRUE);
148 success = open_journal(filename);
149 set_cursor_busy(FALSE);
150 if (success) { g_free(filename); return; }
152 /* open failed */
153 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
154 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Error opening file '%s'", filename);
155 gtk_dialog_run(GTK_DIALOG(dialog));
156 gtk_widget_destroy(dialog);
157 g_free(filename);
162 void
163 on_fileSave_activate (GtkMenuItem *menuitem,
164 gpointer user_data)
166 GtkWidget *dialog;
168 end_text();
169 reset_focus();
170 if (ui.filename == NULL) {
171 on_fileSaveAs_activate(menuitem, user_data);
172 return;
174 set_cursor_busy(TRUE);
175 if (save_journal(ui.filename)) { // success
176 set_cursor_busy(FALSE);
177 ui.saved = TRUE;
178 return;
180 set_cursor_busy(FALSE);
181 /* save failed */
182 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
183 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Error saving file '%s'", ui.filename);
184 gtk_dialog_run(GTK_DIALOG(dialog));
185 gtk_widget_destroy(dialog);
189 void
190 on_fileSaveAs_activate (GtkMenuItem *menuitem,
191 gpointer user_data)
193 GtkWidget *dialog, *warning_dialog;
194 GtkFileFilter *filt_all, *filt_xoj;
195 char *filename;
196 char stime[30];
197 time_t curtime;
198 gboolean warn;
199 struct stat stat_buf;
201 end_text();
202 reset_focus();
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);
207 if (ui.filename!=NULL) {
208 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), ui.filename);
209 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), g_basename(ui.filename));
211 else
212 if (bgpdf.status!=STATUS_NOT_INIT && bgpdf.file_domain == DOMAIN_ABSOLUTE
213 && bgpdf.filename != NULL) {
214 filename = g_strdup_printf("%s.xoj", bgpdf.filename->s);
215 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), filename);
216 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), g_basename(filename));
217 g_free(filename);
219 else {
220 curtime = time(NULL);
221 strftime(stime, 30, "%F-Note-%H-%M.xoj", localtime(&curtime));
222 if (ui.default_path!=NULL)
223 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
224 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), stime);
227 filt_all = gtk_file_filter_new();
228 gtk_file_filter_set_name(filt_all, "All files");
229 gtk_file_filter_add_pattern(filt_all, "*");
230 filt_xoj = gtk_file_filter_new();
231 gtk_file_filter_set_name(filt_xoj, "Xournal files");
232 gtk_file_filter_add_pattern(filt_xoj, "*.xoj");
233 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_xoj);
234 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
236 // somehow this doesn't seem to be set by default
237 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
239 do {
240 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
241 gtk_widget_destroy(dialog);
242 return;
244 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
245 warn = g_file_test (filename, G_FILE_TEST_EXISTS);
246 if (warn) { // ok to overwrite an empty file
247 if (!g_stat(filename, &stat_buf))
248 if (stat_buf.st_size == 0) warn=FALSE;
250 if (warn && ui.filename!=NULL) { // ok to overwrite oneself
251 if (ui.filename[0]=='/' && !strcmp(ui.filename, filename)) warn=FALSE;
252 if (ui.filename[0]!='/' && g_str_has_suffix(filename, ui.filename)) warn=FALSE;
254 if (warn) {
255 warning_dialog = gtk_message_dialog_new(GTK_WINDOW(winMain),
256 GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
257 "Should the file %s be overwritten?", filename);
258 if (gtk_dialog_run(GTK_DIALOG(warning_dialog)) == GTK_RESPONSE_YES)
259 warn = FALSE;
260 gtk_widget_destroy(warning_dialog);
262 } while (warn);
264 gtk_widget_destroy(dialog);
266 set_cursor_busy(TRUE);
267 if (save_journal(filename)) { // success
268 ui.saved = TRUE;
269 set_cursor_busy(FALSE);
270 update_file_name(filename);
271 return;
273 set_cursor_busy(FALSE);
274 /* save failed */
275 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
276 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Error saving file '%s'", filename);
277 gtk_dialog_run(GTK_DIALOG(dialog));
278 gtk_widget_destroy(dialog);
279 g_free(filename);
283 void
284 on_filePrintOptions_activate (GtkMenuItem *menuitem,
285 gpointer user_data)
291 void
292 on_filePrint_activate (GtkMenuItem *menuitem,
293 gpointer user_data)
295 GtkWidget *printDialog;
296 GnomePrintJob *gpj;
297 int fromPage, toPage;
298 int response;
299 char *in_fn;
300 guchar *s;
301 GnomePrintConfig *config = gnome_print_config_default();
303 end_text();
304 reset_focus();
305 if (ui.filename!=NULL) {
306 if (g_str_has_suffix(ui.filename, ".xoj")) {
307 in_fn = g_strdup(ui.filename);
308 g_strlcpy(g_strrstr(in_fn, "xoj"), "pdf", 4);
310 else
311 in_fn = g_strdup_printf("%s.pdf", ui.filename);
312 gnome_print_config_set(config, (guchar *)"Printer", (guchar *)"PDF");
313 gnome_print_config_set(config, (guchar *)GNOME_PRINT_KEY_OUTPUT_FILENAME, (guchar *)in_fn);
314 gnome_print_config_set(config, (guchar *)"Settings.Transport.Backend.FileName", (guchar *)in_fn);
315 g_strlcpy(g_strrstr(in_fn, "pdf"), "ps", 3);
316 gnome_print_config_set(config, (guchar *)"Printer", (guchar *)"GENERIC");
317 gnome_print_config_set (config, (guchar *)GNOME_PRINT_KEY_OUTPUT_FILENAME, (guchar *)in_fn);
318 s = gnome_print_config_get(config, (guchar *)"Settings.Transport.Backend.FileName");
319 if (s != NULL) {
320 g_free(s);
321 gnome_print_config_set(config, (guchar *)"Settings.Transport.Backend.FileName", (guchar *)in_fn);
323 g_free(in_fn);
326 gpj = gnome_print_job_new(config); /* was NULL */
327 gnome_print_config_unref(config);
328 /* end */
329 printDialog = gnome_print_dialog_new(gpj, (guchar *)"Print", GNOME_PRINT_DIALOG_RANGE);
330 gnome_print_dialog_construct_range_page(GNOME_PRINT_DIALOG(printDialog),
331 GNOME_PRINT_RANGE_ALL | GNOME_PRINT_RANGE_RANGE,
332 1, journal.npages, (guchar *)"Current page", (guchar *)"Pages");
333 /* don't have "Current page" as option, else it becomes the default!! */
335 gtk_dialog_set_response_sensitive(GTK_DIALOG(printDialog),
336 GNOME_PRINT_DIALOG_RESPONSE_PREVIEW, FALSE);
337 /* the print-job-preview "feature" is completely, hopelessly broken */
339 response = gtk_dialog_run(GTK_DIALOG(printDialog));
340 if (response <= 0) {
341 gtk_widget_destroy(printDialog);
342 return;
346 if (response == GNOME_PRINT_DIALOG_RESPONSE_PREVIEW) {
347 print_job_render(gpj, 0, journal.npages-1);
348 gtk_widget_destroy(printDialog);
349 preview = gnome_print_job_preview_new(gpj, (guchar *)"Preview");
350 try_fix_print_preview_ui(preview);
351 gtk_window_set_modal(GTK_WINDOW(preview), TRUE);
352 gtk_widget_show_all(preview);
356 if (response == GNOME_PRINT_DIALOG_RESPONSE_PRINT) {
357 switch(gnome_print_dialog_get_range(GNOME_PRINT_DIALOG(printDialog))) {
358 case GNOME_PRINT_RANGE_RANGE:
359 gnome_print_dialog_get_range_page(GNOME_PRINT_DIALOG(printDialog), &fromPage, &toPage);
360 fromPage--;
361 toPage--;
362 break;
363 default:
364 fromPage = 0;
365 toPage = journal.npages-1;
368 gtk_widget_destroy(printDialog);
369 print_job_render(gpj, fromPage, toPage);
374 void
375 on_filePrintPDF_activate (GtkMenuItem *menuitem,
376 gpointer user_data)
379 GtkWidget *dialog, *warning_dialog;
380 GtkFileFilter *filt_all, *filt_pdf;
381 char *filename, *in_fn;
382 char stime[30];
383 time_t curtime;
384 gboolean warn;
386 end_text();
387 reset_focus();
388 dialog = gtk_file_chooser_dialog_new("Export to PDF", GTK_WINDOW (winMain),
389 GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
390 GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
392 if (ui.filename!=NULL) {
393 if (g_str_has_suffix(ui.filename, ".xoj")) {
394 in_fn = g_strdup(ui.filename);
395 g_strlcpy(g_strrstr(in_fn, "xoj"), "pdf", 4);
397 else
398 in_fn = g_strdup_printf("%s.pdf", ui.filename);
399 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER (dialog), in_fn);
400 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), g_basename(in_fn));
401 } else {
402 curtime = time(NULL);
403 strftime(stime, 30, "%F-Note-%H-%M.pdf", localtime(&curtime));
404 if (ui.default_path!=NULL)
405 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
406 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (dialog), stime);
407 in_fn = NULL;
410 filt_all = gtk_file_filter_new();
411 gtk_file_filter_set_name(filt_all, "All files");
412 gtk_file_filter_add_pattern(filt_all, "*");
413 filt_pdf = gtk_file_filter_new();
414 gtk_file_filter_set_name(filt_pdf, "PDF files");
415 gtk_file_filter_add_pattern(filt_pdf, "*.pdf");
416 gtk_file_filter_add_pattern(filt_pdf, "*.PDF");
417 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pdf);
418 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
419 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
420 g_free(in_fn);
422 do {
423 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
424 gtk_widget_destroy(dialog);
425 return;
427 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
428 warn = g_file_test(filename, G_FILE_TEST_EXISTS);
429 if (warn) {
430 warning_dialog = gtk_message_dialog_new(GTK_WINDOW(winMain),
431 GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
432 "Should the file %s be overwritten?", filename);
433 if (gtk_dialog_run(GTK_DIALOG(warning_dialog)) == GTK_RESPONSE_YES)
434 warn = FALSE;
435 gtk_widget_destroy(warning_dialog);
437 } while(warn);
439 gtk_widget_destroy(dialog);
441 set_cursor_busy(TRUE);
442 if (!print_to_pdf(filename)) {
443 set_cursor_busy(FALSE);
444 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
445 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Error creating file '%s'", filename);
446 gtk_dialog_run(GTK_DIALOG(dialog));
447 gtk_widget_destroy(dialog);
449 set_cursor_busy(FALSE);
450 g_free(filename);
454 void
455 on_fileQuit_activate (GtkMenuItem *menuitem,
456 gpointer user_data)
458 end_text();
459 reset_focus();
460 if (ok_to_close()) gtk_main_quit ();
464 void
465 on_editUndo_activate (GtkMenuItem *menuitem,
466 gpointer user_data)
468 struct UndoItem *u;
469 GList *list, *itemlist;
470 struct UndoErasureData *erasure;
471 struct Item *it;
472 struct Brush tmp_brush;
473 struct Background *tmp_bg;
474 double tmp_x, tmp_y;
475 gchar *tmpstr;
476 GnomeCanvasGroup *group;
478 end_text();
479 reset_focus();
480 if (undo == NULL) return; // nothing to undo!
481 reset_selection(); // safer
482 if (undo->type == ITEM_STROKE || undo->type == ITEM_TEXT) {
483 // we're keeping the stroke info, but deleting the canvas item
484 gtk_object_destroy(GTK_OBJECT(undo->item->canvas_item));
485 undo->item->canvas_item = NULL;
486 // we also remove the object from its layer!
487 undo->layer->items = g_list_remove(undo->layer->items, undo->item);
488 undo->layer->nitems--;
490 else if (undo->type == ITEM_ERASURE || undo->type == ITEM_RECOGNIZER) {
491 for (list = undo->erasurelist; list!=NULL; list = list->next) {
492 erasure = (struct UndoErasureData *)list->data;
493 // delete all the created items
494 for (itemlist = erasure->replacement_items; itemlist!=NULL; itemlist = itemlist->next) {
495 it = (struct Item *)itemlist->data;
496 gtk_object_destroy(GTK_OBJECT(it->canvas_item));
497 it->canvas_item = NULL;
498 undo->layer->items = g_list_remove(undo->layer->items, it);
499 undo->layer->nitems--;
501 // recreate the deleted one
502 make_canvas_item_one(undo->layer->group, erasure->item);
504 undo->layer->items = g_list_insert(undo->layer->items, erasure->item,
505 erasure->npos);
506 if (erasure->npos == 0)
507 lower_canvas_item_to(undo->layer->group, erasure->item->canvas_item, NULL);
508 else
509 lower_canvas_item_to(undo->layer->group, erasure->item->canvas_item,
510 ((struct Item *)g_list_nth_data(undo->layer->items, erasure->npos-1))->canvas_item);
511 undo->layer->nitems++;
514 else if (undo->type == ITEM_NEW_BG_ONE || undo->type == ITEM_NEW_BG_RESIZE
515 || undo->type == ITEM_PAPER_RESIZE) {
516 if (undo->type != ITEM_PAPER_RESIZE) {
517 // swap the two bg's
518 tmp_bg = undo->page->bg;
519 undo->page->bg = undo->bg;
520 undo->bg = tmp_bg;
521 undo->page->bg->canvas_item = undo->bg->canvas_item;
522 undo->bg->canvas_item = NULL;
524 if (undo->type != ITEM_NEW_BG_ONE) {
525 tmp_x = undo->page->width;
526 tmp_y = undo->page->height;
527 undo->page->width = undo->val_x;
528 undo->page->height = undo->val_y;
529 undo->val_x = tmp_x;
530 undo->val_y = tmp_y;
531 make_page_clipbox(undo->page);
533 update_canvas_bg(undo->page);
534 do_switch_page(g_list_index(journal.pages, undo->page), TRUE, TRUE);
536 else if (undo->type == ITEM_NEW_DEFAULT_BG) {
537 tmp_bg = ui.default_page.bg;
538 ui.default_page.bg = undo->bg;
539 undo->bg = tmp_bg;
540 tmp_x = ui.default_page.width;
541 tmp_y = ui.default_page.height;
542 ui.default_page.width = undo->val_x;
543 ui.default_page.height = undo->val_y;
544 undo->val_x = tmp_x;
545 undo->val_y = tmp_y;
547 else if (undo->type == ITEM_NEW_PAGE) {
548 // unmap the page; keep the page & its empty layer in memory
549 if (undo->page->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->page->group));
550 // also destroys the background and layer's canvas items
551 undo->page->group = NULL;
552 undo->page->bg->canvas_item = NULL;
553 journal.pages = g_list_remove(journal.pages, undo->page);
554 journal.npages--;
555 if (ui.cur_page == undo->page) ui.cur_page = NULL;
556 // so do_switch_page() won't try to remap the layers of the defunct page
557 if (ui.pageno >= undo->val) ui.pageno--;
558 if (ui.pageno < 0) ui.pageno = 0;
559 do_switch_page(ui.pageno, TRUE, TRUE);
561 else if (undo->type == ITEM_DELETE_PAGE) {
562 journal.pages = g_list_insert(journal.pages, undo->page, undo->val);
563 journal.npages++;
564 make_canvas_items(); // re-create the canvas items
565 do_switch_page(undo->val, TRUE, TRUE);
567 else if (undo->type == ITEM_MOVESEL) {
568 for (itemlist = undo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
569 it = (struct Item *)itemlist->data;
570 if (it->canvas_item != NULL) {
571 if (undo->layer != undo->layer2)
572 gnome_canvas_item_reparent(it->canvas_item, undo->layer->group);
573 gnome_canvas_item_move(it->canvas_item, -undo->val_x, -undo->val_y);
576 move_journal_items_by(undo->itemlist, -undo->val_x, -undo->val_y,
577 undo->layer2, undo->layer, undo->auxlist);
579 else if (undo->type == ITEM_RESIZESEL) {
580 resize_journal_items_by(undo->itemlist,
581 1/undo->scaling_x, 1/undo->scaling_y,
582 -undo->val_x/undo->scaling_x, -undo->val_y/undo->scaling_y);
584 else if (undo->type == ITEM_PASTE) {
585 for (itemlist = undo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
586 it = (struct Item *)itemlist->data;
587 gtk_object_destroy(GTK_OBJECT(it->canvas_item));
588 it->canvas_item = NULL;
589 undo->layer->items = g_list_remove(undo->layer->items, it);
590 undo->layer->nitems--;
593 else if (undo->type == ITEM_NEW_LAYER) {
594 // unmap the layer; keep the empty layer in memory
595 if (undo->layer->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->layer->group));
596 undo->layer->group = NULL;
597 undo->page->layers = g_list_remove(undo->page->layers, undo->layer);
598 undo->page->nlayers--;
599 do_switch_page(ui.pageno, FALSE, FALSE); // don't stay with bad cur_layer info
601 else if (undo->type == ITEM_DELETE_LAYER) {
602 // special case of -1: deleted the last layer, created a new one
603 if (undo->val == -1) {
604 if (undo->layer2->group!=NULL) gtk_object_destroy(GTK_OBJECT(undo->layer2->group));
605 undo->layer2->group = NULL;
606 undo->page->layers = g_list_remove(undo->page->layers, undo->layer2);
607 undo->page->nlayers--;
609 // re-map the layer
610 undo->layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
611 undo->page->group, gnome_canvas_group_get_type(), NULL);
612 lower_canvas_item_to(undo->page->group, GNOME_CANVAS_ITEM(undo->layer->group),
613 (undo->val >= 1) ? GNOME_CANVAS_ITEM(((struct Layer *)
614 g_list_nth_data(undo->page->layers, undo->val-1))->group) :
615 undo->page->bg->canvas_item);
616 undo->page->layers = g_list_insert(undo->page->layers, undo->layer,
617 (undo->val >= 0) ? undo->val:0);
618 undo->page->nlayers++;
620 for (itemlist = undo->layer->items; itemlist!=NULL; itemlist = itemlist->next)
621 make_canvas_item_one(undo->layer->group, (struct Item *)itemlist->data);
623 do_switch_page(ui.pageno, FALSE, FALSE); // show the restored layer & others...
625 else if (undo->type == ITEM_REPAINTSEL) {
626 for (itemlist = undo->itemlist, list = undo->auxlist; itemlist!=NULL;
627 itemlist = itemlist->next, list = list->next) {
628 it = (struct Item *)itemlist->data;
629 g_memmove(&tmp_brush, &(it->brush), sizeof(struct Brush));
630 g_memmove(&(it->brush), list->data, sizeof(struct Brush));
631 g_memmove(list->data, &tmp_brush, sizeof(struct Brush));
632 if (it->type == ITEM_STROKE && it->canvas_item != NULL) {
633 // remark: a variable-width item might have lost its variable-width
634 group = (GnomeCanvasGroup *) it->canvas_item->parent;
635 gtk_object_destroy(GTK_OBJECT(it->canvas_item));
636 make_canvas_item_one(group, it);
638 if (it->type == ITEM_TEXT && it->canvas_item != NULL)
639 gnome_canvas_item_set(it->canvas_item,
640 "fill-color-rgba", it->brush.color_rgba, NULL);
643 else if (undo->type == ITEM_TEXT_EDIT) {
644 tmpstr = undo->str;
645 undo->str = undo->item->text;
646 undo->item->text = tmpstr;
647 gnome_canvas_item_set(undo->item->canvas_item, "text", tmpstr, NULL);
648 update_item_bbox(undo->item);
650 else if (undo->type == ITEM_TEXT_ATTRIB) {
651 tmpstr = undo->str;
652 undo->str = undo->item->font_name;
653 undo->item->font_name = tmpstr;
654 tmp_x = undo->val_x;
655 undo->val_x = undo->item->font_size;
656 undo->item->font_size = tmp_x;
657 g_memmove(&tmp_brush, undo->brush, sizeof(struct Brush));
658 g_memmove(undo->brush, &(undo->item->brush), sizeof(struct Brush));
659 g_memmove(&(undo->item->brush), &tmp_brush, sizeof(struct Brush));
660 gnome_canvas_item_set(undo->item->canvas_item,
661 "fill-color-rgba", undo->item->brush.color_rgba, NULL);
662 update_text_item_displayfont(undo->item);
663 update_item_bbox(undo->item);
666 // move item from undo to redo stack
667 u = undo;
668 undo = undo->next;
669 u->next = redo;
670 redo = u;
671 ui.saved = FALSE;
672 update_undo_redo_enabled();
673 if (u->multiop & MULTIOP_CONT_UNDO) on_editUndo_activate(NULL,NULL); // loop
677 void
678 on_editRedo_activate (GtkMenuItem *menuitem,
679 gpointer user_data)
681 struct UndoItem *u;
682 GList *list, *itemlist, *target;
683 struct UndoErasureData *erasure;
684 struct Item *it;
685 struct Brush tmp_brush;
686 struct Background *tmp_bg;
687 struct Layer *l;
688 double tmp_x, tmp_y;
689 gchar *tmpstr;
690 GnomeCanvasGroup *group;
692 end_text();
693 reset_focus();
694 if (redo == NULL) return; // nothing to redo!
695 reset_selection(); // safer
696 if (redo->type == ITEM_STROKE || redo->type == ITEM_TEXT) {
697 // re-create the canvas_item
698 make_canvas_item_one(redo->layer->group, redo->item);
699 // reinsert the item on its layer
700 redo->layer->items = g_list_append(redo->layer->items, redo->item);
701 redo->layer->nitems++;
703 else if (redo->type == ITEM_ERASURE || redo->type == ITEM_RECOGNIZER) {
704 for (list = redo->erasurelist; list!=NULL; list = list->next) {
705 erasure = (struct UndoErasureData *)list->data;
706 target = g_list_find(redo->layer->items, erasure->item);
707 // re-create all the created items
708 for (itemlist = erasure->replacement_items; itemlist!=NULL; itemlist = itemlist->next) {
709 it = (struct Item *)itemlist->data;
710 make_canvas_item_one(redo->layer->group, it);
711 redo->layer->items = g_list_insert_before(redo->layer->items, target, it);
712 redo->layer->nitems++;
713 lower_canvas_item_to(redo->layer->group, it->canvas_item, erasure->item->canvas_item);
715 // re-delete the deleted one
716 gtk_object_destroy(GTK_OBJECT(erasure->item->canvas_item));
717 erasure->item->canvas_item = NULL;
718 redo->layer->items = g_list_delete_link(redo->layer->items, target);
719 redo->layer->nitems--;
722 else if (redo->type == ITEM_NEW_BG_ONE || redo->type == ITEM_NEW_BG_RESIZE
723 || redo->type == ITEM_PAPER_RESIZE) {
724 if (redo->type != ITEM_PAPER_RESIZE) {
725 // swap the two bg's
726 tmp_bg = redo->page->bg;
727 redo->page->bg = redo->bg;
728 redo->bg = tmp_bg;
729 redo->page->bg->canvas_item = redo->bg->canvas_item;
730 redo->bg->canvas_item = NULL;
732 if (redo->type != ITEM_NEW_BG_ONE) {
733 tmp_x = redo->page->width;
734 tmp_y = redo->page->height;
735 redo->page->width = redo->val_x;
736 redo->page->height = redo->val_y;
737 redo->val_x = tmp_x;
738 redo->val_y = tmp_y;
739 make_page_clipbox(redo->page);
741 update_canvas_bg(redo->page);
742 do_switch_page(g_list_index(journal.pages, redo->page), TRUE, TRUE);
744 else if (redo->type == ITEM_NEW_DEFAULT_BG) {
745 tmp_bg = ui.default_page.bg;
746 ui.default_page.bg = redo->bg;
747 redo->bg = tmp_bg;
748 tmp_x = ui.default_page.width;
749 tmp_y = ui.default_page.height;
750 ui.default_page.width = redo->val_x;
751 ui.default_page.height = redo->val_y;
752 redo->val_x = tmp_x;
753 redo->val_y = tmp_y;
755 else if (redo->type == ITEM_NEW_PAGE) {
756 // remap the page
757 redo->page->bg->canvas_item = NULL;
758 redo->page->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
759 gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
760 make_page_clipbox(redo->page);
761 update_canvas_bg(redo->page);
762 l = (struct Layer *)redo->page->layers->data;
763 l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
764 redo->page->group, gnome_canvas_group_get_type(), NULL);
766 journal.pages = g_list_insert(journal.pages, redo->page, redo->val);
767 journal.npages++;
768 do_switch_page(redo->val, TRUE, TRUE);
770 else if (redo->type == ITEM_DELETE_PAGE) {
771 // unmap all the canvas items
772 gtk_object_destroy(GTK_OBJECT(redo->page->group));
773 redo->page->group = NULL;
774 redo->page->bg->canvas_item = NULL;
775 for (list = redo->page->layers; list!=NULL; list = list->next) {
776 l = (struct Layer *)list->data;
777 for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next)
778 ((struct Item *)itemlist->data)->canvas_item = NULL;
779 l->group = NULL;
781 journal.pages = g_list_remove(journal.pages, redo->page);
782 journal.npages--;
783 if (ui.pageno > redo->val || ui.pageno == journal.npages) ui.pageno--;
784 ui.cur_page = NULL;
785 // so do_switch_page() won't try to remap the layers of the defunct page
786 do_switch_page(ui.pageno, TRUE, TRUE);
788 else if (redo->type == ITEM_MOVESEL) {
789 for (itemlist = redo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
790 it = (struct Item *)itemlist->data;
791 if (it->canvas_item != NULL) {
792 if (redo->layer != redo->layer2)
793 gnome_canvas_item_reparent(it->canvas_item, redo->layer2->group);
794 gnome_canvas_item_move(it->canvas_item, redo->val_x, redo->val_y);
797 move_journal_items_by(redo->itemlist, redo->val_x, redo->val_y,
798 redo->layer, redo->layer2, NULL);
800 else if (redo->type == ITEM_RESIZESEL) {
801 resize_journal_items_by(redo->itemlist,
802 redo->scaling_x, redo->scaling_y, redo->val_x, redo->val_y);
804 else if (redo->type == ITEM_PASTE) {
805 for (itemlist = redo->itemlist; itemlist != NULL; itemlist = itemlist->next) {
806 it = (struct Item *)itemlist->data;
807 make_canvas_item_one(redo->layer->group, it);
808 redo->layer->items = g_list_append(redo->layer->items, it);
809 redo->layer->nitems++;
812 else if (redo->type == ITEM_NEW_LAYER) {
813 redo->layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
814 redo->page->group, gnome_canvas_group_get_type(), NULL);
815 lower_canvas_item_to(redo->page->group, GNOME_CANVAS_ITEM(redo->layer->group),
816 (redo->val >= 1) ? GNOME_CANVAS_ITEM(((struct Layer *)
817 g_list_nth_data(redo->page->layers, redo->val-1))->group) :
818 redo->page->bg->canvas_item);
819 redo->page->layers = g_list_insert(redo->page->layers, redo->layer, redo->val);
820 redo->page->nlayers++;
821 do_switch_page(ui.pageno, FALSE, FALSE);
823 else if (redo->type == ITEM_DELETE_LAYER) {
824 gtk_object_destroy(GTK_OBJECT(redo->layer->group));
825 redo->layer->group = NULL;
826 for (list=redo->layer->items; list!=NULL; list=list->next)
827 ((struct Item *)list->data)->canvas_item = NULL;
828 redo->page->layers = g_list_remove(redo->page->layers, redo->layer);
829 redo->page->nlayers--;
830 if (redo->val == -1) {
831 redo->layer2->group = (GnomeCanvasGroup *)gnome_canvas_item_new(
832 redo->page->group, gnome_canvas_group_get_type(), NULL);
833 redo->page->layers = g_list_append(redo->page->layers, redo->layer2);
834 redo->page->nlayers++;
836 do_switch_page(ui.pageno, FALSE, FALSE);
838 else if (redo->type == ITEM_REPAINTSEL) {
839 for (itemlist = redo->itemlist, list = redo->auxlist; itemlist!=NULL;
840 itemlist = itemlist->next, list = list->next) {
841 it = (struct Item *)itemlist->data;
842 g_memmove(&tmp_brush, &(it->brush), sizeof(struct Brush));
843 g_memmove(&(it->brush), list->data, sizeof(struct Brush));
844 g_memmove(list->data, &tmp_brush, sizeof(struct Brush));
845 if (it->type == ITEM_STROKE && it->canvas_item != NULL) {
846 // remark: a variable-width item might have lost its variable-width
847 group = (GnomeCanvasGroup *) it->canvas_item->parent;
848 gtk_object_destroy(GTK_OBJECT(it->canvas_item));
849 make_canvas_item_one(group, it);
851 if (it->type == ITEM_TEXT && it->canvas_item != NULL)
852 gnome_canvas_item_set(it->canvas_item,
853 "fill-color-rgba", it->brush.color_rgba, NULL);
856 else if (redo->type == ITEM_TEXT_EDIT) {
857 tmpstr = redo->str;
858 redo->str = redo->item->text;
859 redo->item->text = tmpstr;
860 gnome_canvas_item_set(redo->item->canvas_item, "text", tmpstr, NULL);
861 update_item_bbox(redo->item);
863 else if (redo->type == ITEM_TEXT_ATTRIB) {
864 tmpstr = redo->str;
865 redo->str = redo->item->font_name;
866 redo->item->font_name = tmpstr;
867 tmp_x = redo->val_x;
868 redo->val_x = redo->item->font_size;
869 redo->item->font_size = tmp_x;
870 g_memmove(&tmp_brush, redo->brush, sizeof(struct Brush));
871 g_memmove(redo->brush, &(redo->item->brush), sizeof(struct Brush));
872 g_memmove(&(redo->item->brush), &tmp_brush, sizeof(struct Brush));
873 gnome_canvas_item_set(redo->item->canvas_item,
874 "fill-color-rgba", redo->item->brush.color_rgba, NULL);
875 update_text_item_displayfont(redo->item);
876 update_item_bbox(redo->item);
879 // move item from redo to undo stack
880 u = redo;
881 redo = redo->next;
882 u->next = undo;
883 undo = u;
884 ui.saved = FALSE;
885 update_undo_redo_enabled();
886 if (u->multiop & MULTIOP_CONT_REDO) on_editRedo_activate(NULL,NULL); // loop
890 void
891 on_editCut_activate (GtkMenuItem *menuitem,
892 gpointer user_data)
894 end_text();
895 reset_focus();
896 selection_to_clip();
897 selection_delete();
901 void
902 on_editCopy_activate (GtkMenuItem *menuitem,
903 gpointer user_data)
905 end_text();
906 reset_focus();
907 selection_to_clip();
911 void
912 on_editPaste_activate (GtkMenuItem *menuitem,
913 gpointer user_data)
915 end_text();
916 reset_focus();
917 clipboard_paste();
921 void
922 on_editDelete_activate (GtkMenuItem *menuitem,
923 gpointer user_data)
925 end_text();
926 reset_focus();
927 selection_delete();
931 void
932 on_viewContinuous_activate (GtkMenuItem *menuitem,
933 gpointer user_data)
935 GtkAdjustment *v_adj;
936 double yscroll;
937 struct Page *pg;
939 reset_focus();
940 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
941 if (ui.view_continuous) return;
942 ui.view_continuous = TRUE;
943 v_adj = gtk_layout_get_vadjustment(GTK_LAYOUT(canvas));
944 pg = ui.cur_page;
945 yscroll = gtk_adjustment_get_value(v_adj) - pg->voffset*ui.zoom;
946 update_page_stuff();
947 gtk_adjustment_set_value(v_adj, yscroll + pg->voffset*ui.zoom);
948 // force a refresh
949 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
953 void
954 on_viewOnePage_activate (GtkMenuItem *menuitem,
955 gpointer user_data)
957 GtkAdjustment *v_adj;
958 double yscroll;
960 reset_focus();
961 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
962 if (!ui.view_continuous) return;
963 ui.view_continuous = FALSE;
964 v_adj = gtk_layout_get_vadjustment(GTK_LAYOUT(canvas));
965 yscroll = gtk_adjustment_get_value(v_adj) - ui.cur_page->voffset*ui.zoom;
966 update_page_stuff();
967 gtk_adjustment_set_value(v_adj, yscroll + ui.cur_page->voffset*ui.zoom);
968 // force a refresh
969 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
973 void
974 on_viewZoomIn_activate (GtkMenuItem *menuitem,
975 gpointer user_data)
977 reset_focus();
978 if (ui.zoom > MAX_ZOOM) return;
979 ui.zoom *= ui.zoom_step_factor;
980 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
981 rescale_text_items();
982 rescale_bg_pixmaps();
986 void
987 on_viewZoomOut_activate (GtkMenuItem *menuitem,
988 gpointer user_data)
990 reset_focus();
991 if (ui.zoom < MIN_ZOOM) return;
992 ui.zoom /= ui.zoom_step_factor;
993 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
994 rescale_text_items();
995 rescale_bg_pixmaps();
999 void
1000 on_viewNormalSize_activate (GtkMenuItem *menuitem,
1001 gpointer user_data)
1003 reset_focus();
1004 ui.zoom = DEFAULT_ZOOM;
1005 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
1006 rescale_text_items();
1007 rescale_bg_pixmaps();
1011 void
1012 on_viewPageWidth_activate (GtkMenuItem *menuitem,
1013 gpointer user_data)
1015 reset_focus();
1016 ui.zoom = (GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width;
1017 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
1018 rescale_text_items();
1019 rescale_bg_pixmaps();
1023 void
1024 on_viewFirstPage_activate (GtkMenuItem *menuitem,
1025 gpointer user_data)
1027 end_text();
1028 reset_focus();
1029 do_switch_page(0, TRUE, FALSE);
1033 void
1034 on_viewPreviousPage_activate (GtkMenuItem *menuitem,
1035 gpointer user_data)
1037 end_text();
1038 reset_focus();
1039 if (ui.pageno == 0) return;
1040 do_switch_page(ui.pageno-1, TRUE, FALSE);
1044 void
1045 on_viewNextPage_activate (GtkMenuItem *menuitem,
1046 gpointer user_data)
1048 end_text();
1049 reset_focus();
1050 if (ui.pageno == journal.npages-1) { // create a page at end
1051 if (page_ops_forbidden()) return;
1052 on_journalNewPageEnd_activate(menuitem, user_data);
1053 return;
1055 do_switch_page(ui.pageno+1, TRUE, FALSE);
1059 void
1060 on_viewLastPage_activate (GtkMenuItem *menuitem,
1061 gpointer user_data)
1063 end_text();
1064 reset_focus();
1065 do_switch_page(journal.npages-1, TRUE, FALSE);
1069 void
1070 on_viewShowLayer_activate (GtkMenuItem *menuitem,
1071 gpointer user_data)
1073 end_text();
1074 reset_focus();
1075 if (ui.layerno == ui.cur_page->nlayers-1) return;
1076 reset_selection();
1077 ui.layerno++;
1078 ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
1079 gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group));
1080 update_page_stuff();
1084 void
1085 on_viewHideLayer_activate (GtkMenuItem *menuitem,
1086 gpointer user_data)
1088 end_text();
1089 reset_focus();
1090 if (ui.layerno == -1) return;
1091 reset_selection();
1092 gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group));
1093 ui.layerno--;
1094 if (ui.layerno<0) ui.cur_layer = NULL;
1095 else ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
1096 update_page_stuff();
1100 void
1101 on_journalNewPageBefore_activate (GtkMenuItem *menuitem,
1102 gpointer user_data)
1104 struct Page *pg;
1106 end_text();
1107 reset_focus();
1108 if (page_ops_forbidden()) return;
1109 reset_selection();
1110 pg = new_page(ui.cur_page);
1111 journal.pages = g_list_insert(journal.pages, pg, ui.pageno);
1112 journal.npages++;
1113 do_switch_page(ui.pageno, TRUE, TRUE);
1115 prepare_new_undo();
1116 undo->type = ITEM_NEW_PAGE;
1117 undo->val = ui.pageno;
1118 undo->page = pg;
1122 void
1123 on_journalNewPageAfter_activate (GtkMenuItem *menuitem,
1124 gpointer user_data)
1126 struct Page *pg;
1128 end_text();
1129 reset_focus();
1130 if (page_ops_forbidden()) return;
1131 reset_selection();
1132 pg = new_page(ui.cur_page);
1133 journal.pages = g_list_insert(journal.pages, pg, ui.pageno+1);
1134 journal.npages++;
1135 do_switch_page(ui.pageno+1, TRUE, TRUE);
1137 prepare_new_undo();
1138 undo->type = ITEM_NEW_PAGE;
1139 undo->val = ui.pageno;
1140 undo->page = pg;
1144 void
1145 on_journalNewPageEnd_activate (GtkMenuItem *menuitem,
1146 gpointer user_data)
1148 struct Page *pg;
1150 end_text();
1151 reset_focus();
1152 if (page_ops_forbidden()) return;
1153 reset_selection();
1154 pg = new_page((struct Page *)g_list_last(journal.pages)->data);
1155 journal.pages = g_list_append(journal.pages, pg);
1156 journal.npages++;
1157 do_switch_page(journal.npages-1, TRUE, TRUE);
1159 prepare_new_undo();
1160 undo->type = ITEM_NEW_PAGE;
1161 undo->val = ui.pageno;
1162 undo->page = pg;
1166 void
1167 on_journalDeletePage_activate (GtkMenuItem *menuitem,
1168 gpointer user_data)
1170 GList *layerlist, *itemlist;
1171 struct Layer *l;
1173 end_text();
1174 reset_focus();
1175 if (page_ops_forbidden()) return;
1176 if (journal.npages == 1) return;
1177 reset_selection();
1178 prepare_new_undo();
1179 undo->type = ITEM_DELETE_PAGE;
1180 undo->val = ui.pageno;
1181 undo->page = ui.cur_page;
1183 // unmap all the canvas items
1184 gtk_object_destroy(GTK_OBJECT(ui.cur_page->group));
1185 ui.cur_page->group = NULL;
1186 ui.cur_page->bg->canvas_item = NULL;
1187 for (layerlist = ui.cur_page->layers; layerlist!=NULL; layerlist = layerlist->next) {
1188 l = (struct Layer *)layerlist->data;
1189 for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next)
1190 ((struct Item *)itemlist->data)->canvas_item = NULL;
1191 l->group = NULL;
1194 journal.pages = g_list_remove(journal.pages, ui.cur_page);
1195 journal.npages--;
1196 if (ui.pageno == journal.npages) ui.pageno--;
1197 ui.cur_page = NULL;
1198 // so do_switch_page() won't try to remap the layers of the defunct page
1199 do_switch_page(ui.pageno, TRUE, TRUE);
1203 void
1204 on_journalNewLayer_activate (GtkMenuItem *menuitem,
1205 gpointer user_data)
1207 struct Layer *l;
1209 end_text();
1210 reset_focus();
1211 reset_selection();
1212 l = g_new(struct Layer, 1);
1213 l->items = NULL;
1214 l->nitems = 0;
1215 l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
1216 ui.cur_page->group, gnome_canvas_group_get_type(), NULL);
1217 lower_canvas_item_to(ui.cur_page->group, GNOME_CANVAS_ITEM(l->group),
1218 (ui.cur_layer!=NULL)?(GNOME_CANVAS_ITEM(ui.cur_layer->group)):(ui.cur_page->bg->canvas_item));
1219 ui.cur_page->layers = g_list_insert(ui.cur_page->layers, l, ui.layerno+1);
1220 ui.cur_layer = l;
1221 ui.layerno++;
1222 ui.cur_page->nlayers++;
1223 update_page_stuff();
1225 prepare_new_undo();
1226 undo->type = ITEM_NEW_LAYER;
1227 undo->val = ui.layerno;
1228 undo->layer = l;
1229 undo->page = ui.cur_page;
1233 void
1234 on_journalDeleteLayer_activate (GtkMenuItem *menuitem,
1235 gpointer user_data)
1237 GList *list;
1239 end_text();
1240 reset_focus();
1241 if (ui.cur_layer == NULL) return;
1242 reset_selection();
1243 prepare_new_undo();
1244 undo->type = ITEM_DELETE_LAYER;
1245 undo->val = ui.layerno;
1246 undo->layer = ui.cur_layer;
1247 undo->layer2 = NULL;
1248 undo->page = ui.cur_page;
1249 // delete all the canvas items
1250 gtk_object_destroy(GTK_OBJECT(ui.cur_layer->group));
1251 ui.cur_layer->group = NULL;
1252 for (list=ui.cur_layer->items; list!=NULL; list=list->next)
1253 ((struct Item *)list->data)->canvas_item = NULL;
1255 ui.cur_page->layers = g_list_remove(ui.cur_page->layers, ui.cur_layer);
1257 if (ui.cur_page->nlayers>=2) {
1258 ui.cur_page->nlayers--;
1259 ui.layerno--;
1260 if (ui.layerno<0) ui.cur_layer = NULL;
1261 else ui.cur_layer = (struct Layer *)g_list_nth_data(ui.cur_page->layers, ui.layerno);
1263 else { // special case: can't remove the last layer
1264 ui.cur_layer = g_new(struct Layer, 1);
1265 ui.cur_layer->items = NULL;
1266 ui.cur_layer->nitems = 0;
1267 ui.cur_layer->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
1268 ui.cur_page->group, gnome_canvas_group_get_type(), NULL);
1269 ui.cur_page->layers = g_list_append(NULL, ui.cur_layer);
1270 undo->val = -1;
1271 undo->layer2 = ui.cur_layer;
1274 update_page_stuff();
1278 void
1279 on_journalFlatten_activate (GtkMenuItem *menuitem,
1280 gpointer user_data)
1286 // the paper sizes dialog
1288 GtkWidget *papersize_dialog;
1289 int papersize_std, papersize_unit;
1290 double papersize_width, papersize_height;
1291 gboolean papersize_need_init, papersize_width_valid, papersize_height_valid;
1293 #define STD_SIZE_A4 0
1294 #define STD_SIZE_A4R 1
1295 #define STD_SIZE_LETTER 2
1296 #define STD_SIZE_LETTER_R 3
1297 #define STD_SIZE_CUSTOM 4
1299 double unit_sizes[4] = {28.346, 72., 72./DISPLAY_DPI_DEFAULT, 1.};
1300 double std_widths[STD_SIZE_CUSTOM] = {595.27, 841.89, 612., 792.};
1301 double std_heights[STD_SIZE_CUSTOM] = {841.89, 595.27, 792., 612.};
1302 double std_units[STD_SIZE_CUSTOM] = {UNIT_CM, UNIT_CM, UNIT_IN, UNIT_IN};
1304 void
1305 on_journalPaperSize_activate (GtkMenuItem *menuitem,
1306 gpointer user_data)
1308 int i, response;
1309 struct Page *pg;
1310 GList *pglist;
1312 end_text();
1313 reset_focus();
1314 papersize_dialog = create_papersizeDialog();
1315 papersize_width = ui.cur_page->width;
1316 papersize_height = ui.cur_page->height;
1317 papersize_unit = ui.default_unit;
1318 unit_sizes[UNIT_PX] = 1./DEFAULT_ZOOM;
1319 // if (ui.cur_page->bg->type == BG_PIXMAP) papersize_unit = UNIT_PX;
1320 papersize_std = STD_SIZE_CUSTOM;
1321 for (i=0;i<STD_SIZE_CUSTOM;i++)
1322 if (fabs(papersize_width - std_widths[i])<0.1 &&
1323 fabs(papersize_height - std_heights[i])<0.1)
1324 { papersize_std = i; papersize_unit = std_units[i]; }
1325 papersize_need_init = TRUE;
1326 papersize_width_valid = papersize_height_valid = TRUE;
1328 gtk_widget_show(papersize_dialog);
1329 on_comboStdSizes_changed(GTK_COMBO_BOX(g_object_get_data(
1330 G_OBJECT(papersize_dialog), "comboStdSizes")), NULL);
1331 gtk_dialog_set_default_response(GTK_DIALOG(papersize_dialog), GTK_RESPONSE_OK);
1333 response = gtk_dialog_run(GTK_DIALOG(papersize_dialog));
1334 gtk_widget_destroy(papersize_dialog);
1335 if (response != GTK_RESPONSE_OK) return;
1337 pg = ui.cur_page;
1338 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
1339 if (ui.bg_apply_all_pages) pg = (struct Page *)pglist->data;
1340 prepare_new_undo();
1341 if (ui.bg_apply_all_pages) {
1342 if (pglist->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
1343 if (pglist->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
1345 undo->type = ITEM_PAPER_RESIZE;
1346 undo->page = pg;
1347 undo->val_x = pg->width;
1348 undo->val_y = pg->height;
1349 if (papersize_width_valid) pg->width = papersize_width;
1350 if (papersize_height_valid) pg->height = papersize_height;
1351 make_page_clipbox(pg);
1352 update_canvas_bg(pg);
1353 if (!ui.bg_apply_all_pages) break;
1355 do_switch_page(ui.pageno, TRUE, TRUE);
1359 void
1360 on_papercolorWhite_activate (GtkMenuItem *menuitem,
1361 gpointer user_data)
1363 end_text();
1364 reset_focus();
1365 process_papercolor_activate(menuitem, COLOR_WHITE);
1369 void
1370 on_papercolorYellow_activate (GtkMenuItem *menuitem,
1371 gpointer user_data)
1373 end_text();
1374 reset_focus();
1375 process_papercolor_activate(menuitem, COLOR_YELLOW);
1379 void
1380 on_papercolorPink_activate (GtkMenuItem *menuitem,
1381 gpointer user_data)
1383 end_text();
1384 reset_focus();
1385 process_papercolor_activate(menuitem, COLOR_RED);
1389 void
1390 on_papercolorOrange_activate (GtkMenuItem *menuitem,
1391 gpointer user_data)
1393 end_text();
1394 reset_focus();
1395 process_papercolor_activate(menuitem, COLOR_ORANGE);
1399 void
1400 on_papercolorBlue_activate (GtkMenuItem *menuitem,
1401 gpointer user_data)
1403 end_text();
1404 reset_focus();
1405 process_papercolor_activate(menuitem, COLOR_BLUE);
1409 void
1410 on_papercolorGreen_activate (GtkMenuItem *menuitem,
1411 gpointer user_data)
1413 end_text();
1414 reset_focus();
1415 process_papercolor_activate(menuitem, COLOR_GREEN);
1419 void
1420 on_papercolorOther_activate (GtkMenuItem *menuitem,
1421 gpointer user_data)
1427 void
1428 on_paperstylePlain_activate (GtkMenuItem *menuitem,
1429 gpointer user_data)
1431 end_text();
1432 reset_focus();
1433 process_paperstyle_activate(menuitem, RULING_NONE);
1437 void
1438 on_paperstyleLined_activate (GtkMenuItem *menuitem,
1439 gpointer user_data)
1441 end_text();
1442 reset_focus();
1443 process_paperstyle_activate(menuitem, RULING_LINED);
1447 void
1448 on_paperstyleRuled_activate (GtkMenuItem *menuitem,
1449 gpointer user_data)
1451 end_text();
1452 reset_focus();
1453 process_paperstyle_activate(menuitem, RULING_RULED);
1457 void
1458 on_paperstyleGraph_activate (GtkMenuItem *menuitem,
1459 gpointer user_data)
1461 end_text();
1462 reset_focus();
1463 process_paperstyle_activate(menuitem, RULING_GRAPH);
1467 void
1468 on_journalLoadBackground_activate (GtkMenuItem *menuitem,
1469 gpointer user_data)
1471 GtkWidget *dialog, *attach_opt;
1472 struct Background *bg;
1473 struct Page *pg;
1474 int pageno;
1475 GList *bglist, *bglistiter;
1476 GtkFileFilter *filt_all, *filt_pix, *filt_pspdf;
1477 char *filename;
1478 gboolean attach;
1480 end_text();
1481 reset_focus();
1482 dialog = gtk_file_chooser_dialog_new("Open Background", GTK_WINDOW (winMain),
1483 GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1484 GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
1486 filt_all = gtk_file_filter_new();
1487 gtk_file_filter_set_name(filt_all, "All files");
1488 gtk_file_filter_add_pattern(filt_all, "*");
1489 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_all);
1491 #if GTK_CHECK_VERSION(2,6,0)
1493 if (!gtk_check_version(2, 6, 0)) {
1494 filt_pix = gtk_file_filter_new();
1495 gtk_file_filter_set_name(filt_pix, "Bitmap files");
1496 gtk_file_filter_add_pixbuf_formats(filt_pix);
1497 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pix);
1500 #endif
1502 filt_pspdf = gtk_file_filter_new();
1503 gtk_file_filter_set_name(filt_pspdf, "PS/PDF files (as bitmaps)");
1504 gtk_file_filter_add_pattern(filt_pspdf, "*.ps");
1505 gtk_file_filter_add_pattern(filt_pspdf, "*.PS");
1506 gtk_file_filter_add_pattern(filt_pspdf, "*.pdf");
1507 gtk_file_filter_add_pattern(filt_pspdf, "*.PDF");
1508 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (dialog), filt_pspdf);
1510 attach_opt = gtk_check_button_new_with_label("Attach file to the journal");
1511 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(attach_opt), FALSE);
1512 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER (dialog), attach_opt);
1514 if (ui.default_path!=NULL) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (dialog), ui.default_path);
1516 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
1517 gtk_widget_destroy(dialog);
1518 return;
1520 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1521 attach = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(attach_opt));
1522 gtk_widget_destroy(dialog);
1524 set_cursor_busy(TRUE);
1525 bg = attempt_load_pix_bg(filename, attach);
1526 if (bg != NULL) bglist = g_list_append(NULL, bg);
1527 else bglist = attempt_load_gv_bg(filename);
1528 set_cursor_busy(FALSE);
1530 if (bglist == NULL) {
1531 dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL,
1532 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
1533 "Error opening background '%s'", filename);
1534 gtk_dialog_run(GTK_DIALOG(dialog));
1535 gtk_widget_destroy(dialog);
1536 g_free(filename);
1537 return;
1540 g_free(filename);
1541 reset_selection();
1542 pageno = ui.pageno;
1544 for (bglistiter = bglist, pageno = ui.pageno;
1545 bglistiter!=NULL; bglistiter = bglistiter->next, pageno++) {
1546 prepare_new_undo();
1547 if (bglistiter->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
1548 if (bglistiter->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
1550 bg = (struct Background *)bglistiter->data;
1552 if (pageno == journal.npages) {
1553 undo->type = ITEM_NEW_PAGE;
1554 pg = new_page_with_bg(bg,
1555 gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale,
1556 gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale);
1557 journal.pages = g_list_append(journal.pages, pg);
1558 journal.npages++;
1559 undo->val = pageno;
1560 undo->page = pg;
1561 } else
1563 pg = g_list_nth_data(journal.pages, pageno);
1564 undo->type = ITEM_NEW_BG_RESIZE;
1565 undo->page = pg;
1566 undo->bg = pg->bg;
1567 bg->canvas_item = undo->bg->canvas_item;
1568 undo->bg->canvas_item = NULL;
1569 undo->val_x = pg->width;
1570 undo->val_y = pg->height;
1571 pg->bg = bg;
1572 pg->width = gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale;
1573 pg->height = gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale;
1574 make_page_clipbox(pg);
1575 update_canvas_bg(pg);
1579 g_list_free(bglist);
1580 if (ui.zoom != DEFAULT_ZOOM) {
1581 ui.zoom = DEFAULT_ZOOM;
1582 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
1583 rescale_text_items();
1584 rescale_bg_pixmaps();
1586 do_switch_page(ui.pageno, TRUE, TRUE);
1589 void
1590 on_journalScreenshot_activate (GtkMenuItem *menuitem,
1591 gpointer user_data)
1593 struct Background *bg;
1595 end_text();
1596 reset_focus();
1597 reset_selection();
1598 gtk_window_iconify(GTK_WINDOW(winMain)); // hide ourselves
1599 gdk_display_sync(gdk_display_get_default());
1601 if (ui.cursor!=NULL)
1602 gdk_cursor_unref(ui.cursor);
1603 ui.cursor = gdk_cursor_new(GDK_TCROSS);
1605 bg = attempt_screenshot_bg();
1607 gtk_window_deiconify(GTK_WINDOW(winMain));
1608 update_cursor();
1609 if (bg==NULL) return;
1611 prepare_new_undo();
1612 undo->type = ITEM_NEW_BG_RESIZE;
1613 undo->page = ui.cur_page;
1614 undo->bg = ui.cur_page->bg;
1615 bg->canvas_item = undo->bg->canvas_item;
1616 undo->bg->canvas_item = NULL;
1617 undo->val_x = ui.cur_page->width;
1618 undo->val_y = ui.cur_page->height;
1620 ui.cur_page->bg = bg;
1621 ui.cur_page->width = gdk_pixbuf_get_width(bg->pixbuf)/bg->pixbuf_scale;
1622 ui.cur_page->height = gdk_pixbuf_get_height(bg->pixbuf)/bg->pixbuf_scale;
1624 make_page_clipbox(ui.cur_page);
1625 update_canvas_bg(ui.cur_page);
1627 if (ui.zoom != DEFAULT_ZOOM) {
1628 ui.zoom = DEFAULT_ZOOM;
1629 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
1630 rescale_text_items();
1631 rescale_bg_pixmaps();
1633 do_switch_page(ui.pageno, TRUE, TRUE);
1637 void
1638 on_journalApplyAllPages_activate (GtkMenuItem *menuitem,
1639 gpointer user_data)
1641 gboolean active;
1643 end_text();
1644 reset_focus();
1645 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
1646 if (active == ui.bg_apply_all_pages) return;
1647 ui.bg_apply_all_pages = active;
1648 update_page_stuff();
1650 /* THIS IS THE OLD VERSION OF THE FEATURE -- APPLIED CURRENT BG TO ALL
1651 struct Page *page;
1652 GList *pglist;
1654 if (ui.cur_page->bg->type != BG_SOLID) return;
1655 reset_selection();
1656 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
1657 page = (struct Page *)pglist->data;
1658 prepare_new_undo();
1659 undo->type = ITEM_NEW_BG_RESIZE;
1660 undo->page = page;
1661 undo->bg = page->bg;
1662 undo->val_x = page->width;
1663 undo->val_y = page->height;
1664 if (pglist->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
1665 if (pglist->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
1666 page->bg = (struct Background *)g_memdup(ui.cur_page->bg, sizeof(struct Background));
1667 page->width = ui.cur_page->width;
1668 page->height = ui.cur_page->height;
1669 page->bg->canvas_item = undo->bg->canvas_item;
1670 undo->bg->canvas_item = NULL;
1672 make_page_clipbox(page);
1673 update_canvas_bg(page);
1675 do_switch_page(ui.pageno, TRUE, TRUE);
1681 void
1682 on_toolsPen_activate (GtkMenuItem *menuitem,
1683 gpointer user_data)
1685 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1686 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1687 return;
1688 } else {
1689 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1690 return;
1693 if (ui.cur_mapping != 0) return;
1694 if (ui.toolno[0] == TOOL_PEN) return;
1696 end_text();
1697 reset_focus();
1698 reset_selection();
1699 ui.toolno[0] = TOOL_PEN;
1700 ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
1701 ui.cur_brush->ruler = FALSE;
1702 ui.cur_brush->recognizer = FALSE;
1703 update_mapping_linkings(TOOL_PEN);
1704 update_tool_buttons();
1705 update_tool_menu();
1706 update_color_menu();
1707 update_cursor();
1711 void
1712 on_toolsEraser_activate (GtkMenuItem *menuitem,
1713 gpointer user_data)
1715 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1716 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1717 return;
1718 } else {
1719 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1720 return;
1723 if (ui.cur_mapping != 0) return;
1724 if (ui.toolno[0] == TOOL_ERASER) return;
1726 end_text();
1727 reset_focus();
1728 reset_selection();
1729 ui.toolno[0] = TOOL_ERASER;
1730 ui.cur_brush = &(ui.brushes[0][TOOL_ERASER]);
1731 update_mapping_linkings(TOOL_ERASER);
1732 update_tool_buttons();
1733 update_tool_menu();
1734 update_color_menu();
1735 update_cursor();
1739 void
1740 on_toolsHighlighter_activate (GtkMenuItem *menuitem,
1741 gpointer user_data)
1743 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1744 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1745 return;
1746 } else {
1747 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1748 return;
1751 if (ui.cur_mapping != 0) return; // not user-generated
1752 if (ui.toolno[0] == TOOL_HIGHLIGHTER) return;
1754 end_text();
1755 reset_focus();
1756 reset_selection();
1757 ui.toolno[0] = TOOL_HIGHLIGHTER;
1758 ui.cur_brush = &(ui.brushes[0][TOOL_HIGHLIGHTER]);
1759 ui.cur_brush->ruler = FALSE;
1760 ui.cur_brush->recognizer = FALSE;
1761 update_mapping_linkings(TOOL_HIGHLIGHTER);
1762 update_tool_buttons();
1763 update_tool_menu();
1764 update_color_menu();
1765 update_cursor();
1769 void
1770 on_toolsText_activate (GtkMenuItem *menuitem,
1771 gpointer user_data)
1773 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1774 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1775 return;
1776 } else {
1777 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1778 return;
1781 if (ui.cur_mapping != 0) return; // not user-generated
1782 if (ui.toolno[0] == TOOL_TEXT) return;
1784 reset_focus();
1785 reset_selection();
1786 ui.toolno[0] = TOOL_TEXT;
1787 ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
1788 update_mapping_linkings(-1);
1789 update_tool_buttons();
1790 update_tool_menu();
1791 update_color_menu();
1792 update_cursor();
1796 void
1797 on_toolsSelectRegion_activate (GtkMenuItem *menuitem,
1798 gpointer user_data)
1804 void
1805 on_toolsSelectRectangle_activate (GtkMenuItem *menuitem,
1806 gpointer user_data)
1808 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1809 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1810 return;
1811 } else {
1812 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1813 return;
1816 if (ui.cur_mapping != 0) return; // not user-generated
1817 if (ui.toolno[0] == TOOL_SELECTRECT) return;
1819 end_text();
1820 reset_focus();
1821 ui.toolno[0] = TOOL_SELECTRECT;
1822 update_mapping_linkings(-1);
1823 update_tool_buttons();
1824 update_tool_menu();
1825 update_color_menu();
1826 update_cursor();
1830 void
1831 on_toolsVerticalSpace_activate (GtkMenuItem *menuitem,
1832 gpointer user_data)
1834 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1835 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1836 return;
1837 } else {
1838 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1839 return;
1842 if (ui.cur_mapping != 0) return; // not user-generated
1843 if (ui.toolno[0] == TOOL_VERTSPACE) return;
1845 end_text();
1846 reset_focus();
1847 reset_selection();
1848 ui.toolno[0] = TOOL_VERTSPACE;
1849 update_mapping_linkings(-1);
1850 update_tool_buttons();
1851 update_tool_menu();
1852 update_color_menu();
1853 update_cursor();
1857 void
1858 on_colorBlack_activate (GtkMenuItem *menuitem,
1859 gpointer user_data)
1861 process_color_activate(menuitem, COLOR_BLACK);
1865 void
1866 on_colorBlue_activate (GtkMenuItem *menuitem,
1867 gpointer user_data)
1869 process_color_activate(menuitem, COLOR_BLUE);
1874 void
1875 on_colorRed_activate (GtkMenuItem *menuitem,
1876 gpointer user_data)
1878 process_color_activate(menuitem, COLOR_RED);
1882 void
1883 on_colorGreen_activate (GtkMenuItem *menuitem,
1884 gpointer user_data)
1886 process_color_activate(menuitem, COLOR_GREEN);
1890 void
1891 on_colorGray_activate (GtkMenuItem *menuitem,
1892 gpointer user_data)
1894 process_color_activate(menuitem, COLOR_GRAY);
1898 void
1899 on_colorLightBlue_activate (GtkMenuItem *menuitem,
1900 gpointer user_data)
1902 process_color_activate(menuitem, COLOR_LIGHTBLUE);
1906 void
1907 on_colorLightGreen_activate (GtkMenuItem *menuitem,
1908 gpointer user_data)
1910 process_color_activate(menuitem, COLOR_LIGHTGREEN);
1914 void
1915 on_colorMagenta_activate (GtkMenuItem *menuitem,
1916 gpointer user_data)
1918 process_color_activate(menuitem, COLOR_MAGENTA);
1922 void
1923 on_colorOrange_activate (GtkMenuItem *menuitem,
1924 gpointer user_data)
1926 process_color_activate(menuitem, COLOR_ORANGE);
1930 void
1931 on_colorYellow_activate (GtkMenuItem *menuitem,
1932 gpointer user_data)
1934 process_color_activate(menuitem, COLOR_YELLOW);
1938 void
1939 on_colorWhite_activate (GtkMenuItem *menuitem,
1940 gpointer user_data)
1942 process_color_activate(menuitem, COLOR_WHITE);
1946 void
1947 on_colorOther_activate (GtkMenuItem *menuitem,
1948 gpointer user_data)
1954 void
1955 on_penthicknessVeryFine_activate (GtkMenuItem *menuitem,
1956 gpointer user_data)
1958 process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_VERYFINE);
1962 void
1963 on_penthicknessFine_activate (GtkMenuItem *menuitem,
1964 gpointer user_data)
1966 process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_FINE);
1970 void
1971 on_penthicknessMedium_activate (GtkMenuItem *menuitem,
1972 gpointer user_data)
1974 process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_MEDIUM);
1978 void
1979 on_penthicknessThick_activate (GtkMenuItem *menuitem,
1980 gpointer user_data)
1982 process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_THICK);
1986 void
1987 on_penthicknessVeryThick_activate (GtkMenuItem *menuitem,
1988 gpointer user_data)
1990 process_thickness_activate(menuitem, TOOL_PEN, THICKNESS_VERYTHICK);
1994 void
1995 on_eraserFine_activate (GtkMenuItem *menuitem,
1996 gpointer user_data)
1998 process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_FINE);
2002 void
2003 on_eraserMedium_activate (GtkMenuItem *menuitem,
2004 gpointer user_data)
2006 process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_MEDIUM);
2010 void
2011 on_eraserThick_activate (GtkMenuItem *menuitem,
2012 gpointer user_data)
2014 process_thickness_activate(menuitem, TOOL_ERASER, THICKNESS_THICK);
2018 void
2019 on_eraserStandard_activate (GtkMenuItem *menuitem,
2020 gpointer user_data)
2022 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
2023 end_text();
2024 reset_focus();
2025 ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_STANDARD;
2026 update_mapping_linkings(TOOL_ERASER);
2030 void
2031 on_eraserWhiteout_activate (GtkMenuItem *menuitem,
2032 gpointer user_data)
2034 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
2035 end_text();
2036 reset_focus();
2037 ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_WHITEOUT;
2038 update_mapping_linkings(TOOL_ERASER);
2042 void
2043 on_eraserDeleteStrokes_activate (GtkMenuItem *menuitem,
2044 gpointer user_data)
2046 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem))) return;
2047 end_text();
2048 reset_focus();
2049 ui.brushes[0][TOOL_ERASER].tool_options = TOOLOPT_ERASER_STROKES;
2050 update_mapping_linkings(TOOL_ERASER);
2054 void
2055 on_highlighterFine_activate (GtkMenuItem *menuitem,
2056 gpointer user_data)
2058 process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_FINE);
2062 void
2063 on_highlighterMedium_activate (GtkMenuItem *menuitem,
2064 gpointer user_data)
2066 process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_MEDIUM);
2070 void
2071 on_highlighterThick_activate (GtkMenuItem *menuitem,
2072 gpointer user_data)
2074 process_thickness_activate(menuitem, TOOL_HIGHLIGHTER, THICKNESS_THICK);
2078 void
2079 on_toolsTextFont_activate (GtkMenuItem *menuitem,
2080 gpointer user_data)
2082 GtkWidget *dialog;
2083 gchar *str;
2085 dialog = gtk_font_selection_dialog_new("Select Font");
2086 str = make_cur_font_name();
2087 gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dialog), str);
2088 g_free(str);
2089 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_OK) {
2090 gtk_widget_destroy(dialog);
2091 reset_focus();
2092 return;
2094 str = gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(dialog));
2095 gtk_widget_destroy(dialog);
2096 process_font_sel(str);
2099 void
2100 on_toolsDefaultPen_activate (GtkMenuItem *menuitem,
2101 gpointer user_data)
2103 switch_mapping(0);
2104 end_text();
2105 reset_focus();
2106 reset_selection();
2107 g_memmove(&(ui.brushes[0][TOOL_PEN]), ui.default_brushes+TOOL_PEN, sizeof(struct Brush));
2108 ui.toolno[0] = TOOL_PEN;
2109 ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
2110 update_mapping_linkings(TOOL_PEN);
2111 update_tool_buttons();
2112 update_tool_menu();
2113 update_pen_props_menu();
2114 update_color_menu();
2115 update_cursor();
2119 void
2120 on_toolsDefaultEraser_activate (GtkMenuItem *menuitem,
2121 gpointer user_data)
2123 switch_mapping(0);
2124 end_text();
2125 reset_focus();
2126 reset_selection();
2127 g_memmove(&(ui.brushes[0][TOOL_ERASER]), ui.default_brushes+TOOL_ERASER, sizeof(struct Brush));
2128 ui.toolno[0] = TOOL_ERASER;
2129 ui.cur_brush = &(ui.brushes[0][TOOL_ERASER]);
2130 update_mapping_linkings(TOOL_ERASER);
2131 update_tool_buttons();
2132 update_tool_menu();
2133 update_eraser_props_menu();
2134 update_color_menu();
2135 update_cursor();
2139 void
2140 on_toolsDefaultHighlighter_activate (GtkMenuItem *menuitem,
2141 gpointer user_data)
2143 switch_mapping(0);
2144 end_text();
2145 reset_focus();
2146 reset_selection();
2147 g_memmove(&(ui.brushes[0][TOOL_HIGHLIGHTER]), ui.default_brushes+TOOL_HIGHLIGHTER, sizeof(struct Brush));
2148 ui.toolno[0] = TOOL_HIGHLIGHTER;
2149 ui.cur_brush = &(ui.brushes[0][TOOL_HIGHLIGHTER]);
2150 update_mapping_linkings(TOOL_HIGHLIGHTER);
2151 update_tool_buttons();
2152 update_tool_menu();
2153 update_highlighter_props_menu();
2154 update_color_menu();
2155 update_cursor();
2158 void
2159 on_toolsDefaultText_activate (GtkMenuItem *menuitem,
2160 gpointer user_data)
2162 switch_mapping(0);
2163 if (ui.toolno[0]!=TOOL_TEXT) end_text();
2164 reset_focus();
2165 reset_selection();
2166 ui.toolno[0] = TOOL_TEXT;
2167 ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
2168 ui.cur_brush->color_no = ui.default_brushes[TOOL_PEN].color_no;
2169 ui.cur_brush->color_rgba = ui.default_brushes[TOOL_PEN].color_rgba;
2170 g_free(ui.font_name);
2171 ui.font_name = g_strdup(ui.default_font_name);
2172 ui.font_size = ui.default_font_size;
2173 if (ui.cur_item_type == ITEM_TEXT) {
2174 refont_text_item(ui.cur_item, ui.font_name, ui.font_size);
2176 update_font_button();
2177 update_mapping_linkings(-1);
2178 update_tool_buttons();
2179 update_tool_menu();
2180 update_color_menu();
2181 update_cursor();
2185 void
2186 on_toolsSetAsDefault_activate (GtkMenuItem *menuitem,
2187 gpointer user_data)
2189 struct Item *it;
2191 if (ui.cur_mapping!=0) return;
2192 if (ui.toolno[0] < NUM_STROKE_TOOLS)
2193 g_memmove(ui.default_brushes+ui.toolno[0], &(ui.brushes[0][ui.toolno[0]]), sizeof(struct Brush));
2194 if (ui.toolno[0] == TOOL_TEXT) {
2195 if (ui.cur_item_type == ITEM_TEXT) {
2196 g_free(ui.font_name);
2197 ui.font_name = g_strdup(ui.cur_item->font_name);
2198 ui.font_size = ui.cur_item->font_size;
2200 else if (ui.selection!=NULL && ui.selection->items!=NULL &&
2201 ui.selection->items->next==NULL &&
2202 (it=(struct Item*)ui.selection->items->data)->type == ITEM_TEXT) {
2203 g_free(ui.font_name);
2204 ui.font_name = g_strdup(it->font_name);
2205 ui.font_size = it->font_size;
2207 g_free(ui.default_font_name);
2208 ui.default_font_name = g_strdup(ui.font_name);
2209 ui.default_font_size = ui.font_size;
2211 end_text();
2212 reset_focus();
2216 void
2217 on_toolsRuler_activate (GtkMenuItem *menuitem,
2218 gpointer user_data)
2220 gboolean active, current;
2222 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
2223 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2224 else
2225 active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
2227 if (ui.cur_mapping != 0) return;
2228 current = (ui.toolno[0] == TOOL_PEN || ui.toolno[0] == TOOL_HIGHLIGHTER) && ui.cur_brush->ruler;
2229 if (active == current) return;
2231 end_text();
2232 reset_focus();
2233 if (ui.toolno[0]!=TOOL_PEN && ui.toolno[0]!=TOOL_HIGHLIGHTER) {
2234 reset_selection();
2235 ui.toolno[0] = TOOL_PEN;
2236 ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
2237 update_color_menu();
2238 update_tool_buttons();
2239 update_tool_menu();
2240 update_cursor();
2243 ui.cur_brush->ruler = active;
2244 if (active) ui.cur_brush->recognizer = FALSE;
2245 update_mapping_linkings(ui.toolno[0]);
2246 update_ruler_indicator();
2250 void
2251 on_toolsReco_activate (GtkMenuItem *menuitem,
2252 gpointer user_data)
2254 gboolean active, current;
2256 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
2257 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2258 else
2259 active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
2261 if (ui.cur_mapping != 0) return;
2262 current = (ui.toolno[0] == TOOL_PEN || ui.toolno[0] == TOOL_HIGHLIGHTER) && ui.cur_brush->recognizer;
2263 if (active == current) return;
2265 end_text();
2266 reset_focus();
2267 if (ui.toolno[0]!=TOOL_PEN && ui.toolno[0]!=TOOL_HIGHLIGHTER) {
2268 reset_selection();
2269 ui.toolno[0] = TOOL_PEN;
2270 ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
2271 update_color_menu();
2272 update_tool_buttons();
2273 update_tool_menu();
2274 update_cursor();
2277 ui.cur_brush->recognizer = active;
2278 if (active) {
2279 ui.cur_brush->ruler = FALSE;
2280 reset_recognizer();
2282 update_mapping_linkings(ui.toolno[0]);
2283 update_ruler_indicator();
2287 void
2288 on_optionsSavePreferences_activate (GtkMenuItem *menuitem,
2289 gpointer user_data)
2291 end_text();
2292 reset_focus();
2293 save_config_to_file();
2297 void
2298 on_helpIndex_activate (GtkMenuItem *menuitem,
2299 gpointer user_data)
2305 void
2306 on_helpAbout_activate (GtkMenuItem *menuitem,
2307 gpointer user_data)
2309 GtkWidget *aboutDialog;
2310 GtkLabel *labelTitle;
2312 end_text();
2313 reset_focus();
2314 aboutDialog = create_aboutDialog ();
2315 labelTitle = GTK_LABEL(g_object_get_data(G_OBJECT(aboutDialog), "labelTitle"));
2316 gtk_label_set_markup(labelTitle,
2317 "<span size=\"xx-large\" weight=\"bold\">Xournal " VERSION "</span>");
2318 gtk_dialog_run (GTK_DIALOG(aboutDialog));
2319 gtk_widget_destroy(aboutDialog);
2323 void
2324 on_buttonToolDefault_clicked (GtkToolButton *toolbutton,
2325 gpointer user_data)
2327 if (ui.toolno[0]==TOOL_TEXT) {
2328 on_toolsDefaultText_activate(NULL, NULL);
2329 return;
2331 end_text();
2332 reset_focus();
2333 switch_mapping(0);
2334 if (ui.toolno[0] < NUM_STROKE_TOOLS) {
2335 g_memmove(&(ui.brushes[0][ui.toolno[0]]), ui.default_brushes+ui.toolno[0], sizeof(struct Brush));
2336 update_mapping_linkings(ui.toolno[0]);
2337 update_thickness_buttons();
2338 update_color_buttons();
2339 update_color_menu();
2340 if (ui.toolno[0] == TOOL_PEN) update_pen_props_menu();
2341 if (ui.toolno[0] == TOOL_ERASER) update_eraser_props_menu();
2342 if (ui.toolno[0] == TOOL_HIGHLIGHTER) update_highlighter_props_menu();
2343 update_cursor();
2348 void
2349 on_buttonFine_clicked (GtkToolButton *toolbutton,
2350 gpointer user_data)
2352 if (ui.cur_mapping != 0) return;
2353 process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[0], THICKNESS_FINE);
2357 void
2358 on_buttonMedium_clicked (GtkToolButton *toolbutton,
2359 gpointer user_data)
2361 if (ui.cur_mapping != 0) return;
2362 process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[0], THICKNESS_MEDIUM);
2366 void
2367 on_buttonThick_clicked (GtkToolButton *toolbutton,
2368 gpointer user_data)
2370 if (ui.cur_mapping != 0) return;
2371 process_thickness_activate((GtkMenuItem*)toolbutton, ui.toolno[0], THICKNESS_THICK);
2375 gboolean
2376 on_canvas_button_press_event (GtkWidget *widget,
2377 GdkEventButton *event,
2378 gpointer user_data)
2380 double pt[2];
2381 gboolean page_change;
2382 struct Page *tmppage;
2383 GtkWidget *dialog;
2384 int mapping;
2385 gboolean is_core;
2386 struct Item *item;
2388 is_core = (event->device == gdk_device_get_core_pointer());
2389 if (!ui.use_xinput && !is_core) return FALSE;
2390 if (ui.use_xinput && is_core && ui.discard_corepointer) return FALSE;
2391 if (event->button > 3) return FALSE; // no painting with the mouse wheel!
2392 if (event->type != GDK_BUTTON_PRESS) return FALSE;
2393 // double-clicks may have broken axes member (free'd) due to a bug in GDK
2394 if (!is_core) {
2395 // re-get the axis values since Synaptics sends bogus ones
2396 gdk_device_get_state(event->device, event->window, event->axes, NULL);
2397 fix_xinput_coords((GdkEvent *)event);
2399 #ifdef INPUT_DEBUG
2400 printf("DEBUG: ButtonDown (%s) (x,y)=(%.2f,%.2f)\n",
2401 is_core?"core":"xinput", event->x, event->y);
2402 #endif
2403 if (!finite(event->x) || !finite(event->y)) return FALSE; // Xorg 7.3 bug
2405 if (ui.cur_item_type == ITEM_TEXT && !is_event_within_textview(event))
2406 end_text();
2407 if (ui.cur_item_type == ITEM_STROKE && ui.is_corestroke && !is_core &&
2408 ui.cur_path.num_points == 1) {
2409 // Xorg 7.3+ sent core event before XInput event: fix initial point
2410 ui.is_corestroke = FALSE;
2411 get_pointer_coords((GdkEvent *)event, ui.cur_path.coords);
2413 if (ui.cur_item_type != ITEM_NONE) return FALSE; // we're already doing something
2415 ui.is_corestroke = is_core;
2417 if (ui.use_erasertip && event->device->source == GDK_SOURCE_ERASER)
2418 mapping = NUM_BUTTONS;
2419 else mapping = event->button-1;
2421 // check whether we're in a page
2422 page_change = FALSE;
2423 tmppage = ui.cur_page;
2424 get_pointer_coords((GdkEvent *)event, pt);
2425 while (ui.view_continuous && (pt[1] < - VIEW_CONTINUOUS_SKIP)) {
2426 if (ui.pageno == 0) break;
2427 page_change = TRUE;
2428 ui.pageno--;
2429 tmppage = g_list_nth_data(journal.pages, ui.pageno);
2430 pt[1] += tmppage->height + VIEW_CONTINUOUS_SKIP;
2432 while (ui.view_continuous && (pt[1] > tmppage->height + VIEW_CONTINUOUS_SKIP)) {
2433 if (ui.pageno == journal.npages-1) break;
2434 pt[1] -= tmppage->height + VIEW_CONTINUOUS_SKIP;
2435 page_change = TRUE;
2436 ui.pageno++;
2437 tmppage = g_list_nth_data(journal.pages, ui.pageno);
2439 if (page_change) do_switch_page(ui.pageno, FALSE, FALSE);
2441 // can't paint on the background...
2443 if (ui.cur_layer == NULL) {
2444 /* warn */
2445 dialog = gtk_message_dialog_new(GTK_WINDOW(winMain), GTK_DIALOG_MODAL,
2446 GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "Drawing is not allowed on the "
2447 "background layer.\n Switching to Layer 1.");
2448 gtk_dialog_run(GTK_DIALOG(dialog));
2449 gtk_widget_destroy(dialog);
2450 on_viewShowLayer_activate(NULL, NULL);
2451 return FALSE;
2454 // switch mappings if needed
2456 ui.which_mouse_button = event->button;
2457 switch_mapping(mapping);
2459 // in text tool, clicking in a text area edits it
2460 if (ui.toolno[mapping] == TOOL_TEXT) {
2461 item = click_is_in_text(ui.cur_layer, pt[0], pt[1]);
2462 if (item!=NULL) {
2463 reset_selection();
2464 start_text((GdkEvent *)event, item);
2465 return FALSE;
2469 // if this can be a selection move or resize, then it takes precedence over anything else
2470 if (start_resizesel((GdkEvent *)event)) return FALSE;
2471 if (start_movesel((GdkEvent *)event)) return FALSE;
2473 if (ui.toolno[mapping] != TOOL_SELECTREGION && ui.toolno[mapping] != TOOL_SELECTRECT)
2474 reset_selection();
2476 // process the event
2478 if (ui.toolno[mapping] == TOOL_HAND) {
2479 ui.cur_item_type = ITEM_HAND;
2480 get_pointer_coords((GdkEvent *)event, ui.hand_refpt);
2481 ui.hand_refpt[0] += ui.cur_page->hoffset;
2482 ui.hand_refpt[1] += ui.cur_page->voffset;
2484 else if (ui.toolno[mapping] == TOOL_PEN || ui.toolno[mapping] == TOOL_HIGHLIGHTER ||
2485 (ui.toolno[mapping] == TOOL_ERASER && ui.cur_brush->tool_options == TOOLOPT_ERASER_WHITEOUT)) {
2486 create_new_stroke((GdkEvent *)event);
2488 else if (ui.toolno[mapping] == TOOL_ERASER) {
2489 ui.cur_item_type = ITEM_ERASURE;
2490 do_eraser((GdkEvent *)event, ui.cur_brush->thickness/2,
2491 ui.cur_brush->tool_options == TOOLOPT_ERASER_STROKES);
2493 else if (ui.toolno[mapping] == TOOL_SELECTRECT) {
2494 start_selectrect((GdkEvent *)event);
2496 else if (ui.toolno[mapping] == TOOL_VERTSPACE) {
2497 start_vertspace((GdkEvent *)event);
2499 else if (ui.toolno[mapping] == TOOL_TEXT) {
2500 start_text((GdkEvent *)event, NULL);
2502 return FALSE;
2506 gboolean
2507 on_canvas_button_release_event (GtkWidget *widget,
2508 GdkEventButton *event,
2509 gpointer user_data)
2511 gboolean is_core;
2513 if (ui.cur_item_type == ITEM_NONE) return FALSE; // not doing anything
2515 if (event->button != ui.which_mouse_button) return FALSE; // ignore
2517 is_core = (event->device == gdk_device_get_core_pointer());
2518 if (!ui.use_xinput && !is_core) return FALSE;
2519 if (ui.use_xinput && is_core && !ui.is_corestroke) return FALSE;
2520 if (!is_core) fix_xinput_coords((GdkEvent *)event);
2522 if (ui.cur_item_type == ITEM_STROKE) {
2523 finalize_stroke();
2524 if (ui.cur_brush->recognizer) recognize_patterns();
2526 else if (ui.cur_item_type == ITEM_ERASURE) {
2527 finalize_erasure();
2529 else if (ui.cur_item_type == ITEM_SELECTRECT) {
2530 finalize_selectrect();
2532 else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2533 finalize_movesel();
2535 else if (ui.cur_item_type == ITEM_RESIZESEL) {
2536 finalize_resizesel();
2538 else if (ui.cur_item_type == ITEM_HAND) {
2539 ui.cur_item_type = ITEM_NONE;
2542 switch_mapping(0);
2543 return FALSE;
2547 gboolean
2548 on_canvas_enter_notify_event (GtkWidget *widget,
2549 GdkEventCrossing *event,
2550 gpointer user_data)
2553 return FALSE;
2557 gboolean
2558 on_canvas_expose_event (GtkWidget *widget,
2559 GdkEventExpose *event,
2560 gpointer user_data)
2562 if (ui.view_continuous && ui.progressive_bg) rescale_bg_pixmaps();
2563 return FALSE;
2567 gboolean
2568 on_canvas_key_press_event (GtkWidget *widget,
2569 GdkEventKey *event,
2570 gpointer user_data)
2572 // If zoomed-out and in single page mode, switch pages with PgUp/PgDn.
2573 if (!ui.view_continuous &&
2574 (0.96 * ui.zoom * ui.cur_page->height <
2575 GTK_WIDGET(canvas)->allocation.height)) {
2576 if (event->keyval == GDK_Page_Down) {
2577 end_text();
2578 reset_focus();
2579 if (ui.pageno == journal.npages-1) { return FALSE; }
2580 do_switch_page(ui.pageno+1, TRUE, FALSE);
2582 if (event->keyval == GDK_Page_Up) {
2583 end_text();
2584 reset_focus();
2585 if (ui.pageno == 0) { return FALSE; }
2586 do_switch_page(ui.pageno-1, TRUE, FALSE);
2590 return FALSE;
2594 gboolean
2595 on_canvas_motion_notify_event (GtkWidget *widget,
2596 GdkEventMotion *event,
2597 gpointer user_data)
2599 gboolean looks_wrong, is_core;
2600 double pt[2];
2602 /* we don't care about this event unless some operation is in progress;
2603 or if there's a selection (then we might want to change the mouse
2604 cursor to indicate the possibility of resizing) */
2605 if (ui.cur_item_type == ITEM_NONE && ui.selection==NULL) return FALSE;
2607 is_core = (event->device == gdk_device_get_core_pointer());
2608 if (!ui.use_xinput && !is_core) return FALSE;
2609 if (!is_core) fix_xinput_coords((GdkEvent *)event);
2610 if (!finite(event->x) || !finite(event->y)) return FALSE; // Xorg 7.3 bug
2612 if (ui.selection!=NULL && ui.cur_item_type == ITEM_NONE) {
2613 get_pointer_coords((GdkEvent *)event, pt);
2614 update_cursor_for_resize(pt);
2615 return FALSE;
2618 if (ui.use_xinput && is_core && !ui.is_corestroke) return FALSE;
2619 if (!is_core) ui.is_corestroke = FALSE;
2621 #ifdef INPUT_DEBUG
2622 printf("DEBUG: MotionNotify (%s) (x,y)=(%.2f,%.2f)\n",
2623 is_core?"core":"xinput", event->x, event->y);
2624 #endif
2626 looks_wrong = !(event->state & (1<<(7+ui.which_mouse_button)));
2628 if (looks_wrong) { /* mouse button shouldn't be up... give up */
2629 if (ui.cur_item_type == ITEM_STROKE) {
2630 finalize_stroke();
2631 if (ui.cur_brush->recognizer) recognize_patterns();
2633 else if (ui.cur_item_type == ITEM_ERASURE) {
2634 finalize_erasure();
2636 else if (ui.cur_item_type == ITEM_SELECTRECT) {
2637 finalize_selectrect();
2639 else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2640 finalize_movesel();
2642 else if (ui.cur_item_type == ITEM_RESIZESEL) {
2643 finalize_resizesel();
2645 switch_mapping(0);
2646 return FALSE;
2649 if (ui.cur_item_type == ITEM_STROKE) {
2650 continue_stroke((GdkEvent *)event);
2652 else if (ui.cur_item_type == ITEM_ERASURE) {
2653 do_eraser((GdkEvent *)event, ui.cur_brush->thickness/2,
2654 ui.cur_brush->tool_options == TOOLOPT_ERASER_STROKES);
2656 else if (ui.cur_item_type == ITEM_SELECTRECT) {
2657 get_pointer_coords((GdkEvent *)event, pt);
2658 ui.selection->bbox.right = pt[0];
2659 ui.selection->bbox.bottom = pt[1];
2660 gnome_canvas_item_set(ui.selection->canvas_item,
2661 "x2", pt[0], "y2", pt[1], NULL);
2663 else if (ui.cur_item_type == ITEM_MOVESEL || ui.cur_item_type == ITEM_MOVESEL_VERT) {
2664 continue_movesel((GdkEvent *)event);
2666 else if (ui.cur_item_type == ITEM_RESIZESEL) {
2667 continue_resizesel((GdkEvent *)event);
2669 else if (ui.cur_item_type == ITEM_HAND) {
2670 do_hand((GdkEvent *)event);
2673 return FALSE;
2676 void
2677 on_comboLayer_changed (GtkComboBox *combobox,
2678 gpointer user_data)
2680 int val;
2682 if (ui.in_update_page_stuff) return; // avoid a bad retroaction
2684 end_text();
2685 reset_focus();
2687 val = gtk_combo_box_get_active(combobox);
2688 if (val == -1) return;
2689 val = ui.cur_page->nlayers-1-val;
2690 if (val == ui.layerno) return;
2692 reset_selection();
2693 while (val>ui.layerno) {
2694 ui.layerno++;
2695 ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
2696 gnome_canvas_item_show(GNOME_CANVAS_ITEM(ui.cur_layer->group));
2698 while (val<ui.layerno) {
2699 gnome_canvas_item_hide(GNOME_CANVAS_ITEM(ui.cur_layer->group));
2700 ui.layerno--;
2701 if (ui.layerno<0) ui.cur_layer = NULL;
2702 else ui.cur_layer = g_list_nth_data(ui.cur_page->layers, ui.layerno);
2704 update_page_stuff();
2708 gboolean
2709 on_winMain_delete_event (GtkWidget *widget,
2710 GdkEvent *event,
2711 gpointer user_data)
2713 end_text();
2714 reset_focus();
2715 if (ok_to_close()) gtk_main_quit();
2716 return TRUE;
2720 void
2721 on_optionsUseXInput_activate (GtkMenuItem *menuitem,
2722 gpointer user_data)
2724 end_text();
2725 reset_focus();
2726 ui.allow_xinput = ui.use_xinput =
2727 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2729 /* Important note: we'd like ONLY the canvas window itself to receive
2730 XInput events, while its child window in the GDK hierarchy (also
2731 associated to the canvas widget) receives the core events.
2732 This way on_canvas_... will get both types of events -- otherwise,
2733 the proximity detection code in GDK is broken and we'll lose core
2734 events.
2736 Up to GTK+ 2.10, gtk_widget_set_extension_events() only sets
2737 extension events for the widget's main window itself; in GTK+ 2.11
2738 also traverses GDK child windows that belong to the widget
2739 and sets their extension events too. We want to avoid that.
2740 So we use gdk_input_set_extension_events() directly on the canvas.
2743 /* // this causes GTK+ 2.11 bugs
2744 gtk_widget_set_extension_events(GTK_WIDGET (canvas),
2745 ui.use_xinput?GDK_EXTENSION_EVENTS_ALL:GDK_EXTENSION_EVENTS_NONE);
2747 gdk_input_set_extension_events(GTK_WIDGET(canvas)->window,
2748 GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK,
2749 ui.use_xinput?GDK_EXTENSION_EVENTS_ALL:GDK_EXTENSION_EVENTS_NONE);
2751 update_mappings_menu();
2754 void
2755 on_vscroll_changed (GtkAdjustment *adjustment,
2756 gpointer user_data)
2758 gboolean need_update;
2759 double viewport_top, viewport_bottom;
2760 struct Page *tmppage;
2762 if (!ui.view_continuous) return;
2764 if (ui.progressive_bg) rescale_bg_pixmaps();
2765 need_update = FALSE;
2766 viewport_top = adjustment->value / ui.zoom;
2767 viewport_bottom = (adjustment->value + adjustment->page_size) / ui.zoom;
2768 tmppage = ui.cur_page;
2769 while (viewport_top > tmppage->voffset + tmppage->height) {
2770 if (ui.pageno == journal.npages-1) break;
2771 need_update = TRUE;
2772 ui.pageno++;
2773 tmppage = g_list_nth_data(journal.pages, ui.pageno);
2775 while (viewport_bottom < tmppage->voffset) {
2776 if (ui.pageno == 0) break;
2777 need_update = TRUE;
2778 ui.pageno--;
2779 tmppage = g_list_nth_data(journal.pages, ui.pageno);
2781 if (need_update) {
2782 end_text();
2783 do_switch_page(ui.pageno, FALSE, FALSE);
2785 reset_focus();
2786 return;
2789 void
2790 on_spinPageNo_value_changed (GtkSpinButton *spinbutton,
2791 gpointer user_data)
2793 int val;
2795 if (ui.in_update_page_stuff) return; // avoid a bad retroaction
2797 end_text();
2798 reset_focus();
2800 val = gtk_spin_button_get_value_as_int(spinbutton) - 1;
2802 if (val == journal.npages) { // create a page at end
2803 if (page_ops_forbidden()) return;
2804 on_journalNewPageEnd_activate(NULL, NULL);
2805 return;
2808 if (val == ui.pageno) return;
2809 if (val < 0) val = 0;
2810 if (val > journal.npages-1) val = journal.npages-1;
2811 do_switch_page(val, TRUE, FALSE);
2815 void
2816 on_journalDefaultBackground_activate (GtkMenuItem *menuitem,
2817 gpointer user_data)
2819 struct Page *pg;
2820 GList *pglist;
2822 end_text();
2823 reset_focus();
2824 reset_selection();
2826 pg = ui.cur_page;
2827 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
2828 if (ui.bg_apply_all_pages) pg = (struct Page *)pglist->data;
2829 prepare_new_undo();
2830 if (ui.bg_apply_all_pages) {
2831 if (pglist->next!=NULL) undo->multiop |= MULTIOP_CONT_REDO;
2832 if (pglist->prev!=NULL) undo->multiop |= MULTIOP_CONT_UNDO;
2834 undo->type = ITEM_NEW_BG_RESIZE;
2835 undo->page = pg;
2836 undo->bg = pg->bg;
2837 undo->val_x = pg->width;
2838 undo->val_y = pg->height;
2839 pg->bg = (struct Background *)g_memdup(ui.default_page.bg, sizeof(struct Background));
2840 pg->width = ui.default_page.width;
2841 pg->height = ui.default_page.height;
2842 pg->bg->canvas_item = undo->bg->canvas_item;
2843 undo->bg->canvas_item = NULL;
2845 make_page_clipbox(pg);
2846 update_canvas_bg(pg);
2847 if (!ui.bg_apply_all_pages) break;
2849 do_switch_page(ui.pageno, TRUE, TRUE);
2853 void
2854 on_journalSetAsDefault_activate (GtkMenuItem *menuitem,
2855 gpointer user_data)
2857 if (ui.cur_page->bg->type != BG_SOLID) return;
2859 end_text();
2860 reset_focus();
2861 prepare_new_undo();
2862 undo->type = ITEM_NEW_DEFAULT_BG;
2863 undo->val_x = ui.default_page.width;
2864 undo->val_y = ui.default_page.height;
2865 undo->bg = ui.default_page.bg;
2867 ui.default_page.width = ui.cur_page->width;
2868 ui.default_page.height = ui.cur_page->height;
2869 ui.default_page.bg = (struct Background *)g_memdup(ui.cur_page->bg, sizeof(struct Background));
2870 ui.default_page.bg->canvas_item = NULL;
2874 void
2875 on_comboStdSizes_changed (GtkComboBox *combobox,
2876 gpointer user_data)
2878 GtkEntry *entry;
2879 GtkComboBox *comboUnit;
2880 int val;
2881 gchar text[20];
2883 if (papersize_need_init) {
2884 gtk_combo_box_set_active(combobox, papersize_std);
2885 papersize_need_init = FALSE;
2886 } else {
2887 val = gtk_combo_box_get_active(combobox);
2888 if (val == -1 || val == papersize_std) return;
2889 papersize_std = val;
2890 if (val == STD_SIZE_CUSTOM) return;
2891 papersize_unit = std_units[val];
2892 papersize_width = std_widths[val];
2893 papersize_height = std_heights[val];
2895 comboUnit = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboUnit"));
2896 gtk_combo_box_set_active(comboUnit, papersize_unit);
2897 entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryWidth"));
2898 g_snprintf(text, 20, "%.2f", papersize_width/unit_sizes[papersize_unit]);
2899 if (g_str_has_suffix(text, ".00"))
2900 g_snprintf(text, 20, "%d", (int) (papersize_width/unit_sizes[papersize_unit]));
2901 gtk_entry_set_text(entry, text);
2902 entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryHeight"));
2903 g_snprintf(text, 20, "%.2f", papersize_height/unit_sizes[papersize_unit]);
2904 if (g_str_has_suffix(text, ".00"))
2905 g_snprintf(text, 20, "%d", (int) (papersize_height/unit_sizes[papersize_unit]));
2906 gtk_entry_set_text(entry, text);
2910 void
2911 on_entryWidth_changed (GtkEditable *editable,
2912 gpointer user_data)
2914 double val;
2915 const gchar *text;
2916 gchar *ptr;
2917 GtkComboBox *comboStdSizes;
2919 text = gtk_entry_get_text(GTK_ENTRY(editable));
2920 val = strtod(text, &ptr);
2921 papersize_width_valid = (*ptr == 0 && val > 0.);
2922 if (!papersize_width_valid) return; // invalid entry
2923 val *= unit_sizes[papersize_unit];
2924 if (fabs(val - papersize_width) < 0.1) return; // no change
2925 papersize_std = STD_SIZE_CUSTOM;
2926 papersize_width = val;
2927 comboStdSizes = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboStdSizes"));
2928 gtk_combo_box_set_active(comboStdSizes, papersize_std);
2932 void
2933 on_entryHeight_changed (GtkEditable *editable,
2934 gpointer user_data)
2936 double val;
2937 const gchar *text;
2938 gchar *ptr;
2939 GtkComboBox *comboStdSizes;
2941 text = gtk_entry_get_text(GTK_ENTRY(editable));
2942 val = strtod(text, &ptr);
2943 papersize_height_valid = (*ptr == 0 && val > 0.);
2944 if (!papersize_height_valid) return; // invalid entry
2945 val *= unit_sizes[papersize_unit];
2946 if (fabs(val - papersize_height) < 0.1) return; // no change
2947 papersize_std = STD_SIZE_CUSTOM;
2948 papersize_height = val;
2949 comboStdSizes = GTK_COMBO_BOX(g_object_get_data(G_OBJECT(papersize_dialog), "comboStdSizes"));
2950 gtk_combo_box_set_active(comboStdSizes, papersize_std);
2954 void
2955 on_comboUnit_changed (GtkComboBox *combobox,
2956 gpointer user_data)
2958 GtkEntry *entry;
2959 int val;
2960 gchar text[20];
2962 val = gtk_combo_box_get_active(combobox);
2963 if (val == -1 || val == papersize_unit) return;
2964 papersize_unit = val;
2965 entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryWidth"));
2966 if (papersize_width_valid) {
2967 g_snprintf(text, 20, "%.2f", papersize_width/unit_sizes[papersize_unit]);
2968 if (g_str_has_suffix(text, ".00"))
2969 g_snprintf(text, 20, "%d", (int) (papersize_width/unit_sizes[papersize_unit]));
2970 } else *text = 0;
2971 gtk_entry_set_text(entry, text);
2972 if (papersize_height_valid) {
2973 entry = GTK_ENTRY(g_object_get_data(G_OBJECT(papersize_dialog), "entryHeight"));
2974 g_snprintf(text, 20, "%.2f", papersize_height/unit_sizes[papersize_unit]);
2975 if (g_str_has_suffix(text, ".00"))
2976 g_snprintf(text, 20, "%d", (int) (papersize_height/unit_sizes[papersize_unit]));
2977 } else *text = 0;
2978 gtk_entry_set_text(entry, text);
2982 void
2983 on_viewFullscreen_activate (GtkMenuItem *menuitem,
2984 gpointer user_data)
2986 gboolean active;
2988 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_CHECK_MENU_ITEM)
2989 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
2990 else
2991 active = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem));
2993 if (active == ui.fullscreen) return;
2994 end_text();
2995 reset_focus();
2996 ui.fullscreen = active;
2997 gtk_check_menu_item_set_active(
2998 GTK_CHECK_MENU_ITEM(GET_COMPONENT("viewFullscreen")), ui.fullscreen);
2999 gtk_toggle_tool_button_set_active(
3000 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonFullscreen")), ui.fullscreen);
3002 if (ui.fullscreen) gtk_window_fullscreen(GTK_WINDOW(winMain));
3003 else gtk_window_unfullscreen(GTK_WINDOW(winMain));
3005 update_vbox_order(ui.vertical_order[ui.fullscreen?1:0]);
3009 void
3010 on_optionsButtonMappings_activate (GtkMenuItem *menuitem,
3011 gpointer user_data)
3013 end_text();
3014 reset_focus();
3015 ui.use_erasertip =
3016 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3017 update_mappings_menu();
3021 void
3022 on_optionsAntialiasBG_activate (GtkMenuItem *menuitem,
3023 gpointer user_data)
3025 gboolean active;
3027 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3028 if (ui.antialias_bg == active) return;
3029 end_text();
3030 reset_focus();
3031 ui.antialias_bg = active;
3032 rescale_bg_pixmaps();
3036 void
3037 on_optionsProgressiveBG_activate (GtkMenuItem *menuitem,
3038 gpointer user_data)
3040 gboolean active;
3042 active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3043 if (ui.progressive_bg == active) return;
3044 end_text();
3045 reset_focus();
3046 ui.progressive_bg = active;
3047 if (!ui.progressive_bg) rescale_bg_pixmaps();
3051 void
3052 on_mru_activate (GtkMenuItem *menuitem,
3053 gpointer user_data)
3055 int which;
3056 gboolean success;
3057 GtkWidget *dialog;
3059 end_text();
3060 reset_focus();
3061 if (!ok_to_close()) return; // user aborted on save confirmation
3063 for (which = 0 ; which < MRU_SIZE; which++) {
3064 if (ui.mrumenu[which] == GTK_WIDGET(menuitem)) break;
3066 if (which == MRU_SIZE || ui.mru[which] == NULL) return; // not found...
3068 set_cursor_busy(TRUE);
3069 success = open_journal(ui.mru[which]);
3070 set_cursor_busy(FALSE);
3071 if (success) return;
3073 /* open failed */
3074 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
3075 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Error opening file '%s'", ui.mru[which]);
3076 gtk_dialog_run(GTK_DIALOG(dialog));
3077 gtk_widget_destroy(dialog);
3078 delete_mru_entry(which);
3082 void
3083 on_button2Pen_activate (GtkMenuItem *menuitem,
3084 gpointer user_data)
3086 process_mapping_activate(menuitem, 1, TOOL_PEN);
3090 void
3091 on_button2Eraser_activate (GtkMenuItem *menuitem,
3092 gpointer user_data)
3094 process_mapping_activate(menuitem, 1, TOOL_ERASER);
3098 void
3099 on_button2Highlighter_activate (GtkMenuItem *menuitem,
3100 gpointer user_data)
3102 process_mapping_activate(menuitem, 1, TOOL_HIGHLIGHTER);
3106 void
3107 on_button2Text_activate (GtkMenuItem *menuitem,
3108 gpointer user_data)
3110 process_mapping_activate(menuitem, 1, TOOL_TEXT);
3114 void
3115 on_button2SelectRegion_activate (GtkMenuItem *menuitem,
3116 gpointer user_data)
3118 process_mapping_activate(menuitem, 1, TOOL_SELECTREGION);
3122 void
3123 on_button2SelectRectangle_activate (GtkMenuItem *menuitem,
3124 gpointer user_data)
3126 process_mapping_activate(menuitem, 1, TOOL_SELECTRECT);
3130 void
3131 on_button2VerticalSpace_activate (GtkMenuItem *menuitem,
3132 gpointer user_data)
3134 process_mapping_activate(menuitem, 1, TOOL_VERTSPACE);
3138 void
3139 on_button2LinkBrush_activate (GtkMenuItem *menuitem,
3140 gpointer user_data)
3142 int i;
3144 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3145 end_text();
3146 reset_focus();
3147 ui.linked_brush[1] = BRUSH_LINKED;
3148 for (i=0;i<NUM_STROKE_TOOLS;i++) update_mapping_linkings(i);
3152 void
3153 on_button2CopyBrush_activate (GtkMenuItem *menuitem,
3154 gpointer user_data)
3156 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3157 end_text();
3158 reset_focus();
3159 if (ui.toolno[1] >= NUM_STROKE_TOOLS) {
3160 ui.linked_brush[1] = BRUSH_STATIC;
3161 update_mappings_menu_linkings();
3162 return;
3164 ui.linked_brush[1] = BRUSH_COPIED;
3165 g_memmove(&(ui.brushes[1][ui.toolno[1]]), &(ui.brushes[0][ui.toolno[1]]), sizeof(struct Brush));
3169 void
3170 on_button3Pen_activate (GtkMenuItem *menuitem,
3171 gpointer user_data)
3173 process_mapping_activate(menuitem, 2, TOOL_PEN);
3177 void
3178 on_button3Eraser_activate (GtkMenuItem *menuitem,
3179 gpointer user_data)
3181 process_mapping_activate(menuitem, 2, TOOL_ERASER);
3185 void
3186 on_button3Highlighter_activate (GtkMenuItem *menuitem,
3187 gpointer user_data)
3189 process_mapping_activate(menuitem, 2, TOOL_HIGHLIGHTER);
3193 void
3194 on_button3Text_activate (GtkMenuItem *menuitem,
3195 gpointer user_data)
3197 process_mapping_activate(menuitem, 2, TOOL_TEXT);
3201 void
3202 on_button3SelectRegion_activate (GtkMenuItem *menuitem,
3203 gpointer user_data)
3205 process_mapping_activate(menuitem, 2, TOOL_SELECTREGION);
3209 void
3210 on_button3SelectRectangle_activate (GtkMenuItem *menuitem,
3211 gpointer user_data)
3213 process_mapping_activate(menuitem, 2, TOOL_SELECTRECT);
3217 void
3218 on_button3VerticalSpace_activate (GtkMenuItem *menuitem,
3219 gpointer user_data)
3221 process_mapping_activate(menuitem, 2, TOOL_VERTSPACE);
3225 void
3226 on_button3LinkBrush_activate (GtkMenuItem *menuitem,
3227 gpointer user_data)
3229 int i;
3231 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3232 end_text();
3233 reset_focus();
3234 ui.linked_brush[2] = BRUSH_LINKED;
3235 for (i=0;i<NUM_STROKE_TOOLS;i++) update_mapping_linkings(i);
3239 void
3240 on_button3CopyBrush_activate (GtkMenuItem *menuitem,
3241 gpointer user_data)
3243 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
3244 end_text();
3245 reset_focus();
3246 if (ui.toolno[2] >= NUM_STROKE_TOOLS) {
3247 ui.linked_brush[2] = BRUSH_STATIC;
3248 update_mappings_menu_linkings();
3249 return;
3251 ui.linked_brush[2] = BRUSH_COPIED;
3252 g_memmove(&(ui.brushes[2][ui.toolno[2]]), &(ui.brushes[0][ui.toolno[2]]), sizeof(struct Brush));
3255 // the set zoom dialog
3257 GtkWidget *zoom_dialog;
3258 double zoom_percent;
3260 void
3261 on_viewSetZoom_activate (GtkMenuItem *menuitem,
3262 gpointer user_data)
3264 int response;
3265 double test_w, test_h;
3266 GtkSpinButton *spinZoom;
3268 end_text();
3269 reset_focus();
3270 zoom_dialog = create_zoomDialog();
3271 zoom_percent = 100*ui.zoom / DEFAULT_ZOOM;
3272 spinZoom = GTK_SPIN_BUTTON(g_object_get_data(G_OBJECT(zoom_dialog), "spinZoom"));
3273 gtk_spin_button_set_increments(spinZoom, ui.zoom_step_increment, 5*ui.zoom_step_increment);
3274 gtk_spin_button_set_value(spinZoom, zoom_percent);
3275 test_w = 100*(GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width/DEFAULT_ZOOM;
3276 test_h = 100*(GTK_WIDGET(canvas))->allocation.height/ui.cur_page->height/DEFAULT_ZOOM;
3277 if (zoom_percent > 99.9 && zoom_percent < 100.1)
3278 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3279 G_OBJECT(zoom_dialog), "radioZoom100")), TRUE);
3280 else if (zoom_percent > test_w-0.1 && zoom_percent < test_w+0.1)
3281 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3282 G_OBJECT(zoom_dialog), "radioZoomWidth")), TRUE);
3283 else if (zoom_percent > test_h-0.1 && zoom_percent < test_h+0.1)
3284 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3285 G_OBJECT(zoom_dialog), "radioZoomHeight")), TRUE);
3286 else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3287 G_OBJECT(zoom_dialog), "radioZoom")), TRUE);
3288 gtk_widget_show(zoom_dialog);
3290 do {
3291 response = gtk_dialog_run(GTK_DIALOG(zoom_dialog));
3292 if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY) {
3293 ui.zoom = DEFAULT_ZOOM*zoom_percent/100;
3294 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
3295 rescale_text_items();
3296 rescale_bg_pixmaps();
3298 } while (response == GTK_RESPONSE_APPLY);
3300 gtk_widget_destroy(zoom_dialog);
3304 void
3305 on_spinZoom_value_changed (GtkSpinButton *spinbutton,
3306 gpointer user_data)
3308 double val;
3310 val = gtk_spin_button_get_value(GTK_SPIN_BUTTON(g_object_get_data(
3311 G_OBJECT(zoom_dialog), "spinZoom")));
3312 if (val<1) return;
3313 if (val<10) val=10.;
3314 if (val>1500) val=1500.;
3315 if (val<zoom_percent-1 || val>zoom_percent+1)
3316 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_object_get_data(
3317 G_OBJECT(zoom_dialog), "radioZoom")), TRUE);
3318 zoom_percent = val;
3322 void
3323 on_radioZoom_toggled (GtkToggleButton *togglebutton,
3324 gpointer user_data)
3326 // nothing to do
3330 void
3331 on_radioZoom100_toggled (GtkToggleButton *togglebutton,
3332 gpointer user_data)
3334 if (!gtk_toggle_button_get_active(togglebutton)) return;
3335 zoom_percent = 100.;
3336 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3337 G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3341 void
3342 on_radioZoomWidth_toggled (GtkToggleButton *togglebutton,
3343 gpointer user_data)
3345 if (!gtk_toggle_button_get_active(togglebutton)) return;
3346 zoom_percent = 100*(GTK_WIDGET(canvas))->allocation.width/ui.cur_page->width/DEFAULT_ZOOM;
3347 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3348 G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3352 void
3353 on_radioZoomHeight_toggled (GtkToggleButton *togglebutton,
3354 gpointer user_data)
3356 if (!gtk_toggle_button_get_active(togglebutton)) return;
3357 zoom_percent = 100*(GTK_WIDGET(canvas))->allocation.height/ui.cur_page->height/DEFAULT_ZOOM;
3358 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g_object_get_data(
3359 G_OBJECT(zoom_dialog), "spinZoom")), zoom_percent);
3363 void
3364 on_toolsHand_activate (GtkMenuItem *menuitem,
3365 gpointer user_data)
3367 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
3368 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
3369 return;
3370 } else {
3371 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
3372 return;
3375 if (ui.cur_mapping != 0) return;
3376 if (ui.toolno[0] == TOOL_HAND) return;
3378 end_text();
3379 reset_focus();
3380 reset_selection();
3381 ui.toolno[0] = TOOL_HAND;
3382 update_mapping_linkings(-1);
3383 update_tool_buttons();
3384 update_tool_menu();
3385 update_color_menu();
3386 update_cursor();
3390 void
3391 on_button2Hand_activate (GtkMenuItem *menuitem,
3392 gpointer user_data)
3394 process_mapping_activate(menuitem, 1, TOOL_HAND);
3398 void
3399 on_button3Hand_activate (GtkMenuItem *menuitem,
3400 gpointer user_data)
3402 process_mapping_activate(menuitem, 2, TOOL_HAND);
3406 void
3407 on_optionsPrintRuling_activate (GtkMenuItem *menuitem,
3408 gpointer user_data)
3410 end_text();
3411 reset_focus();
3412 ui.print_ruling = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3415 void
3416 on_optionsDiscardCore_activate (GtkMenuItem *menuitem,
3417 gpointer user_data)
3419 end_text();
3420 reset_focus();
3421 ui.discard_corepointer =
3422 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3423 update_mappings_menu();
3426 void
3427 on_fontButton_font_set (GtkFontButton *fontbutton,
3428 gpointer user_data)
3430 gchar *str;
3432 str = g_strdup(gtk_font_button_get_font_name(fontbutton));
3433 process_font_sel(str);
3436 void
3437 on_optionsLeftHanded_activate (GtkMenuItem *menuitem,
3438 gpointer user_data)
3440 end_text();
3441 reset_focus();
3442 ui.left_handed = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3443 gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW(GET_COMPONENT("scrolledwindowMain")),
3444 ui.left_handed?GTK_CORNER_TOP_RIGHT:GTK_CORNER_TOP_LEFT);
3447 void
3448 on_optionsShortenMenus_activate (GtkMenuItem *menuitem,
3449 gpointer user_data)
3451 gchar *item, *nextptr;
3452 GtkWidget *w;
3454 end_text();
3455 reset_focus();
3456 ui.shorten_menus = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3458 /* go over the item list */
3459 item = ui.shorten_menu_items;
3460 while (*item==' ') item++;
3461 while (*item) {
3462 nextptr = strchr(item, ' ');
3463 if (nextptr!=NULL) *nextptr = 0;
3464 // hide or show the item
3465 w = GET_COMPONENT(item);
3466 if (w != NULL) {
3467 if (ui.shorten_menus) gtk_widget_hide(w);
3468 else gtk_widget_show(w);
3470 // next item
3471 if (nextptr==NULL) break;
3472 *nextptr = ' ';
3473 item = nextptr;
3474 while (*item==' ') item++;
3477 // just in case someone tried to unhide stuff they shouldn't be seeing
3478 hide_unimplemented();
3479 // maybe we should also make sure the drawing area stays visible ?
3482 void
3483 on_optionsAutoSavePrefs_activate (GtkMenuItem *menuitem,
3484 gpointer user_data)
3486 end_text();
3487 reset_focus();
3488 ui.auto_save_prefs = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3491 void
3492 on_optionsPressureSensitive_activate (GtkMenuItem *menuitem,
3493 gpointer user_data)
3495 int i;
3496 end_text();
3497 reset_focus();
3498 ui.pressure_sensitivity =
3499 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem));
3500 for (i=0; i<=NUM_BUTTONS; i++)
3501 ui.brushes[i][TOOL_PEN].variable_width = ui.pressure_sensitivity;
3502 update_mappings_menu();