gui2: started working on autolayout.

This commit is contained in:
Martin Preuss
2026-03-07 00:04:36 +01:00
parent a8cb442502
commit 0af5aed2f6
8 changed files with 1367 additions and 28 deletions

View File

@@ -27,7 +27,9 @@
.equ WIDGET_OFFS_HEIGHT_HI = WIDGET_OFFS_BEGIN+7
.equ WIDGET_OFFS_STYLE_LO = WIDGET_OFFS_BEGIN+8 ; byte address (for LPM!)
.equ WIDGET_OFFS_STYLE_HI = WIDGET_OFFS_BEGIN+9
.equ WIDGET_SIZE = WIDGET_OFFS_BEGIN+10
.equ WIDGET_OFFS_TMP_LO = WIDGET_OFFS_BEGIN+10
.equ WIDGET_OFFS_TMP_HI = WIDGET_OFFS_BEGIN+11
.equ WIDGET_SIZE = WIDGET_OFFS_BEGIN+12
; widget style object
.equ WIDGET_STYLE_OFFS_FRONTCOL_NORM = 0
@@ -39,7 +41,7 @@
.equ WIDGET_STYLE_OFFS_BORDERCOL_ACTIVATED = 6
.equ WIDGET_STYLE_OFFS_SHADOWCOL_ACTIVATED = 7
.equ WIDGET_STYLE_OFFS_OUTERBORDERSIZE = 8
.equ WIDGET_STYLE_OFFS_INNERBORDERSIZE = 9
.equ WIDGET_STYLE_OFFS_SPACING = 9
.equ WIDGET_STYLE_OFFS_FONT_LO = 10
.equ WIDGET_STYLE_OFFS_FONT_HI = 11
.equ WIDGET_STYLE_OFFS_CHARWIDTH = 12
@@ -49,22 +51,26 @@
; widget opts_lo (bits 7 and 6 used by OBJECT_OPTSLO)
.equ WIDGET_OPTSLO_INPUT_BIT = 5 ; TOUCH, KEY
.equ WIDGET_OPTSLO_BORDER_BIT = 4
.equ WIDGET_OPTSLO_XALIGN1_BIT = 3 ; (2 bit: left, right, center, filled)
.equ WIDGET_OPTSLO_XALIGN0_BIT = 2
.equ WIDGET_OPTSLO_YALIGN1_BIT = 1 ; (2 bit: top, bottom, center, filled)
.equ WIDGET_OPTSLO_YALIGN0_BIT = 0
.equ WIDGET_OPTSLO_FILLX_BIT = 3
.equ WIDGET_OPTSLO_FILLY_BIT = 2
; values for WIDGET_OPTSLO_XALIGN (2 bits)
.equ WIDGET_OPTSLO_XALIGN_LEFT = 0
.equ WIDGET_OPTSLO_XALIGN_RIGHT = 1
.equ WIDGET_OPTSLO_XALIGN_CENTER = 2
.equ WIDGET_OPTSLO_XALIGN_FILLED = 3
; widget opts_hi
.equ WIDGET_OPTSHI_CONTENT_XALIGN1_BIT = 7 ; (2 bit: left, right, center, filled)
.equ WIDGET_OPTSHI_CONTENT_XALIGN0_BIT = 6
.equ WIDGET_OPTSHI_CONTENT_YALIGN1_BIT = 5 ; (2 bit: top, bottom, center, filled)
.equ WIDGET_OPTSHI_CONTENT_YALIGN0_BIT = 4
; values for WIDGET_OPTSLO_YALIGN (2 bits)
.equ WIDGET_OPTSLO_YALIGN_TOP = 0
.equ WIDGET_OPTSLO_YALIGN_BOTTOM = 1
.equ WIDGET_OPTSLO_YALIGN_CENTER = 2
.equ WIDGET_OPTSLO_YALIGN_FILLED = 3
; values for WIDGET_OPTSHI_CONTENT_XALIGN (2 bits)
.equ WIDGET_XALIGN_LEFT = 0
.equ WIDGET_XALIGN_RIGHT = 1
.equ WIDGET_XALIGN_CENTER = 2
.equ WIDGET_XALIGN_FILLED = 3
; values for WIDGET_OPTSHI_CONTENT_YALIGN (2 bits)
.equ WIDGET_YALIGN_TOP = 0
.equ WIDGET_YALIGN_BOTTOM = 1
.equ WIDGET_YALIGN_CENTER = 2
.equ WIDGET_YALIGN_FILLED = 3
; widget flags
.equ WIDGET_FLAGS_VISIBLE_BIT = 7
@@ -94,12 +100,16 @@
.equ WIDGET_SIGNAL_KEEPALIVE = OBJECT_SIGNAL_NEXTFREE+8
.equ WIDGET_SIGNAL_NEXTFREE = OBJECT_SIGNAL_NEXTFREE+9
; values for signals WIDGET_SIGNAL_SETVALUE and WIDGET_SIGNAL_GETVALUE
.equ WIDGET_VALUE_DEFAULT_WIDTH = 1
.equ WIDGET_VALUE_DEFAULT_HEIGHT = 2
.equ WIDGET_VALUE_NEXTFREE = 3
; args to Widget_AlignPos
.equ WIDGET_1DALIGN_END_BIT = 0
.equ WIDGET_1DALIGN_CENTER_BIT = 1
.equ WIDGET_1DALIGN_BORDER_BIT = 2
; ***************************************************************************
@@ -108,6 +118,29 @@
.cseg
; ---------------------------------------------------------------------------
; @routine Widget_new @global
;
; @return CFLAG set of okay, cleared otherwise
; @return Y address of newly created object
; @param X parent widget
; @param r16 value for OBJECT_OFFS_OPTS_LO
; @param r17 value for OBJECT_OFFS_OPTS_HI
; @clobbers any
Widget_new:
ldi r24, LOW(WIDGET_SIZE)
ldi r25, HIGH(WIDGET_SIZE)
bigcall Object_Alloc ; (!r16, !r17, !X)
brcc Widget_new_ret
rcall Widget_Init ; (r16, r17, X)
sec
Widget_new_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_Init @global
;
@@ -171,7 +204,7 @@ Widget_Init_setDefaultSize:
mov r16, xl
or r16, xh
breq Widget_Init_ret
bigcall OBJ_AddChild
bigcall OBJ_AddChild ; (r18, r19)
Widget_Init_ret:
ret
@@ -233,6 +266,46 @@ Widget_Move:
; ---------------------------------------------------------------------------
; @routine Widget_GetDefaultWidth @global
;
; @param Y address of widget
; @return r19:r18 default width of the widget
; @clobbers any, !Y
Widget_GetDefaultWidth:
ldi r16, WIDGET_SIGNAL_GETVALUE
ldi r17, WIDGET_VALUE_DEFAULT_WIDTH
bigcall OBJ_HandleSignal
brcs Widget_GetDefaultWidth_ret
ldi r18, 1
clr r19
Widget_GetDefaultWidth_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_GetDefaultHeight @global
;
; @param Y address of widget
; @return r19:r18 default height of the widget
; @clobbers any, !Y
Widget_GetDefaultHeight:
ldi r16, WIDGET_SIGNAL_GETVALUE
ldi r17, WIDGET_VALUE_DEFAULT_HEIGHT
bigcall OBJ_HandleSignal
brcs Widget_GetDefaultHeight_ret
ldi r18, 1
clr r19
Widget_GetDefaultHeight_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_OnDraw @global
;
@@ -339,8 +412,7 @@ Widget_Clear:
; @routine Widget_DrawBorder @global
;
; @param Y address of widget
; @param r3:r2 color
; @clobbers any, !Z
; @clobbers any, !Y
Widget_DrawBorder:
rcall widgetLoadDimsForFullWidget ; (none)
@@ -599,6 +671,211 @@ Widget_SelectBorderColors_readColors:
; ---------------------------------------------------------------------------
; @routine Widget_CalcStringWidthFLASH
;
; @param Z pointer to text in FLASH
; @param R18 char width in px
; @return r13:r12 width of string
; @clobbers r16
Widget_CalcStringWidthFLASH:
clr r12
clr r13
push zl
push zh
Widget_CalcStringWidthFLASH_loop:
lpm r16, Z+
tst r16
breq Widget_CalcStringWidthFLASH_done
add r12, r18
adc r13, r18
sub r13, r18
rjmp Widget_CalcStringWidthFLASH_loop
Widget_CalcStringWidthFLASH_done:
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_AlignContentX @global
;
; @param Y address of widget
; @param R13:R12 width of object to align
; @return R5:R4 X
; @clobbers r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, r24, r25
Widget_AlignContentX:
ldd r8, Y+WIDGET_OFFS_WIDTH_LO
ldd r9, Y+WIDGET_OFFS_WIDTH_HI
ldd r24, Y+OBJECT_OFFS_OPTS_LO
ldd r25, Y+OBJECT_OFFS_OPTS_HI
; align horizontally
clr r17
sbrc r24, WIDGET_OPTSLO_BORDER_BIT
ori r17, (1<<WIDGET_1DALIGN_BORDER_BIT)
mov r16, r25
andi r16, (1<<WIDGET_OPTSHI_CONTENT_XALIGN1_BIT) | (1<<WIDGET_OPTSHI_CONTENT_XALIGN0_BIT)
cpi r16, (WIDGET_XALIGN_RIGHT<<WIDGET_OPTSHI_CONTENT_XALIGN0_BIT)
brne Widget_AlignContentX_h1
ori r17, (1<<WIDGET_1DALIGN_END_BIT)
Widget_AlignContentX_h1:
cpi r16, (WIDGET_XALIGN_CENTER<<WIDGET_OPTSHI_CONTENT_XALIGN0_BIT)
brne Widget_AlignContentX_h2
ori r17, (1<<WIDGET_1DALIGN_CENTER_BIT)
Widget_AlignContentX_h2:
mov r18, r8 ; widget width
mov r19, r9
rcall Widget_AlignPos1D ; (r16, r18, r19)
mov r4, r22
mov r5, r23
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_AlignContentY @global
;
; @param Y address of widget
; @param R13:R12 height of object to align
; @return R7:R6 Y
; @clobbers r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, r24, r25
Widget_AlignContentY:
ldd r10, Y+WIDGET_OFFS_HEIGHT_LO
ldd r11, Y+WIDGET_OFFS_HEIGHT_HI
ldd r24, Y+OBJECT_OFFS_OPTS_LO
ldd r25, Y+OBJECT_OFFS_OPTS_HI
; align vertically
clr r17
sbrc r24, WIDGET_OPTSLO_BORDER_BIT
ori r17, (1<<WIDGET_1DALIGN_BORDER_BIT)
mov r16, r24
andi r16, (1<<WIDGET_OPTSHI_CONTENT_YALIGN1_BIT) | (1<<WIDGET_OPTSHI_CONTENT_YALIGN0_BIT)
cpi r16, (WIDGET_YALIGN_BOTTOM<<WIDGET_OPTSHI_CONTENT_YALIGN0_BIT)
brne Widget_AlignContentY_v1
ori r17, (1<<WIDGET_1DALIGN_END_BIT)
Widget_AlignContentY_v1:
cpi r16, (WIDGET_YALIGN_CENTER<<WIDGET_OPTSHI_CONTENT_YALIGN0_BIT)
brne Widget_AlignContentY_v2
ori r17, (1<<WIDGET_1DALIGN_CENTER_BIT)
Widget_AlignContentY_v2:
mov r18, r10 ; widget height
mov r19, r11
rcall Widget_AlignPos1D ; (r16, r18, r19)
mov r6, r22
mov r7, r23
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_AlignPos1D
;
; one-dimensional routine.
;
; @param R19:R18 size of target
; @param R13:R12 size of object to align
; @param
; @param R17 opts (bit 0: align end, bit 1: align center, bit 2: account for border)
; @return R23:R22 pos
; @clobbers r16, r18, r19
Widget_AlignPos1D:
clr r22
clr r23
sbrc r17, WIDGET_1DALIGN_BORDER_BIT
rcall Widget_AlignPos1D_subBordersFromSize
sbrc r17, WIDGET_1DALIGN_END_BIT
rcall Widget_AlignPos1D_alignEnd
sbrc r17, WIDGET_1DALIGN_CENTER_BIT
rcall Widget_AlignPos1D_alignCenter
sbrc r17, WIDGET_1DALIGN_BORDER_BIT
rcall Widget_AlignPos1D_addBordersToPos
Widget_AlignPos1D_ret:
ret
Widget_AlignPos1D_alignEnd:
mov r22, r18
mov r23, r19
sub r22, r12
sbc r23, r13
brcc Widget_AlignPos1D_ret
clr r22
clr r23
ret
Widget_AlignPos1D_alignCenter:
rcall Widget_AlignPos1D_alignEnd
lsr r23
ror r22
ret
Widget_AlignPos1D_subBordersFromSize:
subi r18, 4
sbci r19, 0
ret
Widget_AlignPos1D_addBordersToPos:
ldi r16, 2
add r22, r16
adc r23, r16
sub r23, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_GetCharWidth @global
;
; @param Y address of widget
; @return R16 character width with current font (in pixels)
; @clobbers none
Widget_GetCharWidth:
push zl
push zh
ldd zl, Y+WIDGET_OFFS_STYLE_LO
ldd zh, Y+WIDGET_OFFS_STYLE_HI
adiw zh:zl, WIDGET_STYLE_OFFS_CHARWIDTH
lpm r16, Z
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_GetCharHeight @global
;
; @param Y address of widget
; @return R16 character height with current font (in pixels)
; @clobbers none
Widget_GetCharHeight:
push zl
push zh
ldd zl, Y+WIDGET_OFFS_STYLE_LO
ldd zh, Y+WIDGET_OFFS_STYLE_HI
adiw zh:zl, WIDGET_STYLE_OFFS_CHARHEIGHT
lpm r16, Z
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine widgetDrawChar
;