Author: vince
Date: Mon Sep 27 19:04:32 2010
New Revision: 10852
URL:
http://source.netsurf-browser.org?rev=10852&view=rev
Log:
review comments and cleanup in tree.c
Modified:
branches/jmb/treeview-redux/desktop/tree.c
Modified: branches/jmb/treeview-redux/desktop/tree.c
URL:
http://source.netsurf-browser.org/branches/jmb/treeview-redux/desktop/tre...
==============================================================================
--- branches/jmb/treeview-redux/desktop/tree.c (original)
+++ branches/jmb/treeview-redux/desktop/tree.c Mon Sep 27 19:04:32 2010
@@ -144,61 +144,6 @@
callbacks */
};
-static void tree_delete_node_internal(struct tree *tree, struct node *node,
- bool siblings);
-static void tree_sort_insert(struct node *parent, struct node *node);
-static void tree_set_node_expanded_all(struct tree *tree, struct node *node,
- bool expanded);
-static bool tree_set_node_expanded_internal(struct tree *tree,
- struct node *node, bool expanded, bool folder, bool leaf);
-
-static void tree_draw_node(struct tree *tree, struct node *node,
- int tree_x, int tree_y,
- int clip_x, int clip_y, int clip_width, int clip_height);
-static void tree_draw_node_expansion(struct tree *tree, struct node *node,
- int tree_x, int tree_y);
-static void tree_draw_node_element(struct tree *tree,
- struct node_element *element, int tree_x, int tree_y);
-
-void tree_launch_selected_internal(struct tree *tree, struct node *node);
-
-static void tree_handle_node_changed(struct tree *tree, struct node *node,
- bool recalculate_sizes, bool expansion);
-static void tree_handle_node_element_changed(struct tree *tree,
- struct node_element *element);
-
-static void tree_recalculate_node_element(struct tree *tree,
- struct node_element *element);
-static void tree_recalculate_node_sizes(struct tree *tree, struct node *node,
- bool recalculate_sizes);
-static void tree_recalculate_node_positions(struct tree *tree,
- struct node *root);
-static void tree_recalculate_size(struct tree *tree);
-static int tree_get_node_width(struct node *node);
-static int tree_get_node_height(struct node *node);
-
-
-static void tree_handle_selection_area(struct tree *tree, int y, int height,
- bool invert);
-static void tree_handle_selection_area_node(struct tree *tree,
- struct node *node, int y, int height, bool invert);
-static struct node *tree_get_node_at(struct node *root, int x, int y,
- bool *furniture);
-static struct node_element *tree_get_node_element_at(struct node *node,
- int x, int y, bool *furniture);
-
-static void tree_move_selected_nodes(struct tree *tree,
- struct node *destination, bool before);
-static void tree_selected_to_processing(struct node *node);
-void tree_clear_processing(struct node *node);
-static struct node *tree_move_processing_node(struct tree *tree,
- struct node *node, struct node *link, bool before, bool first);
-
-static void tree_stop_edit(struct tree *tree, bool keep_changes);
-static nserror tree_icon_callback(hlcache_handle *handle,
- const hlcache_event *event, void *pw);
-static void tree_textarea_redraw_request(void *data, int x, int y,
- int width, int height);
/**
* Creates and initialises a new tree.
@@ -212,8 +157,7 @@
* \return the newly created tree, or NULL on memory exhaustion
*/
struct tree *tree_create(unsigned int flags,
- const struct treeview_table *callbacks,
- void *client_data)
+ const struct treeview_table *callbacks, void *client_data)
{
struct tree *tree;
char *title;
@@ -233,7 +177,7 @@
return NULL;
}
tree->root = tree_create_folder_node(NULL, NULL, title,
- false, false, false);
+ false, false, false);
if (tree->root == NULL) {
free(title);
free(tree);
@@ -255,6 +199,245 @@
return tree;
}
+
+/**
+ * Recalculates the dimensions of a node element.
+ *
+ * \param tree the tree to which the element belongs, may be NULL
+ * \param element the element to recalculate
+ */
+static void tree_recalculate_node_element(struct tree *tree,
+ struct node_element *element)
+{
+ struct bitmap *bitmap = NULL;
+ int width, height;
+
+ assert(element != NULL);
+
+ switch (element->type) {
+ case NODE_ELEMENT_TEXT_PLUS_ICON:
+ case NODE_ELEMENT_TEXT:
+ if(element->text == NULL)
+ break;
+
+ if (tree != NULL && element == tree->editing) {
+ textarea_get_dimensions(tree->textarea,
+ &element->box.width, NULL);
+ } else {
+ nsfont.font_width(&plot_fstyle,
+ element->text,
+ strlen(element->text),
+ &element->box.width);
+ }
+
+ element->box.width += 8;
+ element->box.height = TREE_TEXT_HEIGHT;
+
+ if (element->type == NODE_ELEMENT_TEXT_PLUS_ICON)
+ element->box.width += NODE_INSTEP;
+
+ break;
+
+ case NODE_ELEMENT_BITMAP:
+ bitmap = element->bitmap;
+ if (bitmap != NULL) {
+ width = bitmap_get_width(bitmap);
+ height = bitmap_get_height(bitmap);
+ element->box.width = width + 1;
+ element->box.height = height + 2;
+ } else {
+ element->box.width = 0;
+ element->box.height = 0;
+ }
+ break;
+ }
+}
+
+
+/**
+ * Calculates the height of a node including any children
+ *
+ * \param node the node to calculate the height of
+ * \return the total height of the node and children
+ */
+static int tree_get_node_height(struct node *node)
+{
+ int y1;
+
+ assert(node != NULL);
+
+ if ((node->child == NULL) || (node->expanded == false)) {
+ return node->box.height;
+ }
+
+ y1 = node->box.y;
+ if (y1 < 0) {
+ y1 = 0;
+ }
+ node = node->child;
+
+ while ((node->next != NULL) ||
+ ((node->child != NULL) && (node->expanded))) {
+ for (; node->next != NULL; node = node->next);
+
+ if ((node->child != NULL) && (node->expanded)) {
+ node = node->child;
+ }
+ }
+ return node->box.y + node->box.height - y1;
+}
+
+
+/**
+ * Calculates the width of a node including any children
+ *
+ * \param node the node to calculate the height of
+ * \return the total width of the node and children
+ */
+static int tree_get_node_width(struct node *node)
+{
+ int width = 0;
+ int child_width;
+
+ assert(node != NULL);
+
+ for (; node != NULL; node = node->next) {
+ if (width < (node->box.x + node->box.width)) {
+ width = node->box.x + node->box.width;
+ }
+
+ if ((node->child != NULL) && (node->expanded)) {
+ child_width = tree_get_node_width(node->child);
+ if (width < child_width) {
+ width = child_width;
+ }
+ }
+ }
+ return width;
+}
+
+
+/**
+ * Recalculates the position of a node, its siblings and children.
+ *
+ * \param tree the tree to which 'root' belongs
+ * \param root the root node to update from
+ */
+static void tree_recalculate_node_positions(struct tree *tree,
+ struct node *root)
+{
+ struct node *parent;
+ struct node *node;
+ struct node *child;
+ struct node_element *element;
+ int y;
+ bool has_icon;
+
+ for (node = root; node != NULL; node = node->next) {
+
+ parent = node->parent;
+
+ if (node->previous != NULL) {
+ node->box.x = node->previous->box.x;
+ node->box.y = node->previous->box.y +
+ tree_get_node_height(node->previous);
+ } else if (parent != NULL) {
+ node->box.x = parent->box.x + NODE_INSTEP;
+ node->box.y = parent->box.y +
+ parent->box.height;
+ for (child = parent->child; child != node;
+ child = child->next)
+ node->box.y += child->box.height;
+ } else {
+ node->box.x = tree->flags & TREE_NO_FURNITURE
+ ? -NODE_INSTEP + 4 : 0;
+ node->box.y = -20;
+ }
+
+ if (!node->expanded) {
+ node->data.box.x = node->box.x;
+ node->data.box.y = node->box.y;
+ continue;
+ }
+
+ if (node->folder) {
+ node->data.box.x = node->box.x;
+ node->data.box.y = node->box.y;
+ tree_recalculate_node_positions(tree, node->child);
+ } else {
+ y = node->box.y;
+ has_icon = false;
+ for (element = &node->data; element != NULL;
+ element = element->next)
+ if (element->type ==
+ NODE_ELEMENT_TEXT_PLUS_ICON) {
+ has_icon = true;
+ break;
+ }
+
+ for (element = &node->data; element != NULL;
+ element = element->next) {
+ element->box.x = node->box.x;
+ if (element->type !=
+ NODE_ELEMENT_TEXT_PLUS_ICON &&
+ has_icon)
+ element->box.x += NODE_INSTEP;
+ element->box.y = y;
+ y += element->box.height;
+ }
+ }
+
+ }
+}
+
+
+/**
+ * Recalculates the size of a node.
+ *
+ * \param tree the tree to which node belongs, may be NULL
+ * \param node the node to update
+ * \param recalculate_sizes whether the node elements have changed
+ */
+static void tree_recalculate_node_sizes(struct tree *tree, struct node *node,
+ bool recalculate_sizes)
+{
+ struct node_element *element;
+ int width, height;
+
+ assert(node != NULL);
+
+ width = node->box.width;
+ height = node->box.height;
+ node->box.width = 0;
+ node->box.height = 0;
+ if (node->expanded) {
+ for (element = &node->data; element != NULL;
+ element = element->next) {
+ if (recalculate_sizes)
+ tree_recalculate_node_element(tree, element);
+ node->box.width = (node->box.width > element->box.x +
+ element->box.width - node->box.x) ?
+ node->box.width :
+ element->box.width + element->box.x -
+ node->box.x;
+ node->box.height += element->box.height;
+ }
+ } else {
+ if (recalculate_sizes)
+ for (element = &node->data; element != NULL;
+ element = element->next)
+ tree_recalculate_node_element(tree, element);
+ else
+ tree_recalculate_node_element(tree, &node->data);
+ node->box.width = node->data.box.width;
+ node->box.height = node->data.box.height;
+ }
+
+ if (tree != NULL && height != node->box.height)
+ tree_recalculate_node_positions(tree, tree->root);
+}
+
+
/**
* Creates a folder node with the specified title, and optionally links it into
* the tree.
@@ -269,7 +452,7 @@
*/
struct node *tree_create_folder_node(struct tree *tree, struct node *parent,
const char *title, bool editable, bool retain_in_memory,
- bool deleted)
+ bool deleted)
{
struct node *node;
@@ -314,11 +497,11 @@
*/
struct node *tree_create_leaf_node(struct tree *tree, struct node *parent,
const char *title, bool editable, bool retain_in_memory,
- bool deleted)
+ bool deleted)
{
struct node *node;
- assert(title);
+ assert(title != NULL);
node = calloc(sizeof(struct node), 1);
if (node == NULL) {
@@ -326,6 +509,7 @@
warn_user("NoMemory", 0);
return NULL;
}
+
node->folder = false;
node->retain_in_memory = retain_in_memory;
node->deleted = deleted;
@@ -359,14 +543,131 @@
struct node_element *element;
element = calloc(sizeof(struct node_element), 1);
- if (element == NULL) return NULL;
+ if (element == NULL)
+ return NULL;
+
element->parent = parent;
element->flag = flag;
element->type = type;
element->editable = editable;
element->next = parent->data.next;
parent->data.next = element;
+
return element;
+}
+
+
+/**
+ * Inserts a node into the correct place according to the parent's sort function
+ *
+ * \param parent the node whose child node 'node' becomes
+ * \param node the node to be inserted
+ */
+static void tree_sort_insert(struct node *parent, struct node *node)
+{
+ struct node *after;
+
+ assert(node != NULL);
+ assert(parent != NULL);
+ assert(parent->sort != NULL);
+
+ after = parent->last_child;
+ while ((after != NULL) &&
+ (parent->sort(node, after) == -1))
+ after = after->previous;
+
+ if (after != NULL) {
+ if (after->next != NULL)
+ after->next->previous = node;
+ node->next = after->next;
+ node->previous = after;
+ after->next = node;
+ } else {
+ node->previous = NULL;
+ node->next = parent->child;
+ if (parent->child != NULL) {
+ parent->child->previous = node;
+ }
+ parent->child = node;
+ }
+
+ if (node->next == NULL)
+ parent->last_child = node;
+
+ node->parent = parent;
+}
+
+
+/**
+ * Recalculates the size of a tree.
+ *
+ * \param tree the tree to recalculate
+ */
+static void tree_recalculate_size(struct tree *tree)
+{
+ int width, height;
+
+ assert(tree != NULL);
+
+ width = tree->width;
+ height = tree->height;
+
+ tree->width = tree_get_node_width(tree->root);
+ tree->height = tree_get_node_height(tree->root);
+
+ if ((width != tree->width) || (height != tree->height))
+ tree->callbacks->resized(tree, tree->width, tree->height,
+ tree->client_data);
+}
+
+/**
+ * Recalculate the node data and redraw the relevant section of the tree.
+ *
+ * \param tree the tree to redraw, may be NULL
+ * \param node the node to update
+ * \param recalculate_sizes whether the elements have changed
+ * \param expansion the request is the result of a node expansion
+ */
+static void tree_handle_node_changed(struct tree *tree, struct node *node,
+ bool recalculate_sizes, bool expansion)
+{
+ int width, height, tree_height;
+
+ assert(node != NULL);
+
+ width = node->box.width;
+ height = node->box.height;
+ tree_height = tree->height;
+
+ if ((recalculate_sizes) || (expansion)) {
+ tree_recalculate_node_sizes(tree, node, true);
+ }
+
+ if (tree != NULL) {
+ if ((node->box.height != height) || (expansion)) {
+ tree_recalculate_node_positions(tree, tree->root);
+ tree_recalculate_size(tree);
+ tree_height = (tree_height > tree->height) ?
+ tree_height : tree->height;
+ if (tree->redraw) {
+ tree->callbacks->redraw_request(0, node->box.y,
+ tree->width,
+ tree_height - node->box.y,
+ tree->client_data);
+ }
+ } else {
+ width = (width > node->box.width) ?
+ width : node->box.width;
+ if (tree->redraw)
+ tree->callbacks->redraw_request(node->box.x,
+ node->box.y,
+ width, node->box.height,
+ tree->client_data);
+ if (recalculate_sizes) {
+ tree_recalculate_size(tree);
+ }
+ }
+ }
}
@@ -391,9 +692,9 @@
if ((link->folder == 0) || (before)) {
parent = node->parent = link->parent;
- if (parent->sort)
+ if (parent->sort) {
sort = true;
- else {
+ } else {
if (before) {
node->next = link;
node->previous = link->previous;
@@ -409,15 +710,15 @@
link->next->previous = node;
link->next = node;
if ((parent != NULL) &&
- (parent->last_child == link))
+ (parent->last_child == link))
parent->last_child = node;
}
}
} else {
parent = node->parent = link;
- if (parent->sort != NULL)
+ if (parent->sort != NULL) {
sort = true;
- else {
+ } else {
node->next = NULL;
if (link->child == NULL) {
link->child = link->last_child = node;
@@ -431,12 +732,144 @@
}
- if (sort)
+ if (sort) {
tree_sort_insert(parent, node);
+ }
tree_handle_node_changed(tree, link, false, true);
node->deleted = false;
+}
+
+
+/**
+ * Recalculate the node element and redraw the relevant section of the tree.
+ * The tree size is not updated.
+ *
+ * \param tree the tree to redraw, may be NULL
+ * \param element the node element to update
+ */
+static void tree_handle_node_element_changed(struct tree *tree,
+ struct node_element *element)
+{
+ int width, height;
+
+ assert(element != NULL);
+
+ width = element->box.width;
+ height = element->box.height;
+ tree_recalculate_node_element(tree, element);
+
+ if (element->box.height != height) {
+ tree_recalculate_node_sizes(tree, element->parent, false);
+ if ((tree != NULL) && (tree->redraw)) {
+ tree->callbacks->redraw_request(0, element->box.y,
+ tree->width + element->box.width -
+ width,
+ tree->height - element->box.y +
+ element->box.height - height,
+ tree->client_data);
+ }
+ } else {
+ if (element->box.width != width) {
+ tree_recalculate_node_sizes(tree, element->parent,
+ false);
+ }
+
+ if (tree != NULL) {
+ width = (width > element->box.width) ? width :
+ element->box.width;
+ if (tree->redraw) {
+ tree->callbacks->redraw_request(element->box.x,
+ element->box.y,
+ width,
+ element->box.height,
+ tree->client_data);
+ }
+ }
+ }
+}
+
+
+/**
+ * Stops editing a node_element
+ *
+ * \param tree The tree to stop editing for
+ * \param keep_changes If true the changes made to the text will be kept,
+ * if false they will be dropped
+ */
+static void tree_stop_edit(struct tree *tree, bool keep_changes)
+{
+ int text_len;
+ char *text = NULL;
+ struct node_element *element;
+ struct node_msg_data msg_data;
+ node_callback_resp response;
+
+ assert(tree != NULL);
+
+ if (tree->editing == NULL || tree->textarea == NULL)
+ return;
+
+ element = tree->editing;
+
+ if (keep_changes) {
+ text_len = textarea_get_text(tree->textarea, NULL, 0);
+ text = malloc(text_len * sizeof(char));
+ if (text == NULL) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ textarea_destroy(tree->textarea);
+ tree->textarea = NULL;
+ return;
+ }
+ textarea_get_text(tree->textarea, text, text_len);
+ }
+
+
+ if (keep_changes && element->parent->user_callback != NULL) {
+ msg_data.msg = NODE_ELEMENT_EDIT_FINISHING;
+ msg_data.flag = element->flag;
+ msg_data.node = element->parent;
+ msg_data.data.text = text;
+ response = element->parent->user_callback(
+ element->parent->callback_data,
+ &msg_data);
+
+ switch (response) {
+ case NODE_CALLBACK_REJECT:
+ free(text);
+ text = NULL;
+ break;
+ case NODE_CALLBACK_CONTINUE:
+ free(text);
+ text = NULL;
+ return;
+ case NODE_CALLBACK_HANDLED:
+ case NODE_CALLBACK_NOT_HANDLED:
+ text = msg_data.data.text;
+ break;
+ }
+ }
+
+ textarea_destroy(tree->textarea);
+ tree->textarea = NULL;
+ tree->editing = NULL;
+
+ if (text != NULL)
+ tree_update_node_element(tree, element, text, NULL);
+ else
+ tree_handle_node_element_changed(tree, element);
+
+
+ tree_recalculate_size(tree);
+ if (element->parent->user_callback != NULL) {
+ msg_data.msg = NODE_ELEMENT_EDIT_FINISHED;
+ msg_data.flag = element->flag;
+ msg_data.node = element->parent;
+ element->parent->user_callback(element->parent->callback_data,
+ &msg_data);
+ }
}
@@ -483,34 +916,6 @@
tree_handle_node_changed(tree, parent, false, true);
}
-/**
- * Deletes all nodes of a tree and the tree itself.
- *
- * \param tree the tree to be deleted
- */
-void tree_delete(struct tree *tree)
-{
- tree_set_redraw(tree, false);
- if (tree->root->child != NULL)
- tree_delete_node_internal(tree, tree->root->child, true);
-
- free((void *)tree->root->data.text);
- free(tree->root);
- free(tree);
-}
-
-
-/**
- * Gets the redraw property of the given tree.
- *
- * \param tree the tree for which to retrieve the property
- * \return the redraw property of the tree
- */
-bool tree_get_redraw(struct tree *tree)
-{
- return tree->redraw;
-}
-
/**
* Deletes a node from the tree.
@@ -519,26 +924,7 @@
* \param node the node to delete
* \param siblings whether to delete all siblings
*/
-void tree_delete_node(struct tree *tree, struct node *node, bool siblings)
-{
- int y = node->box.y;
- tree_delete_node_internal(tree, node, siblings);
- tree_recalculate_node_positions(tree, tree->root);
- if (tree->redraw)
- tree->callbacks->redraw_request(0, y, tree->width, tree->height,
- tree->client_data);
- tree_recalculate_size(tree);
-}
-
-
-/**
- * Deletes a node from the tree.
- *
- * \param tree the tree to delete from, may be NULL
- * \param node the node to delete
- * \param siblings whether to delete all siblings
- */
-void tree_delete_node_internal(struct tree *tree, struct node *node,
+static void tree_delete_node_internal(struct tree *tree, struct node *node,
bool siblings)
{
struct node *next, *child, *parent;
@@ -569,14 +955,14 @@
if (e->text != NULL) {
response = NODE_CALLBACK_NOT_HANDLED;
if (!e->editable &&
- node->user_callback != NULL) {
+ node->user_callback != NULL) {
msg_data.msg = NODE_DELETE_ELEMENT_TXT;
msg_data.flag = e->flag;
msg_data.node = node;
msg_data.data.text = (void *)e->text;
response = node->user_callback(
- node->callback_data,
- &msg_data);
+ node->callback_data,
+ &msg_data);
}
if (response != NODE_CALLBACK_HANDLED)
free((void *)e->text);
@@ -589,13 +975,13 @@
msg_data.flag = e->flag;
msg_data.node = node;
msg_data.data.bitmap =
- (void *)e->bitmap;
+ (void *)e->bitmap;
response = node->user_callback(
- node->callback_data,
- &msg_data);
+ node->callback_data,
+ &msg_data);
}
/* TODO the type of this field is platform
- dependent */
+ dependent */
if (response != NODE_CALLBACK_HANDLED)
free(e->bitmap);
e->bitmap = NULL;
@@ -610,8 +996,56 @@
if (siblings && next)
tree_delete_node_internal(tree, next, true);
if ((tree->flags & TREE_DELETE_EMPTY_DIRS) && parent != NULL &&
- parent->child == NULL && !parent->deleted)
+ parent->child == NULL && !parent->deleted)
tree_delete_node_internal(tree, parent, false);
+}
+
+
+/**
+ * Deletes all nodes of a tree and the tree itself.
+ *
+ * \param tree the tree to be deleted
+ */
+void tree_delete(struct tree *tree)
+{
+ tree_set_redraw(tree, false);
+ if (tree->root->child != NULL)
+ tree_delete_node_internal(tree, tree->root->child, true);
+
+ free((void *)tree->root->data.text);
+ free(tree->root);
+ free(tree);
+}
+
+
+/**
+ * Gets the redraw property of the given tree.
+ *
+ * \param tree the tree for which to retrieve the property
+ * \return the redraw property of the tree
+ */
+bool tree_get_redraw(struct tree *tree)
+{
+ return tree->redraw;
+}
+
+
+/**
+ * Deletes a node from the tree.
+ *
+ * \param tree the tree to delete from, may be NULL
+ * \param node the node to delete
+ * \param siblings whether to delete all siblings
+ */
+void tree_delete_node(struct tree *tree, struct node *node, bool siblings)
+{
+ int y = node->box.y;
+ tree_delete_node_internal(tree, node, siblings);
+ tree_recalculate_node_positions(tree, tree->root);
+ if (tree->redraw)
+ tree->callbacks->redraw_request(0, y, tree->width, tree->height,
+ tree->client_data);
+ tree_recalculate_size(tree);
}
@@ -620,63 +1054,13 @@
*
* \param tree The tree to which node belongs, may be NULL
* \param node The node for which the icon is set
- * \param icon the image to use
+ * \param icon the image to use
*/
void tree_set_node_icon(struct tree *tree, struct node *node,
hlcache_handle *icon)
{
node->data.type = NODE_ELEMENT_TEXT_PLUS_ICON;
tree_update_node_element(tree, &(node->data), NULL, icon);
-}
-
-/**
- * Update the text of a node element if it has changed.
- *
- * \param element The node element to update.
- * \param text The text to update the element with. The ownership of
- * this string is taken by this function and must not be
- * referred to after the function exits.
- */
-bool tree_update_element_text(struct tree *tree,
- struct node_element *element, char *text)
-{
- const char *node_text; /* existing node text */
-
- if (text == NULL)
- return false;
-
- if (element == NULL) {
- free(text);
- return false;
- }
-
- node_text = tree_node_element_get_text(element);
-
- if ((node_text == NULL) || (strcmp(node_text, text) != 0)) {
- tree_update_node_element(tree, element, text, NULL);
- } else {
- /* text does not need changing, free it */
- free(text);
- }
- return true;
-}
-
-
-/**
- * Updates [all siblings and descendants of] a node to an expansion state.
- *
- * \param tree the tree to update
- * \param node the node to set [all siblings and descendants of]
- * \param expanded the expansion state to set
- * \param folder whether to update folders, if this together with leaf
- * will be false only 'node' will be updated
- * \param leaf whether to update leaves (check also description for folder)
- */
-void tree_set_node_expanded(struct tree *tree, struct node *node, bool expanded,
- bool folder, bool leaf)
-{
- if (tree_set_node_expanded_internal(tree, node, expanded, folder, leaf))
- tree_handle_node_changed(tree, node, false, true);
}
@@ -688,7 +1072,7 @@
* \param node the node to set all siblings and descendants of
* \param expanded the expansion state to set
*/
-void tree_set_node_expanded_all(struct tree *tree, struct node *node,
+static void tree_set_node_expanded_all(struct tree *tree, struct node *node,
bool expanded)
{
for (; node != NULL; node = node->next) {
@@ -713,38 +1097,56 @@
* \param leaf whether to update leaves (check also description for folder)
* \return whether any changes were made
*/
-bool tree_set_node_expanded_internal(struct tree *tree, struct node *node,
- bool expanded, bool folder, bool leaf)
+static bool tree_set_node_expanded_internal(struct tree *tree,
+ struct node *node, bool expanded, bool folder, bool leaf)
{
bool redraw = false;
struct node *end = (folder == false && leaf == false) ?
- node->next : NULL;
+ node->next : NULL;
if (tree->editing != NULL && node == tree->editing->parent)
tree_stop_edit(tree, false);
for (; node != end; node = node->next) {
if ((node->expanded != expanded) && (node != tree->root) &&
- ((folder && (node->folder)) ||
- (leaf && (!node->folder)) ||
- (!folder && !leaf))) {
+ ((folder && (node->folder)) ||
+ (leaf && (!node->folder)) ||
+ (!folder && !leaf))) {
node->expanded = expanded;
if (node->child != NULL)
tree_set_node_expanded_all(tree,
- node->child, false);
+ node->child, false);
if ((node->data.next != NULL) &&
- (node->data.next->box.height == 0))
+ (node->data.next->box.height == 0))
tree_recalculate_node_sizes(tree, node, true);
else
tree_recalculate_node_sizes(tree, node, false);
redraw = true;
}
if ((folder || leaf) && (node->child != NULL) &&
- (node->expanded))
+ (node->expanded))
redraw |= tree_set_node_expanded_internal(tree,
- node->child, expanded, folder, leaf);
+ node->child, expanded, folder, leaf);
}
return redraw;
+}
+
+
+/**
+ * Updates [all siblings and descendants of] a node to an expansion state.
+ *
+ * \param tree the tree to update
+ * \param node the node to set [all siblings and descendants of]
+ * \param expanded the expansion state to set
+ * \param folder whether to update folders, if this together with leaf
+ * will be false only 'node' will be updated
+ * \param leaf whether to update leaves (check also description for folder)
+ */
+void tree_set_node_expanded(struct tree *tree, struct node *node, bool expanded,
+ bool folder, bool leaf)
+{
+ if (tree_set_node_expanded_internal(tree, node, expanded, folder, leaf))
+ tree_handle_node_changed(tree, node, false, true);
}
@@ -775,14 +1177,14 @@
node->selected = selected;
if (tree != NULL && tree->redraw)
tree->callbacks->redraw_request(node->box.x,
- node->box.y,
- node->box.width,
- node->data.box.height,
- tree->client_data);
+ node->box.y,
+ node->box.width,
+ node->data.box.height,
+ tree->client_data);
}
if (all && (node->child != NULL) && (node->expanded))
tree_set_node_selected(tree, node->child, all,
- selected);
+ selected);
}
}
@@ -821,6 +1223,7 @@
tree_recalculate_node_positions(tree, node->child);
}
+
/**
* Sets the delete callback for a node.
*
@@ -833,48 +1236,6 @@
{
node->user_callback = callback;
node->callback_data = data;
-}
-
-
-/**
- * Inserts a node into the correct place according to the parent's sort function
- *
- * \param parent the node whose child node 'node' becomes
- * \param node the node to be inserted
- */
-void tree_sort_insert(struct node *parent, struct node *node)
-{
- struct node *after;
-
- assert(node != NULL);
- assert(parent != NULL);
- assert(parent->sort != NULL);
-
- after = parent->last_child;
- while ((after != NULL) &&
- (parent->sort(node, after) == -1))
- after = after->previous;
-
- if (after != NULL) {
- if (after->next != NULL)
- after->next->previous = node;
- node->next = after->next;
- node->previous = after;
- after->next = node;
- } else {
- node->previous = NULL;
- node->next = parent->child;
- if (parent->child != NULL) {
- parent->child->previous = node;
- }
- parent->child = node;
- }
-
- if (node->next == NULL)
- parent->last_child = node;
-
- node->parent = parent;
-
}
@@ -907,7 +1268,7 @@
if (node->selected)
return true;
if ((node->child != NULL) && (node->expanded) &&
- (tree_node_has_selection(node->child)))
+ (tree_node_has_selection(node->child)))
return true;
}
return false;
@@ -935,6 +1296,39 @@
bool tree_node_is_folder(struct node *node)
{
return node->folder;
+}
+
+
+/**
+ * Update the text of a node element if it has changed.
+ *
+ * \param element The node element to update.
+ * \param text The text to update the element with. The ownership of
+ * this string is taken by this function and must not be
+ * referred to after the function exits.
+ */
+bool tree_update_element_text(struct tree *tree,
+ struct node_element *element, char *text)
+{
+ const char *node_text; /* existing node text */
+
+ if (text == NULL)
+ return false;
+
+ if (element == NULL) {
+ free(text);
+ return false;
+ }
+
+ node_text = tree_node_element_get_text(element);
+
+ if ((node_text == NULL) || (strcmp(node_text, text) != 0)) {
+ tree_update_node_element(tree, element, text, NULL);
+ } else {
+ /* text does not need changing, free it */
+ free(text);
+ }
+ return true;
}
@@ -958,19 +1352,19 @@
tree_stop_edit(tree, false);
if (text != NULL && (element->type == NODE_ELEMENT_TEXT ||
- element->type == NODE_ELEMENT_TEXT_PLUS_ICON)) {
+ element->type == NODE_ELEMENT_TEXT_PLUS_ICON)) {
if (element->text != NULL) {
response = NODE_CALLBACK_NOT_HANDLED;
if (!element->editable &&
- element->parent->user_callback !=
- NULL) {
+ element->parent->user_callback !=
+ NULL) {
msg_data.msg = NODE_DELETE_ELEMENT_TXT;
msg_data.flag = element->flag;
msg_data.node = element->parent;
msg_data.data.text = (void *)element->text;
response = element->parent->user_callback(
- element->parent->callback_data,
- &msg_data);
+ element->parent->callback_data,
+ &msg_data);
}
if (response != NODE_CALLBACK_HANDLED)
free((void *)element->text);
@@ -979,7 +1373,7 @@
}
if (bitmap != NULL && (element->type == NODE_ELEMENT_BITMAP ||
- element->type == NODE_ELEMENT_TEXT_PLUS_ICON)) {
+ element->type == NODE_ELEMENT_TEXT_PLUS_ICON)) {
if (element->bitmap != NULL) {
response = NODE_CALLBACK_NOT_HANDLED;
if (element->parent->user_callback != NULL) {
@@ -988,8 +1382,8 @@
msg_data.node = element->parent;
msg_data.data.bitmap = (void *)element->bitmap;
response = element->parent->user_callback(
- element->parent->callback_data,
- &msg_data);
+ element->parent->callback_data,
+ &msg_data);
}
if (response != NODE_CALLBACK_HANDLED)
free(element->bitmap);
@@ -1057,6 +1451,223 @@
struct node *tree_node_get_next(struct node *node)
{
return node->next;
+}
+
+
+/**
+ * Draws an elements expansion icon
+ *
+ * \param tree the tree to draw the expansion for
+ * \param element the element to draw the expansion for
+ * \param tree_x X coordinate of the tree
+ * \param tree_y Y coordinate of the tree
+ */
+static void tree_draw_node_expansion(struct tree *tree, struct node *node,
+ int tree_x, int tree_y)
+{
+ int x, y;
+
+ assert(tree != NULL);
+ assert(node != NULL);
+
+ if ((node->child != NULL) || (node->data.next != NULL)) {
+ x = tree_x + node->box.x - (NODE_INSTEP / 2) - 4;
+ y = tree_y + node->box.y - (TREE_TEXT_HEIGHT / 2) + 16;
+ plot.rectangle(x, y, x + 9, y + 9, plot_style_fill_white);
+ plot.rectangle(x , y, x + 8, y + 8,
+ plot_style_stroke_darkwbasec);
+ plot.line(x + 2, y + 4, x + 7, y + 4,
+ plot_style_stroke_darkwbasec);
+ if (!node->expanded)
+ plot.line(x + 4, y + 2, x + 4, y + 7,
+ plot_style_stroke_darkwbasec);
+
+ }
+
+}
+
+
+/**
+ * Draws an element, including any expansion icons
+ *
+ * \param tree the tree to draw an element for
+ * \param element the element to draw
+ * \param tree_x X coordinate of the tree
+ * \param tree_y Y coordinate of the tree
+ */
+static void tree_draw_node_element(struct tree *tree,
+ struct node_element *element, int tree_x, int tree_y)
+{
+
+ struct bitmap *bitmap = NULL;
+ int x, y, width;
+ bool selected = false;
+ hlcache_handle *icon;
+ plot_font_style_t *fstyle;
+
+ assert(tree != NULL);
+ assert(element != NULL);
+ assert(element->parent != NULL);
+
+ x = tree_x + element->box.x;
+ y = tree_y + element->box.y;
+ width = element->box.width;
+ if (&element->parent->data == element)
+ if (element->parent->selected)
+ selected = true;
+
+ switch (element->type) {
+ case NODE_ELEMENT_TEXT_PLUS_ICON:
+ icon = element->bitmap;
+ if (icon != NULL &&
+ (content_get_status(icon) ==
+ CONTENT_STATUS_READY ||
+ content_get_status(icon) ==
+ CONTENT_STATUS_DONE)) {
+ content_redraw(icon , x, y + 3,
+ TREE_ICON_SIZE, TREE_ICON_SIZE,
+ x, y, x + TREE_ICON_SIZE,
+ y + TREE_ICON_SIZE, 1, 0);
+ }
+
+ x += NODE_INSTEP;
+ width -= NODE_INSTEP;
+
+ /* fall through */
+ case NODE_ELEMENT_TEXT:
+ if (element->text == NULL)
+ break;
+
+ if (element == tree->editing)
+ return;
+
+ if (selected) {
+ fstyle = &plot_fstyle_selected;
+ plot.rectangle(x, y, x + width,
+ y + element->box.height,
+ plot_style_fill_black);
+ } else {
+ fstyle = &plot_fstyle;
+ plot.rectangle(x, y, x + width,
+ y + element->box.height,
+ plot_style_fill_white);
+ }
+
+ plot.text(x + 4, y + TREE_TEXT_HEIGHT * 0.75,
+ element->text, strlen(element->text),
+ fstyle);
+ break;
+ case NODE_ELEMENT_BITMAP:
+ bitmap = element->bitmap;
+ if (bitmap == NULL)
+ break;
+ plot.bitmap(x, y, element->box.width - 1,
+ element->box.height - 2,
+ bitmap, 0xFFFFFF, BITMAPF_NONE);
+ if (!(tree->flags & TREE_NO_FURNITURE))
+ plot.rectangle(x, y, x + element->box.width - 1,
+ y + element->box.height - 3,
+ plot_style_stroke_darkwbasec);
+
+ break;
+ }
+
+}
+
+
+/**
+ * Redraws a node.
+ *
+ * \param tree the tree to draw
+ * \param node the node to draw children and siblings of
+ * \param tree_x X coordinate of the tree
+ * \param tree_y Y coordinate of the tree
+ * \param clip_x the minimum x of the clipping rectangle
+ * \param clip_y the minimum y of the clipping rectangle
+ * \param clip_width the width of the clipping rectangle
+ * \param clip_height the height of the clipping rectangle
+ */
+static void tree_draw_node(struct tree *tree, struct node *node,
+ int tree_x, int tree_y,
+ int clip_x, int clip_y,
+ int clip_width, int clip_height)
+{
+ struct node_element *element;
+ struct node *parent;
+ int x_max, y_max;
+ int x0, y0, x1, y1;
+
+ assert(tree != NULL);
+ assert(node != NULL);
+
+
+ x_max = clip_x + clip_width + NODE_INSTEP;
+ y_max = clip_y + clip_height;
+
+ if ((node->parent->next != NULL) &&
+ (node->parent->next->box.y < clip_y))
+ return;
+
+ for (; node != NULL; node = node->next) {
+ if (node->box.y > y_max) return;
+ if ((node->next != NULL) &&
+ (!(tree->flags & TREE_NO_FURNITURE))) {
+ x0 = x1 = tree_x + node->box.x - (NODE_INSTEP / 2);
+ y0 = tree_y + node->box.y + (20 / 2);
+ y1 = y0 + node->next->box.y - node->box.y;
+ plot.line(x0, y0, x1, y1, plot_style_stroke_darkwbasec);
+ }
+ if ((node->box.x < x_max) && (node->box.y < y_max) &&
+ (node->box.x + node->box.width
+ + NODE_INSTEP >= clip_x) &&
+ (node->box.y + node->box.height >= clip_y)) {
+ if (!(tree->flags & TREE_NO_FURNITURE)) {
+ if ((node->expanded) && (node->child != NULL)) {
+ x0 = x1 = tree_x + node->box.x +
+ (NODE_INSTEP / 2);
+ y0 = tree_y + node->data.box.y
+ + node->data.box.height;
+ y1 = y0 + (20 / 2);
+ plot.line(x0, y0, x1, y1,
+ plot_style_stroke_darkwbasec);
+
+ }
+ parent = node->parent;
+ if ((parent != NULL) &&
+ (parent != tree->root) &&
+ (parent->child == node)) {
+ x0 = x1 = tree_x + parent->box.x +
+ (NODE_INSTEP / 2);
+ y0 = tree_y + parent->data.box.y +
+ parent->data.box.height;
+ y1 = y0 + (20 / 2);
+ plot.line(x0, y0, x1, y1,
+ plot_style_stroke_darkwbasec);
+ }
+ x0 = tree_x + node->box.x - (NODE_INSTEP / 2);
+ x1 = x0 + (NODE_INSTEP / 2) - 2;
+ y0 = y1 = tree_y + node->data.box.y +
+ node->data.box.height -
+ (20 / 2);
+ plot.line(x0, y0, x1, y1,
+ plot_style_stroke_darkwbasec);
+ tree_draw_node_expansion(tree, node,
+ tree_x, tree_y);
+ }
+ if (node->expanded)
+ for (element = &node->data; element != NULL;
+ element = element->next)
+ tree_draw_node_element(tree, element,
+ tree_x, tree_y);
+ else
+ tree_draw_node_element(tree, &node->data,
+ tree_x, tree_y);
+ }
+ if ((node->child != NULL) && (node->expanded))
+ tree_draw_node(tree, node->child, tree_x, tree_y,
+ clip_x, clip_y,
+ clip_width, clip_height);
+ }
}
@@ -1074,7 +1685,7 @@
* \param clip_height the height of the clipping rectangle
*/
void tree_draw(struct tree *tree, int x, int y,
- int clip_x, int clip_y, int clip_width, int clip_height)
+ int clip_x, int clip_y, int clip_width, int clip_height)
{
int absolute_x, absolute_y;
assert(tree != NULL);
@@ -1086,12 +1697,12 @@
absolute_x = x + clip_x;
absolute_y = y + clip_y;
plot.rectangle(absolute_x, absolute_y,
- absolute_x + clip_width, absolute_y + clip_height,
- plot_style_fill_white);
+ absolute_x + clip_width, absolute_y + clip_height,
+ plot_style_fill_white);
plot.clip(absolute_x, absolute_y,
- absolute_x + clip_width, absolute_y + clip_height);
+ absolute_x + clip_width, absolute_y + clip_height);
tree_draw_node(tree, tree->root->child, x, y, clip_x,
- clip_y, clip_width, clip_height);
+ clip_y, clip_width, clip_height);
if (tree->editing != NULL) {
x = x + tree->editing->box.x;
y = y + tree->editing->box.y;
@@ -1105,222 +1716,6 @@
/**
- * Redraws a node.
- *
- * \param tree the tree to draw
- * \param node the node to draw children and siblings of
- * \param tree_x X coordinate of the tree
- * \param tree_y Y coordinate of the tree
- * \param clip_x the minimum x of the clipping rectangle
- * \param clip_y the minimum y of the clipping rectangle
- * \param clip_width the width of the clipping rectangle
- * \param clip_height the height of the clipping rectangle
- */
-void tree_draw_node(struct tree *tree, struct node *node,
- int tree_x, int tree_y,
- int clip_x, int clip_y, int clip_width, int clip_height) {
-
- struct node_element *element;
- struct node *parent;
- int x_max, y_max;
- int x0, y0, x1, y1;
-
- assert(tree != NULL);
- assert(node != NULL);
-
-
- x_max = clip_x + clip_width + NODE_INSTEP;
- y_max = clip_y + clip_height;
-
- if ((node->parent->next != NULL) &&
- (node->parent->next->box.y < clip_y))
- return;
-
- for (; node != NULL; node = node->next) {
- if (node->box.y > y_max) return;
- if ((node->next != NULL) &&
- (!(tree->flags & TREE_NO_FURNITURE))) {
- x0 = x1 = tree_x + node->box.x - (NODE_INSTEP / 2);
- y0 = tree_y + node->box.y + (20 / 2);
- y1 = y0 + node->next->box.y - node->box.y;
- plot.line(x0, y0, x1, y1, plot_style_stroke_darkwbasec);
- }
- if ((node->box.x < x_max) && (node->box.y < y_max) &&
- (node->box.x + node->box.width
- + NODE_INSTEP >= clip_x) &&
- (node->box.y + node->box.height >= clip_y)) {
- if (!(tree->flags & TREE_NO_FURNITURE)) {
- if ((node->expanded) && (node->child != NULL)) {
- x0 = x1 = tree_x + node->box.x +
- (NODE_INSTEP / 2);
- y0 = tree_y + node->data.box.y
- + node->data.box.height;
- y1 = y0 + (20 / 2);
- plot.line(x0, y0, x1, y1,
- plot_style_stroke_darkwbasec);
-
- }
- parent = node->parent;
- if ((parent != NULL) &&
- (parent != tree->root) &&
- (parent->child == node)) {
- x0 = x1 = tree_x + parent->box.x +
- (NODE_INSTEP / 2);
- y0 = tree_y + parent->data.box.y +
- parent->data.box.height;
- y1 = y0 + (20 / 2);
- plot.line(x0, y0, x1, y1,
- plot_style_stroke_darkwbasec);
- }
- x0 = tree_x + node->box.x - (NODE_INSTEP / 2);
- x1 = x0 + (NODE_INSTEP / 2) - 2;
- y0 = y1 = tree_y + node->data.box.y +
- node->data.box.height -
- (20 / 2);
- plot.line(x0, y0, x1, y1,
- plot_style_stroke_darkwbasec);
- tree_draw_node_expansion(tree, node,
- tree_x, tree_y);
- }
- if (node->expanded)
- for (element = &node->data; element != NULL;
- element = element->next)
- tree_draw_node_element(tree, element,
- tree_x, tree_y);
- else
- tree_draw_node_element(tree, &node->data,
- tree_x, tree_y);
- }
- if ((node->child != NULL) && (node->expanded))
- tree_draw_node(tree, node->child, tree_x, tree_y,
- clip_x, clip_y,
- clip_width, clip_height);
- }
-}
-
-
-/**
- * Draws an elements expansion icon
- *
- * \param tree the tree to draw the expansion for
- * \param element the element to draw the expansion for
- * \param tree_x X coordinate of the tree
- * \param tree_y Y coordinate of the tree
- */
-void tree_draw_node_expansion(struct tree *tree, struct node *node,
- int tree_x, int tree_y)
-{
- int x, y;
-
- assert(tree != NULL);
- assert(node != NULL);
-
- if ((node->child != NULL) || (node->data.next != NULL)) {
- x = tree_x + node->box.x - (NODE_INSTEP / 2) - 4;
- y = tree_y + node->box.y - (TREE_TEXT_HEIGHT / 2) + 16;
- plot.rectangle(x, y, x + 9, y + 9, plot_style_fill_white);
- plot.rectangle(x , y, x + 8, y + 8,
- plot_style_stroke_darkwbasec);
- plot.line(x + 2, y + 4, x + 7, y + 4,
- plot_style_stroke_darkwbasec);
- if (!node->expanded)
- plot.line(x + 4, y + 2, x + 4, y + 7,
- plot_style_stroke_darkwbasec);
-
- }
-
-}
-
-
-/**
- * Draws an element, including any expansion icons
- *
- * \param tree the tree to draw an element for
- * \param element the element to draw
- * \param tree_x X coordinate of the tree
- * \param tree_y Y coordinate of the tree
- */
-void tree_draw_node_element(struct tree *tree, struct node_element *element,
- int tree_x, int tree_y)
-{
-
- struct bitmap *bitmap = NULL;
- int x, y, width;
- bool selected = false;
- hlcache_handle *icon;
- plot_font_style_t *fstyle;
-
- assert(tree != NULL);
- assert(element != NULL);
- assert(element->parent != NULL);
-
- x = tree_x + element->box.x;
- y = tree_y + element->box.y;
- width = element->box.width;
- if (&element->parent->data == element)
- if (element->parent->selected)
- selected = true;
-
- switch (element->type) {
- case NODE_ELEMENT_TEXT_PLUS_ICON:
- icon = element->bitmap;
- if (icon != NULL &&
- (content_get_status(icon) ==
- CONTENT_STATUS_READY ||
- content_get_status(icon) ==
- CONTENT_STATUS_DONE)) {
- content_redraw(icon , x, y + 3,
- TREE_ICON_SIZE, TREE_ICON_SIZE,
- x, y, x + TREE_ICON_SIZE,
- y + TREE_ICON_SIZE, 1, 0);
- }
-
- x += NODE_INSTEP;
- width -= NODE_INSTEP;
-
- /* fall through */
- case NODE_ELEMENT_TEXT:
- if (element->text == NULL)
- break;
-
- if (element == tree->editing)
- return;
-
- if (selected) {
- fstyle = &plot_fstyle_selected;
- plot.rectangle(x, y, x + width,
- y + element->box.height,
- plot_style_fill_black);
- } else {
- fstyle = &plot_fstyle;
- plot.rectangle(x, y, x + width,
- y + element->box.height,
- plot_style_fill_white);
- }
-
- plot.text(x + 4, y + TREE_TEXT_HEIGHT * 0.75,
- element->text, strlen(element->text),
- fstyle);
- break;
- case NODE_ELEMENT_BITMAP:
- bitmap = element->bitmap;
- if (bitmap == NULL)
- break;
- plot.bitmap(x, y, element->box.width - 1,
- element->box.height - 2,
- bitmap, 0xFFFFFF, BITMAPF_NONE);
- if (!(tree->flags & TREE_NO_FURNITURE))
- plot.rectangle(x, y, x + element->box.width - 1,
- y + element->box.height - 3,
- plot_style_stroke_darkwbasec);
-
- break;
- }
-
-}
-
-
-/**
* Finds a node element from a node with a specific user_type
*
* \param node the node to examine
@@ -1407,6 +1802,90 @@
/**
+ * Finds a node element at a specific location.
+ *
+ * \param node the root node to check from
+ * \param x the x co-ordinate
+ * \param y the y co-ordinate
+ * \param furniture whether the returned area was in an elements furniture
+ * \return the node at the specified position, or NULL for none
+ */
+static struct node_element *tree_get_node_element_at(struct node *node,
+ int x, int y, bool *furniture)
+{
+ struct node_element *element;
+ int x0, x1, y0, y1;
+
+ *furniture = false;
+ for (; node != NULL; node = node->next) {
+ if (node->box.y > y) return NULL;
+ if ((node->box.x - NODE_INSTEP < x) && (node->box.y < y)
&&
+ (node->box.x + node->box.width >= x) &&
+ (node->box.y + node->box.height >= y)) {
+ if (node->expanded) {
+ for (element = &node->data; element != NULL;
+ element = element->next) {
+ x0 = element->box.x;
+ y0 = element->box.y;
+ x1 = element->box.x +
+ element->box.width;
+ y1 = element->box.y +
+ element->box.height;
+ if ((x0 < x) && (y0 < y) && (x1 >= x)
+ && (y1 >= y))
+ return element;
+ }
+ } else {
+ x0 = node->data.box.x;
+ y0 = node->data.box.y;
+ x1 = node->data.box.x + node->data.box.width;
+ y1 = node->data.box.y + node->data.box.height;
+ if ((x0 < x) && (y0 < y) && (x1 >= x) &&
+ (y1>= y))
+ return &node->data;
+ }
+ if (((node->child != NULL) ||
+ (node->data.next != NULL)) &&
+ (node->data.box.x - NODE_INSTEP + 4 < x)
+ && (node->data.box.y + 4 < y) &&
+ (node->data.box.x > x) &&
+ (node->data.box.y + 20 > y)) {
+ *furniture = true;
+ return &node->data;
+ }
+ }
+
+ element = tree_get_node_element_at(node->child, x, y,
+ furniture);
+ if ((node->child != NULL) && (node->expanded) &&
+ (element != NULL))
+ return element;
+ }
+ return NULL;
+}
+
+
+/**
+ * Finds a node at a specific location.
+ *
+ * \param root the root node to check from
+ * \param x the x co-ordinate
+ * \param y the y co-ordinate
+ * \param furniture whether the returned area was in an elements furniture
+ * \return the node at the specified position, or NULL for none
+ */
+static struct node *tree_get_node_at(struct node *root, int x, int y,
+ bool *furniture)
+{
+ struct node_element *result;
+
+ if ((result = tree_get_node_element_at(root, x, y, furniture)))
+ return result->parent;
+ return NULL;
+}
+
+
+/**
* Gets link characteristics to insert a node at a specified position.
*
* \param tree the tree to find link information for
@@ -1433,7 +1912,7 @@
if (y < (node->box.y + (node->box.height / 2))) {
*before = true;
} else if ((node->folder) && (node->expanded) &&
- (node->child != NULL)) {
+ (node->child != NULL)) {
node = node->child;
*before = true;
}
@@ -1445,21 +1924,9 @@
* Launches all the selected nodes of the tree
*
* \param tree the tree for which all nodes will be launched
- */
-void tree_launch_selected(struct tree *tree)
-{
- if (tree->root->child != NULL)
- tree_launch_selected_internal(tree, tree->root->child);
-}
-
-
-/**
- * Launches all the selected nodes of the tree
- *
- * \param tree the tree for which all nodes will be launched
* \param node the node which will be checked together with its children
*/
-void tree_launch_selected_internal(struct tree *tree, struct node *node)
+static void tree_launch_selected_internal(struct tree *tree, struct node *node)
{
struct node_msg_data msg_data;
@@ -1473,6 +1940,18 @@
if (node->child != NULL)
tree_launch_selected_internal(tree, node->child);
}
+}
+
+
+/**
+ * Launches all the selected nodes of the tree
+ *
+ * \param tree the tree for which all nodes will be launched
+ */
+void tree_launch_selected(struct tree *tree)
+{
+ if (tree->root->child != NULL)
+ tree_launch_selected_internal(tree, tree->root->child);
}
@@ -1514,11 +1993,11 @@
y1 = tree->editing->box.y + tree->editing->box.height;
if (tree->textarea_drag_start &&
- (mouse & (BROWSER_MOUSE_HOLDING_1 |
- BROWSER_MOUSE_HOLDING_2))) {
+ (mouse & (BROWSER_MOUSE_HOLDING_1 |
+ BROWSER_MOUSE_HOLDING_2))) {
textarea_mouse_action(tree->textarea, mouse,
- x - x0, y - y0);
+ x - x0, y - y0);
return true;
}
@@ -1527,12 +2006,12 @@
if ((x >= x0) && (x < x1) && (y >= y0) && (y < y1))
{
if (mouse & (BROWSER_MOUSE_DRAG_1 |
- BROWSER_MOUSE_DRAG_2))
+ BROWSER_MOUSE_DRAG_2))
tree->textarea_drag_start = true;
else
tree->textarea_drag_start = false;
textarea_mouse_action(tree->textarea, mouse,
- x - x0, y - y0);
+ x - x0, y - y0);
return true;
}
@@ -1542,7 +2021,7 @@
/* we are not interested in the drag path or in mouse presses, return */
if (mouse & (BROWSER_MOUSE_HOLDING_1 | BROWSER_MOUSE_HOLDING_2 |
- BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2))
+ BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_PRESS_2))
return true;
/* cancel edit */
@@ -1555,12 +2034,12 @@
if (element == NULL) {
if (tree->flags & TREE_SINGLE_SELECT) {
tree_set_node_selected(tree, tree->root->child, true,
- false);
+ false);
return true;
}
if (mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_DRAG_1))
tree_set_node_selected(tree, tree->root->child, true,
- false);
+ false);
if (mouse & (BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2)) {
/** @todo the tree window has to scroll the tree when
@@ -1577,24 +2056,24 @@
/* click on furniture or double click on folder toggles node expansion
*/
if (((furniture) && (mouse & (BROWSER_MOUSE_CLICK_1 |
- BROWSER_MOUSE_CLICK_2))) ||
- ((!furniture) && (node->child != NULL) &&
- (mouse & BROWSER_MOUSE_DOUBLE_CLICK))) {
+ BROWSER_MOUSE_CLICK_2))) ||
+ ((!furniture) && (node->child != NULL) &&
+ (mouse & BROWSER_MOUSE_DOUBLE_CLICK))) {
/* clear any selection */
tree_set_node_selected(tree, tree->root->child, true, false);
/* expand / contract node and redraw */
tree_set_node_expanded(tree, node, !node->expanded,
- false, false);
+ false, false);
/* find the last child node if expanded */
last = node;
if ((last->child != NULL) && (last->expanded)) {
last = last->child;
while ((last->next != NULL) ||
- ((last->child != NULL) &&
- (last->expanded))) {
+ ((last->child != NULL) &&
+ (last->expanded))) {
if (last->next != NULL)
last = last->next;
else
@@ -1606,11 +2085,11 @@
if (last->expanded)
for (; element->next != NULL; element = element->next);
tree->callbacks->scroll_visible(element->box.y,
- element->box.height,
- tree->client_data);
+ element->box.height,
+ tree->client_data);
tree->callbacks->scroll_visible(node->data.box.y,
- node->data.box.height,
- tree->client_data);
+ node->data.box.height,
+ tree->client_data);
return true;
}
@@ -1620,12 +2099,12 @@
/* single/double ctrl+click or alt+click starts editing */
if ((element->editable) && (!tree->editing) &&
- ((element->type == NODE_ELEMENT_TEXT) ||
- (element->type == NODE_ELEMENT_TEXT_PLUS_ICON)) &&
- (mouse & (BROWSER_MOUSE_CLICK_1 |
- BROWSER_MOUSE_DOUBLE_CLICK)) &&
- (mouse & BROWSER_MOUSE_MOD_2 ||
- mouse & BROWSER_MOUSE_MOD_3)) {
+ ((element->type == NODE_ELEMENT_TEXT) ||
+ (element->type == NODE_ELEMENT_TEXT_PLUS_ICON)) &&
+ (mouse & (BROWSER_MOUSE_CLICK_1 |
+ BROWSER_MOUSE_DOUBLE_CLICK)) &&
+ (mouse & BROWSER_MOUSE_MOD_2 ||
+ mouse & BROWSER_MOUSE_MOD_3)) {
tree_set_node_selected(tree, tree->root->child, true, false);
tree_start_edit(tree, element);
return true;
@@ -1639,7 +2118,7 @@
msg_data.flag = TREE_ELEMENT_TITLE;
msg_data.node = node;
if (node->user_callback(node->callback_data, &msg_data) !=
- NODE_CALLBACK_HANDLED)
+ NODE_CALLBACK_HANDLED)
return false;
return true;
@@ -1647,12 +2126,12 @@
/* single click (select) cancels current selection and selects item */
if (mouse & BROWSER_MOUSE_CLICK_1 || (mouse & BROWSER_MOUSE_CLICK_2 &&
- tree->flags & TREE_SINGLE_SELECT)) {
+ tree->flags & TREE_SINGLE_SELECT)) {
if (tree->flags & TREE_NO_SELECT)
return true;
if (!node->selected) {
tree_set_node_selected(tree, tree->root->child, true,
- false);
+ false);
node->selected = true;
tree_handle_node_element_changed(tree, &node->data);
}
@@ -1670,13 +2149,13 @@
/* drag starts a drag operation */
if ((!tree->editing) && (mouse & (BROWSER_MOUSE_DRAG_1 |
- BROWSER_MOUSE_DRAG_2))) {
+ BROWSER_MOUSE_DRAG_2))) {
if (tree->flags & TREE_NO_DRAGS)
return true;
if (!node->selected) {
tree_set_node_selected(tree, tree->root->child, true,
- false);
+ false);
node->selected = true;
tree_handle_node_element_changed(tree, &node->data);
}
@@ -1688,457 +2167,6 @@
return false;
-}
-
-
-/**
- * Handle the end of a drag operation
- *
- * \param tree the tree on which the drag was performed
- * \param mouse mouse state during drag end
- * \param x0 x coordinate of drag start
- * \param y0 y coordinate of drag start
- * \param x1 x coordinate of drag end
- * \param y1 y coordinate of drag end
- */
-void tree_drag_end(struct tree *tree, browser_mouse_state mouse, int x0, int y0,
- int x1, int y1)
-{
-
- bool before;
- struct node *node;
- int x, y;
-
- if (tree->textarea_drag_start) {
- x = tree->editing->box.x;
- y = tree->editing->box.y;
- if (tree->editing->type == NODE_ELEMENT_TEXT_PLUS_ICON)
- x += NODE_INSTEP;
- textarea_drag_end(tree->textarea, mouse, x1 - x, y1 - y);
- }
-
- tree->textarea_drag_start = false;
-
- switch (tree->drag) {
- case TREE_NO_DRAG:
- break;
- case TREE_SELECT_DRAG:
- tree_handle_selection_area(tree, y0, y1 - y0,
- (mouse | BROWSER_MOUSE_HOLDING_2));
- break;
- case TREE_MOVE_DRAG:
- if (!(tree->flags & TREE_MOVABLE))
- return;
- node = tree_get_link_details(tree, x1, y1, &before);
- tree_move_selected_nodes(tree, node, before);
- break;
- }
-
- tree->drag = TREE_NO_DRAG;
-}
-
-
-/**
- * Key press handling for a tree.
- *
- * \param tree The tree which got the keypress
- * \param key The ucs4 character codepoint
- * \return true if the keypress is dealt with, false otherwise.
- */
-bool tree_keypress(struct tree *tree, uint32_t key)
-{
-
- if (tree->editing != NULL)
- switch (key) {
- case KEY_ESCAPE:
- tree_stop_edit(tree, false);
- return true;
- case KEY_NL:
- tree_stop_edit(tree, true);
- return true;
- default:
- return textarea_keypress(tree->textarea, key);
- }
-
- return false;
-}
-
-
-/**
- * Alphabetical comparison function for nodes
- *
- * \param n1 first node to compare
- * \param n2 first node to compare
- * \return 0 if equal, greater then zero if n1 > n2,
- * less then zero if n2 < n1
- */
-int tree_alphabetical_sort(struct node *n1, struct node *n2)
-{
- return strcmp(n1->data.text, n2->data.text);
-}
-
-
-/**
- * Recalculate the node data and redraw the relevant section of the tree.
- *
- * \param tree the tree to redraw, may be NULL
- * \param node the node to update
- * \param recalculate_sizes whether the elements have changed
- * \param expansion the request is the result of a node expansion
- */
-void tree_handle_node_changed(struct tree *tree, struct node *node,
- bool recalculate_sizes, bool expansion)
-{
- int width, height, tree_height;
-
- assert(node != NULL);
-
- width = node->box.width;
- height = node->box.height;
- tree_height = tree->height;
- if ((recalculate_sizes) || (expansion))
- tree_recalculate_node_sizes(tree, node, true);
- if (tree != NULL) {
- if ((node->box.height != height) || (expansion)) {
- tree_recalculate_node_positions(tree, tree->root);
- tree_recalculate_size(tree);
- tree_height = (tree_height > tree->height) ?
- tree_height : tree->height;
- if (tree->redraw)
- tree->callbacks->redraw_request(0, node->box.y,
- tree->width,
- tree_height - node->box.y,
- tree->client_data);
- } else {
- width = (width > node->box.width) ?
- width : node->box.width;
- if (tree->redraw)
- tree->callbacks->redraw_request(node->box.x,
- node->box.y,
- width, node->box.height,
- tree->client_data);
- if (recalculate_sizes)
- tree_recalculate_size(tree);
- }
- }
-}
-
-
-/**
- * Recalculate the node element and redraw the relevant section of the tree.
- * The tree size is not updated.
- *
- * \param tree the tree to redraw, may be NULL
- * \param element the node element to update
- */
-void tree_handle_node_element_changed(struct tree *tree,
- struct node_element *element)
-{
- int width, height;
-
- assert(element != NULL);
-
- width = element->box.width;
- height = element->box.height;
- tree_recalculate_node_element(tree, element);
-
- if (element->box.height != height) {
- tree_recalculate_node_sizes(tree, element->parent, false);
- if (tree != NULL && tree->redraw)
- tree->callbacks->redraw_request(0, element->box.y,
- tree->width + element->box.width -
- width,
- tree->height - element->box.y +
- element->box.height - height,
- tree->client_data);
- } else {
- if (element->box.width != width)
- tree_recalculate_node_sizes(tree, element->parent,
- false);
- if (tree != NULL) {
- width = (width > element->box.width) ? width :
- element->box.width;
- if (tree->redraw)
- tree->callbacks->redraw_request(element->box.x,
- element->box.y,
- width, element->box.height,
- tree->client_data);
- }
- }
-}
-
-
-/**
- * Recalculates the dimensions of a node element.
- *
- * \param tree the tree to which the element belongs, may be NULL
- * \param element the element to recalculate
- */
-void tree_recalculate_node_element(struct tree *tree,
- struct node_element *element)
-{
- struct bitmap *bitmap = NULL;
- int width, height;
-
- assert(element != NULL);
-
- switch (element->type) {
- case NODE_ELEMENT_TEXT_PLUS_ICON:
- case NODE_ELEMENT_TEXT:
- if(element->text == NULL)
- break;
- if (tree != NULL && element == tree->editing)
- textarea_get_dimensions(tree->textarea,
- &element->box.width, NULL);
- else
- nsfont.font_width(&plot_fstyle,
- element->text,
- strlen(element->text),
- &element->box.width);
- element->box.width += 8;
- element->box.height = TREE_TEXT_HEIGHT;
- if (element->type == NODE_ELEMENT_TEXT_PLUS_ICON)
- element->box.width += NODE_INSTEP;
- break;
- case NODE_ELEMENT_BITMAP:
- bitmap = element->bitmap;
- if (bitmap != NULL) {
- width = bitmap_get_width(bitmap);
- height = bitmap_get_height(bitmap);
- element->box.width = width + 1;
- element->box.height = height + 2;
- } else {
- element->box.width = 0;
- element->box.height = 0;
- }
- break;
- }
-}
-
-
-/**
- * Recalculates the size of a node.
- *
- * \param tree the tree to which node belongs, may be NULL
- * \param node the node to update
- * \param recalculate_sizes whether the node elements have changed
- */
-void tree_recalculate_node_sizes(struct tree *tree, struct node *node,
- bool recalculate_sizes)
-{
- struct node_element *element;
- int width, height;
-
- assert(node != NULL);
-
- width = node->box.width;
- height = node->box.height;
- node->box.width = 0;
- node->box.height = 0;
- if (node->expanded) {
- for (element = &node->data; element != NULL;
- element = element->next) {
- if (recalculate_sizes)
- tree_recalculate_node_element(tree, element);
- node->box.width = (node->box.width > element->box.x +
- element->box.width - node->box.x) ?
- node->box.width :
- element->box.width + element->box.x -
- node->box.x;
- node->box.height += element->box.height;
- }
- } else {
- if (recalculate_sizes)
- for (element = &node->data; element != NULL;
- element = element->next)
- tree_recalculate_node_element(tree, element);
- else
- tree_recalculate_node_element(tree, &node->data);
- node->box.width = node->data.box.width;
- node->box.height = node->data.box.height;
- }
-
- if (tree != NULL && height != node->box.height)
- tree_recalculate_node_positions(tree, tree->root);
-}
-
-
-/**
- * Recalculates the position of a node, its siblings and children.
- *
- * \param tree the tree to which 'root' belongs
- * \param root the root node to update from
- */
-void tree_recalculate_node_positions(struct tree *tree, struct node *root)
-{
- struct node *parent;
- struct node *node;
- struct node *child;
- struct node_element *element;
- int y;
- bool has_icon;
-
- for (node = root; node != NULL; node = node->next) {
-
- parent = node->parent;
-
- if (node->previous != NULL) {
- node->box.x = node->previous->box.x;
- node->box.y = node->previous->box.y +
- tree_get_node_height(node->previous);
- } else if (parent != NULL) {
- node->box.x = parent->box.x + NODE_INSTEP;
- node->box.y = parent->box.y +
- parent->box.height;
- for (child = parent->child; child != node;
- child = child->next)
- node->box.y += child->box.height;
- } else {
- node->box.x = tree->flags & TREE_NO_FURNITURE
- ? -NODE_INSTEP + 4 : 0;
- node->box.y = -20;
- }
-
- if (!node->expanded) {
- node->data.box.x = node->box.x;
- node->data.box.y = node->box.y;
- continue;
- }
-
- if (node->folder) {
- node->data.box.x = node->box.x;
- node->data.box.y = node->box.y;
- tree_recalculate_node_positions(tree,
- node->child);
- } else {
- y = node->box.y;
- has_icon = false;
- for (element = &node->data; element != NULL;
- element = element->next)
- if (element->type ==
- NODE_ELEMENT_TEXT_PLUS_ICON) {
- has_icon = true;
- break;
- }
-
- for (element = &node->data; element != NULL;
- element = element->next) {
- element->box.x = node->box.x;
- if (element->type !=
- NODE_ELEMENT_TEXT_PLUS_ICON &&
- has_icon)
- element->box.x += NODE_INSTEP;
- element->box.y = y;
- y += element->box.height;
- }
- }
-
- }
-}
-
-
-/**
- * Recalculates the size of a tree.
- *
- * \param tree the tree to recalculate
- */
-void tree_recalculate_size(struct tree *tree)
-{
- int width, height;
-
- assert(tree != NULL);
-
-
- width = tree->width;
- height = tree->height;
-
- tree->width = tree_get_node_width(tree->root);
- tree->height = tree_get_node_height(tree->root);
-
- if ((width != tree->width) || (height != tree->height))
- tree->callbacks->resized(tree, tree->width, tree->height,
- tree->client_data);
-}
-
-
-/**
- * Calculates the width of a node including any children
- *
- * \param node the node to calculate the height of
- * \return the total width of the node and children
- */
-int tree_get_node_width(struct node *node)
-{
- int width = 0;
- int child_width;
-
- assert(node != NULL);
-
- for (; node != NULL; node = node->next) {
- if (width < (node->box.x + node->box.width))
- width = node->box.x + node->box.width;
- if ((node->child != NULL) && (node->expanded)) {
- child_width = tree_get_node_width(node->child);
- if (width < child_width)
- width = child_width;
- }
- }
- return width;
-}
-
-
-/**
- * Calculates the height of a node including any children
- *
- * \param node the node to calculate the height of
- * \return the total height of the node and children
- */
-int tree_get_node_height(struct node *node) {
- int y1;
-
- assert(node != NULL);
-
- if ((node->child != NULL) && (node->expanded)) {
- y1 = node->box.y;
- if (y1 < 0)
- y1 = 0;
- node = node->child;
- while ((node->next != NULL) || ((node->child != NULL) &&
- (node->expanded))) {
- for (; node->next != NULL; node = node->next);
- if ((node->child != NULL) && (node->expanded))
- node = node->child;
- }
- return node->box.y + node->box.height - y1;
- } else {
- return node->box.height;
- }
-}
-
-
-/**
- * Updates the selected state for a region of nodes.
- *
- * \param tree the tree to update
- * \param y the minimum y of the selection rectangle
- * \param height the height of the selection rectangle
- * \param invert whether to invert the selected state
- */
-void tree_handle_selection_area(struct tree *tree, int y, int height,
- bool invert)
-{
- assert(tree != NULL);
- assert(tree->root != NULL);
-
- if (tree->root->child == NULL)
- return;
-
- if (height < 0) {
- y += height;
- height = -height;
- }
- tree_handle_selection_area_node(tree, tree->root->child, y, height,
- invert);
}
@@ -2151,10 +2179,9 @@
* \param height the height of the selection rectangle
* \param invert whether to invert the selected state
*/
-void tree_handle_selection_area_node(struct tree *tree, struct node *node,
- int y, int height, bool invert)
-{
-
+static void tree_handle_selection_area_node(struct tree *tree,
+ struct node *node, int y, int height, bool invert)
+{
struct node_element *element;
struct node *update;
int y_max;
@@ -2173,10 +2200,10 @@
update = NULL;
if (node->expanded) {
for (element = &node->data; element != NULL;
- element = element->next) {
+ element = element->next) {
y0 = element->box.y;
y1 = element->box.y +
- element->box.height;
+ element->box.height;
if ((y0 < y_max) && (y1 >= y)) {
update = element->parent;
break;
@@ -2202,137 +2229,49 @@
}
if ((node->child != NULL) && (node->expanded))
tree_handle_selection_area_node(tree, node->child, y,
- height, invert);
- }
-}
-
-
-/**
- * Finds a node at a specific location.
- *
- * \param root the root node to check from
- * \param x the x co-ordinate
- * \param y the y co-ordinate
- * \param furniture whether the returned area was in an elements furniture
- * \return the node at the specified position, or NULL for none
- */
-struct node *tree_get_node_at(struct node *root, int x, int y, bool *furniture)
-{
- struct node_element *result;
-
- if ((result = tree_get_node_element_at(root, x, y, furniture)))
- return result->parent;
- return NULL;
-}
-
-
-/**
- * Finds a node element at a specific location.
- *
- * \param node the root node to check from
- * \param x the x co-ordinate
- * \param y the y co-ordinate
- * \param furniture whether the returned area was in an elements furniture
- * \return the node at the specified position, or NULL for none
- */
-struct node_element *tree_get_node_element_at(struct node *node, int x, int y,
- bool *furniture)
-{
- struct node_element *element;
- int x0, x1, y0, y1;
-
- *furniture = false;
+ height, invert);
+ }
+}
+
+
+/**
+ * Updates the selected state for a region of nodes.
+ *
+ * \param tree the tree to update
+ * \param y the minimum y of the selection rectangle
+ * \param height the height of the selection rectangle
+ * \param invert whether to invert the selected state
+ */
+static void tree_handle_selection_area(struct tree *tree, int y, int height,
+ bool invert)
+{
+ assert(tree != NULL);
+ assert(tree->root != NULL);
+
+ if (tree->root->child == NULL)
+ return;
+
+ if (height < 0) {
+ y += height;
+ height = -height;
+ }
+ tree_handle_selection_area_node(tree, tree->root->child, y, height,
+ invert);
+}
+
+
+/**
+ * Clears the processing flag.
+ *
+ * \param node the node to process siblings and children of
+ */
+static void tree_clear_processing(struct node *node)
+{
for (; node != NULL; node = node->next) {
- if (node->box.y > y) return NULL;
- if ((node->box.x - NODE_INSTEP < x) && (node->box.y < y)
&&
- (node->box.x + node->box.width >= x) &&
- (node->box.y + node->box.height >= y)) {
- if (node->expanded) {
- for (element = &node->data; element != NULL;
- element = element->next) {
- x0 = element->box.x;
- y0 = element->box.y;
- x1 = element->box.x +
- element->box.width;
- y1 = element->box.y +
- element->box.height;
- if ((x0 < x) && (y0 < y) && (x1 >= x)
- && (y1 >= y))
- return element;
- }
- } else {
- x0 = node->data.box.x;
- y0 = node->data.box.y;
- x1 = node->data.box.x + node->data.box.width;
- y1 = node->data.box.y + node->data.box.height;
- if ((x0 < x) && (y0 < y) && (x1 >= x) &&
- (y1>= y))
- return &node->data;
- }
- if (((node->child != NULL) ||
- (node->data.next != NULL)) &&
- (node->data.box.x - NODE_INSTEP + 4 < x)
- && (node->data.box.y + 4 < y) &&
- (node->data.box.x > x) &&
- (node->data.box.y + 20 > y)) {
- *furniture = true;
- return &node->data;
- }
- }
-
- element = tree_get_node_element_at(node->child, x, y,
- furniture);
- if ((node->child != NULL) && (node->expanded) &&
- (element != NULL))
- return element;
- }
- return NULL;
-}
-
-
-
-/**
- * Moves nodes within a tree.
- *
- * \param tree the tree to process
- * \param destination the node to link before/as a child (folders)
- * or before/after (link)
- * \param before whether to link siblings before or after the supplied
- * node
- */
-void tree_move_selected_nodes(struct tree *tree, struct node *destination,
- bool before)
-{
- struct node *link;
- struct node *test;
- bool error;
-
- tree_clear_processing(tree->root);
- tree_selected_to_processing(tree->root);
-
- /* the destination node cannot be a child of any node with
- the processing flag set */
- error = destination->processing;
- for (test = destination; test != NULL; test = test->parent)
- error |= test->processing;
- if (error) {
- tree_clear_processing(tree->root);
- return;
- }
- if ((destination->folder) && (!destination->expanded) &&
(!before)) {
- tree_set_node_expanded(tree, destination, true, false, false);
- }
- link = tree_move_processing_node(tree, tree->root, destination, before,
- true);
- while (link != NULL)
- link = tree_move_processing_node(tree, tree->root, link, false,
- false);
-
- tree_clear_processing(tree->root);
- tree_recalculate_node_positions(tree, tree->root);
- if (tree->redraw)
- tree->callbacks->redraw_request(0, 0, tree->width, tree->height,
- tree->client_data);
+ node->processing = false;
+ if (node->child != NULL)
+ tree_clear_processing(node->child);
+ }
}
@@ -2341,27 +2280,12 @@
*
* \param node the node to process siblings and children of
*/
-void tree_selected_to_processing(struct node *node)
+static void tree_selected_to_processing(struct node *node)
{
for (; node != NULL; node = node->next) {
node->processing = node->selected;
if ((node->child != NULL) && (node->expanded))
tree_selected_to_processing(node->child);
- }
-}
-
-
-/**
- * Clears the processing flag.
- *
- * \param node the node to process siblings and children of
- */
-void tree_clear_processing(struct node *node)
-{
- for (; node != NULL; node = node->next) {
- node->processing = false;
- if (node->child != NULL)
- tree_clear_processing(node->child);
}
}
@@ -2378,8 +2302,8 @@
* inside of folders)
* \return the node moved
*/
-struct node *tree_move_processing_node(struct tree *tree, struct node *node,
- struct node *link, bool before, bool first)
+static struct node *tree_move_processing_node(struct tree *tree,
+ struct node *node, struct node *link, bool before, bool first)
{
struct node *result;
@@ -2397,12 +2321,165 @@
}
if (node->child != NULL) {
result = tree_move_processing_node(tree, node->child,
- link, before, first);
+ link, before, first);
if (result != NULL)
return result;
}
}
return NULL;
+}
+
+
+/**
+ * Moves nodes within a tree.
+ *
+ * \param tree the tree to process
+ * \param destination the node to link before/as a child (folders)
+ * or before/after (link)
+ * \param before whether to link siblings before or after the supplied
+ * node
+ */
+static void tree_move_selected_nodes(struct tree *tree,
+ struct node *destination, bool before)
+{
+ struct node *link;
+ struct node *test;
+ bool error;
+
+ tree_clear_processing(tree->root);
+ tree_selected_to_processing(tree->root);
+
+ /* the destination node cannot be a child of any node with
+ the processing flag set */
+ error = destination->processing;
+ for (test = destination; test != NULL; test = test->parent)
+ error |= test->processing;
+ if (error) {
+ tree_clear_processing(tree->root);
+ return;
+ }
+ if ((destination->folder) && (!destination->expanded) &&
(!before)) {
+ tree_set_node_expanded(tree, destination, true, false, false);
+ }
+ link = tree_move_processing_node(tree, tree->root, destination, before,
+ true);
+ while (link != NULL)
+ link = tree_move_processing_node(tree, tree->root, link, false,
+ false);
+
+ tree_clear_processing(tree->root);
+ tree_recalculate_node_positions(tree, tree->root);
+ if (tree->redraw)
+ tree->callbacks->redraw_request(0, 0, tree->width, tree->height,
+ tree->client_data);
+}
+
+
+/**
+ * Handle the end of a drag operation
+ *
+ * \param tree the tree on which the drag was performed
+ * \param mouse mouse state during drag end
+ * \param x0 x coordinate of drag start
+ * \param y0 y coordinate of drag start
+ * \param x1 x coordinate of drag end
+ * \param y1 y coordinate of drag end
+ */
+void tree_drag_end(struct tree *tree, browser_mouse_state mouse, int x0, int y0,
+ int x1, int y1)
+{
+
+ bool before;
+ struct node *node;
+ int x, y;
+
+ if (tree->textarea_drag_start) {
+ x = tree->editing->box.x;
+ y = tree->editing->box.y;
+ if (tree->editing->type == NODE_ELEMENT_TEXT_PLUS_ICON)
+ x += NODE_INSTEP;
+ textarea_drag_end(tree->textarea, mouse, x1 - x, y1 - y);
+ }
+
+ tree->textarea_drag_start = false;
+
+ switch (tree->drag) {
+ case TREE_NO_DRAG:
+ break;
+ case TREE_SELECT_DRAG:
+ tree_handle_selection_area(tree, y0, y1 - y0,
+ (mouse | BROWSER_MOUSE_HOLDING_2));
+ break;
+ case TREE_MOVE_DRAG:
+ if (!(tree->flags & TREE_MOVABLE))
+ return;
+ node = tree_get_link_details(tree, x1, y1, &before);
+ tree_move_selected_nodes(tree, node, before);
+ break;
+ }
+
+ tree->drag = TREE_NO_DRAG;
+}
+
+
+/**
+ * Key press handling for a tree.
+ *
+ * \param tree The tree which got the keypress
+ * \param key The ucs4 character codepoint
+ * \return true if the keypress is dealt with, false otherwise.
+ */
+bool tree_keypress(struct tree *tree, uint32_t key)
+{
+
+ if (tree->editing != NULL)
+ switch (key) {
+ case KEY_ESCAPE:
+ tree_stop_edit(tree, false);
+ return true;
+ case KEY_NL:
+ tree_stop_edit(tree, true);
+ return true;
+ default:
+ return textarea_keypress(tree->textarea, key);
+ }
+
+ return false;
+}
+
+
+/**
+ * Alphabetical comparison function for nodes
+ *
+ * \param n1 first node to compare
+ * \param n2 first node to compare
+ * \return 0 if equal, greater then zero if n1 > n2,
+ * less then zero if n2 < n1
+ */
+int tree_alphabetical_sort(struct node *n1, struct node *n2)
+{
+ return strcmp(n1->data.text, n2->data.text);
+}
+
+
+/**
+ * Redraw requests from the textarea are piped through this because we have to
+ * check the redraw flag of the tree before requesting a redraw and change the
+ * position to tree origin relative.
+ */
+static void tree_textarea_redraw_request(void *data, int x, int y,
+ int width, int height)
+{
+ struct tree *tree = data;
+ x = x + tree->editing->box.x;
+ y = y + tree->editing->box.y;
+ if (tree->editing->type == NODE_ELEMENT_TEXT_PLUS_ICON)
+ x += NODE_INSTEP;
+
+ if (tree->redraw)
+ tree->callbacks->redraw_request(x, y,
+ width, height,
+ tree->client_data);
}
@@ -2429,7 +2506,7 @@
for (; parent != NULL; parent = parent->parent) {
if (!parent->expanded) {
tree_set_node_expanded(tree, parent, true,
- false, false);
+ false, false);
}
}
@@ -2441,8 +2518,7 @@
width -= NODE_INSTEP;
tree->textarea = textarea_create(width, height, 0,
- &plot_fstyle, tree_textarea_redraw_request,
- tree);
+ &plot_fstyle, tree_textarea_redraw_request, tree);
if (tree->textarea == NULL) {
tree_stop_edit(tree, false);
return;
@@ -2452,90 +2528,20 @@
tree_handle_node_element_changed(tree, element);
tree_recalculate_size(tree);
tree->callbacks->scroll_visible(element->box.y, element->box.height,
- tree->client_data);
-}
-
-
-/**
- * Stops editing a node_element
- *
- * \param tree The tree to stop editing for
- * \param keep_changes If true the changes made to the text will be kept,
- * if false they will be dropped
- */
-void tree_stop_edit(struct tree *tree, bool keep_changes)
-{
- int text_len;
- char *text = NULL;
- struct node_element *element;
- struct node_msg_data msg_data;
- node_callback_resp response;
-
- assert(tree != NULL);
-
- if (tree->editing == NULL || tree->textarea == NULL)
- return;
-
- element = tree->editing;
-
- if (keep_changes) {
- text_len = textarea_get_text(tree->textarea, NULL, 0);
- text = malloc(text_len * sizeof(char));
- if (text == NULL) {
- LOG(("malloc failed"));
- warn_user("NoMemory", 0);
- textarea_destroy(tree->textarea);
- tree->textarea = NULL;
- return;
- }
- textarea_get_text(tree->textarea, text, text_len);
- }
-
-
- if (keep_changes && element->parent->user_callback != NULL) {
- msg_data.msg = NODE_ELEMENT_EDIT_FINISHING;
- msg_data.flag = element->flag;
- msg_data.node = element->parent;
- msg_data.data.text = text;
- response = element->parent->user_callback(
- element->parent->callback_data,
- &msg_data);
-
- switch (response) {
- case NODE_CALLBACK_REJECT:
- free(text);
- text = NULL;
- break;
- case NODE_CALLBACK_CONTINUE:
- free(text);
- text = NULL;
- return;
- case NODE_CALLBACK_HANDLED:
- case NODE_CALLBACK_NOT_HANDLED:
- text = msg_data.data.text;
- break;
- }
- }
-
- textarea_destroy(tree->textarea);
- tree->textarea = NULL;
- tree->editing = NULL;
-
- if (text != NULL)
- tree_update_node_element(tree, element, text, NULL);
- else
- tree_handle_node_element_changed(tree, element);
-
-
- tree_recalculate_size(tree);
- if (element->parent->user_callback != NULL) {
- msg_data.msg = NODE_ELEMENT_EDIT_FINISHED;
- msg_data.flag = element->flag;
- msg_data.node = element->parent;
- element->parent->user_callback(element->parent->callback_data,
- &msg_data);
- }
-}
+ tree->client_data);
+}
+
+
+/**
+ * Callback for fetchcache(). Should be removed once bitmaps get loaded directly
+ * from disc
+ */
+static nserror tree_icon_callback(hlcache_handle *handle,
+ const hlcache_event *event, void *pw)
+{
+ return NSERROR_OK;
+}
+
/**
* Tree utility function. Placed here so that this code doesn't have to be
@@ -2574,7 +2580,7 @@
/* Build native path */
memcpy(native_path, option_tree_icons_dir,
- strlen(option_tree_icons_dir) + 1);
+ strlen(option_tree_icons_dir) + 1);
path_add_part(native_path, len, name);
/* Convert native path to URL */
@@ -2585,10 +2591,10 @@
}
/* Fetch the icon */
- err = hlcache_handle_retrieve(icon_url, 0, 0, 0,
- tree_icon_callback, 0, 0, 0, &c);
-
-
+ err = hlcache_handle_retrieve(icon_url, 0, 0, 0,
+ tree_icon_callback, 0, 0, 0, &c);
+
+
/* If we built the URL here, free it */
if (url != NULL)
free(url);
@@ -2599,34 +2605,3 @@
return c;
}
-
-
-/**
- * Callback for fetchcache(). Should be removed once bitmaps get loaded directly
- * from disc
- */
-nserror tree_icon_callback(hlcache_handle *handle,
- const hlcache_event *event, void *pw)
-{
- return NSERROR_OK;
-}
-
-/**
- * Redraw requests from the textarea are piped through this because we have to
- * check the redraw flag of the tree before requesting a redraw and change the
- * position to tree origin relative.
- */
-void tree_textarea_redraw_request(void *data, int x, int y,
- int width, int height)
-{
- struct tree *tree = data;
- x = x + tree->editing->box.x;
- y = y + tree->editing->box.y;
- if (tree->editing->type == NODE_ELEMENT_TEXT_PLUS_ICON)
- x += NODE_INSTEP;
-
- if (tree->redraw)
- tree->callbacks->redraw_request(x, y,
- width, height,
- tree->client_data);
-}