; ***************************************************************************
; 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_GUI_TILE_ASM
#define AQH_AVR_GUI_TILE_ASM


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

.equ TILE_OFFS_BEGIN       =  WIDGET_SIZE
.equ TILE_OFFS_WIDTH_LO    =  TILE_OFFS_BEGIN+0
.equ TILE_OFFS_WIDTH_HI    =  TILE_OFFS_BEGIN+1
.equ TILE_OFFS_HEIGHT_LO   =  TILE_OFFS_BEGIN+2
.equ TILE_OFFS_HEIGHT_HI   =  TILE_OFFS_BEGIN+3
.equ TILE_OFFS_COLOR_LO    =  TILE_OFFS_BEGIN+4
.equ TILE_OFFS_COLOR_HI    =  TILE_OFFS_BEGIN+5
.equ TILE_SIZE             =  TILE_OFFS_BEGIN+6


; values
.equ TILE_VALUE_WIDTH      = WIDGET_VALUE_NEXTFREE+0
.equ TILE_VALUE_HEIGHT     = WIDGET_VALUE_NEXTFREE+1
.equ TILE_VALUE_COLOR      = WIDGET_VALUE_NEXTFREE+2
.equ TILE_VALUE_NEXTFREE   = WIDGET_VALUE_NEXTFREE+3




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

.cseg



; ---------------------------------------------------------------------------
; @routine Tile_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

Tile_new:
  ldi r24, LOW(TILE_SIZE)
  ldi r25, HIGH(TILE_SIZE)
  bigcall Object_Alloc           ; (!r16, !r17, !X)
  brcc Tile_new_ret
  rcall Tile_Init               ; (r16, r17, X)
  sec
Tile_new_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Tile_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 any, !Y

Tile_Init:
  ; call base class
  bigcall Widget_Init
  
  ; set default signal map
  ldi r16, LOW(Tile_DefaultSignalmap*2)
  std Y+OBJECT_OFFS_SIGNALMAP_LO, r16
  ldi r16, HIGH(Tile_DefaultSignalmap*2)
  std Y+OBJECT_OFFS_SIGNALMAP_HI, r16

  ret
; @end



; ---------------------------------------------------------------------------
; @routine Tile_SetWidth @global
;
; @param Y  address of widget
; @param X  new value
; @clobbers any, !Y

Tile_SetWidth:
  ldi r16, WIDGET_SIGNAL_SETVALUE
  ldi r17, TILE_VALUE_WIDTH
  bigjmp OBJ_HandleSignal
; @end



; ---------------------------------------------------------------------------
; @routine Tile_SetHeight @global
;
; @param Y  address of widget
; @param X  new value
; @clobbers any, !Y

Tile_SetHeight:
  ldi r16, WIDGET_SIGNAL_SETVALUE
  ldi r17, TILE_VALUE_HEIGHT
  bigjmp OBJ_HandleSignal
; @end



; ---------------------------------------------------------------------------
; @routine Tile_SetColor @global
;
; @param Y  address of widget
; @param X  new value
; @clobbers any, !Y

Tile_SetColor:
  ldi r16, WIDGET_SIGNAL_SETVALUE
  ldi r17, TILE_VALUE_COLOR
  bigjmp OBJ_HandleSignal
; @end





; ***************************************************************************
; signal handlers


; ---------------------------------------------------------------------------
; @routine Tile_OnGetDefaultWidth @global
;
; @param Y    address of widget
; @return r19:r18 default width
; @clobbers any, !Y

Tile_OnGetDefaultWidth:
  ldd r18, Y+TILE_OFFS_WIDTH_LO
  ldd r19, Y+TILE_OFFS_WIDTH_HI
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Tile_OnGetDefaultHeight @global
;
; @param Y    address of widget
; @return r19:r18 default height
; @clobbers any, !Y

Tile_OnGetDefaultHeight:
  ldd r18, Y+TILE_OFFS_HEIGHT_LO
  ldd r19, Y+TILE_OFFS_HEIGHT_HI
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Tile_OnSetValueWidth @global
;
; @param Y  address of widget
; @param X  new value
; @clobbers any, !Y

Tile_OnSetValueWidth:
  std Y+TILE_OFFS_WIDTH_LO, xl
  std Y+TILE_OFFS_WIDTH_HI, xh

  ; set dirty bit
  sbr r17, (1<<WIDGET_FLAGS_DIRTY_BIT)
  std Y+OBJECT_OFFS_FLAGS, r17

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

  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Tile_OnSetValueHeight @global
;
; @param Y  address of widget
; @param X  new value
; @clobbers any, !Y

Tile_OnSetValueHeight:
  std Y+TILE_OFFS_HEIGHT_LO, xl
  std Y+TILE_OFFS_HEIGHT_HI, xh

  ; set dirty bit
  sbr r17, (1<<WIDGET_FLAGS_DIRTY_BIT)
  std Y+OBJECT_OFFS_FLAGS, r17

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

  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Tile_OnSetValueColor @global
;
; @param Y  address of widget
; @param X  new value
; @clobbers any, !Y

Tile_OnSetValueColor:
  std Y+TILE_OFFS_COLOR_LO, xl
  std Y+TILE_OFFS_COLOR_HI, xh

  ; set dirty bit
  sbr r17, (1<<WIDGET_FLAGS_DIRTY_BIT)
  std Y+OBJECT_OFFS_FLAGS, r17

  sec
  ret
; @end



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

Tile_OnDraw:
  ldd r17, Y+OBJECT_OFFS_FLAGS

  ; check whether widget is visible
  sbrs r17, WIDGET_FLAGS_VISIBLE_BIT
    rjmp Tile_OnDraw_ret

  ; check whether widget is dirty
  sbrs r17, WIDGET_FLAGS_DIRTY_BIT
    rjmp Tile_OnDraw_ret

  ; clear dirty bit
  cbr r17, (1<<WIDGET_FLAGS_DIRTY_BIT)
  std Y+OBJECT_OFFS_FLAGS, r17

  ; fill background with stored color
  rcall Widget_LoadDimsForFullWidget   ; (none)
  rcall Widget_MakeAbsPos              ; (r16, r17, r18, r19)
  rcall Widget_ValidateDims            ; (r16, r17)
  ldd r2, Y+TILE_OFFS_COLOR_LO
  ldd r3, Y+TILE_OFFS_COLOR_HI
  bigcall Display_FillRect

  ; maybe draw border
  ldd r17, Y+OBJECT_OFFS_OPTS
  sbrs r17, WIDGET_OPTS_BORDER_BIT
    rjmp Tile_OnDraw_ret
  bigcall Widget_DrawBorder

Tile_OnDraw_ret:
  sec
  ret
; @end






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

Tile_DefaultSignalmap:
  ; header
  .dw Widget_DefaultSignalmap*2  ; next table to use
  ; entries
  .db 0,                           WIDGET_SIGNAL_DRAW,     LOW(Tile_OnDraw),             HIGH(Tile_OnDraw)
  .db WIDGET_VALUE_DEFAULT_WIDTH,  WIDGET_SIGNAL_GETVALUE, LOW(Tile_OnGetDefaultWidth),  HIGH(Tile_OnGetDefaultWidth)
  .db WIDGET_VALUE_DEFAULT_HEIGHT, WIDGET_SIGNAL_GETVALUE, LOW(Tile_OnGetDefaultHeight), HIGH(Tile_OnGetDefaultHeight)
  .db TILE_VALUE_WIDTH,            WIDGET_SIGNAL_SETVALUE, LOW(Tile_OnSetValueWidth),    HIGH(Tile_OnSetValueWidth)
  .db TILE_VALUE_HEIGHT,           WIDGET_SIGNAL_SETVALUE, LOW(Tile_OnSetValueHeight),   HIGH(Tile_OnSetValueHeight)
  .db TILE_VALUE_COLOR,            WIDGET_SIGNAL_SETVALUE, LOW(Tile_OnSetValueColor),    HIGH(Tile_OnSetValueColor)
  .db 0, 0, 0, 0  ; end of table



#endif



