WeeGUI/views.s
2018-03-06 18:04:52 -08:00

1722 lines
32 KiB
ArmAsm

;
; views.s
; Management routines for GUI views
;
; Created by Quinn Dunki on 8/15/14.
; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
;
WG_FEATURE_UP = %00010000
WG_FEATURE_DN = %00100000
WG_FEATURE_LF = %00110000
WG_FEATURE_RT = %01000000
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGCreateView
; Creates and selects a new view
; PARAM0: Pointer to configuration struct (LSB)
; PARAM1: Pointer to configuration struct (MSB)
;
; Configuration struct:
; ID: View ID (0-f)
; ST: Style
; XX: Screen X origin
; YY: Screen Y origin
; SW: Screen width
; SH: Screen height
; VW: View Width
; VH: View Height
;
WGCreateView:
SAVE_AXY
ldy #0
lda (PARAM0),y ; Find our new view record
pha ; Cache view ID so we can select when we're done
asl
asl
asl
asl ; Records are 8 bytes wide
tax
iny
lda (PARAM0),y
pha ; Cache style byte for later
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+0,x ; Screen X
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+1,x ; Screen Y
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+2,x ; Screen Width
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+3,x ; Screen Height
pla
sta WG_VIEWRECORDS+4,x ; Style
stz WG_VIEWRECORDS+5,x ; Initialize scrolling
stz WG_VIEWRECORDS+6,x
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+7,x ; View Width
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+8,x ; View Height
stz WG_VIEWRECORDS+9,x ; Initialize state
stz WG_VIEWRECORDS+10,x ; Initialize callback
stz WG_VIEWRECORDS+11,x
stz WG_VIEWRECORDS+12,x ; Initialize title
stz WG_VIEWRECORDS+13,x
pla
jsr WGSelectView ; Leave this as the active view
WGCreateView_done:
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGCreateCheckbox
; Creates a new checkbox
; PARAM0: Pointer to configuration struct (LSB)
; PARAM1: Pointer to configuration struct (MSB)
;
; Configuration struct:
; ID: View ID (0-f)
; XX: Screen X origin
; YY: Screen Y origin
; SL: String pointer (LSB)
; SH: String pointer (MSB)
;
WGCreateCheckbox:
pha
lda #VIEW_STYLE_CHECK
bra WGCreate1x1_common
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGCreateRadio
; Creates a new radio button
; PARAM0: Pointer to configuration struct (LSB)
; PARAM1: Pointer to configuration struct (MSB)
;
; Configuration struct:
; ID: View ID (0-f)
; XX: Screen X origin
; YY: Screen Y origin
; SL: String pointer (LSB)
; SH: String pointer (MSB)
;
WGCreateRadio:
pha
lda #VIEW_STYLE_RADIO
WGCreate1x1_common:
sta WGCreate1x1_style+1
SAVE_XY
ldy #0
lda (PARAM0),y ; Find our new view record
pha ; Cache view ID so we can select when we're done
asl
asl
asl
asl ; Records are 16 bytes wide
tax
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+0,x ; Screen X
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+1,x ; Screen Y
lda #1
sta WG_VIEWRECORDS+2,x ; Initialize screen width
sta WG_VIEWRECORDS+3,x ; Initialize screen height
sta WG_VIEWRECORDS+7,x ; Initialize view width
sta WG_VIEWRECORDS+8,x ; Initialize view height
WGCreate1x1_style:
lda #$FF ; Self-modifying code!
sta WG_VIEWRECORDS+4,x ; Style
stz WG_VIEWRECORDS+5,x ; Initialize scrolling
stz WG_VIEWRECORDS+6,x
stz WG_VIEWRECORDS+9,x ; Initialize state
stz WG_VIEWRECORDS+10,x ; Initialize callback
stz WG_VIEWRECORDS+11,x
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+12,x ; Title
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+13,x
pla
jsr WGSelectView ; Leave this as the active view
RESTORE_XY
pla
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGCreateProgress
; Creates a new progress bar
; PARAM0: Pointer to configuration struct (LSB)
; PARAM1: Pointer to configuration struct (MSB)
;
; Configuration struct:
; ID: View ID (0-f)
; XX: Screen X origin
; YY: Screen Y origin
; PW: Progress width
;
WGCreateProgress:
SAVE_AXY
ldy #0
lda (PARAM0),y ; Find our new view record
pha ; Cache view ID so we can select when we're done
asl
asl
asl
asl ; Records are 16 bytes wide
tax
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+0,x ; Screen X
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+1,x ; Screen Y
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+2,x ; Screen width
sta WG_VIEWRECORDS+7,x ; View width
lda #1
sta WG_VIEWRECORDS+3,x ; Screen height
sta WG_VIEWRECORDS+8,x ; View height
lda #VIEW_STYLE_PROGRESS
sta WG_VIEWRECORDS+4,x ; Style
stz WG_VIEWRECORDS+5,x ; Initialize scrolling
stz WG_VIEWRECORDS+6,x
stz WG_VIEWRECORDS+9,x ; Initialize state
stz WG_VIEWRECORDS+10,x ; Initialize callback
stz WG_VIEWRECORDS+11,x
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+12,x ; Title
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+13,x
pla
jsr WGSelectView ; Leave this as the active view
WGCreateProgress_done:
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGSetState
; Sets state field in view record
; PARAM0: Value
;
WGSetState:
SAVE_AXY
LDY_ACTIVEVIEW
lda WG_VIEWRECORDS+9,y
and #$80
sta SCRATCH0
lda PARAM0
and #$7F
ora SCRATCH0
sta WG_VIEWRECORDS+9,y ; State (preserving bit 7)
WGSetState_done:
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGCreateButton
; Creates a new button
; PARAM0: Pointer to configuration struct (LSB)
; PARAM1: Pointer to configuration struct (MSB)
;
; Configuration struct:
; ID: View ID (0-f)
; XX: Screen X origin
; YY: Screen Y origin
; BW: Button width
; PL: Action callback (LSB)
; PH: Action callback (MSB)
; SL: Title string pointer (LSB)
; SH: Title string pointer (MSB)
WGCreateButton:
SAVE_AXY
ldy #0
lda (PARAM0),y ; Find our new view record
pha ; Cache view ID so we can select when we're done
asl
asl
asl
asl ; Records are 16 bytes wide
tax
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+0,x ; Screen X
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+1,x ; Screen Y
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+2,x ; Screen width
sta WG_VIEWRECORDS+7,x ; View width
lda #1
sta WG_VIEWRECORDS+3,x ; Initialize screen height
sta WG_VIEWRECORDS+8,x ; Initialize view height
lda #VIEW_STYLE_BUTTON
sta WG_VIEWRECORDS+4,x ; Style
stz WG_VIEWRECORDS+5,x ; Initialize scrolling
stz WG_VIEWRECORDS+6,x
stz WG_VIEWRECORDS+9,x ; Initialize state
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+10,x ; Callback
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+11,x
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+12,x ; Title
iny
lda (PARAM0),y
sta WG_VIEWRECORDS+13,x
pla
jsr WGSelectView ; Leave this as the active view
WGCreateButton_done:
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGDeleteView
; Deletes the current view and removes it from the screen
;
WGDeleteView:
SAVE_AY
LDY_ACTIVEVIEW
lda WG_VIEWRECORDS+2,y
beq WGDeleteView_done ; Not an allocated view
jsr WGEraseView
lda #0
sta WG_VIEWRECORDS+2,y ; 0 width indicates unused view
jsr WGViewPaintAll
WGDeleteView_done:
RESTORE_AY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGPaintView
; Paints the current view
;
WGPaintView:
SAVE_AXY
SAVE_ZPP
LDY_ACTIVEVIEW
lda WG_VIEWRECORDS+4,y ; Cache style information
and #$f ; Mask off flag bits
beq WGPaintView_done ; If it's a stealth view, we're done
pha
lda WG_VIEWRECORDS+0,y ; Fetch the geometry
sta PARAM0
lda WG_VIEWRECORDS+1,y
sta PARAM1
lda WG_VIEWRECORDS+2,y
sta PARAM2
lda WG_VIEWRECORDS+3,y
sta PARAM3
pla ; Draw outline
cmp #VIEW_STYLE_FANCY
beq WGPaintView_decorated
cmp #VIEW_STYLE_RADIO
beq WGPaintView_radio
jsr WGStrokeRect
cmp #VIEW_STYLE_CHECK
beq WGPaintView_check
cmp #VIEW_STYLE_BUTTON
beq WGPaintView_button
cmp #VIEW_STYLE_PROGRESS
beq WGPaintView_progress
bra WGPaintView_done
WGPaintView_decorated:
jsr WGFancyRect
jsr paintWindowTitle
bra WGPaintView_done
WGPaintView_radio:
jsr WGStrokeRoundRect
; execution falls through here
WGPaintView_check:
jsr paintCheck
bra WGPaintView_done
WGPaintView_progress:
jsr paintProgress
bra WGPaintView_done
WGPaintView_button:
jsr paintButton
WGPaintView_done:
jsr WGPointerDirty ; The pointer BG may now be stale
RESTORE_ZPP
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; paintCheck
; Paints the contents of a checkbox
; Y: Index into view records of checkbox to paint
; Side effects: Clobbers all registers,P0,P1
paintCheck:
lda WG_VIEWRECORDS+0,y ; Position cursor
sta WG_CURSORX
lda WG_VIEWRECORDS+1,y
sta WG_CURSORY
lda WG_VIEWRECORDS+9,y ; Determine our visual state
and #$80
bne paintCheck_selected
lda WG_VIEWRECORDS+9,y
ror
bcc paintCheck_unselectedUnchecked
lda #'D'
bra paintCheck_plot
paintCheck_unselectedUnchecked:
lda #' '+$80
bra paintCheck_plot
paintCheck_selected:
lda WG_VIEWRECORDS+9,y
ror
bcc paintCheck_selectedUnchecked
lda #'E'
bra paintCheck_plot
paintCheck_selectedUnchecked:
lda #' '
paintCheck_plot: ; Paint our state
jsr WGPlot
inc WG_CURSORX ; Prepare for title
inc WG_CURSORX
lda #CHAR_NORMAL
sta INVERSE
lda WG_VIEWRECORDS+12,y
sta PARAM0
lda WG_VIEWRECORDS+13,y
sta PARAM1
lda WG_VIEWRECORDS+4,y ; Raw or Apple format title?
and #VIEW_STYLE_RAWTITLE
asl
eor #$80 ; becomes #$80 for Apple format, 0 for raw
sta paintCheck_mask+1
ldy #0
paintCheck_titleLoop:
lda (PARAM0),y
beq paintCheck_done
paintCheck_mask:
ora #$FF ; Self-modifying code!
jsr WGPlot
inc WG_CURSORX
iny
bra paintCheck_titleLoop
paintCheck_done:
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; paintProgress
; Paints the contents of a progress bar
; Y: Index into view records of progress bar to paint
; Side effects: Clobbers all registers,P0,P1
paintProgress:
lda WG_VIEWRECORDS+1,y ; Top edge
sta PARAM1
lda #1
sta PARAM3
lda WG_VIEWRECORDS+9,y ; Progress value as width
sta PARAM2
beq paintProgress_noFill ; skip if nothing to draw
lda WG_VIEWRECORDS+0,y ; Left edge
sta PARAM0
phy
ldy #$20 ; inverse space
jsr WGFillRect
ply
paintProgress_noFill:
lda WG_VIEWRECORDS+2,y ; full width
sec
sbc WG_VIEWRECORDS+9,y ; Progress value
beq paintProgress_done ; skip if nothing to draw
sta PARAM2
lda WG_VIEWRECORDS+0,y ; left edge
clc
adc WG_VIEWRECORDS+9,y ; Progress value
sta PARAM0
ldy #$A0 ; space
jsr WGFillRect
paintProgress_done:
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; paintButton
; Paints the contents of a button
; Y: Index into view records of button to paint
; Side effects: Clobbers all registers,P0,P1,S1
paintButton:
lda INVERSE ; Preserve INVERSE state during this
pha
lda WG_VIEWRECORDS+12,y ; Prep the title string
sta PARAM0
lda WG_VIEWRECORDS+13,y
sta PARAM1
jsr WGStrLen ; Compute centering offset for title
lsr
sta SCRATCH1
lda WG_VIEWRECORDS+2,y
lsr
sec
sbc SCRATCH1
sta SCRATCH1 ; Cache this for left margin rendering
lda #0 ; Position and print title
sta WG_LOCALCURSORX
lda #0
sta WG_LOCALCURSORY
jsr WGSyncGlobalCursor
lda WG_VIEWRECORDS+9,y ; Is button highlighted?
and #$80
bne paintButton_titleSelected
lda #CHAR_NORMAL
sta INVERSE
lda #' '+$80
bra paintButton_titleMarginLeft
paintButton_titleSelected:
lda #CHAR_INVERSE
sta INVERSE
lda #' '
paintButton_titleMarginLeft:
ldx #0
paintButton_titleMarginLeftLoop:
cpx SCRATCH1
bcs paintButton_title ; Left margin finished
jsr WGPlot
inc WG_CURSORX
inc WG_LOCALCURSORX
inx
jmp paintButton_titleMarginLeftLoop
paintButton_title:
pha
lda WG_VIEWRECORDS+4,y ; Raw or Apple format title?
and #VIEW_STYLE_RAWTITLE
beq paintButton_titleApple
bit paintButton_doneRTS ; Set overflow
paintButton_titleApple:
pla
jsr WGPrint
ldx WG_VIEWRECORDS+2,y
stx SCRATCH1 ; Loop until right edge of button is reached
ldx WG_LOCALCURSORX
paintButton_titleMarginRightLoop:
cpx SCRATCH1
bcs paintButton_done ; Right margin finished
jsr WGPlot
inc WG_CURSORX
inc WG_LOCALCURSORX
inx
jmp paintButton_titleMarginRightLoop
paintButton_done:
pla ; Restore inverse state
sta INVERSE
paintButton_doneRTS:
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; paintWindowTitle
; Paints the title of a fancy window
; Y: Index into view records of view title to paint
; Side effects: Clobbers all registers,P0,P1,S1
paintWindowTitle:
lda WG_VIEWRECORDS+12,y ; Prep the title string
sta PARAM0
lda WG_VIEWRECORDS+13,y
sta PARAM1
bne paintWindowTitle_compute
paintWindowTitle_checkNull:
lda PARAM0
beq paintWindowTitle_done
paintWindowTitle_compute:
jsr WGStrLen ; Compute centering offset for title
lsr
sta SCRATCH1
lda WG_VIEWRECORDS+2,y
lsr
sec
sbc SCRATCH1
clc
adc WG_VIEWRECORDS+0,y
sta WG_CURSORX ; Position cursor
lda WG_VIEWRECORDS+1,y
dec
sta WG_CURSORY
lda WG_VIEWRECORDS+4,y ; Raw or Apple format title?
and #VIEW_STYLE_RAWTITLE
asl
eor #$80 ; becomes #$80 for Apple format, 0 for raw
sta paintWindowTitle_mask+1
ldy #0
paintWindowTitleLoop:
lda (PARAM0),y
beq paintWindowTitle_done
paintWindowTitle_mask:
ora #$FF ; Self-modifying code!
jsr WGPlot ; Draw the character
iny
inc WG_CURSORX ; Advance cursors
bra paintWindowTitleLoop
paintWindowTitle_done:
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGEraseView
; Erases the current view (including decoration)
;
WGEraseView:
SAVE_AXY
SAVE_ZPP
LDY_ACTIVEVIEW
lda WG_VIEWRECORDS+0,y
dec
sta PARAM0
lda WG_VIEWRECORDS+1,y
dec
sta PARAM1
lda WG_VIEWRECORDS+2,y
inc
inc
sta PARAM2
lda WG_VIEWRECORDS+3,y
inc
inc
sta PARAM3
ldy #' '+$80
jsr WGFillRect
WGEraseView_done:
RESTORE_ZPP
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGEraseViewContents
; Erases the contents of the current view (interior contents only)
;
WGEraseViewContents:
SAVE_AY
SAVE_ZPP
LDY_ACTIVEVIEW
lda WG_VIEWRECORDS,y ; Fetch the record
sta PARAM0
iny
lda WG_VIEWRECORDS,y
sta PARAM1
iny
lda WG_VIEWRECORDS,y
sta PARAM2
iny
lda WG_VIEWRECORDS,y
sta PARAM3
ldy #' '+$80
jsr WGFillRect
WGEraseViewContents_done:
RESTORE_ZPP
RESTORE_AY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGSelectView
; Selects the active view
; A: ID
;
WGSelectView:
sta WG_ACTIVEVIEW
; Initialize cursor to local origin
stz WG_LOCALCURSORX
stz WG_LOCALCURSORY
jsr cacheClipPlanes ; View changed, so clipping cache is stale
WGSelectView_done:
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGViewFocus
; Shifts focus to the selected view
; Side effects: Changes selected view, repaints some views
;
WGViewFocus:
SAVE_AY
lda WG_ACTIVEVIEW ; Stash current selection
pha
jsr unfocusCurrent
pla
sta WG_FOCUSVIEW ; Focus on our current selection
jsr focusCurrent
RESTORE_AY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGViewFocusQuiet
; Shifts focus to the selected view without redrawing anything
; Side effects: Changes selected view, repaints some views
;
WGViewFocusQuiet:
pha
lda WG_ACTIVEVIEW ; Stash current selection
sta WG_FOCUSVIEW ; Focus on our current selection
pla
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGViewUnfocus
; Unfocuses all views
; Side effects: Changes selected view, repaints some views
;
WGViewUnfocus:
pha
jsr unfocusCurrent
lda #$ff
sta WG_FOCUSVIEW
WGViewUnfocus_done:
pla
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGViewFocusNext
; Shifts focus to the next view
; Side effects: Changes selected view, repaints some views
;
WGViewFocusNext:
SAVE_AY
jsr unfocusCurrent
WGViewFocusNext_loop:
lda WG_FOCUSVIEW ; Increment and wrap
inc
cmp #16
beq WGViewFocusNext_wrap
sta WG_FOCUSVIEW
LDY_FOCUSVIEW
lda WG_VIEWRECORDS+2,y
beq WGViewFocusNext_loop
WGViewFocusNext_wantFocus: ; Does this view accept focus?
LDY_FOCUSVIEW
lda WG_VIEWRECORDS+4,y
and #$f ; Mask off flag bits
cmp #VIEW_STYLE_TAKESFOCUS
bcc WGViewFocusNext_loop
WGViewFocusNext_focus:
jsr focusCurrent
RESTORE_AY
rts
WGViewFocusNext_wrap:
stz WG_FOCUSVIEW
bra WGViewFocusNext_loop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGViewFocusPrev
; Shifts focus to the prev view
; Side effects: Changes selected view, repaints some views
;
WGViewFocusPrev:
SAVE_AXY
jsr unfocusCurrent
WGViewFocusPrev_loop:
ldx WG_FOCUSVIEW ; Decrement and wrap
dex
bmi WGViewFocusPrev_wrap
WGViewFocusPrev_findLoop:
stx WG_FOCUSVIEW
LDY_FOCUSVIEW
lda WG_VIEWRECORDS+2,y
beq WGViewFocusPrev_loop
WGViewFocusPrev_wantFocus: ; Does this view accept focus?
LDY_FOCUSVIEW
lda WG_VIEWRECORDS+4,y
and #$f ; Mask off flag bits
cmp #VIEW_STYLE_TAKESFOCUS
bcc WGViewFocusPrev_loop
WGViewFocusPrev_focus:
jsr focusCurrent
RESTORE_AXY
rts
WGViewFocusPrev_wrap:
ldx #$f
bra WGViewFocusPrev_findLoop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; unfocusCurrent
; Unfocuses current view, if any
; Side effects: Clobbers A,
; Leaves Y pointed at current focus view record
; Changes active view selection
unfocusCurrent:
lda WG_FOCUSVIEW
bmi unfocusCurrentDone ; No current focus
LDY_FOCUSVIEW ; Unfocus current view
lda WG_VIEWRECORDS+9,y
and #%01111111
sta WG_VIEWRECORDS+9,y
lda WG_FOCUSVIEW
jsr WGSelectView
jsr WGPaintView
unfocusCurrentDone:
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; focusCurrent
; Sets focus to desired view, and repaints
; Side effects: Clobbers A
focusCurrent:
lda WG_FOCUSVIEW
jsr WGSelectView
LDY_ACTIVEVIEW
lda WG_VIEWRECORDS+4,y
and #$f ; Mask off flag bits
cmp #VIEW_STYLE_TAKESFOCUS
bcc focusCurrent_done
lda WG_VIEWRECORDS+9,y
ora #%10000000
sta WG_VIEWRECORDS+9,y
jsr WGPaintView
focusCurrent_done:
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGViewFocusAction
; Performs the action of the focused view
; WG_GOSUB : Set if the caller should perform an Applesoft GOSUB
; Side effects: Changes selected view, Repaints some views
;
WGViewFocusAction:
SAVE_AXY
lda WG_FOCUSVIEW
bpl WGViewFocusAction_do
jmp WGViewFocusAction_done
WGViewFocusAction_do:
LDY_FOCUSVIEW
lda WG_VIEWRECORDS+4,y ; What kind of view is it?
and #$f ; Mask off flag bits
cmp #VIEW_STYLE_CHECK
beq WGViewFocusAction_toggleCheckbox
cmp #VIEW_STYLE_RADIO
beq WGViewFocusAction_toggleRadio
bra WGViewFocusAction_buttonClick ; Everything else treated like a button
WGViewFocusAction_toggleRadio:
lda #15
WGViewFocusAction_toggleRadioLoop:
pha
cmp WG_FOCUSVIEW
beq WGViewFocusAction_toggleRadioLoopNext
LDY_AVIEW
lda WG_VIEWRECORDS+4,y
and #$f
cmp #VIEW_STYLE_RADIO
bne WGViewFocusAction_toggleRadioLoopNext
lda WG_VIEWRECORDS+9,y ; check if this radio button is selected
beq WGViewFocusAction_toggleRadioLoopNext
lda #0
sta WG_VIEWRECORDS+9,y ; if so, deselect it and repaint
pla
pha
jsr WGSelectView
jsr WGPaintView
WGViewFocusAction_toggleRadioLoopNext:
pla
dec
bpl WGViewFocusAction_toggleRadioLoop
LDY_FOCUSVIEW
; execution falls through here
WGViewFocusAction_toggleCheckbox:
lda WG_VIEWRECORDS+9,y ; Change the checkbox's state and redraw
eor #%00000001
sta WG_VIEWRECORDS+9,y
lda WG_FOCUSVIEW
jsr WGSelectView
jsr WGPaintView
; Fall through so checkboxes can have callbacks too
; NOTE: Self-modifying code ahead!
WGViewFocusAction_buttonClick:
lda WG_VIEWRECORDS+4,y ; Are we an Applesoft button?
and #VIEW_STYLE_APPLESOFT
bne WGViewFocusAction_buttonClickApplesoft
lda WG_VIEWRECORDS+11,y ; Do we have a callback?
beq WGViewFocusAction_done
sta WGViewFocusAction_userJSR+2 ; Modify code below so we can JSR to user's code
lda WG_VIEWRECORDS+10,y
sta WGViewFocusAction_userJSR+1
WGViewFocusAction_userJSR:
jsr WGViewFocusAction_done ; Overwritten with user's function pointer
bra WGViewFocusAction_done
WGViewFocusAction_buttonClickApplesoft:
lda #0
sta WG_GOSUB
lda WG_VIEWRECORDS+10,y ; Do we have a callback?
beq WGViewFocusAction_mightBeZero
WGViewFocusAction_buttonClickApplesoftNotZero:
sta WG_GOSUBLINE
lda WG_VIEWRECORDS+11,y
sta WG_GOSUBLINE+1
WGViewFocusAction_buttonClickApplesoftGosub:
; Caller needs to handle Applesoft Gosub, so signal with a flag and return
lda #1
sta WG_GOSUB
bra WGViewFocusAction_done
WGViewFocusAction_mightBeZero:
lda WG_VIEWRECORDS+11,y
beq WGViewFocusAction_done
lda WG_VIEWRECORDS+10,y
bra WGViewFocusAction_buttonClickApplesoftNotZero
WGViewFocusAction_done:
RESTORE_AXY
WGViewFocusAction_knownRTS:
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGPendingViewAction
; Performs the action of the pending view, if any
; Global flag set if the caller should perform an Applesoft GOSUB
; Side effects: Changes selected view, Repaints some views
;
WGPendingViewAction:
SAVE_AY
WGEnableGSMouse:
bit GsPollMouse ; self-modified to JSR when appropriate
lda WG_MOUSECLICK_X
bmi WGPendingViewAction_done
sta PARAM0
lda WG_MOUSECLICK_Y
sta PARAM1
jsr WGViewFromPoint
sta WG_PENDINGACTIONVIEW
cmp #$ff
beq WGPendingViewAction_done
and #$f ; Select view in question
jsr WGSelectView
LDY_ACTIVEVIEW
lda WG_VIEWRECORDS+4,y
and #$f
cmp #VIEW_STYLE_FANCY ; Filter out fancy views with high-nybble of 0
bne WGPendingViewAction_chkCallback ; This prevents unnecessary redraws when clicking
lda WG_PENDINGACTIONVIEW ; in the content area
and #$f0
beq WGPendingViewAction_done
WGPendingViewAction_chkCallback:
; lda WG_VIEWRECORDS+10,y ; Optimization- only process things that can be clicked
; bne WGPendingViewAction_hasCallback
; lda WG_VIEWRECORDS+11,y
; beq WGPendingViewAction_done
WGPendingViewAction_hasCallback:
lda WG_PENDINGACTIONVIEW
and #$f0 ; Check for window features
beq WGPendingViewAction_content
cmp #WG_FEATURE_UP
beq WGPendingViewAction_up
cmp #WG_FEATURE_DN
beq WGPendingViewAction_down
cmp #WG_FEATURE_LF
beq WGPendingViewAction_left
cmp #WG_FEATURE_RT
bne WGPendingViewAction_done
lda #$FF ; Right arrow
jsr WGScrollXBy
jsr WGViewFocus
jsr WGViewFocusAction ; Trigger application to redraw contents
WGPendingViewAction_done: ; Located here for branch range
lda #$ff
sta WG_PENDINGACTIONVIEW
sta WG_MOUSECLICK_X
RESTORE_AY
rts
WGPendingViewAction_up:
lda #1 ; Up arrow
jsr WGScrollYBy
jsr WGViewFocusQuiet
jsr WGViewFocusAction ; Trigger application to redraw contents
bra WGPendingViewAction_done
WGPendingViewAction_down:
lda #$FF ; Down arrow
jsr WGScrollYBy
jsr WGViewFocusQuiet
jsr WGViewFocusAction ; Trigger application to redraw contents
bra WGPendingViewAction_done
WGPendingViewAction_left:
lda #1 ; Left arrow
jsr WGScrollXBy
jsr WGViewFocusQuiet
jsr WGViewFocusAction ; Trigger application to redraw contents
bra WGPendingViewAction_done
WGPendingViewAction_content:
jsr WGViewFocus
jsr WGViewFocusAction
jsr delayShort
jsr WGViewUnfocus
jsr WGPointerDirty ; If we redrew anything, the pointer BG will be stale
bra WGPendingViewAction_done
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGPendingClick
; Returns the mouse click that is currently pending
; OUT X,Y : Mouse coordinates, or $ff in X if none
;
WGPendingClick:
ldx WG_MOUSECLICK_X
bmi WGPendingClick_done
ldy WG_MOUSECLICK_Y
WGPendingClick_done:
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGViewSetTitle
; Sets the title of the active view
; PARAM0: Null-terminated string pointer (LSB)
; PARAM1: Null-terminated string pointer (MSB)
WGViewSetTitle:
SAVE_AY
LDY_ACTIVEVIEW
lda PARAM0
sta WG_VIEWRECORDS+12,y
lda PARAM1
sta WG_VIEWRECORDS+13,y
WGViewSetTitle_done:
RESTORE_AY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGViewSetAction
; Sets the callback action of the active view
; PARAM0: Null-terminated function pointer (LSB)
; PARAM1: Null-terminated function pointer (MSB)
WGViewSetAction:
SAVE_AY
LDY_ACTIVEVIEW
lda PARAM0
sta WG_VIEWRECORDS+10,y
lda PARAM1
sta WG_VIEWRECORDS+11,y
WGViewSetAction_done:
RESTORE_AY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGViewSetRawTitle
; Sets the raw title flag of the active view
; PARAM0: Flag to set
WGViewSetRawTitle:
SAVE_AY
LDY_ACTIVEVIEW
lda PARAM0
asl ; Shifts need to match VIEW_STYLE_RAWTITLE
asl
asl
asl
asl
asl
eor WG_VIEWRECORDS+4,y
sta WG_VIEWRECORDS+4,y
WGViewSetRawTitle_done:
RESTORE_AY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGSetCursor
; Sets the current local view cursor
; PARAM0: X
; PARAM1: Y
;
WGSetCursor:
pha
lda PARAM0
bpl WGSetCursor_StoreX
lda #0 ; Prevent negatives
WGSetCursor_StoreX:
sta WG_LOCALCURSORX
lda PARAM1
bpl WGSetCursor_StoreY
lda #0 ; Prevent negatives
WGSetCursor_StoreY:
sta WG_LOCALCURSORY
pla
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGSetGlobalCursor
; Sets the current global cursor
; PARAM0: X
; PARAM1: Y
;
WGSetGlobalCursor:
pha
lda PARAM0
sta WG_CURSORX
lda PARAM1
sta WG_CURSORY
pla
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGSyncGlobalCursor
; Synchronizes the global cursor with the current local view's
; cursor
;
WGSyncGlobalCursor:
SAVE_AY
LDY_ACTIVEVIEW
; Sync X
clc ; Transform to viewspace
lda WG_LOCALCURSORX
adc WG_VIEWRECORDS+0,y
clc
adc WG_VIEWRECORDS+5,y ; Transform to scrollspace
sta WG_CURSORX
; Sync Y
clc ; Transform to viewspace
lda WG_LOCALCURSORY
adc WG_VIEWRECORDS+1,y
clc
adc WG_VIEWRECORDS+6,y ; Transform to scrollspace
sta WG_CURSORY
WGSyncGlobalCursor_done:
RESTORE_AY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGScrollX
; Scrolls the current view horizontally
; A: New scroll amount
; Side effects: Clobbers A
;
WGScrollX:
phy
pha
LDY_ACTIVEVIEW
pla
bmi WGScrollX_Store
lda #0 ; Prevent positive scroll values
WGScrollX_Store:
sta WG_VIEWRECORDS+5,y
jsr cacheClipPlanes ; Scroll offset changed, so clipping cache is stale
WGScrollX_done:
ply
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGScrollXBy
; Scrolls the current view horizontally by a delta
; A: Scroll delta
; Side effects: Clobbers A,S0
;
WGScrollXBy:
SAVE_XY
tax
LDY_ACTIVEVIEW
txa
bpl WGScrollXBy_contentRight
lda WG_VIEWRECORDS+2,y ; Compute left limit
sec
sbc WG_VIEWRECORDS+7,y
sta SCRATCH0
txa ; Compute new scroll value
clc
adc WG_VIEWRECORDS+5,y
cmp SCRATCH0 ; Clamp if needed
bmi WGScrollXBy_clampLeft
sta WG_VIEWRECORDS+5,y
bra WGScrollXBy_done
WGScrollXBy_clampLeft:
lda SCRATCH0
sta WG_VIEWRECORDS+5,y
bra WGScrollXBy_done
WGScrollXBy_contentRight:
clc ; Compute new scroll value
adc WG_VIEWRECORDS+5,y
beq @0 ; Clamp if needed
bpl WGScrollXBy_clampRight
@0: sta WG_VIEWRECORDS+5,y
bra WGScrollXBy_done
WGScrollXBy_clampRight:
lda #0
sta WG_VIEWRECORDS+5,y
WGScrollXBy_done:
RESTORE_XY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGScrollY
; Scrolls the current view vertically
; A: New scroll amount
; Side effects: Clobbers A
;
WGScrollY:
phy
pha
LDY_ACTIVEVIEW
pla
bmi WGScrollY_Store
lda #0 ; Prevent positive scroll values
WGScrollY_Store:
sta WG_VIEWRECORDS+6,y
jsr cacheClipPlanes ; Scroll offset changed, so clipping cache is stale
WGScrollY_done:
ply
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGScrollYBy
; Scrolls the current view horizontally by a delta
; A: Scroll delta
; Side effects: Clobbers A,S0
;
WGScrollYBy:
SAVE_XY
tax
LDY_ACTIVEVIEW
txa
bpl WGScrollYBy_contentDown
lda WG_VIEWRECORDS+3,y ; Compute bottom limit
sec
sbc WG_VIEWRECORDS+8,y
sta SCRATCH0
txa ; Compute new scroll value
clc
adc WG_VIEWRECORDS+6,y
cmp SCRATCH0 ; Clamp if needed
bmi WGScrollYBy_clampTop
sta WG_VIEWRECORDS+6,y
bra WGScrollYBy_done
WGScrollYBy_clampTop:
lda SCRATCH0
sta WG_VIEWRECORDS+6,y
bra WGScrollYBy_done
WGScrollYBy_contentDown:
clc ; Compute new scroll value
adc WG_VIEWRECORDS+6,y
beq @0 ; Clamp if needed
bpl WGScrollYBy_clampBottom
@0: sta WG_VIEWRECORDS+6,y
bra WGScrollYBy_done
WGScrollYBy_clampBottom:
lda #0
sta WG_VIEWRECORDS+6,y
WGScrollYBy_done:
RESTORE_XY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGSetContentWidth
; Sets the content width of the current view
; A: New width
;
WGSetContentWidth:
phy
pha
LDY_ACTIVEVIEW
pla
sta WG_VIEWRECORDS+7,y
jsr cacheClipPlanes ; Content width changed, so clipping cache is stale
ply
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGSetContentHeight
; Sets the content width of the current view
; A: New height
;
WGSetContentHeight:
phy
pha
LDY_ACTIVEVIEW
pla
sta WG_VIEWRECORDS+8,y
jsr cacheClipPlanes ; Content height changed, so clipping cache is stale
ply
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGViewPaintAll
; Repaints all views
; Side effects: Changes selected view
;
WGViewPaintAll:
SAVE_AXY
ldx #0
WGViewPaintAll_loop:
txa
sta WG_ACTIVEVIEW
LDY_ACTIVEVIEW
lda WG_VIEWRECORDS+2,y ; Valid view?
beq WGViewPaintAll_next
jsr WGEraseViewContents
jsr WGPaintView
WGViewPaintAll_next:
inx
cpx #16
bne WGViewPaintAll_loop
WGViewPaintAll_done:
lda #$FF
jsr WGSelectView
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGViewFromPoint
; Finds a view containing the given point
; PARAM0:X
; PARAM1:Y
; OUT A: View ID (or high bit set if no match)
; For Fancy Views, Upper nibble returned indicates feature hit:
; 0000 : Content region
; 0001 : Scroll arrow up
; 0010 : Scroll arrow down
; 0011 : Scroll arrow left
; 0100 : Scroll arrow right
WGViewFromPoint:
SAVE_XY
SAVE_ZPS
ldx #$f ; Scan views backwards, because controls are usually at the end
WGViewFromPoint_loop:
txa
LDY_AVIEW
lda WG_VIEWRECORDS+2,y
beq WGViewFromPoint_loopNext ; Not an allocated view
lda WG_VIEWRECORDS+4,y ; Fancy views are handled differently
and #$f
cmp #VIEW_STYLE_FANCY
beq WGViewFromPoint_loopFancy
lda WG_VIEWRECORDS+2,y
sta SCRATCH0
lda WG_VIEWRECORDS+3,y
sta SCRATCH1
bra WGViewFromPoint_loopCheckBounds
WGViewFromPoint_loopFancy:
lda WG_VIEWRECORDS+2,y ; Include scrollbars
inc
sta SCRATCH0
lda WG_VIEWRECORDS+3,y
inc
sta SCRATCH1
WGViewFromPoint_loopCheckBounds:
lda PARAM0 ; Check left edge
cmp WG_VIEWRECORDS+0,y
bcc WGViewFromPoint_loopNext
lda PARAM1 ; Check top edge
cmp WG_VIEWRECORDS+1,y
bcc WGViewFromPoint_loopNext
lda WG_VIEWRECORDS+0,y ; Check right edge
clc
adc SCRATCH0
cmp PARAM0
bcc WGViewFromPoint_loopNext
beq WGViewFromPoint_loopNext
lda WG_VIEWRECORDS+1,y ; Check bottom edge
clc
adc SCRATCH1
cmp PARAM1
bcc WGViewFromPoint_loopNext
beq WGViewFromPoint_loopNext
; Found a match (in X)
lda WG_VIEWRECORDS+4,y
and #$f ; Mask off flag bits
cmp #VIEW_STYLE_FANCY
bne WGViewFromPoint_matchDone
; For fancy views, check scrollbars as well
lda WG_VIEWRECORDS+0,y ; Right scroll bar?
clc
adc SCRATCH0
dec
cmp PARAM0
bne WGViewFromPoint_checkBottomScroll
lda PARAM1 ; Up arrow?
cmp WG_VIEWRECORDS+1,y
bne WGViewFromPoint_checkDownArrow
txa
ora #WG_FEATURE_UP
bra WGViewFromPoint_matchFancyDone
WGViewFromPoint_loopNext: ; Inserted here for branch range
dex
bmi WGViewFromPoint_noMatch
bra WGViewFromPoint_loop
WGViewFromPoint_checkDownArrow:
lda WG_VIEWRECORDS+1,y ; Down arrow?
clc
adc SCRATCH1
dec
dec
cmp PARAM1
bne WGViewFromPoint_matchDone
txa
ora #WG_FEATURE_DN
bra WGViewFromPoint_matchFancyDone
WGViewFromPoint_checkBottomScroll:
lda WG_VIEWRECORDS+1,y ; Bottom scroll bar?
clc
adc SCRATCH1
dec
cmp PARAM1
bne WGViewFromPoint_matchDone
lda PARAM0 ; Left arrow?
cmp WG_VIEWRECORDS+0,y
bne WGViewFromPoint_checkRightArrow
txa
ora #WG_FEATURE_LF
bra WGViewFromPoint_matchFancyDone
WGViewFromPoint_checkRightArrow:
lda WG_VIEWRECORDS+0,y ; Right arrow?
clc
adc SCRATCH0
dec
dec
cmp PARAM0
bne WGViewFromPoint_matchDone
txa
ora #WG_FEATURE_RT
WGViewFromPoint_matchFancyDone:
tax
WGViewFromPoint_matchDone:
RESTORE_ZPS
txa
RESTORE_XY
rts
WGViewFromPoint_noMatch:
RESTORE_ZPS
lda #$ff
RESTORE_XY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; cacheClipPlanes
; Internal routine to cache the clipping planes for the view
;
cacheClipPlanes:
SAVE_AY
; Compute clip planes in view space
LDY_ACTIVEVIEW
lda WG_VIEWRECORDS+5,y ; Left edge
eor #$ff
inc
sta WG_VIEWCLIP+0
clc
adc WG_VIEWRECORDS+2,y ; Right edge
sta WG_VIEWCLIP+2
lda WG_VIEWRECORDS+7,y ; Right span (distance from window edge to view edge, in viewspace
sec
sbc WG_VIEWCLIP+2
sta WG_VIEWCLIP+4
lda WG_VIEWRECORDS+6,y ; Top edge
eor #$ff
inc
sta WG_VIEWCLIP+1
clc
adc WG_VIEWRECORDS+3,y ; Bottom edge
sta WG_VIEWCLIP+3
RESTORE_AY
rts