diff options
author | Thomas White <taw@bitwiz.org.uk> | 2013-05-27 23:41:09 +0200 |
---|---|---|
committer | Thomas White <taw@bitwiz.org.uk> | 2013-05-27 23:41:09 +0200 |
commit | 1a9db7758e2895c9f9efc31d796147add495ffcc (patch) | |
tree | d7f89ff83388c26cf555138d060d20fa109763d8 /src | |
parent | 8d46c23cb332f7f3b875bfa670fd2d1a5f0b21c1 (diff) |
Selection/resize stuff
Diffstat (limited to 'src')
-rw-r--r-- | src/mainwindow.c | 220 | ||||
-rw-r--r-- | src/presentation.h | 17 |
2 files changed, 231 insertions, 6 deletions
diff --git a/src/mainwindow.c b/src/mainwindow.c index 673d6d0..b7b51e7 100644 --- a/src/mainwindow.c +++ b/src/mainwindow.c @@ -31,6 +31,7 @@ #include <assert.h> #include <gdk/gdkkeysyms.h> #include <gdk-pixbuf/gdk-pixbuf.h> +#include <math.h> #include "presentation.h" #include "mainwindow.h" @@ -803,12 +804,35 @@ static void draw_caret(cairo_t *cr, struct frame *fr, int pos) } +static void draw_resize_handle(cairo_t *cr, double x, double y) +{ + cairo_new_path(cr); + cairo_rectangle(cr, x, y, 20.0, 20.0); + cairo_set_source_rgba(cr, 0.9, 0.9, 0.9, 0.5); + cairo_fill(cr); +} + + static void draw_overlay(cairo_t *cr, struct presentation *p) { int i; for ( i=0; i<p->n_selection; i++ ) { + + double x, y, w, h; + draw_editing_box(cr, p->selection[i]); + + x = p->selection[i]->lop.x; + y = p->selection[i]->lop.y; + w = p->selection[i]->lop.w; + h = p->selection[i]->lop.h; + + /* Draw resize handles */ + draw_resize_handle(cr, x, y+h-20.0); + draw_resize_handle(cr, x+w-20.0, y); + draw_resize_handle(cr, x, y); + draw_resize_handle(cr, x+w-20.0, y+h-20.0); } /* If only one frame is selected, draw the caret */ @@ -829,6 +853,17 @@ static void draw_overlay(cairo_t *cr, struct presentation *p) cairo_stroke(cr); } + if ( (p->drag_status == DRAG_STATUS_DRAGGING) + && (p->drag_reason == DRAG_REASON_RESIZE) ) + { + cairo_new_path(cr); + cairo_rectangle(cr, p->box_x, p->box_y, + p->box_width, p->box_height); + cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); + cairo_set_line_width(cr, 0.5); + cairo_stroke(cr); + } + } @@ -955,9 +990,145 @@ static gboolean im_commit_sig(GtkIMContext *im, gchar *str, } -static struct frame *find_frame_at_position(struct slide *slide, +static int within_frame(struct frame *fr, double x, double y) +{ + if ( x < fr->x ) return 0; + if ( y < fr->y ) return 0; + if ( x > fr->x + fr->w ) return 0; + if ( y > fr->y + fr->h ) return 0; + return 1; +} + + +static struct frame *find_frame_at_position(struct frame *fr, double x, double y) { + int i; + + for ( i=0; i<fr->num_children; i++ ) { + + if ( within_frame(fr->children[i], x, y) ) { + return find_frame_at_position(fr->children[i], x, y); + } + + } + + if ( within_frame(fr, x, y) ) return fr; + return NULL; +} + + +static enum corner which_corner(double xp, double yp, struct frame *fr) +{ + double x, y; /* Relative to object position */ + + x = xp - fr->x; + y = yp - fr->y; + + if ( x < 0.0 ) return CORNER_NONE; + if ( y < 0.0 ) return CORNER_NONE; + if ( x > fr->w ) return CORNER_NONE; + if ( y > fr->h ) return CORNER_NONE; + + /* Top left? */ + if ( (x<20.0) && (y<20.0) ) return CORNER_TL; + if ( (x>fr->w-20.0) && (y<20.0) ) return CORNER_TR; + if ( (x<20.0) && (y>fr->h-20.0) ) { + return CORNER_BL; + } + if ( (x>fr->w-20.0) && (y>fr->h-20.0) ) { + return CORNER_BR; + } + + return CORNER_NONE; +} + + +static void calculate_box_size(struct frame *fr, struct presentation *p, + double x, double y) +{ + double ddx, ddy, dlen, mult; + double vx, vy, dbx, dby; + + ddx = x - p->start_corner_x; + ddy = y - p->start_corner_y; + + switch ( p->drag_corner ) { + + case CORNER_BR : + vx = fr->w; + vy = fr->h; + break; + + case CORNER_BL : + vx = -fr->w; + vy = fr->h; + break; + + case CORNER_TL : + vx = -fr->w; + vy = -fr->h; + break; + + case CORNER_TR : + vx = fr->w; + vy = -fr->h; + break; + + case CORNER_NONE : + default: + vx = 0.0; + vy = 0.0; + break; + + } + + dlen = (ddx*vx + ddy*vy) / p->diagonal_length; + mult = (dlen+p->diagonal_length) / p->diagonal_length; + + p->box_width = fr->w * mult; + p->box_height = fr->h * mult; + dbx = p->box_width - fr->w; + dby = p->box_height - fr->h; + + if ( p->box_width < 40.0 ) { + mult = 40.0 / fr->w; + } + if ( p->box_height < 40.0 ) { + mult = 40.0 / fr->h; + } + p->box_width = fr->w * mult; + p->box_height = fr->h * mult; + dbx = p->box_width - fr->w; + dby = p->box_height - fr->h; + + switch ( p->drag_corner ) { + + case CORNER_BR : + p->box_x = fr->x; + p->box_y = fr->y; + break; + + case CORNER_BL : + p->box_x = fr->x - dbx; + p->box_y = fr->y; + break; + + case CORNER_TL : + p->box_x = fr->x - dbx; + p->box_y = fr->y - dby; + break; + + case CORNER_TR : + p->box_x = fr->x; + p->box_y = fr->y - dby; + break; + + case CORNER_NONE : + break; + + } + } @@ -970,7 +1141,7 @@ static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event, x = event->x - p->border_offs_x; y = event->y - p->border_offs_y; - clicked = find_frame_at_position(p->cur_edit_slide, x, y); + clicked = find_frame_at_position(p->cur_edit_slide->top, x, y); if ( clicked == NULL ) { @@ -989,12 +1160,37 @@ static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event, * selected one, deselect the old one. */ if ( p->selection[0] != clicked ) { set_selection(p, NULL); - } + p->drag_status = DRAG_STATUS_NONE; + p->drag_reason = DRAG_REASON_NONE; + set_selection(p, clicked); + } else { + + enum corner c; + struct frame *fr; + + fr = p->selection[0]; + + /* Within the resizing region? */ + c = which_corner(x, y, fr); + if ( c != CORNER_NONE ) { - p->drag_status = DRAG_STATUS_NONE; - p->drag_reason = DRAG_REASON_NONE; + p->drag_reason = DRAG_REASON_RESIZE; + p->drag_corner = c; - set_selection(p, clicked); + p->start_corner_x = x; + p->start_corner_y = y; + p->diagonal_length = pow(fr->w, 2.0); + p->diagonal_length += pow(fr->h, 2.0); + p->diagonal_length = sqrt(p->diagonal_length); + + calculate_box_size(fr, p, x, y); + + p->drag_status = DRAG_STATUS_COULD_DRAG; + p->drag_reason = DRAG_REASON_RESIZE; + printf("could drag resize\n"); + } + + } } @@ -1007,6 +1203,8 @@ static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event, static gboolean motion_sig(GtkWidget *da, GdkEventMotion *event, struct presentation *p) { + struct frame *fr = p->selection[0]; + if ( p->drag_status == DRAG_STATUS_COULD_DRAG ) { /* We just got a motion signal, and the status was "could drag", @@ -1030,6 +1228,12 @@ static gboolean motion_sig(GtkWidget *da, GdkEventMotion *event, /* Do nothing, handled by dnd_motion() */ break; + case DRAG_REASON_RESIZE : + calculate_box_size(fr, p, event->x - p->border_offs_x, + event->y - p->border_offs_y); + redraw_editor(p); + break; + } gdk_event_request_motions(event); @@ -1099,6 +1303,10 @@ static gboolean button_release_sig(GtkWidget *da, GdkEventButton *event, /* Do nothing, handled in dnd_drop() or dnd_leave() */ break; + case DRAG_REASON_RESIZE : + /* FIXME: Implement */ + break; + } p->drag_reason = DRAG_REASON_NONE; diff --git a/src/presentation.h b/src/presentation.h index 533ee10..f0e3071 100644 --- a/src/presentation.h +++ b/src/presentation.h @@ -56,6 +56,17 @@ enum drag_reason DRAG_REASON_NONE, DRAG_REASON_CREATE, DRAG_REASON_IMPORT, + DRAG_REASON_RESIZE, +}; + + +enum corner +{ + CORNER_NONE, + CORNER_TL, + CORNER_TR, + CORNER_BL, + CORNER_BR }; @@ -125,8 +136,14 @@ struct presentation double start_corner_y; double drag_corner_x; double drag_corner_y; + double diagonal_length; + double box_x; + double box_y; + double box_width; + double box_height; enum drag_reason drag_reason; enum drag_status drag_status; + enum corner drag_corner; /* Stuff to do with drag and drop import of "content" */ int drag_preview_pending; |