diff options
author | Thomas White <taw@bitwiz.org.uk> | 2011-10-13 23:31:15 +0200 |
---|---|---|
committer | Thomas White <taw@bitwiz.org.uk> | 2011-10-13 23:31:15 +0200 |
commit | 2e0f09d78f28c576d9a10dfcd1eeaae81e3baa07 (patch) | |
tree | 9be7b14eefb4451ac6c2a2dccce24625dc3bf7af /src/tool_image.c | |
parent | 7c54f36c7a5352dfd34322397ed322bb377b1abb (diff) |
Add image handling basics
Diffstat (limited to 'src/tool_image.c')
-rw-r--r-- | src/tool_image.c | 307 |
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; +} |