; _______________________________________________________________________________________
;|                                                                                       |
;| ..::FreshLib::..  Free, open source. Licensed under "BSD 2-clause" license."          |
;|_______________________________________________________________________________________|
;
;  Description: TBackWindow object class
;
;  Target OS: Any
;
;  Dependencies:
;
;  Notes: TBackWindow is a window that have TBackBuffer object associated and all drawing
;         happens in the back buffer. This way the repainting events are processed
;         flicker free on all supported OSes.
;_________________________________________________________________________________________
module "TBackWindow library"


object TBackWindow, TWindow
; private fields
  ._pShadow      dd  ?      ; pointer to TBackBuffer
  ._fShadowReady dd ?

; parameters
  param .pShadow, ._pShadow, .SetShadow

; methods
  method   .Destroy
  method   .SetShadow, .value

  method   .SysEventHandler, .pEvent

  abstract ._RedrawShadow  ; abstract method to be implemented in descending classes.
endobj


;_________________________________________________________________________________________


method TBackWindow.Destroy
begin
        set     [.self], TBackWindow:pShadow, 0
        return
endp


;_________________________________________________________________________________________


method TBackWindow.SetShadow
begin
        push    eax esi

        mov     esi, [.self]
        mov     eax, [.value]
        xchg    eax, [esi+TBackWindow._pShadow]
        cmp     eax, [esi+TBackWindow._pShadow]
        je      .finish

        test    eax, eax
        jz      .finish

        stdcall DestroyBackBuffer, eax

.finish:
        mov     [esi+TBackWindow._fShadowReady], 0
        pop     esi eax
        return
endp


;_________________________________________________________________________________________


method TBackWindow.SysEventHandler
begin
        pushad

        mov     esi, [.self]
        mov     ebx, [.pEvent]

        cmp     [ebx+TSysEvent.event], sePaint
        je      .paint

        cmp     [ebx+TSysEvent.event], seResize
        je      .resize

        inherited [.pEvent]

.continue:
        popad
        return

;.........................................................................................
.resize:
;        DebugMsg "Window resized!"
;        OutputValue " width=", [ebx+TMoveResizeEvent.newWidth], 10, -1
;        OutputValue "height=", [ebx+TMoveResizeEvent.newHeight], 10, -1

        mov     [esi+TBackWindow._fShadowReady], 0
        jmp     .continue

;.........................................................................................

.paint:
locals
  .clip_bounds TBounds
endl
        stdcall SetClipRectangle, [ebx+TPaintEvent.context], 0

        get     edi, esi, TBackWindow:pShadow

        get     ecx, esi, TBackWindow:height
        get     eax, esi, TBackWindow:width

        test    edi, edi
        jz      .create_new_shadow

        cmp     eax, [edi+TBackBuffer.width]
        ja      .create_new_shadow

        cmp     ecx, [edi+TBackBuffer.height]
        ja      .create_new_shadow

        shl     eax, 1
        shl     ecx, 1
        add     eax, 100
        add     ecx, 100

        cmp     eax, [edi+TBackBuffer.width]
        ja      .shadow_size_ok
        cmp     ecx, [edi+TBackBuffer.height]
        ja      .shadow_size_ok

        sub     eax, 100
        sub     ecx, 100
        shr     eax, 1
        shr     ecx, 1

.create_new_shadow:
        cmp     [esi+TBackWindow.handle], 0
        je      .end_paint

        lea     eax, [3*eax]
        lea     ecx, [3*ecx]
        sar     eax, 1
        sar     ecx, 1
        add     eax, 100
        add     ecx, 100

;        DebugMsg "Back buffer created."
;        OutputValue " width=", eax, 10, -1
;        OutputValue "height=", ecx, 10, -1

        stdcall CreateBackBuffer, [esi+TBackWindow.handle], eax, ecx
        jc      .end_paint

        set     esi, TBackWindow:pShadow, eax
        jmp     .draw

.shadow_size_ok:
        cmp     [esi+TBackWindow._fShadowReady], FALSE
        jne     .shadowok

.draw:
;        stdcall Get, esi, TWindow.FreeArea

        exec    esi, TBackWindow:_RedrawShadow
        mov     [esi+TBackWindow._fShadowReady], TRUE

;        DebugMsg "Back buffer repainted."

.shadowok:
        lea     eax, [.clip_bounds]
        lea     ecx, [ebx+TPaintEvent.rect]
        stdcall RectToBounds, eax, ecx
        stdcall SetClipRectangle, [ebx+TPaintEvent.context], eax
        stdcall DrawBackBuffer, [ebx+TPaintEvent.context], [esi+TBackWindow._pShadow], 0, 0

        inc     [esi+TWindow.___counter]        ; debug code

;        DebugMsg "Window painted."
;        OutputValue "     X=", [.clip_bounds.x], 10, -1
;        OutputValue "     Y=", [.clip_bounds.y], 10, -1
;        OutputValue " width=", [.clip_bounds.width], 10, -1
;        OutputValue "height=", [.clip_bounds.height], 10, -1


.end_paint:
        clc
        popad
        return

endp


;_________________________________________________________________________________________





endmodule
