+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
/*
* (GLABELS) Label and Business Card Creation program for GNOME
*
* view.c: GLabels View module
*
- * Copyright (C) 2001-2002 Jim Evins <evins@snaught.com>.
+ * Copyright (C) 2001-2007 Jim Evins <evins@snaught.com>.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <config.h>
-#include <gtk/gtk.h>
-#include <gtk/gtkinvisible.h>
+#include "view.h"
+#include <glib/gi18n.h>
+#include <gtk/gtkscrolledwindow.h>
+#include <gtk/gtklayout.h>
+#include <gtk/gtkselection.h>
+#include <gtk/gtkinvisible.h>
+#include <gdk/gdkkeysyms.h>
#include <string.h>
#include <math.h>
-#include "view.h"
+#include "label.h"
+#include "cairo-label-path.h"
+#include "cairo-markup-path.h"
#include "view-object.h"
#include "view-box.h"
#include "view-ellipse.h"
#include "view-barcode.h"
#include "xml-label.h"
#include "color.h"
+#include "prefs.h"
#include "marshal.h"
#include "debug.h"
/* Private macros and constants. */
/*==========================================================================*/
-#define OUTLINE_COLOR GL_COLOR (173, 216, 230)
-#define PAPER_COLOR GL_COLOR (255, 255, 255)
-#define GRID_COLOR GL_COLOR (192, 192, 192)
-#define MARKUP_COLOR GL_COLOR (240, 100, 100)
+#define BG_COLOR GL_COLOR (192, 192, 192)
+
+#define PAPER_RGB_ARGS 1.0, 1.0, 1.0
+#define GRID_RGB_ARGS 0.753, 0.753, 0.753
+#define MARKUP_RGB_ARGS 0.94, 0.39, 0.39
+#define OUTLINE_RGB_ARGS 0.68, 0.85, 0.90
+#define SELECT_LINE_RGBA_ARGS 0.0, 0.0, 1.0, 0.5
+#define SELECT_FILL_RGBA_ARGS 0.75, 0.75, 1.0, 0.5
+
+#define GRID_LINE_WIDTH_PIXELS 1.0
+#define MARKUP_LINE_WIDTH_PIXELS 1.0
+#define OUTLINE_WIDTH_PIXELS 3.0
+#define SELECT_LINE_WIDTH_PIXELS 3.0
+
+#define ZOOMTOFIT_PAD 16
-#define SEL_LINE_COLOR GL_COLOR_A (0, 0, 255, 128)
-#define SEL_FILL_COLOR GL_COLOR_A (192, 192, 255, 128)
+#define POINTS_PER_MM 2.83464566929
/*==========================================================================*/
/* Private types. */
enum {
SELECTION_CHANGED,
+ CONTEXT_MENU_ACTIVATE,
ZOOM_CHANGED,
POINTER_MOVED,
POINTER_EXIT,
/* Private globals */
/*==========================================================================*/
-static GtkContainerClass *parent_class;
-
static guint signals[LAST_SIGNAL] = {0};
/* "CLIPBOARD" selection */
static GdkAtom clipboard_atom = GDK_NONE;
-static gdouble scales[] = {
- 8.0, 6.0, 4.0, 3.0,
- 2.0,
- 1.5, 1.0, 0.5, 0.25,
+static gdouble zooms[] = {
+ 8.00,
+ 6.00,
+ 4.00,
+ 3.00,
+ 2.00,
+ 1.50,
+ 1.00,
+ 0.75,
+ 0.67,
+ 0.50,
+ 0.33,
+ 0.25,
+ 0.20,
+ 0.15,
+ 0.10,
};
-#define N_SCALES G_N_ELEMENTS(scales)
-#define HOME_SCALE 2.0
+#define N_ZOOMS G_N_ELEMENTS(zooms)
+
/*==========================================================================*/
/* Local function prototypes */
/*==========================================================================*/
-static void gl_view_class_init (glViewClass *class);
-static void gl_view_init (glView *view);
-static void gl_view_finalize (GObject *object);
+static void gl_view_finalize (GObject *object);
+
+static void gl_view_construct (glView *view,
+ glLabel *label);
+
+static gdouble get_home_scale (glView *view);
-static void gl_view_construct (glView *view);
-static GtkWidget *gl_view_construct_canvas (glView *view);
-static void gl_view_construct_selection (glView *view);
+static gboolean expose_cb (glView *view,
+ GdkEventExpose *event);
-static gdouble get_apropriate_scale (gdouble w, gdouble h);
+static void realize_cb (glView *view);
-static void draw_layers (glView *view);
+static void size_allocate_cb (glView *view,
+ GtkAllocation *allocation);
-static void draw_label_layer (glView *view);
+static void screen_changed_cb (glView *view);
-static void draw_bg_fg_layers (glView *view);
-static void draw_bg_fg_rect (glView *view);
-static void draw_bg_fg_rounded_rect (glView *view);
-static void draw_bg_fg_round (glView *view);
-static void draw_bg_fg_cd (glView *view);
+static void label_changed_cb (glView *view);
-static void draw_grid_layer (glView *view);
+static void label_resized_cb (glView *view);
-static void draw_markup_layer (glView *view);
+static void label_object_added_cb (glView *view,
+ glLabelObject *object);
-static void draw_markup_margin (glView *view,
- glTemplateMarkupMargin *margin);
-static void draw_markup_margin_rect (glView *view,
- glTemplateMarkupMargin *margin);
-static void draw_markup_margin_rounded_rect (glView *view,
- glTemplateMarkupMargin *margin);
-static void draw_markup_margin_round (glView *view,
- glTemplateMarkupMargin *margin);
-static void draw_markup_margin_cd (glView *view,
- glTemplateMarkupMargin *margin);
+static void draw_layers (glView *view,
+ cairo_t *cr);
+static void draw_bg_layer (glView *view,
+ cairo_t *cr);
+static void draw_grid_layer (glView *view,
+ cairo_t *cr);
+static void draw_markup_layer (glView *view,
+ cairo_t *cr);
+static void draw_objects_layer (glView *view,
+ cairo_t *cr);
+static void draw_fg_layer (glView *view,
+ cairo_t *cr);
+static void draw_highlight_layer (glView *view,
+ cairo_t *cr);
+static void draw_select_region_layer (glView *view,
+ cairo_t *cr);
-static void select_object_real (glView *view,
- glViewObject *view_object);
-static void unselect_object_real (glView *view,
- glViewObject *view_object);
+static void select_object_real (glView *view,
+ glViewObject *view_object);
+static void unselect_object_real (glView *view,
+ glViewObject *view_object);
-static gboolean object_at (glView *view,
- gdouble x, gdouble y);
+static glViewObject *view_view_object_at (glView *view,
+ cairo_t *cr,
+ gdouble x,
+ gdouble y);
-static gboolean is_item_member_of_group (glView *view,
- GnomeCanvasItem *item,
- GnomeCanvasItem *group);
+static void set_zoom_real (glView *view,
+ gdouble zoom,
+ gboolean scale_to_fit_flag);
-static gboolean is_object_selected (glView *view,
- glViewObject *view_object);
+static void selection_clear_cb (GtkWidget *widget,
+ GdkEventSelection *event,
+ glView *view);
-static void move_selection (glView *view,
- gdouble dx, gdouble dy);
+static void selection_get_cb (GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ glView *view);
-static int canvas_event (GnomeCanvas *canvas,
- GdkEvent *event,
- glView *view);
-static int canvas_event_arrow_mode (GnomeCanvas *canvas,
- GdkEvent *event,
- glView *view);
+static void selection_received_cb (GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ guint time,
+ glView *view);
-static int item_event_arrow_mode (GnomeCanvasItem *item,
- GdkEvent *event,
- glViewObject *view_object);
+static gboolean focus_in_event_cb (glView *view,
+ GdkEventFocus *event);
-static GtkWidget *new_selection_menu (glView *view);
+static gboolean focus_out_event_cb (glView *view,
+ GdkEventFocus *event);
-static void popup_selection_menu (glView *view,
- glViewObject *view_object,
- GdkEvent *event);
+static gboolean enter_notify_event_cb (glView *view,
+ GdkEventCrossing *event);
-static void selection_clear_cb (GtkWidget *widget,
- GdkEventSelection *event,
- gpointer data);
+static gboolean leave_notify_event_cb (glView *view,
+ GdkEventCrossing *event);
-static void selection_get_cb (GtkWidget *widget,
- GtkSelectionData *selection_data,
- guint info,
- guint time,
- gpointer data);
+static gboolean motion_notify_event_cb (glView *view,
+ GdkEventMotion *event);
+
+static gboolean button_press_event_cb (glView *view,
+ GdkEventButton *event);
+
+static gboolean button_release_event_cb (glView *view,
+ GdkEventButton *event);
+
+static gboolean key_press_event_cb (glView *view,
+ GdkEventKey *event);
-static void selection_received_cb (GtkWidget *widget,
- GtkSelectionData *selection_data,
- guint time,
- gpointer data);
\f
/****************************************************************************/
/* Boilerplate Object stuff. */
/****************************************************************************/
-guint
-gl_view_get_type (void)
-{
- static guint view_type = 0;
-
- if (!view_type) {
- GTypeInfo view_info = {
- sizeof (glViewClass),
- NULL,
- NULL,
- (GClassInitFunc) gl_view_class_init,
- NULL,
- NULL,
- sizeof (glView),
- 0,
- (GInstanceInitFunc) gl_view_init,
- };
-
- view_type =
- g_type_register_static (gtk_vbox_get_type (),
- "glView", &view_info, 0);
- }
-
- return view_type;
-}
+G_DEFINE_TYPE (glView, gl_view, GTK_TYPE_VBOX);
static void
gl_view_class_init (glViewClass *class)
{
- GObjectClass *object_class = (GObjectClass *) class;
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
gl_debug (DEBUG_VIEW, "START");
- parent_class = g_type_class_peek_parent (class);
+ gl_view_parent_class = g_type_class_peek_parent (class);
object_class->finalize = gl_view_finalize;
G_TYPE_NONE,
0);
+ signals[CONTEXT_MENU_ACTIVATE] =
+ g_signal_new ("context_menu_activate",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (glViewClass, context_menu_activate),
+ NULL, NULL,
+ gl_marshal_VOID__INT_UINT,
+ G_TYPE_NONE,
+ 2, G_TYPE_INT, G_TYPE_UINT);
+
signals[ZOOM_CHANGED] =
g_signal_new ("zoom_changed",
G_OBJECT_CLASS_TYPE (object_class),
static void
gl_view_init (glView *view)
{
+ GtkWidget *wscroll;
+ GdkColor *bg_color;
+
gl_debug (DEBUG_VIEW, "START");
- view->label = NULL;
+ view->label = NULL;
+ view->grid_visible = TRUE;
+ view->grid_spacing = 9;
+ view->markup_visible = TRUE;
+ view->default_font_family = NULL;
+ view->mode = GL_VIEW_MODE_ARROW;
+ view->object_list = NULL;
+ view->selected_object_list = NULL;
+ view->zoom = 1.0;
+ view->home_scale = get_home_scale (view);
+
+ /*
+ * Canvas
+ */
+ view->canvas = gtk_layout_new (NULL, NULL);
+ wscroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (wscroll),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start (GTK_BOX (view), wscroll, TRUE, TRUE, 0);
+ gtk_container_add (GTK_CONTAINER (wscroll), view->canvas);
+
+ bg_color = gl_color_to_gdk_color (BG_COLOR);
+ gtk_widget_modify_bg (GTK_WIDGET (view->canvas), GTK_STATE_NORMAL, bg_color);
+ g_free (bg_color);
+
+ GTK_WIDGET_SET_FLAGS (GTK_WIDGET (view->canvas), GTK_CAN_FOCUS);
+
+ gtk_widget_add_events (GTK_WIDGET (view->canvas),
+ (GDK_FOCUS_CHANGE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_KEY_PRESS_MASK));
+
+ g_signal_connect_swapped (G_OBJECT (view->canvas), "expose-event",
+ G_CALLBACK (expose_cb), view);
+ g_signal_connect_swapped (G_OBJECT (view->canvas), "realize",
+ G_CALLBACK (realize_cb), view);
+ g_signal_connect_swapped (G_OBJECT (view->canvas), "size-allocate",
+ G_CALLBACK (size_allocate_cb), view);
+ g_signal_connect_swapped (G_OBJECT (view->canvas), "screen-changed",
+ G_CALLBACK (screen_changed_cb), view);
+ g_signal_connect_swapped (G_OBJECT (view->canvas), "focus-in-event",
+ G_CALLBACK (focus_in_event_cb), view);
+ g_signal_connect_swapped (G_OBJECT (view->canvas), "focus-out-event",
+ G_CALLBACK (focus_out_event_cb), view);
+ g_signal_connect_swapped (G_OBJECT (view->canvas), "enter-notify-event",
+ G_CALLBACK (enter_notify_event_cb), view);
+ g_signal_connect_swapped (G_OBJECT (view->canvas), "leave-notify-event",
+ G_CALLBACK (leave_notify_event_cb), view);
+ g_signal_connect_swapped (G_OBJECT (view->canvas), "motion-notify-event",
+ G_CALLBACK (motion_notify_event_cb), view);
+ g_signal_connect_swapped (G_OBJECT (view->canvas), "button-press-event",
+ G_CALLBACK (button_press_event_cb), view);
+ g_signal_connect_swapped (G_OBJECT (view->canvas), "button-release-event",
+ G_CALLBACK (button_release_event_cb), view);
+ g_signal_connect_swapped (G_OBJECT (view->canvas), "key-press-event",
+ G_CALLBACK (key_press_event_cb), view);
+
+ /*
+ * Clipboard
+ */
+ view->have_selection = FALSE;
+ view->selection_data = NULL;
+ view->invisible = gtk_invisible_new ();
+ if (!clipboard_atom) {
+ clipboard_atom = gdk_atom_intern ("GLABELS_CLIPBOARD", FALSE);
+ }
+ gtk_selection_add_target (view->invisible,
+ clipboard_atom, GDK_SELECTION_TYPE_STRING, 1);
+ g_signal_connect (G_OBJECT (view->invisible),
+ "selection_clear_event",
+ G_CALLBACK (selection_clear_cb), view);
+ g_signal_connect (G_OBJECT (view->invisible), "selection_get",
+ G_CALLBACK (selection_get_cb), view);
+ g_signal_connect (G_OBJECT (view->invisible),
+ "selection_received",
+ G_CALLBACK (selection_received_cb), view);
- view->grid_spacing = 9;
+ /*
+ * Defaults from preferences
+ */
+ gl_view_set_default_font_family (view, gl_prefs->default_font_family);
+ gl_view_set_default_font_size (view, gl_prefs->default_font_size);
+ gl_view_set_default_font_weight (view, gl_prefs->default_font_weight);
+ gl_view_set_default_font_italic_flag (view, gl_prefs->default_font_italic_flag);
+ gl_view_set_default_text_color (view, gl_prefs->default_text_color);
+ gl_view_set_default_text_alignment (view, gl_prefs->default_text_alignment);
+ gl_view_set_default_text_line_spacing (view, gl_prefs->default_text_line_spacing);
+ gl_view_set_default_line_width (view, gl_prefs->default_line_width);
+ gl_view_set_default_line_color (view, gl_prefs->default_line_color);
+ gl_view_set_default_fill_color (view, gl_prefs->default_fill_color);
gl_debug (DEBUG_VIEW, "END");
}
static void
gl_view_finalize (GObject *object)
{
- glView *view;
+ glView *view = GL_VIEW (object);
gl_debug (DEBUG_VIEW, "START");
g_return_if_fail (object != NULL);
g_return_if_fail (GL_IS_VIEW (object));
- view = GL_VIEW (object);
+ if (view->default_font_family) {
+ g_free (view->default_font_family);
+ }
- G_OBJECT_CLASS (parent_class)->finalize (object);
+ G_OBJECT_CLASS (gl_view_parent_class)->finalize (object);
gl_debug (DEBUG_VIEW, "END");
}
GtkWidget *
gl_view_new (glLabel *label)
{
- glView *view = g_object_new (gl_view_get_type (), NULL);
+ glView *view;
gl_debug (DEBUG_VIEW, "START");
- view->label = label;
+ g_return_val_if_fail (label && GL_IS_LABEL (label), NULL);
+
+ view = g_object_new (GL_TYPE_VIEW, NULL);
- gl_view_construct (view);
+ gl_view_construct (view, label);
gl_debug (DEBUG_VIEW, "END");
/* PRIVATE. Construct composite widget. */
/*---------------------------------------------------------------------------*/
static void
-gl_view_construct (glView *view)
+gl_view_construct (glView *view,
+ glLabel *label)
{
- GtkWidget *wvbox, *wscroll;
+ GList *p_obj;
+ glLabelObject *object;
gl_debug (DEBUG_VIEW, "START");
g_return_if_fail (GL_IS_VIEW (view));
- wvbox = GTK_WIDGET (view);
-
- view->state = GL_VIEW_STATE_ARROW;
- view->object_list = NULL;
-
- gl_view_construct_canvas (view);
- wscroll = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (wscroll),
- GTK_POLICY_AUTOMATIC,
- GTK_POLICY_AUTOMATIC);
- gtk_box_pack_start (GTK_BOX (wvbox), wscroll, TRUE, TRUE, 0);
- gtk_container_add (GTK_CONTAINER (wscroll), view->canvas);
-
- gl_view_construct_selection (view);
+ view->label = label;
- view->menu = new_selection_menu (view);
+ for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next)
+ {
+ object = GL_LABEL_OBJECT (p_obj->data);
+
+ if (GL_IS_LABEL_BOX (object)) {
+ gl_view_box_new (GL_LABEL_BOX(object), view);
+ } else if (GL_IS_LABEL_ELLIPSE (object)) {
+ gl_view_ellipse_new (GL_LABEL_ELLIPSE(object), view);
+ } else if (GL_IS_LABEL_LINE (object)) {
+ gl_view_line_new (GL_LABEL_LINE(object), view);
+ } else if (GL_IS_LABEL_IMAGE (object)) {
+ gl_view_image_new (GL_LABEL_IMAGE(object), view);
+ } else if (GL_IS_LABEL_TEXT (object)) {
+ gl_view_text_new (GL_LABEL_TEXT(object), view);
+ } else if (GL_IS_LABEL_BARCODE (object)) {
+ gl_view_barcode_new (GL_LABEL_BARCODE(object), view);
+ } else {
+ /* Should not happen! */
+ g_message ("Invalid label object type.");
+ }
+ }
+
+ g_signal_connect_swapped (G_OBJECT (view->label), "changed",
+ G_CALLBACK (label_changed_cb), view);
+ g_signal_connect_swapped (G_OBJECT (view->label), "size_changed",
+ G_CALLBACK (label_resized_cb), view);
+ g_signal_connect_swapped (G_OBJECT (view->label), "object_added",
+ G_CALLBACK (label_object_added_cb), view);
gl_debug (DEBUG_VIEW, "END");
}
/*---------------------------------------------------------------------------*/
-/* PRIVATE. Create canvas w/ a background in the shape of the label/card. */
+/* PRIAVTE. Calculate 1:1 scale for screen. */
/*---------------------------------------------------------------------------*/
-static GtkWidget *
-gl_view_construct_canvas (glView *view)
+static gdouble
+get_home_scale (glView *view)
{
- gdouble scale;
- glLabel *label = view->label;
- gdouble label_width, label_height;
+ GdkScreen *screen;
+ gdouble screen_width_pixels;
+ gdouble screen_width_mm;
+ gdouble screen_height_pixels;
+ gdouble screen_height_mm;
+ gdouble x_pixels_per_mm;
+ gdouble y_pixels_per_mm;
+ gdouble scale;
- gl_debug (DEBUG_VIEW, "START");
+ if (view->canvas == NULL) return 1.0;
- g_return_val_if_fail (GL_IS_VIEW (view), NULL);
- g_return_val_if_fail (label != NULL, NULL);
+ if (!gtk_widget_has_screen (GTK_WIDGET (view->canvas))) return 1.0;
- gtk_widget_push_colormap (gdk_rgb_get_colormap ());
- view->canvas = gnome_canvas_new_aa ();
- gtk_widget_pop_colormap ();
+ screen = gtk_widget_get_screen (GTK_WIDGET (view->canvas));
- gl_label_get_size (label, &label_width, &label_height);
- gl_debug (DEBUG_VIEW, "Label size: w=%lf, h=%lf",
- label_width, label_height);
+ gl_debug (DEBUG_VIEW, "Screen = %p", screen);
- scale = get_apropriate_scale (label_width, label_height);
- gl_debug (DEBUG_VIEW, "scale =%lf", scale);
+ screen_width_pixels = gdk_screen_get_width (screen);
+ screen_width_mm = gdk_screen_get_width_mm (screen);
+ screen_height_pixels = gdk_screen_get_height (screen);
+ screen_height_mm = gdk_screen_get_height_mm (screen);
- gl_debug (DEBUG_VIEW, "Canvas size: w=%lf, h=%lf",
- scale * label_width + 40,
- scale * label_height + 40);
- gtk_widget_set_size_request (GTK_WIDGET(view->canvas),
- scale * label_width + 40,
- scale * label_height + 40);
- gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (view->canvas),
- scale);
- view->scale = scale;
+ x_pixels_per_mm = screen_width_pixels / screen_width_mm;
+ y_pixels_per_mm = screen_height_pixels / screen_height_mm;
- gnome_canvas_set_scroll_region (GNOME_CANVAS (view->canvas),
- 0.0, 0.0, label_width, label_height);
+ gl_debug (DEBUG_VIEW, "Horizontal dot pitch: %g pixels/mm (%g dpi)",
+ x_pixels_per_mm, x_pixels_per_mm * 25.4);
+ gl_debug (DEBUG_VIEW, "Vertical dot pitch: %g pixels/mm (%g dpi)",
+ y_pixels_per_mm, y_pixels_per_mm * 25.4);
- draw_layers (view);
+ scale = (x_pixels_per_mm + y_pixels_per_mm) / 2.0;
- g_signal_connect (G_OBJECT (view->canvas), "event",
- G_CALLBACK (canvas_event), view);
+ gl_debug (DEBUG_VIEW, "Average dot pitch: %g pixels/mm (%g dpi)",
+ scale, scale * 25.4);
- gl_debug (DEBUG_VIEW, "END");
+ scale /= POINTS_PER_MM;
+
+ gl_debug (DEBUG_VIEW, "Scale = %g pixels/point", scale);
- return view->canvas;
+ /* Make sure scale is somewhat sane. */
+ if ( (scale < 0.25) || (scale > 4.0) ) return 1.0;
+
+ return scale;
}
/*---------------------------------------------------------------------------*/
-/* PRIVATE. Create clipboard selection targets. */
+/* Schedule canvas update. */
/*---------------------------------------------------------------------------*/
-static void
-gl_view_construct_selection (glView *view)
+void
+gl_view_update (glView *view)
{
+ GtkWidget *widget;
+ GdkRegion *region;
+
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ widget = GTK_WIDGET (view->canvas);
- view->have_selection = FALSE;
- view->selection_data = NULL;
- view->invisible = gtk_invisible_new ();
+ if (!widget->window) return;
- view->selected_object_list = NULL;
+ if ( !view->update_scheduled_flag )
+ {
+ view->update_scheduled_flag = TRUE;
- if (!clipboard_atom) {
- clipboard_atom = gdk_atom_intern ("GLABELS_CLIPBOARD", FALSE);
- }
+ region = gdk_drawable_get_clip_region (widget->window);
+ /* redraw the cairo canvas completely by exposing it */
+ gdk_window_invalidate_region (widget->window, region, TRUE);
+ gdk_region_destroy (region);
+ }
- gtk_selection_add_target (view->invisible,
- clipboard_atom, GDK_SELECTION_TYPE_STRING, 1);
+ gl_debug (DEBUG_VIEW, "END");
+}
- g_signal_connect (G_OBJECT (view->invisible),
- "selection_clear_event",
- G_CALLBACK (selection_clear_cb), view);
+/*---------------------------------------------------------------------------*/
+/* Schedule canvas region update. */
+/*---------------------------------------------------------------------------*/
+void
+gl_view_update_region (glView *view,
+ cairo_t *cr,
+ glLabelRegion *region)
+{
+ GtkWidget *widget;
+ GdkRectangle rect;
+ gdouble x, y, w, h;
- g_signal_connect (G_OBJECT (view->invisible), "selection_get",
- G_CALLBACK (selection_get_cb), view);
+ gl_debug (DEBUG_VIEW, "START");
- g_signal_connect (G_OBJECT (view->invisible),
- "selection_received",
- G_CALLBACK (selection_received_cb), view);
+ widget = GTK_WIDGET (view->canvas);
+
+ if (!widget->window) return;
+
+ x = MIN (region->x1, region->x2);
+ y = MIN (region->y1, region->y2);
+ w = fabs (region->x2 - region->x1);
+ h = fabs (region->y2 - region->y1);
+
+ cairo_user_to_device (cr, &x, &y);
+ cairo_user_to_device_distance (cr, &w, &h);
+
+ rect.x = x - 3;
+ rect.y = y - 3;
+ rect.width = w + 6;
+ rect.height = h + 6;
+
+ gdk_window_invalidate_rect (widget->window, &rect, TRUE);
gl_debug (DEBUG_VIEW, "END");
}
/*---------------------------------------------------------------------------*/
-/* PRIVATE. Determine an apropriate scale for given label & screen size */
+/* PRIVATE. Expose handler. */
/*---------------------------------------------------------------------------*/
-static gdouble
-get_apropriate_scale (gdouble w, gdouble h)
+static gboolean
+expose_cb (glView *view,
+ GdkEventExpose *event)
{
- gdouble w_screen, h_screen;
- gint i;
- gdouble k;
+ cairo_t *cr;
- gl_debug (DEBUG_VIEW, "");
+ gl_debug (DEBUG_VIEW, "START");
- w_screen = (gdouble) gdk_screen_width ();
- h_screen = (gdouble) gdk_screen_height ();
+ view->update_scheduled_flag = FALSE;
- for (i = 0; i < N_SCALES; i++) {
- k = scales[i];
- if (k <= HOME_SCALE) {
- if ((k * w < (w_screen - 256))
- && (k * h < (h_screen - 256)))
- return k;
- }
- }
+ /* get a cairo_t */
+ cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
+
+ cairo_rectangle (cr,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+ cairo_clip (cr);
+
+ draw_layers (view, cr);
+
+ cairo_destroy (cr);
- return 0.25;
+ gl_debug (DEBUG_VIEW, "END");
+
+ return FALSE;
}
/*---------------------------------------------------------------------------*/
-/* PRIVATE. Create, draw and order layers. */
+/* PRIVATE. Realize handler. */
/*---------------------------------------------------------------------------*/
static void
-draw_layers (glView *view)
+realize_cb (glView *view)
{
- draw_bg_fg_layers (view);
- draw_grid_layer (view);
- draw_markup_layer (view);
- draw_label_layer (view);
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ gl_debug (DEBUG_VIEW, "START");
- gnome_canvas_item_raise_to_top (GNOME_CANVAS_ITEM(view->fg_group));
+ gl_debug (DEBUG_VIEW, "END");
}
/*---------------------------------------------------------------------------*/
-/* PRIVATE. Draw label layer. */
+/* PRIVATE. Size allocation changed callback. */
/*---------------------------------------------------------------------------*/
static void
-draw_label_layer (glView *view)
+size_allocate_cb (glView *view,
+ GtkAllocation *allocation)
{
- GnomeCanvasGroup *group;
- glLabel *label;
- GList *p_obj;
- glLabelObject *object;
- glViewObject *view_object;
-
- group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
- view->label_group = GNOME_CANVAS_GROUP(
- gnome_canvas_item_new (group,
- gnome_canvas_group_get_type (),
- "x", 0.0,
- "y", 0.0,
- NULL));
+ gl_debug (DEBUG_VIEW, "START");
- label = view->label;
+ GTK_LAYOUT (view->canvas)->hadjustment->page_size = allocation->width;
+ GTK_LAYOUT (view->canvas)->hadjustment->page_increment = allocation->width / 2;
+
+ GTK_LAYOUT (view->canvas)->vadjustment->page_size = allocation->height;
+ GTK_LAYOUT (view->canvas)->vadjustment->page_increment = allocation->height / 2;
- for (p_obj = label->objects; p_obj != NULL; p_obj = p_obj->next) {
- object = (glLabelObject *) p_obj->data;
+ g_signal_emit_by_name (GTK_LAYOUT (view->canvas)->hadjustment, "changed");
+ g_signal_emit_by_name (GTK_LAYOUT (view->canvas)->vadjustment, "changed");
- if (GL_IS_LABEL_BOX (object)) {
- view_object = gl_view_box_new (GL_LABEL_BOX(object),
- view);
- } else if (GL_IS_LABEL_ELLIPSE (object)) {
- view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(object),
- view);
- } else if (GL_IS_LABEL_LINE (object)) {
- view_object = gl_view_line_new (GL_LABEL_LINE(object),
- view);
- } else if (GL_IS_LABEL_IMAGE (object)) {
- view_object = gl_view_image_new (GL_LABEL_IMAGE(object),
- view);
- } else if (GL_IS_LABEL_TEXT (object)) {
- view_object = gl_view_text_new (GL_LABEL_TEXT(object),
- view);
- } else if (GL_IS_LABEL_BARCODE (object)) {
- view_object = gl_view_barcode_new (GL_LABEL_BARCODE(object),
- view);
- } else {
- /* Should not happen! */
- view_object = NULL;
- g_warning ("Invalid label object type.");
- }
+ if (view->zoom_to_fit_flag) {
+ /* Maintain best fit zoom */
+ gl_view_zoom_to_fit (view);
}
+
+ gl_debug (DEBUG_VIEW, "END");
}
+
+
/*---------------------------------------------------------------------------*/
-/* PRIVATE. Draw background and foreground outlines. */
+/* PRIVATE. Screen changed callback. */
/*---------------------------------------------------------------------------*/
static void
-draw_bg_fg_layers (glView *view)
-{
- glLabel *label;
- glTemplate *template;
- GnomeCanvasGroup *group;
-
- group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
- view->bg_group = GNOME_CANVAS_GROUP(
- gnome_canvas_item_new (group,
- gnome_canvas_group_get_type (),
- "x", 0.0,
- "y", 0.0,
- NULL));
- view->fg_group = GNOME_CANVAS_GROUP(
- gnome_canvas_item_new (group,
- gnome_canvas_group_get_type (),
- "x", 0.0,
- "y", 0.0,
- NULL));
-
- label = view->label;
- template = gl_label_get_template (label);
-
- switch (template->label.style) {
-
- case GL_TEMPLATE_STYLE_RECT:
- if (template->label.rect.r == 0.0) {
- /* Square corners. */
- draw_bg_fg_rect (view);
- } else {
- /* Rounded corners. */
- draw_bg_fg_rounded_rect (view);
- }
- break;
+screen_changed_cb (glView *view)
+{
+ gl_debug (DEBUG_VIEW, "START");
- case GL_TEMPLATE_STYLE_ROUND:
- draw_bg_fg_round (view);
- break;
+ if (gtk_widget_has_screen (GTK_WIDGET (view->canvas))) {
- case GL_TEMPLATE_STYLE_CD:
- draw_bg_fg_cd (view);
- break;
+ view->home_scale = get_home_scale (view);
- default:
- g_warning ("Unknown template label style");
- break;
+ if (view->zoom_to_fit_flag) {
+ /* Maintain best fit zoom */
+ gl_view_zoom_to_fit (view);
+ }
}
+
+ gl_debug (DEBUG_VIEW, "END");
}
/*---------------------------------------------------------------------------*/
-/* PRIVATE. Draw simple recangular background. */
+/* PRIVATE. Handle label changed event. */
/*---------------------------------------------------------------------------*/
static void
-draw_bg_fg_rect (glView *view)
+label_changed_cb (glView *view)
{
- glLabel *label = view->label;
- glTemplate *template;
- gdouble w, h;
- GnomeCanvasItem *item;
+ g_return_if_fail (view && GL_IS_VIEW (view));
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
- g_return_if_fail (label != NULL);
-
- gl_label_get_size (label, &w, &h);
- template = gl_label_get_template (label);
-
- /* Background */
- item = gnome_canvas_item_new (view->bg_group,
- gnome_canvas_rect_get_type (),
- "x1", 0.0,
- "y1", 0.0,
- "x2", w,
- "y2", h,
- "fill_color_rgba", PAPER_COLOR,
- NULL);
-
- /* Foreground */
- item = gnome_canvas_item_new (view->fg_group,
- gnome_canvas_rect_get_type (),
- "x1", 0.0,
- "y1", 0.0,
- "x2", w,
- "y2", h,
- "width_pixels", 2,
- "outline_color_rgba", OUTLINE_COLOR,
- NULL);
+ gl_view_update (view);
gl_debug (DEBUG_VIEW, "END");
}
+
/*---------------------------------------------------------------------------*/
-/* PRIVATE. Draw rounded recangular background. */
+/* PRIVATE. Handle label resize event. */
/*---------------------------------------------------------------------------*/
static void
-draw_bg_fg_rounded_rect (glView *view)
+label_resized_cb (glView *view)
{
- glLabel *label = view->label;
- GnomeCanvasPoints *points;
- gint i_coords, i_theta;
- glTemplate *template;
- gdouble r, w, h;
- GnomeCanvasItem *item;
+ g_return_if_fail (view && GL_IS_VIEW (view));
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
- g_return_if_fail (label != NULL);
-
- gl_label_get_size (label, &w, &h);
- template = gl_label_get_template (label);
- r = template->label.rect.r;
+ g_signal_emit_by_name (GTK_LAYOUT (view->canvas)->hadjustment, "changed");
+ g_signal_emit_by_name (GTK_LAYOUT (view->canvas)->vadjustment, "changed");
- points = gnome_canvas_points_new (4 * (1 + 90 / 5));
- i_coords = 0;
- for (i_theta = 0; i_theta <= 90; i_theta += 5) {
- points->coords[i_coords++] =
- r - r * sin (i_theta * M_PI / 180.0);
- points->coords[i_coords++] =
- r - r * cos (i_theta * M_PI / 180.0);
- }
- for (i_theta = 0; i_theta <= 90; i_theta += 5) {
- points->coords[i_coords++] =
- r - r * cos (i_theta * M_PI / 180.0);
- points->coords[i_coords++] =
- (h - r) + r * sin (i_theta * M_PI / 180.0);
- }
- for (i_theta = 0; i_theta <= 90; i_theta += 5) {
- points->coords[i_coords++] =
- (w - r) + r * sin (i_theta * M_PI / 180.0);
- points->coords[i_coords++] =
- (h - r) + r * cos (i_theta * M_PI / 180.0);
- }
- for (i_theta = 0; i_theta <= 90; i_theta += 5) {
- points->coords[i_coords++] =
- (w - r) + r * cos (i_theta * M_PI / 180.0);
- points->coords[i_coords++] =
- r - r * sin (i_theta * M_PI / 180.0);
- }
+ gl_view_update (view);
- /* Background */
- item = gnome_canvas_item_new (view->bg_group,
- gnome_canvas_polygon_get_type (),
- "points", points,
- "fill_color_rgba", PAPER_COLOR,
- NULL);
+ gl_debug (DEBUG_VIEW, "END");
+}
- /* Foreground */
- item = gnome_canvas_item_new (view->fg_group,
- gnome_canvas_polygon_get_type (),
- "points", points,
- "width_pixels", 2,
- "outline_color_rgba", OUTLINE_COLOR,
- NULL);
- gnome_canvas_points_free (points);
+/*---------------------------------------------------------------------------*/
+/* PRIVATE. Handle new label object. */
+/*---------------------------------------------------------------------------*/
+static void
+label_object_added_cb (glView *view,
+ glLabelObject *object)
+{
+ glViewObject *view_object;
- gl_debug (DEBUG_VIEW, "END");
+ g_return_if_fail (view && GL_IS_VIEW (view));
+ g_return_if_fail (object && GL_IS_LABEL_OBJECT (object));
+
+ if (GL_IS_LABEL_BOX (object)) {
+ view_object = gl_view_box_new (GL_LABEL_BOX(object), view);
+ } else if (GL_IS_LABEL_ELLIPSE (object)) {
+ view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(object), view);
+ } else if (GL_IS_LABEL_LINE (object)) {
+ view_object = gl_view_line_new (GL_LABEL_LINE(object), view);
+ } else if (GL_IS_LABEL_IMAGE (object)) {
+ view_object = gl_view_image_new (GL_LABEL_IMAGE(object), view);
+ } else if (GL_IS_LABEL_TEXT (object)) {
+ view_object = gl_view_text_new (GL_LABEL_TEXT(object), view);
+ } else if (GL_IS_LABEL_BARCODE (object)) {
+ view_object = gl_view_barcode_new (GL_LABEL_BARCODE(object), view);
+ } else {
+ /* Should not happen! */
+ view_object = NULL;
+ g_message ("Invalid label object type.");
+ }
+
+ gl_view_select_object (view, view_object);
}
/*---------------------------------------------------------------------------*/
-/* PRIVATE. Draw round background. */
+/* PRIVATE. Create, draw and order layers. */
/*---------------------------------------------------------------------------*/
static void
-draw_bg_fg_round (glView *view)
+draw_layers (glView *view,
+ cairo_t *cr)
{
- glLabel *label = view->label;
- glTemplate *template;
- gdouble r;
- GnomeCanvasItem *item;
+ gdouble scale;
+ gdouble w, h;
+ gint canvas_w, canvas_h;
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+ g_return_if_fail (view->label && GL_IS_LABEL (view->label));
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
- g_return_if_fail (label != NULL);
+ scale = view->zoom * view->home_scale;
+
+ gl_label_get_size (view->label, &w, &h);
- template = gl_label_get_template (label);
+ scale = view->home_scale * view->zoom;
+ gtk_layout_set_size (GTK_LAYOUT (view->canvas), w*scale+8, h*scale+8);
- r = template->label.round.r;
+ gdk_drawable_get_size (GTK_LAYOUT (view->canvas)->bin_window, &canvas_w, &canvas_h);
- /* Background */
- item = gnome_canvas_item_new (view->bg_group,
- gnome_canvas_ellipse_get_type (),
- "x1", 0.0,
- "y1", 0.0,
- "x2", 2.0*r,
- "y2", 2.0*r,
- "fill_color_rgba", PAPER_COLOR,
- NULL);
+ view->x0 = (canvas_w/scale - w) / 2.0;
+ view->y0 = (canvas_h/scale - h) / 2.0;
+ view->w = w;
+ view->h = h;
- /* Foreground */
- item = gnome_canvas_item_new (view->fg_group,
- gnome_canvas_ellipse_get_type (),
- "x1", 0.0,
- "y1", 0.0,
- "x2", 2.0*r,
- "y2", 2.0*r,
- "width_pixels", 2,
- "outline_color_rgba", OUTLINE_COLOR,
- NULL);
+ cairo_save (cr);
+
+ cairo_scale (cr, scale, scale);
+ cairo_translate (cr, view->x0, view->y0);
+
+ draw_bg_layer (view, cr);
+ draw_grid_layer (view, cr);
+ draw_markup_layer (view, cr);
+ draw_objects_layer (view, cr);
+ draw_fg_layer (view, cr);
+ draw_highlight_layer (view, cr);
+ draw_select_region_layer (view, cr);
+
+ cairo_restore (cr);
gl_debug (DEBUG_VIEW, "END");
+
}
/*---------------------------------------------------------------------------*/
-/* PRIVATE. Draw CD style background, circular w/ concentric hole. */
+/* PRIVATE. Draw background */
/*---------------------------------------------------------------------------*/
static void
-draw_bg_fg_cd (glView *view)
+draw_bg_layer (glView *view,
+ cairo_t *cr)
{
- glLabel *label = view->label;
- glTemplate *template;
- gdouble r1, r2;
- GnomeCanvasItem *item;
-
- gl_debug (DEBUG_VIEW, "START");
+ g_return_if_fail (view && GL_IS_VIEW (view));
+ g_return_if_fail (view->label && GL_IS_LABEL (view->label));
- g_return_if_fail (GL_IS_VIEW (view));
- g_return_if_fail (label != NULL);
-
- template = gl_label_get_template (label);
-
- r1 = template->label.cd.r1;
- r2 = template->label.cd.r2;
-
- /* Background */
- /* outer circle */
- item = gnome_canvas_item_new (view->bg_group,
- gnome_canvas_ellipse_get_type (),
- "x1", 0.0,
- "y1", 0.0,
- "x2", 2.0*r1,
- "y2", 2.0*r1,
- "fill_color_rgba", PAPER_COLOR,
- NULL);
- /* hole */
- item = gnome_canvas_item_new (view->bg_group,
- gnome_canvas_ellipse_get_type (),
- "x1", r1 - r2,
- "y1", r1 - r2,
- "x2", r1 + r2,
- "y2", r1 + r2,
- "fill_color_rgba", GRID_COLOR,
- NULL);
-
- /* Foreground */
- /* outer circle */
- item = gnome_canvas_item_new (view->fg_group,
- gnome_canvas_ellipse_get_type (),
- "x1", 0.0,
- "y1", 0.0,
- "x2", 2.0*r1,
- "y2", 2.0*r1,
- "width_pixels", 2,
- "outline_color_rgba", OUTLINE_COLOR,
- NULL);
- /* hole */
- item = gnome_canvas_item_new (view->fg_group,
- gnome_canvas_ellipse_get_type (),
- "x1", r1 - r2,
- "y1", r1 - r2,
- "x2", r1 + r2,
- "y2", r1 + r2,
- "width_pixels", 2,
- "outline_color_rgba", OUTLINE_COLOR,
- NULL);
+ gl_cairo_label_path (cr, view->label->template, view->label->rotate_flag, FALSE);
- gl_debug (DEBUG_VIEW, "END");
+ cairo_set_source_rgb (cr, PAPER_RGB_ARGS);
+ cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_fill (cr);
}
/*---------------------------------------------------------------------------*/
/* PRIVATE. Draw grid lines. */
/*---------------------------------------------------------------------------*/
static void
-draw_grid_layer (glView *view)
+draw_grid_layer (glView *view,
+ cairo_t *cr)
{
- gdouble w, h, x, y;
- GnomeCanvasPoints *points;
- GnomeCanvasItem *item;
- GnomeCanvasGroup *group;
+ gdouble w, h;
+ gdouble x, y;
+ gdouble x0, y0;
+ const lglTemplateFrame *frame;
gl_debug (DEBUG_VIEW, "START");
g_return_if_fail (view && GL_IS_VIEW (view));
g_return_if_fail (view->label && GL_IS_LABEL(view->label));
- gl_label_get_size (view->label, &w, &h);
+ if (view->grid_visible)
+ {
- group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
- view->grid_group = GNOME_CANVAS_GROUP(
- gnome_canvas_item_new (group,
- gnome_canvas_group_get_type (),
- "x", 0.0,
- "y", 0.0,
- NULL));
- points = gnome_canvas_points_new (2);
-
- points->coords[1] = 0.0;
- points->coords[3] = h;
- for ( x=0.0; x < w; x += view->grid_spacing ) {
- points->coords[0] = points->coords[2] = x;
- item = gnome_canvas_item_new (view->grid_group,
- gnome_canvas_line_get_type (),
- "points", points,
- "width_pixels", 1,
- "fill_color_rgba", GRID_COLOR,
- NULL);
- }
- points->coords[0] = points->coords[2] = w;
- item = gnome_canvas_item_new (view->grid_group,
- gnome_canvas_line_get_type (),
- "points", points,
- "width_pixels", 1,
- "fill_color_rgba", GRID_COLOR,
- NULL);
-
- points->coords[0] = 0.0;
- points->coords[2] = w;
- for ( y=0.0; y < h; y += view->grid_spacing ) {
- points->coords[1] = points->coords[3] = y;
- item = gnome_canvas_item_new (view->grid_group,
- gnome_canvas_line_get_type (),
- "points", points,
- "width_pixels", 1,
- "fill_color_rgba", GRID_COLOR,
- NULL);
- }
- points->coords[1] = points->coords[3] = h;
- item = gnome_canvas_item_new (view->grid_group,
- gnome_canvas_line_get_type (),
- "points", points,
- "width_pixels", 1,
- "fill_color_rgba", GRID_COLOR,
- NULL);
-
- gnome_canvas_points_free (points);
-
- gl_debug (DEBUG_VIEW, "END");
-}
-
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. Draw markup lines. */
-/*---------------------------------------------------------------------------*/
-static void
-draw_markup_layer (glView *view)
-{
- GnomeCanvasGroup *group;
- glLabel *label;
- glTemplate *template;
- GList *p;
- glTemplateMarkup *markup;
-
- group = gnome_canvas_root (GNOME_CANVAS (view->canvas));
- view->markup_group = GNOME_CANVAS_GROUP(
- gnome_canvas_item_new (group,
- gnome_canvas_group_get_type (),
- "x", 0.0,
- "y", 0.0,
- NULL));
- label = view->label;
- template = gl_label_get_template (label);
-
- for ( p=template->label.any.markups; p != NULL; p=p->next ) {
- markup = (glTemplateMarkup *)p->data;
-
- switch (markup->type) {
- case GL_TEMPLATE_MARKUP_MARGIN:
- draw_markup_margin (view,
- (glTemplateMarkupMargin *)markup);
- break;
- default:
- g_warning ("Unknown template markup type");
- break;
- }
- }
-}
+ frame = lgl_template_get_first_frame (view->label->template);
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. Draw margin markup. */
-/*---------------------------------------------------------------------------*/
-static void
-draw_markup_margin (glView *view,
- glTemplateMarkupMargin *margin)
-{
- glLabel *label;
- glTemplate *template;
+ gl_label_get_size (view->label, &w, &h);
+
+ if (frame->shape == LGL_TEMPLATE_FRAME_SHAPE_RECT) {
+ x0 = 0.0;
+ y0 = 0.0;
+ } else {
+ /* round labels, adjust grid to line up with center of label. */
+ x0 = fmod (w/2.0, view->grid_spacing);
+ y0 = fmod (h/2.0, view->grid_spacing);
+ }
- label = view->label;
- template = gl_label_get_template (label);
- switch (template->label.style) {
+ cairo_save (cr);
- case GL_TEMPLATE_STYLE_RECT:
- if (template->label.rect.r == 0.0) {
- /* Square corners. */
- draw_markup_margin_rect (view, margin);
- } else {
- if ( margin->size < template->label.rect.r) {
- /* Rounded corners. */
- draw_markup_margin_rounded_rect (view, margin);
- } else {
- /* Square corners. */
- draw_markup_margin_rect (view, margin);
- }
- }
- break;
+ cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
+ cairo_set_line_width (cr, GRID_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
+ cairo_set_source_rgb (cr, GRID_RGB_ARGS);
- case GL_TEMPLATE_STYLE_ROUND:
- draw_markup_margin_round (view, margin);
- break;
+ for ( x=x0+view->grid_spacing; x < w; x += view->grid_spacing )
+ {
+ cairo_move_to (cr, x, 0);
+ cairo_line_to (cr, x, h);
+ cairo_stroke (cr);
+ }
- case GL_TEMPLATE_STYLE_CD:
- draw_markup_margin_cd (view, margin);
- break;
+ for ( y=y0+view->grid_spacing; y < h; y += view->grid_spacing )
+ {
+ cairo_move_to (cr, 0, y);
+ cairo_line_to (cr, w, y);
+ cairo_stroke (cr);
+ }
- default:
- g_warning ("Unknown template label style");
- break;
- }
+ cairo_restore (cr);
+
+ }
+
+ gl_debug (DEBUG_VIEW, "END");
}
/*---------------------------------------------------------------------------*/
-/* PRIVATE. Draw simple recangular margin. */
+/* PRIVATE. Draw markup layer. */
/*---------------------------------------------------------------------------*/
static void
-draw_markup_margin_rect (glView *view,
- glTemplateMarkupMargin *margin)
+draw_markup_layer (glView *view,
+ cairo_t *cr)
{
- glLabel *label = view->label;
- glTemplate *template;
- gdouble w, h, m;
- GnomeCanvasItem *item;
+ glLabel *label;
+ const lglTemplateFrame *frame;
+ GList *p;
+ lglTemplateMarkup *markup;
- gl_debug (DEBUG_VIEW, "START");
+ g_return_if_fail (view && GL_IS_VIEW (view));
+ g_return_if_fail (view->label && GL_IS_LABEL (view->label));
- g_return_if_fail (GL_IS_VIEW (view));
- g_return_if_fail (label != NULL);
+ if (view->markup_visible)
+ {
- gl_label_get_size (label, &w, &h);
- template = gl_label_get_template (label);
- m = margin->size;
+ label = view->label;
+ frame = lgl_template_get_first_frame (label->template);
- /* Bounding box @ margin */
- gnome_canvas_item_new (view->markup_group,
- gnome_canvas_rect_get_type (),
- "x1", m,
- "y1", m,
- "x2", w - m,
- "y2", h - m,
- "width_pixels", 1,
- "outline_color_rgba", MARKUP_COLOR,
- NULL);
+ cairo_save (cr);
+
+ cairo_set_line_width (cr, MARKUP_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
+ cairo_set_source_rgb (cr, MARKUP_RGB_ARGS);
+
+ for ( p=frame->all.markups; p != NULL; p=p->next )
+ {
+ markup = (lglTemplateMarkup *)p->data;
+
+ gl_cairo_markup_path (cr, markup, label);
+
+ cairo_stroke (cr);
+ }
+
+ cairo_restore (cr);
+ }
- gl_debug (DEBUG_VIEW, "END");
}
/*---------------------------------------------------------------------------*/
-/* PRIVATE. Draw rounded recangular markup. */
+/* PRIVATE. Draw objects layer. */
/*---------------------------------------------------------------------------*/
static void
-draw_markup_margin_rounded_rect (glView *view,
- glTemplateMarkupMargin *margin)
+draw_objects_layer (glView *view,
+ cairo_t *cr)
{
- glLabel *label = view->label;
- GnomeCanvasPoints *points;
- gint i_coords, i_theta;
- glTemplate *template;
- gdouble r, w, h, m;
- GnomeCanvasItem *item;
-
- gl_debug (DEBUG_VIEW, "START");
-
- g_return_if_fail (GL_IS_VIEW (view));
- g_return_if_fail (label != NULL);
-
- gl_label_get_size (label, &w, &h);
- template = gl_label_get_template (label);
- r = template->label.rect.r;
- m = margin->size;
+ gl_label_draw (view->label, cr, TRUE, NULL);
+}
- r = r - m;
- w = w - 2 * m;
- h = h - 2 * m;
+/*---------------------------------------------------------------------------*/
+/* PRIVATE. Draw foreground */
+/*---------------------------------------------------------------------------*/
+static void
+draw_fg_layer (glView *view,
+ cairo_t *cr)
+{
+ g_return_if_fail (view && GL_IS_VIEW (view));
+ g_return_if_fail (view->label && GL_IS_LABEL (view->label));
- /* rectangle with rounded corners */
- points = gnome_canvas_points_new (4 * (1 + 90 / 5));
- i_coords = 0;
- for (i_theta = 0; i_theta <= 90; i_theta += 5) {
- points->coords[i_coords++] =
- m + r - r * sin (i_theta * M_PI / 180.0);
- points->coords[i_coords++] =
- m + r - r * cos (i_theta * M_PI / 180.0);
- }
- for (i_theta = 0; i_theta <= 90; i_theta += 5) {
- points->coords[i_coords++] =
- m + r - r * cos (i_theta * M_PI / 180.0);
- points->coords[i_coords++] =
- m + (h - r) + r * sin (i_theta * M_PI / 180.0);
- }
- for (i_theta = 0; i_theta <= 90; i_theta += 5) {
- points->coords[i_coords++] =
- m + (w - r) + r * sin (i_theta * M_PI / 180.0);
- points->coords[i_coords++] =
- m + (h - r) + r * cos (i_theta * M_PI / 180.0);
- }
- for (i_theta = 0; i_theta <= 90; i_theta += 5) {
- points->coords[i_coords++] =
- m + (w - r) + r * cos (i_theta * M_PI / 180.0);
- points->coords[i_coords++] =
- m + r - r * sin (i_theta * M_PI / 180.0);
- }
- item = gnome_canvas_item_new (view->markup_group,
- gnome_canvas_polygon_get_type (),
- "points", points,
- "width_pixels", 1,
- "outline_color_rgba", MARKUP_COLOR,
- NULL);
- gnome_canvas_points_free (points);
+ gl_cairo_label_path (cr, view->label->template, view->label->rotate_flag, FALSE);
- gl_debug (DEBUG_VIEW, "END");
+ cairo_set_line_width (cr, OUTLINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
+ cairo_set_source_rgb (cr, OUTLINE_RGB_ARGS);
+ cairo_stroke (cr);
}
/*---------------------------------------------------------------------------*/
-/* PRIVATE. Draw round margin. */
+/* PRIVATE. Create highlight layer. */
/*---------------------------------------------------------------------------*/
static void
-draw_markup_margin_round (glView *view,
- glTemplateMarkupMargin *margin)
+draw_highlight_layer (glView *view,
+ cairo_t *cr)
{
- glLabel *label = view->label;
- glTemplate *template;
- gdouble r, m;
- GnomeCanvasItem *item;
+ GList *p_obj;
+ glViewObject *view_object;
- gl_debug (DEBUG_VIEW, "START");
+ g_return_if_fail (view && GL_IS_VIEW (view));
- g_return_if_fail (GL_IS_VIEW (view));
- g_return_if_fail (label != NULL);
+ cairo_save (cr);
- template = gl_label_get_template (label);
+ cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
- r = template->label.round.r;
- m = margin->size;
+ for (p_obj = view->selected_object_list; p_obj != NULL; p_obj = p_obj->next)
+ {
+ view_object = GL_VIEW_OBJECT (p_obj->data);
- /* Margin outline */
- item = gnome_canvas_item_new (view->markup_group,
- gnome_canvas_ellipse_get_type (),
- "x1", m,
- "y1", m,
- "x2", 2.0*r - m,
- "y2", 2.0*r - m,
- "width_pixels", 1,
- "outline_color_rgba", MARKUP_COLOR,
- NULL);
+ gl_view_object_draw_handles (view_object, cr);
+ }
- gl_debug (DEBUG_VIEW, "END");
+ cairo_restore (cr);
}
/*---------------------------------------------------------------------------*/
-/* PRIVATE. Draw CD margins. */
+/* PRIVATE. Draw select region layer. */
/*---------------------------------------------------------------------------*/
static void
-draw_markup_margin_cd (glView *view,
- glTemplateMarkupMargin *margin)
+draw_select_region_layer (glView *view,
+ cairo_t *cr)
{
- glLabel *label = view->label;
- glTemplate *template;
- gdouble m, r1, r2;
- GnomeCanvasItem *item;
+ gdouble x1, y1;
+ gdouble w, h;
- gl_debug (DEBUG_VIEW, "START");
+ g_return_if_fail (view && GL_IS_VIEW (view));
- g_return_if_fail (GL_IS_VIEW (view));
- g_return_if_fail (label != NULL);
+ if (view->select_region_visible)
+ {
+ x1 = MIN (view->select_region.x1, view->select_region.x2);
+ y1 = MIN (view->select_region.y1, view->select_region.y2);
+ w = fabs (view->select_region.x2 - view->select_region.x1);
+ h = fabs (view->select_region.y2 - view->select_region.y1);
- template = gl_label_get_template (label);
+ cairo_save (cr);
- r1 = template->label.cd.r1;
- r2 = template->label.cd.r2;
- m = margin->size;
+ cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
- /* outer margin */
- item = gnome_canvas_item_new (view->markup_group,
- gnome_canvas_ellipse_get_type (),
- "x1", m,
- "y1", m,
- "x2", 2.0*r1 - m,
- "y2", 2.0*r1 - m,
- "width_pixels", 1,
- "outline_color_rgba", MARKUP_COLOR,
- NULL);
- /* inner margin */
- item = gnome_canvas_item_new (view->markup_group,
- gnome_canvas_ellipse_get_type (),
- "x1", r1 - r2 - m,
- "y1", r1 - r2 - m,
- "x2", r1 + r2 + m,
- "y2", r1 + r2 + m,
- "width_pixels", 1,
- "outline_color_rgba", MARKUP_COLOR,
- NULL);
+ cairo_rectangle (cr, x1, y1, w, h);
- gl_debug (DEBUG_VIEW, "END");
-}
+ cairo_set_source_rgba (cr, SELECT_FILL_RGBA_ARGS);
+ cairo_fill_preserve (cr);
-/*****************************************************************************/
-/* Raise foreground items to top. */
-/*****************************************************************************/
-void
-gl_view_raise_fg (glView *view)
-{
- GList *p;
+ cairo_set_line_width (cr, SELECT_LINE_WIDTH_PIXELS/(view->home_scale * view->zoom));
+ cairo_set_source_rgba (cr, SELECT_LINE_RGBA_ARGS);
+ cairo_stroke (cr);
- gnome_canvas_item_raise_to_top (GNOME_CANVAS_ITEM(view->fg_group));
+ cairo_restore (cr);
+ }
}
/*****************************************************************************/
/* Show grid. */
/*****************************************************************************/
-void gl_view_show_grid (glView *view)
+void
+gl_view_show_grid (glView *view)
{
- gnome_canvas_item_show (GNOME_CANVAS_ITEM(view->grid_group));
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ view->grid_visible = TRUE;
+ gl_view_update (view);
}
/*****************************************************************************/
/* Hide grid. */
/*****************************************************************************/
-void gl_view_hide_grid (glView *view)
+void
+gl_view_hide_grid (glView *view)
{
- gnome_canvas_item_hide (GNOME_CANVAS_ITEM(view->grid_group));
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ view->grid_visible = FALSE;
+ gl_view_update (view);
}
/*****************************************************************************/
/* Set grid spacing. */
/*****************************************************************************/
-void gl_view_set_grid_spacing (glView *view,
- gdouble spacing)
+void
+gl_view_set_grid_spacing (glView *view,
+ gdouble spacing)
{
- view->grid_spacing = spacing;
+ g_return_if_fail (view && GL_IS_VIEW (view));
- gtk_object_destroy (GTK_OBJECT(view->grid_group));
- draw_grid_layer (view);
+ view->grid_spacing = spacing;
+ gl_view_update (view);
}
/*****************************************************************************/
/* Show markup. */
/*****************************************************************************/
-void gl_view_show_markup (glView *view)
+void
+gl_view_show_markup (glView *view)
{
- gnome_canvas_item_show (GNOME_CANVAS_ITEM(view->markup_group));
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ view->markup_visible = TRUE;
+ gl_view_update (view);
}
/*****************************************************************************/
/* Hide markup. */
/*****************************************************************************/
-void gl_view_hide_markup (glView *view)
+void
+gl_view_hide_markup (glView *view)
{
- gnome_canvas_item_hide (GNOME_CANVAS_ITEM(view->markup_group));
-}
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ view->markup_visible = FALSE;
+ gl_view_update (view);
+}
/*****************************************************************************/
/* Set arrow mode. */
void
gl_view_arrow_mode (glView *view)
{
- static GdkCursor *cursor = NULL;
+ GdkCursor *cursor;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
-
- if (!cursor) {
- cursor = gdk_cursor_new (GDK_LEFT_PTR);
- }
+ g_return_if_fail (view && GL_IS_VIEW (view));
+ cursor = gdk_cursor_new (GDK_LEFT_PTR);
gdk_window_set_cursor (view->canvas->window, cursor);
+ gdk_cursor_unref (cursor);
- view->state = GL_VIEW_STATE_ARROW;
+ view->mode = GL_VIEW_MODE_ARROW;
+ view->state = GL_VIEW_IDLE;
gl_debug (DEBUG_VIEW, "END");
}
/*****************************************************************************/
void
gl_view_object_create_mode (glView *view,
- glLabelObjectType type)
+ glLabelObjectType type)
{
- GdkCursor *cursor;
+ GdkCursor *cursor = NULL;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
- switch (type) {
+ switch (type)
+ {
case GL_LABEL_OBJECT_BOX:
cursor = gl_view_box_get_create_cursor ();
break;
cursor = gl_view_barcode_get_create_cursor ();
break;
default:
- g_warning ("Invalid label object type.");/*Should not happen!*/
+ g_message ("Invalid label object type.");/*Should not happen!*/
break;
}
gdk_window_set_cursor (view->canvas->window, cursor);
+ gdk_cursor_unref (cursor);
- view->state = GL_VIEW_STATE_OBJECT_CREATE;
+ view->mode = GL_VIEW_MODE_OBJECT_CREATE;
+ view->state = GL_VIEW_IDLE;
view->create_type = type;
gl_debug (DEBUG_VIEW, "END");
{
gl_debug (DEBUG_VIEW, "START");
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
select_object_real (view, view_object);
g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
{
gl_debug (DEBUG_VIEW, "START");
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
unselect_object_real (view, view_object);
g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
/* 1st unselect anything already selected. */
for (p = view->selected_object_list; p != NULL; p = p_next) {
void
gl_view_unselect_all (glView *view)
{
- GList *p, *p_next;
+ GList *p;
+ GList *p_next;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
for (p = view->selected_object_list; p != NULL; p = p_next) {
p_next = p->next;
/* Select all objects within given rectangular region (adding to selection). */
/*****************************************************************************/
void
-gl_view_select_region (glView *view,
- gdouble x1,
- gdouble y1,
- gdouble x2,
- gdouble y2)
+gl_view_select_region (glView *view,
+ glLabelRegion *region)
{
- GList *p;
- glViewObject *view_object;
+ GList *p;
+ glViewObject *view_object;
glLabelObject *object;
- gdouble i_x1, i_y1, i_x2, i_y2, w, h;
+ gdouble r_x1, r_y1;
+ gdouble r_x2, r_y2;
+ glLabelRegion obj_extent;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
- g_return_if_fail ((x1 <= x2) && (y1 <= y2));
+ g_return_if_fail (view && GL_IS_VIEW (view));
- for (p = view->object_list; p != NULL; p = p->next) {
+ r_x1 = MIN (region->x1, region->x2);
+ r_y1 = MIN (region->y1, region->y2);
+ r_x2 = MAX (region->x1, region->x2);
+ r_y2 = MAX (region->y1, region->y2);
+
+ for (p = view->object_list; p != NULL; p = p->next)
+ {
view_object = GL_VIEW_OBJECT(p->data);
- if (!is_object_selected (view, view_object)) {
+ if (!gl_view_is_object_selected (view, view_object))
+ {
object = gl_view_object_get_object (view_object);
- gl_label_object_get_position (object, &i_x1, &i_y1);
- gl_label_object_get_size (object, &w, &h);
- i_x2 = i_x1 + w;
- i_y2 = i_y1 + h;
- if ((i_x1 >= x1) && (i_x2 <= x2) && (i_y1 >= y1)
- && (i_y2 <= y2)) {
+ gl_label_object_get_extent (object, &obj_extent);
+ if ((obj_extent.x1 >= r_x1) &&
+ (obj_extent.x2 <= r_x2) &&
+ (obj_extent.y1 >= r_y1) &&
+ (obj_extent.y2 <= r_y2))
+ {
select_object_real (view, view_object);
}
{
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
- if (!is_object_selected (view, view_object)) {
+ if (!gl_view_is_object_selected (view, view_object)) {
view->selected_object_list =
- g_list_prepend (view->selected_object_list, view_object);
+ g_list_append (view->selected_object_list, view_object);
}
- gl_view_object_show_highlight (view_object);
gtk_widget_grab_focus (GTK_WIDGET (view->canvas));
+ gl_view_update (view);
+
gl_debug (DEBUG_VIEW, "END");
}
{
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
- gl_view_object_hide_highlight (view_object);
-
view->selected_object_list =
g_list_remove (view->selected_object_list, view_object);
+ gl_view_update (view);
+
gl_debug (DEBUG_VIEW, "END");
}
/*---------------------------------------------------------------------------*/
/* PRIVATE. Return object at (x,y). */
/*---------------------------------------------------------------------------*/
-static gboolean
-object_at (glView *view,
- gdouble x,
- gdouble y)
+static glViewObject *
+view_view_object_at (glView *view,
+ cairo_t *cr,
+ gdouble x,
+ gdouble y)
{
- GnomeCanvasItem *item, *p_item;
- GList *p;
+ GList *p_obj;
+ glViewObject *view_object;
- gl_debug (DEBUG_VIEW, "");
+ g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
- g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
+ for (p_obj = g_list_last (view->object_list); p_obj != NULL; p_obj = p_obj->prev)
+ {
- item = gnome_canvas_get_item_at (GNOME_CANVAS (view->canvas), x, y);
+ view_object = GL_VIEW_OBJECT (p_obj->data);
- /* No item is at x, y */
- if (item == NULL)
- return FALSE;
+ if (gl_view_object_at (view_object, cr, x, y))
+ {
+ return view_object;
+ }
- /* ignore items not in label group, e.g. background items */
- if (!is_item_member_of_group(view, item, GNOME_CANVAS_ITEM(view->label_group)))
- return FALSE;
+ }
- return TRUE;
+ return NULL;
}
/*---------------------------------------------------------------------------*/
-/* PRIVATE. Is the item a child (or grandchild, etc.) of group. */
+/* PRIVATE. Return object handle at (x,y). */
/*---------------------------------------------------------------------------*/
-static gboolean
-is_item_member_of_group (glView *view,
- GnomeCanvasItem *item,
- GnomeCanvasItem *group)
+static glViewObject *
+view_handle_at (glView *view,
+ cairo_t *cr,
+ gdouble x,
+ gdouble y,
+ glViewObjectHandle *handle)
{
- GnomeCanvasItem *parent;
- GnomeCanvasItem *root_group;
+ GList *p_obj;
+ glViewObject *view_object;
+
+ g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
- root_group = GNOME_CANVAS_ITEM(gnome_canvas_root (GNOME_CANVAS (view->canvas)));
+ for (p_obj = g_list_last (view->selected_object_list); p_obj != NULL; p_obj = p_obj->prev)
+ {
+
+ view_object = GL_VIEW_OBJECT (p_obj->data);
+
+ if ((*handle = gl_view_object_handle_at (view_object, cr, x, y)))
+ {
+ return view_object;
+ }
- for ( parent=item->parent; parent && (parent!=root_group); parent=parent->parent) {
- if (parent == group) return TRUE;
}
- return FALSE;
+
+ return NULL;
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. Is the object in our current selection? */
-/*---------------------------------------------------------------------------*/
-static gboolean
-is_object_selected (glView *view,
- glViewObject *view_object)
+/*****************************************************************************/
+/* Is the object in our current selection? */
+/*****************************************************************************/
+gboolean
+gl_view_is_object_selected (glView *view,
+ glViewObject *view_object)
{
gl_debug (DEBUG_VIEW, "");
- g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
+ g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
g_return_val_if_fail (GL_IS_VIEW_OBJECT (view_object), FALSE);
if (g_list_find (view->selected_object_list, view_object) == NULL) {
{
gl_debug (DEBUG_VIEW, "");
- g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
+ g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
if (view->selected_object_list == NULL) {
return TRUE;
{
gl_debug (DEBUG_VIEW, "");
- g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
+ g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
if (view->selected_object_list == NULL)
return FALSE;
void
gl_view_delete_selection (glView *view)
{
- GList *p, *p_next;
+ GList *object_list;
+ GList *p;
+ GList *p_next;
+ glViewObject *view_object;
+ glLabelObject *object;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
- for (p = view->selected_object_list; p != NULL; p = p_next) {
+ object_list = view->selected_object_list;
+ view->selected_object_list = NULL;
+ g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
+
+ for (p = object_list; p != NULL; p = p_next) {
p_next = p->next;
- g_object_unref (G_OBJECT (p->data));
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_remove (object);
}
- g_signal_emit (G_OBJECT(view), signals[SELECTION_CHANGED], 0);
+ g_list_free (object_list);
gl_debug (DEBUG_VIEW, "END");
}
/*****************************************************************************/
-/* Edit properties of selected object. */
+/* Get object property editor of first selected object. */
/*****************************************************************************/
-void
-gl_view_edit_object_props (glView *view)
+GtkWidget *
+gl_view_get_editor (glView *view)
{
glViewObject *view_object;
+ GtkWidget *editor = NULL;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
- if (gl_view_is_selection_atomic (view)) {
+ if (!gl_view_is_selection_empty (view)) {
view_object = GL_VIEW_OBJECT(view->selected_object_list->data);
- gl_view_object_show_dialog (view_object);
+ editor = gl_view_object_get_editor (view_object);
}
gl_debug (DEBUG_VIEW, "END");
+
+ return editor;
}
/*****************************************************************************/
void
gl_view_raise_selection (glView *view)
{
- GList *p;
- glViewObject *view_object;
- glLabelObject *label_object;
+ GList *p;
+ glViewObject *view_object;
+ glLabelObject *object;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
for (p = view->selected_object_list; p != NULL; p = p->next) {
view_object = GL_VIEW_OBJECT (p->data);
- label_object = gl_view_object_get_object (view_object);
- gl_label_object_raise_to_top (label_object);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_raise_to_top (object);
}
gl_debug (DEBUG_VIEW, "END");
void
gl_view_lower_selection (glView *view)
{
- GList *p;
- glViewObject *view_object;
- glLabelObject *label_object;
+ GList *p;
+ glViewObject *view_object;
+ glLabelObject *object;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
for (p = view->selected_object_list; p != NULL; p = p->next) {
view_object = GL_VIEW_OBJECT (p->data);
- label_object = gl_view_object_get_object (view_object);
- gl_label_object_lower_to_bottom (label_object);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_lower_to_bottom (object);
}
gl_debug (DEBUG_VIEW, "END");
}
/*****************************************************************************/
-/* Flip selected objects horizontally. */
+/* Rotate selected objects by given angle. */
/*****************************************************************************/
void
-gl_view_flip_selection_horiz (glView *view)
+gl_view_rotate_selection (glView *view,
+ gdouble theta_degs)
{
- GList *p;
- glViewObject *view_object;
- glLabelObject *label_object;
+ GList *p;
+ glViewObject *view_object;
+ glLabelObject *object;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
for (p = view->selected_object_list; p != NULL; p = p->next) {
view_object = GL_VIEW_OBJECT (p->data);
- label_object = gl_view_object_get_object (view_object);
- gl_label_object_flip_horiz (label_object);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_rotate (object, theta_degs);
}
gl_debug (DEBUG_VIEW, "END");
}
/*****************************************************************************/
-/* Flip selected objects vertically. */
+/* Rotate selected objects 90 degrees left. */
/*****************************************************************************/
void
-gl_view_flip_selection_vert (glView *view)
+gl_view_rotate_selection_left (glView *view)
{
- GList *p;
- glViewObject *view_object;
- glLabelObject *label_object;
+ GList *p;
+ glViewObject *view_object;
+ glLabelObject *object;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
for (p = view->selected_object_list; p != NULL; p = p->next) {
view_object = GL_VIEW_OBJECT (p->data);
- label_object = gl_view_object_get_object (view_object);
- gl_label_object_flip_vert (label_object);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_rotate (object, -90.0);
}
gl_debug (DEBUG_VIEW, "END");
}
/*****************************************************************************/
-/* "Cut" selected items and place in clipboard selections. */
+/* Rotate selected objects 90 degrees right. */
/*****************************************************************************/
void
-gl_view_cut (glView *view)
+gl_view_rotate_selection_right (glView *view)
{
+ GList *p;
+ glViewObject *view_object;
+ glLabelObject *object;
+
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
- gl_view_copy (view);
- gl_view_delete_selection (view);
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_rotate (object, 90.0);
+ }
gl_debug (DEBUG_VIEW, "END");
}
/*****************************************************************************/
-/* "Copy" selected items to clipboard selections. */
+/* Flip selected objects horizontally. */
/*****************************************************************************/
void
-gl_view_copy (glView *view)
+gl_view_flip_selection_horiz (glView *view)
{
- GList *p;
- glViewObject *view_object;
+ GList *p;
+ glViewObject *view_object;
glLabelObject *object;
- glTemplate *template;
- gboolean rotate_flag;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
-
- if (view->selected_object_list) {
-
- if ( view->selection_data ) {
- g_object_unref (view->selection_data);
- }
- template = gl_label_get_template (view->label);
- rotate_flag = gl_label_get_rotate_flag (view->label);
- view->selection_data = GL_LABEL(gl_label_new ());
- gl_label_set_template (view->selection_data, template);
- gl_label_set_rotate_flag (view->selection_data, rotate_flag);
- gl_template_free (&template);
-
- for (p = view->selected_object_list; p != NULL; p = p->next) {
-
- view_object = GL_VIEW_OBJECT (p->data);
- object = gl_view_object_get_object (view_object);
-
- gl_debug (DEBUG_VIEW, "Object copied");
-
- if (GL_IS_LABEL_BOX (object)) {
- gl_label_box_dup (GL_LABEL_BOX(object),
- view->selection_data);
- } else if (GL_IS_LABEL_ELLIPSE (object)) {
- gl_label_ellipse_dup (GL_LABEL_ELLIPSE(object),
- view->selection_data);
- } else if (GL_IS_LABEL_LINE (object)) {
- gl_label_line_dup (GL_LABEL_LINE(object),
- view->selection_data);
- } else if (GL_IS_LABEL_IMAGE (object)) {
- gl_label_image_dup (GL_LABEL_IMAGE(object),
- view->selection_data);
- } else if (GL_IS_LABEL_TEXT (object)) {
- gl_label_text_dup (GL_LABEL_TEXT(object),
- view->selection_data);
- } else if (GL_IS_LABEL_BARCODE (object)) {
- gl_label_barcode_dup (GL_LABEL_BARCODE(object),
- view->selection_data);
- } else {
- /* Should not happen! */
- g_warning ("Invalid label object type.");
- }
-
-
- }
-
- gtk_selection_owner_set (view->invisible,
- clipboard_atom, GDK_CURRENT_TIME);
- view->have_selection = TRUE;
+ g_return_if_fail (view && GL_IS_VIEW (view));
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_flip_horiz (object);
}
gl_debug (DEBUG_VIEW, "END");
}
/*****************************************************************************/
-/* "Paste" from private clipboard selection. */
+/* Flip selected objects vertically. */
/*****************************************************************************/
void
-gl_view_paste (glView *view)
+gl_view_flip_selection_vert (glView *view)
{
+ GList *p;
+ glViewObject *view_object;
+ glLabelObject *object;
+
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
- gtk_selection_convert (GTK_WIDGET (view->invisible),
- clipboard_atom, GDK_SELECTION_TYPE_STRING,
- GDK_CURRENT_TIME);
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_flip_vert (object);
+ }
gl_debug (DEBUG_VIEW, "END");
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. move selected objects */
-/*---------------------------------------------------------------------------*/
-static void
-move_selection (glView *view,
- gdouble dx,
- gdouble dy)
+/*****************************************************************************/
+/* Align selected objects to left most edge. */
+/*****************************************************************************/
+void
+gl_view_align_selection_left (glView *view)
{
- GList *p;
+ GList *p;
+ glViewObject *view_object;
glLabelObject *object;
+ gdouble dx, x1_min;
+ glLabelRegion obj_extent;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
-
- for (p = view->selected_object_list; p != NULL; p = p->next) {
+ g_return_if_fail (view && GL_IS_VIEW (view));
- object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
- gl_label_object_set_position_relative (object, dx, dy);
+ g_return_if_fail (!gl_view_is_selection_empty (view) &&
+ !gl_view_is_selection_atomic (view));
+
+ /* find left most edge */
+ p = view->selected_object_list;
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ x1_min = obj_extent.x1;
+ for (p = p->next; p != NULL; p = p->next)
+ {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ if ( obj_extent.x1 < x1_min ) x1_min = obj_extent.x1;
+ }
+ /* now adjust the object positions to line up the left edges */
+ for (p = view->selected_object_list; p != NULL; p = p->next)
+ {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ dx = x1_min - obj_extent.x1;
+ gl_label_object_set_position_relative (object, dx, 0.0);
}
gl_debug (DEBUG_VIEW, "END");
}
+
/*****************************************************************************/
-/* Zoom in one "notch" */
+/* Align selected objects to right most edge. */
/*****************************************************************************/
void
-gl_view_zoom_in (glView *view)
+gl_view_align_selection_right (glView *view)
{
- gint i, i_min;
- gdouble dist, dist_min;
+ GList *p;
+ glViewObject *view_object;
+ glLabelObject *object;
+ gdouble dx, x2_max;
+ glLabelRegion obj_extent;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
- /* Find index of current scale (or best match) */
- i_min = 1; /* start with 2nd largest scale */
- dist_min = fabs (scales[1] - view->scale);
- for (i = 2; i < N_SCALES; i++) {
- dist = fabs (scales[i] - view->scale);
- if (dist < dist_min) {
- i_min = i;
- dist_min = dist;
- }
+ g_return_if_fail (!gl_view_is_selection_empty (view) &&
+ !gl_view_is_selection_atomic (view));
+
+ /* find right most edge */
+ p = view->selected_object_list;
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ x2_max = obj_extent.x2;
+ for (p = p->next; p != NULL; p = p->next)
+ {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ if ( obj_extent.x2 > x2_max ) x2_max = obj_extent.x2;
}
- /* zoom in one "notch" */
- i = MAX (0, i_min - 1);
- gl_view_set_zoom (view, scales[i] / HOME_SCALE);
+ /* now adjust the object positions to line up the right edges */
+ for (p = view->selected_object_list; p != NULL; p = p->next)
+ {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ dx = x2_max - obj_extent.x2;
+ gl_label_object_set_position_relative (object, dx, 0.0);
+ }
gl_debug (DEBUG_VIEW, "END");
}
/*****************************************************************************/
-/* Zoom out one "notch" */
+/* Align selected objects to horizontal center of objects. */
/*****************************************************************************/
void
-gl_view_zoom_out (glView *view)
+gl_view_align_selection_hcenter (glView *view)
{
- gint i, i_min;
- gdouble dist, dist_min;
+ GList *p;
+ glViewObject *view_object;
+ glLabelObject *object;
+ gdouble dx;
+ gdouble dxmin;
+ gdouble xsum, xavg;
+ glLabelRegion obj_extent;
+ gdouble xcenter;
+ gint n;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
- /* Find index of current scale (or best match) */
- i_min = 0; /* start with largest scale */
- dist_min = fabs (scales[0] - view->scale);
- for (i = 1; i < N_SCALES; i++) {
- dist = fabs (scales[i] - view->scale);
- if (dist < dist_min) {
- i_min = i;
- dist_min = dist;
+ g_return_if_fail (!gl_view_is_selection_empty (view) &&
+ !gl_view_is_selection_atomic (view));
+
+ /* find average center of objects */
+ xsum = 0.0;
+ n = 0;
+ for (p = view->selected_object_list; p != NULL; p = p->next)
+ {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ xsum += (obj_extent.x1 + obj_extent.x2) / 2.0;
+ n++;
+ }
+ xavg = xsum / n;
+
+ /* find center of object closest to average center */
+ p = view->selected_object_list;
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ dxmin = fabs (xavg - (obj_extent.x1 + obj_extent.x2)/2.0);
+ xcenter = (obj_extent.x1 + obj_extent.x2)/2.0;
+ for (p = p->next; p != NULL; p = p->next)
+ {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ dx = fabs (xavg - (obj_extent.x1 + obj_extent.x2)/2.0);
+ if ( dx < dxmin )
+ {
+ dxmin = dx;
+ xcenter = (obj_extent.x1 + obj_extent.x2)/2.0;
}
}
- /* zoom out one "notch" */
- if (i_min >= N_SCALES)
- return;
- i = i_min + 1;
- if (i >= N_SCALES)
- return;
- gl_view_set_zoom (view, scales[i] / HOME_SCALE);
+ /* now adjust the object positions to line up this center */
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ dx = xcenter - (obj_extent.x1 + obj_extent.x2)/2.0;
+ gl_label_object_set_position_relative (object, dx, 0.0);
+ }
gl_debug (DEBUG_VIEW, "END");
}
/*****************************************************************************/
-/* Set current zoom factor to explicit value. */
+/* Align selected objects to top most edge. */
/*****************************************************************************/
void
-gl_view_set_zoom (glView *view,
- gdouble scale)
+gl_view_align_selection_top (glView *view)
{
+ GList *p;
+ glViewObject *view_object;
+ glLabelObject *object;
+ gdouble dy, y1_min;
+ glLabelRegion obj_extent;
+
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
- g_return_if_fail (scale > 0.0);
+ g_return_if_fail (view && GL_IS_VIEW (view));
- view->scale = scale * HOME_SCALE;
- gnome_canvas_set_pixels_per_unit (GNOME_CANVAS (view->canvas),
- scale * HOME_SCALE);
+ g_return_if_fail (!gl_view_is_selection_empty (view) &&
+ !gl_view_is_selection_atomic (view));
+
+ /* find top most edge */
+ p = view->selected_object_list;
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ y1_min = obj_extent.y1;
+ for (p = p->next; p != NULL; p = p->next)
+ {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ if ( obj_extent.y1 < y1_min ) y1_min = obj_extent.y1;
+ }
- g_signal_emit (G_OBJECT(view), signals[ZOOM_CHANGED], 0, scale);
+ /* now adjust the object positions to line up the top edges */
+ for (p = view->selected_object_list; p != NULL; p = p->next)
+ {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ dy = y1_min - obj_extent.y1;
+ gl_label_object_set_position_relative (object, 0.0, dy);
+ }
gl_debug (DEBUG_VIEW, "END");
}
/*****************************************************************************/
-/* Get current zoom factor. */
+/* Align selected objects to bottom most edge. */
/*****************************************************************************/
-gdouble
-gl_view_get_zoom (glView *view)
+void
+gl_view_align_selection_bottom (glView *view)
{
- gl_debug (DEBUG_VIEW, "");
+ GList *p;
+ glViewObject *view_object;
+ glLabelObject *object;
+ gdouble dy, y2_max;
+ glLabelRegion obj_extent;
- g_return_val_if_fail (GL_IS_VIEW (view), 1.0);
+ gl_debug (DEBUG_VIEW, "START");
- return view->scale / HOME_SCALE;
-}
+ g_return_if_fail (view && GL_IS_VIEW (view));
-/*****************************************************************************/
-/* Is this the maximum zoom level. */
-/*****************************************************************************/
-gboolean
-gl_view_is_zoom_max (glView *view)
-{
- gl_debug (DEBUG_VIEW, "");
+ g_return_if_fail (!gl_view_is_selection_empty (view) &&
+ !gl_view_is_selection_atomic (view));
+
+ /* find bottom most edge */
+ p = view->selected_object_list;
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ y2_max = obj_extent.y2;
+ for (p = p->next; p != NULL; p = p->next)
+ {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ if ( obj_extent.y2 > y2_max ) y2_max = obj_extent.y2;
+ }
- g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
+ /* now adjust the object positions to line up the bottom edges */
+ for (p = view->selected_object_list; p != NULL; p = p->next)
+ {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ dy = y2_max - obj_extent.y2;
+ gl_label_object_set_position_relative (object, 0.0, dy);
+ }
- return view->scale >= scales[0];
+ gl_debug (DEBUG_VIEW, "END");
}
/*****************************************************************************/
-/* Is this the minimum zoom level. */
+/* Align selected objects to viertical center of objects. */
/*****************************************************************************/
-gboolean
-gl_view_is_zoom_min (glView *view)
+void
+gl_view_align_selection_vcenter (glView *view)
{
- gl_debug (DEBUG_VIEW, "");
+ GList *p;
+ glViewObject *view_object;
+ glLabelObject *object;
+ gdouble dy;
+ gdouble dymin;
+ gdouble ysum, yavg;
+ glLabelRegion obj_extent;
+ gdouble ycenter;
+ gint n;
- g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
+ gl_debug (DEBUG_VIEW, "START");
- return view->scale <= scales[N_SCALES-1];
-}
+ g_return_if_fail (view && GL_IS_VIEW (view));
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. Canvas event handler. */
-/*---------------------------------------------------------------------------*/
-static int
-canvas_event (GnomeCanvas *canvas,
- GdkEvent *event,
- glView *view)
-{
- gdouble x, y;
-
- gl_debug (DEBUG_VIEW, "");
-
- /* emit pointer signals regardless of state */
- switch (event->type) {
- case GDK_MOTION_NOTIFY:
- gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
- gnome_canvas_window_to_world (canvas,
- event->motion.x,
- event->motion.y, &x, &y);
- g_signal_emit (G_OBJECT(view), signals[POINTER_MOVED], 0, x, y);
- break; /* fall through */
-
- case GDK_LEAVE_NOTIFY:
- gl_debug (DEBUG_VIEW, "LEAVEW_NOTIFY");
- g_signal_emit (G_OBJECT(view), signals[POINTER_EXIT], 0);
- break; /* fall through */
+ g_return_if_fail (!gl_view_is_selection_empty (view) &&
+ !gl_view_is_selection_atomic (view));
- default:
- break; /* fall through */
- }
-
-
- switch (view->state) {
-
- case GL_VIEW_STATE_ARROW:
- return canvas_event_arrow_mode (canvas, event, view);
-
- case GL_VIEW_STATE_OBJECT_CREATE:
- switch (view->create_type) {
- case GL_LABEL_OBJECT_BOX:
- return gl_view_box_create_event_handler (canvas,
- event,
- view);
- break;
- case GL_LABEL_OBJECT_ELLIPSE:
- return gl_view_ellipse_create_event_handler (canvas,
- event,
- view);
- break;
- case GL_LABEL_OBJECT_LINE:
- return gl_view_line_create_event_handler (canvas,
- event,
- view);
- break;
- case GL_LABEL_OBJECT_IMAGE:
- return gl_view_image_create_event_handler (canvas,
- event,
- view);
- break;
- case GL_LABEL_OBJECT_TEXT:
- return gl_view_text_create_event_handler (canvas,
- event,
- view);
- break;
- case GL_LABEL_OBJECT_BARCODE:
- return gl_view_barcode_create_event_handler (canvas,
- event,
- view);
- break;
- default:
- /*Should not happen!*/
- g_warning ("Invalid label object type.");
- return FALSE;
+ /* find average center of objects */
+ ysum = 0.0;
+ n = 0;
+ for (p = view->selected_object_list; p != NULL; p = p->next)
+ {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ ysum += (obj_extent.y1 + obj_extent.y2) / 2.0;
+ n++;
+ }
+ yavg = ysum / n;
+
+ /* find center of object closest to average center */
+ p = view->selected_object_list;
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ dymin = fabs (yavg - (obj_extent.y1 + obj_extent.y2)/2.0);
+ ycenter = (obj_extent.y1 + obj_extent.y2)/2.0;
+ for (p = p->next; p != NULL; p = p->next)
+ {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ dy = fabs (yavg - (obj_extent.y1 + obj_extent.y2)/2.0);
+ if ( dy < dymin )
+ {
+ dymin = dy;
+ ycenter = (obj_extent.y1 + obj_extent.y2)/2.0;
+ }
}
- default:
- g_warning ("Invalid view state."); /*Should not happen!*/
- return FALSE;
-
+ /* now adjust the object positions to line up this center */
+ for (p = view->selected_object_list; p != NULL; p = p->next)
+ {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ dy = ycenter - (obj_extent.y1 + obj_extent.y2)/2.0;
+ gl_label_object_set_position_relative (object, 0.0, dy);
}
+
+ gl_debug (DEBUG_VIEW, "END");
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. Canvas event handler (arrow mode) */
-/*---------------------------------------------------------------------------*/
-static int
-canvas_event_arrow_mode (GnomeCanvas *canvas,
- GdkEvent *event,
- glView *view)
+/*****************************************************************************/
+/* Center selected objects to in center of label. */
+/*****************************************************************************/
+void
+gl_view_center_selection_horiz (glView *view)
{
- static gdouble x0, y0;
- static gboolean dragging = FALSE;
- static GnomeCanvasItem *item;
- gdouble x, y, x1, y1, x2, y2;
- GnomeCanvasGroup *group;
- GdkCursor *cursor;
+ GList *p;
+ glViewObject *view_object;
+ glLabelObject *object;
+ gdouble dx;
+ gdouble x_label_center;
+ gdouble x_obj_center;
+ glLabelRegion obj_extent;
+ gdouble w, h;
- gl_debug (DEBUG_VIEW, "");
+ gl_debug (DEBUG_VIEW, "START");
- switch (event->type) {
-
- case GDK_BUTTON_PRESS:
- gl_debug (DEBUG_VIEW, "BUTTON_PRESS");
- switch (event->button.button) {
- case 1:
- gnome_canvas_window_to_world (canvas,
- event->button.x,
- event->button.y, &x, &y);
-
- if (!object_at (view, x, y)) {
- if (!(event->button.state & GDK_CONTROL_MASK)) {
- gl_view_unselect_all (view);
- }
-
- dragging = TRUE;
- gdk_pointer_grab (GTK_WIDGET (view->canvas)->
- window, FALSE,
- GDK_POINTER_MOTION_MASK |
- GDK_BUTTON_RELEASE_MASK |
- GDK_BUTTON_PRESS_MASK, NULL,
- NULL, event->button.time);
- group =
- gnome_canvas_root (GNOME_CANVAS
- (view->canvas));
- item =
- gnome_canvas_item_new (group,
- gnome_canvas_rect_get_type (),
- "x1", x, "y1", y,
- "x2", x, "y2", y,
- "width_pixels", 2,
- "outline_color_rgba",
- SEL_LINE_COLOR,
- "fill_color_rgba",
- SEL_FILL_COLOR,
- NULL);
- x0 = x;
- y0 = y;
+ g_return_if_fail (view && GL_IS_VIEW (view));
- }
- return FALSE;
+ g_return_if_fail (!gl_view_is_selection_empty (view));
- default:
- return FALSE;
- }
+ gl_label_get_size (view->label, &w, &h);
+ x_label_center = w / 2.0;
- case GDK_BUTTON_RELEASE:
- gl_debug (DEBUG_VIEW, "BUTTON_RELEASE");
- switch (event->button.button) {
- case 1:
- if (dragging) {
- dragging = FALSE;
- gdk_pointer_ungrab (event->button.time);
- gnome_canvas_window_to_world (canvas,
- event->button.x,
- event->button.y,
- &x, &y);
- x1 = MIN (x, x0);
- y1 = MIN (y, y0);
- x2 = MAX (x, x0);
- y2 = MAX (y, y0);
- gl_view_select_region (view, x1, y1, x2, y2);
- gtk_object_destroy (GTK_OBJECT (item));
- return TRUE;
- }
- return FALSE;
+ /* adjust the object positions */
+ for (p = view->selected_object_list; p != NULL; p = p->next)
+ {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ x_obj_center = (obj_extent.x1 + obj_extent.x2) / 2.0;
+ dx = x_label_center - x_obj_center;
+ gl_label_object_set_position_relative (object, dx, 0.0);
+ }
- default:
- return FALSE;
- }
+ gl_debug (DEBUG_VIEW, "END");
+}
- case GDK_MOTION_NOTIFY:
- gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
- gnome_canvas_window_to_world (canvas,
- event->motion.x,
- event->motion.y, &x, &y);
- if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
- gnome_canvas_item_set (item,
- "x1", MIN (x, x0),
- "y1", MIN (y, y0),
- "x2", MAX (x, x0),
- "y2", MAX (y, y0), NULL);
- return TRUE;
- } else {
- return FALSE;
- }
- case GDK_KEY_PRESS:
- gl_debug (DEBUG_VIEW, "KEY_PRESS");
- if (!dragging) {
- switch (event->key.keyval) {
- case GDK_Left:
- case GDK_KP_Left:
- move_selection (view,
- -1.0 / (view->scale), 0.0);
- break;
- case GDK_Up:
- case GDK_KP_Up:
- move_selection (view,
- 0.0, -1.0 / (view->scale));
- break;
- case GDK_Right:
- case GDK_KP_Right:
- move_selection (view,
- 1.0 / (view->scale), 0.0);
- break;
- case GDK_Down:
- case GDK_KP_Down:
- move_selection (view,
- 0.0, 1.0 / (view->scale));
- break;
- case GDK_Delete:
- case GDK_KP_Delete:
- gl_view_delete_selection (view);
- cursor = gdk_cursor_new (GDK_LEFT_PTR);
- gdk_window_set_cursor (view->canvas->window,
- cursor);
- gdk_cursor_unref (cursor);
- break;
- default:
- return FALSE;
- }
- }
- return TRUE; /* We handled this or we were dragging. */
+/*****************************************************************************/
+/* Center selected objects to in center of label. */
+/*****************************************************************************/
+void
+gl_view_center_selection_vert (glView *view)
+{
+ GList *p;
+ glViewObject *view_object;
+ glLabelObject *object;
+ gdouble dy;
+ gdouble y_label_center;
+ gdouble y_obj_center;
+ glLabelRegion obj_extent;
+ gdouble w, h;
- default:
- gl_debug (DEBUG_VIEW, "default");
- return FALSE;
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ g_return_if_fail (!gl_view_is_selection_empty (view));
+
+ gl_label_get_size (view->label, &w, &h);
+ y_label_center = h / 2.0;
+
+ /* adjust the object positions */
+ for (p = view->selected_object_list; p != NULL; p = p->next)
+ {
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+ gl_label_object_get_extent (object, &obj_extent);
+ y_obj_center = (obj_extent.y1 + obj_extent.y2) / 2.0;
+ dy = y_label_center - y_obj_center;
+ gl_label_object_set_position_relative (object, 0.0, dy);
}
+ gl_debug (DEBUG_VIEW, "END");
}
+
/*****************************************************************************/
-/* Item event handler. */
+/* Move selected objects */
/*****************************************************************************/
-gint
-gl_view_item_event_handler (GnomeCanvasItem *item,
- GdkEvent *event,
- glViewObject *view_object)
+void
+gl_view_move_selection (glView *view,
+ gdouble dx,
+ gdouble dy)
{
- glView *view;
+ GList *p;
+ glLabelObject *object;
- gl_debug (DEBUG_VIEW, "");
+ gl_debug (DEBUG_VIEW, "START");
- view = gl_view_object_get_view(view_object);
- switch (view->state) {
+ g_return_if_fail (view && GL_IS_VIEW (view));
- case GL_VIEW_STATE_ARROW:
- return item_event_arrow_mode (item, event, view_object);
+ for (p = view->selected_object_list; p != NULL; p = p->next)
+ {
- default:
- return FALSE;
+ object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
+ gl_label_object_set_position_relative (object, dx, dy);
}
+ gl_debug (DEBUG_VIEW, "END");
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. Item event handler (arrow mode) */
-/*---------------------------------------------------------------------------*/
-static int
-item_event_arrow_mode (GnomeCanvasItem *item,
- GdkEvent *event,
- glViewObject *view_object)
+/*****************************************************************************/
+/* Can text properties be set for selection? */
+/*****************************************************************************/
+gboolean
+gl_view_can_selection_text (glView *view)
{
- static gdouble x, y;
- static gboolean dragging = FALSE;
- glView *view;
- GdkCursor *cursor;
- gdouble item_x, item_y;
- gdouble new_x, new_y;
- gboolean control_key_pressed;
+ GList *p;
+ glLabelObject *object;
gl_debug (DEBUG_VIEW, "");
- item_x = event->button.x;
- item_y = event->button.y;
- gnome_canvas_item_w2i (item->parent, &item_x, &item_y);
-
- view = gl_view_object_get_view(view_object);
-
- switch (event->type) {
-
- case GDK_BUTTON_PRESS:
- gl_debug (DEBUG_VIEW, "BUTTON_PRESS");
- control_key_pressed = event->button.state & GDK_CONTROL_MASK;
- switch (event->button.button) {
- case 1:
- if (control_key_pressed) {
- if (is_object_selected (view, view_object)) {
- /* Un-selecting a selected item */
- gl_view_unselect_object (view,
- view_object);
- return TRUE;
- } else {
- /* Add to current selection */
- gl_view_select_object (view,
- view_object);
- }
- } else {
- if (!is_object_selected (view, view_object)) {
- /* No control, key so remove any selections before adding */
- gl_view_unselect_all (view);
- /* Add to current selection */
- gl_view_select_object (view,
- view_object);
- }
- }
- /* Go into dragging mode while button remains pressed. */
- x = item_x;
- y = item_y;
- cursor = gdk_cursor_new (GDK_FLEUR);
- gnome_canvas_item_grab (item,
- GDK_POINTER_MOTION_MASK |
- GDK_BUTTON_RELEASE_MASK |
- GDK_BUTTON_PRESS_MASK,
- cursor, event->button.time);
- gdk_cursor_unref (cursor);
- dragging = TRUE;
- return TRUE;
+ g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
- case 3:
- if (!is_object_selected (view, view_object)) {
- if (!control_key_pressed) {
- /* No control, key so remove any selections before adding */
- gl_view_unselect_all (view);
- }
- }
- /* Add to current selection */
- gl_view_select_object (view, view_object);
- /* bring up apropriate menu for selection. */
- popup_selection_menu (view, view_object, event);
- return TRUE;
+ for (p = view->selected_object_list; p != NULL; p = p->next)
+ {
- default:
- return FALSE;
+ object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
+ if (gl_label_object_can_text (object))
+ {
+ return TRUE;
}
- case GDK_BUTTON_RELEASE:
- gl_debug (DEBUG_VIEW, "BUTTON_RELEASE");
- switch (event->button.button) {
- case 1:
- /* Exit dragging mode */
- gnome_canvas_item_ungrab (item, event->button.time);
- dragging = FALSE;
- return TRUE;
+ }
- default:
- return FALSE;
- }
+ return FALSE;
+}
- case GDK_MOTION_NOTIFY:
- gl_debug (DEBUG_VIEW, "MOTION_NOTIFY");
- if (dragging && (event->motion.state & GDK_BUTTON1_MASK)) {
- /* Dragging mode, move selection */
- new_x = item_x;
- new_y = item_y;
- move_selection (view, (new_x - x), (new_y - y));
- x = new_x;
- y = new_y;
- return TRUE;
- } else {
- return FALSE;
- }
+/*****************************************************************************/
+/* Set font family for all text contained in selected objects. */
+/*****************************************************************************/
+void
+gl_view_set_selection_font_family (glView *view,
+ const gchar *font_family)
+{
+ GList *p;
+ glLabelObject *object;
- case GDK_2BUTTON_PRESS:
- gl_debug (DEBUG_VIEW, "2BUTTON_PRESS");
- switch (event->button.button) {
- case 1:
- /* Also exit dragging mode w/ double-click, run dlg */
- gnome_canvas_item_ungrab (item, event->button.time);
- dragging = FALSE;
- gl_view_select_object (view, view_object);
- gl_view_object_show_dialog (view_object);
- return TRUE;
+ gl_debug (DEBUG_VIEW, "START");
- default:
- return FALSE;
- }
+ g_return_if_fail (view && GL_IS_VIEW (view));
- case GDK_ENTER_NOTIFY:
- gl_debug (DEBUG_VIEW, "ENTER_NOTIFY");
- cursor = gdk_cursor_new (GDK_FLEUR);
- gdk_window_set_cursor (view->canvas->window, cursor);
- gdk_cursor_unref (cursor);
- return TRUE;
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
- case GDK_LEAVE_NOTIFY:
- gl_debug (DEBUG_VIEW, "LEAVE_NOTIFY");
- cursor = gdk_cursor_new (GDK_LEFT_PTR);
- gdk_window_set_cursor (view->canvas->window, cursor);
- gdk_cursor_unref (cursor);
- return TRUE;
+ object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
+ gl_label_object_set_font_family (object, font_family);
- default:
- gl_debug (DEBUG_VIEW, "default");
- return FALSE;
}
+ gl_debug (DEBUG_VIEW, "END");
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. create menu for multiple selections. */
-/*---------------------------------------------------------------------------*/
-GtkWidget *
-new_selection_menu (glView *view)
+/*****************************************************************************/
+/* Set font size for all text contained in selected objects. */
+/*****************************************************************************/
+void
+gl_view_set_selection_font_size (glView *view,
+ gdouble font_size)
{
- GtkWidget *menu, *menuitem;
+ GList *p;
+ glLabelObject *object;
gl_debug (DEBUG_VIEW, "START");
- g_return_val_if_fail (GL_IS_VIEW (view), NULL);
-
- menu = gtk_menu_new ();
-
- menuitem = gtk_menu_item_new_with_label (_("Delete"));
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
- gtk_widget_show (menuitem);
- g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
- G_CALLBACK (gl_view_delete_selection), view);
+ g_return_if_fail (view && GL_IS_VIEW (view));
- menuitem = gtk_menu_item_new ();
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
- gtk_widget_show (menuitem);
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
- menuitem = gtk_menu_item_new_with_label (_("Bring to front"));
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
- gtk_widget_show (menuitem);
- g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
- G_CALLBACK (gl_view_raise_selection), view);
+ object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
+ gl_label_object_set_font_size (object, font_size);
- menuitem = gtk_menu_item_new_with_label (_("Send to back"));
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
- gtk_widget_show (menuitem);
- g_signal_connect_swapped (G_OBJECT (menuitem), "activate",
- G_CALLBACK (gl_view_lower_selection), view);
+ }
gl_debug (DEBUG_VIEW, "END");
-
- return menu;
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. popup menu for given item. */
-/*---------------------------------------------------------------------------*/
-static void
-popup_selection_menu (glView *view,
- glViewObject *view_object,
- GdkEvent *event)
+/*****************************************************************************/
+/* Set font weight for all text contained in selected objects. */
+/*****************************************************************************/
+void
+gl_view_set_selection_font_weight (glView *view,
+ PangoWeight font_weight)
{
- GtkMenu *menu;
+ GList *p;
+ glLabelObject *object;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
- g_return_if_fail (GL_IS_VIEW_OBJECT (view_object));
-
- if (gl_view_is_selection_atomic (view)) {
-
- menu = gl_view_object_get_menu (view_object);
- if (menu != NULL) {
- gtk_menu_popup (GTK_MENU (menu),
- NULL, NULL, NULL, NULL,
- event->button.button,
- event->button.time);
- }
+ g_return_if_fail (view && GL_IS_VIEW (view));
- } else {
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
- if (view->menu != NULL) {
- gtk_menu_popup (GTK_MENU (view->menu),
- NULL, NULL, NULL, NULL,
- event->button.button,
- event->button.time);
- }
+ object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
+ gl_label_object_set_font_weight (object, font_weight);
}
gl_debug (DEBUG_VIEW, "END");
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. Handle "selection-clear" signal. */
-/*---------------------------------------------------------------------------*/
-static void
-selection_clear_cb (GtkWidget *widget,
- GdkEventSelection *event,
- gpointer data)
+/*****************************************************************************/
+/* Set font italic flag for all text contained in selected objects. */
+/*****************************************************************************/
+void
+gl_view_set_selection_font_italic_flag (glView *view,
+ gboolean font_italic_flag)
{
- glView *view = GL_VIEW (data);
+ GList *p;
+ glLabelObject *object;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
- view->have_selection = FALSE;
- g_object_unref (view->selection_data);
- view->selection_data = NULL;
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
+
+ object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
+ gl_label_object_set_font_italic_flag (object, font_italic_flag);
+
+ }
gl_debug (DEBUG_VIEW, "END");
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. Handle "selection-get" signal. */
-/*---------------------------------------------------------------------------*/
-static void
-selection_get_cb (GtkWidget *widget,
- GtkSelectionData *selection_data,
- guint info,
- guint time,
- gpointer data)
+/*****************************************************************************/
+/* Set text alignment for all text contained in selected objects. */
+/*****************************************************************************/
+void
+gl_view_set_selection_text_alignment (glView *view,
+ PangoAlignment text_alignment)
{
- glView *view = GL_VIEW (data);
- gchar *buffer;
- glXMLLabelStatus status;
+ GList *p;
+ glLabelObject *object;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
- if (view->have_selection) {
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
+
+ object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
+ gl_label_object_set_text_alignment (object, text_alignment);
- buffer = gl_xml_label_save_buffer (view->selection_data,
- &status);
- gtk_selection_data_set (selection_data,
- GDK_SELECTION_TYPE_STRING, 8, buffer,
- strlen (buffer));
- g_free (buffer);
}
gl_debug (DEBUG_VIEW, "END");
}
-/*---------------------------------------------------------------------------*/
-/* PRIVATE. Handle "selection-received" signal. (Result of Paste) */
-/*---------------------------------------------------------------------------*/
-static void
-selection_received_cb (GtkWidget *widget,
- GtkSelectionData *selection_data,
- guint time,
- gpointer data)
+/*****************************************************************************/
+/* Set text line spacing for all text contained in selected objects. */
+/*****************************************************************************/
+void
+gl_view_set_selection_text_line_spacing (glView *view,
+ gdouble text_line_spacing)
{
- glView *view = GL_VIEW (data);
- glLabel *label = NULL;
- glXMLLabelStatus status;
- GList *p, *p_next;
- glLabelObject *object, *newobject;
- glViewObject *view_object;
+ GList *p;
+ glLabelObject *object;
gl_debug (DEBUG_VIEW, "START");
- g_return_if_fail (GL_IS_VIEW (view));
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
+
+ object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
+ gl_label_object_set_text_line_spacing (object, text_line_spacing);
- if (selection_data->length < 0) {
- return;
}
- if (selection_data->type != GDK_SELECTION_TYPE_STRING) {
- return;
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+/*****************************************************************************/
+/* Set text color for all text contained in selected objects. */
+/*****************************************************************************/
+void
+gl_view_set_selection_text_color (glView *view,
+ glColorNode *text_color_node)
+{
+ GList *p;
+ glLabelObject *object;
+
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
+
+ object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
+ gl_label_object_set_text_color (object, text_color_node);
+
}
- gl_view_unselect_all (view);
+ gl_debug (DEBUG_VIEW, "END");
+}
- label = gl_xml_label_open_buffer (selection_data->data, &status);
- for (p = label->objects; p != NULL; p = p_next) {
- p_next = p->next;
+/*****************************************************************************/
+/* Can fill properties be set for selection? */
+/*****************************************************************************/
+gboolean
+gl_view_can_selection_fill (glView *view)
+{
+ GList *p;
+ glLabelObject *object;
- object = (glLabelObject *) p->data;
- gl_label_object_set_parent (object, view->label);
+ gl_debug (DEBUG_VIEW, "");
- gl_debug (DEBUG_VIEW, "object pasted");
+ g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
- if (GL_IS_LABEL_BOX (object)) {
- view_object = gl_view_box_new (GL_LABEL_BOX(object),
- view);
- } else if (GL_IS_LABEL_ELLIPSE (object)) {
- view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(object),
- view);
- } else if (GL_IS_LABEL_LINE (object)) {
- view_object = gl_view_line_new (GL_LABEL_LINE(object),
- view);
- } else if (GL_IS_LABEL_IMAGE (object)) {
- view_object = gl_view_image_new (GL_LABEL_IMAGE(object),
- view);
- } else if (GL_IS_LABEL_TEXT (object)) {
- view_object = gl_view_text_new (GL_LABEL_TEXT(object),
- view);
- } else if (GL_IS_LABEL_BARCODE (object)) {
- view_object = gl_view_barcode_new (GL_LABEL_BARCODE(object),
- view);
- } else {
- /* Should not happen! */
- view_object = NULL;
- g_warning ("Invalid label object type.");
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
+
+ object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
+ if (gl_label_object_can_fill (object)) {
+ return TRUE;
}
- gl_view_select_object (view, view_object);
+
}
- g_object_unref (label);
- gl_debug (DEBUG_VIEW, "END");
+ return FALSE;
+}
+
+/*****************************************************************************/
+/* Set fill color for all selected objects. */
+/*****************************************************************************/
+void
+gl_view_set_selection_fill_color (glView *view,
+ glColorNode *fill_color_node)
+{
+ GList *p;
+ glLabelObject *object;
+
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
+
+ object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
+ gl_label_object_set_fill_color (object, fill_color_node);
+
+ }
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+/*****************************************************************************/
+/* Can line color properties be set for selection? */
+/*****************************************************************************/
+gboolean
+gl_view_can_selection_line_color (glView *view)
+{
+ GList *p;
+ glLabelObject *object;
+
+ gl_debug (DEBUG_VIEW, "");
+
+ g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
+
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
+
+ object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
+ if (gl_label_object_can_line_color (object)) {
+ return TRUE;
+ }
+
+ }
+
+ return FALSE;
+}
+
+/*****************************************************************************/
+/* Set line color for all selected objects. */
+/*****************************************************************************/
+void
+gl_view_set_selection_line_color (glView *view,
+ glColorNode *line_color_node)
+{
+ GList *p;
+ glLabelObject *object;
+
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
+
+ object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
+ gl_label_object_set_line_color (object, line_color_node);
+
+ }
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+/*****************************************************************************/
+/* Can line width properties be set for selection? */
+/*****************************************************************************/
+gboolean
+gl_view_can_selection_line_width (glView *view)
+{
+ GList *p;
+ glLabelObject *object;
+
+ gl_debug (DEBUG_VIEW, "");
+
+ g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
+
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
+
+ object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
+ if (gl_label_object_can_line_width (object)) {
+ return TRUE;
+ }
+
+ }
+
+ return FALSE;
+}
+
+/*****************************************************************************/
+/* Set line width for all selected objects. */
+/*****************************************************************************/
+void
+gl_view_set_selection_line_width (glView *view,
+ gdouble line_width)
+{
+ GList *p;
+ glLabelObject *object;
+
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
+
+ object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
+ gl_label_object_set_line_width (object, line_width);
+
+ }
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+/*****************************************************************************/
+/* "Cut" selected items and place in clipboard selections. */
+/*****************************************************************************/
+void
+gl_view_cut (glView *view)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ gl_view_copy (view);
+ gl_view_delete_selection (view);
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+/*****************************************************************************/
+/* "Copy" selected items to clipboard selections. */
+/*****************************************************************************/
+void
+gl_view_copy (glView *view)
+{
+ GList *p;
+ glViewObject *view_object;
+ glLabelObject *object;
+
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ if (view->selected_object_list) {
+
+ if ( view->selection_data ) {
+ g_object_unref (view->selection_data);
+ }
+ view->selection_data = GL_LABEL(gl_label_new ());
+ gl_label_set_template (view->selection_data, view->label->template);
+ gl_label_set_rotate_flag (view->selection_data, view->label->rotate_flag);
+
+ for (p = view->selected_object_list; p != NULL; p = p->next) {
+
+ view_object = GL_VIEW_OBJECT (p->data);
+ object = gl_view_object_get_object (view_object);
+
+ gl_label_object_dup (object, view->selection_data);
+
+ }
+
+ gtk_selection_owner_set (view->invisible,
+ clipboard_atom, GDK_CURRENT_TIME);
+ view->have_selection = TRUE;
+
+ }
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+/*****************************************************************************/
+/* "Paste" from private clipboard selection. */
+/*****************************************************************************/
+void
+gl_view_paste (glView *view)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ gtk_selection_convert (GTK_WIDGET (view->invisible),
+ clipboard_atom, GDK_SELECTION_TYPE_STRING,
+ GDK_CURRENT_TIME);
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+/*****************************************************************************/
+/* Zoom in one "notch" */
+/*****************************************************************************/
+void
+gl_view_zoom_in (glView *view)
+{
+ gint i, i_min;
+ gdouble dist, dist_min;
+
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ /* Find index of current scale (or best match) */
+ i_min = 1; /* start with 2nd largest scale */
+ dist_min = fabs (zooms[1] - view->zoom);
+ for (i = 2; i < N_ZOOMS; i++) {
+ dist = fabs (zooms[i] - view->zoom);
+ if (dist < dist_min) {
+ i_min = i;
+ dist_min = dist;
+ }
+ }
+
+ /* zoom in one "notch" */
+ i = MAX (0, i_min - 1);
+ gl_debug (DEBUG_VIEW, "zoom[%d] = %g", i, zooms[i]);
+ set_zoom_real (view, zooms[i], FALSE);
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+/*****************************************************************************/
+/* Zoom out one "notch" */
+/*****************************************************************************/
+void
+gl_view_zoom_out (glView *view)
+{
+ gint i, i_min;
+ gdouble dist, dist_min;
+
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ /* Find index of current scale (or best match) */
+ i_min = 0; /* start with largest scale */
+ dist_min = fabs (zooms[0] - view->zoom);
+ for (i = 1; i < N_ZOOMS; i++) {
+ dist = fabs (zooms[i] - view->zoom);
+ if (dist < dist_min) {
+ i_min = i;
+ dist_min = dist;
+ }
+ }
+
+ /* zoom out one "notch" */
+ if (i_min >= N_ZOOMS)
+ return;
+ i = i_min + 1;
+ if (i >= N_ZOOMS)
+ return;
+ set_zoom_real (view, zooms[i], FALSE);
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+/*****************************************************************************/
+/* Set zoom to best fit. */
+/*****************************************************************************/
+void
+gl_view_zoom_to_fit (glView *view)
+{
+ gint w_view, h_view;
+ gdouble w_label, h_label;
+ gdouble x_scale, y_scale, scale;
+
+ gl_debug (DEBUG_VIEW, "");
+
+ if ( ! GTK_WIDGET_VISIBLE(view)) {
+ set_zoom_real (view, 1.0, TRUE);
+ return;
+ }
+
+ w_view = GTK_WIDGET(view)->allocation.width;
+ h_view = GTK_WIDGET(view)->allocation.height;
+
+ gl_label_get_size (GL_LABEL(view->label), &w_label, &h_label);
+
+ gl_debug (DEBUG_VIEW, "View size: %d, %d", w_view, h_view);
+ gl_debug (DEBUG_VIEW, "Label size: %g, %g", w_label, h_label);
+
+ /* Calculate best scale */
+ x_scale = (double)(w_view - ZOOMTOFIT_PAD) / w_label;
+ y_scale = (double)(h_view - ZOOMTOFIT_PAD) / h_label;
+ scale = MIN (x_scale, y_scale);
+ gl_debug (DEBUG_VIEW, "Candidate zooms: %g, %g => %g", x_scale, y_scale, scale);
+
+ /* Limit */
+ gl_debug (DEBUG_VIEW, "Scale: %g", scale);
+ scale = MIN (scale, zooms[0]*view->home_scale);
+ scale = MAX (scale, zooms[N_ZOOMS-1]*view->home_scale);
+ gl_debug (DEBUG_VIEW, "Limitted scale: %g", scale);
+
+ set_zoom_real (view, scale/view->home_scale, TRUE);
+}
+
+/*****************************************************************************/
+/* Set current zoom factor to explicit value. */
+/*****************************************************************************/
+void
+gl_view_set_zoom (glView *view,
+ gdouble zoom)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ set_zoom_real (view, zoom, FALSE);
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE. Set canvas scale. */
+/*---------------------------------------------------------------------------*/
+static void
+set_zoom_real (glView *view,
+ gdouble zoom,
+ gboolean zoom_to_fit_flag)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+ g_return_if_fail (zoom > 0.0);
+
+ /* Limit, if needed */
+ gl_debug (DEBUG_VIEW, "Zoom requested: %g", zoom);
+ zoom = MIN (zoom, zooms[0]);
+ zoom = MAX (zoom, zooms[N_ZOOMS-1]);
+ gl_debug (DEBUG_VIEW, "Limitted zoom: %g", zoom);
+
+ if ( zoom != view->zoom ) {
+
+ view->zoom = zoom;
+ view->zoom_to_fit_flag = zoom_to_fit_flag;
+
+ gl_view_update (view);
+
+ g_signal_emit (G_OBJECT(view), signals[ZOOM_CHANGED], 0, zoom);
+
+ }
+
+ gl_debug (DEBUG_VIEW, "END");
+
+}
+
+
+/*****************************************************************************/
+/* Get current zoom factor. */
+/*****************************************************************************/
+gdouble
+gl_view_get_zoom (glView *view)
+{
+ gl_debug (DEBUG_VIEW, "");
+
+ g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
+
+ return view->zoom;
+}
+
+/*****************************************************************************/
+/* Is this the maximum zoom level. */
+/*****************************************************************************/
+gboolean
+gl_view_is_zoom_max (glView *view)
+{
+ gl_debug (DEBUG_VIEW, "");
+
+ g_return_val_if_fail (GL_IS_VIEW (view), FALSE);
+
+ return view->zoom >= zooms[0];
+}
+
+/*****************************************************************************/
+/* Is this the minimum zoom level. */
+/*****************************************************************************/
+gboolean
+gl_view_is_zoom_min (glView *view)
+{
+ gl_debug (DEBUG_VIEW, "");
+
+ g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
+
+ return view->zoom <= zooms[N_ZOOMS-1];
+}
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE. Handle "selection-clear" signal. */
+/*---------------------------------------------------------------------------*/
+static void
+selection_clear_cb (GtkWidget *widget,
+ GdkEventSelection *event,
+ glView *view)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ view->have_selection = FALSE;
+ g_object_unref (view->selection_data);
+ view->selection_data = NULL;
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE. Handle "selection-get" signal. */
+/*---------------------------------------------------------------------------*/
+static void
+selection_get_cb (GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ glView *view)
+{
+ gchar *buffer;
+ glXMLLabelStatus status;
+
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ if (view->have_selection) {
+
+ buffer = gl_xml_label_save_buffer (view->selection_data,
+ &status);
+ gtk_selection_data_set (selection_data,
+ GDK_SELECTION_TYPE_STRING, 8,
+ (guchar *)buffer, strlen (buffer));
+ g_free (buffer);
+ }
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE. Handle "selection-received" signal. (Result of Paste) */
+/*---------------------------------------------------------------------------*/
+static void
+selection_received_cb (GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ guint time,
+ glView *view)
+{
+ glLabel *label = NULL;
+ glXMLLabelStatus status;
+ GList *p, *p_next;
+ glLabelObject *object, *newobject;
+ glViewObject *view_object;
+
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ if (selection_data->length < 0) {
+ return;
+ }
+ if (selection_data->type != GDK_SELECTION_TYPE_STRING) {
+ return;
+ }
+
+ gl_view_unselect_all (view);
+
+ label = gl_xml_label_open_buffer ((gchar *)selection_data->data, &status);
+ for (p = label->objects; p != NULL; p = p_next) {
+ p_next = p->next;
+
+ object = (glLabelObject *) p->data;
+ newobject = gl_label_object_dup (object, view->label);
+
+ gl_debug (DEBUG_VIEW, "object pasted");
+
+ if (GL_IS_LABEL_BOX (newobject)) {
+ view_object = gl_view_box_new (GL_LABEL_BOX(newobject),
+ view);
+ } else if (GL_IS_LABEL_ELLIPSE (newobject)) {
+ view_object = gl_view_ellipse_new (GL_LABEL_ELLIPSE(newobject),
+ view);
+ } else if (GL_IS_LABEL_LINE (newobject)) {
+ view_object = gl_view_line_new (GL_LABEL_LINE(newobject),
+ view);
+ } else if (GL_IS_LABEL_IMAGE (newobject)) {
+ view_object = gl_view_image_new (GL_LABEL_IMAGE(newobject),
+ view);
+ } else if (GL_IS_LABEL_TEXT (newobject)) {
+ view_object = gl_view_text_new (GL_LABEL_TEXT(newobject),
+ view);
+ } else if (GL_IS_LABEL_BARCODE (newobject)) {
+ view_object = gl_view_barcode_new (GL_LABEL_BARCODE(newobject),
+ view);
+ } else {
+ /* Should not happen! */
+ view_object = NULL;
+ g_message ("Invalid label object type.");
+ }
+ gl_view_select_object (view, view_object);
+ }
+ g_object_unref (label);
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+/****************************************************************************/
+/* Set default font family. */
+/****************************************************************************/
+void
+gl_view_set_default_font_family (glView *view,
+ const gchar *font_family)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ if (view->default_font_family) {
+ g_free (view->default_font_family);
+ }
+ view->default_font_family = g_strdup (font_family);
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+
+/****************************************************************************/
+/* Set default font size. */
+/****************************************************************************/
+void
+gl_view_set_default_font_size (glView *view,
+ gdouble font_size)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ view->default_font_size = font_size;
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+
+/****************************************************************************/
+/* Set default font weight. */
+/****************************************************************************/
+void
+gl_view_set_default_font_weight (glView *view,
+ PangoWeight font_weight)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ view->default_font_weight = font_weight;
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+
+/****************************************************************************/
+/* Set default font italic flag. */
+/****************************************************************************/
+void
+gl_view_set_default_font_italic_flag (glView *view,
+ gboolean font_italic_flag)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ view->default_font_italic_flag = font_italic_flag;
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+
+/****************************************************************************/
+/* Set default text color. */
+/****************************************************************************/
+void
+gl_view_set_default_text_color (glView *view,
+ guint text_color)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ view->default_text_color = text_color;
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+
+/****************************************************************************/
+/* Set default text alignment. */
+/****************************************************************************/
+void
+gl_view_set_default_text_alignment (glView *view,
+ PangoAlignment text_alignment)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ view->default_text_alignment = text_alignment;
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+/****************************************************************************/
+/* Set default text line spacing. */
+/****************************************************************************/
+void
+gl_view_set_default_text_line_spacing (glView *view,
+ gdouble text_line_spacing)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ view->default_text_line_spacing = text_line_spacing;
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+
+/****************************************************************************/
+/* Set default line width. */
+/****************************************************************************/
+void
+gl_view_set_default_line_width (glView *view,
+ gdouble line_width)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ view->default_line_width = line_width;
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+
+/****************************************************************************/
+/* Set default line color. */
+/****************************************************************************/
+void
+gl_view_set_default_line_color (glView *view,
+ guint line_color)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ view->default_line_color = line_color;
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+
+/****************************************************************************/
+/* Set default fill color. */
+/****************************************************************************/
+void
+gl_view_set_default_fill_color (glView *view,
+ guint fill_color)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_if_fail (view && GL_IS_VIEW (view));
+
+ view->default_fill_color = fill_color;
+
+ gl_debug (DEBUG_VIEW, "END");
+}
+
+
+
+/****************************************************************************/
+/* Get default font family. */
+/****************************************************************************/
+gchar *
+gl_view_get_default_font_family (glView *view)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_val_if_fail (view && GL_IS_VIEW (view), NULL);
+
+ gl_debug (DEBUG_VIEW, "END");
+
+ return g_strdup (view->default_font_family);
+}
+
+
+/****************************************************************************/
+/* Get default font size. */
+/****************************************************************************/
+gdouble
+gl_view_get_default_font_size (glView *view)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_val_if_fail (view && GL_IS_VIEW (view), 12.0);
+
+ gl_debug (DEBUG_VIEW, "END");
+
+ return view->default_font_size;
+}
+
+
+/****************************************************************************/
+/* Get default font weight. */
+/****************************************************************************/
+PangoWeight
+gl_view_get_default_font_weight (glView *view)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_val_if_fail (view && GL_IS_VIEW (view), PANGO_WEIGHT_NORMAL);
+
+ gl_debug (DEBUG_VIEW, "END");
+
+ return view->default_font_weight;
+}
+
+
+/****************************************************************************/
+/* Get default font italic flag. */
+/****************************************************************************/
+gboolean
+gl_view_get_default_font_italic_flag (glView *view)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_val_if_fail (view && GL_IS_VIEW (view), FALSE);
+
+ gl_debug (DEBUG_VIEW, "END");
+
+ return view->default_font_italic_flag;
+}
+
+
+/****************************************************************************/
+/* Get default text color. */
+/****************************************************************************/
+guint
+gl_view_get_default_text_color (glView *view)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
+
+ gl_debug (DEBUG_VIEW, "END");
+
+ return view->default_text_color;
+}
+
+
+/****************************************************************************/
+/* Get default text alignment. */
+/****************************************************************************/
+PangoAlignment
+gl_view_get_default_text_alignment (glView *view)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_val_if_fail (view && GL_IS_VIEW (view), PANGO_ALIGN_LEFT);
+
+ gl_debug (DEBUG_VIEW, "END");
+
+ return view->default_text_alignment;
+}
+
+/****************************************************************************/
+/* Get default text line spacing. */
+/****************************************************************************/
+gdouble
+gl_view_get_default_text_line_spacing (glView *view)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
+
+ gl_debug (DEBUG_VIEW, "END");
+
+ return view->default_text_line_spacing;
+}
+
+
+
+/****************************************************************************/
+/* Get default line width. */
+/****************************************************************************/
+gdouble
+gl_view_get_default_line_width (glView *view)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_val_if_fail (view && GL_IS_VIEW (view), 1.0);
+
+ gl_debug (DEBUG_VIEW, "END");
+
+ return view->default_line_width;
+}
+
+
+/****************************************************************************/
+/* Get default line color. */
+/****************************************************************************/
+guint
+gl_view_get_default_line_color (glView *view)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
+
+ gl_debug (DEBUG_VIEW, "END");
+
+ return view->default_line_color;
+}
+
+
+/****************************************************************************/
+/* Get default fill color. */
+/****************************************************************************/
+guint
+gl_view_get_default_fill_color (glView *view)
+{
+ gl_debug (DEBUG_VIEW, "START");
+
+ g_return_val_if_fail (view && GL_IS_VIEW (view), 0);
+
+ gl_debug (DEBUG_VIEW, "END");
+
+ return view->default_fill_color;
+}
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE. Focus in event handler. */
+/*---------------------------------------------------------------------------*/
+static gboolean
+focus_in_event_cb (glView *view,
+ GdkEventFocus *event)
+{
+ GTK_WIDGET_SET_FLAGS (GTK_WIDGET (view->canvas), GTK_HAS_FOCUS);
+
+ return FALSE;
+}
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE. Focus out event handler. */
+/*---------------------------------------------------------------------------*/
+static gboolean
+focus_out_event_cb (glView *view,
+ GdkEventFocus *event)
+{
+ GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (view->canvas), GTK_HAS_FOCUS);
+
+ return FALSE;
+}
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE. Enter notify event handler. */
+/*---------------------------------------------------------------------------*/
+static gboolean
+enter_notify_event_cb (glView *view,
+ GdkEventCrossing *event)
+{
+ gtk_widget_grab_focus(GTK_WIDGET (view->canvas));
+
+ return FALSE;
+}
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE. Leave notify event handler. */
+/*---------------------------------------------------------------------------*/
+static gboolean
+leave_notify_event_cb (glView *view,
+ GdkEventCrossing *event)
+{
+
+ g_signal_emit (G_OBJECT(view), signals[POINTER_EXIT], 0);
+
+ return FALSE;
+}
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE. Motion notify event handler. */
+/*---------------------------------------------------------------------------*/
+static gboolean
+motion_notify_event_cb (glView *view,
+ GdkEventMotion *event)
+{
+ gboolean return_value = FALSE;
+ cairo_t *cr;
+ gdouble scale;
+ gdouble x, y;
+ GdkCursor *cursor;
+ glViewObjectHandle handle;
+
+ cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
+
+ /*
+ * Translate to label coordinates
+ */
+ scale = view->zoom * view->home_scale;
+ cairo_scale (cr, scale, scale);
+ cairo_translate (cr, view->x0, view->y0);
+
+ x = event->x;
+ y = event->y;
+ cairo_device_to_user (cr, &x, &y);
+
+ /*
+ * Emit signal regardless of mode
+ */
+ g_signal_emit (G_OBJECT(view), signals[POINTER_MOVED], 0, x, y);
+
+ /*
+ * Handle event as appropriate for mode
+ */
+ switch (view->mode)
+ {
+
+ case GL_VIEW_MODE_ARROW:
+ switch (view->state)
+ {
+
+ case GL_VIEW_IDLE:
+ if (view_handle_at (view, cr, event->x, event->y, &handle))
+ {
+ cursor = gdk_cursor_new (GDK_CROSSHAIR);
+ }
+ else if (view_view_object_at (view, cr, event->x, event->y))
+ {
+ cursor = gdk_cursor_new (GDK_FLEUR);
+ }
+ else
+ {
+ cursor = gdk_cursor_new (GDK_LEFT_PTR);
+ }
+ gdk_window_set_cursor (view->canvas->window, cursor);
+ gdk_cursor_unref (cursor);
+ break;
+
+ case GL_VIEW_ARROW_SELECT_REGION:
+#ifdef CLIP_UPDATES
+ gl_view_update_region (view, cr, &view->select_region);
+#endif
+ view->select_region.x2 = x;
+ view->select_region.y2 = y;
+#ifdef CLIP_UPDATES
+ gl_view_update_region (view, cr, &view->select_region);
+#else
+ gl_view_update (view);
+#endif
+ break;
+
+ case GL_VIEW_ARROW_MOVE:
+ gl_view_move_selection (view,
+ (x - view->move_last_x),
+ (y - view->move_last_y));
+ view->move_last_x = x;
+ view->move_last_y = y;
+ break;
+
+ case GL_VIEW_ARROW_RESIZE:
+ gl_view_object_resize_event (view->resize_object,
+ view->resize_handle,
+ view->resize_honor_aspect,
+ cr,
+ event->x,
+ event->y);
+ break;
+
+ default:
+ g_message ("Invalid arrow state."); /*Should not happen!*/
+ }
+ return_value = TRUE;
+ break;
+
+
+ case GL_VIEW_MODE_OBJECT_CREATE:
+ if (view->state != GL_VIEW_IDLE)
+ {
+ switch (view->create_type)
+ {
+ case GL_LABEL_OBJECT_BOX:
+ gl_view_box_create_motion_event (view, x, y);
+ break;
+ case GL_LABEL_OBJECT_ELLIPSE:
+ gl_view_ellipse_create_motion_event (view, x, y);
+ break;
+ case GL_LABEL_OBJECT_LINE:
+ gl_view_line_create_motion_event (view, x, y);
+ break;
+ case GL_LABEL_OBJECT_IMAGE:
+ gl_view_image_create_motion_event (view, x, y);
+ break;
+ case GL_LABEL_OBJECT_TEXT:
+ gl_view_text_create_motion_event (view, x, y);
+ break;
+ case GL_LABEL_OBJECT_BARCODE:
+ gl_view_barcode_create_motion_event (view, x, y);
+ break;
+ default:
+ g_message ("Invalid create type."); /*Should not happen!*/
+ }
+ }
+ break;
+
+
+ default:
+ g_message ("Invalid view mode."); /*Should not happen!*/
+
+ }
+
+ cairo_destroy (cr);
+
+ /*
+ * FIXME: we re-establish grabs here if the grab has been lost. We seem to be
+ * losing grabs when we emit signals that lead to the manipulation of
+ * the GtkUIManager. Needs more investigation
+ */
+ if (view->grabbed_flag && !gdk_pointer_is_grabbed ())
+ {
+ gdk_pointer_grab (GTK_LAYOUT (view->canvas)->bin_window,
+ FALSE,
+ (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
+ NULL,
+ NULL,
+ event->time);
+ }
+
+ return return_value;
+}
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE. Button press event handler. */
+/*---------------------------------------------------------------------------*/
+static gboolean
+button_press_event_cb (glView *view,
+ GdkEventButton *event)
+{
+ gboolean return_value = FALSE;
+ cairo_t *cr;
+ gdouble scale;
+ gdouble x, y;
+ glViewObject *view_object;
+ glViewObjectHandle handle;
+
+ cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
+
+ /*
+ * Translate to label coordinates
+ */
+ scale = view->zoom * view->home_scale;
+ cairo_scale (cr, scale, scale);
+ cairo_translate (cr, view->x0, view->y0);
+
+ x = event->x;
+ y = event->y;
+ cairo_device_to_user (cr, &x, &y);
+
+ switch (event->button)
+ {
+
+ case 1:
+ /*
+ * Handle event as appropriate for mode
+ */
+ switch (view->mode)
+ {
+ case GL_VIEW_MODE_ARROW:
+ if ((view_object = view_handle_at (view, cr, event->x, event->y, &handle)))
+ {
+ view->resize_object = view_object;
+ view->resize_handle = handle;
+ view->resize_honor_aspect = event->state & GDK_CONTROL_MASK;
+
+ view->state = GL_VIEW_ARROW_RESIZE;
+ }
+ else if ((view_object = view_view_object_at (view, cr, event->x, event->y)))
+ {
+ if (event->state & GDK_CONTROL_MASK)
+ {
+ if (gl_view_is_object_selected (view, view_object))
+ {
+ /* Un-selecting a selected item */
+ gl_view_unselect_object (view, view_object);
+ } else {
+ /* Add to current selection */
+ gl_view_select_object (view, view_object);
+ }
+ }
+ else
+ {
+ if (!gl_view_is_object_selected (view, view_object))
+ {
+ /* remove any selections before adding */
+ gl_view_unselect_all (view);
+ /* Add to current selection */
+ gl_view_select_object (view, view_object);
+ }
+ }
+ view->move_last_x = x;
+ view->move_last_y = y;
+
+ view->state = GL_VIEW_ARROW_MOVE;
+ }
+ else
+ {
+ if (!(event->state & GDK_CONTROL_MASK))
+ {
+ gl_view_unselect_all (view);
+ }
+
+ view->select_region_visible = TRUE;
+ view->select_region.x1 = x;
+ view->select_region.y1 = y;
+ view->select_region.x2 = x;
+ view->select_region.y2 = y;
+
+ view->state = GL_VIEW_ARROW_SELECT_REGION;
+ }
+
+
+ return_value = TRUE;
+ break;
+
+ case GL_VIEW_MODE_OBJECT_CREATE:
+ switch (view->create_type)
+ {
+ case GL_LABEL_OBJECT_BOX:
+ gl_view_box_create_button_press_event (view, x, y);
+ break;
+ case GL_LABEL_OBJECT_ELLIPSE:
+ gl_view_ellipse_create_button_press_event (view, x, y);
+ break;
+ case GL_LABEL_OBJECT_LINE:
+ gl_view_line_create_button_press_event (view, x, y);
+ break;
+ case GL_LABEL_OBJECT_IMAGE:
+ gl_view_image_create_button_press_event (view, x, y);
+ break;
+ case GL_LABEL_OBJECT_TEXT:
+ gl_view_text_create_button_press_event (view, x, y);
+ break;
+ case GL_LABEL_OBJECT_BARCODE:
+ gl_view_barcode_create_button_press_event (view, x, y);
+ break;
+ default:
+ g_message ("Invalid create type."); /*Should not happen!*/
+ }
+ view->state = GL_VIEW_CREATE_DRAG;
+ return_value = TRUE;
+ break;
+
+ default:
+ g_message ("Invalid view mode."); /*Should not happen!*/
+ }
+
+ view->grabbed_flag = TRUE;
+ gdk_pointer_grab (GTK_LAYOUT (view->canvas)->bin_window,
+ FALSE,
+ (GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
+ NULL,
+ NULL,
+ event->time);
+ break;
+
+ case 3:
+ g_signal_emit (G_OBJECT (view),
+ signals[CONTEXT_MENU_ACTIVATE], 0,
+ event->button, event->time);
+ return_value = TRUE;
+ break;
+
+ }
+
+ cairo_destroy (cr);
+
+ return return_value;
+}
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE. Button release event handler. */
+/*---------------------------------------------------------------------------*/
+static gboolean
+button_release_event_cb (glView *view,
+ GdkEventButton *event)
+{
+ gboolean return_value = FALSE;
+ cairo_t *cr;
+ gdouble scale;
+ gdouble x, y;
+ GdkCursor *cursor;
+
+ cr = gdk_cairo_create (GTK_LAYOUT (view->canvas)->bin_window);
+
+ /*
+ * Translate to label coordinates
+ */
+ scale = view->zoom * view->home_scale;
+ cairo_scale (cr, scale, scale);
+ cairo_translate (cr, view->x0, view->y0);
+
+ x = event->x;
+ y = event->y;
+ cairo_device_to_user (cr, &x, &y);
+
+ switch (event->button)
+ {
+
+ case 1:
+ view->grabbed_flag = FALSE;
+ gdk_pointer_ungrab (event->time);
+ /*
+ * Handle event as appropriate for mode
+ */
+ switch (view->mode)
+ {
+ case GL_VIEW_MODE_ARROW:
+ switch (view->state)
+ {
+ case GL_VIEW_ARROW_RESIZE:
+ view->resize_object = NULL;
+
+ view->state = GL_VIEW_IDLE;
+ break;
+
+ case GL_VIEW_ARROW_SELECT_REGION:
+#ifdef CLIP_UPDATES
+ gl_view_update_region (view, cr, &view->select_region);
+#else
+ gl_view_update (view);
+#endif
+
+ view->select_region_visible = FALSE;
+ view->select_region.x2 = x;
+ view->select_region.y2 = y;
+
+ gl_view_select_region (view, &view->select_region);
+
+ view->state = GL_VIEW_IDLE;
+ break;
+
+ default:
+ view->state = GL_VIEW_IDLE;
+ break;
+
+ }
+
+ return_value = TRUE;
+ break;
+
+
+ case GL_VIEW_MODE_OBJECT_CREATE:
+ switch (view->create_type)
+ {
+ case GL_LABEL_OBJECT_BOX:
+ gl_view_box_create_button_release_event (view, x, y);
+ break;
+ case GL_LABEL_OBJECT_ELLIPSE:
+ gl_view_ellipse_create_button_release_event (view, x, y);
+ break;
+ case GL_LABEL_OBJECT_LINE:
+ gl_view_line_create_button_release_event (view, x, y);
+ break;
+ case GL_LABEL_OBJECT_IMAGE:
+ gl_view_image_create_button_release_event (view, x, y);
+ break;
+ case GL_LABEL_OBJECT_TEXT:
+ gl_view_text_create_button_release_event (view, x, y);
+ break;
+ case GL_LABEL_OBJECT_BARCODE:
+ gl_view_barcode_create_button_release_event (view, x, y);
+ break;
+ default:
+ g_message ("Invalid create type."); /*Should not happen!*/
+ }
+ view->mode = GL_VIEW_MODE_ARROW;
+ view->state = GL_VIEW_IDLE;
+ cursor = gdk_cursor_new (GDK_LEFT_PTR);
+ gdk_window_set_cursor (view->canvas->window, cursor);
+ gdk_cursor_unref (cursor);
+ break;
+
+
+ default:
+ g_message ("Invalid view mode."); /*Should not happen!*/
+ }
+
+ }
+
+ cairo_destroy (cr);
+
+ return return_value;
+}
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE. Key press event handler. */
+/*---------------------------------------------------------------------------*/
+static gboolean
+key_press_event_cb (glView *view,
+ GdkEventKey *event)
+{
+ GdkCursor *cursor;
+
+ gl_debug (DEBUG_VIEW, "");
+
+ if ( (view->mode == GL_VIEW_MODE_ARROW) &&
+ (view->state == GL_VIEW_IDLE) )
+ {
+ switch (event->keyval) {
+
+ case GDK_Left:
+ case GDK_KP_Left:
+ gl_view_move_selection (view, -1.0 / (view->zoom), 0.0);
+ break;
+ case GDK_Up:
+ case GDK_KP_Up:
+ gl_view_move_selection (view, 0.0, -1.0 / (view->zoom));
+ break;
+ case GDK_Right:
+ case GDK_KP_Right:
+ gl_view_move_selection (view, 1.0 / (view->zoom), 0.0);
+ break;
+ case GDK_Down:
+ case GDK_KP_Down:
+ gl_view_move_selection (view, 0.0, 1.0 / (view->zoom));
+ break;
+ case GDK_Delete:
+ case GDK_KP_Delete:
+ gl_view_delete_selection (view);
+ cursor = gdk_cursor_new (GDK_LEFT_PTR);
+ gdk_window_set_cursor (GTK_WIDGET (view->canvas)->window
+, cursor);
+ gdk_cursor_unref (cursor);
+ break;
+ default:
+ return FALSE;
+
+ }
+ }
+ return TRUE; /* We handled this or we were dragging. */
}