diff --git a/avr/modules/lcd2/gui2/base/mlayout.asm b/avr/modules/lcd2/gui2/base/mlayout.asm new file mode 100644 index 0000000..f2e25f9 --- /dev/null +++ b/avr/modules/lcd2/gui2/base/mlayout.asm @@ -0,0 +1,689 @@ +; *************************************************************************** +; 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_MLAYOUT_ASM +#define AQH_AVR_GUI2_MLAYOUT_ASM + + +; TODO: use this class also for HLayout and VLayout, those are just special +; cases with only one row (HLayout) or column (VLayout) + + + +; *************************************************************************** +; 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(;LAYOUT_SIZE) + ldi r25, HIGH(;LAYOUT_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: +MLayout_OnGetDefaultWidth: +MLayout_OnGetDefaultHeight: + ret + + + +; --------------------------------------------------------------------------- +; @routine mLayoutColumnsHorizontally +; +; @param Y pointer to widget + +mLayoutColumnsHorizontally: + bigcall OBJ_GetFirstChild ; test for children + brcc mLayoutColumnsHorizontally_ret ; none, done here + + ; preparations + rcall Layout_SetDefaultWidths ; calc default widths of children and store in Y+WIDGET_OFFS_TMP + rcall mLayoutCopyTmpToWidth ; copy to width fields for later + rcall mLayoutGetBorders ; r22=spacing, r23=outer borders + ; calc size of each column and store it in the first widget of a column as TMP + rcall mLayoutCalcAndSetSizesSkipped ; (r18-r31, !Y) + ; calc total width of first row (which has the maximum sizes of each column) + rcall mLayoutCalcFirstSizesContiguous ; r21:r20 width of first row (r16, r18, r19, r24, r25) + ; layout columns of first row + rcall mLayoutColumnsExpandFirstRow ; TODO: only if FILL set in PACK byte! + ; copy layout from first row to all other rows + rcall mLayoutCopyTmpFromFirstLine + ; finally horizontally position all cells + rcall mLayoutColumnsPositionX +mLayoutColumnsHorizontally_ret: + ret +; @end + + + + +; --------------------------------------------------------------------------- +; @routine mLayoutColumnsPositionX +; +; @param Y pointer to widget +; @param r22 spacing (between widgets) +; @param r23 outer border size + +mLayoutColumnsPositionX: + push yl + push yh + bigcall OBJ_GetFirstChild + brcc mLayoutColumnsPositionX_done +mLayoutColumnsPositionX_loop1: + ldd r24, Y+MLAYOUT_OFFS_COLSORROWS + mov r4, r23 ; X pos (start at left border) + clr r5 +mLayoutColumnsPositionX_loop2: + 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 + ldi 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, r4 + adc r21, r5 + 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 r4, r18 ; advance X + adc r5, r19 + bigcall OBJ_GetNext + brcc mLayoutColumnsPositionX_done + mov yl, r18 + mov yh, r19 + dec r24 + brne mLayoutColumnsPositionX_loop2 + rjmp mLayoutColumnsPositionX_loop1 +mLayoutColumnsPositionX_done: + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutPackCell +; +; @param Y address of widget +; @param r19:r18 size of target widget (i.e. width or height) +; @param r17 pack mode (see @ref WIDGET_PACK_BEGIN) +; @param R13:R12 size of object to pack (i.e. width or height) +; @param r22 spacing (between widgets) +; @return R21:R20 pos +; @clobbers r17, r18, r19 + +mLayoutPackCell: + ; subtract borders + clr r23 + sub r18, r22 ; subtract spacing + sbc r19, r23 + + andi r17, 3 ; only 2 bits pack mode + cpi r17, WIDGET_PACK_END + breq mLayoutPackCell_end + cpi r17, WIDGET_PACK_CENTER + breq mLayoutPackCell_center + rjmp mLayoutPackCell_ret ; begin/filled, align at begin +mLayoutPackCell_end: + sub r18, r12 + sbc r19, r13 + add r20, r18 + adc r21, r19 + rjmp mLayoutPackCell_ret +mLayoutPackCell_center: + sub r18, r12 + sbc r19, r13 + lsr r19 + ror r18 + add r20, r18 + adc r21, r19 + rjmp mLayoutPackCell_ret +mLayoutPackCell_ret: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCopyTmpFromFirstLine +; +; TMP in widgets of first row/column contains the available space per cell. +; +; @param Y pointer to widget +; @clobbers r17, r18, r19, r20, r21, r24 + +mLayoutCopyTmpFromFirstLine: + push yl + push yh + ldd r24, Y+MLAYOUT_OFFS_COLSORROWS + bigcall OBJ_GetFirstChild +mLayoutCopyTmpFromFirstLine_loop: + push yl + push yh + ldd r20, Y+WIDGET_OFFS_TMP_LO + ldd r21, Y+WIDGET_OFFS_TMP_HI + ; goto same cell in next block (e.g. same column in next row) + ldd r17, Y+MLAYOUT_OFFS_COLSORROWS +mLayoutCopyTmpFromFirstLine_loop2: + bigcall OBJ_GetNext + brcc mLayoutCopyTmpFromFirstLine_nextColumn + mov yl, r18 + mov yh, r19 + dec r17 + brne mLayoutCopyTmpFromFirstLine_loop2 + std Y+WIDGET_OFFS_TMP_LO, r20 + std Y+WIDGET_OFFS_TMP_HI, r21 +mLayoutCopyTmpFromFirstLine_nextColumn: + pop yh + pop yl + bigcall OBJ_GetNext + brcc mLayoutCopyTmpFromFirstLine_done + mov yl, r18 + mov yh, r19 + rjmp mLayoutCopyTmpFromFirstLine_loop +mLayoutCopyTmpFromFirstLine_done: + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCopyTmpToWidth +; +; @param Y pointer to widget +; +mLayoutCopyTmpToWidth: + push yl + push yh + bigcall OBJ_GetFirstChild + brcc mLayoutCopyTmpToWidth_ret +mLayoutCopyTmpToWidth_loop: + mov yl, r18 + mov yh, r19 + ldd r18, Y+WIDGET_OFFS_TMP_LO + ldd r19, Y+WIDGET_OFFS_TMP_HI + std Y+WIDGET_OFFS_WIDTH_LO, r18 + std Y+WIDGET_OFFS_WIDTH_HI, r19 +mLayoutCopyTmpToWidth_next: + rcall OBJ_GetNext + brcs mLayoutCopyTmpToWidth_loop +mLayoutCopyTmpToWidth_ret: + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCountChildrenWithMatchingPackMode +; +; @param Y pointer to widget +; @param r21:r20 width of first row + +mLayoutColumnsExpandFirstRow: + ldd r24, Y+MLAYOUT_OFFS_COLSORROWS + ldi r25, 1 + ldi r22, (1<