; ***************************************************************************
; 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_CHECKBUTTON_ASM
#define AQH_AVR_GUI_CHECKBUTTON_ASM


; ***************************************************************************
; This module uses a horizontal layout with two children:
; - a checkBox
; - a label
;
; The current state can be set with @ref CheckButton_SetState and retrieved
; with @ref CheckButton_GetState.
; ***************************************************************************




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

.equ CHECKBUTTON_OFFS_BEGIN       =  BUTTON_SIZE
.equ CHECKBUTTON_OFFS_CHECKBOX_LO =  CHECKBUTTON_OFFS_BEGIN+0
.equ CHECKBUTTON_OFFS_CHECKBOX_HI =  CHECKBUTTON_OFFS_BEGIN+1
.equ CHECKBUTTON_OFFS_MODE        =  CHECKBUTTON_OFFS_BEGIN+2
.equ CHECKBUTTON_SIZE             =  CHECKBUTTON_OFFS_BEGIN+3


; modes
.equ CHECKBUTTON_MODE_TOGGLE      = 0
.equ CHECKBUTTON_MODE_ONLYON      = 1

; values
.equ CHECKBUTTON_VALUE_STATE        = IMAGEVIEW_VALUE_NEXTFREE+0
.equ CHECKBUTTON_VALUE_NEXTFREE     = IMAGEVIEW_VALUE_NEXTFREE+1



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

.cseg



; ---------------------------------------------------------------------------
; @routine CheckButton_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 label text ressource
; @param r22 mode (see @ref BUTTON_MODE_NORMAL)
; @clobbers any

CheckButton_new:
  push r20
    push r21
      push r22
        ldi r24, LOW(CHECKBUTTON_SIZE)
        ldi r25, HIGH(CHECKBUTTON_SIZE)
        bigcall Object_Alloc            ; (!r16, !r17, !X)
      pop r22
    pop r21
  pop r20
  brcc CheckButton_new_ret
  rcall CheckButton_Init            ; (r16, r17, X)
  sec
CheckButton_new_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine CheckButton_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 label text ressource
; @param r22 mode (see @ref BUTTON_MODE_NORMAL)
; @clobbers r16, r17, X

CheckButton_Init:
  push r20
    push r21
      mov r20, r22          ; mode
      ; call base class
      bigcall Button_Init
    pop r21
  pop r20
  brcc CheckButton_Init_ret

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

  rcall checkButtonCreateChildren
CheckButton_Init_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine checkButtonCreateChildren
;
; @param Y address of widget
; @param r21:r20 label text ressource
; @clobbers any, !Y

checkButtonCreateChildren:
  push yl
    push yh
      push r20
        push r21
          ; create HLayout
          ldi r20, VLAYOUT_MODE_EXPAND
          mov xl, yl                    ; use THIS as parent
          mov xh, yh
          ldi r16, 0
          ldi r17, (WIDGET_PACK_FILLED<<WIDGET_PACK_HSELF0_BIT)    | (WIDGET_PACK_BEGIN<<WIDGET_PACK_VSELF0_BIT) | \
                   (WIDGET_PACK_BEGIN<<WIDGET_PACK_HCONTENT0_BIT)  | (WIDGET_PACK_CENTER<<WIDGET_PACK_VCONTENT0_BIT)
          bigcall HLayout_New
        pop r21
      pop r20
      brcc checkButtonCreateChildren_popRet
      mov xl, yl   ; HLayout, use as new parent
      mov xh, yh
      ; create checkBox
      push r20
        push r21
          push xl
            push xh
              ldi r16, 0
              ldi r17, (WIDGET_PACK_BEGIN<<WIDGET_PACK_HSELF0_BIT)     | (WIDGET_PACK_BEGIN<<WIDGET_PACK_VSELF0_BIT) | \
                       (WIDGET_PACK_BEGIN<<WIDGET_PACK_HCONTENT0_BIT)  | (WIDGET_PACK_CENTER<<WIDGET_PACK_VCONTENT0_BIT)
              bigcall CheckBox_new
            pop xh
          pop xl
        pop r21
      pop r20
      brcc checkButtonCreateChildren_popRet
      mov r18, yl
      mov r19, yh
    pop yh
  pop yl
  std Y+CHECKBUTTON_OFFS_CHECKBOX_LO, r18
  std Y+CHECKBUTTON_OFFS_CHECKBOX_HI, r19
  ; create label
  push yl
    push yh
      ldi r16, 0
      ldi r17, (WIDGET_PACK_BEGIN<<WIDGET_PACK_HSELF0_BIT)     | (WIDGET_PACK_BEGIN<<WIDGET_PACK_VSELF0_BIT) | \
               (WIDGET_PACK_BEGIN<<WIDGET_PACK_HCONTENT0_BIT)  | (WIDGET_PACK_CENTER<<WIDGET_PACK_VCONTENT0_BIT)
      bigcall Label_new
checkButtonCreateChildren_popRet:
    pop yh
  pop yl  
checkButtonCreateChildren_ret:
  ret
; @end



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

checkButtonToggle:
  rcall CheckButton_GetState  ; r16=current state
  cpi r16, CHECKBOX_STATE_UNCHECKED
  breq checkButtonToggle_wasUnchecked
  ldi r16, CHECKBOX_STATE_UNCHECKED
  rjmp checkButtonToggle_set
checkButtonToggle_wasUnchecked:
  ldi r16, CHECKBOX_STATE_CHECKED
checkButtonToggle_set:
  push r16
    rcall CheckButton_SetState
  pop xl                              ; pop new state into XL
  ldi r16, WIDGET_SIGNAL_COMMAND
  bigjmp OBJ_EmitSignal                          ; (any, !Y)
; @end



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

checkButtonSetOn:
  ldi r16, CHECKBOX_STATE_CHECKED
  push r16
    rcall CheckButton_SetState
  pop xl                              ; pop new state into XL
  ldi r16, WIDGET_SIGNAL_COMMAND
  bigjmp OBJ_EmitSignal                          ; (any, !Y)
; @end




; ---------------------------------------------------------------------------
; @routine CheckButton_SetState @global
;
; Set state of checkbox without emitting a signal.
;
; @param Y address of widget
; @param r16 new state
; @clobbers any, !Y

CheckButton_SetState:
  ldd r18, Y+CHECKBUTTON_OFFS_CHECKBOX_LO
  ldd r19, Y+CHECKBUTTON_OFFS_CHECKBOX_HI
  mov r17, r18
  or r17, r19
  breq CheckButton_SetState_ret
  push yl
    push yh
      mov yl, r18
      mov yh, r19
      bigcall CheckBox_SetState
    pop yh
  pop yl
CheckButton_SetState_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine CheckButton_GetState @global
;
; @param Y address of widget
; @return r16 state
; @clobbers any, !Y

CheckButton_GetState:
  ldd r18, Y+CHECKBUTTON_OFFS_CHECKBOX_LO
  ldd r19, Y+CHECKBUTTON_OFFS_CHECKBOX_HI
  mov r17, r18
  or r17, r19
  breq CheckButton_GetState_ret           ; defaults to r18=0
  push yl
    push yh
      mov yl, r18
      mov yh, r19
      bigcall CheckBox_GetState
    pop yh
  pop yl
CheckButton_GetState_ret:
  ret
; @end





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

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

CheckButton_OnTouchEnd:
  bigcall Button_OnTouchEnd

  ldd r16, Y+CHECKBUTTON_OFFS_MODE
  cpi r16, CHECKBUTTON_MODE_TOGGLE
  breq CheckButton_OnTouchEnd_toggle
  cpi r16, CHECKBUTTON_MODE_ONLYON
  breq CheckButton_OnTouchEnd_onlyOn
  rjmp CheckButton_OnTouchEnd_done
CheckButton_OnTouchEnd_onlyOn:
  rcall checkButtonSetOn
  rjmp CheckButton_OnTouchEnd_done
CheckButton_OnTouchEnd_toggle:
  rcall checkButtonToggle
CheckButton_OnTouchEnd_done:
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine CheckButton_OnSetValueState @global
;
; @param Y  address of widget
; @param XL new state to set
; @clobbers any, !Y

CheckButton_OnSetValueState:
  ; TODO
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine CheckButton_OnGetValueState @global
;
; @param Y    address of widget
; @return r18 current state
; @clobbers any, !Y

CheckButton_OnGetValueState:
  ; TODO
  sec
  ret
; @end




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

CheckButton_DefaultSignalmap:
  ; header
  .dw Button_DefaultSignalmap*2  ; next table to use
  ; entries
  .db 0,                           WIDGET_SIGNAL_TOUCH_END, LOW(CheckButton_OnTouchEnd),      HIGH(CheckButton_OnTouchEnd)
  .db CHECKBUTTON_VALUE_STATE,     WIDGET_SIGNAL_SETVALUE,  LOW(CheckButton_OnSetValueState), HIGH(CheckButton_OnSetValueState)
  .db CHECKBUTTON_VALUE_STATE,     WIDGET_SIGNAL_GETVALUE,  LOW(CheckButton_OnGetValueState), HIGH(CheckButton_OnGetValueState)
  .db 0, 0, 0, 0  ; end of table



#endif



