gui2: added generic button class

this gives child elements a button behavior.
This commit is contained in:
Martin Preuss
2026-03-09 18:20:51 +01:00
parent f5e19ac0a1
commit 2827f4e063
6 changed files with 598 additions and 18 deletions

View File

@@ -91,11 +91,15 @@
.equ WIDGET_SIGNAL_LAYOUT = OBJECT_SIGNAL_NEXTFREE+2
.equ WIDGET_SIGNAL_DRAW = OBJECT_SIGNAL_NEXTFREE+3
.equ WIDGET_SIGNAL_TOUCH = OBJECT_SIGNAL_NEXTFREE+4
.equ WIDGET_SIGNAL_CLICKED = OBJECT_SIGNAL_NEXTFREE+5
.equ WIDGET_SIGNAL_SETVALUE = OBJECT_SIGNAL_NEXTFREE+6
.equ WIDGET_SIGNAL_GETVALUE = OBJECT_SIGNAL_NEXTFREE+7
.equ WIDGET_SIGNAL_KEEPALIVE = OBJECT_SIGNAL_NEXTFREE+8
.equ WIDGET_SIGNAL_NEXTFREE = OBJECT_SIGNAL_NEXTFREE+9
.equ WIDGET_SIGNAL_COMMAND = OBJECT_SIGNAL_NEXTFREE+5
.equ WIDGET_SIGNAL_CHANGE = OBJECT_SIGNAL_NEXTFREE+6
.equ WIDGET_SIGNAL_SETVALUE = OBJECT_SIGNAL_NEXTFREE+7
.equ WIDGET_SIGNAL_GETVALUE = OBJECT_SIGNAL_NEXTFREE+8
.equ WIDGET_SIGNAL_KEEPALIVE = OBJECT_SIGNAL_NEXTFREE+9
.equ WIDGET_SIGNAL_TOUCH_BEGIN = OBJECT_SIGNAL_NEXTFREE+10
.equ WIDGET_SIGNAL_TOUCH_MOVE = OBJECT_SIGNAL_NEXTFREE+11
.equ WIDGET_SIGNAL_TOUCH_END = OBJECT_SIGNAL_NEXTFREE+12
.equ WIDGET_SIGNAL_NEXTFREE = OBJECT_SIGNAL_NEXTFREE+13
; values for signals WIDGET_SIGNAL_SETVALUE and WIDGET_SIGNAL_GETVALUE
.equ WIDGET_VALUE_DEFAULT_WIDTH = 1
@@ -335,6 +339,133 @@ Widget_GetDefaultHeight_ret:
; ---------------------------------------------------------------------------
; @routine Widget_IsPointInRect @global
;
; @param R19:R18 check X
; @param R21:R20 check Y
; @param R5:R4 widget X
; @param R7:R6 widget Y
; @param R9:R8 widget width
; @param R11:R10 widget height
; @return CFLAG set if inside rect, cleared otherwise
; @clobbers R16, R17
Widget_IsPointInRect:
; check X
mov r16, r18 ; checkX-widgetX
mov r17, r19
sub r16, r4
sbc r17, r5
brcs Widget_IsPointInRect_no ; jmp if left of widget
sub r16, r8 ; sub width
sbc r17, r9
brcc Widget_IsPointInRect_no ; jmp if right of widget
mov r16, r20 ; checkY-widgetY
mov r17, r21
sub r16, r6
sbc r17, r7
brcs Widget_IsPointInRect_no ; jmp if above widget
sub r16, r10 ; sub height
sbc r17, r11
brcc Widget_IsPointInRect_no ; jmp if below widget
sec ; is inside rect
rjmp Widget_IsPointInRect_ret
Widget_IsPointInRect_no:
clc
Widget_IsPointInRect_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_GetApp @global
;
; @param Y address of object
; @return R19:R18 byte address pointer to GuiApp
; @clobbers none
Widget_GetApp:
push yl
push yh
bigcall OBJ_GetRootToY ; (r18, r19)
bigcall RootWindow_GetApp ; (none)
pop yh
pop yl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_GrabTouchEvents @global
;
; Let this widget grab touch events until ungrabbed.
;
; @param Y address of object
; @param X byte address of widget grabbing touch events
; @return CFLAG set if grabbed, cleared on error
; @clobbers r16, r17, r18, r19
Widget_GrabTouchEvents:
rcall Widget_GetApp ; r19:r18=guiapp
push yl
push yh
push xl
push xh
mov xl, yl
mov xh, yh
mov yl, r18
mov yh, r19
bigcall GuiApp_GrabTouchEvents ; (r16, r17)
pop xh
pop xl
pop yh
pop yl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_UngrabTouchEvents @global
;
; Let this widget grab touch events until ungrabbed.
;
; @param Y address of object
; @param X byte address of widget grabbing touch events
; @return CFLAG set if grabbed, cleared on error
; @clobbers r16, r17, r18, r19
Widget_UngrabTouchEvents:
rcall Widget_GetApp ; (r18, r19)
push yl
push yh
push xl
push xh
mov xl, yl
mov xh, yh
mov yl, r18
mov yh, r19
bigcall GuiApp_UngrabTouchEvents ; (r16, r17)
pop xh
pop xl
pop yh
pop yl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_OnDraw @global
;
@@ -470,6 +601,84 @@ Widget_OnGetValue_ret:
; ---------------------------------------------------------------------------
; @routine Widget_OnTouch @global
;
; @param Y address of widget
; @param r17 value requested
; @param xl param1
; @param xh param2
; @return CFLAG set if signal handled
; @return r19:r18 value
; @clobbers any, !Y
Widget_OnTouch:
ldd r16, Y+OBJECT_OFFS_FLAGS
sbrs r16, WIDGET_FLAGS_VISIBLE_BIT
rjmp Widget_OnTouch_done
; read touch signal data from X
ld r18, X+ ; WIDGET_DATA_TOUCH_OFFS_X_LO
ld r19, X+ ; WIDGET_DATA_TOUCH_OFFS_X_HI
ld r20, X+ ; WIDGET_DATA_TOUCH_OFFS_Y_LO
ld r21, X+ ; WIDGET_DATA_TOUCH_OFFS_Z_HI
ld r22, X ; WIDGET_DATA_TOUCH_OFFS_STATE
sbiw xh:xl, 4
sbrs r22, DISPLAY_IFLAGS_PRESSED_BIT
rjmp Widget_OnTouch_up
; down (active touch)
ldd r16, Y+OBJECT_OFFS_FLAGS
sbrc r16, WIDGET_FLAGS_TOUCH_BIT
rjmp Widget_OnTouch_move ; already pressed, jmp
; newly pressed
rcall Widget_LoadDimsForFullWidget ; (none)
push r18
push r19
rcall Widget_MakeAbsPos ; (r16, r17, r18, r19)
pop r19
pop r18
rcall Widget_IsPointInRect ; (R16, R17)
brcc Widget_OnTouch_done ; touch not inside this widget, jmp
; touch down inside this widget, handle
bigcall Widget_GrabTouchEvents ; (r16, r17, r18, r19)
brcc Widget_OnTouch_done ; can't grab, abort
ldd r16, Y+OBJECT_OFFS_FLAGS
sbr r16, (1<<WIDGET_FLAGS_TOUCH_BIT)
std Y+OBJECT_OFFS_FLAGS, r16
; send TOUCH_BEGIN to this object
ldi r16, WIDGET_SIGNAL_TOUCH_BEGIN
clr r17
bigcall OBJ_HandleSignal ; (any, !Y)
rjmp Widget_OnTouch_done
Widget_OnTouch_up:
ldd r16, Y+OBJECT_OFFS_FLAGS
sbrs r16, WIDGET_FLAGS_TOUCH_BIT
rjmp Widget_OnTouch_done
; was pressed, not any more
bigcall Widget_UngrabTouchEvents ; (r16, r17, r18, r19)
ldd r16, Y+OBJECT_OFFS_FLAGS
cbr r16, (1<<WIDGET_FLAGS_TOUCH_BIT)
std Y+OBJECT_OFFS_FLAGS, r16
; send TOUCH_END to this object
ldi r16, WIDGET_SIGNAL_TOUCH_END
clr r17
bigcall OBJ_HandleSignal ; (any, !Y)
rjmp Widget_OnTouch_done
Widget_OnTouch_move:
; send TOUCH_MOVE to this object
ldi r16, WIDGET_SIGNAL_TOUCH_MOVE
clr r17
bigcall OBJ_HandleSignal ; (any, !Y)
Widget_OnTouch_done:
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_Clear @global
;
@@ -477,7 +686,7 @@ Widget_OnGetValue_ret:
; @clobbers any, !Y
Widget_Clear:
rcall widgetLoadDimsForFullWidget ; (none)
rcall Widget_LoadDimsForFullWidget ; (none)
rcall Widget_MakeAbsPos ; (r16, r17, r18, r19)
rcall Widget_SelectColors ; (R16)
mov r2, r0 ; use background
@@ -495,7 +704,7 @@ Widget_Clear:
; @clobbers any, !Y
Widget_DrawBorder:
rcall widgetLoadDimsForFullWidget ; (none)
rcall Widget_LoadDimsForFullWidget ; (none)
rcall Widget_MakeAbsPos ; (R16, R17)
rcall Widget_SelectBorderColors ; (R16)
bigcall Display_DrawRect
@@ -987,7 +1196,7 @@ widgetDrawChar_done:
; ---------------------------------------------------------------------------
; @routine widgetLoadDimsForFullWidget
; @routine Widget_LoadDimsForFullWidget
;
; @param Y address of widget
; @return r5:r4 X (0)
@@ -996,7 +1205,7 @@ widgetDrawChar_done:
; @return r11:R10 widget height
; @clobbers none
widgetLoadDimsForFullWidget:
Widget_LoadDimsForFullWidget:
clr r4
clr r5
clr r6