summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-07-31 15:27:58 +0200
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-07-31 15:27:58 +0200
commit1e7d369b182d10a50fda73038a539a78ed548013 (patch)
treef8774986119924370a44034233d326498855848d
parentcd6ccea2d6eed57e550c31565bc2e17d509c2e2b (diff)
mouse area selection
-rw-r--r--callbacks.c4
-rw-r--r--gtkplaylist.c152
-rw-r--r--gtkplaylist.h2
3 files changed, 137 insertions, 21 deletions
diff --git a/callbacks.c b/callbacks.c
index 969afadd..2e31817e 100644
--- a/callbacks.c
+++ b/callbacks.c
@@ -86,7 +86,7 @@ on_playlist_realize (GtkWidget *widget,
GtkTargetEntry entry = {
.target = "",
.flags = GTK_TARGET_SAME_WIDGET | GTK_TARGET_OTHER_APP,
- 1
+ 0
};
// setup drag-drop source
// gtk_drag_source_set (widget, GDK_BUTTON1_MASK, &entry, 1, GDK_ACTION_MOVE);
@@ -124,7 +124,7 @@ on_playlist_motion_notify_event (GtkWidget *widget,
GdkEventMotion *event,
gpointer user_data)
{
- gtkps_mousemove (event->state, event->x, event->y);
+ gtkps_mousemove (event);
return FALSE;
}
diff --git a/gtkplaylist.c b/gtkplaylist.c
index 45270c4d..f86f1d96 100644
--- a/gtkplaylist.c
+++ b/gtkplaylist.c
@@ -199,6 +199,48 @@ gtkps_expose (GtkWidget *widget, int x, int y, int w, int h) {
}
void
+gtkps_select_single (int sel) {
+ int idx=0;
+ GtkWidget *widget = lookup_widget (mainwin, "playlist");
+ for (playItem_t *it = playlist_head; it; it = it->next, idx++) {
+ if (idx == sel) {
+ if (!it->selected) {
+ it->selected = 1;
+ redraw_ps_row (widget, idx);
+ }
+ }
+ else if (it->selected) {
+ it->selected = 0;
+ redraw_ps_row (widget, idx);
+ }
+ }
+}
+
+// {{{ expected behaviour for mouse1 without modifiers:
+// {{{ [+] if clicked unselected item:
+// unselect all
+// select clicked item
+// playlist_row = clicked
+// redraw
+// start 'area selection' mode
+// }}}
+// {{{ [+] if clicked selected item:
+// playlist_row = clicked
+// redraw
+// wait until next release or motion event, whichever is 1st
+// if release is 1st:
+// unselect all except clicked, redraw
+// else if motion is 1st:
+// enter drag-drop mode
+// }}}
+// }}}
+int areaselect = 0;
+int areaselect_x = -1;
+int areaselect_y = -1;
+int areaselect_dx = -1;
+int areaselect_dy = -1;
+int dragwait = 0;
+void
gtkps_mouse1_pressed (int state, int ex, int ey, double time) {
// cursor must be set here, but selection must be handled in keyrelease
if (ps_getcount () == 0) {
@@ -240,23 +282,21 @@ gtkps_mouse1_pressed (int state, int ex, int ey, double time) {
// handle selection
if (!(state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)))
{
- // reset selection, and set it to single item
- int idx=0;
- for (playItem_t *it = playlist_head; it; it = it->next, idx++) {
- if (idx == sel) {
- if (!it->selected) {
- it->selected = 1;
-// if (idx != y && idx != playlist_row) {
- redraw_ps_row (widget, idx);
-// }
- }
- }
- else if (it->selected) {
- it->selected = 0;
-// if (idx != y && idx != playlist_row) {
- redraw_ps_row (widget, idx);
-// }
- }
+ playItem_t *it = ps_get_for_idx (sel);
+ if (!it || !it->selected) {
+ // reset selection, and set it to single item
+ gtkps_select_single (sel);
+ areaselect = 1;
+ areaselect_x = ex;
+ areaselect_y = ey;
+ areaselect_dx = -1;
+ areaselect_dy = -1;
+ shift_sel_anchor = playlist_row;
+ }
+ else {
+ dragwait = 1;
+ redraw_ps_row (widget, prev);
+ redraw_ps_row (widget, playlist_row);
}
}
else if (state & GDK_CONTROL_MASK) {
@@ -300,10 +340,86 @@ gtkps_mouse1_pressed (int state, int ex, int ey, double time) {
void
gtkps_mouse1_released (int state, int ex, int ey, double time) {
+ if (dragwait) {
+ dragwait = 0;
+ int y = ey/rowheight + scrollpos;
+ gtkps_select_single (y);
+ }
+ else if (areaselect) {
+ areaselect = 0;
+ }
+}
+
+void
+gtkps_draw_areasel (GtkWidget *widget, int x, int y) {
+ // erase previous rect using 4 blits from backbuffer
+ if (areaselect_dx != -1) {
+ int sx = min (areaselect_x, areaselect_dx);
+ int sy = min (areaselect_y, areaselect_dy);
+ int dx = max (areaselect_x, areaselect_dx);
+ int dy = max (areaselect_y, areaselect_dy);
+ int w = dx - sx + 1;
+ int h = dy - sy + 1;
+ //gdk_draw_drawable (widget->window, widget->style->black_gc, backbuf, sx, sy, sx, sy, dx - sx + 1, dy - sy + 1);
+ gdk_draw_drawable (widget->window, widget->style->black_gc, backbuf, sx, sy, sx, sy, w, 1);
+ gdk_draw_drawable (widget->window, widget->style->black_gc, backbuf, sx, sy, sx, sy, 1, h);
+ gdk_draw_drawable (widget->window, widget->style->black_gc, backbuf, sx, sy + h - 1, sx, sy + h - 1, w, 1);
+ gdk_draw_drawable (widget->window, widget->style->black_gc, backbuf, sx + w - 1, sy, sx + w - 1, sy, 1, h);
+ }
+ areaselect_dx = x;
+ areaselect_dy = y;
+ cairo_t *cr;
+ cr = gdk_cairo_create (widget->window);
+ if (!cr) {
+ return;
+ }
+ cairo_set_source_rgb (cr, 1.f, 1.f, 1.f);
+ cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
+ cairo_set_line_width (cr, 1);
+ int sx = min (areaselect_x, x);
+ int sy = min (areaselect_y, y);
+ int dx = max (areaselect_x, x);
+ int dy = max (areaselect_y, y);
+ cairo_rectangle (cr, sx, sy, dx-sx, dy-sy);
+ cairo_stroke (cr);
+ cairo_destroy (cr);
}
void
-gtkps_mousemove (int state, int x, int y) {
+gtkps_mousemove (GdkEventMotion *event) {
+ if (dragwait) {
+ dragwait = 0;
+ GtkWidget *widget = lookup_widget (mainwin, "playlist");
+ GtkTargetEntry entry = {
+ .target = "",
+ .flags = GTK_TARGET_SAME_WIDGET,
+ .info = 0
+ };
+ GtkTargetList *lst = gtk_target_list_new (&entry, 1);
+ gtk_drag_begin (widget, lst, GDK_ACTION_MOVE, 1, (GdkEvent *)event);
+ }
+ else if (areaselect) {
+ GtkWidget *widget = lookup_widget (mainwin, "playlist");
+ int y = event->y/rowheight + scrollpos;
+ if (y != shift_sel_anchor) {
+ int start = min (y, shift_sel_anchor);
+ int end = max (y, shift_sel_anchor);
+ int idx=0;
+ for (playItem_t *it = playlist_head; it; it = it->next, idx++) {
+ if (idx >= start && idx <= end) {
+ it->selected = 1;
+ redraw_ps_row (widget, idx);
+ }
+ else if (it->selected)
+ {
+ it->selected = 0;
+ redraw_ps_row (widget, idx);
+ }
+ }
+ }
+ // debug only
+ // gtkps_draw_areasel (widget, event->x, event->y);
+ }
}
void
diff --git a/gtkplaylist.h b/gtkplaylist.h
index 1b6b0d74..49a01c58 100644
--- a/gtkplaylist.h
+++ b/gtkplaylist.h
@@ -35,7 +35,7 @@ void
gtkps_mouse1_released (int state, int ex, int ey, double time);
void
-gtkps_mousemove (int state, int x, int y);
+gtkps_mousemove (GdkEventMotion *event);
void
gtkps_scroll (int newscroll);