; ***************************************************************************
; 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_WLIST_ASM
#define AQH_AVR_GUI2_WLIST_ASM


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

.equ WLIST_OFFS_BEGIN       =  VLAYOUT_SIZE
.equ WLIST_OFFS_ELEMLIST_LO = VLAYOUT_OFFS_BEGIN+0
.equ WLIST_OFFS_ELEMLIST_HI = VLAYOUT_OFFS_BEGIN+1
.equ WLIST_OFFS_ELEMOFFSET =  VLAYOUT_OFFS_BEGIN+2
.equ WLIST_OFFS_ELEMNUM    =  VLAYOUT_OFFS_BEGIN+3
.equ WLIST_SIZE            =  VLAYOUT_OFFS_BEGIN+4


; signals
.equ WLIST_SIGNAL_MKOBJECT = WIDGET_SIGNAL_NEXTFREE+0
.equ WLIST_SIGNAL_NEXTFREE = WIDGET_SIGNAL_NEXTFREE+1



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

.cseg



; ---------------------------------------------------------------------------
; @routine WList_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
; @clobbers any

WList_new:
  ldi r24, LOW(VLAYOUT_SIZE)
  ldi r25, HIGH(VLAYOUT_SIZE)
  bigcall Object_Alloc         ; (!r16, !r17, !X)
  brcc WList_new_ret
  rcall WList_Init               ; (r16, r17, X)
  sec
WList_new_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine WList_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
; @clobbers r16, r17, X

WList_Init:
  ; call base class
  ldi r20, VLAYOUT_MODE_EXPAND
  bigcall VLayout_Init             ; (r16, r17, X)

  ; set widget-specific data

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

  ret
; @end




wListRebuild:
  ; release current widgets
  bigcall OBJ_FreeChildren   ; (any, !Y)
  
  rcall wListGetStartElement
  brcc wListRebuild_ret
  
  ; get startY and height
  bigcall Widget_GetBorderAndSpacing
  mov r6, r23  ; YPOS (start after border)
  clr r7
  ldd r10, Y+WIDGET_OFFS_HEIGHT_LO
  ldd r11, Y+WIDGET_OFFS_HEIGHT_HI
  sub r10, r23
  sbc r11, r23
  add r11, r23

  ; loop vars:
  ; - r7:r6  : current Ypos
  ; - r11:r10: widget height
  ; - r22    : spacing
  ; - r23    : number of items handled
  ; - X      : current element
  clr r23
wListRebuild_loop:
    ; check height (does element fit?)
    adiw xh:xl, WLIST_ELEM_OFFS_HEIGHT_LO
    ld r18, X+
    ld r19, X
    sbiw xh:xl, (WLIST_ELEM_OFFS_HEIGHT_LO+1)
    add r18, r6   ; height+currentY
    adc r19, r7
    cp r18, r10
    cpc r19, r11
    brcc wListRebuild_ret ; outside window, done

    ; create child widget for item
    push r6
      push r7
        push r10
          push r11
            push r22
              push r23
                push xl
                  push xh
                    ldi r16, WLIST_SIGNAL_MKOBJECT ; in: list element
                    clr r17
                    bigcall OBJ_HandleSignal       ; out: r19:r18=result (if CFLAG set)
                  pop xh
                pop xl
              pop r23
            pop r22
          pop r11
        pop r10
      pop r7
    pop r6
    brcc wListRebuild_ret

    inc r23 ; inc number of items

    ; increment Y
    adiw xh:xl, WLIST_ELEM_OFFS_HEIGHT_LO
    ld r18, X+
    ld r19, X
    sbiw xh:xl, (WLIST_ELEM_OFFS_HEIGHT_LO+1)
    add r6, r18  ; add item height
    adc r7, r19
    add r6, r22  ; add spacing
    adc r7, r22
    sub r7, r22
    
    ; next element
    ld r16, X+
    ld r17, X
    mov xl, r16
    mov xh, r17
    or r16, r17
  brne wListRebuild_loop
  std Y+WLIST_OFFS_ELEMNUM, r23
wListRebuild_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine wListGetStartElement @global
;
; @param  Y     address of widget
; @return CFLAG set if start element found, cleared otherwise
; @return X     pointer to start element

wListGetStartElement:
  push yl
    push yh
      ldd r16, Y+WLIST_OFFS_ELEMOFFSET
      ldd r17, Y+WLIST_OFFS_ELEMLIST_LO
      ldd yh, Y+WLIST_OFFS_ELEMLIST_HI
      mov yl, r17
      bigcall List_GetItemAt             ; X=element at (r16, r17)
    pop yh
  pop yl
  ret
; @end




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

WList_DefaultSignalmap:
  ; header
  .dw VLayout_DefaultSignalmap*2  ; next table to use
  ; entries

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




#endif

