mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-22 02:11:19 +00:00
[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:
parent
4bc6aab7ec
commit
e15f2097df
6 changed files with 85 additions and 40 deletions
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue