From 8912ba1c8eb9d7796c173933ba87cc8479ddd8fa Mon Sep 17 00:00:00 2001 From: Slava Zanko Date: Tue, 14 Jan 2014 14:57:09 +0300 Subject: [PATCH] Add WScrollBar. Signed-off-by: Slava Zanko --- lib/widget.h | 1 + lib/widget/Makefile.am | 1 + lib/widget/history.c | 15 +++ lib/widget/listbox.c | 45 ------- lib/widget/listbox.h | 1 - lib/widget/scrollbar.c | 285 +++++++++++++++++++++++++++++++++++++++++ lib/widget/scrollbar.h | 44 +++++++ 7 files changed, 346 insertions(+), 46 deletions(-) create mode 100644 lib/widget/scrollbar.c create mode 100644 lib/widget/scrollbar.h diff --git a/lib/widget.h b/lib/widget.h index f5d4eaeb0..d2177b672 100644 --- a/lib/widget.h +++ b/lib/widget.h @@ -31,6 +31,7 @@ typedef struct WDialog WDialog; #include "lib/widget/input.h" #include "lib/widget/listbox-window.h" #include "lib/widget/quick.h" +#include "lib/widget/scrollbar.h" #include "lib/widget/wtools.h" #include "lib/widget/dialog-switch.h" diff --git a/lib/widget/Makefile.am b/lib/widget/Makefile.am index 40058c9de..573e3aa8a 100644 --- a/lib/widget/Makefile.am +++ b/lib/widget/Makefile.am @@ -19,6 +19,7 @@ libmcwidget_la_SOURCES = \ menu.c menu.h \ quick.c quick.h \ radio.c radio.h \ + scrollbar.c scrollbar.h \ widget-common.c widget-common.h \ wtools.c wtools.h diff --git a/lib/widget/history.c b/lib/widget/history.c index 8e4a2113b..940119a0b 100644 --- a/lib/widget/history.c +++ b/lib/widget/history.c @@ -124,6 +124,9 @@ history_dlg_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, v case MSG_RESIZE: return history_dlg_reposition (DIALOG (w)); + case MSG_ACTION: + return dlg_broadcast_msg_to (DIALOG (w), msg, FALSE, 0); + default: return dlg_default_callback (w, sender, msg, parm, data); } @@ -358,6 +361,18 @@ history_show (GList ** history, Widget * widget, int current) listbox_select_entry (query_list, current); } + if (!mc_global.tty.slow_terminal) + { + WScrollBar *scrollbar; + + scrollbar = scrollbar_new (WIDGET (query_list), SCROLLBAR_VERTICAL); + scrollbar_set_current (scrollbar, &query_list->pos); + scrollbar_set_total (scrollbar, &query_list->count); + scrollbar_set_first_displayed (scrollbar, &query_list->top); + + add_widget (query_dlg, scrollbar); + } + if (dlg_run (query_dlg) != B_CANCEL) { char *q; diff --git a/lib/widget/listbox.c b/lib/widget/listbox.c index 1accc76fc..6a5dd4638 100644 --- a/lib/widget/listbox.c +++ b/lib/widget/listbox.c @@ -80,44 +80,6 @@ listbox_entry_free (void *data) /* --------------------------------------------------------------------------------------------- */ -static void -listbox_drawscroll (WListbox * l) -{ - Widget *w = WIDGET (l); - int max_line = w->lines - 1; - int line = 0; - int i; - - /* Are we at the top? */ - widget_move (w, 0, w->cols); - if (l->top == 0) - tty_print_one_vline (TRUE); - else - tty_print_char ('^'); - - /* Are we at the bottom? */ - widget_move (w, max_line, w->cols); - if ((l->top + w->lines == l->count) || (w->lines >= l->count)) - tty_print_one_vline (TRUE); - else - tty_print_char ('v'); - - /* Now draw the nice relative pointer */ - if (l->count != 0) - line = 1 + ((l->pos * (w->lines - 2)) / l->count); - - for (i = 1; i < max_line; i++) - { - widget_move (w, i, w->cols); - if (i != line) - tty_print_one_vline (TRUE); - else - tty_print_char ('*'); - } -} - -/* --------------------------------------------------------------------------------------------- */ - static void listbox_draw (WListbox * l, gboolean focused) { @@ -172,12 +134,6 @@ listbox_draw (WListbox * l, gboolean focused) } l->cursor_y = sel_line; - - if (l->scrollbar && (l->count > w->lines)) - { - tty_setcolor (normalc); - listbox_drawscroll (l); - } } /* --------------------------------------------------------------------------------------------- */ @@ -535,7 +491,6 @@ listbox_new (int y, int x, int height, int width, gboolean deletable, lcback_fn l->deletable = deletable; l->callback = callback; l->allow_duplicates = TRUE; - l->scrollbar = !mc_global.tty.slow_terminal; widget_want_hotkey (w, TRUE); widget_want_cursor (w, FALSE); diff --git a/lib/widget/listbox.h b/lib/widget/listbox.h index eee50b7c9..518eaa021 100644 --- a/lib/widget/listbox.h +++ b/lib/widget/listbox.h @@ -50,7 +50,6 @@ typedef struct WListbox int top; /* The first element displayed */ int count; /* Number of items in the listbox */ gboolean allow_duplicates; /* Do we allow duplicates on the list? */ - gboolean scrollbar; /* Draw a scrollbar? */ gboolean deletable; /* Can list entries be deleted? */ lcback_fn callback; /* The callback function */ int cursor_x, cursor_y; /* Cache the values */ diff --git a/lib/widget/scrollbar.c b/lib/widget/scrollbar.c new file mode 100644 index 000000000..350081e0a --- /dev/null +++ b/lib/widget/scrollbar.c @@ -0,0 +1,285 @@ +/* + Widgets for the Midnight Commander: scrollbar + + Copyright (C) 2014 + The Free Software Foundation, Inc. + + Authors: + Slava Zanko , 2014 + + This file is part of the Midnight Commander. + + The Midnight Commander is free software: you can redistribute it + and/or modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + The Midnight Commander is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +/** \file scrollbar.c + * \brief Source: WScrollBar widget + */ + +#include + +#include +#include + +#include "lib/global.h" + +#include "lib/tty/tty.h" +#include "lib/tty/color.h" +#include "lib/skin.h" +#include "lib/strutil.h" +#include "lib/widget.h" + +/*** global variables ****************************************************************************/ + +/*** file scope macro definitions ****************************************************************/ + +/*** file scope type declarations ****************************************************************/ + +/*** file scope variables ************************************************************************/ + +/* --------------------------------------------------------------------------------------------- */ +/*** file scope functions ************************************************************************/ +/* --------------------------------------------------------------------------------------------- */ + +static void +scrollbar_set_size (WScrollBar *scrollbar) +{ + Widget *w = WIDGET (scrollbar); + Widget *p = scrollbar->parent; + Widget *o = WIDGET (p->owner); + int py = p->y; + int px = p->x; + + /* There folloing cases are possible here: + 1. Parent is in dialog, scrollbar isn't. + Parents coordinates are absolute. Scrollbar's coordinate are relative to owner. + We need relative parent's coordinates here to place scrollbar properly. + 2. Parent and scrollbar are in dialog. + Parent's and scrollbar's coordinates are absolute. Use them. + 3. Parent and scrollbar aren't in dialog. + Parent's and scrollbar's coordinates are relative to owner. Use them. + 4. Parent isn't in dialog, scrollbar is. + This is abnormal and should not happen. */ + + if (o != NULL && w->owner == NULL) + { + /* Get relative parent's coordinates */ + py -= o->y; + px -= o->x; + } + + switch (scrollbar->type) + { + case SCROLLBAR_VERTICAL: + w->y = py; + w->x = px + p->cols; + w->lines = p->lines; + w->cols = 1; + break; + + default: + w->x = px; + w->y = py + p->lines; + w->cols = p->cols; + w->lines = 1; + break; + } +} + +/* --------------------------------------------------------------------------------------------- */ + +static void +scrollbar_draw_horizontal (WScrollBar * scrollbar) +{ + Widget *w = WIDGET (scrollbar); + int column = 0; + int i; + + /* Now draw the nice relative pointer */ + if (*scrollbar->total != 0) + column = *scrollbar->current * w->cols / *scrollbar->total; + + for (i = 0; i < w->cols; i++) + { + widget_move (w, 0, i); + if (i != column) + tty_print_char ('!'); + else + tty_print_char ('+'); + } +} + +/* --------------------------------------------------------------------------------------------- */ + +static void +scrollbar_draw_vertical (WScrollBar * scrollbar) +{ + Widget *w = WIDGET (scrollbar); + int line = 0; + int i; + + /* Now draw the nice relative pointer */ + if (*scrollbar->total != 0) + line = *scrollbar->current * w->lines / *scrollbar->total; + + for (i = 0; i < w->lines; i++) + { + widget_move (w, i, 0); + if (i != line) + tty_print_char ('|'); + else + tty_print_char ('+'); + } +} + +/* --------------------------------------------------------------------------------------------- */ + +static void +scrollbar_draw (WScrollBar * scrollbar) +{ + // const gboolean disabled = (scrollbar->parent->options & W_DISABLED) != 0; + // const int normalc = disabled ? DISABLED_COLOR : scrollbar->parent->color[DLG_COLOR_NORMAL]; + const int normalc = DISABLED_COLOR; + + if (*scrollbar->total <= scrollbar->parent->lines) + return; + + tty_setcolor (normalc); + + switch (scrollbar->type) + { + case SCROLLBAR_VERTICAL: + scrollbar_draw_vertical (scrollbar); + break; + default: + scrollbar_draw_horizontal (scrollbar); + } +} + +/* --------------------------------------------------------------------------------------------- */ + +static cb_ret_t +scrollbar_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data) +{ + WScrollBar *scrollbar = SCROLLBAR (w); + cb_ret_t ret = MSG_HANDLED; + + switch (msg) + { + case MSG_INIT: +// w->pos_flags = WPOS_KEEP_RIGHT | WPOS_KEEP_BOTTOM; + return MSG_HANDLED; + + case MSG_RESIZE: + scrollbar_set_size (scrollbar); + return MSG_HANDLED; + + case MSG_FOCUS: + return MSG_NOT_HANDLED; + + case MSG_ACTION: + ret = MSG_NOT_HANDLED; + + case MSG_DRAW: + scrollbar_draw (scrollbar); + return ret; + + case MSG_DESTROY: + return MSG_HANDLED; + + default: + return widget_default_callback (w, sender, msg, parm, data); + } +} + +/* --------------------------------------------------------------------------------------------- */ +/*** public functions ****************************************************************************/ +/* --------------------------------------------------------------------------------------------- */ +/** + * Create new WScrollBar object. + * + * @param parent parent widget + * @param type type of scrollbar (vertical or horizontal) + * @return new WScrollBar object + */ + +WScrollBar * +scrollbar_new (Widget * parent, scrollbar_type_t type) +{ + WScrollBar *scrollbar; + Widget *widget; + + scrollbar = g_new (WScrollBar, 1); + scrollbar->type = type; + + widget = WIDGET (scrollbar); + widget_init (widget, 1, 1, 1, 1, scrollbar_callback, NULL); + + scrollbar->parent = parent; + scrollbar_set_size (scrollbar); + + widget_want_cursor (widget, FALSE); + widget_want_hotkey (widget, FALSE); + + return scrollbar; +} + +/* --------------------------------------------------------------------------------------------- */ +/** + * Set total count of items. + * + * @param scrollbar WScrollBar object + * @param total total count of items + */ + +void +scrollbar_set_total (WScrollBar * scrollbar, int *total) +{ + if (scrollbar != NULL) + scrollbar->total = total; +} + +/* --------------------------------------------------------------------------------------------- */ + +/** + * Set current position of item. + * + * @param scrollbar WScrollBar object + * @param current current position of item + */ + +void +scrollbar_set_current (WScrollBar * scrollbar, int *current) +{ + if (scrollbar != NULL) + scrollbar->current = current; +} + +/* --------------------------------------------------------------------------------------------- */ + +/** + * Set position of first displayed item. + * + * @param scrollbar WScrollBar object + * @param first_displayed position of first displayed item + */ + +void +scrollbar_set_first_displayed (WScrollBar * scrollbar, int *first_displayed) +{ + if (scrollbar != NULL) + scrollbar->first_displayed = first_displayed; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/lib/widget/scrollbar.h b/lib/widget/scrollbar.h new file mode 100644 index 000000000..3dcf79f13 --- /dev/null +++ b/lib/widget/scrollbar.h @@ -0,0 +1,44 @@ + +/** \file scrollbar.h + * \brief Header: WScrollBar widget + */ + +#ifndef MC__WIDGET_SCROLLBAR_H +#define MC__WIDGET_SCROLLBAR_H + +/*** typedefs(not structures) and defined constants **********************************************/ + +#define SCROLLBAR(x) ((WScrollBar *)(x)) + +/*** enums ***************************************************************************************/ + +typedef enum +{ + SCROLLBAR_VERTICAL, + SCROLLBAR_HORISONTAL +} scrollbar_type_t; + +/*** structures declarations (and typedefs of structures)*****************************************/ + +typedef struct +{ + Widget widget; + scrollbar_type_t type; + int *total; + int *current; + int *first_displayed; + Widget *parent; +} WScrollBar; + +/*** global variables defined in .c file *********************************************************/ + +/*** declarations of public functions ************************************************************/ + +WScrollBar *scrollbar_new (Widget * parent, scrollbar_type_t type); +void scrollbar_set_total (WScrollBar * scrollbar, int *total); +void scrollbar_set_current (WScrollBar * scrollbar, int *current); +void scrollbar_set_first_displayed (WScrollBar * scrollbar, int *first_displayed); + +/*** inline functions ****************************************************************************/ + +#endif /* MC__WIDGET_SCROLLBAR_H */