aboutsummaryrefslogtreecommitdiff
path: root/src/tool_image.c
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2011-10-13 23:31:15 +0200
committerThomas White <taw@bitwiz.org.uk>2011-10-13 23:31:15 +0200
commit2e0f09d78f28c576d9a10dfcd1eeaae81e3baa07 (patch)
tree9be7b14eefb4451ac6c2a2dccce24625dc3bf7af /src/tool_image.c
parent7c54f36c7a5352dfd34322397ed322bb377b1abb (diff)
Add image handling basics
Diffstat (limited to 'src/tool_image.c')
-rw-r--r--src/tool_image.c307
1 files changed, 307 insertions, 0 deletions
diff --git a/src/tool_image.c b/src/tool_image.c
new file mode 100644
index 0000000..af4ada5
--- /dev/null
+++ b/src/tool_image.c
@@ -0,0 +1,307 @@
+/*
+ * tool_image.c
+ *
+ * Colloquium - A tiny presentation program
+ *
+ * Copyright (c) 2011 Thomas White <taw@bitwiz.org.uk>
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "presentation.h"
+#include "objects.h"
+#include "mainwindow.h"
+#include "slide_render.h"
+
+
+enum image_drag_reason
+{
+ IMAGE_DRAG_REASON_NONE,
+ IMAGE_DRAG_REASON_RESIZE,
+};
+
+
+struct image_toolinfo
+{
+ struct toolinfo base;
+ enum image_drag_reason drag_reason;
+ double box_x;
+ double box_y;
+ double box_width;
+ double box_height;
+ double drag_offset_x;
+ double drag_offset_y;
+};
+
+
+struct image_object
+{
+ struct object base;
+
+ struct image *image;
+};
+
+
+static void update_image(struct image_object *o)
+{
+ /* FIXME: Implement this */
+}
+
+
+static void render_image_object(cairo_t *cr, struct object *op)
+{
+ struct image_object *o = (struct image_object *)op;
+
+ cairo_new_path(cr);
+ cairo_rectangle(cr, op->x, op->y, op->bb_width, op->bb_height);
+ gdk_cairo_set_source_pixbuf(cr, o->image->pb, op->x, op->y);
+ cairo_fill(cr);
+}
+
+
+
+static void update_image_object(struct object *op)
+{
+ struct image_object *o = (struct image_object *)op;
+ update_image(o);
+}
+
+
+static void delete_image_object(struct object *op)
+{
+ //struct image_object *o = (struct image_object *)op;
+}
+
+
+struct object *add_image_object(struct slide *s, double x, double y,
+ double bb_width, double bb_height,
+ char *filename, struct style *sty,
+ struct image_store *is,
+ struct image_toolinfo *ti)
+{
+ struct image_object *new;
+
+ new = calloc(1, sizeof(*new));
+ if ( new == NULL ) return NULL;
+
+ /* Base properties */
+ new->base.x = x; new->base.y = y;
+ new->base.bb_width = bb_width;
+ new->base.bb_height = bb_height;
+ new->base.type = IMAGE;
+ new->base.empty = 0;
+ new->base.parent = NULL;
+ new->base.style = sty;
+
+ new->image = get_image(is, filename);
+ if ( new->image == NULL ) {
+ free(new);
+ printf("Failed to load or get image.\n");
+ return NULL;
+ }
+
+ /* Methods for this object */
+ new->base.render_object = render_image_object;
+ new->base.delete_object = delete_image_object;
+ new->base.update_object = update_image_object;
+
+ if ( add_object_to_slide(s, (struct object *)new) ) {
+ free(new);
+ return NULL;
+ }
+ s->object_seq++;
+
+ update_image(new);
+
+ return (struct object *)new;
+}
+
+
+static void click_select(struct presentation *p, struct toolinfo *tip,
+ double x, double y, GdkEventButton *event,
+ enum drag_status *drag_status,
+ enum drag_reason *drag_reason)
+{
+ double xo, yo;
+ struct image_toolinfo *ti = (struct image_toolinfo *)tip;
+ struct image_object *o = (struct image_object *)p->editing_object;
+
+ assert(o->base.type == IMAGE);
+
+ xo = x - o->base.x; yo = y - o->base.y;
+
+ /* Within the resizing region? */
+ if ( (xo > o->base.bb_width - 20.0) && (yo > o->base.bb_height - 20.0) )
+ {
+ double cx, cy;
+
+ ti->drag_reason = IMAGE_DRAG_REASON_RESIZE;
+
+ /* Initial size of rubber band box */
+ ti->box_x = o->base.x; ti->box_y = o->base.y;
+ ti->box_width = o->base.bb_width;
+ ti->box_height = o->base.bb_height;
+
+ /* Coordinates of the bottom right corner */
+ cx = o->base.x + o->base.bb_width;
+ cy = o->base.y + o->base.bb_height;
+
+ ti->drag_offset_x = x - cx;
+ ti->drag_offset_y = y - cy;
+
+ /* Tell the MCP what we did, and return */
+ *drag_status = DRAG_STATUS_DRAGGING;
+ *drag_reason = DRAG_REASON_TOOL;
+ return;
+ }
+}
+
+
+static void drag(struct toolinfo *tip, struct presentation *p,
+ struct object *o, double x, double y)
+{
+ struct image_toolinfo *ti = (struct image_toolinfo *)tip;
+
+ ti->box_width = x - ti->drag_offset_x - ti->box_x;
+ ti->box_height = y - ti->drag_offset_y - ti->box_y;
+ if ( ti->box_width < 20.0 ) ti->box_width = 20.0;
+ if ( ti->box_height < 20.0 ) ti->box_height = 20.0;
+
+ redraw_overlay(p);
+}
+
+
+static void end_drag(struct toolinfo *tip, struct presentation *p,
+ struct object *o, double x, double y)
+{
+ struct image_toolinfo *ti = (struct image_toolinfo *)tip;
+
+ ti->box_width = x - ti->drag_offset_x - ti->box_x;
+ ti->box_height = y - ti->drag_offset_y - ti->box_y;
+ if ( ti->box_width < 20.0 ) ti->box_width = 20.0;
+ if ( ti->box_height < 20.0 ) ti->box_height = 20.0;
+
+ o->bb_width = ti->box_width;
+ o->bb_height = ti->box_height;
+ update_image((struct image_object *)o);
+ o->parent->object_seq++;
+
+ ti->drag_reason = IMAGE_DRAG_REASON_NONE;
+ redraw_overlay(p);
+}
+
+
+static void create_region(struct toolinfo *tip, struct presentation *p,
+ double x1, double y1, double x2, double y2)
+{
+ //struct object *n;
+ //struct image_toolinfo *ti = (struct image_toolinfo *)tip;
+ //struct image_object *o;
+
+ /* FIXME: Open an "Open file" dialogue box and use the result */
+}
+
+
+static void select_object(struct object *o, struct toolinfo *tip)
+{
+ /* Do nothing */
+}
+
+
+static int deselect_object(struct object *o, struct toolinfo *tip)
+{
+ if ( (o != NULL) && o->empty ) {
+ delete_object(o);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static void draw_overlay(struct toolinfo *tip, cairo_t *cr, struct object *n)
+{
+ struct image_toolinfo *ti = (struct image_toolinfo *)tip;
+ //struct image_object *o = (struct image_object *)n;
+
+ if ( n != NULL ) {
+
+ draw_editing_box(cr, n->x, n->y, n->bb_width, n->bb_height);
+
+ /* Draw resize handle */
+ cairo_new_path(cr);
+ cairo_rectangle(cr, n->x+n->bb_width-20.0,
+ n->y+n->bb_height-20.0, 20.0, 20.0);
+ cairo_set_source_rgba(cr, 0.9, 0.9, 0.9, 0.5);
+ cairo_fill(cr);
+ }
+
+ if ( ti->drag_reason == IMAGE_DRAG_REASON_RESIZE ) {
+
+ /* FIXME: Use common draw_rubberband_box() routine */
+ cairo_new_path(cr);
+ cairo_rectangle(cr, ti->box_x, ti->box_y,
+ ti->box_width, ti->box_height);
+ cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
+ cairo_set_line_width(cr, 0.5);
+ cairo_stroke(cr);
+
+ }
+
+}
+
+
+static void key_pressed(struct object *o, guint keyval, struct toolinfo *tip)
+{
+ /* Do nothing */
+}
+
+
+static void im_commit(struct object *o, gchar *str, struct toolinfo *tip)
+{
+ /* Do nothing */
+}
+
+
+struct toolinfo *initialise_image_tool()
+{
+ struct image_toolinfo *ti;
+
+ ti = malloc(sizeof(*ti));
+
+ ti->base.click_select = click_select;
+ ti->base.create_default = NULL;
+ ti->base.select = select_object;
+ ti->base.deselect = deselect_object;
+ ti->base.drag = drag;
+ ti->base.end_drag = end_drag;
+ ti->base.create_region = create_region;
+ ti->base.draw_editing_overlay = draw_overlay;
+ ti->base.key_pressed = key_pressed;
+ ti->base.im_commit = im_commit;
+
+ return (struct toolinfo *)ti;
+}