; *************************************************************************** ; copyright : (C) 2025 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. * ; *************************************************************************** ; *************************************************************************** ; defs .equ WID_WIDGET_INTER_BORDER = 2 ; *************************************************************************** ; code .cseg ; --------------------------------------------------------------------------- ; @routine WID_Widget_new @global ; ; @param Y pointer to window SRAM ; @param X pointer to parent ; @param r18 WID_OFFS_OPTIONS1 ; @param r19 WID_OFFS_OPTIONS2 WID_Widget_Init: push r18 push r19 push xl push xh ldi zl, LOW(WID_Widget_Handler) ldi zh, HIGH(WID_Widget_Handler) clr r17 rcall OBJ_Init pop xh pop xl pop r19 pop r18 std Y+WID_OFFS_OPTIONS1, r18 std Y+WID_OFFS_OPTIONS2, r19 mov r16, xl or r16, xh breq WID_Widget_noParent ; copy defaults from parent adiw xh:xl, WID_OFFS_BG_COL_LO ld r16, X+ ; WID_OFFS_BG_COL_LO std Y+WID_OFFS_BG_COL_LO, r16 ld r16, X+ ; WID_OFFS_BG_COL_HI std Y+WID_OFFS_BG_COL_HI, r16 ld r16, X+ ; WID_OFFS_FG_COL_LO std Y+WID_OFFS_FG_COL_LO, r16 ld r16, X+ ; WID_OFFS_FG_COL_HI std Y+WID_OFFS_FG_COL_HI, r16 ld r16, X+ ; WID_OFFS_FONT_LO std Y+WID_OFFS_FONT_LO, r16 ld r16, X+ ; WID_OFFS_FONT_HI std Y+WID_OFFS_FONT_HI, r16 rjmp WID_Widget_end WID_Widget_noParent: ; preset without parent clr r16 std Y+WID_OFFS_FONT_LO, r16 std Y+WID_OFFS_FONT_HI, r16 std Y+WID_OFFS_FG_COL_LO, r16 ; foreground black std Y+WID_OFFS_FG_COL_HI, r16 dec r16 std Y+WID_OFFS_BG_COL_LO, r16 ; background white std Y+WID_OFFS_BG_COL_HI, r16 ldi r16, 2 ; default borders std Y+WID_OFFS_BORDER_TOP, r16 std Y+WID_OFFS_BORDER_BOT, r16 std Y+WID_OFFS_BORDER_LEFT, r16 std Y+WID_OFFS_BORDER_RIGHT, r16 WID_Widget_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine WID_Widget_Handler ; ; Signal handler for an object. A signal can have up to 3 parameters ; conveyed in registers R18, R19 and X. ; ; @param Y pointer to object SRAM ; @param r16 signal ; @param R18 1st param ; @param R19 2nd param ; @param X 3rd param ; @clobbers any, !Y WID_Widget_Handler: cpi r16, WID_SIGNAL_GETMINWIDTH breq WID_Widget_Handler_getMinWidth cpi r16, WID_SIGNAL_GETMINHEIGHT breq WID_Widget_Handler_getMinHeight cpi r16, WID_SIGNAL_LAYOUT breq WID_Widget_Handler_layout cpi r16, WID_SIGNAL_DRAW breq WID_Widget_Handler_draw ; for now just forward signal to all children WID_Widget_Handler_forward: rcall OBJ_ForwardSignalToChildren ret WID_Widget_Handler_getMinWidth: rjmp widgetGetMinWidth WID_Widget_Handler_getMinHeight: rjmp widgetGetMinHeight WID_Widget_Handler_layout: rjmp widgetLayout WID_Widget_Handler_draw: rjmp wDraw ; @end wDraw: ldd r16, Y+OBJ_OFFS_OPTIONS sbrs r16, WID_OPTIONS0_BIT_VISIBLE ; only draw visible widgets rjmp wDraw_ret cbr r16, (1< count all visible children rcall wGetSumOfMatchingVisibleChildrenHeights ; r19:r18=sum of all children heights pop r22 clr r23 ; r23:r22=number of visible expandable children ; calculate number of bytes to add to each expandable child widget ldd r20, Y+WID_OFFS_HEIGHT_LO ; total height ldd r21, Y+WID_OFFS_HEIGHT_HI clr r16 ldd r17, Y+WID_OFFS_BORDER_TOP ; subtract top border sub r20, r17 sbc r21, r16 brcs wVLayout_heightTooSmall ; jmp if too small ldd r17, Y+WID_OFFS_BORDER_BOT ; subtract bottom border sub r20, r17 sbc r21, r16 brcs wVLayout_heightTooSmall ; jmp if too small sub r20, r18 ; r21:r20 = HEIGHT-SUM_OF_VIS_CHILDREN_HEIGHTS sbc r21, r19 brcc wVLayout_heightTooSmall breq wVLayout_yDone ; nothing to distribute bigcall Utils_Divu16_16_16 ; r17:r16 = r21:r20 / r23:r22 ; add additional pixel to heights of expandable child widgets rcall wAddToHeightsOfExpandableVisibleChildren wVLayout_yDone: rcall wSetRelYFromHeightInVisibleChildren rcall wAlignChildrenHorizontally ; rcall wSetAbsoluteCoords call in GUI loop after calling layout on all widgets wVLayout_heightTooSmall: ; TODO: how to handle this case? ret ; @end wSetAbsoluteCoords: push yl push yh wSetAbsoluteCoords_loop: ldd r18, Y+OBJ_OFFS_OPTIONS andi r18, WID_OPTIONS0_BIT_VISIBLE breq wSetAbsoluteCoords_nextSibling push yl push yh bigcall Tree_GetParentObject clr r18 clr r19 clr r20 clr r21 mov r17, xl or r17, xh breq wSetAbsoluteCoords_r1820set mov yl, xl mov yh, xh ldd r18, Y+WID_OFFS_ABS_X_LO ldd r19, Y+WID_OFFS_ABS_X_HI ldd r20, Y+WID_OFFS_ABS_Y_LO ldd r21, Y+WID_OFFS_ABS_Y_HI wSetAbsoluteCoords_r1820set: pop yh pop yl ; handle X ldd r16, Y+WID_OFFS_REL_X_LO ldd r17, Y+WID_OFFS_REL_X_HI add r16, r18 adc r17, r19 std Y+WID_OFFS_ABS_X_LO, r16 std Y+WID_OFFS_ABS_X_HI, r17 ; handle Y ldd r16, Y+WID_OFFS_REL_Y_LO ldd r17, Y+WID_OFFS_REL_Y_HI add r16, r20 adc r17, r21 std Y+WID_OFFS_ABS_Y_LO, r16 std Y+WID_OFFS_ABS_Y_HI, r17 bigcall Tree_GetObjectBelow rjmp wSetAbsoluteCoords_loopEnd wSetAbsoluteCoords_nextSibling: bigcall Tree_GetNextSibling wSetAbsoluteCoords_loopEnd: mov r17, xl or r17, xh breq wSetAbsoluteCoords_end mov yl, xl mov yh, xh rjmp wSetAbsoluteCoords_loop wSetAbsoluteCoords_end: pop yh pop yl ret ; @end ; --------------------------------------------------------------------------- ; @routine wAlignChildrenHorizontally ; ; Horizontally align children within the width of the parent widget. ; Only changes Y+WID_OFFS_REL_X_LO/HI. ; ; @param Y pointer to object SRAM ; @clobbers r16, r17, r18, r19, r24, r25 wAlignChildrenHorizontally: push yl push yh ldd r24, Y+WID_OFFS_WIDTH_LO ; parent width ldd r25, Y+WID_OFFS_WIDTH_HI ldd r19, Y+WID_OFFS_BORDER_LEFT ; subtract left border mov r16, r19 clr r17 sub r24, r16 sbc r25, r17 ldd r16, Y+WID_OFFS_BORDER_RIGHT ; subtract right border sub r24, r16 sbc r25, r17 ; r25:r24=parent width minus lateral borders, r19=left border rcall Tree_GetFirstChildObject ; (none) wAlignChildrenHorizontally_loop: mov r17, xl or r17, xh breq wAlignChildrenHorizontally_loopEnd mov yl, xl mov yh, yl ldd r18, Y+OBJ_OFFS_OPTIONS andi r18, WID_OPTIONS0_BIT_VISIBLE breq wAlignChildrenHorizontally_loopNext push r24 push r25 push r19 rcall wAlignHorizontally pop r19 add r24, r19 adc r25, r19 sub r25, r19 std Y+WID_OFFS_REL_X_LO, r24 std Y+WID_OFFS_REL_X_HI, r25 pop r25 pop r24 wAlignChildrenHorizontally_loopNext: rcall Tree_GetNextSibling ; (none) rjmp wAlignChildrenHorizontally_loop wAlignChildrenHorizontally_loopEnd: pop yh pop yl ret ; @end ; --------------------------------------------------------------------------- ; @routine wAlignHorizontally ; ; @param r25:r24 parent width minus lateral borders ; @return r25:r24 proposed X position relative to parent ; @clobbers r16, r17 wAlignHorizontally: ldd r16, Y+WID_OFFS_OPTIONS1 sbrc r16, WID_OPTIONS1_BIT_STRETCH_X rjmp wAlignHorizontally_stretch andi r16, (WID_OPTIONS1_BIT_HALIGN0 | WID_OPTIONS1_BIT_HALIGN1) cpi r16, (0<