aboutsummaryrefslogtreecommitdiff
path: root/src/gtk-ink.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gtk-ink.c')
-rw-r--r--src/gtk-ink.c297
1 files changed, 297 insertions, 0 deletions
diff --git a/src/gtk-ink.c b/src/gtk-ink.c
new file mode 100644
index 0000000..793911d
--- /dev/null
+++ b/src/gtk-ink.c
@@ -0,0 +1,297 @@
+/*
+ * gtk-ink.c
+ *
+ * GTK widget to display and collect Ink
+ *
+ * (c) 2002-2005 Thomas White <taw27@srcf.ucam.org>
+ * Part of TuxMessenger - GTK+-based MSN Messenger client
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 dated June, 1991.
+ *
+ * This package is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this package; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <math.h>
+#include <libgnomecanvas/libgnomecanvas.h>
+
+#include "gtk-ink.h"
+#include "ink.h"
+
+#define PAPER_WIDTH 640
+#define PAPER_HEIGHT 480
+
+static GtkObjectClass *parent_class = NULL;
+
+static void gtk_ink_draw_point(GtkInk *gtk_ink, GnomeCanvasGroup *root, InkPoint *prev_point, InkPoint *new_point) {
+
+ if ( prev_point == NULL ) {
+ gnome_canvas_item_new(root, gnome_canvas_ellipse_get_type(), "fill-color-gdk", gtk_ink->fgcolour, "x1", new_point->x-1, "y1", new_point->y-1, "x2", new_point->x+1, "y2", new_point->y+1, NULL);
+ } else {
+
+ GnomeCanvasPoints *points;
+ gdouble width;
+ gdouble delta;
+
+ points = gnome_canvas_points_new(2);
+ points->coords[0] = prev_point->x;
+ points->coords[1] = prev_point->y;
+ points->coords[2] = new_point->x;
+ points->coords[3] = new_point->y;
+
+ delta = sqrt((prev_point->x - new_point->x)*(prev_point->x - new_point->x) + (prev_point->y - new_point->y)*(prev_point->y - new_point->y));
+
+ /* Calibrate 'feel' here. */
+ width = (15-delta)/6.5;
+ if ( width < 0 ) {
+ width = 0;
+ }
+
+ gnome_canvas_item_new(root, gnome_canvas_line_get_type(), "fill-color-gdk", gtk_ink->fgcolour, "points", points, "width-units", width, NULL);
+ }
+
+}
+
+gboolean gtk_ink_realize(GtkWidget *widget, GtkInk *gtk_ink) {
+
+ InkStroke *stroke;
+ GnomeCanvasGroup *root;
+
+ GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
+ root = gnome_canvas_root(GNOME_CANVAS(gtk_ink));
+
+ /* Draw the (initial) pattern. */
+ stroke = gtk_ink->ink->strokes;
+ while ( stroke != NULL ) {
+
+ InkPoint *point;
+ point = stroke->points;
+
+ while ( point != NULL ) {
+
+ gtk_ink_draw_point(gtk_ink, root, point->prev, point);
+ point = point->next;
+
+ }
+ stroke = stroke->next;
+ }
+
+ return FALSE;
+
+}
+
+gboolean gtk_ink_expose_event(GtkWidget *widget, GdkEventExpose *event, GtkInk *gtk_ink) {
+
+ /* Draw the border. */
+ gtk_paint_shadow(widget->style, ((GtkLayout *)gtk_ink)->bin_window, widget->state, GTK_SHADOW_IN, &event->area, widget, NULL, 0, 0, gtk_ink->width, gtk_ink->height);
+
+ return FALSE;
+
+}
+
+static void gtk_ink_size_allocate(GtkWidget *widget, GtkAllocation *allocation, GtkInk *gtk_ink) {
+
+ gtk_ink->width = allocation->width;
+ gtk_ink->height = allocation->height;
+ gnome_canvas_set_scroll_region(GNOME_CANVAS(gtk_ink), 0, 0, allocation->width, allocation->height);
+
+ /* Sort the background out. */
+ if ( (gtk_ink->width > gtk_ink->x_bg_drawn * PAPER_WIDTH) || (gtk_ink->height > gtk_ink->y_bg_drawn * PAPER_HEIGHT) ) {
+
+ int x, y;
+ GnomeCanvasGroup *root;
+
+ root = gnome_canvas_root(GNOME_CANVAS(gtk_ink));
+
+ for ( x=gtk_ink->x_bg_drawn; x<=gtk_ink->width/PAPER_WIDTH; x++ ) {
+ for ( y=0; y<=gtk_ink->height/PAPER_HEIGHT; y++ ) {
+ if ( gtk_ink->bgpixbuf == NULL ) {
+ gnome_canvas_item_lower_to_bottom(gnome_canvas_item_new(root, gnome_canvas_rect_get_type(), "fill-color-gdk", gtk_ink->bgcolour, "x1", (gdouble)x*PAPER_WIDTH, "y1", (gdouble)y*PAPER_HEIGHT, "x2", (gdouble)(x+1)*PAPER_WIDTH, "y2", (gdouble)(y+1)*PAPER_HEIGHT, NULL));
+ } else {
+ gnome_canvas_item_lower_to_bottom(gnome_canvas_item_new(root, gnome_canvas_pixbuf_get_type(), "pixbuf", gtk_ink->bgpixbuf, "x", (gdouble)x*PAPER_WIDTH, "y", (gdouble)y*PAPER_HEIGHT, "x-in-pixels", TRUE, "y-in-pixels", TRUE, "width-set", FALSE, "height-set", FALSE, NULL));
+ }
+ }
+ }
+ gtk_ink->x_bg_drawn = (gtk_ink->width/PAPER_WIDTH)+1;
+
+ for ( x=0; x<gtk_ink->width/PAPER_WIDTH; x++ ) {
+ for ( y=gtk_ink->y_bg_drawn; y<=gtk_ink->height/PAPER_HEIGHT; y++ ) {
+ if ( gtk_ink->bgpixbuf == NULL ) {
+ gnome_canvas_item_lower_to_bottom(gnome_canvas_item_new(root, gnome_canvas_rect_get_type(), "fill-color-gdk", gtk_ink->bgcolour, "x1", (gdouble)x*PAPER_WIDTH, "y1", (gdouble)y*PAPER_HEIGHT, "x2", (gdouble)(x+1)*PAPER_WIDTH, "y2", (gdouble)(y+1)*PAPER_HEIGHT, NULL));
+ } else {
+ gnome_canvas_item_lower_to_bottom(gnome_canvas_item_new(root, gnome_canvas_pixbuf_get_type(), "pixbuf", gtk_ink->bgpixbuf, "x", (gdouble)x*PAPER_WIDTH, "y", (gdouble)y*PAPER_HEIGHT, "x-in-pixels", TRUE, "y-in-pixels", TRUE, "width-set", FALSE, "height-set", FALSE, NULL));
+ }
+ }
+ }
+ gtk_ink->y_bg_drawn = (gtk_ink->height/PAPER_HEIGHT)+1;
+
+ }
+
+}
+
+static void gtk_ink_add_point_and_draw(GtkInk *gtk_ink, double x, double y) {
+
+ InkStroke *stroke;
+ InkPoint *prev_point;
+ InkPoint *new_point;
+
+ stroke = ink_stroke_get_last(gtk_ink->ink);
+ prev_point = ink_point_get_last(stroke);
+ new_point = ink_point_add(stroke, x, y);
+
+ gtk_ink_draw_point(gtk_ink, gnome_canvas_root(GNOME_CANVAS(gtk_ink)), prev_point, new_point);
+
+}
+
+static gboolean gtk_ink_button_release(GtkWidget *widget, GdkEventButton *event, GtkInk *gtk_ink) {
+ gtk_ink->drawing = FALSE;
+ return TRUE;
+}
+
+static gboolean gtk_ink_button_press(GtkWidget *widget, GdkEventButton *event, GtkInk *gtk_ink) {
+
+ ink_stroke_new(gtk_ink->ink);
+ gtk_ink_add_point_and_draw(gtk_ink, event->x, event->y);
+ gtk_ink->drawing = TRUE;
+
+ /* Grab focus */
+ if ( !GTK_WIDGET_HAS_DEFAULT(gtk_ink) ) {
+ gtk_widget_grab_default(GTK_WIDGET(gtk_ink));
+ }
+ if ( !GTK_WIDGET_HAS_FOCUS(gtk_ink) ) {
+ gtk_widget_grab_focus(GTK_WIDGET(gtk_ink));
+ }
+
+ return TRUE; /* Claim it. */
+
+}
+
+static gboolean gtk_ink_motion(GtkWidget *widget, GdkEventMotion *event, GtkInk *gtk_ink) {
+
+ if ( gtk_ink->drawing ) {
+ gtk_ink_add_point_and_draw(gtk_ink, event->x, event->y);
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+static void gtk_ink_destroy(GtkObject *gtk_ink) {
+
+ /* GdkColors automagically freed. */
+ parent_class->destroy(gtk_ink);
+
+}
+
+GtkWidget *gtk_ink_new(GtkInkFlags flags, Ink *ink, GdkColor *fgcolour, GdkColor *bgcolour) {
+
+ GtkInk *gtk_ink;
+
+ gtk_ink = GTK_INK(gtk_type_new(gtk_ink_get_type()));
+
+ gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(gtk_ink), 1);
+
+ gtk_signal_connect_after(GTK_OBJECT(gtk_ink), "expose_event", GTK_SIGNAL_FUNC(gtk_ink_expose_event), gtk_ink);
+ gtk_signal_connect(GTK_OBJECT(gtk_ink), "size_allocate", GTK_SIGNAL_FUNC(gtk_ink_size_allocate), gtk_ink);
+ gtk_signal_connect(GTK_OBJECT(gtk_ink), "realize", GTK_SIGNAL_FUNC(gtk_ink_realize), gtk_ink);
+
+ if ( flags & GTK_INK_FLAG_EDITABLE ) {
+ gtk_signal_connect(GTK_OBJECT(gtk_ink), "button-press-event", GTK_SIGNAL_FUNC(gtk_ink_button_press), gtk_ink);
+ gtk_signal_connect(GTK_OBJECT(gtk_ink), "button-release-event", GTK_SIGNAL_FUNC(gtk_ink_button_release), gtk_ink);
+ gtk_signal_connect(GTK_OBJECT(gtk_ink), "motion-notify-event", GTK_SIGNAL_FUNC(gtk_ink_motion), gtk_ink);
+ gtk_widget_add_events(GTK_WIDGET(gtk_ink), GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_MOTION_MASK);
+ }
+ g_object_set(G_OBJECT(gtk_ink), "can-focus", TRUE, "can-default", TRUE, NULL);
+
+ /* Set up properties. */
+ gtk_ink->bgcolour = gdk_color_copy(bgcolour);
+ gtk_ink->fgcolour = gdk_color_copy(fgcolour);
+ gtk_ink->flags = flags;
+ gtk_ink->ink = ink;
+ gtk_ink->x_bg_drawn = 0;
+ gtk_ink->y_bg_drawn = 0;
+ gtk_ink->drawing = FALSE;
+
+ if ( flags & GTK_INK_FLAG_PAPER ) {
+ gtk_ink->bgpixbuf = gdk_pixbuf_new_from_file("/usr/local/share/tuxmessenger/paper.png", NULL);
+ } else {
+ gtk_ink->bgpixbuf = NULL;
+ }
+
+ return GTK_WIDGET(gtk_ink);
+
+}
+
+static GObject *gtk_ink_constructor(GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) {
+
+ GtkInkClass *class;
+ GObjectClass *p_class;
+ GObject *obj;
+
+ class = GTK_INK_CLASS(g_type_class_peek(gtk_ink_get_type()));
+ p_class = G_OBJECT_CLASS(g_type_class_peek_parent(class));
+
+ obj = p_class->constructor(type, n_construct_properties, construct_properties);
+ g_object_set(obj, "aa", TRUE, NULL);
+
+ return obj;
+
+}
+
+static void gtk_ink_class_init(GtkInkClass *class) {
+
+ GtkObjectClass *object_class;
+ GObjectClass *g_object_class;
+
+ object_class = (GtkObjectClass *) class;
+ g_object_class = G_OBJECT_CLASS(class);
+
+ object_class->destroy = gtk_ink_destroy;
+ g_object_class->constructor = gtk_ink_constructor;
+
+ parent_class = gtk_type_class(gnome_canvas_get_type());
+
+}
+
+static void gtk_ink_init(GtkInk *gtk_ink) {
+}
+
+guint gtk_ink_get_type(void) {
+
+ static guint gtk_ink_type = 0;
+
+ if ( !gtk_ink_type ) {
+
+ GtkTypeInfo gtk_ink_info = {
+ "GtkInk",
+ sizeof(GtkInk),
+ sizeof(GtkInkClass),
+ (GtkClassInitFunc) gtk_ink_class_init,
+ (GtkObjectInitFunc) gtk_ink_init,
+ NULL,
+ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+ gtk_ink_type = gtk_type_unique(gnome_canvas_get_type(), &gtk_ink_info);
+
+ }
+
+ return gtk_ink_type;
+
+}