8 #include <libgnomecanvas/libgnomecanvas.h>
11 #include "xo-interface.h"
12 #include "xo-support.h"
13 #include "xo-callbacks.h"
18 // some global constants
20 guint predef_colors_rgba[COLOR_MAX] =
21 { 0x000000ff, 0x3333ccff, 0xff0000ff, 0x008000ff,
22 0x808080ff, 0x00c0ffff, 0x00ff00ff, 0xff00ffff,
23 0xff8000ff, 0xffff00ff, 0xffffffff };
25 guint predef_bgcolors_rgba[COLOR_MAX] = // meaningless ones set to white
26 { 0xffffffff, 0xa0e8ffff, 0xffc0d4ff, 0x80ffc0ff,
27 0xffffffff, 0xa0e8ffff, 0x80ffc0ff, 0xffc0d4ff,
28 0xffc080ff, 0xffff80ff, 0xffffffff };
30 double predef_thickness[NUM_STROKE_TOOLS][THICKNESS_MAX] =
31 { { 0.42, 0.85, 1.41, 2.26, 5.67 }, // pen thicknesses = 0.15, 0.3, 0.5, 0.8, 2 mm
32 { 2.83, 2.83, 8.50, 19.84, 19.84 }, // eraser thicknesses = 1, 3, 7 mm
33 { 2.83, 2.83, 8.50, 19.84, 19.84 }, // highlighter thicknesses = 1, 3, 7 mm
36 // some manipulation functions
38 struct Page *new_page(struct Page *template)
40 struct Page *pg = (struct Page *) g_memdup(template, sizeof(struct Page));
41 struct Layer *l = g_new(struct Layer, 1);
45 pg->layers = g_list_append(NULL, l);
47 pg->bg = (struct Background *)g_memdup(template->bg, sizeof(struct Background));
48 pg->bg->canvas_item = NULL;
49 if (pg->bg->type == BG_PIXMAP || pg->bg->type == BG_PDF) {
50 gdk_pixbuf_ref(pg->bg->pixbuf);
51 refstring_ref(pg->bg->filename);
53 pg->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
54 gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
55 make_page_clipbox(pg);
57 l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
58 pg->group, gnome_canvas_group_get_type(), NULL);
63 /* Create a page from a background.
64 Note: bg should be an UNREFERENCED background.
65 If needed, first duplicate it and increase the refcount of the pixbuf.
67 struct Page *new_page_with_bg(struct Background *bg, double width, double height)
69 struct Page *pg = g_new(struct Page, 1);
70 struct Layer *l = g_new(struct Layer, 1);
74 pg->layers = g_list_append(NULL, l);
77 pg->bg->canvas_item = NULL;
80 pg->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
81 gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
82 make_page_clipbox(pg);
84 l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
85 pg->group, gnome_canvas_group_get_type(), NULL);
90 void realloc_cur_path(int n)
92 if (n <= ui.cur_path_storage_alloc) return;
93 ui.cur_path_storage_alloc = n+10;
94 ui.cur_path.coords = g_realloc(ui.cur_path.coords, 2*(n+10)*sizeof(double));
97 // undo utility functions
99 void prepare_new_undo(void)
102 // add a new UndoItem on the stack
103 u = (struct UndoItem *)g_malloc(sizeof(struct UndoItem));
111 void clear_redo_stack(void)
115 struct UndoErasureData *erasure;
118 /* Warning: the redo items might reference items from past redo entries,
119 which have been destroyed before them. Be careful! As a rule, it's
120 safe to destroy data which has been created at the current history step,
121 it's unsafe to refer to any data from previous history steps */
124 if (redo->type == ITEM_STROKE) {
125 gnome_canvas_points_free(redo->item->path);
127 /* the strokes are unmapped, so there are no associated canvas items */
129 else if (redo->type == ITEM_ERASURE) {
130 for (list = redo->erasurelist; list!=NULL; list=list->next) {
131 erasure = (struct UndoErasureData *)list->data;
132 for (repl = erasure->replacement_items; repl!=NULL; repl=repl->next) {
133 it = (struct Item *)repl->data;
134 gnome_canvas_points_free(it->path);
137 g_list_free(erasure->replacement_items);
140 g_list_free(redo->erasurelist);
142 else if (redo->type == ITEM_NEW_BG_ONE || redo->type == ITEM_NEW_BG_RESIZE
143 || redo->type == ITEM_NEW_DEFAULT_BG) {
144 if (redo->bg->type == BG_PIXMAP || redo->bg->type == BG_PDF) {
145 if (redo->bg->pixbuf!=NULL) gdk_pixbuf_unref(redo->bg->pixbuf);
146 refstring_unref(redo->bg->filename);
150 else if (redo->type == ITEM_NEW_PAGE) {
151 redo->page->group = NULL;
152 delete_page(redo->page);
154 else if (redo->type == ITEM_MOVESEL || redo->type == ITEM_REPAINTSEL) {
155 g_list_free(redo->itemlist); g_list_free(redo->auxlist);
157 else if (redo->type == ITEM_PASTE) {
158 for (list = redo->itemlist; list!=NULL; list=list->next) {
159 it = (struct Item *)list->data;
160 if (it->type == ITEM_STROKE) gnome_canvas_points_free(it->path);
163 g_list_free(redo->itemlist);
165 else if (redo->type == ITEM_NEW_LAYER) {
173 update_undo_redo_enabled();
176 void clear_undo_stack(void)
180 struct UndoErasureData *erasure;
183 // for strokes, items are already in the journal, so we don't free them
184 // for erasures, we need to free the dead items
185 if (undo->type == ITEM_ERASURE) {
186 for (list = undo->erasurelist; list!=NULL; list=list->next) {
187 erasure = (struct UndoErasureData *)list->data;
188 gnome_canvas_points_free(erasure->item->path);
189 g_free(erasure->item);
190 g_list_free(erasure->replacement_items);
193 g_list_free(undo->erasurelist);
195 else if (undo->type == ITEM_NEW_BG_ONE || undo->type == ITEM_NEW_BG_RESIZE
196 || undo->type == ITEM_NEW_DEFAULT_BG) {
197 if (undo->bg->type == BG_PIXMAP || undo->bg->type == BG_PDF) {
198 if (undo->bg->pixbuf!=NULL) gdk_pixbuf_unref(undo->bg->pixbuf);
199 refstring_unref(undo->bg->filename);
203 else if (undo->type == ITEM_MOVESEL || undo->type == ITEM_REPAINTSEL) {
204 g_list_free(undo->itemlist); g_list_free(undo->auxlist);
206 else if (undo->type == ITEM_PASTE) {
207 g_list_free(undo->itemlist);
209 else if (undo->type == ITEM_DELETE_LAYER) {
210 undo->layer->group = NULL;
211 delete_layer(undo->layer);
213 else if (undo->type == ITEM_DELETE_PAGE) {
214 undo->page->group = NULL;
215 delete_page(undo->page);
222 update_undo_redo_enabled();
225 // free data structures
227 void delete_journal(struct Journal *j)
229 while (j->pages!=NULL) {
230 delete_page((struct Page *)j->pages->data);
231 j->pages = g_list_delete_link(j->pages, j->pages);
235 void delete_page(struct Page *pg)
239 while (pg->layers!=NULL) {
240 l = (struct Layer *)pg->layers->data;
243 pg->layers = g_list_delete_link(pg->layers, pg->layers);
245 if (pg->group!=NULL) gtk_object_destroy(GTK_OBJECT(pg->group));
246 // this also destroys the background's canvas items
247 if (pg->bg->type == BG_PIXMAP || pg->bg->type == BG_PDF) {
248 if (pg->bg->pixbuf != NULL) gdk_pixbuf_unref(pg->bg->pixbuf);
249 if (pg->bg->filename != NULL) refstring_unref(pg->bg->filename);
255 void delete_layer(struct Layer *l)
259 while (l->items!=NULL) {
260 item = (struct Item *)l->items->data;
261 if (item->type == ITEM_STROKE && item->path != NULL)
262 gnome_canvas_points_free(item->path);
263 // don't need to delete the canvas_item, as it's part of the group destroyed below
265 l->items = g_list_delete_link(l->items, l->items);
267 if (l->group!= NULL) gtk_object_destroy(GTK_OBJECT(l->group));
271 // referenced strings
273 struct Refstring *new_refstring(const char *s)
275 struct Refstring *rs = g_new(struct Refstring, 1);
277 if (s!=NULL) rs->s = g_strdup(s);
283 struct Refstring *refstring_ref(struct Refstring *rs)
289 void refstring_unref(struct Refstring *rs)
293 if (rs->s!=NULL) g_free(rs->s);
294 if (rs->aux!=NULL) g_free(rs->aux);
300 // some helper functions
302 void get_pointer_coords(GdkEvent *event, gdouble *ret)
305 gdk_event_get_coords(event, &x, &y);
306 gnome_canvas_window_to_world(canvas, x, y, ret, ret+1);
307 ret[0] -= ui.cur_page->hoffset;
308 ret[1] -= ui.cur_page->voffset;
311 void fix_xinput_coords(GdkEvent *event)
313 double *axes, *px, *py, axis_width;
317 if (event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) {
318 axes = event->button.axes;
319 px = &(event->button.x);
320 py = &(event->button.y);
321 device = event->button.device;
323 else if (event->type == GDK_MOTION_NOTIFY) {
324 axes = event->motion.axes;
325 px = &(event->motion.x);
326 py = &(event->motion.y);
327 device = event->motion.device;
329 else return; // nothing we know how to do
331 gdk_window_get_origin(event->any.window, &wx, &wy);
332 gnome_canvas_get_scroll_offsets(canvas, &sx, &sy);
334 axis_width = device->axes[0].max - device->axes[0].min;
335 if (axis_width>EPSILON)
336 *px = (axes[0]/axis_width)*ui.screen_width + sx - wx;
338 axis_width = device->axes[1].max - device->axes[1].min;
339 if (axis_width>EPSILON)
340 *py = (axes[1]/axis_width)*ui.screen_height + sy - wy;
343 void update_item_bbox(struct Item *item)
348 if (item->type == ITEM_STROKE) {
349 item->bbox.left = item->bbox.right = item->path->coords[0];
350 item->bbox.top = item->bbox.bottom = item->path->coords[1];
351 for (i=1, p=item->path->coords+2; i<item->path->num_points; i++, p+=2)
353 if (p[0] < item->bbox.left) item->bbox.left = p[0];
354 if (p[0] > item->bbox.right) item->bbox.right = p[0];
355 if (p[1] < item->bbox.top) item->bbox.top = p[1];
356 if (p[1] > item->bbox.bottom) item->bbox.bottom = p[1];
361 void make_page_clipbox(struct Page *pg)
363 GnomeCanvasPathDef *pg_clip;
365 pg_clip = gnome_canvas_path_def_new_sized(4);
366 gnome_canvas_path_def_moveto(pg_clip, 0., 0.);
367 gnome_canvas_path_def_lineto(pg_clip, 0., pg->height);
368 gnome_canvas_path_def_lineto(pg_clip, pg->width, pg->height);
369 gnome_canvas_path_def_lineto(pg_clip, pg->width, 0.);
370 gnome_canvas_path_def_closepath(pg_clip);
371 gnome_canvas_item_set(GNOME_CANVAS_ITEM(pg->group), "path", pg_clip, NULL);
372 gnome_canvas_path_def_unref(pg_clip);
375 void make_canvas_items(void)
380 GList *pagelist, *layerlist, *itemlist;
382 for (pagelist = journal.pages; pagelist!=NULL; pagelist = pagelist->next) {
383 pg = (struct Page *)pagelist->data;
384 if (pg->group == NULL) {
385 pg->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
386 gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
387 make_page_clipbox(pg);
389 if (pg->bg->canvas_item == NULL) update_canvas_bg(pg);
390 for (layerlist = pg->layers; layerlist!=NULL; layerlist = layerlist->next) {
391 l = (struct Layer *)layerlist->data;
392 if (l->group == NULL)
393 l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
394 pg->group, gnome_canvas_group_get_type(), NULL);
395 for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next) {
396 item = (struct Item *)itemlist->data;
397 if (item->type == ITEM_STROKE && item->canvas_item == NULL) {
398 item->canvas_item = gnome_canvas_item_new(l->group,
399 gnome_canvas_line_get_type(), "points", item->path,
400 "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND,
401 "fill-color-rgba", item->brush.color_rgba,
402 "width-units", item->brush.thickness, NULL);
409 void update_canvas_bg(struct Page *pg)
411 GnomeCanvasGroup *group;
412 GnomeCanvasPoints *seg;
413 GdkPixbuf *scaled_pix;
418 if (pg->bg->canvas_item != NULL)
419 gtk_object_destroy(GTK_OBJECT(pg->bg->canvas_item));
420 pg->bg->canvas_item = NULL;
422 if (pg->bg->type == BG_SOLID)
424 pg->bg->canvas_item = gnome_canvas_item_new(pg->group,
425 gnome_canvas_group_get_type(), NULL);
426 group = GNOME_CANVAS_GROUP(pg->bg->canvas_item);
427 lower_canvas_item_to(pg->group, pg->bg->canvas_item, NULL);
428 gnome_canvas_item_new(group, gnome_canvas_rect_get_type(),
429 "x1", 0., "x2", pg->width, "y1", 0., "y2", pg->height,
430 "fill-color-rgba", pg->bg->color_rgba, NULL);
431 if (pg->bg->ruling == RULING_NONE) return;
432 seg = gnome_canvas_points_new(2);
434 if (pg->bg->ruling == RULING_GRAPH) {
435 pt[1] = 0; pt[3] = pg->height;
436 for (x=RULING_GRAPHSPACING; x<pg->width-1; x+=RULING_GRAPHSPACING) {
438 gnome_canvas_item_new(group, gnome_canvas_line_get_type(),
439 "points", seg, "fill-color-rgba", RULING_COLOR,
440 "width-units", RULING_THICKNESS, NULL);
442 pt[0] = 0; pt[2] = pg->width;
443 for (y=RULING_GRAPHSPACING; y<pg->height-1; y+=RULING_GRAPHSPACING) {
445 gnome_canvas_item_new(group, gnome_canvas_line_get_type(),
446 "points", seg, "fill-color-rgba", RULING_COLOR,
447 "width-units", RULING_THICKNESS, NULL);
449 gnome_canvas_points_free(seg);
452 pt[0] = 0; pt[2] = pg->width;
453 for (y=RULING_TOPMARGIN; y<pg->height-1; y+=RULING_SPACING) {
455 gnome_canvas_item_new(group, gnome_canvas_line_get_type(),
456 "points", seg, "fill-color-rgba", RULING_COLOR,
457 "width-units", RULING_THICKNESS, NULL);
459 if (pg->bg->ruling == RULING_LINED) {
460 pt[0] = pt[2] = RULING_LEFTMARGIN;
461 pt[1] = 0; pt[3] = pg->height;
462 gnome_canvas_item_new(group, gnome_canvas_line_get_type(),
463 "points", seg, "fill-color-rgba", RULING_MARGIN_COLOR,
464 "width-units", RULING_THICKNESS, NULL);
466 gnome_canvas_points_free(seg);
470 if (pg->bg->type == BG_PIXMAP)
472 if (ui.antialias_bg) {
473 set_cursor_busy(TRUE);
474 w = (int)floor(pg->width*ui.zoom+0.5);
475 h = (int)floor(pg->height*ui.zoom+0.5);
476 if (w == gdk_pixbuf_get_width(pg->bg->pixbuf) &&
477 h == gdk_pixbuf_get_height(pg->bg->pixbuf))
478 scaled_pix = gdk_pixbuf_ref(pg->bg->pixbuf);
480 scaled_pix = gdk_pixbuf_scale_simple(pg->bg->pixbuf, w, h, GDK_INTERP_BILINEAR);
481 pg->bg->pixbuf_scale = ui.zoom;
482 set_cursor_busy(FALSE);
485 scaled_pix = gdk_pixbuf_ref(pg->bg->pixbuf);
486 pg->bg->pixbuf_scale = 0;
488 pg->bg->canvas_item = gnome_canvas_item_new(pg->group,
489 gnome_canvas_pixbuf_get_type(),
490 "pixbuf", scaled_pix,
491 "width", pg->width, "height", pg->height,
492 "width-set", TRUE, "height-set", TRUE,
494 gdk_pixbuf_unref(scaled_pix);
495 lower_canvas_item_to(pg->group, pg->bg->canvas_item, NULL);
498 if (pg->bg->type == BG_PDF)
500 if (pg->bg->pixbuf == NULL) return;
501 pg->bg->canvas_item = gnome_canvas_item_new(pg->group,
502 gnome_canvas_pixbuf_get_type(),
503 "pixbuf", pg->bg->pixbuf,
504 "width", pg->width, "height", pg->height,
505 "width-set", TRUE, "height-set", TRUE,
507 lower_canvas_item_to(pg->group, pg->bg->canvas_item, NULL);
512 gboolean is_visible(struct Page *pg)
514 GtkAdjustment *v_adj;
517 if (!ui.view_continuous) return (pg == ui.cur_page);
518 v_adj = gtk_layout_get_vadjustment(GTK_LAYOUT(canvas));
519 ytop = v_adj->value/ui.zoom;
520 ybot = (v_adj->value + v_adj->page_size) / ui.zoom;
521 return (MAX(ytop, pg->voffset) < MIN(ybot, pg->voffset+pg->height));
524 void rescale_bg_pixmaps(void)
530 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
531 pg = (struct Page *)pglist->data;
532 // in progressive mode we scale only visible pages
533 if (ui.progressive_bg && !is_visible(pg)) continue;
535 if (pg->bg->type == BG_PIXMAP && pg->bg->canvas_item!=NULL) { // do the rescaling ourselves
536 if (ui.antialias_bg) {
537 if (pg->bg->pixbuf_scale == ui.zoom) continue;
538 set_cursor_busy(TRUE);
539 pix = gdk_pixbuf_scale_simple(pg->bg->pixbuf,
540 (int)floor(pg->width*ui.zoom+0.5), (int)floor(pg->height*ui.zoom+0.5),
541 GDK_INTERP_BILINEAR);
542 gnome_canvas_item_set(pg->bg->canvas_item, "pixbuf", pix, NULL);
543 gdk_pixbuf_unref(pix);
544 pg->bg->pixbuf_scale = ui.zoom;
545 set_cursor_busy(FALSE);
548 g_object_get(G_OBJECT(pg->bg->canvas_item), "pixbuf", &pix, NULL);
549 if (pix!=pg->bg->pixbuf)
550 gnome_canvas_item_set(pg->bg->canvas_item, "pixbuf", pg->bg->pixbuf, NULL);
551 pg->bg->pixbuf_scale = 0;
554 if (pg->bg->type == BG_PDF) { // request an asynchronous update
555 if (pg->bg->pixbuf_scale == ui.zoom) continue;
556 add_bgpdf_request(pg->bg->file_page_seq, ui.zoom, FALSE);
557 pg->bg->pixbuf_scale = ui.zoom;
562 gboolean have_intersect(struct BBox *a, struct BBox *b)
564 return (MAX(a->top, b->top) <= MIN(a->bottom, b->bottom)) &&
565 (MAX(a->left, b->left) <= MIN(a->right, b->right));
568 /* In libgnomecanvas 2.10.0, the lower/raise functions fail to update
569 correctly the end of the group's item list. We try to work around this.
570 DON'T USE gnome_canvas_item_raise/lower directly !! */
572 void lower_canvas_item_to(GnomeCanvasGroup *g, GnomeCanvasItem *item, GnomeCanvasItem *after)
576 i1 = g_list_index(g->item_list, item);
577 if (i1 == -1) return;
579 if (after == NULL) i2 = -1;
580 else i2 = g_list_index(g->item_list, after);
582 if (i1 < i2) gnome_canvas_item_raise(item, i2-i1);
583 if (i1 > i2+1) gnome_canvas_item_lower(item, i1-i2-1);
585 // BUGFIX for libgnomecanvas
586 g->item_list_end = g_list_last(g->item_list);
589 // some interface functions
591 void update_thickness_buttons(void)
593 if (ui.selection!=NULL || ui.toolno[ui.cur_mapping] >= NUM_STROKE_TOOLS) {
594 gtk_toggle_tool_button_set_active(
595 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonThicknessOther")), TRUE);
597 switch (ui.cur_brush->thickness_no) {
599 gtk_toggle_tool_button_set_active(
600 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonFine")), TRUE);
602 case THICKNESS_MEDIUM:
603 gtk_toggle_tool_button_set_active(
604 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonMedium")), TRUE);
606 case THICKNESS_THICK:
607 gtk_toggle_tool_button_set_active(
608 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonThick")), TRUE);
611 gtk_toggle_tool_button_set_active(
612 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonThicknessOther")), TRUE);
616 void update_color_buttons(void)
618 if (ui.selection!=NULL || (ui.toolno[ui.cur_mapping] != TOOL_PEN
619 && ui.toolno[ui.cur_mapping] != TOOL_HIGHLIGHTER)) {
620 gtk_toggle_tool_button_set_active(
621 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonColorOther")), TRUE);
623 switch (ui.cur_brush->color_no) {
625 gtk_toggle_tool_button_set_active(
626 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonBlack")), TRUE);
629 gtk_toggle_tool_button_set_active(
630 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonBlue")), TRUE);
633 gtk_toggle_tool_button_set_active(
634 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonRed")), TRUE);
637 gtk_toggle_tool_button_set_active(
638 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonGreen")), TRUE);
641 gtk_toggle_tool_button_set_active(
642 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonGray")), TRUE);
644 case COLOR_LIGHTBLUE:
645 gtk_toggle_tool_button_set_active(
646 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonLightBlue")), TRUE);
648 case COLOR_LIGHTGREEN:
649 gtk_toggle_tool_button_set_active(
650 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonLightGreen")), TRUE);
653 gtk_toggle_tool_button_set_active(
654 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonMagenta")), TRUE);
657 gtk_toggle_tool_button_set_active(
658 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonOrange")), TRUE);
661 gtk_toggle_tool_button_set_active(
662 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonYellow")), TRUE);
665 gtk_toggle_tool_button_set_active(
666 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonWhite")), TRUE);
669 gtk_toggle_tool_button_set_active(
670 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonColorOther")), TRUE);
674 void update_tool_buttons(void)
676 switch(ui.toolno[ui.cur_mapping]) {
678 gtk_toggle_tool_button_set_active(
679 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonPen")), TRUE);
682 gtk_toggle_tool_button_set_active(
683 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonEraser")), TRUE);
685 case TOOL_HIGHLIGHTER:
686 gtk_toggle_tool_button_set_active(
687 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonHighlighter")), TRUE);
690 gtk_toggle_tool_button_set_active(
691 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonText")), TRUE);
693 case TOOL_SELECTREGION:
694 gtk_toggle_tool_button_set_active(
695 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonSelectRegion")), TRUE);
697 case TOOL_SELECTRECT:
698 gtk_toggle_tool_button_set_active(
699 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonSelectRectangle")), TRUE);
702 gtk_toggle_tool_button_set_active(
703 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonVerticalSpace")), TRUE);
706 gtk_toggle_tool_button_set_active(
707 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonHand")), TRUE);
711 gtk_toggle_tool_button_set_active(
712 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonRuler")), ui.ruler[ui.cur_mapping]);
713 update_thickness_buttons();
714 update_color_buttons();
717 void update_tool_menu(void)
719 switch(ui.toolno[0]) {
721 gtk_check_menu_item_set_active(
722 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsPen")), TRUE);
725 gtk_check_menu_item_set_active(
726 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsEraser")), TRUE);
728 case TOOL_HIGHLIGHTER:
729 gtk_check_menu_item_set_active(
730 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsHighlighter")), TRUE);
733 gtk_check_menu_item_set_active(
734 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsText")), TRUE);
736 case TOOL_SELECTREGION:
737 gtk_check_menu_item_set_active(
738 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsSelectRegion")), TRUE);
740 case TOOL_SELECTRECT:
741 gtk_check_menu_item_set_active(
742 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsSelectRectangle")), TRUE);
745 gtk_check_menu_item_set_active(
746 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsVerticalSpace")), TRUE);
749 gtk_check_menu_item_set_active(
750 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsHand")), TRUE);
754 gtk_check_menu_item_set_active(
755 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsRuler")), ui.ruler[0]);
758 void update_ruler_indicator(void)
760 gtk_toggle_tool_button_set_active(
761 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonRuler")), ui.ruler[ui.cur_mapping]);
762 gtk_check_menu_item_set_active(
763 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsRuler")), ui.ruler[0]);
766 void update_color_menu(void)
768 if (ui.selection!=NULL || (ui.toolno[ui.cur_mapping] != TOOL_PEN
769 && ui.toolno[ui.cur_mapping] != TOOL_HIGHLIGHTER)) {
770 gtk_check_menu_item_set_active(
771 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorNA")), TRUE);
773 switch (ui.cur_brush->color_no) {
775 gtk_check_menu_item_set_active(
776 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorBlack")), TRUE);
779 gtk_check_menu_item_set_active(
780 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorBlue")), TRUE);
783 gtk_check_menu_item_set_active(
784 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorRed")), TRUE);
787 gtk_check_menu_item_set_active(
788 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorGreen")), TRUE);
791 gtk_check_menu_item_set_active(
792 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorGray")), TRUE);
794 case COLOR_LIGHTBLUE:
795 gtk_check_menu_item_set_active(
796 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorLightBlue")), TRUE);
798 case COLOR_LIGHTGREEN:
799 gtk_check_menu_item_set_active(
800 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorLightGreen")), TRUE);
803 gtk_check_menu_item_set_active(
804 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorMagenta")), TRUE);
807 gtk_check_menu_item_set_active(
808 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorOrange")), TRUE);
811 gtk_check_menu_item_set_active(
812 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorYellow")), TRUE);
815 gtk_check_menu_item_set_active(
816 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorWhite")), TRUE);
819 gtk_check_menu_item_set_active(
820 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorOther")), TRUE);
824 void update_pen_props_menu(void)
826 switch(ui.brushes[0][TOOL_PEN].thickness_no) {
827 case THICKNESS_VERYFINE:
828 gtk_check_menu_item_set_active(
829 GTK_CHECK_MENU_ITEM(GET_COMPONENT("penthicknessVeryFine")), TRUE);
832 gtk_check_menu_item_set_active(
833 GTK_CHECK_MENU_ITEM(GET_COMPONENT("penthicknessFine")), TRUE);
835 case THICKNESS_MEDIUM:
836 gtk_check_menu_item_set_active(
837 GTK_CHECK_MENU_ITEM(GET_COMPONENT("penthicknessMedium")), TRUE);
839 case THICKNESS_THICK:
840 gtk_check_menu_item_set_active(
841 GTK_CHECK_MENU_ITEM(GET_COMPONENT("penthicknessThick")), TRUE);
843 case THICKNESS_VERYTHICK:
844 gtk_check_menu_item_set_active(
845 GTK_CHECK_MENU_ITEM(GET_COMPONENT("penthicknessVeryThick")), TRUE);
850 void update_eraser_props_menu(void)
852 switch (ui.brushes[0][TOOL_ERASER].thickness_no) {
854 gtk_check_menu_item_set_active(
855 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserFine")), TRUE);
857 case THICKNESS_MEDIUM:
858 gtk_check_menu_item_set_active(
859 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserMedium")), TRUE);
861 case THICKNESS_THICK:
862 gtk_check_menu_item_set_active(
863 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserThick")), TRUE);
867 gtk_check_menu_item_set_active(
868 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserStandard")),
869 ui.brushes[0][TOOL_ERASER].tool_options == TOOLOPT_ERASER_STANDARD);
870 gtk_check_menu_item_set_active(
871 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserWhiteout")),
872 ui.brushes[0][TOOL_ERASER].tool_options == TOOLOPT_ERASER_WHITEOUT);
873 gtk_check_menu_item_set_active(
874 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserDeleteStrokes")),
875 ui.brushes[0][TOOL_ERASER].tool_options == TOOLOPT_ERASER_STROKES);
878 void update_highlighter_props_menu(void)
880 switch (ui.brushes[0][TOOL_HIGHLIGHTER].thickness_no) {
882 gtk_check_menu_item_set_active(
883 GTK_CHECK_MENU_ITEM(GET_COMPONENT("highlighterFine")), TRUE);
885 case THICKNESS_MEDIUM:
886 gtk_check_menu_item_set_active(
887 GTK_CHECK_MENU_ITEM(GET_COMPONENT("highlighterMedium")), TRUE);
889 case THICKNESS_THICK:
890 gtk_check_menu_item_set_active(
891 GTK_CHECK_MENU_ITEM(GET_COMPONENT("highlighterThick")), TRUE);
896 void update_mappings_menu_linkings(void)
898 switch (ui.linked_brush[1]) {
900 gtk_check_menu_item_set_active(
901 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2LinkBrush")), TRUE);
904 gtk_check_menu_item_set_active(
905 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2CopyBrush")), TRUE);
908 gtk_check_menu_item_set_active(
909 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2NABrush")), TRUE);
912 switch (ui.linked_brush[2]) {
914 gtk_check_menu_item_set_active(
915 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3LinkBrush")), TRUE);
918 gtk_check_menu_item_set_active(
919 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3CopyBrush")), TRUE);
922 gtk_check_menu_item_set_active(
923 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3NABrush")), TRUE);
928 void update_mappings_menu(void)
930 gtk_widget_set_sensitive(GET_COMPONENT("optionsButtonMappings"), ui.use_xinput);
931 gtk_widget_set_sensitive(GET_COMPONENT("optionsDiscardCoreEvents"), ui.use_xinput);
932 gtk_check_menu_item_set_active(
933 GTK_CHECK_MENU_ITEM(GET_COMPONENT("optionsButtonMappings")), ui.use_erasertip);
934 gtk_check_menu_item_set_active(
935 GTK_CHECK_MENU_ITEM(GET_COMPONENT("optionsDiscardCoreEvents")), ui.discard_corepointer);
937 switch(ui.toolno[1]) {
939 gtk_check_menu_item_set_active(
940 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2Pen")), TRUE);
943 gtk_check_menu_item_set_active(
944 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2Eraser")), TRUE);
946 case TOOL_HIGHLIGHTER:
947 gtk_check_menu_item_set_active(
948 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2Highlighter")), TRUE);
951 gtk_check_menu_item_set_active(
952 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2Text")), TRUE);
954 case TOOL_SELECTREGION:
955 gtk_check_menu_item_set_active(
956 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2SelectRegion")), TRUE);
958 case TOOL_SELECTRECT:
959 gtk_check_menu_item_set_active(
960 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2SelectRectangle")), TRUE);
963 gtk_check_menu_item_set_active(
964 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2VerticalSpace")), TRUE);
967 switch(ui.toolno[2]) {
969 gtk_check_menu_item_set_active(
970 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3Pen")), TRUE);
973 gtk_check_menu_item_set_active(
974 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3Eraser")), TRUE);
976 case TOOL_HIGHLIGHTER:
977 gtk_check_menu_item_set_active(
978 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3Highlighter")), TRUE);
981 gtk_check_menu_item_set_active(
982 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3Text")), TRUE);
984 case TOOL_SELECTREGION:
985 gtk_check_menu_item_set_active(
986 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3SelectRegion")), TRUE);
988 case TOOL_SELECTRECT:
989 gtk_check_menu_item_set_active(
990 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3SelectRectangle")), TRUE);
993 gtk_check_menu_item_set_active(
994 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3VerticalSpace")), TRUE);
997 update_mappings_menu_linkings();
1000 void do_switch_page(int pg, gboolean rescroll, gboolean refresh_all)
1003 struct Layer *layer;
1008 /* re-show all the layers of the old page */
1009 if (ui.cur_page != NULL)
1010 for (i=0, list = ui.cur_page->layers; list!=NULL; i++, list = list->next) {
1011 layer = (struct Layer *)list->data;
1012 if (layer->group!=NULL)
1013 gnome_canvas_item_show(GNOME_CANVAS_ITEM(layer->group));
1016 ui.cur_page = g_list_nth_data(journal.pages, ui.pageno);
1017 ui.layerno = ui.cur_page->nlayers-1;
1018 ui.cur_layer = (struct Layer *)(g_list_last(ui.cur_page->layers)->data);
1019 update_page_stuff();
1020 if (ui.progressive_bg) rescale_bg_pixmaps();
1022 if (rescroll) { // scroll and force a refresh
1023 gtk_adjustment_set_value(gtk_layout_get_vadjustment(GTK_LAYOUT(canvas)),
1024 ui.cur_page->voffset*ui.zoom);
1026 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
1027 else if (!ui.view_continuous)
1028 gnome_canvas_item_move(GNOME_CANVAS_ITEM(ui.cur_page->group), 0., 0.);
1032 void update_page_stuff(void)
1035 GtkComboBox *layerbox;
1038 GtkSpinButton *spin;
1040 double vertpos, maxwidth;
1041 struct Layer *layer;
1044 // move the page groups to their rightful locations or hide them
1045 if (ui.view_continuous) {
1048 for (i=0, pglist = journal.pages; pglist!=NULL; i++, pglist = pglist->next) {
1049 pg = (struct Page *)pglist->data;
1050 if (pg->group!=NULL) {
1051 pg->hoffset = 0.; pg->voffset = vertpos;
1052 gnome_canvas_item_set(GNOME_CANVAS_ITEM(pg->group),
1053 "x", pg->hoffset, "y", pg->voffset, NULL);
1054 gnome_canvas_item_show(GNOME_CANVAS_ITEM(pg->group));
1056 vertpos += pg->height + VIEW_CONTINUOUS_SKIP;
1057 if (pg->width > maxwidth) maxwidth = pg->width;
1059 vertpos -= VIEW_CONTINUOUS_SKIP;
1060 gnome_canvas_set_scroll_region(canvas, 0, 0, maxwidth, vertpos);
1062 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
1063 pg = (struct Page *)pglist->data;
1064 if (pg == ui.cur_page && pg->group!=NULL) {
1065 pg->hoffset = 0.; pg->voffset = 0.;
1066 gnome_canvas_item_set(GNOME_CANVAS_ITEM(pg->group),
1067 "x", pg->hoffset, "y", pg->voffset, NULL);
1068 gnome_canvas_item_show(GNOME_CANVAS_ITEM(pg->group));
1070 if (pg->group!=NULL) gnome_canvas_item_hide(GNOME_CANVAS_ITEM(pg->group));
1073 gnome_canvas_set_scroll_region(canvas, 0, 0, ui.cur_page->width, ui.cur_page->height);
1076 // update the page / layer info at bottom of screen
1078 spin = GTK_SPIN_BUTTON(GET_COMPONENT("spinPageNo"));
1079 ui.in_update_page_stuff = TRUE; // avoid a bad retroaction
1080 gtk_spin_button_set_range(spin, 1, journal.npages+1);
1081 /* npages+1 will be used to create a new page at end */
1082 gtk_spin_button_set_value(spin, ui.pageno+1);
1083 g_snprintf(tmp, 10, " of %d", journal.npages);
1084 gtk_label_set_text(GTK_LABEL(GET_COMPONENT("labelNumpages")), tmp);
1086 layerbox = GTK_COMBO_BOX(GET_COMPONENT("comboLayer"));
1087 if (ui.layerbox_length == 0) {
1088 gtk_combo_box_prepend_text(layerbox, "Background");
1089 ui.layerbox_length++;
1091 while (ui.layerbox_length > ui.cur_page->nlayers+1) {
1092 gtk_combo_box_remove_text(layerbox, 0);
1093 ui.layerbox_length--;
1095 while (ui.layerbox_length < ui.cur_page->nlayers+1) {
1096 g_snprintf(tmp, 10, "Layer %d", ui.layerbox_length++);
1097 gtk_combo_box_prepend_text(layerbox, tmp);
1099 gtk_combo_box_set_active(layerbox, ui.cur_page->nlayers-1-ui.layerno);
1100 ui.in_update_page_stuff = FALSE;
1102 // update the paper-style menu radio buttons
1104 if (ui.view_continuous)
1105 gtk_check_menu_item_set_active(
1106 GTK_CHECK_MENU_ITEM(GET_COMPONENT("viewContinuous")), TRUE);
1108 gtk_check_menu_item_set_active(
1109 GTK_CHECK_MENU_ITEM(GET_COMPONENT("viewOnePage")), TRUE);
1111 if (ui.cur_page->bg->type == BG_SOLID && !ui.bg_apply_all_pages) {
1112 switch (ui.cur_page->bg->color_no) {
1114 gtk_check_menu_item_set_active(
1115 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorWhite")), TRUE);
1118 gtk_check_menu_item_set_active(
1119 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorYellow")), TRUE);
1122 gtk_check_menu_item_set_active(
1123 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorPink")), TRUE);
1126 gtk_check_menu_item_set_active(
1127 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorOrange")), TRUE);
1130 gtk_check_menu_item_set_active(
1131 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorBlue")), TRUE);
1134 gtk_check_menu_item_set_active(
1135 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorGreen")), TRUE);
1138 gtk_check_menu_item_set_active(
1139 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorOther")), TRUE);
1142 switch (ui.cur_page->bg->ruling) {
1144 gtk_check_menu_item_set_active(
1145 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstylePlain")), TRUE);
1148 gtk_check_menu_item_set_active(
1149 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstyleLined")), TRUE);
1152 gtk_check_menu_item_set_active(
1153 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstyleRuled")), TRUE);
1156 gtk_check_menu_item_set_active(
1157 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstyleGraph")), TRUE);
1161 gtk_check_menu_item_set_active(
1162 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorNA")), TRUE);
1163 gtk_check_menu_item_set_active(
1164 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstyleNA")), TRUE);
1167 // enable/disable the page/layer menu items and toolbar buttons
1169 gtk_widget_set_sensitive(GET_COMPONENT("journalPaperColor"),
1170 ui.cur_page->bg->type == BG_SOLID || ui.bg_apply_all_pages);
1171 gtk_widget_set_sensitive(GET_COMPONENT("journalSetAsDefault"),
1172 ui.cur_page->bg->type == BG_SOLID);
1174 gtk_widget_set_sensitive(GET_COMPONENT("viewFirstPage"), ui.pageno!=0);
1175 gtk_widget_set_sensitive(GET_COMPONENT("viewPreviousPage"), ui.pageno!=0);
1176 gtk_widget_set_sensitive(GET_COMPONENT("viewNextPage"), TRUE);
1177 gtk_widget_set_sensitive(GET_COMPONENT("viewLastPage"), ui.pageno!=journal.npages-1);
1178 gtk_widget_set_sensitive(GET_COMPONENT("buttonFirstPage"), ui.pageno!=0);
1179 gtk_widget_set_sensitive(GET_COMPONENT("buttonPreviousPage"), ui.pageno!=0);
1180 gtk_widget_set_sensitive(GET_COMPONENT("buttonNextPage"), TRUE);
1181 gtk_widget_set_sensitive(GET_COMPONENT("buttonLastPage"), ui.pageno!=journal.npages-1);
1183 gtk_widget_set_sensitive(GET_COMPONENT("viewShowLayer"), ui.layerno!=ui.cur_page->nlayers-1);
1184 gtk_widget_set_sensitive(GET_COMPONENT("viewHideLayer"), ui.layerno>=0);
1186 gtk_widget_set_sensitive(GET_COMPONENT("editPaste"), ui.cur_layer!=NULL);
1187 gtk_widget_set_sensitive(GET_COMPONENT("buttonPaste"), ui.cur_layer!=NULL);
1190 void update_toolbar_and_menu(void)
1192 update_tool_buttons(); // takes care of other toolbar buttons as well
1194 update_color_menu();
1195 update_pen_props_menu();
1196 update_eraser_props_menu();
1197 update_highlighter_props_menu();
1198 update_mappings_menu();
1200 gtk_toggle_tool_button_set_active(
1201 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonFullscreen")), ui.fullscreen);
1202 gtk_check_menu_item_set_active(
1203 GTK_CHECK_MENU_ITEM(GET_COMPONENT("viewFullscreen")), ui.fullscreen);
1206 void update_file_name(char *filename)
1209 if (ui.filename != NULL) g_free(ui.filename);
1210 ui.filename = filename;
1211 if (filename == NULL) {
1212 gtk_window_set_title(GTK_WINDOW (winMain), "Xournal");
1215 p = g_utf8_strrchr(filename, -1, '/');
1216 if (p == NULL) p = filename;
1217 else p = g_utf8_next_char(p);
1218 g_snprintf(tmp, 100, "Xournal - %s", p);
1219 gtk_window_set_title(GTK_WINDOW (winMain), tmp);
1220 new_mru_entry(filename);
1223 void update_undo_redo_enabled(void)
1225 gtk_widget_set_sensitive(GET_COMPONENT("editUndo"), undo!=NULL);
1226 gtk_widget_set_sensitive(GET_COMPONENT("editRedo"), redo!=NULL);
1227 gtk_widget_set_sensitive(GET_COMPONENT("buttonUndo"), undo!=NULL);
1228 gtk_widget_set_sensitive(GET_COMPONENT("buttonRedo"), redo!=NULL);
1231 void update_copy_paste_enabled(void)
1233 gtk_widget_set_sensitive(GET_COMPONENT("editCut"), ui.selection!=NULL);
1234 gtk_widget_set_sensitive(GET_COMPONENT("editCopy"), ui.selection!=NULL);
1235 gtk_widget_set_sensitive(GET_COMPONENT("editDelete"), ui.selection!=NULL);
1236 gtk_widget_set_sensitive(GET_COMPONENT("buttonCut"), ui.selection!=NULL);
1237 gtk_widget_set_sensitive(GET_COMPONENT("buttonCopy"), ui.selection!=NULL);
1240 void update_mapping_linkings(int toolno)
1244 for (i = 1; i<=NUM_BUTTONS; i++) {
1245 if (ui.linked_brush[i] == BRUSH_LINKED) {
1246 if (toolno >= 0 && toolno < NUM_STROKE_TOOLS)
1247 g_memmove(&(ui.brushes[i][toolno]), &(ui.brushes[0][toolno]), sizeof(struct Brush));
1248 ui.ruler[i] = ui.ruler[0];
1249 if (ui.toolno[i]!=TOOL_PEN && ui.toolno[i]!=TOOL_HIGHLIGHTER)
1250 ui.ruler[i] = FALSE;
1252 if (ui.linked_brush[i] == BRUSH_COPIED && toolno == ui.toolno[i]) {
1253 ui.linked_brush[i] = BRUSH_STATIC;
1254 if (i==1 || i==2) update_mappings_menu_linkings();
1259 void set_cur_color(int color)
1261 ui.cur_brush->color_no = color;
1262 if (ui.toolno[0] == TOOL_HIGHLIGHTER)
1263 ui.cur_brush->color_rgba = predef_colors_rgba[color] & HILITER_ALPHA_MASK;
1265 ui.cur_brush->color_rgba = predef_colors_rgba[color];
1266 update_mapping_linkings(ui.toolno[0]);
1269 void process_color_activate(GtkMenuItem *menuitem, int color)
1271 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1272 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1275 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1279 if (ui.cur_mapping != 0) return; // not user-generated
1281 if (ui.selection != NULL) {
1282 recolor_selection(color);
1283 update_color_buttons();
1284 update_color_menu();
1287 if (ui.toolno[0] != TOOL_PEN && ui.toolno[0] != TOOL_HIGHLIGHTER) {
1288 if (ui.selection != NULL) return;
1289 ui.toolno[0] = TOOL_PEN;
1290 ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
1291 update_tool_buttons();
1295 set_cur_color(color);
1296 update_color_buttons();
1297 update_color_menu();
1301 void process_thickness_activate(GtkMenuItem *menuitem, int tool, int val)
1303 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1304 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1307 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1311 if (ui.cur_mapping != 0) return; // not user-generated
1313 if (ui.selection != NULL && GTK_OBJECT_TYPE(menuitem) != GTK_TYPE_RADIO_MENU_ITEM) {
1314 rethicken_selection(val);
1315 update_thickness_buttons();
1318 if (tool >= NUM_STROKE_TOOLS) {
1319 update_thickness_buttons(); // undo illegal button selection
1323 ui.brushes[0][tool].thickness_no = val;
1324 ui.brushes[0][tool].thickness = predef_thickness[tool][val];
1325 update_mapping_linkings(tool);
1327 update_thickness_buttons();
1328 if (tool == TOOL_PEN) update_pen_props_menu();
1329 if (tool == TOOL_ERASER) update_eraser_props_menu();
1330 if (tool == TOOL_HIGHLIGHTER) update_highlighter_props_menu();
1334 void process_papercolor_activate(GtkMenuItem *menuitem, int color)
1340 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1343 if ((ui.cur_page->bg->type != BG_SOLID) || ui.bg_apply_all_pages)
1344 gtk_check_menu_item_set_active(
1345 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorNA")), TRUE);
1349 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
1350 if (ui.bg_apply_all_pages) pg = (struct Page *)pglist->data;
1351 if (pg->bg->type == BG_SOLID && pg->bg->color_no != color) {
1353 if (hasdone) undo->multiop |= MULTIOP_CONT_UNDO;
1354 undo->multiop |= MULTIOP_CONT_REDO;
1356 undo->type = ITEM_NEW_BG_ONE;
1358 undo->bg = (struct Background *)g_memdup(pg->bg, sizeof(struct Background));
1359 undo->bg->canvas_item = NULL;
1361 pg->bg->color_no = color;
1362 pg->bg->color_rgba = predef_bgcolors_rgba[color];
1363 update_canvas_bg(pg);
1365 if (!ui.bg_apply_all_pages) break;
1367 if (hasdone) undo->multiop -= MULTIOP_CONT_REDO;
1370 void process_paperstyle_activate(GtkMenuItem *menuitem, int style)
1374 gboolean hasdone, must_upd;
1376 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1379 if (ui.bg_apply_all_pages)
1380 gtk_check_menu_item_set_active(
1381 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstyleNA")), TRUE);
1386 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
1387 if (ui.bg_apply_all_pages) pg = (struct Page *)pglist->data;
1388 if (pg->bg->type != BG_SOLID || pg->bg->ruling != style) {
1390 undo->type = ITEM_NEW_BG_ONE;
1391 if (hasdone) undo->multiop |= MULTIOP_CONT_UNDO;
1392 undo->multiop |= MULTIOP_CONT_REDO;
1395 undo->bg = (struct Background *)g_memdup(pg->bg, sizeof(struct Background));
1396 undo->bg->canvas_item = NULL;
1398 if (pg->bg->type != BG_SOLID) {
1399 pg->bg->type = BG_SOLID;
1400 pg->bg->color_no = COLOR_WHITE;
1401 pg->bg->color_rgba = predef_bgcolors_rgba[COLOR_WHITE];
1402 pg->bg->filename = NULL;
1403 pg->bg->pixbuf = NULL;
1406 pg->bg->ruling = style;
1407 update_canvas_bg(pg);
1409 if (!ui.bg_apply_all_pages) break;
1411 if (hasdone) undo->multiop -= MULTIOP_CONT_REDO;
1412 if (must_upd) update_page_stuff();
1415 gboolean ok_to_close(void)
1418 GtkResponseType response;
1421 if (ui.saved) return TRUE;
1422 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
1423 GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, "Save changes to '%s'?",
1424 (ui.filename!=NULL) ? ui.filename:"Untitled");
1425 gtk_dialog_add_button(GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
1426 response = gtk_dialog_run(GTK_DIALOG (dialog));
1427 gtk_widget_destroy(dialog);
1428 if (response == GTK_RESPONSE_CANCEL || response == GTK_RESPONSE_DELETE_EVENT)
1429 return FALSE; // aborted
1430 if (response == GTK_RESPONSE_YES) {
1431 on_fileSave_activate(NULL, NULL);
1432 if (!ui.saved) return FALSE; // if save failed, then we abort
1437 // test if we're still busy loading a PDF background file
1438 gboolean page_ops_forbidden(void)
1440 return (bgpdf.status != STATUS_NOT_INIT && bgpdf.create_pages);
1443 // selection / clipboard stuff
1445 void reset_selection(void)
1447 if (ui.selection == NULL) return;
1448 if (ui.selection->canvas_item != NULL)
1449 gtk_object_destroy(GTK_OBJECT(ui.selection->canvas_item));
1450 g_list_free(ui.selection->items);
1451 g_free(ui.selection);
1452 ui.selection = NULL;
1453 update_copy_paste_enabled();
1454 update_color_menu();
1455 update_thickness_buttons();
1456 update_color_buttons();
1459 void move_journal_items_by(GList *itemlist, double dx, double dy,
1460 struct Layer *l1, struct Layer *l2, GList *depths)
1463 GnomeCanvasItem *refitem;
1468 while (itemlist!=NULL) {
1469 item = (struct Item *)itemlist->data;
1470 if (item->type == ITEM_STROKE) {
1471 for (pt=item->path->coords, i=0; i<item->path->num_points; i++, pt+=2)
1472 { pt[0] += dx; pt[1] += dy; }
1473 item->bbox.left += dx;
1474 item->bbox.right += dx;
1475 item->bbox.top += dy;
1476 item->bbox.bottom += dy;
1479 // find out where to insert
1480 if (depths != NULL) {
1481 if (depths->data == NULL) link = l2->items;
1483 link = g_list_find(l2->items, depths->data);
1484 if (link != NULL) link = link->next;
1487 l2->items = g_list_insert_before(l2->items, link, item);
1489 l1->items = g_list_remove(l1->items, item);
1492 if (depths != NULL) { // also raise/lower the canvas items
1493 if (item->canvas_item!=NULL) {
1494 if (depths->data == NULL) link = NULL;
1495 else link = g_list_find(l2->items, depths->data);
1496 if (link != NULL) refitem = ((struct Item *)(link->data))->canvas_item;
1497 else refitem = NULL;
1498 lower_canvas_item_to(l2->group, item->canvas_item, refitem);
1500 depths = depths->next;
1502 itemlist = itemlist->next;
1506 // Switch between button mappings
1508 /* NOTE ABOUT BUTTON MAPPINGS: ui.cur_mapping is 0 except while a canvas
1509 click event is being processed ... */
1511 void switch_mapping(int m)
1513 if (ui.cur_mapping == m) return;
1516 if (ui.toolno[m] < NUM_STROKE_TOOLS)
1517 ui.cur_brush = &(ui.brushes[m][ui.toolno[m]]);
1518 update_tool_buttons();
1519 update_color_menu();
1523 void process_mapping_activate(GtkMenuItem *menuitem, int m, int tool)
1525 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
1526 if (ui.cur_mapping!=0) return;
1527 if (ui.toolno[m] == tool) return;
1528 ui.toolno[m] = tool;
1529 ui.ruler[m] = FALSE;
1530 if (ui.linked_brush[m] == BRUSH_LINKED
1531 && (tool==TOOL_PEN || tool==TOOL_HIGHLIGHTER))
1532 ui.ruler[m] = ui.ruler[0];
1533 if (ui.linked_brush[m] == BRUSH_COPIED) {
1534 ui.linked_brush[m] = BRUSH_STATIC;
1535 update_mappings_menu_linkings();
1539 // update the ordering of components in the main vbox
1541 const char *vbox_component_names[VBOX_MAIN_NITEMS]=
1542 {"scrolledwindowMain", "menubar", "toolbarMain", "toolbarPen", "hbox1"};
1544 void update_vbox_order(int *order)
1548 GtkBox *vboxMain = GTK_BOX(GET_COMPONENT("vboxMain"));
1549 gboolean present[VBOX_MAIN_NITEMS];
1551 for (i=0; i<VBOX_MAIN_NITEMS; i++) present[i] = FALSE;
1553 for (i=0; i<VBOX_MAIN_NITEMS; i++) {
1554 if (order[i]<0 || order[i]>=VBOX_MAIN_NITEMS) continue;
1555 present[order[i]] = TRUE;
1556 child = GET_COMPONENT(vbox_component_names[order[i]]);
1557 gtk_box_reorder_child(vboxMain, child, j++);
1558 gtk_widget_show(child);
1560 for (i=1; i<VBOX_MAIN_NITEMS; i++) // hide others, but not the drawing area!
1561 if (!present[i]) gtk_widget_hide(GET_COMPONENT(vbox_component_names[i]));