From 30be5b36810d2c0f011d771e5b1b91eeb8b767d1 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Mon, 23 Mar 2026 00:20:36 +0100 Subject: [PATCH] gui2: fixed an important bug (was decrementing r25!) --- avr/modules/lcd2/gui2/base/mlayout.asm | 79 +- avr/modules/lcd2/gui2/base/mlayout2.asm | 1151 +++++++++++++++++++++++ 2 files changed, 1208 insertions(+), 22 deletions(-) create mode 100644 avr/modules/lcd2/gui2/base/mlayout2.asm diff --git a/avr/modules/lcd2/gui2/base/mlayout.asm b/avr/modules/lcd2/gui2/base/mlayout.asm index f395b70..918c6a0 100644 --- a/avr/modules/lcd2/gui2/base/mlayout.asm +++ b/avr/modules/lcd2/gui2/base/mlayout.asm @@ -19,6 +19,30 @@ +.macro M_MLAYOUT_FOREVERY_CONT + push yl + push yh + ldi zl, LOW(@0) + ldi zh, HIGH(@0) + rcall mLayoutForEveryObjectContiguous + pop yh + pop yl +.endmacro + + + +.macro M_MLAYOUT_FOREVERY_SKIPPED + push yl + push yh + ldi zl, LOW(@0) + ldi zh, HIGH(@0) + rcall mLayoutForEveryObjectSkipped + pop yh + pop yl +.endmacro + + + ; *************************************************************************** ; defines @@ -266,9 +290,9 @@ 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 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 r12, Y+WIDGET_OFFS_HEIGHT_LO ; default height ldd r13, Y+WIDGET_OFFS_HEIGHT_HI ldd r17, Y+WIDGET_OFFS_PACK lsr r17 ; WIDGET_PACK_VSELF0_BIT = 2 -> shift 2 times right @@ -283,8 +307,8 @@ mLayoutCallbackPositionY: 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 +; std Y+WIDGET_OFFS_HEIGHT_LO, r12 ; set new height +; std Y+WIDGET_OFFS_HEIGHT_HI, r13 add xl, r18 ; advance Y adc xh, r19 add xl, r22 ; add spacing @@ -380,7 +404,7 @@ mLayoutSetupFirstSkipped: ; ; @param Y object to start with ; @param r25 number of widgets to skip -; @clobbers r18, r19, r25 +; @clobbers r18, r19 mLayoutCallbackSetupFirstSkipped: push zl @@ -406,7 +430,7 @@ mLayoutCallbackSetupFirstSkipped: ; @param Y object to start with ; @param r25 number of widgets to handle ; @return r21:r20 maximum TMP value encountered -; @clobbers r18, r19, r25, Z +; @clobbers r18, r19, Z mLayoutGetMaxTmpContiguous: push yl @@ -752,7 +776,7 @@ mLayoutCopyTmpToHeight: push yh ldi zl, LOW(mLayoutCallbackCopyTmpToHeight) ldi zh, HIGH(mLayoutCallbackCopyTmpToHeight) - rcall mLayoutForEveryObjectContiguous ; (r18, r19, r25, Y) + rcall mLayoutForEveryObjectContiguous ; (r18, r19, Y) pop yh pop yl ret @@ -781,7 +805,7 @@ mLayoutCallbackCopyTmpToHeight: ; @routine mLayoutSumContiguous ; ; @param Y object to start with -; @param r25 number of widgets to handle +; @param r25 widgets per column/row ; @param r22 spacing between widgets ; @param r23 border at beginning and and ; @return r21:r20 total size in the given dimension including borders and inter-widget spacing @@ -792,7 +816,6 @@ mLayoutSumContiguous: push yh mov r20, r23 ; start with border clr r21 - clr r25 ldi zl, LOW(mLayoutCallbackAddToSum) ldi zh, HIGH(mLayoutCallbackAddToSum) rcall mLayoutForEveryObjectContiguous ; (r18, r19, r25, Y) @@ -886,25 +909,33 @@ mLayoutCallbackAddToSum: mLayoutForEveryObjectContiguous: push r25 + mov r18, r25 mLayoutForEveryObjectContiguous_loop: - push r25 - push yl - push yh - icall - pop yh - pop yl - pop r25 + push r18 + push r25 + push yl + push yh + icall + pop yh + pop yl + pop r25 + pop r18 brcs mLayoutForEveryObjectContiguous_ret - tst r25 + tst r18 breq mLayoutForEveryObjectContiguous_next - dec r25 + dec r18 clc breq mLayoutForEveryObjectContiguous_ret mLayoutForEveryObjectContiguous_next: - bigcall OBJ_GetNext - brcc mLayoutForEveryObjectContiguous_ret - mov yl, r18 - mov yh, r19 + push r18 + bigcall OBJ_GetNext + brcs mLayoutForEveryObjectContiguous_loopEnd + pop r18 + rjmp mLayoutForEveryObjectContiguous_ret +mLayoutForEveryObjectContiguous_loopEnd: + mov yl, r18 + mov yh, r19 + pop r18 rjmp mLayoutForEveryObjectContiguous_loop mLayoutForEveryObjectContiguous_ret: pop r25 @@ -934,6 +965,10 @@ mLayoutForEveryObjectContiguous_ret: ; @clobbers r18, r19, Y {any} mLayoutForEveryObjectSkipped: + tst r25 + brne mLayoutForEveryObjectSkipped_loop +bigjmp DEBUG2 + mLayoutForEveryObjectSkipped_loop: push r25 push yl diff --git a/avr/modules/lcd2/gui2/base/mlayout2.asm b/avr/modules/lcd2/gui2/base/mlayout2.asm new file mode 100644 index 0000000..1a9b3d3 --- /dev/null +++ b/avr/modules/lcd2/gui2/base/mlayout2.asm @@ -0,0 +1,1151 @@ +; *************************************************************************** +; 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?? + + + +.macro M_MLAYOUT_FOREVERY_CONT + push yl + push yh + ldi zl, LOW(@0) + ldi zh, HIGH(@0) + rcall mLayoutForEveryObjectContiguous + pop yh + pop yl +.endmacro + + + +.macro M_MLAYOUT_FOREVERY_SKIPPED + push yl + push yh + ldi zl, LOW(@0) + ldi zh, HIGH(@0) + rcall mLayoutForEveryObjectSkipped + pop yh + pop yl +.endmacro + + + + + +; *************************************************************************** +; 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 + + + + +; --------------------------------------------------------------------------- +; @routine MLayout_OnLayout @global +; +; @param Y widget +; @clobbers any, !Y + +MLayout_OnLayout: + bigcall OBJ_GetFirstChild ; test for children + brcc MLayout_OnLayout_ret ; none, done here + + ldd r16, Y+MLAYOUT_OFFS_MODE + cpi r16, HLAYOUT_MODE_COLUMNS + breq MLayout_OnLayout_columns + rjmp MLayout_OnLayout_ret +MLayout_OnLayout_columns: + rcall MLayout_Layout_ColumnMode +MLayout_OnLayout_ret: + sec + ret + + +; --------------------------------------------------------------------------- +; @routine MLayout_OnGetDefaultWidth @global +; +; @param Y widget +; @clobbers any, !Y + +MLayout_OnGetDefaultWidth: + bigcall OBJ_GetFirstChild ; test for children + brcc MLayout_OnGetDefaultWidth_ret ; none, done here + + ldd r16, Y+MLAYOUT_OFFS_MODE + cpi r16, HLAYOUT_MODE_COLUMNS + breq MLayout_OnGetDefaultWidth_columns + rjmp MLayout_OnLayout_ret +MLayout_OnGetDefaultWidth_columns: + rcall MLayout_OnGetDefaultWidth_ColumnMode +MLayout_OnGetDefaultWidth_ret: + sec + ret + + + +; --------------------------------------------------------------------------- +; @routine MLayout_OnGetDefaultHeight @global +; +; @param Y widget +; @clobbers any, !Y + +MLayout_OnGetDefaultHeight: + bigcall OBJ_GetFirstChild ; test for children + brcc MLayout_OnGetDefaultHeight_ret ; none, done here + + ldd r16, Y+MLAYOUT_OFFS_MODE + cpi r16, HLAYOUT_MODE_COLUMNS + breq MLayout_OnGetDefaultHeight_columns + rjmp MLayout_OnLayout_ret +MLayout_OnGetDefaultHeight_columns: + rcall MLayout_OnGetDefaultHeight_ColumnMode +MLayout_OnGetDefaultHeight_ret: + sec + ret + + + +; --------------------------------------------------------------------------- +; @routine MLayout_GetFirstChildToY +; +; @param Y widget +; @return CFLAG set if child found, cleared on error +; @return Y first child widget +; @clobbers none + +MLayout_GetFirstChildToY: + push r18 + push r19 + bigcall OBJ_GetFirstChild + brcc MLayout_GetFirstChildToY_ret + mov yl, r18 + mov yh, r19 +MLayout_GetFirstChildToY_ret: + pop r19 + pop r18 + 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 mLayoutCallbackSetXTmp +; +; @param Y widget +; @param r21:r20 TMP to set +; @param X X to set +; @clobbers none + +mLayoutCallbackSetXTmp: + std Y+WIDGET_OFFS_X_LO, xl + std Y+WIDGET_OFFS_X_HI, xh + std Y+WIDGET_OFFS_TMP_LO, r20 + std Y+WIDGET_OFFS_TMP_HI, r21 + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackSetYTmp +; +; @param Y widget +; @param r21:r20 TMP to set +; @param X Y to set +; @clobbers none + +mLayoutCallbackSetYTmp: + std Y+WIDGET_OFFS_Y_LO, xl + std Y+WIDGET_OFFS_Y_HI, xh + std Y+WIDGET_OFFS_TMP_LO, r20 + std Y+WIDGET_OFFS_TMP_HI, r21 + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackPositionX +; +; @param Y widget +; @param r22 spacing between widgets +; @param X current X pos +; @clobbers r10-r13, r16-r21 + +mLayoutCallbackPositionX: + ldd r20, Y+WIDGET_OFFS_TMP_LO + ldd r21, Y+WIDGET_OFFS_TMP_HI + std Y+WIDGET_OFFS_X_LO, xl ; set new X + std Y+WIDGET_OFFS_X_HI, xh + add xl, r20 ; add cell width + adc xh, r21 + add xl, r22 ; add spacing + adc xh, r22 + sub xh, r22 + clc + ret + + +; ldd r16, Y+OBJECT_OFFS_FLAGS +; sbrs r16, WIDGET_FLAGS_VISIBLE_BIT +; rjmp mLayoutCallbackPositionX_ret + ldd r10, Y+WIDGET_OFFS_TMP_LO ; calculated cell width + ldd r11, 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 + push r10 ; cell width + push r11 + rcall mLayoutPackCell ; R21:R20=relative pos, R19:R18=new size (r17, r18, r19) + pop r11 + pop r10 + 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, r10 ; advance X + adc xh, r11 + add xl, r22 ; add spacing + adc xh, r22 + sub xh, r22 +mLayoutCallbackPositionX_ret: + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackPositionY +; +; @param Y widget +; @param r22 spacing between widgets +; @param X current Y pos +; @clobbers r10-r13, r16-r21 + +mLayoutCallbackPositionY: +; debug +ldi r20, 20 +clr r21 +std Y+WIDGET_OFFS_Y_LO, xl ; set new Y +std Y+WIDGET_OFFS_Y_HI, xh +add xl, r20 +adc xh, r21 +clc +ret + + ldd r16, Y+OBJECT_OFFS_FLAGS + sbrs r16, WIDGET_FLAGS_VISIBLE_BIT + rjmp mLayoutCallbackPositionY_ret + ldd r10, Y+WIDGET_OFFS_TMP_LO ; calculated cell width + ldd r11, Y+WIDGET_OFFS_TMP_HI + ldd r12, Y+WIDGET_OFFS_HEIGHT_LO ; default height + 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 + push r18 + push r19 + rcall mLayoutPackCell ; R21:R20=relative pos (r17, r18, r19) + pop r19 + pop r18 + 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, r12 ; set new height +; std Y+WIDGET_OFFS_HEIGHT_HI, r13 + 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 mLayoutSetupFirstContiguous +; +; For every contiguous widget (e.g. in a row) determine the maximum TMP value +; of all widgets orthogonal to that widget, e.g. when working in column mode: +; Get the highest width for every column and store that in the first widget of +; that column (i.e. in the first row). +; +; @param R25 widgets per row/column +; @param r25 widgets per row/column +; @clobbers r18, r19, Z + +mLayoutSetupFirstContiguous: + push yl + push yh + ldi zl, LOW(mLayoutCallbackSetupFirstContiguous) + ldi zh, HIGH(mLayoutCallbackSetupFirstContiguous) + rcall mLayoutForEveryObjectContiguous ; (r18, r19, Y) + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackSetupFirstContiguous +; +; @param Y object to start with +; @param r25 widgets per row/column +; @clobbers r18, r19, r20, r21 + +mLayoutCallbackSetupFirstContiguous: + push zl + push zh + push yl + push yh + rcall mLayoutGetMaxTmpSkipped ; (r18, r19, Z) + pop yh + pop yl + std Y+WIDGET_OFFS_TMP_LO, r20 + std Y+WIDGET_OFFS_TMP_HI, r21 + pop zh + pop zl + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutSetupFirstSkipped +; +; For every skipped widget (e.g. in a column) determine the maximum TMP value +; of all widgets orthogonal to that widget. +; Same as mLayoutSetupFirstContiguous except orthograde. +; +; @param Y object to start with +; @param r25 number of widgets to skip +; @clobbers r18, r19, Z + +mLayoutSetupFirstSkipped: + push yl + push yh + ldi zl, LOW(mLayoutCallbackSetupFirstSkipped) + ldi zh, HIGH(mLayoutCallbackSetupFirstSkipped) + rcall mLayoutForEveryObjectSkipped ; (r18, r19, Y) + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackSetupFirstSkipped +; +; For every skipped widget (e.g. in a column) determine the maximum TMP value +; of all widgets orthogonal to that widget. +; Same as mLayoutSetupFirstContiguous except orthograde. +; +; @param Y object to start with +; @param r25 number of widgets to skip +; @clobbers r18, r19 + +mLayoutCallbackSetupFirstSkipped: + push zl + push zh + push yl + push yh + rcall mLayoutGetMaxTmpContiguous ; (r18, r19, Z) + pop yh + pop yl + std Y+WIDGET_OFFS_TMP_LO, r20 + std Y+WIDGET_OFFS_TMP_HI, r21 + pop zh + pop zl + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutGetMaxTmpContiguous +; +; @param Y object to start with +; @param r25 number of widgets to handle +; @return r21:r20 maximum TMP value encountered +; @clobbers r18, r19, Z + +mLayoutGetMaxTmpContiguous: + push yl + push yh + clr r20 + clr r21 + ldi zl, LOW(mLayoutCallbackGetMaxTmp) + ldi zh, HIGH(mLayoutCallbackGetMaxTmp) + rcall mLayoutForEveryObjectContiguous ; (r18, r19, Y) + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutGetMaxTmpSkipped +; +; @param Y object to start with +; @param r25 number of widgets to skip after each widget handled +; @return r21:r20 maximum TMP value encountered +; @clobbers r18, r19, Z + +mLayoutGetMaxTmpSkipped: + push yl + push yh + clr r20 + clr r21 + ldi zl, LOW(mLayoutCallbackGetMaxTmp) + ldi zh, HIGH(mLayoutCallbackGetMaxTmp) + rcall mLayoutForEveryObjectSkipped ; (r18, r19, Y) + pop yh + pop yl + ret +; @end + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackGetMaxTmp +; +; @param Y object whose TMP value is to be added +; @param r21:r20 current maximum value +; @return CFLAG clear (to not abort the loop function) +; @clobbers r18, r19 + +mLayoutCallbackGetMaxTmp: + ldd r18, Y+WIDGET_OFFS_TMP_LO + ldd r19, Y+WIDGET_OFFS_TMP_HI + cp r20, r18 + cpc r21, r19 + brcc mLayoutCallbackGetMaxTmp_ret + mov r20, r18 + mov r21, r19 +mLayoutCallbackGetMaxTmp_ret: + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCountChildrenMatchingPackContiguous +; +; @param Y object whose TMP value is to be added +; @param r22 mask for WIDGET_OFFS_PACK +; @param r23 value for WIDGET_OFFS_PACK +; @param r25 number of widgets to handle +; @return r20 number of matching children +; @clobbers r18, r19 + +mLayoutCountChildrenMatchingPackContiguous: + push yl + push yh + clr r20 + ldi zl, LOW(mLayoutCallbackCountChildrenMatchingPack) + ldi zh, HIGH(mLayoutCallbackCountChildrenMatchingPack) + rcall mLayoutForEveryObjectContiguous ; (r18, r19, Y) + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCountChildrenMatchingPackSkipped +; +; @param Y object whose TMP value is to be added +; @param r22 mask for WIDGET_OFFS_PACK +; @param r23 value for WIDGET_OFFS_PACK +; @param r25 number of widgets to handle (0=all) +; @return r20 number of matching children +; @clobbers r18, r19, r25 + +mLayoutCountChildrenMatchingPackSkipped: + push yl + push yh + clr r20 + ldi zl, LOW(mLayoutCallbackCountChildrenMatchingPack) + ldi zh, HIGH(mLayoutCallbackCountChildrenMatchingPack) + rcall mLayoutForEveryObjectSkipped ; (r18, r19, Y) + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackCountChildrenMatchingPack +; +; @param Y object whose TMP value is to be added +; @param r20 number of matching children so far +; @param r22 mask for WIDGET_OFFS_PACK +; @param r23 value for WIDGET_OFFS_PACK +; @return CFLAG clear (to not abort the loop function) +; @clobbers r18 + +mLayoutCallbackCountChildrenMatchingPack: + ldd r18, Y+OBJECT_OFFS_FLAGS + sbrs r18, WIDGET_FLAGS_VISIBLE_BIT + rjmp mLayoutCallbackCountChildrenMatchingPack_ret + ldd r18, Y+WIDGET_OFFS_PACK + eor r18, r23 + and r18, r22 + brne mLayoutCallbackCountChildrenMatchingPack_ret + inc r20 +mLayoutCallbackCountChildrenMatchingPack_ret: + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutExpandChildrenMatchingPackContiguous +; +; @param Y object whose TMP value is to be added +; @param r21:r20 value to add to TMP +; @param r22 mask for WIDGET_OFFS_PACK +; @param r23 value for WIDGET_OFFS_PACK +; @param r25 number of widgets to handle +; @clobbers r18, r19 + +mLayoutExpandChildrenMatchingPackContiguous: + push yl + push yh + clr r20 + ldi zl, LOW(mLayoutCallbackExpandChildrenMatchingPack) + ldi zh, HIGH(mLayoutCallbackExpandChildrenMatchingPack) + rcall mLayoutForEveryObjectContiguous ; (r18, r19, Y) + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutExpandChildrenMatchingPackSkipped +; +; @param Y object whose TMP value is to be added +; @param r21:r20 value to add to TMP +; @param r22 mask for WIDGET_OFFS_PACK +; @param r23 value for WIDGET_OFFS_PACK +; @param r25 number of widgets to skip +; @clobbers r18, r19 + +mLayoutExpandChildrenMatchingPackSkipped: + push yl + push yh + clr r20 + ldi zl, LOW(mLayoutCallbackExpandChildrenMatchingPack) + ldi zh, HIGH(mLayoutCallbackExpandChildrenMatchingPack) + rcall mLayoutForEveryObjectSkipped ; (r18, r19, Y) + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackExpandChildrenMatchingPack +; +; @param Y object whose TMP value is to be added +; @param r21:r20 space to add to expandable widgets +; @param r22 mask for WIDGET_OFFS_PACK +; @param r23 value for WIDGET_OFFS_PACK +; @return CFLAG clear (to not abort the loop function) +; @clobbers r18, r19 + +mLayoutCallbackExpandChildrenMatchingPack: + ldd r18, Y+OBJECT_OFFS_FLAGS + sbrs r18, WIDGET_FLAGS_VISIBLE_BIT + rjmp mLayoutCallbackExpandChildrenMatchingPack_ret + ldd r18, Y+WIDGET_OFFS_PACK + eor r18, r23 + and r18, r22 + brne mLayoutCallbackExpandChildrenMatchingPack_ret + ldd r18, Y+WIDGET_OFFS_TMP_LO + ldd r19, Y+WIDGET_OFFS_TMP_HI + add r18, r20 + adc r19, r21 + std Y+WIDGET_OFFS_TMP_LO, r18 + std Y+WIDGET_OFFS_TMP_HI, r19 +mLayoutCallbackExpandChildrenMatchingPack_ret: + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutSetDefaultWidthToTmp +; +; @param Y object to start with +; @param r25 number of widgets to handle (0=any) +; @clobbers any, !Y + +mLayoutSetDefaultWidthToTmp: + push yl + push yh + ldi zl, LOW(mLayoutCallbackDefaultWidthToTmp) + ldi zh, HIGH(mLayoutCallbackDefaultWidthToTmp) + rcall mLayoutForEveryObjectContiguous ; (any) + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackDefaultWidthToTmp +; +; @param Y object whose TMP value is to be added +; @return CFLAG clear (to not abort the loop function) +; @clobbers r18, r19 (any, !Y) + +mLayoutCallbackDefaultWidthToTmp: + push zl + push zh + bigcall Widget_GetDefaultWidth ; (any, !Y) + pop zh + pop zl + std Y+WIDGET_OFFS_TMP_LO, r18 + std Y+WIDGET_OFFS_TMP_HI, r19 + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutSetDefaultHeightToTmp +; +; @param Y object to start with +; @param r25 number of widgets to handle (0=any) +; @clobbers any, !Y + +mLayoutSetDefaultHeightToTmp: + push yl + push yh + ldi zl, LOW(mLayoutCallbackDefaultHeightToTmp) + ldi zh, HIGH(mLayoutCallbackDefaultHeightToTmp) + rcall mLayoutForEveryObjectContiguous ; (any) + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackDefaultHeightToTmp +; +; @param Y object whose TMP value is to be added +; @return CFLAG clear (to not abort the loop function) +; @clobbers r18, r19 (any, !Y) + +mLayoutCallbackDefaultHeightToTmp: + push zl + push zh + bigcall Widget_GetDefaultHeight ; (any, !Y) + pop zh + pop zl + std Y+WIDGET_OFFS_TMP_LO, r18 + std Y+WIDGET_OFFS_TMP_HI, r19 + clc + ret +; @end + + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCopyTmpToWidth +; +; @param Y object to start with +; @param r25 number of widgets to handle (0=all) +; @clobbers r18, r19, Z + +mLayoutCopyTmpToWidth: + push yl + push yh + ldi zl, LOW(mLayoutCallbackCopyTmpToWidth) + ldi zh, HIGH(mLayoutCallbackCopyTmpToWidth) + rcall mLayoutForEveryObjectContiguous ; (r18, r19, Y) + pop yh + pop yl + ret +; @end + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackCopyTmpToWidth +; +; @param Y object to start with +; @clobbers r18, r19 + +mLayoutCallbackCopyTmpToWidth: + 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 + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCopyTmpToHeight +; +; @param Y object to start with +; @param r25 number of widgets to handle (0=all) +; @clobbers r18, r19, Z + +mLayoutCopyTmpToHeight: + push yl + push yh + ldi zl, LOW(mLayoutCallbackCopyTmpToHeight) + ldi zh, HIGH(mLayoutCallbackCopyTmpToHeight) + rcall mLayoutForEveryObjectContiguous ; (r18, r19, Y) + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackCopyTmpToHeight +; +; @param Y object to start with +; @clobbers r18, r19 + +mLayoutCallbackCopyTmpToHeight: + ldd r18, Y+WIDGET_OFFS_TMP_LO + ldd r19, Y+WIDGET_OFFS_TMP_HI + std Y+WIDGET_OFFS_HEIGHT_LO, r18 + std Y+WIDGET_OFFS_HEIGHT_HI, r19 + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutSumContiguous +; +; @param Y object to start with +; @param r25 widgets per column/row +; @param r22 spacing between widgets +; @param r23 border at beginning and and +; @return r21:r20 total size in the given dimension including borders and inter-widget spacing +; @clobbers r18, r19, r25 + +mLayoutSumContiguous: + push yl + push yh + mov r20, r23 ; start with border + clr r21 + ldi zl, LOW(mLayoutCallbackAddToSum) + ldi zh, HIGH(mLayoutCallbackAddToSum) + rcall mLayoutForEveryObjectContiguous ; (r18, r19, r25, Y) + sub r20, r22 ; undo last adding inter-widget space + sbc r21, r22 + add r21, r22 + add r20, r23 ; end with border + adc r21, r23 + sub r21, r23 + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutSumSkipped +; +; @param Y object to start with +; @param r25 number of widgets to skip after each widget handled +; @param r22 spacing between widgets +; @param r23 border at beginning and end +; @return r21:r20 sum of TMP values +; @clobbers r18, r19, r25 + +mLayoutSumSkipped: + push yl + push yh + mov r20, r23 ; start with border + clr r21 + ldi zl, LOW(mLayoutCallbackAddToSum) + ldi zh, HIGH(mLayoutCallbackAddToSum) + rcall mLayoutForEveryObjectSkipped ; (r18, r19, r25, Y) + sub r20, r22 ; undo last adding inter-widget space + sbc r21, r22 + add r21, r22 + add r20, r23 ; end with border + adc r21, r23 + sub r21, r23 + pop yh + pop yl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutCallbackAddToSum +; +; @param Y object whose TMP value is to be added +; @param r25 number of widgets to handle +; @param r21:r20 sum so far (TMP will be added to it) +; @param r22 spacing between widgets +; @return CFLAG clear (to not abort the loop function) +; @clobbers r18, r19 + +mLayoutCallbackAddToSum: + ldd r18, Y+WIDGET_OFFS_TMP_LO + ldd r19, Y+WIDGET_OFFS_TMP_HI + add r20, r18 ; add TMP + adc r21, r19 + add r20, r22 ; add spacing + adc r21, r22 + sub r21, r22 + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutForEveryObjectContiguous +; +; This routine itself uses R18, R19, R25 and Y. All other registers may be +; passed to the callback routine. +; However, the callback function must make sure that it doesn't modify registers +; which are to be passed to next objects later! +; +; This routine traverses the given number of contiguous objects until there is no +; next object. +; +; Y and R25 are preserved around the callback. Z MUST NOT be modified by the callback! +; +; @param Y object to start with +; @param r25 number of widgets to handle (0=all) +; @param Z pointer to routine to call (using ICALL) +; @return CFLAG set if the callback returned with CFLAG set on any widget +; @return Y object on which the call returned with CFLAG set (otherwise last object handled) +; @clobbers r18, r19, Y {any} + +mLayoutForEveryObjectContiguous: + push r25 + mov r18, r25 +mLayoutForEveryObjectContiguous_loop: + push r18 + push r25 + push yl + push yh + icall + pop yh + pop yl + pop r25 + pop r18 + brcs mLayoutForEveryObjectContiguous_ret + tst r18 + breq mLayoutForEveryObjectContiguous_next + dec r18 + clc + breq mLayoutForEveryObjectContiguous_ret +mLayoutForEveryObjectContiguous_next: + push r18 + bigcall OBJ_GetNext + brcs mLayoutForEveryObjectContiguous_loopEnd + pop r18 + rjmp mLayoutForEveryObjectContiguous_ret +mLayoutForEveryObjectContiguous_loopEnd: + mov yl, r18 + mov yh, r19 + pop r18 + rjmp mLayoutForEveryObjectContiguous_loop +mLayoutForEveryObjectContiguous_ret: + pop r25 + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutForEveryObjectSkipped +; +; This routine itself uses R18, R19, R25 and Y. All other registers may be +; passed to the callback routine. +; However, the callback function must make sure that it doesn't modify registers +; which are to be passed to next objects later! +; +; This routine traverses the given objects skipping [R25] objects after each round +; until there is no next object. +; +; Y and R25 are preserved around the callback. Z MUST NOT be modified by the callback! +; +; @param Y object to start with +; @param r25 number of widgets to skip per round +; @param Z pointer to routine to call (using ICALL) +; @return CFLAG set if the callback returned with CFLAG set on any widget +; @return Y object on which the call returned with CFLAG set (garbage otherwise) +; @clobbers r18, r19, Y {any} + +mLayoutForEveryObjectSkipped: +mLayoutForEveryObjectSkipped_loop: + push r25 + push yl + push yh + icall + pop yh + pop yl + pop r25 + brcs mLayoutForEveryObjectSkipped_ret + push r16 + mov r16, r25 + bigcall OBJ_SkipObjects ; (R16) + pop r16 + brcc mLayoutForEveryObjectSkipped_ret + mov yl, r18 + mov yh, r19 + rjmp mLayoutForEveryObjectSkipped_loop +mLayoutForEveryObjectSkipped_ret: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutGetBorders +; +; @param Y address of widget +; @return r22 spacing +; @return r23 outer borders +; @clobbers Z + +mLayoutGetBorders: + ldd zl, Y+WIDGET_OFFS_STYLE_LO + ldd zh, Y+WIDGET_OFFS_STYLE_HI + adiw zh:zl, WIDGET_STYLE_OFFS_SPACING + lpm r22, Z + sbiw zh:zl, WIDGET_STYLE_OFFS_SPACING + adiw zh:zl, WIDGET_STYLE_OFFS_OUTERBORDERSIZE + lpm r23, Z + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine mLayoutPackCell +; +; @param Y address of widget +; @param r17 pack mode (see @ref WIDGET_PACK_BEGIN) +; @param R11:R10 size of cell area (i.e. width or height) +; @param R13:R12 size of object to pack (i.e. width or height) +; @param r22 spacing (between widgets) +; @return R21:R20 pos +; @return R19:R18 new size of widget +; @clobbers r17, r18, r19 + +mLayoutPackCell: + clr r20 ; preset pos + clr r21 + mov r18, r13 ; preset widget size + mov r19, r12 + + ; subtract borders from cell size + sub r10, r22 ; subtract spacing + sbc r11, r22 + add r11, r22 + + andi r17, 3 ; only 2 bits pack mode + cpi r17, WIDGET_PACK_FILLED + breq mLayoutPackCell_filled + 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_filled: + mov r18, r10 ; use full cell size (minus spacing) + mov r19, r11 + rjmp mLayoutPackCell_ret +mLayoutPackCell_end: + sub r10, r12 + sbc r11, r13 + mov r20, r10 + mov r21, r11 + rjmp mLayoutPackCell_ret +mLayoutPackCell_center: + sub r10, r12 + sbc r11, r13 + lsr r11 + ror r10 + mov r20, r10 + mov r21, r11 + rjmp mLayoutPackCell_ret +mLayoutPackCell_ret: + ret +; @end + + + + + + + + +; *************************************************************************** +; data in FLASH + +MLayout_DefaultSignalmap: + ; header + .dw Widget_DefaultSignalmap*2 ; next table to use + ; entries + .db 0, WIDGET_SIGNAL_LAYOUT, LOW(MLayout_OnLayout), HIGH(MLayout_OnLayout) + .db WIDGET_VALUE_DEFAULT_WIDTH, WIDGET_SIGNAL_GETVALUE, LOW(MLayout_OnGetDefaultWidth), HIGH(MLayout_OnGetDefaultWidth) + .db WIDGET_VALUE_DEFAULT_HEIGHT, WIDGET_SIGNAL_GETVALUE, LOW(MLayout_OnGetDefaultHeight), HIGH(MLayout_OnGetDefaultHeight) + + .db 0, 0, 0, 0 ; end of table + + + + +#endif +