summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2013-08-17 12:51:08 +0100
committerMichael Drake <tlsa@netsurf-browser.org>2013-08-17 12:51:08 +0100
commit59ea55ef3d573decd77b281797e6c0a3add6f2e9 (patch)
treec0f4985eee6d57b6f34dd02beeb662dc3c6bb3aa
parentdee0cb03809c1db10faf6e3dc2afe29e5b8e5da6 (diff)
downloadnetsurf-59ea55ef3d573decd77b281797e6c0a3add6f2e9.tar.gz
netsurf-59ea55ef3d573decd77b281797e6c0a3add6f2e9.tar.bz2
Propagate selection to visible descendant nodes when a move drag is started with folder selected.
-rw-r--r--desktop/treeview.c78
1 files changed, 65 insertions, 13 deletions
diff --git a/desktop/treeview.c b/desktop/treeview.c
index bad15639b..b52c98a1a 100644
--- a/desktop/treeview.c
+++ b/desktop/treeview.c
@@ -1363,7 +1363,8 @@ struct treeview_selection_walk_data {
TREEVIEW_WALK_CLEAR_SELECTION,
TREEVIEW_WALK_SELECT_ALL,
TREEVIEW_WALK_COMMIT_SELECT_DRAG,
- TREEVIEW_WALK_DELETE_SELECTION
+ TREEVIEW_WALK_DELETE_SELECTION,
+ TREEVIEW_WALK_PROPAGATE_SELECTION
} purpose;
union {
bool has_selection;
@@ -1411,6 +1412,15 @@ static nserror treeview_node_selection_walk_cb(treeview_node *n,
}
break;
+ case TREEVIEW_WALK_PROPAGATE_SELECTION:
+ if (n->parent != NULL &&
+ n->parent->flags & TREE_NODE_SELECTED &&
+ !(n->flags & TREE_NODE_SELECTED)) {
+ n->flags ^= TREE_NODE_SELECTED;
+ changed = true;
+ }
+ break;
+
case TREEVIEW_WALK_CLEAR_SELECTION:
if (n->flags & TREE_NODE_SELECTED) {
n->flags ^= TREE_NODE_SELECTED;
@@ -1577,6 +1587,38 @@ static bool treeview_delete_selection(treeview *tree, struct rect *rect)
}
+/**
+ * Propagate selection to visible descendants of selected nodes.
+ *
+ * \param tree Treeview object to propagate selection in
+ * \param rect Redraw rectangle (if redraw required)
+ * \return true iff redraw required
+ */
+static bool treeview_propagate_selection(treeview *tree, struct rect *rect)
+{
+ struct treeview_selection_walk_data sw;
+
+ assert(tree != NULL);
+ assert(tree->root != NULL);
+
+ rect->x0 = 0;
+ rect->y0 = 0;
+ rect->x1 = REDRAW_MAX;
+ rect->y1 = 0;
+
+ sw.purpose = TREEVIEW_WALK_PROPAGATE_SELECTION;
+ sw.data.redraw.required = false;
+ sw.data.redraw.rect = rect;
+ sw.current_y = 0;
+ sw.tree = tree;
+
+ treeview_walk_internal(tree->root, false, NULL,
+ treeview_node_selection_walk_cb, &sw);
+
+ return sw.data.redraw.required;
+}
+
+
struct treeview_launch_walk_data {
int selected_depth;
treeview *tree;
@@ -1785,6 +1827,7 @@ static bool treeview_keyboard_navigation(treeview *tree, uint32_t key,
* Set the drag&drop drop indicator
*
* \param tree Treeview object to set node indicator in
+ * \param need_redraw True iff we already have a redraw region
* \param target The treeview node with mouse pointer over it
* \param node_height The height of node
* \param node_y The Y coord of the top of target node
@@ -1792,14 +1835,13 @@ static bool treeview_keyboard_navigation(treeview *tree, uint32_t key,
* \param rect Redraw rectangle (if redraw required)
* \return true iff redraw required
*/
-static bool treeview_set_move_indicator(treeview *tree,
+static bool treeview_set_move_indicator(treeview *tree, bool need_redraw,
treeview_node *target, int node_height,
int node_y, int mouse_y, struct rect *rect)
{
enum treeview_target_pos target_pos;
int mouse_pos = mouse_y - node_y;
int x;
- bool need_redraw;
assert(tree != NULL);
assert(tree->root != NULL);
@@ -1836,13 +1878,24 @@ static bool treeview_set_move_indicator(treeview *tree,
if (target_pos == tree->move.target_pos &&
target == tree->move.target) {
/* No change */
- return false;
+ return need_redraw;
}
if (tree->move.target_pos != TV_TARGET_NONE) {
/* Need to clear old indicator position */
- *rect = tree->move.target_area;
- need_redraw = true;
+ if (need_redraw) {
+ if (rect->x0 > tree->move.target_area.x0)
+ rect->x0 = tree->move.target_area.x0;
+ if (tree->move.target_area.x1 > rect->x1)
+ rect->x1 = tree->move.target_area.x1;
+ if (rect->y0 > tree->move.target_area.y0)
+ rect->y0 = tree->move.target_area.y0;
+ if (tree->move.target_area.y1 > rect->y1)
+ rect->y1 = tree->move.target_area.y1;
+ } else {
+ *rect = tree->move.target_area;
+ need_redraw = true;
+ }
}
if (target_pos == TV_TARGET_ABOVE) {
@@ -1868,12 +1921,10 @@ static bool treeview_set_move_indicator(treeview *tree,
if (target_pos != TV_TARGET_NONE) {
/* Need to draw new indicator position */
if (need_redraw) {
- if (rect->x0 != tree->move.target_area.x0) {
- if (rect->x0 > tree->move.target_area.x0)
- rect->x0 = tree->move.target_area.x0;
- if (tree->move.target_area.x1 > rect->x1)
- rect->x1 = tree->move.target_area.x1;
- }
+ if (rect->x0 > tree->move.target_area.x0)
+ rect->x0 = tree->move.target_area.x0;
+ if (tree->move.target_area.x1 > rect->x1)
+ rect->x1 = tree->move.target_area.x1;
if (rect->y0 > tree->move.target_area.y0)
rect->y0 = tree->move.target_area.y0;
if (tree->move.target_area.y1 > rect->y1)
@@ -2065,6 +2116,7 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
ma->tree->drag.type = TV_DRAG_MOVE;
ma->tree->cw_t->drag_status(ma->tree->cw_h,
CORE_WINDOW_DRAG_MOVE);
+ redraw |= treeview_propagate_selection(ma->tree, &r);
} else if (ma->mouse & BROWSER_MOUSE_DRAG_2) {
ma->tree->drag.type = TV_DRAG_SELECTION;
@@ -2100,7 +2152,7 @@ static nserror treeview_node_mouse_action_cb(treeview_node *node, void *ctx,
break;
case TV_DRAG_MOVE:
- redraw |= treeview_set_move_indicator(ma->tree,
+ redraw |= treeview_set_move_indicator(ma->tree, redraw,
node, height, ma->current_y, ma->y, &r);
break;