[qwaq] Add a scrollbar view

This commit is contained in:
Bill Currie 2020-03-30 20:29:48 +09:00
parent dff0fd983c
commit 5bc57518b7
8 changed files with 332 additions and 0 deletions

View file

@ -40,6 +40,7 @@ qwaq_app_dat_src= \
ui/listener.r \
ui/proxyview.r \
ui/rect.r \
ui/scrollbar.r \
ui/textcontext.r \
ui/titlebar.r \
ui/view.r \

View file

@ -85,6 +85,7 @@ typedef enum qwaq_commands_e {
qwaq_cmd_wresize,
qwaq_cmd_resizeterm,
qwaq_cmd_mvwhline,
qwaq_cmd_mvwvline,
} qwaq_commands;
static const char *qwaq_command_names[]= {
@ -118,6 +119,7 @@ static const char *qwaq_command_names[]= {
"wresize",
"resizeterm",
"mvwhline"
"mvwvline"
};
static window_t *
@ -615,6 +617,19 @@ cmd_mvwhline (qwaq_resources_t *res)
mvwhline (window->win, y, x, ch, n);
}
static void
cmd_mvwvline (qwaq_resources_t *res)
{
int window_id = RB_PEEK_DATA (res->command_queue, 2);
int x = RB_PEEK_DATA (res->command_queue, 3);
int y = RB_PEEK_DATA (res->command_queue, 4);
int ch = RB_PEEK_DATA (res->command_queue, 5);
int n = RB_PEEK_DATA (res->command_queue, 6);
window_t *window = get_window (res, __FUNCTION__, window_id);
mvwvline (window->win, y, x, ch, n);
}
static void
dump_command (qwaq_resources_t *res, int len)
{
@ -757,6 +772,9 @@ process_commands (qwaq_resources_t *res)
case qwaq_cmd_mvwhline:
cmd_mvwhline (res);
break;
case qwaq_cmd_mvwvline:
cmd_mvwvline (res);
break;
}
pthread_mutex_lock (&res->command_cond.mut);
RB_DROP_DATA (res->command_queue, len);
@ -1109,6 +1127,33 @@ bi_mvwhline (progs_t *pr)
qwaq_mvwhline (pr, window_id, x, y, ch, n);
}
static void
qwaq_mvwvline (progs_t *pr, int window_id, int x, int y, int ch, int n)
{
qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq");
if (get_window (res, __FUNCTION__, window_id)) {
int command[] = {
qwaq_cmd_mvwvline, 0,
window_id, x, y, ch, n
};
command[1] = CMD_SIZE(command);
qwaq_submit_command (res, command);
}
}
static void
bi_mvwvline (progs_t *pr)
{
int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window;
int x = P_INT (pr, 1);
int y = P_INT (pr, 2);
int ch = P_INT (pr, 3);
int n = P_INT (pr, 4);
qwaq_mvwvline (pr, window_id, x, y, ch, n);
}
static void
qwaq_mvwaddstr (progs_t *pr, int window_id, int x, int y, const char *str)
{
@ -1821,6 +1866,18 @@ bi_i_TextContext__mvhline_ (progs_t *pr)
qwaq_mvwhline (pr, window_id, pos->x, pos->y, ch, n);
}
static void
bi_i_TextContext__mvvline_ (progs_t *pr)
{
__auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0);
int window_id = self->window;
__auto_type pos = &P_PACKED (pr, Point, 2);
int ch = P_INT (pr, 3);
int n = P_INT (pr, 4);
qwaq_mvwvline (pr, window_id, pos->x, pos->y, ch, n);
}
static void
bi_qwaq_clear (progs_t *pr, void *data)
{
@ -1875,6 +1932,7 @@ static builtin_t builtins[] = {
{"wresize", bi_wresize, -1},
{"resizeterm", bi_resizeterm, -1},
{"mvwhline", bi_mvwhline, -1},
{"mvwvline", bi_mvwvline, -1},
{"_c_TextContext__is_initialized", bi_c_TextContext__is_initialized, -1},
{"_c_TextContext__max_colors", bi_c_TextContext__max_colors, -1},
@ -1900,6 +1958,7 @@ static builtin_t builtins[] = {
{"_i_TextContext__scrollok_", bi_i_TextContext__scrollok_, -1},
{"_i_TextContext__border_", bi_i_TextContext__border_, -1},
{"_i_TextContext__mvhline_", bi_i_TextContext__mvhline_, -1},
{"_i_TextContext__mvvline_", bi_i_TextContext__mvvline_, -1},
{0}
};

View file

@ -30,6 +30,8 @@
- (void) mvvprintf: (Point) pos, string fmt, @va_list args;
- (void) mvaddch: (Point) pos, int ch;
- (void) mvaddstr: (Point) pos, string str;
- (void) mvhline:(Point)pos, int ch, int len;
- (void) mvvline:(Point)pos, int ch, int len;
@end
@interface DrawBuffer : Object <DrawBuffer, TextContext>

View file

@ -248,4 +248,20 @@
[self addstr: str];
}
- (void) mvhline:(Point)pos, int ch, int len
{
while (len-- > 0) {
[self mvaddch:pos, ch];
pos.x++;
}
}
- (void) mvvline:(Point)pos, int ch, int len
{
while (len-- > 0) {
[self mvaddch:pos, ch];
pos.y++;
}
}
@end

View file

@ -0,0 +1,35 @@
#ifndef __qwaq_ui_scrollbar_h
#define __qwaq_ui_scrollbar_h
#include "ui/view.h"
@class Button;
@class Group;
@class ListenerGroup;
@interface ScrollBar : View
{
int vertical;
int bgchar;
Point mouseStart;
Button *backButton;
Button *forwardButton;
Button *thumbTab;
Group *objects;
ListenerGroup *onScroll;
unsigned pageStep;
unsigned singleStep;
unsigned range;
unsigned index;
}
+(ScrollBar *)horizontal:(unsigned)len at:(Point)pos;
+(ScrollBar *)vertical:(unsigned)len at:(Point)pos;
-(ListenerGroup *)onScroll;
-setRange:(unsigned)range;
-setPageStep:(unsigned)pageStep;
-setSingleStep:(unsigned)singleStep;
-setIndex:(unsigned)index;
@end
#endif//__qwaq_ui_scrollbar_h

216
ruamoko/qwaq/ui/scrollbar.r Normal file
View file

@ -0,0 +1,216 @@
#include "ui/button.h"
#include "ui/group.h"
#include "ui/listener.h"
#include "ui/scrollbar.h"
@implementation ScrollBar
-initWithRect:(Rect)rect
{
if (!(self = [super initWithRect:rect])) {
return nil;
}
objects = [[Group withContext:textContext owner:self] retain];
onScroll = [[ListenerGroup listener] retain];
vertical = xlen == 1;
DrawBuffer *icons[3] = {
[DrawBuffer buffer:{1, 1}],
[DrawBuffer buffer:{1, 1}],
[DrawBuffer buffer:{1, 1}],
};
[icons[2] addch:acs_char (ACS_DIAMOND)];
Point thumbPos;
SEL thumbSel;
growMode = gfGrowAll;
if (vertical) {
[icons[0]addch:acs_char (ACS_UARROW)];
[icons[1]addch:acs_char (ACS_DARROW)];
thumbPos = {0, 1};
thumbSel = @selector(verticalSlide);
growMode &= ~gfGrowLoY;
} else {
[icons[0]addch:acs_char (ACS_LARROW)];
[icons[1]addch:acs_char (ACS_RARROW)];
thumbPos = {1, 0};
thumbSel = @selector(horizontalSlide);
growMode &= ~gfGrowLoX;
}
bgchar = acs_char (ACS_CKBOARD);
backButton = [Button withPos:{0, 0}
releasedIcon:icons[0] pressedIcon:icons[0]];
forwardButton = [Button withPos:{xlen - 1, ylen - 1}
releasedIcon:icons[1] pressedIcon:icons[1]];
thumbTab = [Button withPos:thumbPos
releasedIcon:icons[2] pressedIcon:icons[2]];
[[backButton onPress] addListener:self :@selector(scrollBack:)];
[[forwardButton onPress] addListener:self :@selector(scrollForward:)];
[[thumbTab onPress] addListener:self :thumbSel];
singleStep = 1;
[objects insert:backButton];
[objects insert:forwardButton];
[objects insert:thumbTab];
return self;
}
+(ScrollBar *)horizontal:(unsigned)len at:(Point)pos
{
if (len == 1) {
[self error:"can't make scrollbar of length 1"];
}
return [[[self alloc] initWithRect:{pos, {len, 1}}] autorelease];
}
+(ScrollBar *)vertical:(unsigned)len at:(Point)pos
{
if (len == 1) {
[self error:"can't make scrollbar of length 1"];
}
return [[[self alloc] initWithRect:{pos, {1, len}}] autorelease];
}
-(ListenerGroup *)onScroll
{
return onScroll;
}
-draw
{
if (vertical) {
[self mvvline:pos, bgchar, ylen];
} else {
[self mvhline:pos, bgchar, xlen];
}
[super draw];
[objects draw];
return self;
}
static void
position_tab (ScrollBar *self)
{
Point p = {0, 0};
Point o = [self.thumbTab origin];
if (self.range > 0) {
if (self.vertical) {
p.y = 1 + self.index * (self.ylen - 2) / (self.range - 1);
} else {
p.x = 1 + self.index * (self.xlen - 2) / (self.range - 1);
}
}
[self.thumbTab move:{p.x - o.x, p.y - o.y}];
}
-resize:(Extent)delta
{
Extent size = self.size;
[super resize:delta];
delta = {self.size.width - size.width, self.size.height - size.height};
[objects resize:delta];
position_tab (self);
return self;
}
-page:(unsigned)step dir:(unsigned) dir
{
unsigned oind = index;
if (dir) {
if (range - 1 - index < step) {
step = range - 1 - index;
}
index += step;
} else {
if (index < step) {
step = index;
}
index -= step;
}
if (index != oind) {
position_tab (self);
[onScroll respond:self];
}
return self;
}
static void
page (ScrollBar *self, Point pos)
{
unsigned pageDir = 0;
if (self.vertical) {
if (pos.y < [self.thumbTab origin].y) {
pageDir = 0;
} else {
pageDir = 1;
}
} else {
if (pos.x < [self.thumbTab origin].x) {
pageDir = 0;
} else {
pageDir = 1;
}
}
[self page:self.pageStep dir:pageDir];
}
-(void)scrollBack:(id)sender
{
[self page:singleStep dir:0];
}
-(void)scrollForward:(id)sender
{
[self page:singleStep dir:1];
}
-handleEvent:(qwaq_event_t *)event
{
[super handleEvent: event];
[objects handleEvent: event];
if (event.what == qe_mousedown) {
[self grabMouse];
mouseStart = {event.mouse.x, event.mouse.y};
page(self, mouseStart);
event.what = qe_none;
} else if (event.what==qe_mouseauto) {
page(self, mouseStart);
event.what = qe_none;
} else if (event.what == qe_mouseup) {
[self releaseMouse];
event.what = qe_none;
}
return self;
}
-setRange:(unsigned)range
{
self.range = range;
return self;
}
-setPageStep:(unsigned)pageStep
{
self.pageStep = pageStep;
return self;
}
-setSingleStep:(unsigned)singleStep
{
self.singleStep = singleStep;
return self;
}
-setIndex:(unsigned)index
{
if (index > self.index) {
[self page:index - self.index dir:1];
} else {
[self page:self.index - index dir:0];
}
return self;
}
@end

View file

@ -55,6 +55,7 @@
- (void) scrollok: (int) flag;
- (void) border: (box_sides_t) sides, box_corners_t corners;
- (void) mvhline: (Point) pos, int ch, int n;
- (void) mvvline: (Point) pos, int ch, int n;
-clearReact: (Rect) rect;
@end

View file

@ -163,6 +163,7 @@ static TextContext *screen;
- (void) mvaddch: (Point) pos, int ch = #0;
- (void) mvaddstr: (Point) pos, string str = #0;
- (void) mvhline: (Point) pos, int ch, int n = #0;
- (void) mvvline: (Point) pos, int ch, int n = #0;
- (void) resizeTo: (Extent) newSize = #0; // absolute size
- (void) refresh = #0;
@ -218,5 +219,6 @@ void wresize (window_t window, int width, int height) = #0;
void resizeterm (int width, int height) = #0;
Rect getwrect (window_t window) = #0;
void mvwhline (window_t win, int x, int y, int ch, int n) = #0;
void mvwvline (window_t win, int x, int y, int ch, int n) = #0;
void printf(string fmt, ...) = #0;