; ***************************************************************************
; 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_BASE_DIALOG_ASM
#define AQH_AVR_GUI_BASE_DIALOG_ASM


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

; DIALOG data
.equ DIALOG_OFFS_BEGIN            = MAINWINDOW_SIZE
.equ DIALOG_OFFS_CURRSUBDLG_LO    = DIALOG_OFFS_BEGIN+0
.equ DIALOG_OFFS_CURRSUBDLG_HI    = DIALOG_OFFS_BEGIN+1
.equ DIALOG_SIZE                  = DIALOG_OFFS_BEGIN+2


.equ DIALOG_OPTS_STDBTNS_BIT      =  0 ; use standard buttons


; signals
.equ DIALOG_SIGNAL_TOGUI          =  WIDGET_SIGNAL_NEXTFREE+0
.equ DIALOG_SIGNAL_FROMGUI        =  WIDGET_SIGNAL_NEXTFREE+1
.equ DIALOG_SIGNAL_MKCONTENT      =  WIDGET_SIGNAL_NEXTFREE+2
.equ DIALOG_SIGNAL_RMCONTENT      =  WIDGET_SIGNAL_NEXTFREE+3
.equ DIALOG_SIGNAL_NEXT           =  WIDGET_SIGNAL_NEXTFREE+4

; selectors
.equ DIALOG_SEL_OKBUTTON    = 1
.equ DIALOG_SEL_ABORTBUTTON = 2
.equ DIALOG_SEL_NEXTFREE    = 3

.equ DIALOG_RESULT_OK       = 0
.equ DIALOG_RESULT_ABORTED  = 1



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

.cseg



; ---------------------------------------------------------------------------
; @routine Dialog_Init @global
;
; @param Y pointer to MainWindow
; @param X pointer to root window
; @param r16 value for OBJECT_OFFS_OPTS
; @param R21:R20 title ressource
; @return CFLAG set of okay, cleared otherwise
; @clobbers any, !Y

Dialog_Init:
  ldi r17, (WIDGET_PACK_FILLED<<WIDGET_PACK_HSELF0_BIT) | (WIDGET_PACK_FILLED<<WIDGET_PACK_VSELF0_BIT) ; PACK
  bigcall MainWindow_Init
  brcc Dialog_Init_ret

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

Dialog_Init_ret:
  ret
; @end




; ---------------------------------------------------------------------------
; @routine Dialog_AddDefaultButtons @global
;
; @param Y pointer to dialog
; @clobbers any, !Y

Dialog_AddDefaultButtons:
  bigcall MainWindow_GetContentWidget  ; r19:r18=content window
  brcc Dialog_AddDefaultButtons_ret

  mov xl, r18                          ; use content window as parent
  mov xh, r19
  ldi r16, 0                                                                                      ; OPTS
  ldi r17, (WIDGET_PACK_END<<WIDGET_PACK_HSELF0_BIT) | (WIDGET_PACK_END<<WIDGET_PACK_VSELF0_BIT) ; PACK
  push zl
    push zh
      ldi zl, LOW(Dialog_ButtonsConfig*2)
      ldi zh, HIGH(Dialog_ButtonsConfig*2)
      bigcall CWidget_Create               ; (any, !Y)
    pop zh
  pop zl
Dialog_AddDefaultButtons_ret:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Dialog_toGui @global
;
; @param Y pointer to dialog
; @clobbers any, !Y

Dialog_toGui:
  ldi r16, DIALOG_SIGNAL_TOGUI
  clr r17
  bigjmp OBJ_HandleSignal
; @end



; ---------------------------------------------------------------------------
; @routine Dialog_fromGui @global
;
; @param Y pointer to dialog
; @clobbers any, !Y

Dialog_fromGui:
  ldi r16, DIALOG_SIGNAL_FROMGUI
  clr r17
  bigjmp OBJ_HandleSignal
; @end



; ---------------------------------------------------------------------------
; @routine Dialog_MkContent @global
;
; @param Y pointer to dialog
; @clobbers any, !Y

Dialog_MkContent:
  ldi r16, DIALOG_SIGNAL_MKCONTENT
  clr r17
  bigjmp OBJ_HandleSignal
; @end



; ---------------------------------------------------------------------------
; @routine Dialog_RmContent @global
;
; @param Y pointer to dialog
; @clobbers any, !Y

Dialog_RmContent:
  ldi r16, DIALOG_SIGNAL_RMCONTENT
  clr r17
  bigjmp OBJ_HandleSignal
; @end



; ---------------------------------------------------------------------------
; @routine Dialog_EnterSubDialog
; @param Y   pointer to dialog
; @param X   pointer to new dialog to enter
; @clobbers any, !Y

Dialog_EnterSubDialog:
  std Y+DIALOG_OFFS_CURRSUBDLG_LO, xl
  std Y+DIALOG_OFFS_CURRSUBDLG_HI, xh
  
  adiw xh:xl, OBJECT_OFFS_TARGET_LO
  st X+, yl
  st X, yh
  sbiw xh:xl, (OBJECT_OFFS_TARGET_LO+1)
  
  push yl
    push yh
      bigcall Widget_GetApp                     ; R19:R18=gui (none)
      mov yl, r18
      mov yh, r19
      bigcall GuiApp_EnterWindow
    pop yh
  pop yl
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Dialog_LeaveSubDialog
; @param Y   pointer to dialog
; @clobbers any, !Y

Dialog_LeaveSubDialog:
  ; leave sub-dialog
  push yl
    push yh
      bigcall Widget_GetApp                     ; R19:R18=gui
      mov yl, r18
      mov yh, r19
      bigcall GuiApp_LeaveWindow
    pop yh
  pop yl

  ; mark sub-dialog for destruction
  ldd xl, Y+DIALOG_OFFS_CURRSUBDLG_LO
  ldd xh, Y+DIALOG_OFFS_CURRSUBDLG_HI
  clr r16
  std Y+DIALOG_OFFS_CURRSUBDLG_LO, r16
  std Y+DIALOG_OFFS_CURRSUBDLG_HI, r16
  adiw xh:xl, OBJECT_OFFS_FLAGS
  ld r16, X
  sbr r16, (1<<OBJECT_FLAGS_DESTROY_BIT)
  st X, r16
  ret
; @end





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

; ---------------------------------------------------------------------------
; @routine Dialog_OnOk @global
;
; @param Y pointer to dialog
; @clobbers any, !Y

Dialog_OnOk:
  rcall Dialog_fromGui
  ldi r16, WIDGET_SIGNAL_DIALOG_END
  ldi xl, LOW(DIALOG_RESULT_OK)
  ldi xh, HIGH(DIALOG_RESULT_OK)
  bigcall OBJ_EmitSignal
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Dialog_OnOAbort @global
;
; @param Y pointer to dialog
; @clobbers any, !Y

Dialog_OnAbort:
  ldi r16, WIDGET_SIGNAL_DIALOG_END
  ldi xl, LOW(DIALOG_RESULT_ABORTED)
  ldi xh, HIGH(DIALOG_RESULT_ABORTED)
  bigcall OBJ_EmitSignal
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Dialog_OnShow @global
;
; @param  Y       pointer to dialog
; @clobbers any, !Y

Dialog_OnShow:
  ; check VISIBLE flag
  ldd r16, Y+OBJECT_OFFS_FLAGS
  sbrc r16, WIDGET_FLAGS_VISIBLE_BIT
    rjmp Dialog_OnShow_ret

  ; set VISIBLE flag
  sbr r16, (1<<WIDGET_FLAGS_VISIBLE_BIT) | (1<<WIDGET_FLAGS_DIRTY_BIT) | (1<<WIDGET_FLAGS_LAYOUT_BIT)
  std Y+OBJECT_OFFS_FLAGS, r16

  bigcall MainWindow_CreateContentWidget
  brcc Dialog_OnShow_ret

  rcall Dialog_MkContent

  ldd r16, Y+OBJECT_OFFS_OPTS
  sbrs r16, DIALOG_OPTS_STDBTNS_BIT
    rjmp Dialog_OnShow_toGui
  bigcall Dialog_AddDefaultButtons   ; (any, !Y)
  brcc Dialog_OnShow_ret
Dialog_OnShow_toGui:
  rcall Dialog_toGui

Dialog_OnShow_ret:
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Dialog_OnHide @global
;
; @param  Y       pointer to dialog
; @return CFLAG set of okay, cleared otherwise
; @clobbers any, !Y

Dialog_OnHide:
  ldd r16, Y+OBJECT_OFFS_FLAGS
  sbrs r16, WIDGET_FLAGS_VISIBLE_BIT
    rjmp Dialog_OnHide_ret

  ; read data into settings struct
  rcall Dialog_fromGui
  ; prepare destruction of content
  rcall Dialog_RmContent

  ; clr VISIBLE flag
  ldd r16, Y+OBJECT_OFFS_FLAGS
  cbr r16, (1<<WIDGET_FLAGS_VISIBLE_BIT)
  std Y+OBJECT_OFFS_FLAGS, r16

Dialog_OnHide_ret:
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Dialog_OnFromGui @global
;
; @param Y pointer to dialog
; @clobbers any, !Y

Dialog_OnFromGui:
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Dialog_OnToGui @global
;
; @param Y pointer to dialog
; @clobbers any, !Y

Dialog_OnToGui:
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine Dialog_OnRmContent @global
;
; @param Y pointer to dialog
; @clobbers any, !Y

Dialog_OnRmContent:
  ; prepare destruction of content
  bigcall MainWindow_GetContentWidget
  brcc Dialog_OnHide_ret
  push yl
    push yh
      mov yl, r18
      mov yh, r19
      ldd r16, Y+OBJECT_OFFS_FLAGS
      sbr r16, (1<<OBJECT_FLAGS_DESTROY_BIT)
      std Y+OBJECT_OFFS_FLAGS, r16
    pop yh
  pop yl
  sec
  ret
; @end




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



Dialog_ButtonsConfig:
  .db CWIDGETCFG_MAINWIDGET_TYPE_HLAYOUT, 0                 ; TYPE, FLAGS
  .dw (Dialog_HLayoutStyle*2)                               ; STYLE
  .db HLAYOUT_MODE_EXPAND, 0                                ; PARAM1, PARAM2
  
  ; ok button
  .db CWIDGETCFG_WIDGET_TYPE_TEXTBUTTON, 0                  ; TYPE, FLAGS
  .db DIALOG_SEL_OKBUTTON, 0                                ; SELECTOR, RESERVED
  .db (1<<WIDGET_OPTS_BORDER_BIT), \
      (WIDGET_PACK_END<<WIDGET_PACK_HSELF0_BIT) | \
      (WIDGET_PACK_END<<WIDGET_PACK_VSELF0_BIT) | \
      (WIDGET_PACK_CENTER<<WIDGET_PACK_HCONTENT0_BIT) | \
      (WIDGET_PACK_CENTER<<WIDGET_PACK_VCONTENT0_BIT)       ; OPTS, PACK
  .dw (DefaultStyle_SpacyButton*2)                          ; STYLE
  .dw RESSOURCE_TXT_DIALOGOK                                ; PARAM1, PARAM2 (text ressource)
  .db DIALOG_SEL_OKBUTTON, BUTTON_MODE_NORMAL               ; PARAM3, PARAM4
  .dw 0, 0                                                  ; MINVAL, MAXVAL

  ; abort button
  .db CWIDGETCFG_WIDGET_TYPE_TEXTBUTTON, 0                  ; TYPE, FLAGS
  .db DIALOG_SEL_ABORTBUTTON, 0                             ; SELECTOR, RESERVED
  .db (1<<WIDGET_OPTS_BORDER_BIT), \
      (WIDGET_PACK_END<<WIDGET_PACK_HSELF0_BIT) | \
      (WIDGET_PACK_END<<WIDGET_PACK_VSELF0_BIT) | \
      (WIDGET_PACK_CENTER<<WIDGET_PACK_HCONTENT0_BIT) | \
      (WIDGET_PACK_CENTER<<WIDGET_PACK_VCONTENT0_BIT)       ; OPTS, PACK
  .dw (DefaultStyle_SpacyButton*2)                          ; STYLE
  .dw RESSOURCE_TXT_DIALOGABORT                             ; PARAM1, PARAM2 (text ressource)
  .db DIALOG_SEL_ABORTBUTTON, BUTTON_MODE_NORMAL            ; PARAM3, PARAM4
  .dw 0, 0                                                  ; MINVAL, MAXVAL

  ; end of configuration
  .dw 0
; @end



; ---------------------------------------------------------------------------
; @data Dialog_HLayoutStyle

Dialog_HLayoutStyle:
  .dw STYLE_WIN_FGCOL_NORM           ; frontCol_norm
  .dw STYLE_WIN_BGCOL_NORM           ; backCol_norm
  .dw STYLE_WIN_BORDERCOL_NORM       ; borderCol_norm
  .dw STYLE_WIN_SHADOWCOL_NORM       ; shadowCol_norm
  
  .dw STYLE_WIN_FGCOL_ACTIVATED      ; frontCol_activated
  .dw STYLE_WIN_BGCOL_ACTIVATED      ; backCol_activated
  .dw STYLE_WIN_BORDERCOL_ACTIVATED  ; borderCol_activated
  .dw STYLE_WIN_SHADOWCOL_ACTIVATED  ; shadowCol_activated

  .db 2, 10                          ; outerBorderSize, innerBorderSize
  .dw (STYLE_WIN_FONT*2)             ; font
  .db STYLE_WIN_FONT_WIDTH, \
      STYLE_WIN_FONT_HEIGHT          ; charWidth, charHeight
; @end



Dialog_DefaultSignalmap:
  ; header
  .dw MainWindow_DefaultSignalmap*2  ; next table to use
  ; entries
  .db DIALOG_SEL_OKBUTTON,    WIDGET_SIGNAL_COMMAND,   LOW(Dialog_OnOk),        HIGH(Dialog_OnOk)
  .db DIALOG_SEL_ABORTBUTTON, WIDGET_SIGNAL_COMMAND,   LOW(Dialog_OnAbort),     HIGH(Dialog_OnAbort)
  .db 0,                      WIDGET_SIGNAL_SHOW,      LOW(Dialog_OnShow),      HIGH(Dialog_OnShow)
  .db 0,                      WIDGET_SIGNAL_HIDE,      LOW(Dialog_OnHide),      HIGH(Dialog_OnHide)
  .db 0,                      DIALOG_SIGNAL_FROMGUI,   LOW(Dialog_OnFromGui),   HIGH(Dialog_OnFromGui)
  .db 0,                      DIALOG_SIGNAL_TOGUI,     LOW(Dialog_OnToGui),     HIGH(Dialog_OnToGui)
  .db 0,                      DIALOG_SIGNAL_RMCONTENT, LOW(Dialog_OnRmContent), HIGH(Dialog_OnRmContent)
  ; end of table
  .db 0, 0, 0, 0




#endif

