[qwaq] Move scroll bar management into View

Putting it in Editor worked as a proof of concept, but it seems those
always turn out to need tweaking like this because the concept proves
itself to be generally worthwhile :P
This commit is contained in:
Bill Currie 2020-03-31 11:21:47 +09:00
parent 4bc6aab7ec
commit e15f2097df
6 changed files with 85 additions and 40 deletions

View file

@ -7,25 +7,22 @@
@class Editor;
@class EditBuffer;
@class ListenerGroup;
@class ScrollBar;
@interface Editor : View
{
EditBuffer *buffer;
DrawBuffer *linebuffer;
ScrollBar *vScrollBar;
eb_sel_t selection;
unsigned base_index; // top left corner
unsigned line_index; // current line
unsigned char_index; // current character
unsigned old_cind; // previous character
Point scroll;
Point base;
Point cursor;
unsigned line_count;
string filename;
}
+(Editor *)withRect:(Rect)rect file:(string)filename;
-setVerticalScrollBar:(ScrollBar *)scrollbar;
-(string)filename;
-scrollUp:(unsigned) count;
-scrollDown:(unsigned) count;

View file

@ -17,6 +17,7 @@
linebuffer = [[DrawBuffer buffer: { xlen, 1 }] retain];
growMode = gfGrowHi;
options = ofCanFocus | ofRelativeEvents;
[onViewScrolled addListener:self :@selector(onScroll:)];
return self;
}
@ -25,19 +26,6 @@
return [[[self alloc] initWithRect:rect file:filename] autorelease];
}
-setVerticalScrollBar:(ScrollBar *)scrollbar
{
[scrollbar retain];
[[vScrollBar onScroll] removeListener:self :@selector(onScroll:)];
[vScrollBar release];
vScrollBar = scrollbar;
[vScrollBar setRange:line_count];
[vScrollBar setPageStep: ylen];
[[vScrollBar onScroll] addListener:self :@selector(onScroll:)];
return self;
}
-(void)dealloc
{
[vScrollBar release];
@ -57,7 +45,7 @@
unsigned lind = base_index;
int *lbuf = [linebuffer buffer];
for (int y = 0; y < ylen; y++) {
lind = [buffer formatLine:lind from:scroll.x into:lbuf width:xlen
lind = [buffer formatLine:lind from:base.x into:lbuf width:xlen
highlight:selection colors: {color_palette[047],
color_palette[007]}];
[textContext blitFromBuffer: linebuffer to: {xpos, ypos + y}
@ -141,10 +129,10 @@ static int handleEvent (Editor *self, qwaq_event_t *event)
-scrollLeft:(unsigned) count
{
if (scroll.x > count) {
scroll.x -= count;
if (base.x > count) {
base.x -= count;
} else {
scroll.x = 0;
base.x = 0;
}
[self redraw];
return self;
@ -152,10 +140,10 @@ static int handleEvent (Editor *self, qwaq_event_t *event)
-scrollRight:(unsigned) count
{
if (1024 - scroll.x > count) {
scroll.x += count;
if (1024 - base.x > count) {
base.x += count;
} else {
scroll.x = 1024;
base.x = 1024;
}
[self redraw];
return self;
@ -163,24 +151,33 @@ static int handleEvent (Editor *self, qwaq_event_t *event)
-scrollTo:(unsigned)target
{
if (target > scroll.y) {
base_index = [buffer nextLine:base_index :target - scroll.y];
} else if (target < scroll.y) {
base_index = [buffer prevLine:base_index :scroll.y - target];
if (target > base.y) {
base_index = [buffer nextLine:base_index :target - base.y];
} else if (target < base.y) {
base_index = [buffer prevLine:base_index :base.y - target];
}
scroll.y = target;
base.y = target;
return self;
}
-(void)onScroll:(id)sender
{
[self scrollTo:[sender index]];
base.x = scroll.x;
[self scrollTo:scroll.y];
}
-setVerticalScrollBar:(ScrollBar *)scrollbar
{
[super setVerticalScrollBar:scrollbar];
[vScrollBar setRange:line_count];
[vScrollBar setPageStep: ylen];
return self;
}
-recenter:(int) force
{
if (!force) {
if (cursor.y >= scroll.y && cursor.y - scroll.y < ylen) {
if (cursor.y >= base.y && cursor.y - base.y < ylen) {
return self;
}
}
@ -221,7 +218,7 @@ static int handleEvent (Editor *self, qwaq_event_t *event)
if (pos.x < 0 || pos.y < 0 || pos.x >= xlen || pos.y >= ylen) {
return nil;
}
pos.x += scroll.x;
pos.x += base.x;
unsigned lind = [buffer nextLine:base_index :pos.y];
unsigned cind = [buffer charPtr:lind at:pos.x];
eb_sel_t word = [buffer getWord: cind];

View file

@ -20,7 +20,7 @@
Button *forwardButton;
Button *thumbTab;
Group *objects;
ListenerGroup *onScroll;
ListenerGroup *onScrollBarModified;
unsigned pageStep;
unsigned singleStep;
@ -29,7 +29,7 @@
}
+(ScrollBar *)horizontal:(unsigned)len at:(Point)pos;
+(ScrollBar *)vertical:(unsigned)len at:(Point)pos;
-(ListenerGroup *)onScroll;
-(ListenerGroup *)onScrollBarModified;
-setRange:(unsigned)range;
-setPageStep:(unsigned)pageStep;
-setSingleStep:(unsigned)singleStep;

View file

@ -13,7 +13,7 @@
options = ofRelativeEvents;
buffer = [[DrawBuffer buffer:size] retain];
objects = [[Group withContext:buffer owner:self] retain];
onScroll = [[ListenerGroup listener] retain];
onScrollBarModified = [[ListenerGroup listener] retain];
vertical = xlen == 1;
DrawBuffer *icons[3] = {
[DrawBuffer buffer:{1, 1}],
@ -61,7 +61,7 @@
{
[objects release];
[buffer release];
[onScroll release];
[onScrollBarModified release];
}
+(ScrollBar *)horizontal:(unsigned)len at:(Point)pos
@ -80,9 +80,9 @@
return [[[self alloc] initWithRect:{pos, {1, len}}] autorelease];
}
-(ListenerGroup *)onScroll
-(ListenerGroup *)onScrollBarModified
{
return onScroll;
return onScrollBarModified;
}
-draw
@ -142,7 +142,7 @@ position_tab (ScrollBar *self)
}
if (index != oind) {
[onScroll respond:self];
[onScrollBarModified respond:self];
position_tab (self);
}
return self;

View file

@ -10,6 +10,7 @@
@class Group;
@class ListenerGroup;
@class ScrollBar;
enum {
ofCanFocus = 0x0001,
@ -59,6 +60,10 @@ enum {
-(int) options;
-(int) state;
-setVerticalScrollBar:(ScrollBar *)scrollbar;
-setHorizontalScrollBar:(ScrollBar *)scrollbar;
-(ListenerGroup *) onViewScrolled;
-(id<TextContext>)context;
-setContext: (id<TextContext>) context;
-draw;
@ -114,6 +119,10 @@ enum {
ListenerGroup *onReceiveFocus;
ListenerGroup *onReleaseFocus;
ListenerGroup *onEvent;
ListenerGroup *onViewScrolled;
ScrollBar *hScrollBar;
ScrollBar *vScrollBar;
Point scroll;
}
+(View *)viewWithRect:(Rect)rect;
+(View *)viewWithRect:(Rect)rect options:(int)options;

View file

@ -1,7 +1,8 @@
#include "ui/curses.h"
#include "ui/listener.h"
#include "ui/view.h"
#include "ui/group.h"
#include "ui/scrollbar.h"
#include "ui/view.h"
@implementation View
@ -20,6 +21,7 @@ static void view_init(View *self)
self.onReceiveFocus = [ListenerGroup listener];
self.onReleaseFocus = [ListenerGroup listener];
self.onEvent = [ListenerGroup listener];
self.onViewScrolled = [ListenerGroup listener];
}
-init
@ -64,6 +66,7 @@ static void view_init(View *self)
[onReceiveFocus release];
[onReleaseFocus release];
[onEvent release];
[onViewScrolled release];
[super dealloc];
}
@ -88,6 +91,40 @@ static void view_init(View *self)
return state;
}
-(void)onScrollBarModified:(id)sender
{
if (sender == vScrollBar) {
scroll.y = [sender index];
} else if (sender == hScrollBar) {
scroll.x = [sender index];
}
[onViewScrolled respond:self];
}
static void
setScrollBar (View *self, ScrollBar **sb, ScrollBar *scrollbar)
{
SEL sel = @selector(onScrollBarModified:);
[scrollbar retain];
[[*sb onScrollBarModified] removeListener:self :sel];
[*sb release];
*sb = scrollbar;
[[*sb onScrollBarModified] addListener:self :sel];
}
-setVerticalScrollBar:(ScrollBar *)scrollbar
{
setScrollBar (self, &vScrollBar, scrollbar);
return self;
}
-setHorizontalScrollBar:(ScrollBar *)scrollbar
{
setScrollBar (self, &hScrollBar, scrollbar);
return self;
}
static void
updateScreenCursor (View *view)
{
@ -321,6 +358,11 @@ updateScreenCursor (View *view)
return onEvent;
}
-(ListenerGroup *) onViewScrolled
{
return onViewScrolled;
}
-handleEvent: (qwaq_event_t *) event
{
// give any listeners a chance to override or extend event handling