1 // comment out the line below if you want the thickness settings of v 0.2
11 #include <libgnomecanvas/libgnomecanvas.h>
14 #include "xo-interface.h"
15 #include "xo-support.h"
16 #include "xo-callbacks.h"
21 // some global constants
23 guint predef_colors_rgba[COLOR_MAX] =
24 { 0x000000ff, 0x3333ccff, 0xff0000ff, 0x008000ff,
25 0x808080ff, 0x00c0ffff, 0x00ff00ff, 0xff00ffff,
26 0xff8000ff, 0xffff00ff, 0xffffffff };
28 guint predef_bgcolors_rgba[COLOR_MAX] = // meaningless ones set to white
29 { 0xffffffff, 0xa0e8ffff, 0xffc0d4ff, 0x80ffc0ff,
30 0xffffffff, 0xa0e8ffff, 0x80ffc0ff, 0xffc0d4ff,
31 0xffc080ff, 0xffff80ff, 0xffffffff };
34 double predef_thickness[NUM_STROKE_TOOLS][THICKNESS_MAX] =
35 { { 0.42, 0.85, 1.41, 2.26, 5.67 }, // pen thicknesses = 0.15, 0.3, 0.5, 0.8, 2 mm
36 { 2.83, 2.83, 8.50, 19.84, 19.84 }, // eraser thicknesses = 1, 2.5, 5 mm
37 { 2.83, 2.83, 8.50, 19.84, 19.84 }, // highlighter thicknesses = 1, 2.5, 5 mm
40 double predef_thickness[NUM_STROKE_TOOLS][THICKNESS_MAX] =
41 { { 0.42, 0.85, 1.41, 2.26, 5.67 }, // pen thicknesses = 0.15, 0.3, 0.5, 0.8, 2 mm
42 { 2.83, 2.83, 7.08, 14.17, 14.17 }, // eraser thicknesses = 1, 2.5, 5 mm
43 { 2.83, 2.83, 7.08, 14.17, 14.17 }, // highlighter thicknesses = 1, 2.5, 5 mm
47 // some manipulation functions
49 struct Page *new_page(struct Page *template)
51 struct Page *pg = (struct Page *) g_memdup(template, sizeof(struct Page));
52 struct Layer *l = g_new(struct Layer, 1);
56 pg->layers = g_list_append(NULL, l);
58 pg->bg = (struct Background *)g_memdup(template->bg, sizeof(struct Background));
59 pg->bg->canvas_item = NULL;
60 if (pg->bg->type == BG_PIXMAP || pg->bg->type == BG_PDF) {
61 gdk_pixbuf_ref(pg->bg->pixbuf);
62 refstring_ref(pg->bg->filename);
64 pg->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
65 gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
66 make_page_clipbox(pg);
68 l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
69 pg->group, gnome_canvas_group_get_type(), NULL);
74 /* Create a page from a background.
75 Note: bg should be an UNREFERENCED background.
76 If needed, first duplicate it and increase the refcount of the pixbuf.
78 struct Page *new_page_with_bg(struct Background *bg, double width, double height)
80 struct Page *pg = g_new(struct Page, 1);
81 struct Layer *l = g_new(struct Layer, 1);
85 pg->layers = g_list_append(NULL, l);
88 pg->bg->canvas_item = NULL;
91 pg->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
92 gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
93 make_page_clipbox(pg);
95 l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
96 pg->group, gnome_canvas_group_get_type(), NULL);
101 void realloc_cur_path(int n)
103 if (n <= ui.cur_path_storage_alloc) return;
104 ui.cur_path_storage_alloc = n+10;
105 ui.cur_path.coords = g_realloc(ui.cur_path.coords, 2*(n+10)*sizeof(double));
108 // undo utility functions
110 void prepare_new_undo(void)
113 // add a new UndoItem on the stack
114 u = (struct UndoItem *)g_malloc(sizeof(struct UndoItem));
122 void clear_redo_stack(void)
126 struct UndoErasureData *erasure;
129 /* Warning: the redo items might reference items from past redo entries,
130 which have been destroyed before them. Be careful! As a rule, it's
131 safe to destroy data which has been created at the current history step,
132 it's unsafe to refer to any data from previous history steps */
135 if (redo->type == ITEM_STROKE) {
136 gnome_canvas_points_free(redo->item->path);
138 /* the strokes are unmapped, so there are no associated canvas items */
140 else if (redo->type == ITEM_ERASURE) {
141 for (list = redo->erasurelist; list!=NULL; list=list->next) {
142 erasure = (struct UndoErasureData *)list->data;
143 for (repl = erasure->replacement_items; repl!=NULL; repl=repl->next) {
144 it = (struct Item *)repl->data;
145 gnome_canvas_points_free(it->path);
148 g_list_free(erasure->replacement_items);
151 g_list_free(redo->erasurelist);
153 else if (redo->type == ITEM_NEW_BG_ONE || redo->type == ITEM_NEW_BG_RESIZE
154 || redo->type == ITEM_NEW_DEFAULT_BG) {
155 if (redo->bg->type == BG_PIXMAP || redo->bg->type == BG_PDF) {
156 if (redo->bg->pixbuf!=NULL) gdk_pixbuf_unref(redo->bg->pixbuf);
157 refstring_unref(redo->bg->filename);
161 else if (redo->type == ITEM_NEW_PAGE) {
162 redo->page->group = NULL;
163 delete_page(redo->page);
165 else if (redo->type == ITEM_MOVESEL || redo->type == ITEM_REPAINTSEL) {
166 g_list_free(redo->itemlist); g_list_free(redo->auxlist);
168 else if (redo->type == ITEM_PASTE) {
169 for (list = redo->itemlist; list!=NULL; list=list->next) {
170 it = (struct Item *)list->data;
171 if (it->type == ITEM_STROKE) gnome_canvas_points_free(it->path);
174 g_list_free(redo->itemlist);
176 else if (redo->type == ITEM_NEW_LAYER) {
184 update_undo_redo_enabled();
187 void clear_undo_stack(void)
191 struct UndoErasureData *erasure;
194 // for strokes, items are already in the journal, so we don't free them
195 // for erasures, we need to free the dead items
196 if (undo->type == ITEM_ERASURE) {
197 for (list = undo->erasurelist; list!=NULL; list=list->next) {
198 erasure = (struct UndoErasureData *)list->data;
199 gnome_canvas_points_free(erasure->item->path);
200 g_free(erasure->item);
201 g_list_free(erasure->replacement_items);
204 g_list_free(undo->erasurelist);
206 else if (undo->type == ITEM_NEW_BG_ONE || undo->type == ITEM_NEW_BG_RESIZE
207 || undo->type == ITEM_NEW_DEFAULT_BG) {
208 if (undo->bg->type == BG_PIXMAP || undo->bg->type == BG_PDF) {
209 if (undo->bg->pixbuf!=NULL) gdk_pixbuf_unref(undo->bg->pixbuf);
210 refstring_unref(undo->bg->filename);
214 else if (undo->type == ITEM_MOVESEL || undo->type == ITEM_REPAINTSEL) {
215 g_list_free(undo->itemlist); g_list_free(undo->auxlist);
217 else if (undo->type == ITEM_PASTE) {
218 g_list_free(undo->itemlist);
220 else if (undo->type == ITEM_DELETE_LAYER) {
221 undo->layer->group = NULL;
222 delete_layer(undo->layer);
224 else if (undo->type == ITEM_DELETE_PAGE) {
225 undo->page->group = NULL;
226 delete_page(undo->page);
233 update_undo_redo_enabled();
236 // free data structures
238 void delete_journal(struct Journal *j)
240 while (j->pages!=NULL) {
241 delete_page((struct Page *)j->pages->data);
242 j->pages = g_list_delete_link(j->pages, j->pages);
246 void delete_page(struct Page *pg)
250 while (pg->layers!=NULL) {
251 l = (struct Layer *)pg->layers->data;
254 pg->layers = g_list_delete_link(pg->layers, pg->layers);
256 if (pg->group!=NULL) gtk_object_destroy(GTK_OBJECT(pg->group));
257 // this also destroys the background's canvas items
258 if (pg->bg->type == BG_PIXMAP || pg->bg->type == BG_PDF) {
259 if (pg->bg->pixbuf != NULL) gdk_pixbuf_unref(pg->bg->pixbuf);
260 if (pg->bg->filename != NULL) refstring_unref(pg->bg->filename);
266 void delete_layer(struct Layer *l)
270 while (l->items!=NULL) {
271 item = (struct Item *)l->items->data;
272 if (item->type == ITEM_STROKE && item->path != NULL)
273 gnome_canvas_points_free(item->path);
274 // don't need to delete the canvas_item, as it's part of the group destroyed below
276 l->items = g_list_delete_link(l->items, l->items);
278 if (l->group!= NULL) gtk_object_destroy(GTK_OBJECT(l->group));
282 // referenced strings
284 struct Refstring *new_refstring(const char *s)
286 struct Refstring *rs = g_new(struct Refstring, 1);
288 if (s!=NULL) rs->s = g_strdup(s);
294 struct Refstring *refstring_ref(struct Refstring *rs)
300 void refstring_unref(struct Refstring *rs)
304 if (rs->s!=NULL) g_free(rs->s);
305 if (rs->aux!=NULL) g_free(rs->aux);
311 // some helper functions
313 void get_pointer_coords(GdkEvent *event, gdouble *ret)
316 gdk_event_get_coords(event, &x, &y);
317 gnome_canvas_window_to_world(canvas, x, y, ret, ret+1);
318 ret[0] -= ui.cur_page->hoffset;
319 ret[1] -= ui.cur_page->voffset;
322 void fix_xinput_coords(GdkEvent *event)
324 double *axes, *px, *py, axis_width;
328 if (event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) {
329 axes = event->button.axes;
330 px = &(event->button.x);
331 py = &(event->button.y);
332 device = event->button.device;
334 else if (event->type == GDK_MOTION_NOTIFY) {
335 axes = event->motion.axes;
336 px = &(event->motion.x);
337 py = &(event->motion.y);
338 device = event->motion.device;
340 else return; // nothing we know how to do
342 gdk_window_get_origin(event->any.window, &wx, &wy);
343 gnome_canvas_get_scroll_offsets(canvas, &sx, &sy);
345 axis_width = device->axes[0].max - device->axes[0].min;
346 if (axis_width>EPSILON)
347 *px = (axes[0]/axis_width)*ui.screen_width + sx - wx;
349 axis_width = device->axes[1].max - device->axes[1].min;
350 if (axis_width>EPSILON)
351 *py = (axes[1]/axis_width)*ui.screen_height + sy - wy;
354 void update_item_bbox(struct Item *item)
359 if (item->type == ITEM_STROKE) {
360 item->bbox.left = item->bbox.right = item->path->coords[0];
361 item->bbox.top = item->bbox.bottom = item->path->coords[1];
362 for (i=1, p=item->path->coords+2; i<item->path->num_points; i++, p+=2)
364 if (p[0] < item->bbox.left) item->bbox.left = p[0];
365 if (p[0] > item->bbox.right) item->bbox.right = p[0];
366 if (p[1] < item->bbox.top) item->bbox.top = p[1];
367 if (p[1] > item->bbox.bottom) item->bbox.bottom = p[1];
372 void make_page_clipbox(struct Page *pg)
374 GnomeCanvasPathDef *pg_clip;
376 pg_clip = gnome_canvas_path_def_new_sized(4);
377 gnome_canvas_path_def_moveto(pg_clip, 0., 0.);
378 gnome_canvas_path_def_lineto(pg_clip, 0., pg->height);
379 gnome_canvas_path_def_lineto(pg_clip, pg->width, pg->height);
380 gnome_canvas_path_def_lineto(pg_clip, pg->width, 0.);
381 gnome_canvas_path_def_closepath(pg_clip);
382 gnome_canvas_item_set(GNOME_CANVAS_ITEM(pg->group), "path", pg_clip, NULL);
383 gnome_canvas_path_def_unref(pg_clip);
386 void make_canvas_items(void)
391 GList *pagelist, *layerlist, *itemlist;
393 for (pagelist = journal.pages; pagelist!=NULL; pagelist = pagelist->next) {
394 pg = (struct Page *)pagelist->data;
395 if (pg->group == NULL) {
396 pg->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
397 gnome_canvas_root(canvas), gnome_canvas_clipgroup_get_type(), NULL);
398 make_page_clipbox(pg);
400 if (pg->bg->canvas_item == NULL) update_canvas_bg(pg);
401 for (layerlist = pg->layers; layerlist!=NULL; layerlist = layerlist->next) {
402 l = (struct Layer *)layerlist->data;
403 if (l->group == NULL)
404 l->group = (GnomeCanvasGroup *) gnome_canvas_item_new(
405 pg->group, gnome_canvas_group_get_type(), NULL);
406 for (itemlist = l->items; itemlist!=NULL; itemlist = itemlist->next) {
407 item = (struct Item *)itemlist->data;
408 if (item->type == ITEM_STROKE && item->canvas_item == NULL) {
409 item->canvas_item = gnome_canvas_item_new(l->group,
410 gnome_canvas_line_get_type(), "points", item->path,
411 "cap-style", GDK_CAP_ROUND, "join-style", GDK_JOIN_ROUND,
412 "fill-color-rgba", item->brush.color_rgba,
413 "width-units", item->brush.thickness, NULL);
420 void update_canvas_bg(struct Page *pg)
422 GnomeCanvasGroup *group;
423 GnomeCanvasPoints *seg;
424 GdkPixbuf *scaled_pix;
429 if (pg->bg->canvas_item != NULL)
430 gtk_object_destroy(GTK_OBJECT(pg->bg->canvas_item));
431 pg->bg->canvas_item = NULL;
433 if (pg->bg->type == BG_SOLID)
435 pg->bg->canvas_item = gnome_canvas_item_new(pg->group,
436 gnome_canvas_group_get_type(), NULL);
437 group = GNOME_CANVAS_GROUP(pg->bg->canvas_item);
438 lower_canvas_item_to(pg->group, pg->bg->canvas_item, NULL);
439 gnome_canvas_item_new(group, gnome_canvas_rect_get_type(),
440 "x1", 0., "x2", pg->width, "y1", 0., "y2", pg->height,
441 "fill-color-rgba", pg->bg->color_rgba, NULL);
442 if (pg->bg->ruling == RULING_NONE) return;
443 seg = gnome_canvas_points_new(2);
445 if (pg->bg->ruling == RULING_GRAPH) {
446 pt[1] = 0; pt[3] = pg->height;
447 for (x=RULING_GRAPHSPACING; x<pg->width-1; x+=RULING_GRAPHSPACING) {
449 gnome_canvas_item_new(group, gnome_canvas_line_get_type(),
450 "points", seg, "fill-color-rgba", RULING_COLOR,
451 "width-units", RULING_THICKNESS, NULL);
453 pt[0] = 0; pt[2] = pg->width;
454 for (y=RULING_GRAPHSPACING; y<pg->height-1; y+=RULING_GRAPHSPACING) {
456 gnome_canvas_item_new(group, gnome_canvas_line_get_type(),
457 "points", seg, "fill-color-rgba", RULING_COLOR,
458 "width-units", RULING_THICKNESS, NULL);
460 gnome_canvas_points_free(seg);
463 pt[0] = 0; pt[2] = pg->width;
464 for (y=RULING_TOPMARGIN; y<pg->height-1; y+=RULING_SPACING) {
466 gnome_canvas_item_new(group, gnome_canvas_line_get_type(),
467 "points", seg, "fill-color-rgba", RULING_COLOR,
468 "width-units", RULING_THICKNESS, NULL);
470 if (pg->bg->ruling == RULING_LINED) {
471 pt[0] = pt[2] = RULING_LEFTMARGIN;
472 pt[1] = 0; pt[3] = pg->height;
473 gnome_canvas_item_new(group, gnome_canvas_line_get_type(),
474 "points", seg, "fill-color-rgba", RULING_MARGIN_COLOR,
475 "width-units", RULING_THICKNESS, NULL);
477 gnome_canvas_points_free(seg);
481 if (pg->bg->type == BG_PIXMAP)
483 if (ui.antialias_bg) {
484 set_cursor_busy(TRUE);
485 w = (int)floor(pg->width*ui.zoom+0.5);
486 h = (int)floor(pg->height*ui.zoom+0.5);
487 if (w == gdk_pixbuf_get_width(pg->bg->pixbuf) &&
488 h == gdk_pixbuf_get_height(pg->bg->pixbuf))
489 scaled_pix = gdk_pixbuf_ref(pg->bg->pixbuf);
491 scaled_pix = gdk_pixbuf_scale_simple(pg->bg->pixbuf, w, h, GDK_INTERP_BILINEAR);
492 pg->bg->pixbuf_scale = ui.zoom;
493 set_cursor_busy(FALSE);
496 scaled_pix = gdk_pixbuf_ref(pg->bg->pixbuf);
497 pg->bg->pixbuf_scale = 0;
499 pg->bg->canvas_item = gnome_canvas_item_new(pg->group,
500 gnome_canvas_pixbuf_get_type(),
501 "pixbuf", scaled_pix,
502 "width", pg->width, "height", pg->height,
503 "width-set", TRUE, "height-set", TRUE,
505 gdk_pixbuf_unref(scaled_pix);
506 lower_canvas_item_to(pg->group, pg->bg->canvas_item, NULL);
509 if (pg->bg->type == BG_PDF)
511 if (pg->bg->pixbuf == NULL) return;
512 pg->bg->canvas_item = gnome_canvas_item_new(pg->group,
513 gnome_canvas_pixbuf_get_type(),
514 "pixbuf", pg->bg->pixbuf,
515 "width", pg->width, "height", pg->height,
516 "width-set", TRUE, "height-set", TRUE,
518 lower_canvas_item_to(pg->group, pg->bg->canvas_item, NULL);
523 gboolean is_visible(struct Page *pg)
525 GtkAdjustment *v_adj;
528 if (!ui.view_continuous) return (pg == ui.cur_page);
529 v_adj = gtk_layout_get_vadjustment(GTK_LAYOUT(canvas));
530 ytop = v_adj->value/ui.zoom;
531 ybot = (v_adj->value + v_adj->page_size) / ui.zoom;
532 return (MAX(ytop, pg->voffset) < MIN(ybot, pg->voffset+pg->height));
535 void rescale_bg_pixmaps(void)
541 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
542 pg = (struct Page *)pglist->data;
543 // in progressive mode we scale only visible pages
544 if (ui.progressive_bg && !is_visible(pg)) continue;
546 if (pg->bg->type == BG_PIXMAP) { // do the rescaling ourselves
547 if (ui.antialias_bg) {
548 if (pg->bg->pixbuf_scale == ui.zoom) continue;
549 set_cursor_busy(TRUE);
550 pix = gdk_pixbuf_scale_simple(pg->bg->pixbuf,
551 (int)floor(pg->width*ui.zoom+0.5), (int)floor(pg->height*ui.zoom+0.5),
552 GDK_INTERP_BILINEAR);
553 gnome_canvas_item_set(pg->bg->canvas_item, "pixbuf", pix, NULL);
554 gdk_pixbuf_unref(pix);
555 pg->bg->pixbuf_scale = ui.zoom;
556 set_cursor_busy(FALSE);
559 pix = GDK_PIXBUF(g_object_get_data(G_OBJECT(pg->bg->canvas_item), "pixbuf"));
560 if (pix!=pg->bg->pixbuf)
561 gnome_canvas_item_set(pg->bg->canvas_item, "pixbuf", pg->bg->pixbuf, NULL);
562 pg->bg->pixbuf_scale = 0;
565 if (pg->bg->type == BG_PDF) { // request an asynchronous update
566 if (pg->bg->pixbuf_scale == ui.zoom) continue;
567 add_bgpdf_request(pg->bg->file_page_seq, ui.zoom, FALSE);
568 pg->bg->pixbuf_scale = ui.zoom;
573 gboolean have_intersect(struct BBox *a, struct BBox *b)
575 return (MAX(a->top, b->top) <= MIN(a->bottom, b->bottom)) &&
576 (MAX(a->left, b->left) <= MIN(a->right, b->right));
579 /* In libgnomecanvas 2.10.0, the lower/raise functions fail to update
580 correctly the end of the group's item list. We try to work around this.
581 DON'T USE gnome_canvas_item_raise/lower directly !! */
583 void lower_canvas_item_to(GnomeCanvasGroup *g, GnomeCanvasItem *item, GnomeCanvasItem *after)
587 i1 = g_list_index(g->item_list, item);
588 if (i1 == -1) return;
590 if (after == NULL) i2 = -1;
591 else i2 = g_list_index(g->item_list, after);
593 if (i1 < i2) gnome_canvas_item_raise(item, i2-i1);
594 if (i1 > i2+1) gnome_canvas_item_lower(item, i1-i2-1);
596 // BUGFIX for libgnomecanvas
597 g->item_list_end = g_list_last(g->item_list);
600 // some interface functions
602 void update_thickness_buttons(void)
604 if (ui.selection!=NULL || ui.toolno[ui.cur_mapping] >= NUM_STROKE_TOOLS) {
605 gtk_toggle_tool_button_set_active(
606 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonThicknessOther")), TRUE);
608 switch (ui.cur_brush->thickness_no) {
610 gtk_toggle_tool_button_set_active(
611 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonFine")), TRUE);
613 case THICKNESS_MEDIUM:
614 gtk_toggle_tool_button_set_active(
615 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonMedium")), TRUE);
617 case THICKNESS_THICK:
618 gtk_toggle_tool_button_set_active(
619 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonThick")), TRUE);
622 gtk_toggle_tool_button_set_active(
623 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonThicknessOther")), TRUE);
627 void update_color_buttons(void)
629 if (ui.selection!=NULL || (ui.toolno[ui.cur_mapping] != TOOL_PEN
630 && ui.toolno[ui.cur_mapping] != TOOL_HIGHLIGHTER)) {
631 gtk_toggle_tool_button_set_active(
632 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonColorOther")), TRUE);
634 switch (ui.cur_brush->color_no) {
636 gtk_toggle_tool_button_set_active(
637 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonBlack")), TRUE);
640 gtk_toggle_tool_button_set_active(
641 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonBlue")), TRUE);
644 gtk_toggle_tool_button_set_active(
645 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonRed")), TRUE);
648 gtk_toggle_tool_button_set_active(
649 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonGreen")), TRUE);
652 gtk_toggle_tool_button_set_active(
653 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonGray")), TRUE);
655 case COLOR_LIGHTBLUE:
656 gtk_toggle_tool_button_set_active(
657 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonLightBlue")), TRUE);
659 case COLOR_LIGHTGREEN:
660 gtk_toggle_tool_button_set_active(
661 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonLightGreen")), TRUE);
664 gtk_toggle_tool_button_set_active(
665 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonMagenta")), TRUE);
668 gtk_toggle_tool_button_set_active(
669 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonOrange")), TRUE);
672 gtk_toggle_tool_button_set_active(
673 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonYellow")), TRUE);
676 gtk_toggle_tool_button_set_active(
677 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonWhite")), TRUE);
680 gtk_toggle_tool_button_set_active(
681 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonColorOther")), TRUE);
685 void update_tool_buttons(void)
687 switch(ui.toolno[ui.cur_mapping]) {
689 gtk_toggle_tool_button_set_active(
690 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonPen")), TRUE);
693 gtk_toggle_tool_button_set_active(
694 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonEraser")), TRUE);
696 case TOOL_HIGHLIGHTER:
697 gtk_toggle_tool_button_set_active(
698 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonHighlighter")), TRUE);
701 gtk_toggle_tool_button_set_active(
702 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonText")), TRUE);
704 case TOOL_SELECTREGION:
705 gtk_toggle_tool_button_set_active(
706 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonSelectRegion")), TRUE);
708 case TOOL_SELECTRECT:
709 gtk_toggle_tool_button_set_active(
710 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonSelectRectangle")), TRUE);
713 gtk_toggle_tool_button_set_active(
714 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonVerticalSpace")), TRUE);
717 gtk_toggle_tool_button_set_active(
718 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonHand")), TRUE);
722 gtk_toggle_tool_button_set_active(
723 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonRuler")), ui.ruler[ui.cur_mapping]);
724 update_thickness_buttons();
725 update_color_buttons();
728 void update_tool_menu(void)
730 switch(ui.toolno[0]) {
732 gtk_check_menu_item_set_active(
733 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsPen")), TRUE);
736 gtk_check_menu_item_set_active(
737 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsEraser")), TRUE);
739 case TOOL_HIGHLIGHTER:
740 gtk_check_menu_item_set_active(
741 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsHighlighter")), TRUE);
744 gtk_check_menu_item_set_active(
745 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsText")), TRUE);
747 case TOOL_SELECTREGION:
748 gtk_check_menu_item_set_active(
749 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsSelectRegion")), TRUE);
751 case TOOL_SELECTRECT:
752 gtk_check_menu_item_set_active(
753 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsSelectRectangle")), TRUE);
756 gtk_check_menu_item_set_active(
757 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsVerticalSpace")), TRUE);
760 gtk_check_menu_item_set_active(
761 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsHand")), TRUE);
765 gtk_check_menu_item_set_active(
766 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsRuler")), ui.ruler[0]);
769 void update_ruler_indicator(void)
771 gtk_toggle_tool_button_set_active(
772 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonRuler")), ui.ruler[ui.cur_mapping]);
773 gtk_check_menu_item_set_active(
774 GTK_CHECK_MENU_ITEM(GET_COMPONENT("toolsRuler")), ui.ruler[0]);
777 void update_color_menu(void)
779 if (ui.selection!=NULL || (ui.toolno[ui.cur_mapping] != TOOL_PEN
780 && ui.toolno[ui.cur_mapping] != TOOL_HIGHLIGHTER)) {
781 gtk_check_menu_item_set_active(
782 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorNA")), TRUE);
784 switch (ui.cur_brush->color_no) {
786 gtk_check_menu_item_set_active(
787 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorBlack")), TRUE);
790 gtk_check_menu_item_set_active(
791 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorBlue")), TRUE);
794 gtk_check_menu_item_set_active(
795 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorRed")), TRUE);
798 gtk_check_menu_item_set_active(
799 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorGreen")), TRUE);
802 gtk_check_menu_item_set_active(
803 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorGray")), TRUE);
805 case COLOR_LIGHTBLUE:
806 gtk_check_menu_item_set_active(
807 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorLightBlue")), TRUE);
809 case COLOR_LIGHTGREEN:
810 gtk_check_menu_item_set_active(
811 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorLightGreen")), TRUE);
814 gtk_check_menu_item_set_active(
815 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorMagenta")), TRUE);
818 gtk_check_menu_item_set_active(
819 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorOrange")), TRUE);
822 gtk_check_menu_item_set_active(
823 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorYellow")), TRUE);
826 gtk_check_menu_item_set_active(
827 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorWhite")), TRUE);
830 gtk_check_menu_item_set_active(
831 GTK_CHECK_MENU_ITEM(GET_COMPONENT("colorOther")), TRUE);
835 void update_pen_props_menu(void)
837 switch(ui.brushes[0][TOOL_PEN].thickness_no) {
838 case THICKNESS_VERYFINE:
839 gtk_check_menu_item_set_active(
840 GTK_CHECK_MENU_ITEM(GET_COMPONENT("penthicknessVeryFine")), TRUE);
843 gtk_check_menu_item_set_active(
844 GTK_CHECK_MENU_ITEM(GET_COMPONENT("penthicknessFine")), TRUE);
846 case THICKNESS_MEDIUM:
847 gtk_check_menu_item_set_active(
848 GTK_CHECK_MENU_ITEM(GET_COMPONENT("penthicknessMedium")), TRUE);
850 case THICKNESS_THICK:
851 gtk_check_menu_item_set_active(
852 GTK_CHECK_MENU_ITEM(GET_COMPONENT("penthicknessThick")), TRUE);
854 case THICKNESS_VERYTHICK:
855 gtk_check_menu_item_set_active(
856 GTK_CHECK_MENU_ITEM(GET_COMPONENT("penthicknessVeryThick")), TRUE);
861 void update_eraser_props_menu(void)
863 switch (ui.brushes[0][TOOL_ERASER].thickness_no) {
865 gtk_check_menu_item_set_active(
866 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserFine")), TRUE);
868 case THICKNESS_MEDIUM:
869 gtk_check_menu_item_set_active(
870 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserMedium")), TRUE);
872 case THICKNESS_THICK:
873 gtk_check_menu_item_set_active(
874 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserThick")), TRUE);
878 gtk_check_menu_item_set_active(
879 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserStandard")),
880 ui.brushes[0][TOOL_ERASER].tool_options == TOOLOPT_ERASER_STANDARD);
881 gtk_check_menu_item_set_active(
882 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserWhiteout")),
883 ui.brushes[0][TOOL_ERASER].tool_options == TOOLOPT_ERASER_WHITEOUT);
884 gtk_check_menu_item_set_active(
885 GTK_CHECK_MENU_ITEM(GET_COMPONENT("eraserDeleteStrokes")),
886 ui.brushes[0][TOOL_ERASER].tool_options == TOOLOPT_ERASER_STROKES);
889 void update_highlighter_props_menu(void)
891 switch (ui.brushes[0][TOOL_HIGHLIGHTER].thickness_no) {
893 gtk_check_menu_item_set_active(
894 GTK_CHECK_MENU_ITEM(GET_COMPONENT("highlighterFine")), TRUE);
896 case THICKNESS_MEDIUM:
897 gtk_check_menu_item_set_active(
898 GTK_CHECK_MENU_ITEM(GET_COMPONENT("highlighterMedium")), TRUE);
900 case THICKNESS_THICK:
901 gtk_check_menu_item_set_active(
902 GTK_CHECK_MENU_ITEM(GET_COMPONENT("highlighterThick")), TRUE);
907 void update_mappings_menu_linkings(void)
909 switch (ui.linked_brush[1]) {
911 gtk_check_menu_item_set_active(
912 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2LinkBrush")), TRUE);
915 gtk_check_menu_item_set_active(
916 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2CopyBrush")), TRUE);
919 gtk_check_menu_item_set_active(
920 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2NABrush")), TRUE);
923 switch (ui.linked_brush[2]) {
925 gtk_check_menu_item_set_active(
926 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3LinkBrush")), TRUE);
929 gtk_check_menu_item_set_active(
930 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3CopyBrush")), TRUE);
933 gtk_check_menu_item_set_active(
934 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3NABrush")), TRUE);
939 void update_mappings_menu(void)
941 gtk_check_menu_item_set_active(
942 GTK_CHECK_MENU_ITEM(GET_COMPONENT("optionsButtonMappings")), ui.use_erasertip);
944 switch(ui.toolno[1]) {
946 gtk_check_menu_item_set_active(
947 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2Pen")), TRUE);
950 gtk_check_menu_item_set_active(
951 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2Eraser")), TRUE);
953 case TOOL_HIGHLIGHTER:
954 gtk_check_menu_item_set_active(
955 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2Highlighter")), TRUE);
958 gtk_check_menu_item_set_active(
959 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2Text")), TRUE);
961 case TOOL_SELECTREGION:
962 gtk_check_menu_item_set_active(
963 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2SelectRegion")), TRUE);
965 case TOOL_SELECTRECT:
966 gtk_check_menu_item_set_active(
967 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2SelectRectangle")), TRUE);
970 gtk_check_menu_item_set_active(
971 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button2VerticalSpace")), TRUE);
974 switch(ui.toolno[2]) {
976 gtk_check_menu_item_set_active(
977 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3Pen")), TRUE);
980 gtk_check_menu_item_set_active(
981 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3Eraser")), TRUE);
983 case TOOL_HIGHLIGHTER:
984 gtk_check_menu_item_set_active(
985 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3Highlighter")), TRUE);
988 gtk_check_menu_item_set_active(
989 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3Text")), TRUE);
991 case TOOL_SELECTREGION:
992 gtk_check_menu_item_set_active(
993 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3SelectRegion")), TRUE);
995 case TOOL_SELECTRECT:
996 gtk_check_menu_item_set_active(
997 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3SelectRectangle")), TRUE);
1000 gtk_check_menu_item_set_active(
1001 GTK_CHECK_MENU_ITEM(GET_COMPONENT("button3VerticalSpace")), TRUE);
1004 update_mappings_menu_linkings();
1007 void do_switch_page(int pg, gboolean rescroll, gboolean refresh_all)
1010 struct Layer *layer;
1015 /* re-show all the layers of the old page */
1016 if (ui.cur_page != NULL)
1017 for (i=0, list = ui.cur_page->layers; list!=NULL; i++, list = list->next) {
1018 layer = (struct Layer *)list->data;
1019 if (layer->group!=NULL)
1020 gnome_canvas_item_show(GNOME_CANVAS_ITEM(layer->group));
1023 ui.cur_page = g_list_nth_data(journal.pages, ui.pageno);
1024 ui.layerno = ui.cur_page->nlayers-1;
1025 ui.cur_layer = (struct Layer *)(g_list_last(ui.cur_page->layers)->data);
1026 update_page_stuff();
1027 if (ui.progressive_bg) rescale_bg_pixmaps();
1029 if (rescroll) { // scroll and force a refresh
1030 gtk_adjustment_set_value(gtk_layout_get_vadjustment(GTK_LAYOUT(canvas)),
1031 ui.cur_page->voffset*ui.zoom);
1033 gnome_canvas_set_pixels_per_unit(canvas, ui.zoom);
1034 else if (!ui.view_continuous)
1035 gnome_canvas_item_move(GNOME_CANVAS_ITEM(ui.cur_page->group), 0., 0.);
1039 void update_page_stuff(void)
1042 GtkComboBox *layerbox;
1045 GtkSpinButton *spin;
1047 double vertpos, maxwidth;
1048 struct Layer *layer;
1051 // move the page groups to their rightful locations or hide them
1052 if (ui.view_continuous) {
1055 for (i=0, pglist = journal.pages; pglist!=NULL; i++, pglist = pglist->next) {
1056 pg = (struct Page *)pglist->data;
1057 if (pg->group!=NULL) {
1058 pg->hoffset = 0.; pg->voffset = vertpos;
1059 gnome_canvas_item_set(GNOME_CANVAS_ITEM(pg->group),
1060 "x", pg->hoffset, "y", pg->voffset, NULL);
1061 gnome_canvas_item_show(GNOME_CANVAS_ITEM(pg->group));
1063 vertpos += pg->height + VIEW_CONTINUOUS_SKIP;
1064 if (pg->width > maxwidth) maxwidth = pg->width;
1066 vertpos -= VIEW_CONTINUOUS_SKIP;
1067 gnome_canvas_set_scroll_region(canvas, 0, 0, maxwidth, vertpos);
1069 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
1070 pg = (struct Page *)pglist->data;
1071 if (pg == ui.cur_page && pg->group!=NULL) {
1072 pg->hoffset = 0.; pg->voffset = 0.;
1073 gnome_canvas_item_set(GNOME_CANVAS_ITEM(pg->group),
1074 "x", pg->hoffset, "y", pg->voffset, NULL);
1075 gnome_canvas_item_show(GNOME_CANVAS_ITEM(pg->group));
1077 if (pg->group!=NULL) gnome_canvas_item_hide(GNOME_CANVAS_ITEM(pg->group));
1080 gnome_canvas_set_scroll_region(canvas, 0, 0, ui.cur_page->width, ui.cur_page->height);
1083 // update the page / layer info at bottom of screen
1085 spin = GTK_SPIN_BUTTON(GET_COMPONENT("spinPageNo"));
1086 ui.in_update_page_stuff = TRUE; // avoid a bad retroaction
1087 gtk_spin_button_set_range(spin, 1, journal.npages+1);
1088 /* npages+1 will be used to create a new page at end */
1089 gtk_spin_button_set_value(spin, ui.pageno+1);
1090 g_snprintf(tmp, 10, " of %d", journal.npages);
1091 gtk_label_set_text(GTK_LABEL(GET_COMPONENT("labelNumpages")), tmp);
1093 layerbox = GTK_COMBO_BOX(GET_COMPONENT("comboLayer"));
1094 if (ui.layerbox_length == 0) {
1095 gtk_combo_box_prepend_text(layerbox, "Background");
1096 ui.layerbox_length++;
1098 while (ui.layerbox_length > ui.cur_page->nlayers+1) {
1099 gtk_combo_box_remove_text(layerbox, 0);
1100 ui.layerbox_length--;
1102 while (ui.layerbox_length < ui.cur_page->nlayers+1) {
1103 g_snprintf(tmp, 10, "Layer %d", ui.layerbox_length++);
1104 gtk_combo_box_prepend_text(layerbox, tmp);
1106 gtk_combo_box_set_active(layerbox, ui.cur_page->nlayers-1-ui.layerno);
1107 ui.in_update_page_stuff = FALSE;
1109 // update the paper-style menu radio buttons
1111 if (ui.view_continuous)
1112 gtk_check_menu_item_set_active(
1113 GTK_CHECK_MENU_ITEM(GET_COMPONENT("viewContinuous")), TRUE);
1115 gtk_check_menu_item_set_active(
1116 GTK_CHECK_MENU_ITEM(GET_COMPONENT("viewOnePage")), TRUE);
1118 if (ui.cur_page->bg->type == BG_SOLID && !ui.bg_apply_all_pages) {
1119 switch (ui.cur_page->bg->color_no) {
1121 gtk_check_menu_item_set_active(
1122 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorWhite")), TRUE);
1125 gtk_check_menu_item_set_active(
1126 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorYellow")), TRUE);
1129 gtk_check_menu_item_set_active(
1130 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorPink")), TRUE);
1133 gtk_check_menu_item_set_active(
1134 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorOrange")), TRUE);
1137 gtk_check_menu_item_set_active(
1138 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorBlue")), TRUE);
1141 gtk_check_menu_item_set_active(
1142 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorGreen")), TRUE);
1145 gtk_check_menu_item_set_active(
1146 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorOther")), TRUE);
1149 switch (ui.cur_page->bg->ruling) {
1151 gtk_check_menu_item_set_active(
1152 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstylePlain")), TRUE);
1155 gtk_check_menu_item_set_active(
1156 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstyleLined")), TRUE);
1159 gtk_check_menu_item_set_active(
1160 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstyleRuled")), TRUE);
1163 gtk_check_menu_item_set_active(
1164 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstyleGraph")), TRUE);
1168 gtk_check_menu_item_set_active(
1169 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorNA")), TRUE);
1170 gtk_check_menu_item_set_active(
1171 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstyleNA")), TRUE);
1174 // enable/disable the page/layer menu items and toolbar buttons
1176 gtk_widget_set_sensitive(GET_COMPONENT("journalPaperColor"),
1177 ui.cur_page->bg->type == BG_SOLID || ui.bg_apply_all_pages);
1178 gtk_widget_set_sensitive(GET_COMPONENT("journalSetAsDefault"),
1179 ui.cur_page->bg->type == BG_SOLID);
1181 gtk_widget_set_sensitive(GET_COMPONENT("viewFirstPage"), ui.pageno!=0);
1182 gtk_widget_set_sensitive(GET_COMPONENT("viewPreviousPage"), ui.pageno!=0);
1183 gtk_widget_set_sensitive(GET_COMPONENT("viewNextPage"), TRUE);
1184 gtk_widget_set_sensitive(GET_COMPONENT("viewLastPage"), ui.pageno!=journal.npages-1);
1185 gtk_widget_set_sensitive(GET_COMPONENT("buttonFirstPage"), ui.pageno!=0);
1186 gtk_widget_set_sensitive(GET_COMPONENT("buttonPreviousPage"), ui.pageno!=0);
1187 gtk_widget_set_sensitive(GET_COMPONENT("buttonNextPage"), TRUE);
1188 gtk_widget_set_sensitive(GET_COMPONENT("buttonLastPage"), ui.pageno!=journal.npages-1);
1190 gtk_widget_set_sensitive(GET_COMPONENT("viewShowLayer"), ui.layerno!=ui.cur_page->nlayers-1);
1191 gtk_widget_set_sensitive(GET_COMPONENT("viewHideLayer"), ui.layerno>=0);
1193 gtk_widget_set_sensitive(GET_COMPONENT("editPaste"), ui.cur_layer!=NULL);
1194 gtk_widget_set_sensitive(GET_COMPONENT("buttonPaste"), ui.cur_layer!=NULL);
1197 void update_toolbar_and_menu(void)
1199 update_tool_buttons(); // takes care of other toolbar buttons as well
1201 update_color_menu();
1202 update_pen_props_menu();
1203 update_eraser_props_menu();
1204 update_highlighter_props_menu();
1205 update_mappings_menu();
1207 gtk_toggle_tool_button_set_active(
1208 GTK_TOGGLE_TOOL_BUTTON(GET_COMPONENT("buttonFullscreen")), ui.fullscreen);
1209 gtk_check_menu_item_set_active(
1210 GTK_CHECK_MENU_ITEM(GET_COMPONENT("viewFullscreen")), ui.fullscreen);
1213 void update_file_name(char *filename)
1216 if (ui.filename != NULL) g_free(ui.filename);
1217 ui.filename = filename;
1218 if (filename == NULL) {
1219 gtk_window_set_title(GTK_WINDOW (winMain), "Xournal");
1222 p = g_utf8_strrchr(filename, -1, '/');
1223 if (p == NULL) p = filename;
1224 else p = g_utf8_next_char(p);
1225 g_snprintf(tmp, 100, "Xournal - %s", p);
1226 gtk_window_set_title(GTK_WINDOW (winMain), tmp);
1227 new_mru_entry(filename);
1230 void update_undo_redo_enabled(void)
1232 gtk_widget_set_sensitive(GET_COMPONENT("editUndo"), undo!=NULL);
1233 gtk_widget_set_sensitive(GET_COMPONENT("editRedo"), redo!=NULL);
1234 gtk_widget_set_sensitive(GET_COMPONENT("buttonUndo"), undo!=NULL);
1235 gtk_widget_set_sensitive(GET_COMPONENT("buttonRedo"), redo!=NULL);
1238 void update_copy_paste_enabled(void)
1240 gtk_widget_set_sensitive(GET_COMPONENT("editCut"), ui.selection!=NULL);
1241 gtk_widget_set_sensitive(GET_COMPONENT("editCopy"), ui.selection!=NULL);
1242 gtk_widget_set_sensitive(GET_COMPONENT("editDelete"), ui.selection!=NULL);
1243 gtk_widget_set_sensitive(GET_COMPONENT("buttonCut"), ui.selection!=NULL);
1244 gtk_widget_set_sensitive(GET_COMPONENT("buttonCopy"), ui.selection!=NULL);
1247 void update_mapping_linkings(int toolno)
1251 for (i = 1; i<=NUM_BUTTONS; i++) {
1252 if (ui.linked_brush[i] == BRUSH_LINKED) {
1253 if (toolno >= 0 && toolno < NUM_STROKE_TOOLS)
1254 g_memmove(&(ui.brushes[i][toolno]), &(ui.brushes[0][toolno]), sizeof(struct Brush));
1255 ui.ruler[i] = ui.ruler[0];
1256 if (ui.toolno[i]!=TOOL_PEN && ui.toolno[i]!=TOOL_HIGHLIGHTER)
1257 ui.ruler[i] = FALSE;
1259 if (ui.linked_brush[i] == BRUSH_COPIED && toolno == ui.toolno[i]) {
1260 ui.linked_brush[i] = BRUSH_STATIC;
1261 if (i==1 || i==2) update_mappings_menu_linkings();
1266 void set_cur_color(int color)
1268 ui.cur_brush->color_no = color;
1269 if (ui.toolno[0] == TOOL_HIGHLIGHTER)
1270 ui.cur_brush->color_rgba = predef_colors_rgba[color] & HILITER_ALPHA_MASK;
1272 ui.cur_brush->color_rgba = predef_colors_rgba[color];
1273 update_mapping_linkings(ui.toolno[0]);
1276 void process_color_activate(GtkMenuItem *menuitem, int color)
1278 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1279 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1282 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1286 if (ui.cur_mapping != 0) return; // not user-generated
1288 if (ui.selection != NULL) {
1289 recolor_selection(color);
1290 update_color_buttons();
1291 update_color_menu();
1294 if (ui.toolno[0] != TOOL_PEN && ui.toolno[0] != TOOL_HIGHLIGHTER) {
1295 if (ui.selection != NULL) return;
1296 ui.toolno[0] = TOOL_PEN;
1297 ui.cur_brush = &(ui.brushes[0][TOOL_PEN]);
1298 update_tool_buttons();
1302 set_cur_color(color);
1303 update_color_buttons();
1304 update_color_menu();
1308 void process_thickness_activate(GtkMenuItem *menuitem, int tool, int val)
1310 if (GTK_OBJECT_TYPE(menuitem) == GTK_TYPE_RADIO_MENU_ITEM) {
1311 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1314 if (!gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON (menuitem)))
1318 if (ui.cur_mapping != 0) return; // not user-generated
1320 if (ui.selection != NULL && GTK_OBJECT_TYPE(menuitem) != GTK_TYPE_RADIO_MENU_ITEM) {
1321 rethicken_selection(val);
1322 update_thickness_buttons();
1325 if (tool >= NUM_STROKE_TOOLS) {
1326 update_thickness_buttons(); // undo illegal button selection
1330 ui.brushes[0][tool].thickness_no = val;
1331 ui.brushes[0][tool].thickness = predef_thickness[tool][val];
1332 update_mapping_linkings(tool);
1334 update_thickness_buttons();
1335 if (tool == TOOL_PEN) update_pen_props_menu();
1336 if (tool == TOOL_ERASER) update_eraser_props_menu();
1337 if (tool == TOOL_HIGHLIGHTER) update_highlighter_props_menu();
1341 void process_papercolor_activate(GtkMenuItem *menuitem, int color)
1347 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1350 if ((ui.cur_page->bg->type != BG_SOLID) || ui.bg_apply_all_pages)
1351 gtk_check_menu_item_set_active(
1352 GTK_CHECK_MENU_ITEM(GET_COMPONENT("papercolorNA")), TRUE);
1356 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
1357 if (ui.bg_apply_all_pages) pg = (struct Page *)pglist->data;
1358 if (pg->bg->type == BG_SOLID && pg->bg->color_no != color) {
1360 if (hasdone) undo->multiop |= MULTIOP_CONT_UNDO;
1361 undo->multiop |= MULTIOP_CONT_REDO;
1363 undo->type = ITEM_NEW_BG_ONE;
1365 undo->bg = (struct Background *)g_memdup(pg->bg, sizeof(struct Background));
1366 undo->bg->canvas_item = NULL;
1368 pg->bg->color_no = color;
1369 pg->bg->color_rgba = predef_bgcolors_rgba[color];
1370 update_canvas_bg(pg);
1372 if (!ui.bg_apply_all_pages) break;
1374 if (hasdone) undo->multiop -= MULTIOP_CONT_REDO;
1377 void process_paperstyle_activate(GtkMenuItem *menuitem, int style)
1381 gboolean hasdone, must_upd;
1383 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)))
1386 if (ui.bg_apply_all_pages)
1387 gtk_check_menu_item_set_active(
1388 GTK_CHECK_MENU_ITEM(GET_COMPONENT("paperstyleNA")), TRUE);
1393 for (pglist = journal.pages; pglist!=NULL; pglist = pglist->next) {
1394 if (ui.bg_apply_all_pages) pg = (struct Page *)pglist->data;
1395 if (pg->bg->type != BG_SOLID || pg->bg->ruling != style) {
1397 undo->type = ITEM_NEW_BG_ONE;
1398 if (hasdone) undo->multiop |= MULTIOP_CONT_UNDO;
1399 undo->multiop |= MULTIOP_CONT_REDO;
1402 undo->bg = (struct Background *)g_memdup(pg->bg, sizeof(struct Background));
1403 undo->bg->canvas_item = NULL;
1405 if (pg->bg->type != BG_SOLID) {
1406 pg->bg->type = BG_SOLID;
1407 pg->bg->color_no = COLOR_WHITE;
1408 pg->bg->color_rgba = predef_bgcolors_rgba[COLOR_WHITE];
1409 pg->bg->filename = NULL;
1410 pg->bg->pixbuf = NULL;
1413 pg->bg->ruling = style;
1414 update_canvas_bg(pg);
1416 if (!ui.bg_apply_all_pages) break;
1418 if (hasdone) undo->multiop -= MULTIOP_CONT_REDO;
1419 if (must_upd) update_page_stuff();
1422 gboolean ok_to_close(void)
1425 GtkResponseType response;
1428 if (ui.saved) return TRUE;
1429 dialog = gtk_message_dialog_new(GTK_WINDOW (winMain), GTK_DIALOG_DESTROY_WITH_PARENT,
1430 GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, "Save changes to '%s'?",
1431 (ui.filename!=NULL) ? ui.filename:"Untitled");
1432 gtk_dialog_add_button(GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
1433 response = gtk_dialog_run(GTK_DIALOG (dialog));
1434 gtk_widget_destroy(dialog);
1435 if (response == GTK_RESPONSE_CANCEL || response == GTK_RESPONSE_DELETE_EVENT)
1436 return FALSE; // aborted
1437 if (response == GTK_RESPONSE_YES) {
1438 on_fileSave_activate(NULL, NULL);
1439 if (!ui.saved) return FALSE; // if save failed, then we abort
1444 // test if we're still busy loading a PDF background file
1445 gboolean page_ops_forbidden(void)
1447 return (bgpdf.status != STATUS_NOT_INIT && bgpdf.create_pages);
1450 // selection / clipboard stuff
1452 void reset_selection(void)
1454 if (ui.selection == NULL) return;
1455 if (ui.selection->canvas_item != NULL)
1456 gtk_object_destroy(GTK_OBJECT(ui.selection->canvas_item));
1457 g_list_free(ui.selection->items);
1458 g_free(ui.selection);
1459 ui.selection = NULL;
1460 update_copy_paste_enabled();
1461 update_color_menu();
1462 update_thickness_buttons();
1463 update_color_buttons();
1466 void move_journal_items_by(GList *itemlist, double dx, double dy,
1467 struct Layer *l1, struct Layer *l2, GList *depths)
1470 GnomeCanvasItem *refitem;
1475 while (itemlist!=NULL) {
1476 item = (struct Item *)itemlist->data;
1477 if (item->type == ITEM_STROKE) {
1478 for (pt=item->path->coords, i=0; i<item->path->num_points; i++, pt+=2)
1479 { pt[0] += dx; pt[1] += dy; }
1480 item->bbox.left += dx;
1481 item->bbox.right += dx;
1482 item->bbox.top += dy;
1483 item->bbox.bottom += dy;
1486 // find out where to insert
1487 if (depths != NULL) {
1488 if (depths->data == NULL) link = l2->items;
1490 link = g_list_find(l2->items, depths->data);
1491 if (link != NULL) link = link->next;
1494 l2->items = g_list_insert_before(l2->items, link, item);
1496 l1->items = g_list_remove(l1->items, item);
1499 if (depths != NULL) { // also raise/lower the canvas items
1500 if (item->canvas_item!=NULL) {
1501 if (depths->data == NULL) link = NULL;
1502 else link = g_list_find(l2->items, depths->data);
1503 if (link != NULL) refitem = ((struct Item *)(link->data))->canvas_item;
1504 else refitem = NULL;
1505 lower_canvas_item_to(l2->group, item->canvas_item, refitem);
1507 depths = depths->next;
1509 itemlist = itemlist->next;
1513 // Switch between button mappings
1515 /* NOTE ABOUT BUTTON MAPPINGS: ui.cur_mapping is 0 except while a canvas
1516 click event is being processed ... */
1518 void switch_mapping(int m)
1520 if (ui.cur_mapping == m) return;
1523 if (ui.toolno[m] < NUM_STROKE_TOOLS)
1524 ui.cur_brush = &(ui.brushes[m][ui.toolno[m]]);
1525 update_tool_buttons();
1526 update_color_menu();
1530 void process_mapping_activate(GtkMenuItem *menuitem, int m, int tool)
1532 if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem))) return;
1533 if (ui.cur_mapping!=0) return;
1534 if (ui.toolno[m] == tool) return;
1535 ui.toolno[m] = tool;
1536 ui.ruler[m] = FALSE;
1537 if (ui.linked_brush[m] == BRUSH_LINKED
1538 && (tool==TOOL_PEN || tool==TOOL_HIGHLIGHTER))
1539 ui.ruler[m] = ui.ruler[0];
1540 if (ui.linked_brush[m] == BRUSH_COPIED) {
1541 ui.linked_brush[m] = BRUSH_STATIC;
1542 update_mappings_menu_linkings();