; _______________________________________________________________________________________
;|                                                                                       |
;| ..::FreshLib::..  Free, open source. Licensed under "BSD 2-clause" license."          |
;|_______________________________________________________________________________________|
;
;  Description: TForm object class
;
;  Target OS: Any
;
;  Dependencies:
;
;  Notes: Represents form window that to serve as parent window for other controls.
;_________________________________________________________________________________________

module "TForm library"


mrNone   = 0
mrOK     = 1
mrCancel = 2
mrAbort  = 3
mrRetry  = 4
mrIgnore = 5
mrYes    = 6
mrNo     = 7
mrMaybe  = 8


object TForm, TWindow

  ._modal_result dd ?
  ._OnClose      dd ?         ; On close window event handler.

  ._p_split_grid     dd ?
  ._p_split_template dd ?
  ._drag_splitter    dd ?

  param .ModalResult, ._modal_result, ._modal_result
  param .OnClose, ._OnClose, ._OnClose

  param .SplitGrid, ._p_split_grid, .SetSplitGrid

  method .__RealignSplitGrid, .newW, .newH

  method .SetSplitGrid, .value
  method .AttachControlToCell, .pWindow, .idCell

  method .SetWidth, .value
  method .SetHeight, .value

  method .EventMouseMove, .x, .y, .kbdState
  method .EventButtonPress, .button, .kbdState, .x, .y
  method .EventButtonRelease, .button, .kbdState, .x, .y

  method .Resize, .newWidth, .newHeight

  method .CloseRequest, .reason
  method .Paint

endobj



;----------------------------------------------------------------------
; Interface for TForm.OnClose user handler.
; Arguments:
;   .self - pointer to the TForm object
;   .reason - the reason for the close request.
;
; Returns:
;   CF = 1 - Ignore the request. The form will not be closed.
;   CF = 0 - Destroy the object.
;
; If the OnClose event handler is not set, the form will be destroyed.
;----------------------------------------------------------------------
interface TForm.OnClose, .self, .reason



; OS independent code.



method TForm.Paint
begin
        pushad

        mov     esi, [.self]
        mov     edi, [esi+TWindow._canvas]
        test    edi, edi
        jz      .finish

        stdcall DrawSolidRect, edi, 0, 0, [esi+TWindow._width], [esi+TWindow._height], [GUI.clDialogBk]

        mov     ebx, [esi+TForm._p_split_grid]
        test    ebx, ebx
        jz      .finish

        lea     ebx, [ebx+TArray.array]
        stdcall DrawSplitters, edi, ebx

.finish:
        inherited
        popad
        return
endp




method TForm.Resize        ;, .newWidth, .newHeight
begin
        exec      [.self], TForm:__RealignSplitGrid, [.newWidth], [.newHeight]
        inherited [.newWidth], [.newHeight]
        return
endp




method TForm.SetWidth
begin
        push    eax
        mov     eax, [.self]
        exec      eax, TForm:__RealignSplitGrid, [.value], [eax+TWindow._height]
        inherited [.value]
        pop     eax
        return
endp



method TForm.SetHeight
begin
        push    eax
        mov     eax, [.self]
        exec      eax, TForm:__RealignSplitGrid, [eax+TWindow._height], [.value]
        inherited [.value]
        pop     eax
        return
endp




method TForm.CloseRequest     ;, .reason
begin
        push    eax

        get     eax, [.self], TForm:OnClose

        test    eax, eax
        jz      .destroy

        stdcall eax, [.self], [.reason]
        jc      .finish

.destroy:
        destroy [.self]

.finish:
        pop     eax
        return
endp



; sets the splitgrid from a template.

method TForm.SetSplitGrid
begin
        pushad
        mov     esi, [.self]
        mov     edx, [.value]
        cmp     edx, [esi+TForm._p_split_template]
        je      .finish

        mov     [esi+TForm._p_split_template], edx

        mov     ecx, [esi+TForm._p_split_grid]
        test    ecx, ecx
        jz      .old_ok

        stdcall FreeMem, ecx

.old_ok:
        test    edx, edx
        jz      .finish

        stdcall ReadSplitGridTemplate, edx
        mov     [esi+TForm._p_split_grid], eax

        exec    esi, TForm:__RealignSplitGrid, [esi+TWindow._width], [esi+TWindow._height]
        exec    esi, TForm:Refresh

.finish:
        popad
        return
endp





method TForm.AttachControlToCell;, .pWindow, .idCell
begin
        pushad
        mov     esi, [.self]
        mov     edi, [esi+TForm._p_split_grid]
        test    edi, edi
        jz      .finish

        mov     eax, [.idCell]
        cmp     eax, [edi+TArray.count]
        jae     .finish

        imul    eax, sizeof.TSplitRect
        lea     edi, [edi+TArray.array+eax]

        push    [.pWindow]
        pop     [edi+TSplitRect.pWindow]

        exec    esi, TForm:__RealignSplitGrid, [esi+TWindow._width], [esi+TWindow._height]

.finish:
        popad
        return
endp



method TForm.__RealignSplitGrid
.rect RECT
begin
        pushad

        mov     esi, [.self]
        mov     ebx, [esi+TForm._p_split_grid]
        test    ebx, ebx
        jz      .finish

        lea     ebx, [ebx+TArray.array]

        xor     eax, eax
        mov     ecx, [.newW]
        mov     edx, [.newH]

        mov     [.rect.left], eax
        mov     [.rect.top], eax
        mov     [.rect.right], ecx
        mov     [.rect.bottom], edx

        lea     eax, [.rect]
        stdcall RealignGrid, ebx, eax


.finish:
        popad
        return
endp






method TForm.EventMouseMove     ;, .x, .y, .kbdState
begin
        pushad

        mov     ebx, [.self]

        mov     esi, [ebx+TForm._drag_splitter]
        test    esi, esi
        jz      .find_splitter

        mov     ecx, [esi+TSplitRect.type]
        and     ecx, stVert
        mov     eax, [.x+ecx] ; the respective coordinate.

        sub     eax, [esi+TSplitRect.rect.left+ecx]

        test    [esi+TSplitRect.type], stOriginBR
        jz      .sizeok

        mov     edx, [esi+TSplitRect.rect.right+ecx]
        sub     edx, [esi+TSplitRect.rect.left+ecx]
        sub     eax, edx
        neg     eax

        sub     eax, [esi+TSplitRect.spWidth]

.sizeok:
        test    [esi+TSplitRect.type], stRelative
        jz      .posok

        cdq
        mov     ebx, $8000
        imul    ebx

        mov     ebx, [esi+ecx+TSplitRect.rect.right]
        sub     ebx, [esi+ecx+TSplitRect.rect.left]     ; size of rect (x or y depending on type)

        idiv    ebx

.posok:
        mov     [esi+TSplitRect.pos], eax
        stdcall RealignGrid, esi, esi

        exec    [.self], TWindow:Refresh

.finish:
        popad
        inherited [.x], [.y], [.kbdState]
        return


.find_splitter:
        mov     edi, [ebx+TForm._p_split_grid]
        test    edi, edi
        jnz     .found

.set_default:
        mov     ecx, [ebx+TForm._cursor]
        jmp     .setit

.found:
        lea     edi, [edi+TArray.array]

        lea     eax, [.x]
        stdcall FindSplitter, edi, eax
        jnc     .set_default

        test    [eax+TSplitRect.type], stJustGap
        jnz     .finish

        mov     ecx, mcSizeH
        test    [eax+TSplitRect.type], stVert
        jz      .setit
        mov     ecx, mcSizeV

.setit:
        stdcall GetStockCursor, ecx

        get     edx, ebx, TWindow:OSWindow
        stdcall SetMouseCursor, [edx+TWindow.handle], eax
        jmp     .finish

endp



method TForm.EventButtonPress   ;, .button, .kbdState, .x, .y
  .pnt POINT
  .cliprect RECT
begin
        pushad

        mov     esi, [.self]
        mov     ebx, [esi+TForm._p_split_grid]
        test    ebx, ebx
        jz      .finish

        lea     ebx, [ebx+TArray.array]

        mov     eax, [.x]
        mov     ecx, [.y]
        mov     [.pnt.x], eax
        mov     [.pnt.y], ecx

        lea     eax, [.pnt]
        stdcall FindSplitter, ebx, eax
        jnc     .finish

        test    [eax+TSplitRect.type], stJustGap
        jnz     .finish

        mov     [esi+TForm._drag_splitter], eax

        stdcall SetMouseCapture, esi

.finish:
        popad
        inherited [.button], [.kbdState], [.x], [.y]
        return
endp



method TForm.EventButtonRelease ;, .button, .kbdState, .x, .y
begin
        push    eax

        mov     eax, [.self]
        mov     [eax+TForm._drag_splitter], 0
        stdcall SetMouseCapture, 0

.finish:
        pop     eax
        inherited [.button], [.kbdState], [.x], [.y]
        return
endp




endmodule

