summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2017-09-10 15:50:35 +0100
committerMichael Drake <tlsa@netsurf-browser.org>2017-09-10 15:53:15 +0100
commitc20ad212731526d46f872a8220c6a1f53696f7e1 (patch)
tree47a0989de513dad3c4efe3e9e4b7995de44cc089 /desktop
parentc478f35c81478e48d3a86ac57e7bb7c34a3ce107 (diff)
downloadnetsurf-c20ad212731526d46f872a8220c6a1f53696f7e1.tar.gz
netsurf-c20ad212731526d46f872a8220c6a1f53696f7e1.tar.bz2
Treeview: Add support for rendering search filter matches as-you-type.
Diffstat (limited to 'desktop')
-rw-r--r--desktop/treeview.c231
1 files changed, 230 insertions, 1 deletions
diff --git a/desktop/treeview.c b/desktop/treeview.c
index 8b66730d5..85bc61d8e 100644
--- a/desktop/treeview.c
+++ b/desktop/treeview.c
@@ -2462,6 +2462,228 @@ static void treeview_redraw_tree(
}
+/**
+ * Draw a treeview normally, in tree mode.
+ *
+ * \param[in] tree The treeview we're rendering.
+ * \param[in] x X coordinate we're rendering the treeview at.
+ * \param[in] y Y coordinate we're rendering the treeview at.
+ * \param[in,out] render_y Current vertical position in tree, updated on exit.
+ * \param[in] r Clip rectangle.
+ * \param[in] data Redraw data for rendering contents.
+ * \param[in] ctx Current render context.
+ */
+static void treeview_redraw_search(
+ treeview *tree,
+ const int x,
+ const int y,
+ int *render_y_in_out,
+ struct rect *r,
+ struct content_redraw_data *data,
+ const struct redraw_context *ctx)
+{
+ struct treeview_node_style *style = &plot_style_odd;
+ enum treeview_resource_id res = TREE_RES_CONTENT;
+ int baseline = (tree_g.line_height * 3 + 2) / 4;
+ plot_font_style_t *infotext_style;
+ treeview_node *root = tree->root;
+ treeview_node *node = tree->root;
+ int render_y = *render_y_in_out;
+ plot_font_style_t *text_style;
+ plot_style_t *bg_style;
+ int sel_min, sel_max;
+ uint32_t count = 0;
+ struct rect rect;
+ int inset;
+ int x0;
+
+ if (tree->drag.start.y > tree->drag.prev.y) {
+ sel_min = tree->drag.prev.y;
+ sel_max = tree->drag.start.y;
+ } else {
+ sel_min = tree->drag.start.y;
+ sel_max = tree->drag.prev.y;
+ }
+
+ while (node != NULL) {
+ struct treeview_node_entry *entry;
+ struct bitmap *furniture;
+ bool invert_selection;
+ treeview_node *next;
+ int height;
+ int i;
+
+ next = node->children;
+
+ if (next != NULL) {
+ /* down to children */
+ node = next;
+ } else {
+ /* No children. As long as we're not at the root,
+ * go to next sibling if present, or nearest ancestor
+ * with a next sibling. */
+
+ while (node != root &&
+ node->next_sib == NULL) {
+ node = node->parent;
+ }
+
+ if (node == root)
+ break;
+
+ node = node->next_sib;
+ }
+
+ assert(node != NULL);
+ assert(node != root);
+ assert(node->type == TREE_NODE_FOLDER ||
+ node->type == TREE_NODE_ENTRY);
+
+ if (node->type == TREE_NODE_FOLDER ||
+ !(node->flags & TV_NFLAGS_MATCHED)) {
+ continue;
+ }
+
+ count++;
+ inset = x + tree_g.window_padding;
+ height = tree_g.line_height;
+
+ if ((render_y + height) < r->y0) {
+ /* This node's line is above clip region */
+ render_y += height;
+ continue;
+ }
+
+ style = (count & 0x1) ? &plot_style_odd : &plot_style_even;
+ if (tree->drag.type == TV_DRAG_SELECTION &&
+ (render_y + height >= sel_min &&
+ render_y < sel_max)) {
+ invert_selection = true;
+ } else {
+ invert_selection = false;
+ }
+ if ((node->flags & TV_NFLAGS_SELECTED && !invert_selection) ||
+ (!(node->flags & TV_NFLAGS_SELECTED) &&
+ invert_selection)) {
+ bg_style = &style->sbg;
+ text_style = &style->stext;
+ infotext_style = &style->sitext;
+ furniture = (node->flags & TV_NFLAGS_EXPANDED) ?
+ style->furn[TREE_FURN_CONTRACT].sel :
+ style->furn[TREE_FURN_EXPAND].sel;
+ } else {
+ bg_style = &style->bg;
+ text_style = &style->text;
+ infotext_style = &style->itext;
+ furniture = (node->flags & TV_NFLAGS_EXPANDED) ?
+ style->furn[TREE_FURN_CONTRACT].bmp :
+ style->furn[TREE_FURN_EXPAND].bmp;
+ }
+
+ /* Render background */
+ rect.x0 = r->x0;
+ rect.y0 = render_y;
+ rect.x1 = r->x1;
+ rect.y1 = render_y + height;
+ ctx->plot->rectangle(ctx, bg_style, &rect);
+
+ /* Render toggle */
+ ctx->plot->bitmap(ctx,
+ furniture,
+ inset,
+ render_y + tree_g.line_height / 4,
+ style->furn[TREE_FURN_EXPAND].size,
+ style->furn[TREE_FURN_EXPAND].size,
+ bg_style->fill_colour,
+ BITMAPF_NONE);
+
+ /* Render icon */
+ if (node->type == TREE_NODE_ENTRY) {
+ res = TREE_RES_CONTENT;
+ } else if (node->flags & TV_NFLAGS_SPECIAL) {
+ res = TREE_RES_FOLDER_SPECIAL;
+ } else {
+ res = TREE_RES_FOLDER;
+ }
+
+ if (treeview_res[res].ready) {
+ /* Icon resource is available */
+ data->x = inset + tree_g.step_width;
+ data->y = render_y + ((tree_g.line_height -
+ treeview_res[res].height + 1) / 2);
+ data->background_colour = bg_style->fill_colour;
+
+ content_redraw(treeview_res[res].c, data, r, ctx);
+ }
+
+ /* Render text */
+ x0 = inset + tree_g.step_width + tree_g.icon_step;
+ ctx->plot->text(ctx,
+ text_style,
+ x0, render_y + baseline,
+ node->text.data,
+ node->text.len);
+
+ /* Rendered the node */
+ render_y += tree_g.line_height;
+ if (render_y > r->y1) {
+ /* Passed the bottom of what's in the clip region.
+ * Done. */
+ break;
+ }
+
+
+ if (node->type != TREE_NODE_ENTRY ||
+ !(node->flags & TV_NFLAGS_EXPANDED))
+ /* Done everything for this node */
+ continue;
+
+ /* Render expanded entry fields */
+ entry = (struct treeview_node_entry *)node;
+ for (i = 0; i < tree->n_fields - 1; i++) {
+ struct treeview_field *ef = &(tree->fields[i + 1]);
+
+ if (ef->flags & TREE_FLAG_SHOW_NAME) {
+ int max_width = tree->field_width;
+
+ ctx->plot->text(ctx,
+ infotext_style,
+ x0 + max_width - ef->value.width - tree_g.step_width,
+ render_y + baseline,
+ ef->value.data,
+ ef->value.len);
+
+ ctx->plot->text(ctx,
+ infotext_style,
+ x0 + max_width,
+ render_y + baseline,
+ entry->fields[i].value.data,
+ entry->fields[i].value.len);
+ } else {
+ ctx->plot->text(ctx,
+ infotext_style,
+ x0, render_y + baseline,
+ entry->fields[i].value.data,
+ entry->fields[i].value.len);
+ }
+
+ /* Rendered the expanded entry field */
+ render_y += tree_g.line_height;
+ }
+
+ /* Finished rendering expanded entry */
+
+ if (render_y > r->y1) {
+ /* Passed the bottom of what's in the clip region.
+ * Done. */
+ break;
+ }
+ }
+
+ *render_y_in_out = render_y;
+}
+
+
/* Exported interface, documented in treeview.h */
void
treeview_redraw(treeview *tree,
@@ -2533,7 +2755,14 @@ treeview_redraw(treeview *tree,
render_y += tree_g.line_height;
}
- treeview_redraw_tree(tree, x, y, &render_y, &r, &data, &new_ctx);
+ /* Render the treeview data */
+ if (tree->search.search == true) {
+ treeview_redraw_search(tree, x, y,
+ &render_y, &r, &data, &new_ctx);
+ } else {
+ treeview_redraw_tree(tree, x, y,
+ &render_y, &r, &data, &new_ctx);
+ }
if (render_y < r.y1) {
/* Fill the blank area at the bottom */