quakeforge/ruamoko/qwaq/ui/scrollbar.r

228 lines
4.5 KiB
R
Raw Normal View History

2020-03-30 11:29:48 +00:00
#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;
}
buffer = [[DrawBuffer buffer:size] retain];
objects = [[Group withContext:buffer owner:self] retain];
2020-03-30 11:29:48 +00:00
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)];
2020-03-30 11:29:48 +00:00
thumbPos = {0, 1};
thumbSel = @selector(verticalSlide);
growMode &= ~gfGrowLoY;
} else {
[icons[0] addch:acs_char (ACS_LARROW)];
[icons[1] addch:acs_char (ACS_RARROW)];
2020-03-30 11:29:48 +00:00
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;
}
-(void)dealloc
{
[objects release];
[buffer release];
[onScroll release];
}
2020-03-30 11:29:48 +00:00
+(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
{
syncprintf("scrollbar start");
2020-03-30 11:29:48 +00:00
if (vertical) {
[self mvvline:pos, bgchar, ylen];
} else {
[self mvhline:pos, bgchar, xlen];
}
[super draw];
[objects draw];
[textContext blitFromBuffer:buffer to:pos from:[buffer rect]];
syncprintf("scrollbar end");
2020-03-30 11:29:48 +00:00
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