diff --git a/avr/modules/lcd2/win/widget.asm b/avr/modules/lcd2/win/widget.asm index 40c2fef..aee4957 100644 --- a/avr/modules/lcd2/win/widget.asm +++ b/avr/modules/lcd2/win/widget.asm @@ -103,6 +103,8 @@ WID_Widget_Handler: 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 ; for now just forward signal to all children WID_Widget_Handler_forward: rcall OBJ_ForwardSignalToChildren @@ -111,71 +113,182 @@ WID_Widget_Handler_getMinWidth: rjmp widgetGetMinWidth WID_Widget_Handler_getMinHeight: rjmp widgetGetMinHeight +WID_Widget_Handler_layout: + rjmp widgetLayout ; @end +widgetLayout: + rcall wSetChildrenWidthsFromMinWidths + rcall wSetChildrenHeightsFromMinHeights -; --------------------------------------------------------------------------- -; @routine widgetGetMinWidth -; -; @return r19:r18 minimum width of widget -; @clobbers any, !Y + ; count number of expandable children + ldi r16, WID_OPTIONS1_BIT_STRETCH_Y + ldi r17, WID_OPTIONS1_BIT_STRETCH_Y + rcall widgetCountVisibleChildrenWithOptions1 ; (r18, r24, r25, X) + tst r18 + breq widgetLayout_Ydone ; no expandable children, nothing to distribute + ; determine full height needed by all children + push r18 ; number of visible expandable child widgets + clr r17 ; mask=0 -> 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 widgetLayout_heightTooSmall ; jmp if too small + ldd r17, Y+WID_OFFS_BORDER_BOT ; subtract bottom border + sub r20, r17 + sbc r21, r16 + brcs widgetLayout_heightTooSmall ; jmp if too small + + sub r20, r18 ; r21:r20 = HEIGHT-SUM_OF_VIS_CHILDREN_HEIGHTS + sbc r21, r19 + brcc widgetLayout_heightTooSmall + breq widgetLayout_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 -widgetGetMinWidth: - ldi r16, WID_SIGNAL_GETMINWIDTH - rjmp widgetGetMinSize +widgetLayout_yDone: + rcall wSetRelYFromHeightInVisibleChildren + rcall wAlignChildrenHorizontally +widgetLayout_heightTooSmall: + ; TODO: how to handle this case? + ret ; @end ; --------------------------------------------------------------------------- -; @routine widgetGetMinHeight +; @routine wAlignChildrenHorizontally ; -; @return r19:r18 minimum height of widget -; @clobbers any, !Y - -widgetGetMinHeight: - ldi r16, WID_SIGNAL_GETMINHEIGHT - rjmp widgetGetMinSize -; @end - - - -; --------------------------------------------------------------------------- -; @routine widgetGetMinSize +; Horizontally align children within the width of the parent widget. +; Only changes Y+WID_OFFS_REL_X_LO/HI. ; -; @param r16 signal to send (WID_SIGNAL_GETMINWIDTH, WID_SIGNAL_GETMINHEIGHT) -; @return r19:r18 minimum width or height of widget -; @clobbers any, !Y +; @param Y pointer to object SRAM +; @clobbers r16, r17, r18, r19, r24, r25 -widgetGetMinSize: +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) - clr r24 - clr r25 -widgetGetMinSize_loop: +wAlignChildrenHorizontally_loop: mov r17, xl or r17, xh - breq widgetGetMinSize_loopEnd + breq wAlignChildrenHorizontally_loopEnd mov yl, xl mov yh, yl - push r16 - push r24 - push r25 - ldi r18, 1 ; default value for when the signal is not handled - ldi r19, 0 ; default value for when the signal is not handled - rcall OBJ_Handler ; ask child for its minimum size - pop r25 - pop r24 - pop r16 + 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 + andi r16, (WID_OPTIONS1_BIT_HALIGN0 | WID_OPTIONS1_BIT_HALIGN1) + cpi r16, (0<