diff options
-rwxr-xr-x | atari/toolbar.c | 23 | ||||
-rw-r--r-- | desktop/textarea.c | 254 | ||||
-rw-r--r-- | desktop/textarea.h | 52 | ||||
-rw-r--r-- | 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 @@ -153,18 +179,6 @@ 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 * * \param width if not NULL, gets updated to the width of the 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; |