quakeforge/ruamoko/qwaq/ui/scrollbar.r

267 lines
5.1 KiB
R
Raw Normal View History

#include "ruamoko/qwaq/ui/button.h"
#include "ruamoko/qwaq/ui/group.h"
#include "ruamoko/qwaq/ui/listener.h"
#include "ruamoko/qwaq/ui/scrollbar.h"
2020-03-30 11:29:48 +00:00
@implementation ScrollBar
-initWithRect:(Rect)rect
{
if (!(self = [super initWithRect:rect])) {
return nil;
}
options = ofRelativeEvents;
buffer = [[DrawBuffer buffer:size] retain];
objects = [[Group withContext:buffer owner:self] retain];
onScrollBarModified = [[ListenerGroup listener] retain];
2020-03-30 11:29:48 +00:00
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:);
2020-03-30 11:29:48 +00:00
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:);
2020-03-30 11:29:48 +00:00
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]];
[forwardButton setGrowMode:gfGrowAll];
[[backButton onClick] addListener:self :@selector(scrollBack:)];
[[forwardButton onClick] addListener:self :@selector(scrollForward:)];
2020-03-30 11:29:48 +00:00
[[thumbTab onPress] addListener:self :thumbSel];
singleStep = 1;
[objects insert:backButton];
[objects insert:forwardButton];
[objects insert:thumbTab];
return self;
}
-(void)dealloc
{
[objects release];
[buffer release];
[onScrollBarModified release];
[super dealloc];
}
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 *)onScrollBarModified
2020-03-30 11:29:48 +00:00
{
return onScrollBarModified;
2020-03-30 11:29:48 +00:00
}
-updateAbsPos: (Point) absPos
{
[super updateAbsPos: absPos];
[objects updateAbsPos: absRect.offset];
return self;
}
2020-03-30 11:29:48 +00:00
-draw
{
[super draw];
2020-03-30 11:29:48 +00:00
if (vertical) {
[buffer mvvline:{0,0}, bgchar, ylen];
2020-03-30 11:29:48 +00:00
} else {
[buffer mvhline:{0,0}, bgchar, xlen];
2020-03-30 11:29:48 +00:00
}
[objects draw];
[textContext blitFromBuffer:buffer to:pos from:[buffer rect]];
2020-03-30 11:29:48 +00:00
return self;
}
static void
position_tab (ScrollBar *self)
{
Point p = {0, 0};
if (self.range > 0) {
if (self.vertical) {
p.y = 1 + self.index * (self.ylen - 3) / self.range;
} else {
p.x = 1 + self.index * (self.xlen - 3) / self.range;
}
} else {
if (self.vertical) {
p.y = 1;
2020-03-30 11:29:48 +00:00
} else {
p.x = 1;
2020-03-30 11:29:48 +00:00
}
}
[self.thumbTab moveTo:p];
[self redraw];
2020-03-30 11:29:48 +00:00
}
-resize:(Extent)delta
{
Extent size = self.size;
[super resize:delta];
delta = {self.size.width - size.width, self.size.height - size.height};
[objects resize:delta];
[buffer resizeTo:self.size];
2020-03-30 11:29:48 +00:00
position_tab (self);
return self;
}
-page:(unsigned)step dir:(unsigned) dir
{
unsigned oind = index;
if (dir) {
if (range - index < step) {
step = range - index;
2020-03-30 11:29:48 +00:00
}
index += step;
} else {
if (index < step) {
step = index;
}
index -= step;
}
if (index != oind) {
[onScrollBarModified respond:self];
position_tab (self);
2020-03-30 11:29:48 +00:00
}
return self;
}
static void
page (ScrollBar *self, Point pos, Point thumb)
2020-03-30 11:29:48 +00:00
{
unsigned pageDir = 0;
if (self.vertical) {
if (pos.y < thumb.y) {
2020-03-30 11:29:48 +00:00
pageDir = 0;
} else {
pageDir = 1;
}
} else {
if (pos.x < thumb.x) {
2020-03-30 11:29:48 +00:00
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];
}
-(void)horizontalSlide:(id)sender
{
}
-(void)verticalSlide:(id)sender
{
}
2020-03-30 11:29:48 +00:00
-handleEvent:(qwaq_event_t *)event
{
[super handleEvent: event];
[objects handleEvent: event];
if (event.what == qe_mousedown) {
[self grabMouse];
mouseTime = event.when;
2020-03-30 11:29:48 +00:00
mouseStart = {event.mouse.x, event.mouse.y};
tabStart = [thumbTab origin];
page(self, mouseStart, tabStart);
2020-03-30 11:29:48 +00:00
event.what = qe_none;
} else if (event.what==qe_mouseauto) {
if (event.when - mouseTime > 0.1) {
mouseTime = event.when;
page(self, mouseStart, tabStart);
}
2020-03-30 11:29:48 +00:00
event.what = qe_none;
} else if (event.what == qe_mouseup) {
[self releaseMouse];
event.what = qe_none;
}
return self;
}
-setRange:(unsigned)range
{
self.range = range;
2021-09-24 17:14:26 +00:00
if (index > range) {
index = range;
[onScrollBarModified respond:self];
position_tab (self);
}
2020-03-30 11:29:48 +00:00
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;
}
-(unsigned)index
{
return index;
}
2020-03-30 11:29:48 +00:00
@end