quakeforge/ruamoko/qwaq/ui/button.r
2020-03-31 14:40:22 +09:00

180 lines
3.3 KiB
R

#include "ui/button.h"
#include "ui/listener.h"
@implementation Button
+(Button *)withPos:(Point)pos releasedIcon:(DrawBuffer *)released
pressedIcon:(DrawBuffer *)pressed
{
return [[[self alloc] initWithPos:pos
releasedIcon:released
pressedIcon:pressed] autorelease];
}
+(Button *)withRect:(Rect)rect
{
return [[[self alloc] initWithRect:rect] autorelease];
}
-initWithPos: (Point) pos releasedIcon: (DrawBuffer *) released
pressedIcon: (DrawBuffer *) pressed
{
Extent size = mergeExtents ([released size], [pressed size]);
if (!(self = [super initWithRect: {pos, size}])) {
return nil;
}
icon[0] = [released retain];
icon[1] = [pressed retain];
onPress = [[ListenerGroup listener] retain];
onRelease = [[ListenerGroup listener] retain];
onClick = [[ListenerGroup listener] retain];
onDrag = [[ListenerGroup listener] retain];
onAuto = [[ListenerGroup listener] retain];
onHover = [[ListenerGroup listener] retain];
return self;
}
-initWithRect: (Rect) rect
{
if (!(self = [super initWithRect: rect])) {
return nil;
}
icon[0] = nil;
icon[1] = nil;
onPress = [[ListenerGroup listener] retain];
onRelease = [[ListenerGroup listener] retain];
onClick = [[ListenerGroup listener] retain];
onDrag = [[ListenerGroup listener] retain];
onAuto = [[ListenerGroup listener] retain];
onHover = [[ListenerGroup listener] retain];
return self;
}
-(void)dealloc
{
[icon[0] release];
[icon[1] release];
[onPress release];
[onRelease release];
[onClick release];
[onDrag release];
[onAuto release];
[onHover release];
[super dealloc];
}
-draw
{
[super draw];
if (icon[pressed]) {
[textContext blitFromBuffer: icon[pressed]
to: pos
from: [icon[pressed] rect]];
}
return self;
}
-handleEvent: (qwaq_event_t *) event
{
ListenerGroup *action = nil;
[super handleEvent: event];
if (event.what & qe_mouse) {
switch ((qwaq_mouse_event) (event.what & qe_mouse)) {
case qe_mousedown:
pressed = 1;
click = 0;
dragBase = {event.mouse.x, event.mouse.y};
action = onPress;
[self grabMouse];
[self redraw];
break;
case qe_mouseup:
pressed = 0;
click = 0;
action = onRelease;
[self releaseMouse];
if ([self containsPoint: {event.mouse.x, event.mouse.y}]) {
[onClick respond: self];
}
[self redraw];
break;
case qe_mouseclick:
action = onClick;
click = event.mouse.click;
break;
case qe_mousemove:
click = 0;
if (pressed) {
dragPos = {event.mouse.x, event.mouse.y};
action = onDrag;
}
break;
case qe_mouseauto:
if (pressed
&& [self containsPoint: {event.mouse.x, event.mouse.y}]) {
click = 0;
action = onAuto;
}
break;
}
if (action) {
[action respond: self];
}
event.what = qe_none;
}
return self;
}
-(ListenerGroup *) onPress
{
return onPress;
}
-(ListenerGroup *) onRelease
{
return onRelease;
}
-(ListenerGroup *) onClick
{
return onClick;
}
-(ListenerGroup *) onDrag
{
return onDrag;
}
-(ListenerGroup *) onAuto
{
return onAuto;
}
-(ListenerGroup *) onHover
{
return onHover;
}
- (int) click
{
return click;
}
- (Point) delta
{
return {dragPos.x - dragBase.x, dragPos.y - dragBase.y};
}
-move:(Point) delta
{
Point pos = self.pos;
[super move:delta];
dragBase.x += self.pos.x - pos.x;
dragBase.y += self.pos.y - pos.y;
return self;
}
@end