summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--desktop/treeview.c107
-rw-r--r--desktop/treeview.h19
2 files changed, 126 insertions, 0 deletions
diff --git a/desktop/treeview.c b/desktop/treeview.c
index bf2d0ef37..a0fbe9203 100644
--- a/desktop/treeview.c
+++ b/desktop/treeview.c
@@ -685,6 +685,37 @@ static inline treeview_node * treeview_node_next(treeview_node *node, bool full)
}
+/* Find node at given y-position
+ *
+ * \param tree Treeview object to delete node from
+ * \param target_y Target y-position
+ * \return node at y_target
+ */
+static treeview_node * treeview_y_node(treeview *tree, int target_y)
+{
+ treeview_node *n;
+ int y = 0;
+ int h;
+
+ assert(tree != NULL);
+ assert(tree->root != NULL);
+
+ n = treeview_node_next(tree->root, false);
+
+ while (n != NULL) {
+ h = (n->type == TREE_NODE_ENTRY) ?
+ n->height : tree_g.line_height;
+ if (target_y >= y && target_y < y + h)
+ return n;
+ y += h;
+
+ n = treeview_node_next(n, false);
+ }
+
+ return NULL;
+}
+
+
/* Find y position of the top of a node
*
* \param tree Treeview object to delete node from
@@ -1596,6 +1627,7 @@ void treeview_redraw(treeview *tree, int x, int y, struct rect *clip,
struct treeview_selection_walk_data {
enum {
TREEVIEW_WALK_HAS_SELECTION,
+ TREEVIEW_WALK_GET_FIRST_SELECTED,
TREEVIEW_WALK_CLEAR_SELECTION,
TREEVIEW_WALK_SELECT_ALL,
TREEVIEW_WALK_COMMIT_SELECT_DRAG,
@@ -1616,6 +1648,9 @@ struct treeview_selection_walk_data {
struct {
treeview_node *prev;
} yank;
+ struct {
+ treeview_node *n;
+ } first;
} data;
int current_y;
treeview *tree;
@@ -1641,6 +1676,14 @@ static nserror treeview_node_selection_walk_cb(treeview_node *n,
}
break;
+ case TREEVIEW_WALK_GET_FIRST_SELECTED:
+ if (n->flags & TREE_NODE_SELECTED) {
+ sw->data.first.n = n;
+ *end = true; /* Can abort tree walk */
+ return NSERROR_OK;
+ }
+ break;
+
case TREEVIEW_WALK_DELETE_SELECTION:
if (n->flags & TREE_NODE_SELECTED) {
err = treeview_delete_node_internal(sw->tree, n, true);
@@ -1744,6 +1787,26 @@ bool treeview_has_selection(treeview *tree)
}
+/**
+ * Get first selected node (in any)
+ *
+ * \param tree Treeview object in which to create folder
+ * \return the first selected treeview node, or NULL
+ */
+static treeview_node * treeview_get_first_selected(treeview *tree)
+{
+ struct treeview_selection_walk_data sw;
+
+ sw.purpose = TREEVIEW_WALK_GET_FIRST_SELECTED;
+ sw.data.first.n = NULL;
+
+ treeview_walk_internal(tree->root, false, NULL,
+ treeview_node_selection_walk_cb, &sw);
+
+ return sw.data.first.n;
+}
+
+
/* Exported interface, documented in treeview.h */
bool treeview_clear_selection(treeview *tree, struct rect *rect)
{
@@ -2060,6 +2123,50 @@ static nserror treeview_launch_selection(treeview *tree)
}
+/* Exported interface, documented in treeview.h */
+nserror treeview_get_relation(treeview *tree, treeview_node **relation,
+ enum treeview_relationship *rel, bool at_y, int y)
+{
+ treeview_node *n;
+
+ assert(tree != NULL);
+
+ if (at_y) {
+ n = treeview_y_node(tree, y);
+
+ } else {
+ n = treeview_get_first_selected(tree);
+ }
+
+ if (n != NULL && n->parent != NULL) {
+ if (n == n->parent->children) {
+ /* First child */
+ *relation = n->parent;
+ *rel = TREE_REL_FIRST_CHILD;
+ } else {
+ /* Not first child */
+ *relation = n->prev_sib;
+ *rel = TREE_REL_NEXT_SIBLING;
+ }
+ } else {
+ if (tree->root->children == NULL) {
+ /* First child of root */
+ *relation = tree->root;
+ *rel = TREE_REL_FIRST_CHILD;
+ } else {
+ /* Last child of root */
+ n = tree->root->children;
+ while (n->next_sib != NULL)
+ n = n->next_sib;
+ *relation = n;
+ *rel = TREE_REL_NEXT_SIBLING;
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+
struct treeview_nav_state {
treeview *tree;
treeview_node *prev;
diff --git a/desktop/treeview.h b/desktop/treeview.h
index 42dd4ca6b..ee2e82b42 100644
--- a/desktop/treeview.h
+++ b/desktop/treeview.h
@@ -153,6 +153,25 @@ nserror treeview_create(treeview **tree,
nserror treeview_destroy(treeview *tree);
/**
+ * Find a releation for node creation.
+ *
+ * \param tree Treeview object in which to create folder
+ * \param relation Existing node to insert as relation of, or NULL
+ * \param rel Folder's relationship to relation
+ * \param at_y Iff true, insert at y-offest
+ * \param y Y-offset in px from top of hotlist. Ignored if (!at_y).
+ * \return NSERROR_OK on success, appropriate error otherwise
+ *
+ * If at_y is set, we find a relation that will put the created node at that
+ * position.
+ *
+ * If at_y is unset, we find a relation that would put the node below the first
+ * selected node, or at the end of the treeview if no nodes selected.
+ */
+nserror treeview_get_relation(treeview *tree, treeview_node **relation,
+ enum treeview_relationship *rel, bool at_y, int y);
+
+/**
* Create a folder node in given treeview
*
* \param tree Treeview object in which to create folder