Add WScrollBar.

Signed-off-by: Slava Zanko <slavazanko@gmail.com>
This commit is contained in:
Slava Zanko 2014-01-14 14:57:09 +03:00
parent d84b98af3b
commit 8912ba1c8e
7 changed files with 346 additions and 46 deletions

View File

@ -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"

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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 */

285
lib/widget/scrollbar.c Normal file
View File

@ -0,0 +1,285 @@
/*
Widgets for the Midnight Commander: scrollbar
Copyright (C) 2014
The Free Software Foundation, Inc.
Authors:
Slava Zanko <slavazanko@gmail.com>, 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 <http://www.gnu.org/licenses/>.
*/
/** \file scrollbar.c
* \brief Source: WScrollBar widget
*/
#include <config.h>
#include <stdlib.h>
#include <string.h>
#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;
}
/* --------------------------------------------------------------------------------------------- */

44
lib/widget/scrollbar.h Normal file
View File

@ -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 */