From 5e3a8f444a96a373bc0419c4d7748ccb3be4aac0 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Sat, 21 Mar 2026 08:28:23 +0100 Subject: [PATCH] gui2: 2nd try for a matrix layout. --- avr/devices/c03/test/main.asm | 9 +- avr/modules/lcd2/gui2/base/mlayout2.asm | 1343 +++++++++++++++++++++++ 2 files changed, 1348 insertions(+), 4 deletions(-) create mode 100644 avr/modules/lcd2/gui2/base/mlayout2.asm diff --git a/avr/devices/c03/test/main.asm b/avr/devices/c03/test/main.asm index 4db095c..137f3a9 100644 --- a/avr/devices/c03/test/main.asm +++ b/avr/devices/c03/test/main.asm @@ -255,8 +255,8 @@ test: push yl push yh - bigcall ClimateWin_new -; rcall mkTestWindow +; bigcall ClimateWin_new + rcall mkTestWindow mov xl, yl mov xh, yh pop yh @@ -339,8 +339,8 @@ mkTestWindow: push xl ; content window push xh - rcall mkTestWidgets -; rcall mkSimpleTestWidgets +; rcall mkTestWidgets + rcall mkSimpleTestWidgets pop xh pop xl mkTestWindow_popRet: @@ -470,6 +470,7 @@ GUI2_MODULE_BEGIN: .include "modules/lcd2/gui2/base/layout.asm" .include "modules/lcd2/gui2/base/hlayout.asm" .include "modules/lcd2/gui2/base/vlayout.asm" +.include "modules/lcd2/gui2/base/mlayout2.asm" .include "modules/lcd2/gui2/base/guiapp.asm" .include "modules/lcd2/gui2/base/mainwindow.asm" .include "modules/lcd2/gui2/base/rootwindow.asm" diff --git a/avr/modules/lcd2/gui2/base/mlayout2.asm b/avr/modules/lcd2/gui2/base/mlayout2.asm new file mode 100644 index 0000000..e1dcc55 --- /dev/null +++ b/avr/modules/lcd2/gui2/base/mlayout2.asm @@ -0,0 +1,1343 @@ +; *************************************************************************** +; copyright : (C) 2026 by Martin Preuss +; email : martin@libchipcard.de +; +; *************************************************************************** +; * This file is part of the project "AqHome". * +; * Please see toplevel file COPYING of that project for license details. * +; *************************************************************************** + +#ifndef AQH_AVR_GUI2_MLAYOUT2_ASM +#define AQH_AVR_GUI2_MLAYOUT2_ASM + +; TODO: +; - use this class also for HLayout and VLayout, those are just special +; cases with only one row (HLayout) or column (VLayout) +; - add TMP2, use TMP1 for X, TMP2 for Y, position cells ?? +; - set X=left pos of space allocated to object, Y=top pos?? +; - use that to position cells in the end?? + + + +; *************************************************************************** +; defines + + +.equ MLAYOUT_OFFS_BEGIN = WIDGET_SIZE +.equ MLAYOUT_OFFS_MODE = MLAYOUT_OFFS_BEGIN+0 +.equ MLAYOUT_OFFS_COLSORROWS = MLAYOUT_OFFS_BEGIN+1 +.equ MLAYOUT_SIZE = MLAYOUT_OFFS_BEGIN+2 + + +; values for MLAYOUT_OFFS_MODE +.equ HLAYOUT_MODE_COLUMNS = 0 +.equ HLAYOUT_MODE_ROWS = 1 + + + + + +; *************************************************************************** +; code + +.cseg + + + +; --------------------------------------------------------------------------- +; @routine MLayout_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 +; @param r17 value for WIDGET_OFFS_PACK +; @param r20 layout mode (MLAYOUT_MODE_COLUMNS, MLAYOUT_MODE_ROWS) +; @param r21 number of columns or rows (depending on mode in r20) +; @clobbers any + +MLayout_new: + push r20 + push r21 + ldi r24, LOW(MLAYOUT_SIZE) + ldi r25, HIGH(MLAYOUT_SIZE) + bigcall Object_Alloc ; (!r16, !r17, !X) + pop r21 + pop r20 + brcc MLayout_new_ret + rcall MLayout_Init ; (r16, r17, X) + sec +MLayout_new_ret: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine MLayout_Init @global +; +; @param Y address of widget +; @param X parent widget (if any) +; @param r16 value for OBJECT_OFFS_OPTS +; @param r17 value for WIDGET_OFFS_PACK +; @param r20 layout mode (MLAYOUT_MODE_COLUMN, MLAYOUT_MODE_ROW) +; @param r21 number of columns or rows (depending on mode in r20) +; @clobbers r16, r17, X + +MLayout_Init: + push r20 + push r21 + ; call base class + bigcall Widget_Init ; (r16, r17, X) + pop r21 + pop r20 + + ; set widget-specific data + std Y+MLAYOUT_OFFS_MODE, r20 + std Y+MLAYOUT_OFFS_COLSORROWS, r21 + + ; set default signal map + ldi r16, LOW(MLayout_DefaultSignalmap*2) + std Y+OBJECT_OFFS_SIGNALMAP_LO, r16 + ldi r16, HIGH(MLayout_DefaultSignalmap*2) + std Y+OBJECT_OFFS_SIGNALMAP_HI, r16 + + ret +; @end + + + + +MLayout_OnLayout: + bigcall OBJ_GetFirstChild ; test for children + brcc MLayout_OnLayout_ret ; none, done here + ; TODO +MLayout_OnLayout_ret: + sec + ret + + +MLayout_OnGetDefaultWidth: +MLayout_OnGetDefaultHeight: + ret + + + + + + + + + +mLayoutColumnLayoutHorizontally: + ; prepare + rcall mLayoutSetDefaultWidthToTmp ; (any, !Y) + rcall mLayoutCopyTmpToWidth ; (r18, r19, r25, Z) + rcall mLayoutGetBorders ; r22=spacing, r23=border + + ; prepare first row + rcall mLayoutSetupFirstContiguous ; set max column widths to first row (r18, r19, r25, Z) + + ; possibly distribute free space to expandable columns + push r22 ; spacing + push r23 ; border + rcall mLayoutColumnExpandColumns ; (r16-r23, r25) + pop r23 + pop r22 + + rcall mLayoutColumnCopyTmpFromFirstRow ; copy TMP of every column from first row to following (r18-r21, r25, Z) + + rcall mLayoutColumnPositionX ; (r12, r13, r16-r21, r25, X) + ret +; @end + + + +mLayoutColumnLayoutVertically: + ; prepare + rcall mLayoutSetDefaultHeightToTmp ; (any, !Y) + rcall mLayoutCopyTmpToHeight ; (r18, r19, r25, Z) + rcall mLayoutGetBorders ; r22=spacing, r23=border + + ; prepare first row + rcall mLayoutSetupFirstSkipped ; set max column widths to first column (r18, r19, r25, Z) + + ; possibly distribute free space to expandable columns + push r22 ; spacing + push r23 ; border + rcall mLayoutColumnExpandRows ; (r16-r23, r25) + pop r23 + pop r22 + + rcall mLayoutColumnCopyTmpFromFirstColumn ; copy TMP of every column from first row to following (r18-r21, r25, Z) + + rcall mLayoutColumnPositionY ; (r12, r13, r16-r21, r25, X) + ret +; @end + + + + + + +; --------------------------------------------------------------------------- +; @routine mLayoutColumnCopyTmpFromFirstRow +; +; @param Y widget +; @clobbers r18-r21, r25, Z + +mLayoutColumnCopyTmpFromFirstRow: + push yl + push yh + ldi zl, LOW(mLayoutCallbackColumnCopyRow) + ldi zh, HIGH(mLayoutCallbackColumnCopyRow) + ldd r25, Y+MLAYOUT_OFFS_COLSORROWS + rcall mLayoutForEveryObjectContiguous ; (r18-r21, r25, Y) + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackColumnCopyRow +; +; @param Y widget +; @clobbers r18, r19, r20, r21, r25 + +mLayoutCallbackColumnCopyRow: + push zl + push zh + rcall mLayoutColumnCopyTmpAcrossColumn ; (r18, r19, r20, r21, r25, Z) + pop zh + pop zl + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutColumnCopyTmpAcrossColumn +; +; @param Y widget +; @clobbers r18, r19, r20, r21, r25, Z + +mLayoutColumnCopyTmpAcrossColumn: + push yl + push yh + ldd r20, Y+WIDGET_OFFS_TMP_LO + ldd r21, Y+WIDGET_OFFS_TMP_HI + ldi zl, LOW(mLayoutCallbackSetTmp) + ldi zh, HIGH(mLayoutCallbackSetTmp) + ldd r25, Y+MLAYOUT_OFFS_COLSORROWS + rcall mLayoutForEveryObjectSkipped ; (r18, r19, r25, Y) + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutColumnCopyTmpFromFirstColumn +; +; @param Y widget +; @clobbers r18-r21, r25, Z + +mLayoutColumnCopyTmpFromFirstColumn: + push yl + push yh + ldi zl, LOW(mLayoutCallbackColumnCopyColumn) + ldi zh, HIGH(mLayoutCallbackColumnCopyColumn) + ldd r25, Y+MLAYOUT_OFFS_COLSORROWS + rcall mLayoutForEveryObjectSkipped ; (r18-r21, r25, Y) + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackColumnCopyColumn +; +; @param Y widget +; @clobbers r18, r19, r20, r21, r25 + +mLayoutCallbackColumnCopyColumn: + push zl + push zh + rcall mLayoutColumnCopyTmpAcrossRow ; (r18, r19, r20, r21, r25, Z) + pop zh + pop zl + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutColumnCopyTmpAcrossRow +; +; @param Y widget +; @clobbers r18, r19, r20, r21, r25, Z + +mLayoutColumnCopyTmpAcrossRow: + push yl + push yh + ldd r20, Y+WIDGET_OFFS_TMP_LO + ldd r21, Y+WIDGET_OFFS_TMP_HI + ldi zl, LOW(mLayoutCallbackSetTmp) + ldi zh, HIGH(mLayoutCallbackSetTmp) + ldd r25, Y+MLAYOUT_OFFS_COLSORROWS + rcall mLayoutForEveryObjectContiguous ; (r18, r19, r25, Y) + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackSetTmp +; +; @param Y widget +; @param r21:r20 TMP to set +; @clobbers none + +mLayoutCallbackSetTmp: + std Y+WIDGET_OFFS_TMP_LO, r20 + std Y+WIDGET_OFFS_TMP_HI, r21 + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutColumnPositionX +; +; Set X and width to all columns of the row +; +; @param Y first widget of current row +; @param r22 spacing between widgets +; @param r23 border at beginning and and +; @clobbers r12, r13, r16-r21, r25, X + +mLayoutColumnPositionX: + mov xl, r23 ; start at border + clr xh + push yl + push yh + ldi zl, LOW(mLayoutCallbackPositionX) + ldi zh, HIGH(mLayoutCallbackPositionX) + ldd r25, Y+MLAYOUT_OFFS_COLSORROWS + rcall mLayoutForEveryObjectContiguous ; (r12, r13, r16-r21, r25, Y) + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackPositionX +; +; @param Y widget +; @param r22 spacing between widgets +; @param X current X pos +; @clobbers r12, r13, r16-r21 + +mLayoutCallbackPositionX: + ldd r16, Y+OBJECT_OFFS_FLAGS + sbrs r16, WIDGET_FLAGS_VISIBLE_BIT + rjmp mLayoutCallbackPositionX_ret + ldd r18, Y+WIDGET_OFFS_TMP_LO ; calculated cell width + ldd r19, Y+WIDGET_OFFS_TMP_HI + ldd r12, Y+WIDGET_OFFS_WIDTH_LO ; default width + ldd r13, Y+WIDGET_OFFS_WIDTH_HI + ldd r17, Y+WIDGET_OFFS_PACK + andi r17, 3 ; WIDGET_PACK_HSELF0_BIT = 0, no shift necessary + rcall mLayoutPackCell ; R21:R20=relative pos (r17, r18, r19) + add r20, xl + adc r21, xh + std Y+WIDGET_OFFS_X_LO, r20 ; set new X + std Y+WIDGET_OFFS_X_HI, r21 + std Y+WIDGET_OFFS_WIDTH_LO, r18 ; set new width + std Y+WIDGET_OFFS_WIDTH_HI, r19 + add xl, r18 ; advance X + adc xh, r19 + add xl, r22 ; add spacing + adc xh, r22 + sub xh, r22 +mLayoutCallbackPositionX_ret: + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutColumnPositionY +; +; Set X and width to all columns of the row +; +; @param Y first widget of current row +; @param r22 spacing between widgets +; @param r23 border at beginning and end +; @clobbers r12, r13, r16-r21, r25, X + +mLayoutColumnPositionY: + mov xl, r23 ; start at border + clr xh + push yl + push yh + ldi zl, LOW(mLayoutCallbackPositionY) + ldi zh, HIGH(mLayoutCallbackPositionY) + ldd r25, Y+MLAYOUT_OFFS_COLSORROWS + rcall mLayoutForEveryObjectSkipped ; (r12, r13, r16-r21, r25, Y) + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackPositionY +; +; @param Y widget +; @param r22 spacing between widgets +; @param X current Y pos +; @clobbers r12, r13, r16-r21 + +mLayoutCallbackPositionY: + ldd r16, Y+OBJECT_OFFS_FLAGS + sbrs r16, WIDGET_FLAGS_VISIBLE_BIT + rjmp mLayoutCallbackPositionY_ret + ldd r18, Y+WIDGET_OFFS_TMP_LO ; calculated cell width + ldd r19, Y+WIDGET_OFFS_TMP_HI + ldd r12, Y+WIDGET_OFFS_HEIGHT_LO ; default width + ldd r13, Y+WIDGET_OFFS_HEIGHT_HI + ldd r17, Y+WIDGET_OFFS_PACK + lsr r17 ; WIDGET_PACK_VSELF0_BIT = 2 -> shift 2 times right + lsr r17 + andi r17, 3 + rcall mLayoutPackCell ; R21:R20=relative pos (r17, r18, r19) + add r20, xl + adc r21, xh + std Y+WIDGET_OFFS_Y_LO, r20 ; set new Y + std Y+WIDGET_OFFS_Y_HI, r21 + std Y+WIDGET_OFFS_HEIGHT_LO, r18 ; set new width + std Y+WIDGET_OFFS_HEIGHT_HI, r19 + add xl, r18 ; advance Y + adc xh, r19 + add xl, r22 ; add spacing + adc xh, r22 + sub xh, r22 +mLayoutCallbackPositionY_ret: + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutColumnExpandColumns +; +; Calculate additional space per expandable widget in a row. +; +; @param Y first widget of current row +; @return CFLAG set if there is additional space to distribute +; @return r21:r20 space to add to every expandable widget +; @clobbers r16-r23, r25 + +mLayoutColumnExpandColumns: + rcall mLayoutColumnCalcAddSpacePerColumn ; r21:r20=additional space (r16-r23, r25) + brcc mLayoutColumnExpandColumns_ret + + ldi r22, (1<