From 5124b8a02a2adb72a7352f14e06dc2a773afbc1f Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 12 Jan 2013 20:46:01 +0000 Subject: Add textarea_setup struct to textarea_create API. --- desktop/textarea.h | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'desktop/textarea.h') diff --git a/desktop/textarea.h b/desktop/textarea.h index e4fa2c7aa..a798e7c9f 100644 --- a/desktop/textarea.h +++ b/desktop/textarea.h @@ -36,6 +36,26 @@ typedef enum textarea_flags { TEXTAREA_READONLY = (1 << 2) } textarea_flags; +typedef struct textarea_setup { + textarea_flags flags; + + int width; + int height; + + int pad_top; + int pad_right; + int pad_bottom; + int pad_left; + + int border_width; + colour border_col; + + colour selected_text; + colour selected_bg; + plot_font_style_t text; + +} textarea_setup; + struct textarea; @@ -54,8 +74,7 @@ typedef void(*textarea_redraw_request_callback)(void *data, int x, int y, * \param data user specified data which will be passed to redraw callbacks * \return Opaque handle for textarea or 0 on error */ -struct textarea *textarea_create(int width, int height, - textarea_flags flags, const plot_font_style_t *style, +struct textarea *textarea_create(const textarea_setup *setup, textarea_redraw_request_callback redraw_request, void *data); /** -- cgit v1.2.3 From c7a37392e49deb5007dc3679e0aa7e65b4ff0c8b Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 12 Jan 2013 20:59:32 +0000 Subject: Add background colour to textarea_redraw API. Add source comments. --- desktop/textarea.c | 2 +- desktop/textarea.h | 46 +++++++++++++++++++++------------------------- desktop/tree.c | 5 ++++- 3 files changed, 26 insertions(+), 27 deletions(-) (limited to 'desktop/textarea.h') diff --git a/desktop/textarea.c b/desktop/textarea.c index 3ab8c5af5..9b14773cf 100644 --- a/desktop/textarea.c +++ b/desktop/textarea.c @@ -874,7 +874,7 @@ int textarea_get_caret(struct textarea *ta) /* exported interface, documented in textarea.h */ -void textarea_redraw(struct textarea *ta, int x, int y, +void textarea_redraw(struct textarea *ta, int x, int y, colour bg, const struct rect *clip, const struct redraw_context *ctx) { const struct plotter_table *plot = ctx->plot; diff --git a/desktop/textarea.h b/desktop/textarea.h index a798e7c9f..641d39c73 100644 --- a/desktop/textarea.h +++ b/desktop/textarea.h @@ -37,22 +37,22 @@ typedef enum textarea_flags { } textarea_flags; typedef struct textarea_setup { - textarea_flags flags; + textarea_flags flags; /**< Setup flags */ - int width; - int height; + int width; /**< Textarea width */ + int height; /**< Textarea height */ - int pad_top; - int pad_right; - int pad_bottom; - int pad_left; + int pad_top; /**< Textarea top padding */ + int pad_right; /**< Textarea right padding */ + int pad_bottom; /**< Textarea bottom padding */ + int pad_left; /**< Textarea left padding */ - int border_width; - colour border_col; + int border_width; /**< Textarea border width */ + colour border_col; /**< Textarea border colour */ - colour selected_text; - colour selected_bg; - plot_font_style_t text; + colour selected_text; /**< Textarea selected text colour */ + colour selected_bg; /**< Textarea selection background colour */ + plot_font_style_t text; /**< Font and textarea background colour */ } textarea_setup; @@ -65,13 +65,9 @@ typedef void(*textarea_redraw_request_callback)(void *data, int x, int y, /** * Create a text area * - * \param width width of the text area - * \param height width of the text area - * \param flags text area flags - * \param style font style - * \param redraw_start_callback will be called when textarea wants to redraw - * \param redraw_end_callback will be called when textarea finisjes redrawing - * \param data user specified data which will be passed to redraw callbacks + * \param setup textarea settings and style + * \param redraw_callback will be called when textarea wants to redraw + * \param data user specified data which will be passed to callbacks * \return Opaque handle for textarea or 0 on error */ struct textarea *textarea_create(const textarea_setup *setup, @@ -125,14 +121,14 @@ int textarea_get_caret(struct textarea *ta); /** * Handle redraw requests for text areas * - * \param redraw Redraw request block - * \param x0 left X coordinate of redraw area - * \param y0 top Y coordinate of redraw area - * \param x1 right X coordinate of redraw area - * \param y1 bottom Y coordinate of redraw area + * \param ta textarea to render + * \param x x coordinate of textarea top + * \param y y coordinate of textarea left + * \param bg background colour under textarea + * \param clip clip rectangle * \param ctx current redraw context */ -void textarea_redraw(struct textarea *ta, int x, int y, +void textarea_redraw(struct textarea *ta, int x, int y, colour bg, const struct rect *clip, const struct redraw_context *ctx); /** diff --git a/desktop/tree.c b/desktop/tree.c index df2e9263f..a48b615a0 100644 --- a/desktop/tree.c +++ b/desktop/tree.c @@ -2078,7 +2078,10 @@ void tree_draw(struct tree *tree, int x, int y, y = y + tree->editing->box.y; if (tree->editing->type == NODE_ELEMENT_TEXT_PLUS_ICON) x += NODE_INSTEP; - textarea_redraw(tree->textarea, x, y, &clip, &new_ctx); + textarea_redraw(tree->textarea, x, y, + plot_style_fill_tree_background. + fill_colour, + &clip, &new_ctx); } } -- cgit v1.2.3 From 2b7bc02961a3fa251f58618b73527968cecda8ef Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 13 Jan 2013 23:01:29 +0000 Subject: Implement most of the styling needed for HTML. Allow caret to be hidden. --- desktop/textarea.c | 107 ++++++++++++++++++++++++++++++----------------------- desktop/textarea.h | 2 +- 2 files changed, 62 insertions(+), 47 deletions(-) (limited to 'desktop/textarea.h') diff --git a/desktop/textarea.c b/desktop/textarea.c index 606618c6e..94d9b96c1 100644 --- a/desktop/textarea.c +++ b/desktop/textarea.c @@ -34,18 +34,7 @@ #include "utils/utf8.h" #include "utils/utils.h" -#define MARGIN_LEFT 4 -#define MARGIN_RIGHT 4 #define CARET_COLOR 0x0000FF -/* background color for readonly textarea */ -#define BORDER_COLOR 0x000000 -#define SELECTION_COL 0xFFDDDD - -static plot_style_t pstyle_stroke_border = { - .stroke_type = PLOT_OP_TYPE_SOLID, - .stroke_colour = BORDER_COLOR, - .stroke_width = 1, -}; static plot_style_t pstyle_stroke_caret = { .stroke_type = PLOT_OP_TYPE_SOLID, @@ -245,8 +234,8 @@ static bool textarea_scroll_visible(struct textarea *ta) if (ta->caret_pos.char_off == -1) return false; - x0 = MARGIN_LEFT; - x1 = ta->vis_width - MARGIN_RIGHT; + x0 = ta->border_width + ta->pad_left; + x1 = ta->vis_width - (ta->border_width + ta->pad_left); y0 = 0; y1 = ta->vis_height; @@ -267,8 +256,8 @@ static bool textarea_scroll_visible(struct textarea *ta) if (x < x0) { ta->scroll_x -= x0 - x ; scrolled = true; - } else if (x > x1 - 1) { - ta->scroll_x += x - (x1 - 1); + } else if (x > x1) { + ta->scroll_x += x - x1; scrolled = true; } @@ -291,6 +280,10 @@ static bool textarea_reflow(struct textarea *ta, unsigned int line) int x; char *space, *para_end; unsigned int line_count = 0; + int avail_width = ta->vis_width - 2 * ta->border_width - + ta->pad_left - ta->pad_right; + if (avail_width < 0) + avail_width = 0; /** \todo pay attention to line parameter */ /** \todo create horizontal scrollbar if needed */ @@ -327,8 +320,7 @@ static bool textarea_reflow(struct textarea *ta, unsigned int line) /* Wrap current line in paragraph */ nsfont.font_split(&ta->fstyle, text, para_end - text, - ta->vis_width - MARGIN_LEFT - MARGIN_RIGHT, - &b_off, &x); + avail_width, &b_off, &x); if (b_off == 0) { /* Text wasn't split */ @@ -407,8 +399,8 @@ static void textarea_get_xy_offset(struct textarea *ta, int x, int y, return; } - x = x - MARGIN_LEFT + ta->scroll_x; - y = y + ta->scroll_y; + x = x - ta->border_width - ta->pad_left + ta->scroll_x; + y = y - ta->border_width - ta->pad_top + ta->scroll_y; if (x < 0) x = 0; @@ -668,8 +660,8 @@ struct textarea *textarea_create(const textarea_setup *setup, INTTOFIX((setup->text.size / FONT_SIZE_SCALE))))), F_72)); - ret->caret_pos.line = ret->caret_pos.char_off = 0; - ret->caret_x = MARGIN_LEFT; + ret->caret_pos.line = ret->caret_pos.char_off = -1; + ret->caret_x = 0; ret->caret_y = 0; ret->sel_start = -1; ret->sel_end = -1; @@ -759,7 +751,7 @@ bool textarea_set_caret(struct textarea *ta, int caret) if (ta->flags & TEXTAREA_MULTILINE) { /* Multiline textarea */ - text_y_offset = 0; + text_y_offset = ta->border_width + ta->pad_top; } else { /* Single line text area; text is vertically centered */ text_y_offset = (ta->vis_height - ta->line_height + 1) / 2; @@ -813,7 +805,7 @@ bool textarea_set_caret(struct textarea *ta, int caret) b_off - ta->lines[ta->caret_pos.line].b_start, &x); - x += MARGIN_LEFT; + x += ta->border_width + ta->pad_left; ta->caret_x = x; y = ta->line_height * ta->caret_pos.line; ta->caret_y = y; @@ -827,9 +819,9 @@ bool textarea_set_caret(struct textarea *ta, int caret) /* Just caret moved, redraw it */ x -= ta->scroll_x; y -= ta->scroll_y; - x0 = max(x - 1, MARGIN_LEFT); + x0 = max(x - 1, ta->border_width); y0 = max(y + text_y_offset, 0); - x1 = min(x + 1, ta->vis_width - MARGIN_RIGHT); + x1 = min(x + 1, ta->vis_width - ta->border_width); y1 = min(y + ta->line_height + text_y_offset, ta->vis_height); @@ -852,6 +844,9 @@ int textarea_get_caret(struct textarea *ta) { unsigned int c_off = 0, b_off; + /* Ensure caret isn't hidden */ + if (ta->caret_pos.char_off < 0) + textarea_set_caret(ta, 0); /* if the text is a trailing NUL only */ if (ta->text_utf8_len == 0) @@ -884,7 +879,7 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, .stroke_width = 0, .stroke_colour = NS_TRANSPARENT, .fill_type = PLOT_OP_TYPE_SOLID, - .fill_colour = ta->fstyle.background + .fill_colour = ta->border_col }; r = *clip; @@ -922,15 +917,29 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, r.y1 = y + ta->vis_height; plot->clip(&r); - plot->rectangle(r.x0, r.y0, r.x1, r.y1, &plot_style_fill_bg); - plot->rectangle(x, y, - x + ta->vis_width - 1, y + ta->vis_height - 1, - &pstyle_stroke_border); + if (ta->border_col != NS_TRANSPARENT && + ta->border_width > 0) { + /* Plot border */ + plot->rectangle(x, y, x + ta->vis_width, y + ta->vis_height, + &plot_style_fill_bg); + } + if (ta->fstyle.background != NS_TRANSPARENT) { + /* Plot background */ + plot_style_fill_bg.fill_colour = ta->fstyle.background; + plot->rectangle(x + ta->border_width, y + ta->border_width, + x + ta->vis_width - ta->border_width, + y + ta->vis_height - ta->border_width, + &plot_style_fill_bg); + } - if (r.x0 < x + MARGIN_LEFT) - r.x0 = x + MARGIN_LEFT; - if (r.x1 > x + ta->vis_width - MARGIN_RIGHT) - r.x1 = x + ta->vis_width - MARGIN_RIGHT; + if (r.x0 < x + ta->border_width) + r.x0 = x + ta->border_width; + if (r.x1 > x + ta->vis_width - ta->border_width) + r.x1 = x + ta->vis_width - ta->border_width; + if (r.y0 < y + ta->border_width) + r.y0 = y + ta->border_width; + if (r.y1 > y + ta->vis_width - ta->border_width) + r.y1 = y + ta->vis_height - ta->border_width; if (line0 > 0) c_pos = utf8_bounded_length(ta->text, @@ -938,14 +947,17 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, else c_pos = 0; + text_y_offset = text_y_offset_baseline = ta->border_width; if (ta->flags & TEXTAREA_MULTILINE) { /* Multiline textarea */ - text_y_offset = 0; - text_y_offset_baseline = (ta->line_height * 3 + 2) / 4; + text_y_offset += ta->pad_top; + text_y_offset_baseline += (ta->line_height * 3 + 2) / 4 + + ta->pad_top; } else { /* Single line text area; text is vertically centered */ - text_y_offset = (ta->vis_height - ta->line_height + 1) / 2; - text_y_offset_baseline = (ta->vis_height * 3 + 2) / 4; + int vis_height = ta->vis_height - 2 * ta->border_width; + text_y_offset += (vis_height - ta->line_height + 1) / 2; + text_y_offset_baseline += (vis_height * 3 + 2) / 4; } plot_style_fill_bg.fill_colour = ta->sel_fstyle.background; @@ -956,6 +968,7 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, if (ta->lines[line].b_length == 0) continue; + /* reset clip rectangle */ plot->clip(&r); c_len = utf8_bounded_length( @@ -963,7 +976,7 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, ta->lines[line].b_length); b_end = 0; - right = x + MARGIN_LEFT; + right = x + ta->border_width + ta->pad_left; do { sel_start = ta->sel_start; @@ -1014,9 +1027,9 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, left = right; nsfont.font_width(&ta->fstyle, line_text, b_end, &right); - right += x + MARGIN_LEFT; + right += x + ta->border_width + ta->pad_left; - /* set clip */ + /* set clip rectangle for line part */ s = r; if (s.x0 < left) s.x0 = left; @@ -1036,7 +1049,8 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, } /* draw text */ - plot->text(x + MARGIN_LEFT - ta->scroll_x, + plot->text(x + ta->border_width + ta->pad_left - + ta->scroll_x, y + line * ta->line_height + text_y_offset_baseline - ta->scroll_y, ta->text + ta->lines[line].b_start, @@ -1048,9 +1062,10 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, } while (c_pos < c_pos + c_len); /* if there is a newline between the lines, skip it */ - if (line < ta->line_count - 1 && ta->lines[line + 1].b_start != - ta->lines[line].b_start + - ta->lines[line].b_length) + if (line < ta->line_count - 1 && + ta->lines[line + 1].b_start != + ta->lines[line].b_start + + ta->lines[line].b_length) c_pos++; } @@ -1061,7 +1076,7 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, if (ta->sel_end == -1 || ta->sel_start == ta->sel_end) { /* There is no selection; draw caret */ int caret_y = y + ta->caret_y + text_y_offset; - int caret_height = caret_y + ta->line_height - 1; + int caret_height = caret_y + ta->line_height; plot->line(x + ta->caret_x, caret_y, x + ta->caret_x, caret_height, diff --git a/desktop/textarea.h b/desktop/textarea.h index 641d39c73..7624c3187 100644 --- a/desktop/textarea.h +++ b/desktop/textarea.h @@ -52,7 +52,7 @@ typedef struct textarea_setup { colour selected_text; /**< Textarea selected text colour */ colour selected_bg; /**< Textarea selection background colour */ - plot_font_style_t text; /**< Font and textarea background colour */ + plot_font_style_t text; /**< Textarea background colour and font */ } textarea_setup; -- cgit v1.2.3 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(-) (limited to 'desktop/textarea.h') 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 From 663191791eda7034c3d7d99a4039eca8ba02b441 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Wed, 30 Jan 2013 18:01:01 +0000 Subject: Add move caret msg. Add flag to choose internal caret or caret move msgs. --- atari/toolbar.c | 2 +- desktop/textarea.c | 31 ++++++++++++++++++++++++++----- desktop/textarea.h | 16 ++++++++++++---- desktop/tree.c | 2 +- 4 files changed, 40 insertions(+), 11 deletions(-) (limited to 'desktop/textarea.h') diff --git a/atari/toolbar.c b/atari/toolbar.c index d4feaabfb..cf68194d6 100755 --- a/atari/toolbar.c +++ b/atari/toolbar.c @@ -790,7 +790,7 @@ CMP_TOOLBAR tb_create( struct gui_window * gw ) int ta_height = toolbar_styles[t->style].height; ta_height -= (TOOLBAR_URL_MARGIN_TOP + TOOLBAR_URL_MARGIN_BOTTOM); textarea_setup ta_setup; - ta_setup.flags = TEXTAREA_DEFAULT; + ta_setup.flags = TEXTAREA_INTERNAL_CARET; ta_setup.width = 300; ta_setup.height = ta_height; ta_setup.pad_top = 0; diff --git a/desktop/textarea.c b/desktop/textarea.c index cef2c6c70..2c7b7484d 100644 --- a/desktop/textarea.c +++ b/desktop/textarea.c @@ -1173,6 +1173,7 @@ int textarea_get_caret(struct textarea *ta) void textarea_redraw(struct textarea *ta, int x, int y, colour bg, const struct rect *clip, const struct redraw_context *ctx) { + struct textarea_msg msg; const struct plotter_table *plot = ctx->plot; int line0, line1, line, left, right; int chars, text_y_offset, text_y_offset_baseline; @@ -1383,13 +1384,33 @@ void textarea_redraw(struct textarea *ta, int x, int y, colour bg, if ((ta->sel_end == -1 || ta->sel_start == ta->sel_end) && ta->caret_pos.char_off >= 0) { - /* There is no selection, and caret visible: draw caret */ + /* There is no selection, and caret visible: show caret */ int caret_y = y - ta->scroll_y + ta->caret_y + text_y_offset; - int caret_height = caret_y + ta->line_height; - plot->line(x - ta->scroll_x + ta->caret_x, caret_y, - x - ta->scroll_x + ta->caret_x, caret_height, - &pstyle_stroke_caret); + if (ta->flags & TEXTAREA_INTERNAL_CARET) { + /* Render our own caret */ + plot->line(x - ta->scroll_x + ta->caret_x, caret_y, + x - ta->scroll_x + ta->caret_x, + caret_y + ta->line_height, + &pstyle_stroke_caret); + } else { + /* Tell client where caret should be placed */ + msg.ta = ta; + msg.type = TEXTAREA_MSG_MOVED_CARET; + msg.data.caret.hidden = false; + msg.data.caret.x = x - ta->scroll_x + ta->caret_x; + msg.data.caret.y = caret_y; + msg.data.caret.height = ta->line_height; + + ta->callback(ta->data, &msg); + } + } else if (!(ta->flags & TEXTAREA_INTERNAL_CARET)) { + /* Caret hidden, and client is responsible: tell client */ + msg.ta = ta; + msg.type = TEXTAREA_MSG_MOVED_CARET; + msg.data.caret.hidden = true; + + ta->callback(ta->data, &msg); } if (ta->bar_x != NULL) diff --git a/desktop/textarea.h b/desktop/textarea.h index fb8b13425..6a1a4714d 100644 --- a/desktop/textarea.h +++ b/desktop/textarea.h @@ -34,9 +34,10 @@ struct textarea; /* Text area flags */ typedef enum { - TEXTAREA_DEFAULT = (1 << 0), - TEXTAREA_MULTILINE = (1 << 1), - TEXTAREA_READONLY = (1 << 2) + TEXTAREA_DEFAULT = (1 << 0), /**< Standard input */ + TEXTAREA_MULTILINE = (1 << 1), /**< Multiline area */ + TEXTAREA_READONLY = (1 << 2), /**< Non-editable */ + TEXTAREA_INTERNAL_CARET = (1 << 3) /**< Render own caret */ } textarea_flags; typedef enum { @@ -47,7 +48,8 @@ typedef enum { typedef enum { TEXTAREA_MSG_DRAG_REPORT, /**< Textarea drag start/end report */ - TEXTAREA_MSG_REDRAW_REQUEST /**< Textarea redraw request */ + TEXTAREA_MSG_REDRAW_REQUEST, /**< Textarea redraw request */ + TEXTAREA_MSG_MOVED_CARET /**< Textarea caret moved */ } textarea_msg_type; struct textarea_msg { @@ -57,6 +59,12 @@ struct textarea_msg { union { textarea_drag_type drag; struct rect redraw; + struct { + bool hidden; + int x; + int y; + int height; + } caret; } data; }; diff --git a/desktop/tree.c b/desktop/tree.c index 4f9170d06..959b9870a 100644 --- a/desktop/tree.c +++ b/desktop/tree.c @@ -2972,7 +2972,7 @@ void tree_start_edit(struct tree *tree, struct node_element *element) tree->ta_height = height; - ta_setup.flags = TEXTAREA_DEFAULT; + ta_setup.flags = TEXTAREA_INTERNAL_CARET; ta_setup.width = width; ta_setup.height = tree->ta_height; ta_setup.pad_top = 0; -- cgit v1.2.3