diff options
author | Thomas White <taw@bitwiz.org.uk> | 2011-10-11 23:38:05 +0200 |
---|---|---|
committer | Thomas White <taw@bitwiz.org.uk> | 2011-10-11 23:38:05 +0200 |
commit | 80224ffa532362f66e905ecf3b599fff17bb2e39 (patch) | |
tree | e9c531273e5be7c1739b696018f3d56832fbd0cf | |
parent | 920a213f5453ef9b904d8b90be37ec678b5c7055 (diff) |
Design for general drag logic
-rw-r--r-- | src/mainwindow.c | 156 | ||||
-rw-r--r-- | src/presentation.c | 1 | ||||
-rw-r--r-- | src/presentation.h | 28 | ||||
-rw-r--r-- | src/slide_render.c | 11 | ||||
-rw-r--r-- | src/tool_select.c | 21 | ||||
-rw-r--r-- | src/tool_text.c | 114 |
6 files changed, 231 insertions, 100 deletions
diff --git a/src/mainwindow.c b/src/mainwindow.c index 6dc82a4..c74abd5 100644 --- a/src/mainwindow.c +++ b/src/mainwindow.c @@ -609,69 +609,6 @@ static gboolean key_press_sig(GtkWidget *da, GdkEventKey *event, } -static void start_drag_create(struct presentation *p, double x, double y) -{ - p->start_corner_x = x; - p->start_corner_y = y; - p->create_dragging = 1; -} - - -static void drag_create(struct presentation *p, double x, double y) -{ - p->drag_corner_x = x; - p->drag_corner_y = y; - redraw_overlay(p); -} - - -static void finish_drag_create(struct presentation *p, double x, double y) -{ - p->drag_corner_x = x; - p->drag_corner_y = y; - p->create_dragging = 0; - redraw_overlay(p); - p->cur_tool->create_region(p->cur_tool, p, - p->start_corner_x, p->start_corner_y, - p->drag_corner_x, p->drag_corner_y); -} - - -static gboolean motion_sig(GtkWidget *da, GdkEventMotion *event, - struct presentation *p) -{ - switch ( p->drag_reason ) { - - case DRAG_REASON_NONE : - /* If there was no reason before, now there is */ - p->drag_reason = DRAG_REASON_CREATE; - - /* Start the drag, and send the first drag event */ - start_drag_create(p, p->start_create_drag_x, - p->start_create_drag_y); - drag_create(p, event->x - p->border_offs_x, - event->y - p->border_offs_y); - break; - - case DRAG_REASON_MOVE : - p->cur_tool->drag_object(p->cur_tool, p, p->editing_object, - event->x - p->border_offs_x, - event->y - p->border_offs_y); - break; - - case DRAG_REASON_CREATE : - drag_create(p, event->x - p->border_offs_x, - event->y - p->border_offs_y); - - break; - - } - - gdk_event_request_motions(event); - return FALSE; -} - - static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event, struct presentation *p) { @@ -685,23 +622,33 @@ static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event, if ( clicked == NULL ) { + /* Clicked no object. Deselect old object and set up for + * (maybe) creating a new one. */ + if ( p->editing_object != NULL ) { p->cur_tool->deselect(p->editing_object, p->cur_tool); p->editing_object = NULL; } - p->start_create_drag_x = x; - p->start_create_drag_y = y; - p->drag_reason = DRAG_REASON_NONE; + p->start_corner_x = event->x - p->border_offs_x; + p->start_corner_y = event->y - p->border_offs_y; + p->drag_status = DRAG_STATUS_COULD_DRAG; + p->drag_reason = DRAG_REASON_CREATE; } else { - if ( p->editing_object != NULL ) { + /* If the clicked object is not the same as the previously + * selected one, deselect the old one. */ + if ( p->editing_object != clicked ) { p->cur_tool->deselect(p->editing_object, p->cur_tool); + p->editing_object = NULL; } - p->editing_object = clicked; - p->cur_tool->click_select(p, p->cur_tool, x, y); - p->drag_reason = DRAG_REASON_MOVE; + p->editing_object = clicked; + p->drag_status = DRAG_STATUS_NONE; + p->drag_reason = DRAG_REASON_NONE; + p->cur_tool->click_select(p, p->cur_tool, x, y, event, + &p->drag_status, + &p->drag_reason); } gtk_widget_grab_focus(GTK_WIDGET(da)); @@ -710,6 +657,41 @@ static gboolean button_press_sig(GtkWidget *da, GdkEventButton *event, } +static gboolean motion_sig(GtkWidget *da, GdkEventMotion *event, + struct presentation *p) +{ + if ( p->drag_status == DRAG_STATUS_COULD_DRAG ) { + + /* We just got a motion signal, and the status was "could drag", + * therefore the drag has started. */ + p->drag_status = DRAG_STATUS_DRAGGING; + + } + + switch ( p->drag_reason ) { + + case DRAG_REASON_NONE : + break; + + case DRAG_REASON_CREATE : + p->drag_corner_x = event->x - p->border_offs_x; + p->drag_corner_y = event->y - p->border_offs_y; + redraw_overlay(p); + break; + + case DRAG_REASON_TOOL : + p->cur_tool->drag(p->cur_tool, p, p->editing_object, + event->x - p->border_offs_x, + event->y - p->border_offs_y); + break; + + } + + gdk_event_request_motions(event); + return FALSE; +} + + static gboolean button_release_sig(GtkWidget *da, GdkEventButton *event, struct presentation *p) { @@ -718,22 +700,37 @@ static gboolean button_release_sig(GtkWidget *da, GdkEventButton *event, x = event->x - p->border_offs_x; y = event->y - p->border_offs_y; - switch ( p->drag_reason ) { + /* Not dragging? Then I don't care. */ + if ( p->drag_status != DRAG_STATUS_DRAGGING ) return FALSE; + + p->drag_corner_x = x; + p->drag_corner_y = y; + p->drag_status = DRAG_STATUS_NONE; + + switch ( p->drag_reason ) + { case DRAG_REASON_NONE : - p->cur_tool->click_create(p, p->cur_tool, x, y); + printf("Release on pointless drag.\n"); break; case DRAG_REASON_CREATE : - finish_drag_create(p, x, y); - break; - - case DRAG_REASON_MOVE : - /* FIXME: Update presentation and other stuff? */ + redraw_overlay(p); + p->cur_tool->create_region(p->cur_tool, p, + p->start_corner_x, + p->start_corner_y, + p->drag_corner_x, + p->drag_corner_y); + break; + + case DRAG_REASON_TOOL : + p->cur_tool->end_drag(p->cur_tool, p, p->editing_object, x, y); break; } + p->drag_reason = DRAG_REASON_NONE; + gtk_widget_grab_focus(GTK_WIDGET(da)); redraw_overlay(p); return FALSE; @@ -771,7 +768,9 @@ static void draw_overlay(cairo_t *cr, struct presentation *p) cairo_stroke(cr); } - if ( p->create_dragging ) { + if ( (p->drag_status == DRAG_STATUS_DRAGGING) + && (p->drag_reason == DRAG_REASON_CREATE) ) { + cairo_new_path(cr); cairo_rectangle(cr, p->start_corner_x, p->start_corner_y, p->drag_corner_x - p->start_corner_x, @@ -779,6 +778,7 @@ static void draw_overlay(cairo_t *cr, struct presentation *p) cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); cairo_set_line_width(cr, 0.5); cairo_stroke(cr); + } } diff --git a/src/presentation.c b/src/presentation.c index c66507d..b05ba4b 100644 --- a/src/presentation.c +++ b/src/presentation.c @@ -220,6 +220,7 @@ struct presentation *new_presentation() new->editing_object = NULL; new->completely_empty = 1; + new->drag_status = DRAG_STATUS_NONE; new->ss = new_stylesheet(); diff --git a/src/presentation.h b/src/presentation.h index a06fbc9..5b319ab 100644 --- a/src/presentation.h +++ b/src/presentation.h @@ -50,7 +50,15 @@ enum drag_reason { DRAG_REASON_NONE, DRAG_REASON_CREATE, - DRAG_REASON_MOVE, + DRAG_REASON_TOOL, +}; + + +enum drag_status +{ + DRAG_STATUS_NONE, + DRAG_STATUS_COULD_DRAG, + DRAG_STATUS_DRAGGING, }; @@ -59,13 +67,17 @@ struct toolinfo void (*click_create)(struct presentation *p, struct toolinfo *tip, double x, double y); void (*click_select)(struct presentation *p, struct toolinfo *tip, - double x, double y); + double x, double y, GdkEventButton *event, + enum drag_status *drag_status, + enum drag_reason *drag_reason); void (*create_default)(struct presentation *p, struct style *sty, struct toolinfo *tip); void (*select)(struct object *o, struct toolinfo *tip); int (*deselect)(struct object *o, struct toolinfo *tip); - void (*drag_object)(struct toolinfo *tip, struct presentation *p, - struct object *o, double x, double y); + void (*drag)(struct toolinfo *tip, struct presentation *p, + struct object *o, double x, double y); + void (*end_drag)(struct toolinfo *tip, struct presentation *p, + struct object *o, double x, double y); void (*create_region)(struct toolinfo *tip, struct presentation *p, double x1, double y1, double x2, double y2); @@ -128,16 +140,14 @@ struct presentation /* Tool status */ struct toolinfo *cur_tool; - double drag_offs_x; - double drag_offs_y; - double start_create_drag_x; - double start_create_drag_y; - int create_dragging; + + /* Rubber band boxes and related stuff */ double start_corner_x; double start_corner_y; double drag_corner_x; double drag_corner_y; enum drag_reason drag_reason; + enum drag_status drag_status; unsigned int num_slides; struct slide **slides; diff --git a/src/slide_render.c b/src/slide_render.c index 3c05f70..e68499a 100644 --- a/src/slide_render.c +++ b/src/slide_render.c @@ -82,9 +82,20 @@ void check_redraw_slide(struct slide *s) void draw_editing_box(cairo_t *cr, double xmin, double ymin, double width, double height) { + const double dash[] = {2.0, 2.0}; + cairo_new_path(cr); cairo_rectangle(cr, xmin-5.0, ymin-5.0, width+10.0, height+10.0); cairo_set_source_rgb(cr, 0.0, 0.69, 1.0); cairo_set_line_width(cr, 0.5); cairo_stroke(cr); + + cairo_new_path(cr); + cairo_rectangle(cr, xmin, ymin, width, height); + cairo_set_dash(cr, dash, 2, 0.0); + cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); + cairo_set_line_width(cr, 0.1); + cairo_stroke(cr); + + cairo_set_dash(cr, NULL, 0, 0.0); } diff --git a/src/tool_select.c b/src/tool_select.c index c03ebd1..57e6721 100644 --- a/src/tool_select.c +++ b/src/tool_select.c @@ -51,18 +51,23 @@ static void click_create(struct presentation *p, struct toolinfo *tip, static void click_select(struct presentation *p, struct toolinfo *tip, - double x, double y) + double x, double y, GdkEventButton *event, + enum drag_status *drag_status, + enum drag_reason *drag_reason) { struct select_toolinfo *ti = (struct select_toolinfo *)tip; struct object *clicked = p->editing_object; ti->drag_offs_x = clicked->x - x; ti->drag_offs_y = clicked->y - y; + + *drag_status = DRAG_STATUS_COULD_DRAG; + *drag_reason = DRAG_REASON_TOOL; } -static void drag_object(struct toolinfo *tip, struct presentation *p, - struct object *o, double x, double y) +static void drag(struct toolinfo *tip, struct presentation *p, + struct object *o, double x, double y) { struct select_toolinfo *ti = (struct select_toolinfo *)tip; double eright, ebottom; @@ -85,6 +90,13 @@ static void drag_object(struct toolinfo *tip, struct presentation *p, } +static void end_drag(struct toolinfo *tip, struct presentation *p, + struct object *o, double x, double y) +{ + /* FIXME: Update projection or something? */ +} + + static void create_region(struct toolinfo *tip, struct presentation *p, double x1, double y1, double x2, double y2) { @@ -136,7 +148,8 @@ struct toolinfo *initialise_select_tool() ti->base.create_default = NULL; ti->base.select = select_object; ti->base.deselect = deselect_object; - ti->base.drag_object = drag_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; diff --git a/src/tool_text.c b/src/tool_text.c index a7f27c2..4af8b8e 100644 --- a/src/tool_text.c +++ b/src/tool_text.c @@ -37,10 +37,24 @@ #include "slide_render.h" +enum text_drag_reason +{ + TEXT_DRAG_REASON_NONE, + TEXT_DRAG_REASON_RESIZE, +}; + + struct text_toolinfo { - struct toolinfo base; - PangoContext *pc; + struct toolinfo base; + PangoContext *pc; + enum text_drag_reason drag_reason; + double box_x; + double box_y; + double box_width; + double box_height; + double drag_offset_x; + double drag_offset_y; }; @@ -446,17 +460,48 @@ static void click_create(struct presentation *p, struct toolinfo *tip, static void click_select(struct presentation *p, struct toolinfo *tip, - double x, double y) + double x, double y, GdkEventButton *event, + enum drag_status *drag_status, + enum drag_reason *drag_reason) { int xp, yp; + double xo, yo; gboolean v; + struct text_toolinfo *ti = (struct text_toolinfo *)tip; struct text_object *o = (struct text_object *)p->editing_object; int idx, trail; assert(o->base.type == TEXT); - xp = (x - o->base.x + o->offs_x)*PANGO_SCALE; - yp = (y - o->base.y + o->offs_y)*PANGO_SCALE; + 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 = TEXT_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; + } + + xp = (xo + o->offs_x)*PANGO_SCALE; + yp = (yo + o->offs_y)*PANGO_SCALE; v = pango_layout_xy_to_index(o->layout, xp, yp, &idx, &trail); @@ -465,10 +510,37 @@ static void click_select(struct presentation *p, struct toolinfo *tip, } -static void drag_object(struct toolinfo *tip, struct presentation *p, - struct object *o, double x, double y) +static void drag(struct toolinfo *tip, struct presentation *p, + struct object *o, double x, double y) { - /* Do nothing */ + struct text_toolinfo *ti = (struct text_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 text_toolinfo *ti = (struct text_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_text((struct text_object *)o); + o->parent->object_seq++; + + ti->drag_reason = TEXT_DRAG_REASON_NONE; + redraw_overlay(p); } @@ -524,10 +596,33 @@ static int deselect_object(struct object *o, struct toolinfo *tip) static void draw_overlay(struct toolinfo *tip, cairo_t *cr, struct object *o) { + struct text_toolinfo *ti = (struct text_toolinfo *)tip; + if ( o != NULL ) { + draw_editing_box(cr, o->x, o->y, o->bb_width, o->bb_height); + + cairo_new_path(cr); + cairo_rectangle(cr, o->x+o->bb_width-20.0, + o->y+o->bb_height-20.0, 20.0, 20.0); + cairo_set_source_rgba(cr, 0.9, 0.9, 0.9, 0.2); + cairo_fill(cr); + draw_caret(cr, o); } + + if ( ti->drag_reason == TEXT_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); + + } + } @@ -572,7 +667,8 @@ struct toolinfo *initialise_text_tool(GtkWidget *w) ti->base.create_default = create_default; ti->base.select = select_object; ti->base.deselect = deselect_object; - ti->base.drag_object = drag_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; |