From a2fdf8997f2b7c45050dccf001c5e4f06671bd8c Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Thu, 21 Jul 2011 14:07:59 +0400 Subject: [PATCH] Allow move and resize edit window using mouse. Left click on the top line and drag to move. Left click on bottom-right corner and drag to resize. Signed-off-by: Andrew Borodin --- src/editor/edit.c | 1 + src/editor/editdraw.c | 7 +- src/editor/editwidget.c | 239 +++++++++++++++++++++++++++------------- src/editor/editwidget.h | 15 +++ 4 files changed, 186 insertions(+), 76 deletions(-) diff --git a/src/editor/edit.c b/src/editor/edit.c index 28222adcf..8f121faa2 100644 --- a/src/editor/edit.c +++ b/src/editor/edit.c @@ -2264,6 +2264,7 @@ edit_init (WEdit * edit, int y, int x, int lines, int cols, const vfs_path_t * f } edit_purge_widget (edit); + edit->drag_state = MCEDIT_DRAG_NORMAL; edit->widget.y = y; edit->widget.x = x; edit->widget.lines = lines; diff --git a/src/editor/editdraw.c b/src/editor/editdraw.c index 0ed019a66..c7aa763cd 100644 --- a/src/editor/editdraw.c +++ b/src/editor/editdraw.c @@ -795,12 +795,15 @@ render_edit_text (WEdit * edit, long start_row, long start_column, long end_row, static inline void edit_render (WEdit * edit, int page, int row_start, int col_start, int row_end, int col_end) { + gboolean completely = (edit->force & REDRAW_COMPLETELY) != 0; + if (page) /* if it was an expose event, 'page' would be set */ edit->force |= REDRAW_PAGE | REDRAW_IN_BOUNDS; - if (edit->force & REDRAW_COMPLETELY) - buttonbar_redraw (find_buttonbar (edit->widget.owner)); render_edit_text (edit, row_start, col_start, row_end, col_end); + + if (completely) + buttonbar_redraw (find_buttonbar (edit->widget.owner)); /* * edit->force != 0 means a key was pending and the redraw * was halted, so next time we must redraw everything in case stuff diff --git a/src/editor/editwidget.c b/src/editor/editwidget.c index b4e0d19bf..81cec81ca 100644 --- a/src/editor/editwidget.c +++ b/src/editor/editwidget.c @@ -71,7 +71,6 @@ static cb_ret_t edit_callback (Widget * w, widget_msg_t msg, int parm); - /* --------------------------------------------------------------------------------------------- */ static char * @@ -124,6 +123,8 @@ edit_event (Gpm_Event * event, void *data) if (!mouse_global_in_widget (event, w)) return MOU_UNHANDLED; + local = mouse_get_local (event, w); + /* Unknown event type */ if ((event->type & (GPM_DOWN | GPM_DRAG | GPM_UP)) == 0) return MOU_NORMAL; @@ -131,88 +132,176 @@ edit_event (Gpm_Event * event, void *data) edit_update_curs_row (edit); edit_update_curs_col (edit); - local = mouse_get_local (event, w); - - /* Double click */ - if ((local.type & (GPM_DOUBLE | GPM_UP)) == (GPM_UP | GPM_DOUBLE)) + if (!EDIT_WITH_FRAME || (local.buttons & GPM_B_LEFT) == 0 || (local.type & GPM_UP) != 0) + edit->drag_state = MCEDIT_DRAG_NORMAL; + else if (local.y == 1 && edit->drag_state != MCEDIT_DRAG_RESIZE) { - edit_mark_current_word_cmd (edit); - goto update; + /* click on the top line (move) */ + + /* start move; save x coordinate of mouse */ + if ((local.type & GPM_DOWN) != 0) + edit->drag_state_start = local.x; + + /* moving */ + if ((local.type & (GPM_DOWN | GPM_DRAG)) != 0) + edit->drag_state = MCEDIT_DRAG_MOVE; } + else if (local.y == w->lines && local.x == w->cols) + { + /* click on bottom-right corner (resize) */ + if ((local.type & (GPM_DOWN | GPM_DRAG)) != 0) + edit->drag_state = MCEDIT_DRAG_RESIZE; + } + + if (edit->drag_state == MCEDIT_DRAG_NORMAL) + { + gboolean done = TRUE; + + /* Double click */ + if ((local.type & (GPM_DOUBLE | GPM_UP)) == (GPM_UP | GPM_DOUBLE)) + { + edit_mark_current_word_cmd (edit); + goto update; + } #if 0 - /* Triple click */ - if ((local.type & (GPM_TRIPLE | GPM_UP)) == (GPM_UP | GPM_TRIPLE)) - { - edit_mark_current_line_cmd (edit); - goto update; - } + /* Triple click */ + if ((local.type & (GPM_TRIPLE | GPM_UP)) == (GPM_UP | GPM_TRIPLE)) + { + edit_mark_current_line_cmd (edit); + goto update; + } #endif - /* Wheel events */ - if ((local.buttons & GPM_B_UP) != 0 && (local.type & GPM_DOWN) != 0) - { - edit_move_up (edit, 2, 1); - goto update; - } - if ((local.buttons & GPM_B_DOWN) != 0 && (local.type & GPM_DOWN) != 0) - { - edit_move_down (edit, 2, 1); - goto update; - } - - /* A lone up mustn't do anything */ - if (edit->mark2 != -1 && (local.type & (GPM_UP | GPM_DRAG)) != 0) - return MOU_NORMAL; - - if ((local.type & (GPM_DOWN | GPM_UP)) != 0) - edit_push_key_press (edit); - - if (EDIT_WITH_FRAME) - { - local.y--; - local.x--; - } - - if (!option_cursor_beyond_eol) - edit->prev_col = local.x - edit->start_col - option_line_state_width - 1; - else - { - long line_len = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0, - edit_eol (edit, edit->curs1)); - - if (local.x > line_len) + /* Wheel events */ + if ((local.buttons & GPM_B_UP) != 0 && (local.type & GPM_DOWN) != 0) { - edit->over_col = local.x - line_len - edit->start_col - option_line_state_width - 1; - edit->prev_col = line_len; + edit_move_up (edit, 2, 1); + goto update; } - else + if ((local.buttons & GPM_B_DOWN) != 0 && (local.type & GPM_DOWN) != 0) { - edit->over_col = 0; - edit->prev_col = local.x - option_line_state_width - edit->start_col - 1; + edit_move_down (edit, 2, 1); + goto update; } - } - if (local.y > (edit->curs_row + 1)) - edit_move_down (edit, local.y - (edit->curs_row + 1), 0); - else if (local.y < (edit->curs_row + 1)) - edit_move_up (edit, (edit->curs_row + 1) - local.y, 0); + /* continue handle current event */ + goto cont; + + /* handle DRAG mouse event, don't use standard way to continue + * event handling outside of widget */ + do + { + int c; + + c = tty_get_event (event, FALSE, TRUE); + if (c == EV_NONE || c != EV_MOUSE) + break; + + local = mouse_get_local (event, w); + + cont: + /* A lone up mustn't do anything */ + if (edit->mark2 != -1 && (local.type & (GPM_UP | GPM_DRAG)) != 0) + return MOU_NORMAL; + + if ((local.type & (GPM_DOWN | GPM_UP)) != 0) + edit_push_key_press (edit); + + local.x--; + if (!option_cursor_beyond_eol) + edit->prev_col = local.x - edit->start_col - option_line_state_width - 1; + else + { + long line_len = edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0, + edit_eol (edit, edit->curs1)); + + if (local.x > line_len) + { + edit->over_col = + local.x - line_len - edit->start_col - option_line_state_width - 1; + edit->prev_col = line_len; + } + else + { + edit->over_col = 0; + edit->prev_col = local.x - option_line_state_width - edit->start_col - 1; + } + } + + if (EDIT_WITH_FRAME) + local.y--; + if (local.y > (edit->curs_row + 1)) + edit_move_down (edit, local.y - (edit->curs_row + 1), 0); + else if (local.y < (edit->curs_row + 1)) + edit_move_up (edit, (edit->curs_row + 1) - local.y, 0); + else + edit_move_to_prev_col (edit, edit_bol (edit, edit->curs1)); + + if ((local.type & GPM_DOWN) != 0) + { + edit_mark_cmd (edit, 1); /* reset */ + edit->highlight = 0; + } + + done = (local.type & GPM_DRAG) == 0; + if (done) + edit_mark_cmd (edit, 0); + + update: + edit_find_bracket (edit); + edit->force |= REDRAW_COMPLETELY; + edit_update_curs_row (edit); + edit_update_curs_col (edit); + edit_update_screen (edit); + } + while (EDIT_WITH_FRAME && !done); + } else - edit_move_to_prev_col (edit, edit_bol (edit, edit->curs1)); + while (edit->drag_state != MCEDIT_DRAG_NORMAL) + { + int c; - if ((local.type & GPM_DOWN) != 0) - { - edit_mark_cmd (edit, 1); /* reset */ - edit->highlight = 0; - } + c = tty_get_event (event, FALSE, TRUE); - if ((local.type & GPM_DRAG) == 0) - edit_mark_cmd (edit, 0); + if (c == EV_NONE || c != EV_MOUSE) + { + /* redraw frame */ + edit->drag_state = MCEDIT_DRAG_NORMAL; + edit->force |= REDRAW_COMPLETELY; + edit_update_screen (edit); + } + else + { + Dlg_head *h = w->owner; - update: - edit_find_bracket (edit); - edit->force |= REDRAW_COMPLETELY; - edit_update_curs_row (edit); - edit_update_curs_col (edit); - edit_update_screen (edit); + if (edit->drag_state == MCEDIT_DRAG_MOVE) + { + int y = event->y - 1; + int x = event->x - 1; + + y = max (y, h->y + 1); /* status line */ + y = min (y, h->y + h->lines - 2); /* buttonbar */ + x = max (x, h->x); + x = min (x, h->x + h->cols - 1); + /* don't use widget_set_size() here to avoid double draw */ + w->y = y; + w->x = x - edit->drag_state_start; + edit->force |= REDRAW_PAGE; + } + else if (edit->drag_state == MCEDIT_DRAG_RESIZE) + { + event->y = min (event->y, h->y + h->lines - 1); /* buttonbar */ + event->x = min (event->x, h->x + h->cols); + local = mouse_get_local (event, w); + + /* don't use widget_set_size() here to avoid double draw */ + w->lines = max (2 + 2, local.y); + w->cols = max (2 + LINE_STATE_WIDTH, local.x); + edit->force |= REDRAW_COMPLETELY; + } + + dlg_redraw (h); + } + } return MOU_NORMAL; } @@ -282,7 +371,6 @@ edit_dialog_callback (Dlg_head * h, Widget * sender, dlg_msg_t msg, int parm, vo widget_set_size (&buttonbar->widget, h->lines - 1, h->x, 1, h->cols); widget_set_size (&menubar->widget, h->y, h->x, 1, h->cols); menubar_arrange (menubar); - widget_set_size (&edit->widget, h->y + 1, h->x, h->lines - 2, h->cols); return MSG_HANDLED; case DLG_ACTION: @@ -444,9 +532,12 @@ edit_update_screen (WEdit * e) edit_status (e); else { - /* draw a frame around edit area */ - tty_setcolor (EDITOR_NORMAL_COLOR); - tty_draw_box (e->widget.y, e->widget.x, e->widget.lines, e->widget.cols, TRUE); + if ((e->force & REDRAW_COMPLETELY) != 0) + { + /* draw a frame around edit area */ + tty_setcolor (EDITOR_NORMAL_COLOR); + tty_draw_box (e->widget.y, e->widget.x, e->widget.lines, e->widget.cols, TRUE); + } edit_info_status (e); } diff --git a/src/editor/editwidget.h b/src/editor/editwidget.h index 3732f70a4..2c45f0e84 100644 --- a/src/editor/editwidget.h +++ b/src/editor/editwidget.h @@ -45,9 +45,24 @@ struct syntax_rule unsigned char border; }; +/* + * State of WEdit window + * MCEDIT_DRAG_NORMAL - window is in normal mode + * MCEDIT_DRAG_MOVE - window is being moved + * MCEDIT_DRAG_RESIZE - window is being resized + */ +typedef enum +{ + MCEDIT_DRAG_NORMAL = 0, + MCEDIT_DRAG_MOVE, + MCEDIT_DRAG_RESIZE +} mcedit_drag_state_t; + struct WEdit { Widget widget; + mcedit_drag_state_t drag_state; + int drag_state_start; /* save cursor position before window moving */ vfs_path_t *filename_vpath; /* Name of the file */ vfs_path_t *dir_vpath; /* NULL if filename is absolute */