; ***************************************************************************
; 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_MCLAYOUT_ASM
#define AQH_AVR_GUI2_MCLAYOUT_ASM


; ***************************************************************************
; defines

.equ MCLAYOUT_OFFS_BEGIN      =  WIDGET_SIZE
.equ MCLAYOUT_OFFS_MODE       =  MCLAYOUT_OFFS_BEGIN+0
.equ MCLAYOUT_OFFS_COLUMNS    =  MCLAYOUT_OFFS_BEGIN+1
.equ MCLAYOUT_SIZE            =  MCLAYOUT_OFFS_BEGIN+2



; ***************************************************************************
; code

.cseg



; ---------------------------------------------------------------------------
; @routine MCLayout_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 number of columns or rows (depending on mode in r20)
; @clobbers any

MCLayout_new:
  push r20
    ldi r24, LOW(MCLAYOUT_SIZE)
    ldi r25, HIGH(MCLAYOUT_SIZE)
    bigcall Object_Alloc         ; (!r16, !r17, !X)
  pop r20
  brcc MCLayout_new_ret
  rcall MCLayout_Init               ; (r16, r17, X)
  sec
MCLayout_new_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine MCLayout_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 number of columns or rows (depending on mode in r20)
; @clobbers r16, r17, X

MCLayout_Init:
  push r20
    ; call base class
    bigcall Widget_Init             ; (r16, r17, X)
  pop r20

  ; set widget-specific data
  std Y+MCLAYOUT_OFFS_COLUMNS, r20

  ; set default signal map
  ldi r16, LOW(MCLayout_DefaultSignalmap*2)
  std Y+OBJECT_OFFS_SIGNALMAP_LO, r16
  ldi r16, HIGH(MCLayout_DefaultSignalmap*2)
  std Y+OBJECT_OFFS_SIGNALMAP_HI, r16

  ret
; @end



; ---------------------------------------------------------------------------
; @routine MCLayout_OnGetDefaultHeight
;
; @param Y pointer to widget
; @return r19:r18 value
; @clobbers any, !Y

MCLayout_OnGetDefaultHeight:
;  rcall Layout_SetDefaultHeights
;  rcall Layout_GetMaxTmp
;  bigcall Widget_AddOuterStyleBorders   ; (r20, r21)
  ldi r18, 10
  clr r19
  sec
  ret

; @end



; ---------------------------------------------------------------------------
; @routine MCLayout_OnGetDefaultWidth
;
; @param Y pointer to widget
; @return r19:r18 value
; @clobbers any, !Y

MCLayout_OnGetDefaultWidth:
;  rcall Layout_SetDefaultWidths
;  rcall Layout_SumTmpValues     ; r19:r18=default width
  ldi r18, 10
  clr r19
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine MCLayout_OnLayout
;
; @param Y pointer to widget
; @clobbers any, !Y

MCLayout_OnLayout:
  ldd r25, Y+MCLAYOUT_OFFS_COLUMNS
  rcall Layout_CountChildrenSkipped   ; r16=number of rows used (r18, r19)

  mov r24, r16                        ; store for later
  ldd r17, Y+MCLAYOUT_OFFS_COLUMNS
  cp r16, r17
  brcc MCLayout_OnLayout_mkCtx
  mov r16, r17
MCLayout_OnLayout_mkCtx:
  ; create and preset context
  push r24                                ; num of children
    rcall LayoutCtx_CreateContextForN     ; X=ctx (any, !R16, !Y)
  pop r24
  brcc MCLayout_OnLayout_ret
  
  push r24                                ; num of children
    ldd r24, Y+MCLAYOUT_OFFS_COLUMNS
    rcall mcLayoutHorizontally
  pop r24
  rcall mcLayoutVertically
  
  ; release layout context
  bigcall LayoutCtx_free

  ; force re-drawing of this widget, clear layout bit
  ldd r16, Y+OBJECT_OFFS_FLAGS
  sbr r16, (1<<WIDGET_FLAGS_DIRTY_BIT)
  cbr r16, (1<<WIDGET_FLAGS_LAYOUT_BIT)
  std Y+OBJECT_OFFS_FLAGS, r16
MCLayout_OnLayout_ret:
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine mcLayoutVertically
;
; @param Y pointer to widget
; @param X layout context
; @param r24 number of rows
; @clobbers any, !X, !Y

mcLayoutVertically:
  ; prepare
  push xl
    push xh
      push r24
        rcall Layout_SetDefaultHeights ; (any, !Y)
      pop r24
    pop xh
  pop xl

  ldd r20, Y+WIDGET_OFFS_HEIGHT_LO
  ldd r21, Y+WIDGET_OFFS_HEIGHT_HI
  adiw xh:xl, LAYOUT_CTX_OFFS_TOTALSIZE_LO
  st X+, r20
  st X, r21
  sbiw xh:xl, (LAYOUT_CTX_OFFS_TOTALSIZE_LO+1)
  adiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS
  st X, r24
  sbiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS

  ; read positions and flags into new layout context
  ldd r25, Y+MCLAYOUT_OFFS_COLUMNS
  bigcall LayoutCtx_ReadYMaxDimsVertical     ; (r16-r20, Z)

  ; layout
  bigcall LayoutCtx_LayoutExpand             ; (r16-r25)

  ; pack
  ldd r25, Y+MCLAYOUT_OFFS_COLUMNS
  rcall LayoutCtx_PackYVertical              ; (r16, r18, r19, r24, Z)

  ret
; @end



; ---------------------------------------------------------------------------
; @routine mcLayoutHorizontally
;
; @param Y pointer to widget
; @param X layout context
; @param r24 number of items to use
; @clobbers any, !Y

mcLayoutHorizontally:
  ; prepare
  push xl
    push xh
      push r24
        rcall Layout_SetDefaultWidths  ; (any, !Y)
      pop r24
    pop xh
  pop xl

  ; setup layout context for horizontal operations
  ldd r20, Y+WIDGET_OFFS_WIDTH_LO
  ldd r21, Y+WIDGET_OFFS_WIDTH_HI
  adiw xh:xl, LAYOUT_CTX_OFFS_TOTALSIZE_LO
  st X+, r20
  st X, r21
  sbiw xh:xl, (LAYOUT_CTX_OFFS_TOTALSIZE_LO+1)
  adiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS
  st X, r24
  sbiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS

  ; read positions and flags into new layout context
  ldd r25, Y+MCLAYOUT_OFFS_COLUMNS
  bigcall LayoutCtx_ReadXMaxDimsHorizontal   ; (r16-r20, Z)

  ; layout
  bigcall LayoutCtx_LayoutExpand             ; (r16-r25)

  ; pack
  ldd r25, Y+MCLAYOUT_OFFS_COLUMNS
  rcall LayoutCtx_PackXHorizontal            ; (r16, r18, r19, r24, Z)

  ret
; @end








; ***************************************************************************
; data in FLASH

MCLayout_DefaultSignalmap:
  ; header
  .dw Widget_DefaultSignalmap*2  ; next table to use
  ; entries
  .db 0,                           WIDGET_SIGNAL_LAYOUT,   LOW(MCLayout_OnLayout),           HIGH(MCLayout_OnLayout)
  .db WIDGET_VALUE_DEFAULT_WIDTH,  WIDGET_SIGNAL_GETVALUE, LOW(MCLayout_OnGetDefaultWidth),  HIGH(MCLayout_OnGetDefaultWidth)
  .db WIDGET_VALUE_DEFAULT_HEIGHT, WIDGET_SIGNAL_GETVALUE, LOW(MCLayout_OnGetDefaultHeight), HIGH(MCLayout_OnGetDefaultHeight)

  .db 0, 0, 0, 0  ; end of table



#endif

