; ***************************************************************************
; 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_LABEL_ASM
#define AQH_AVR_GUI2_LABEL_ASM


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

.equ LABEL_OFFS_BEGIN       =  WIDGET_SIZE
.equ LABEL_OFFS_TEXTRES_LO  =  LABEL_OFFS_BEGIN+0
.equ LABEL_OFFS_TEXTRES_HI  =  LABEL_OFFS_BEGIN+1
.equ LABEL_OFFS_MINWIDTH_LO =  LABEL_OFFS_BEGIN+2
.equ LABEL_OFFS_MINWIDTH_HI =  LABEL_OFFS_BEGIN+3
.equ LABEL_OFFS_IDX         =  LABEL_OFFS_BEGIN+4
.equ LABEL_SIZE             =  LABEL_OFFS_BEGIN+5


; values
.equ LABEL_VALUE_TEXTRES    = WIDGET_VALUE_NEXTFREE+0
.equ LABEL_VALUE_IDX        = WIDGET_VALUE_NEXTFREE+1
.equ LABEL_VALUE_MINWIDTH   = WIDGET_VALUE_NEXTFREE+2
.equ LABEL_VALUE_NEXTFREE   = WIDGET_VALUE_NEXTFREE+3

.equ LABEL_IDX_SPACING      = 8



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

.cseg



; ---------------------------------------------------------------------------
; @routine Label_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 r21:r20 ressource id for label text
; @clobbers any

Label_new:
  ldi r24, LOW(LABEL_SIZE)
  ldi r25, HIGH(LABEL_SIZE)
  push r20
    push r21
      bigcall Object_Alloc           ; (!r16, !r17, !X)
    pop r21
  pop r20
  brcc Label_new_ret
  rcall Label_Init               ; (r16, r17, X)
  sec
Label_new_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Label_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 r21:r20 ressource id for label text
; @clobbers r16, r17, X

Label_Init:
  push r20
    push r21
      ; call base class
      bigcall Widget_Init                       ; (r16, r17, X)
    pop r21
  pop r20
  
  ; setup label data
  std Y+LABEL_OFFS_TEXTRES_LO, r20
  std Y+LABEL_OFFS_TEXTRES_HI, r21
  
  ; set default signal map
  ldi r16, LOW(Label_DefaultSignalmap*2)
  std Y+OBJECT_OFFS_SIGNALMAP_LO, r16
  ldi r16, HIGH(Label_DefaultSignalmap*2)
  std Y+OBJECT_OFFS_SIGNALMAP_HI, r16

  ret
; @end



#if 0
; ---------------------------------------------------------------------------
; @routine Label_SetTextRessourceId @global
;
; @param Y address of widget
; @param X id of text ressource
; @clobbers r16, r17, r18, r19

xLabel_SetTextRessourceId:
  std Y+LABEL_OFFS_TEXTRES_LO, xl
  std Y+LABEL_OFFS_TEXTRES_HI, xh
  ldd r16, Y+OBJECT_OFFS_FLAGS
  ori r16, (1<<WIDGET_FLAGS_DIRTY_BIT)
  std Y+OBJECT_OFFS_FLAGS, r16
  ; force layout of this and all parent widgets
  ldi r16, (1<<WIDGET_FLAGS_LAYOUT_BIT)
  bigcall OBJ_AddFlagsUp                 ; (r17, r18, r19)
  ret
; @end
#endif





; ---------------------------------------------------------------------------
; @routine Label_OnDraw @global
;
; @param Y address of widget
; @param xl param1
; @param xh param2
; @clobbers any, !Y

Label_OnDraw:
  ldd r16, Y+OBJECT_OFFS_FLAGS
  andi r16, (1<<WIDGET_FLAGS_DIRTY_BIT)
  breq Label_OnDraw_ret

  bigcall Widget_Clear
  rcall labelWriteText

  ldd r16, Y+OBJECT_OFFS_OPTS
  andi r16, (1<<WIDGET_OPTS_BORDER_BIT)
  breq Label_OnDraw_done
  bigcall Widget_DrawBorder

Label_OnDraw_done:
  ldd r16, Y+OBJECT_OFFS_FLAGS
  cbr r16, (1<<WIDGET_FLAGS_DIRTY_BIT)
  std Y+OBJECT_OFFS_FLAGS, r16

Label_OnDraw_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Label_OnGetDefaultWidth @global
;
; @param Y address of widget
; @return CFLAG set if signal handled
; @return r19:r18 value
; @clobbers any, !Y

Label_OnGetDefaultWidth:
  rcall labelCalcTextWidth
  mov r18, r12
  mov r19, r13
  ldd r16, Y+LABEL_OFFS_MINWIDTH_LO
  ldd r17, Y+LABEL_OFFS_MINWIDTH_HI
  cp r18, r16
  cpc r19, r17
  brcc Label_OnGetDefaultWidth_addBorders
  mov r18, r16
  mov r19, r17
Label_OnGetDefaultWidth_addBorders:
  bigcall Widget_AddOuterStyleBorders  ; (r20, r21)
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Label_OnGetDefaultHeight @global
;
; @param Y address of widget
; @param xl param1
; @param xh param2
; @return CFLAG set if signal handled
; @return r19:r18 value
; @clobbers any, !Y

Label_OnGetDefaultHeight:
  bigcall Widget_GetCharHeight    ; R16=char height
  mov r18, r16
  clr r19
  bigcall Widget_AddOuterStyleBorders  ; (r20, r21)
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Label_OnSetValueTextRes @global
;
; @param Y address of widget
; @param X id of text ressource
; @clobbers r16, r17, r18, r19

Label_OnSetValueTextRes:
  std Y+LABEL_OFFS_TEXTRES_LO, xl
  std Y+LABEL_OFFS_TEXTRES_HI, xh
  rcall labelSetDirtyAndLayoutFlags

  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Label_OnSetValueMinWidth @global
;
; @param Y address of widget
; @param X id of text ressource
; @clobbers r16, r17, r18, r19

Label_OnSetValueMinWidth:
  std Y+LABEL_OFFS_MINWIDTH_LO, xl
  std Y+LABEL_OFFS_MINWIDTH_HI, xh
  rcall labelSetDirtyAndLayoutFlags
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Label_OnSetValueIdx @global
;
; @param Y address of widget
; @param X id of text ressource
; @clobbers none

Label_OnSetValueIdx:
  std Y+LABEL_OFFS_IDX, xl
  rcall labelSetDirtyAndLayoutFlags
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine labelSetDirtyAndLayoutFlags
;
; @param Y address of widget
; @clobbers r16-r19

labelSetDirtyAndLayoutFlags:
  ; set dirty flag
  ldd r16, Y+OBJECT_OFFS_FLAGS
  ori r16, (1<<WIDGET_FLAGS_DIRTY_BIT)
  std Y+OBJECT_OFFS_FLAGS, r16

  ; force layout of this and all parent widgets
  ldi r16, (1<<WIDGET_FLAGS_LAYOUT_BIT)
  bigcall OBJ_AddFlagsUp                 ; (r17, r18, r19)
  ret
; @end



; ---------------------------------------------------------------------------
; @routine labelWriteText
;
; @param Y address of widget
; @clobbers any, !Y

labelWriteText:
  rcall labelAlignTextXY       ; (r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19)
  bigcall Widget_DrawTextFlash ; (any, !Y)
  ldd r16, Y+LABEL_OFFS_IDX
  tst r16
  breq labelWriteText_ret
  ldi r17, LABEL_IDX_SPACING
  add r5, r17
  adc r6, r17
  sub r6, r17
  ldi r17, '0'
  add r16, r17
  push zl
    push zh
      rcall widgetDrawChar     ; (any, !Y, !R6, !R7, !R8, !R9, !R10, !R11)
    pop zh
  pop zl

labelWriteText_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine labelAlignTextXY
;
; @param  Y       address of widget
; @param  R13:R12 width of object to align
; @return R5:R4   X
; @return R7:R6   Y
; @return Z byte address pointer to text in FLASH
; @clobbers r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, r24, r25

labelAlignTextXY:
  rcall labelCalcTextWidth   ; Z=text, R13:R12=text width (r16, r17, r18)
  bigcall Widget_PackContentX  ; R5:R4=X (r17, r18, r19, r20, r21)

  bigcall Widget_GetCharHeight ; R16=char height
  mov r12, r16
  clr r13
  bigcall Widget_PackContentY  ; R7:R6=Y (r17, r18, r19, r20, r21)
  ret
; @end



; ---------------------------------------------------------------------------
; @routine labelCalcTextWidth
;
; @param Y address of widget
; @return Z byte address pointer to text in FLASH
; @return r13:r12 width of string
; @clobbers r16, r17, r18

labelCalcTextWidth:
  ; get text from ressource id
  ldd r16, Y+LABEL_OFFS_TEXTRES_LO
  ldd r17, Y+LABEL_OFFS_TEXTRES_HI
  ldi zl, LOW(RESSOURCE_ADDR*2)
  ldi zh, HIGH(RESSOURCE_ADDR*2)
  bigcall RES_GetRessource            ; (r16, r17, r18)
  brcs labelCalcTextWidth_haveText
  ldi zl, LOW(labelEmptyString*2)     ; use empty default text
  ldi zh, HIGH(labelEmptyString*2)
labelCalcTextWidth_haveText:
  bigcall Widget_GetCharWidth         ; R16=char width
  mov r18, r16
  bigcall Widget_CalcStringWidthFLASH ; r13:r12=size (r16)
  ldd r16, Y+LABEL_OFFS_IDX
  tst r16
  breq labelCalcTextWidth_ret
  ; add spacing
  ldi r16, LABEL_IDX_SPACING
  add r12, r16
  adc r13, r16
  sub r13, r16
  ; add width of one char
  rcall Widget_GetCharWidth   ; r16=charWidth (none)
  add r12, r16
  adc r13, r16
  sub r13, r16
labelCalcTextWidth_ret:
  ret
; @end



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

labelEmptyString:
  .dw 0


Label_DefaultSignalmap:
  ; header
  .dw Widget_DefaultSignalmap*2  ; next table to use
  ; entries
  .db 0,                           WIDGET_SIGNAL_DRAW,     LOW(Label_OnDraw),             HIGH(Label_OnDraw)

  .db LABEL_VALUE_TEXTRES,         WIDGET_SIGNAL_SETVALUE, LOW(Label_OnSetValueTextRes),  HIGH(Label_OnSetValueTextRes)
  .db LABEL_VALUE_MINWIDTH,        WIDGET_SIGNAL_SETVALUE, LOW(Label_OnSetValueMinWidth), HIGH(Label_OnSetValueMinWidth)
  .db LABEL_VALUE_IDX,             WIDGET_SIGNAL_SETVALUE, LOW(Label_OnSetValueIdx),      HIGH(Label_OnSetValueIdx)
  .db WIDGET_VALUE_DEFAULT_WIDTH,  WIDGET_SIGNAL_GETVALUE, LOW(Label_OnGetDefaultWidth),  HIGH(Label_OnGetDefaultWidth)
  .db WIDGET_VALUE_DEFAULT_HEIGHT, WIDGET_SIGNAL_GETVALUE, LOW(Label_OnGetDefaultHeight), HIGH(Label_OnGetDefaultHeight)

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


#endif

