; *************************************************************************** ; 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<