From 93cc123200f1e4856ad5b5c608d8deeb34522053 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Tue, 29 Jan 2013 17:34:08 +0000 Subject: Update textarea to inform client what it's doing with drags. Now single callback for both redraw requests and drag reports. Update treeview to use new textarea API. Update Atari URL bar to use new textarea API. (Ignores drag reports, currently.) Minor textarea fixes. --- atari/toolbar.c | 23 ++++- desktop/textarea.c | 254 +++++++++++++++++++++++++++++++++++++---------------- desktop/textarea.h | 52 +++++++---- desktop/tree.c | 93 +++++++++++--------- 4 files changed, 282 insertions(+), 140 deletions(-) diff --git a/atari/toolbar.c b/atari/toolbar.c index 82dc047fa..d30382842 100755 --- a/atari/toolbar.c +++ b/atari/toolbar.c @@ -651,7 +651,26 @@ static void tb_txt_request_redraw(void *data, int x, int y, int w, int h) t->url.rdw_area.g_h = ( oldy1 > newy1 ) ? oldy1 - t->url.rdw_area.g_y : newy1 - t->url.rdw_area.g_y; } -} +} + + +static void tb_txt_callback(void *data, struct textarea_msg *msg) +{ + switch (msg->type) { + case TEXTAREA_MSG_DRAG_REPORT: + break; + + case TEXTAREA_MSG_REDRAW_REQUEST: + tb_txt_redraw_request(data, + msg->data.redraw.x0, msg->data.redraw.y0, + msg->data.redraw.x1 - msg->data.redraw.x0, + msg->data.redraw.y1 - msg->data.redraw.y0); + break; + + default: + break; + } +} void tb_url_redraw( struct gui_window * gw ) { @@ -785,7 +804,7 @@ CMP_TOOLBAR tb_create( struct gui_window * gw ) ta_setup.text = font_style_url; ta_setup.text.foreground = 0x000000; ta_setup.text.background = 0xffffff; - t->url.textarea = textarea_create( &ta_setup, tb_txt_request_redraw, t ); + t->url.textarea = textarea_create( &ta_setup, tb_txt_callback, t ); if( t->url.textarea != NULL ){ textarea_set_text(t->url.textarea, "http://"); } diff --git a/desktop/textarea.c b/desktop/textarea.c index e94360e5b..725c911b7 100644 --- a/desktop/textarea.c +++ b/desktop/textarea.c @@ -43,18 +43,14 @@ static plot_style_t pstyle_stroke_caret = { .stroke_width = 1, }; +static struct textarea_msg msg; + struct line_info { unsigned int b_start; /**< Byte offset of line start */ unsigned int b_length; /**< Byte length of line */ }; - -typedef enum textarea_drag_type_internal { - TEXTAREA_DRAG_NONE, - TEXTAREA_DRAG_SCROLLBAR, - TEXTAREA_DRAG_SELECTION -} textarea_drag_type_internal; struct textarea_drag { - textarea_drag_type_internal type; + textarea_drag_type type; union { struct scrollbar* scrollbar; } data; @@ -106,7 +102,7 @@ struct textarea { int line_height; /**< Line height obtained from style */ /** Callback function for a redraw request */ - textarea_redraw_request_callback redraw_request; + textarea_client_callback callback; void *data; /**< Client data for callback */ @@ -179,7 +175,14 @@ static bool textarea_select(struct textarea *ta, int c_start, int c_end) ta->sel_start = c_start; ta->sel_end = c_end; - ta->redraw_request(ta->data, 0, 0, ta->vis_width, ta->vis_height); + msg.ta = ta; + msg.type = TEXTAREA_MSG_REDRAW_REQUEST; + msg.data.redraw.x0 = 0; + msg.data.redraw.y0 = 0; + msg.data.redraw.x1 = ta->vis_width; + msg.data.redraw.y1 = ta->vis_height; + + ta->callback(ta->data, &msg); return true; } @@ -322,6 +325,7 @@ static bool textarea_scroll_visible(struct textarea *ta) return scrolled; } + /** * Callback for scrollbar widget. */ @@ -331,27 +335,46 @@ static void textarea_scrollbar_callback(void *client_data, struct textarea *ta = client_data; switch(scrollbar_data->msg) { - case SCROLLBAR_MSG_MOVED: - /* Scrolled; redraw everything */ - ta->scroll_x = scrollbar_get_offset(ta->bar_x); - ta->scroll_y = scrollbar_get_offset(ta->bar_y); + case SCROLLBAR_MSG_MOVED: + /* Scrolled; redraw everything */ + ta->scroll_x = scrollbar_get_offset(ta->bar_x); + ta->scroll_y = scrollbar_get_offset(ta->bar_y); + + msg.ta = ta; + msg.type = TEXTAREA_MSG_REDRAW_REQUEST; + msg.data.redraw.x0 = 0; + msg.data.redraw.y0 = 0; + msg.data.redraw.x1 = ta->vis_width; + msg.data.redraw.y1 = ta->vis_height; + + ta->callback(ta->data, &msg); + break; - ta->redraw_request(ta->data, 0, 0, - ta->vis_width, - ta->vis_height); - break; + case SCROLLBAR_MSG_SCROLL_START: + ta->drag_info.type = TEXTAREA_DRAG_SCROLLBAR; + ta->drag_info.data.scrollbar = scrollbar_data->scrollbar; - case SCROLLBAR_MSG_SCROLL_START: - ta->drag_info.type = TEXTAREA_DRAG_SCROLLBAR; - ta->drag_info.data.scrollbar = - scrollbar_data->scrollbar; - /* TODO: Tell textarea client we're handling a drag */ - break; + msg.ta = ta; + msg.type = TEXTAREA_MSG_DRAG_REPORT; + msg.data.drag = ta->drag_info.type; - case SCROLLBAR_MSG_SCROLL_FINISHED: - ta->drag_info.type = TEXTAREA_DRAG_NONE; - /* TODO: Tell textarea client drag finished */ - break; + /* Tell client we're handling a drag */ + ta->callback(ta->data, &msg); + break; + + case SCROLLBAR_MSG_SCROLL_FINISHED: + ta->drag_info.type = TEXTAREA_DRAG_NONE; + + msg.ta = ta; + msg.type = TEXTAREA_MSG_DRAG_REPORT; + msg.data.drag = ta->drag_info.type; + + /* Tell client we finished handling the drag */ + ta->callback(ta->data, &msg); + break; + + default: + break; } } @@ -799,15 +822,79 @@ static bool textarea_replace_text(struct textarea *ta, unsigned int start, } +/** + * Handles the end of a drag operation + * + * \param ta Text area + * \param mouse the mouse state at drag end moment + * \param x X coordinate + * \param y Y coordinate + * \return true if drag end was handled false otherwise + */ +static bool textarea_drag_end(struct textarea *ta, browser_mouse_state mouse, + int x, int y) +{ + int c_end; + size_t b_off; + unsigned int c_off; + + assert(ta->drag_info.type != TEXTAREA_DRAG_NONE); + + switch (ta->drag_info.type) { + case TEXTAREA_DRAG_SCROLLBAR: + if (ta->drag_info.data.scrollbar == ta->bar_x) { + x -= ta->border_width; + y -= ta->vis_height - ta->border_width - + SCROLLBAR_WIDTH; + } else { + x -= ta->vis_width - ta->border_width - + SCROLLBAR_WIDTH; + y -= ta->border_width; + } + scrollbar_mouse_drag_end(ta->drag_info.data.scrollbar, + mouse, x, y); + assert(ta->drag_info.type == TEXTAREA_DRAG_NONE); + + /* Return, since drag end already reported to textarea client */ + return true; + + case TEXTAREA_DRAG_SELECTION: + ta->drag_info.type = TEXTAREA_DRAG_NONE; + + textarea_get_xy_offset(ta, x, y, &b_off, &c_off); + c_end = c_off; + + if (!textarea_select(ta, ta->drag_start_char, c_end)) + return false; + + break; + + default: + return false; + } + + /* Report drag end to client, if not already reported */ + assert(ta->drag_info.type == TEXTAREA_DRAG_NONE); + + msg.ta = ta; + msg.type = TEXTAREA_MSG_DRAG_REPORT; + msg.data.drag = ta->drag_info.type; + + ta->callback(ta->data, &msg); + + return true; +} + + /* exported interface, documented in textarea.h */ struct textarea *textarea_create(const textarea_setup *setup, - textarea_redraw_request_callback redraw_request, void *data) + textarea_client_callback callback, void *data) { struct textarea *ret; - if (redraw_request == NULL) { + if (callback == NULL) { LOG(("no callback provided")); return NULL; } @@ -818,7 +905,7 @@ struct textarea *textarea_create(const textarea_setup *setup, return NULL; } - ret->redraw_request = redraw_request; + ret->callback = callback; ret->data = data; ret->flags = setup->flags; @@ -972,7 +1059,14 @@ bool textarea_set_caret(struct textarea *ta, int caret) width = 2; height = ta->line_height; - ta->redraw_request(ta->data, x0, y0, width, height); + msg.ta = ta; + msg.type = TEXTAREA_MSG_REDRAW_REQUEST; + msg.data.redraw.x0 = x0; + msg.data.redraw.y0 = y0; + msg.data.redraw.x1 = x0 + width; + msg.data.redraw.y1 = y0 + height; + + ta->callback(ta->data, &msg); } /* check if the caret has to be drawn at all */ @@ -1032,8 +1126,14 @@ bool textarea_set_caret(struct textarea *ta, int caret) height = y1 - y0; if (width > 0 && height > 0) { - ta->redraw_request(ta->data, x0, y0, - width, height); + msg.ta = ta; + msg.type = TEXTAREA_MSG_REDRAW_REQUEST; + msg.data.redraw.x0 = x0; + msg.data.redraw.y0 = y0; + msg.data.redraw.x1 = x0 + width; + msg.data.redraw.y1 = y0 + height; + + ta->callback(ta->data, &msg); } } } @@ -1147,8 +1247,7 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, (ta->bar_x != NULL ? SCROLLBAR_WIDTH : 0); if (line0 > 0) - c_pos = utf8_bounded_length(ta->text, - ta->lines[line0].b_start - 1); + c_pos = utf8_bounded_length(ta->text, ta->lines[line0].b_start); else c_pos = 0; @@ -1683,8 +1782,14 @@ bool textarea_keypress(struct textarea *ta, uint32_t key) textarea_set_caret(ta, caret); //TODO:redraw only the important part if (redraw) { - ta->redraw_request(ta->data, 0, 0, - ta->vis_width, ta->vis_height); + msg.ta = ta; + msg.type = TEXTAREA_MSG_REDRAW_REQUEST; + msg.data.redraw.x0 = 0; + msg.data.redraw.y0 = 0; + msg.data.redraw.x1 = ta->vis_width; + msg.data.redraw.y1 = ta->vis_height; + + ta->callback(ta->data, &msg); } return true; @@ -1701,7 +1806,14 @@ bool textarea_mouse_action(struct textarea *ta, browser_mouse_state mouse, size_t b_off; unsigned int c_off; + if (ta->drag_info.type != TEXTAREA_DRAG_NONE && + mouse == BROWSER_MOUSE_HOVER) { + /* There is a drag that we must end */ + textarea_drag_end(ta, mouse, x, y); + } + if (ta->drag_info.type == TEXTAREA_DRAG_SCROLLBAR) { + /* Scrollbar drag in progress; pass input to scrollbar */ if (ta->drag_info.data.scrollbar == ta->bar_x) { x -= ta->border_width; y -= ta->vis_height - ta->border_width - @@ -1718,6 +1830,8 @@ bool textarea_mouse_action(struct textarea *ta, browser_mouse_state mouse, /* Horizontal scrollbar */ if (ta->bar_x != NULL && ta->drag_info.type == TEXTAREA_DRAG_NONE) { + /* No drag happening, but mouse input is over scrollbar; + * pass input to scrollbar */ sx = x - ta->border_width; sy = y - (ta->vis_height - ta->border_width - SCROLLBAR_WIDTH); sl = ta->vis_width - 2 * ta->border_width - @@ -1731,6 +1845,8 @@ bool textarea_mouse_action(struct textarea *ta, browser_mouse_state mouse, /* Vertical scrollbar */ if (ta->bar_y != NULL && ta->drag_info.type == TEXTAREA_DRAG_NONE) { + /* No drag happening, but mouse input is over scrollbar; + * pass input to scrollbar */ sx = x - (ta->vis_width - ta->border_width - SCROLLBAR_WIDTH); sy = y - ta->border_width; sl = ta->vis_height - 2 * ta->border_width; @@ -1752,9 +1868,15 @@ bool textarea_mouse_action(struct textarea *ta, browser_mouse_state mouse, if (ta->sel_start != -1) { /* remove selection */ ta->sel_start = ta->sel_end = -1; - ta->redraw_request(ta->data, 0, 0, - ta->vis_width, - ta->vis_height); + + msg.ta = ta; + msg.type = TEXTAREA_MSG_REDRAW_REQUEST; + msg.data.redraw.x0 = 0; + msg.data.redraw.y0 = 0; + msg.data.redraw.x1 = ta->vis_width; + msg.data.redraw.y1 = ta->vis_height; + + ta->callback(ta->data, &msg); } } else if (mouse & BROWSER_MOUSE_DOUBLE_CLICK) { @@ -1768,47 +1890,17 @@ bool textarea_mouse_action(struct textarea *ta, browser_mouse_state mouse, c_start = ta->drag_start_char; c_end = c_off; ta->drag_info.type = TEXTAREA_DRAG_SELECTION; - return textarea_select(ta, c_start, c_end); - } - - return true; -} - - -/* exported interface, documented in textarea.h */ -bool textarea_drag_end(struct textarea *ta, browser_mouse_state mouse, - int x, int y) -{ - int c_end; - size_t b_off; - unsigned int c_off; - switch (ta->drag_info.type) { - case TEXTAREA_DRAG_SCROLLBAR: - if (ta->drag_info.data.scrollbar == ta->bar_x) { - x -= ta->border_width; - y -= ta->vis_height - ta->border_width - - SCROLLBAR_WIDTH; - } else { - x -= ta->vis_width - ta->border_width - - SCROLLBAR_WIDTH; - y -= ta->border_width; - } - scrollbar_mouse_drag_end(ta->drag_info.data.scrollbar, - mouse, x, y); - return true; + msg.ta = ta; + msg.type = TEXTAREA_MSG_DRAG_REPORT; + msg.data.drag = ta->drag_info.type; - case TEXTAREA_DRAG_SELECTION: - textarea_get_xy_offset(ta, x, y, &b_off, &c_off); - c_end = c_off; - ta->drag_info.type = TEXTAREA_DRAG_NONE; - return textarea_select(ta, ta->drag_start_char, c_end); + ta->callback(ta->data, &msg); - default: - break; + return textarea_select(ta, c_start, c_end); } - return false; + return true; } @@ -1828,5 +1920,13 @@ void textarea_set_dimensions(struct textarea *ta, int width, int height) ta->vis_width = width; ta->vis_height = height; textarea_reflow(ta, 0); - ta->redraw_request(ta->data, 0, 0, ta->vis_width, ta->vis_height); + + msg.ta = ta; + msg.type = TEXTAREA_MSG_REDRAW_REQUEST; + msg.data.redraw.x0 = 0; + msg.data.redraw.y0 = 0; + msg.data.redraw.x1 = ta->vis_width; + msg.data.redraw.y1 = ta->vis_height; + + ta->callback(ta->data, &msg); } diff --git a/desktop/textarea.h b/desktop/textarea.h index 7624c3187..fb8b13425 100644 --- a/desktop/textarea.h +++ b/desktop/textarea.h @@ -29,13 +29,37 @@ #include "desktop/browser.h" #include "desktop/plot_style.h" + +struct textarea; + /* Text area flags */ -typedef enum textarea_flags { +typedef enum { TEXTAREA_DEFAULT = (1 << 0), TEXTAREA_MULTILINE = (1 << 1), TEXTAREA_READONLY = (1 << 2) } textarea_flags; +typedef enum { + TEXTAREA_DRAG_NONE, + TEXTAREA_DRAG_SCROLLBAR, + TEXTAREA_DRAG_SELECTION +} textarea_drag_type; + +typedef enum { + TEXTAREA_MSG_DRAG_REPORT, /**< Textarea drag start/end report */ + TEXTAREA_MSG_REDRAW_REQUEST /**< Textarea redraw request */ +} textarea_msg_type; + +struct textarea_msg { + struct textarea *ta; + + textarea_msg_type type; + union { + textarea_drag_type drag; + struct rect redraw; + } data; +}; + typedef struct textarea_setup { textarea_flags flags; /**< Setup flags */ @@ -56,11 +80,13 @@ typedef struct textarea_setup { } textarea_setup; - -struct textarea; - -typedef void(*textarea_redraw_request_callback)(void *data, int x, int y, - int width, int height); +/** + * Client callback for the textarea + * + * \param data user data passed at textarea creation + * \param textarea_msg textarea message data + */ +typedef void(*textarea_client_callback)(void *data, struct textarea_msg *msg); /** * Create a text area @@ -71,7 +97,7 @@ typedef void(*textarea_redraw_request_callback)(void *data, int x, int y, * \return Opaque handle for textarea or 0 on error */ struct textarea *textarea_create(const textarea_setup *setup, - textarea_redraw_request_callback redraw_request, void *data); + textarea_client_callback callback, void *data); /** * Destroy a text area @@ -152,18 +178,6 @@ bool textarea_keypress(struct textarea *ta, uint32_t key); bool textarea_mouse_action(struct textarea *ta, browser_mouse_state mouse, int x, int y); -/** - * Handles the end of a drag operation - * - * \param ta Text area - * \param mouse the mouse state at drag end moment - * \param x X coordinate - * \param y Y coordinate - * \return true if drag end was handled false otherwise - */ -bool textarea_drag_end(struct textarea *ta, browser_mouse_state mouse, - int x, int y); - /** * Gets the dimensions of a textarea * diff --git a/desktop/tree.c b/desktop/tree.c index a48b615a0..4f9170d06 100644 --- a/desktop/tree.c +++ b/desktop/tree.c @@ -160,8 +160,7 @@ struct tree { int height; /* Tree height */ unsigned int flags; /* Tree flags */ struct textarea *textarea; /* Handle for UTF-8 textarea */ - bool textarea_drag_start; /* whether the start of a mouse drag - was in the textarea */ + int ta_height; /* Textarea height */ struct node_element *editing; /* Node element being edited */ bool redraw; /* Flag indicating whether the tree @@ -263,7 +262,6 @@ struct tree *tree_create(unsigned int flags, tree->height = 0; tree->flags = flags; tree->textarea = NULL; - tree->textarea_drag_start = false; tree->editing = NULL; tree->redraw = false; tree->drag = TREE_NO_DRAG; @@ -2430,9 +2428,9 @@ bool tree_mouse_action(struct tree *tree, browser_mouse_state mouse, int x, x0 += NODE_INSTEP; x1 = tree->editing->box.x + tree->editing->box.width; y0 = tree->editing->box.y; - y1 = tree->editing->box.y + tree->editing->box.height; + y1 = tree->editing->box.y + tree->ta_height; - if (tree->textarea_drag_start && + if (tree->drag == TREE_TEXTAREA_DRAG && (mouse & (BROWSER_MOUSE_HOLDING_1 | BROWSER_MOUSE_HOLDING_2))) { /* Track the drag path */ @@ -2441,19 +2439,7 @@ bool tree_mouse_action(struct tree *tree, browser_mouse_state mouse, int x, return true; } - - if ((x >= x0) && (x < x1) && (y >= y0) && (y < y1)) { - /* Inside the textarea */ - if (mouse & (BROWSER_MOUSE_DRAG_1 | - BROWSER_MOUSE_DRAG_2)) { - /* Drag starting */ - tree->textarea_drag_start = true; - tree->drag = TREE_TEXTAREA_DRAG; - } else { - /* Other action */ - tree->textarea_drag_start = false; - } textarea_mouse_action(tree->textarea, mouse, x - x0, y - y0); return true; @@ -2461,8 +2447,6 @@ bool tree_mouse_action(struct tree *tree, browser_mouse_state mouse, int x, } } - tree->textarea_drag_start = false; - /* we are not interested in the drag path, return */ if (mouse & (BROWSER_MOUSE_HOLDING_1 | BROWSER_MOUSE_HOLDING_2)) return true; @@ -2835,25 +2819,25 @@ void tree_drag_end(struct tree *tree, browser_mouse_state mouse, int x0, int y0, struct node *node; int x, y; - if (tree->textarea_drag_start) { + switch (tree->drag) { + case TREE_NO_DRAG: + case TREE_UNKNOWN_DRAG: + break; + + case TREE_TEXTAREA_DRAG: 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: - case TREE_TEXTAREA_DRAG: - case TREE_UNKNOWN_DRAG: + textarea_mouse_action(tree->textarea, BROWSER_MOUSE_HOVER, + x1 - x, y1 - y); 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; @@ -2875,7 +2859,6 @@ void tree_drag_end(struct tree *tree, browser_mouse_state mouse, int x0, int y0, */ bool tree_keypress(struct tree *tree, uint32_t key) { - if (tree->editing != NULL) switch (key) { case KEY_ESCAPE: @@ -2912,19 +2895,43 @@ int tree_alphabetical_sort(struct node *n1, struct node *n2) * 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) + +static void tree_textarea_callback(void *data, struct textarea_msg *msg) { 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; + int x, y; - if (tree->redraw) - tree->callbacks->redraw_request(x, y, - width, height, - tree->client_data); + switch (msg->type) { + case TEXTAREA_MSG_DRAG_REPORT: + if (msg->data.drag == TEXTAREA_DRAG_NONE) { + /* Textarea drag finished */ + tree->drag = TREE_NO_DRAG; + } else { + /* Textarea drag started */ + tree->drag = TREE_TEXTAREA_DRAG; + } + break; + + case TEXTAREA_MSG_REDRAW_REQUEST: + x = msg->data.redraw.x0 + tree->editing->box.x; + y = msg->data.redraw.y0 + tree->editing->box.y; + + if (tree->editing->type == NODE_ELEMENT_TEXT_PLUS_ICON) + x += NODE_INSTEP; + + /* Redraw the textarea */ + if (tree->redraw) + tree->callbacks->redraw_request(x, y, + msg->data.redraw.x1 - + msg->data.redraw.x0, + msg->data.redraw.y1 - + msg->data.redraw.y0, + tree->client_data); + break; + + default: + break; + } } @@ -2963,9 +2970,11 @@ void tree_start_edit(struct tree *tree, struct node_element *element) if (element->type == NODE_ELEMENT_TEXT_PLUS_ICON) width -= NODE_INSTEP; + tree->ta_height = height; + ta_setup.flags = TEXTAREA_DEFAULT; ta_setup.width = width; - ta_setup.height = height; + ta_setup.height = tree->ta_height; ta_setup.pad_top = 0; ta_setup.pad_right = 4; ta_setup.pad_bottom = 0; @@ -2979,7 +2988,7 @@ void tree_start_edit(struct tree *tree, struct node_element *element) ta_setup.text.background = 0xffffff; tree->textarea = textarea_create(&ta_setup, - tree_textarea_redraw_request, tree); + tree_textarea_callback, tree); if (tree->textarea == NULL) { tree_stop_edit(tree, false); return; -- cgit v1.2.3