Function NDW_TREE_SORT_FILTER_EVENTS(CtrlEntId, Event, Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, Param14, Param15)

/***********************************************************************************************************************

    This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
    permission from SRP Computer Solutions, Inc.

    Name        :   NDW_TREE_SORT_FILTER_EVENTS

    Description :   Event commuter module for the NDW_Tree_Sort_Filter window.

    Notes       :   This is typically called by setting up a QuickEvent to execute a procedure and	
				    the procedure will be this function. The Parameters field would then contain	
				    the necessary parameters to for proper event routing in this routine. The syntax
				    for these parameters are:														
																								
				    'event name','@SELF',['@PARAM1','@PARAMx']										
																								
				    'event name' is the actual event that is being called (e.g. 'CREATE'). It should
				    be surrounded by single quotes. '@SELF' will tell NDW_DatePicker_Events what    
				    the fully qualified name of the current control is. '@PARAMx' is to pass any	
				    additional parameters that the current event may have. '@SELF' and '@PARAMx'	
				    also need to be surrounded by single quotes.									

    Parameters  :
        Event          [in] -- The event that is being executed in the window.							
        CtrlEntId	   [in] -- The control that is calling the event.									
        Param1-13	   [in] -- Additional parameters that the event is passing through.				

    History     :   (Date, Initials, Notes)
        01/12/24    djs     Adapted from NDW_TREE_FILTER_EVENTS.
        

***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler
#window NDW_TREE_SORT_FILTER

$Insert APP_INSERTS
$Insert EVENT_SETUP

Equ TreeFilter$     To @Window : '.OLE_TREE_FILTER'

Declare function   SendMessage, Send_Message, SRP_Get_Window_Rect, Delete, SRP_Rotate_Array, Insert

Equ DTM_READCELLRECT$       to 1079
Equ DTM_GETCELLLEFTBOTTOM$  to 1160
Equ DTA_CURRENT$            to 1

SubclassInfo    = Form_Services('FindSubclassControl')
Subclass        = SubclassInfo<1>

If Assigned(Param8) else Param8 = ''

// Update the arguments so that the OpenInsight OLE event will treate the ActiveX event as a native event handler.
If Event EQ 'OLE' then
    Transfer Event to OIEvent
    Transfer Param1 to Event
    Transfer Param2 to Param1
    Transfer Param3 to Param2
    Transfer Param4 to Param3
    Transfer Param5 to Param4
    Transfer Param6 to Param5
    Transfer Param7 to Param6
    Transfer Param8 to Param7
end

GoToEvent Event for CtrlEntId else
    // Event not implemented
end

If Assigned(EventFlow) else EventFlow = EVENT_CONTINUE$

Return EventFlow or 1


//-----------------------------------------------------------------------------
// EVENT HANDLERS
//-----------------------------------------------------------------------------


Event WINDOW.CREATE(CreateParam)
    
	GoSub Setup_OLE_Controls

    GoSub Determine_Position

 	SRP_Show_Window(@Window, '', '', '', True$, '', True$, True$, Size, False$)
end event


Event OLE_TREE_FILTER.OnItemCheck(ItemKey, Checked)

    Convert ',' to @FM in ItemKey
    SelectedItems = Get_Property(@Window, '@SELECTED_FILTER_ITEMS')
    KeyValue      = Get_Property(TreeFilter$, 'OLE.Item[' : ItemKey : ']')<1>
    If ItemKey NE '(Select All)' then
        SelectedItems<0, ItemKey> = Checked
        If Checked then
            // Check edge case that user has selected all items, but (Select All) is not set to true.
            ItemList    = Get_Property(@Window, '@ALL_FILTER_ITEMS')
            AllSelected = DCount(ItemList, @VM) EQ Sum(SelectedItems)
            If AllSelected then
                Set_Property(TreeFilter$, 'OLE.ItemChecked[(Select All)]', True$)
            end else
                // Set (Select All) item to mixed state.
                Set_Property(TreeFilter$, 'OLE.ItemChecked[(Select All)]', 2)
            end
            
        end else
            // Check for edge case
            If (Sum(SelectedItems) EQ 0) then
                // User has deselected every item
                Set_Property(TreeFilter$, 'OLE.ItemChecked[(Select All)]', False$)
            end else
                // Not all items are selected. Set (Select All) to mixed state.
                Set_Property(TreeFilter$, 'OLE.ItemChecked[(Select All)]', 2)
            end
        end
    end else
        ItemList      = Get_Property(@Window, '@ALL_FILTER_ITEMS')
        If Checked then
            // Select all items
            For each Item in ItemList using @VM setting vPos
                SelectedItems<0, vPos> = True$
                Set_Property(TreeFilter$, 'OLE.ItemChecked[' : vPos : ']', True$)
            Next Item
        end else
            // Deselect all items
            For each Item in ItemList using @VM setting vPos
                SelectedItems<0, vPos> = False$
                Set_Property(TreeFilter$, 'OLE.ItemChecked[' : vPos : ']', False$)
            Next Item
        end
    end
    Set_Property(@Window:'.PUB_OK', 'ENABLED', (Sum(SelectedItems) NE 0))
    Set_Property(@Window, '@SELECTED_FILTER_ITEMS', SelectedItems)    
end event


Event PUB_CANCEL.CLICK()
    End_Dialog(@Window, 'Cancel')
end event


Event PUB_OK.CLICK()
    GoSub Return_Filter_Items
end event


********************************************
* Internal procedures follow				
********************************************

Setup_OLE_Controls:
    SizeWindow  = Get_Property(@Window, 'SIZE')
    
    Set_Property(TreeFilter$, 'OLE.Theme', 'Windows7Blue')
    Set_Property(TreeFilter$, 'OLE.Font', SystemFont$)

	// Use asynchronous event handling (because in Dialog Box)
	Send_Message(TreeFilter$, "QUALIFY_EVENT", "ALL_OLES", 1)

    GoSub Setup_Filter_Items
   
return


Determine_Position:
    // Determine the Parent window
    MdiActive = Get_Property(Parent, "MDIACTIVE")
    If Len(MdiActive) then
        Parent = MdiActive
    end

    // Determine the control to do the lookup for
    CtrlId = Get_Property(Parent, "FOCUS")
    
    // Get some property values
    Ctrls  = Parent     :@RM: @Window :@RM: CtrlId :@RM: CtrlId   :@RM: CtrlId   :@RM: CtrlId      :@RM: "SYSTEM"
    Props  = "MDIFRAME" :@RM: "SIZE"  :@RM: "TYPE" :@RM: "HANDLE" :@RM: "SELPOS" :@RM: "ORIG_TEXT" :@RM: "SIZE"
    Vals = Get_Property(Ctrls, Props)

    Frame  = Field(Vals, @RM, 1)
    Size   = Field(Vals, @RM, 2)
    Type   = Field(Vals, @RM, 3)
    CtlHdl = Field(Vals, @RM, 4)
    SelPos = Field(Vals, @RM, 5)
    ProgID = Field(Vals, @RM, 6)    ; // To check for OLE EditTables
    Screen = Field(Vals, @RM, 7)
    
    // If no frame, use window size to determine if calendar should show below or above control
    If Frame then
        WinSize = SRP_Get_Window_Rect(Frame)
    end else
        WinSize = SRP_Get_Window_Rect(Parent)
    end        

    Table = (Type EQ "EDITTABLE") OR (ProgID _EQC "SRP.EditTable.1")
    If Table else
        SelPos = ""
    end
  
    If ProgID _EQC "SRP.EditTable.1" then
        // OLE EditTables need to use the CellText property
        ColNo = SelPos<1>
        RowNo = SelPos<2>
        Convert @FM to ";" in SelPos
        DfltDate = Iconv(Get_Property(CtrlId, "OLE.CellText[":SelPos:"]"), "D")
    end else
        DfltDate = Get_Property(CtrlId, "INVALUE", SelPos)
    end
 	If DfltDate then
        Set_Property(@Window:".OLE_DATEPICKER", "OLE.Selection", DfltDate)
        Send_Message(@Window:".OLE_DATEPICKER", "OLE.EnsureVisible", DfltDate)
    end

    Rect = Str(\00\, 16)
    
    CtlSize = SRP_Get_Window_Rect(CtrlId)
    xPos    = CtlSize<1>
    yPos    = CtlSize<2>
    
    If Table then
        // add x, y and y+h of cell
        If ProgID _EQC "SRP.EditTable.1" then
            CellSize = Memory_Services('GetValue', 'Cell_Size')
            *xPos   += CellSize<1>
            xPos    += CellSize<1> + 1  ; // This makes alignment better
            yPos    += CellSize<2>
            cyPos    = yPos + CellSize<4>
        end else
            LeftBottom = SendMessage(CtlHdl, DTM_GETCELLLEFTBOTTOM$, DTA_CURRENT$,  0)
            xPos += mod(LeftBottom, 65536)
            cyPos = yPos + int(LeftBottom / 65536)

            // Get y position with different SendMessage call
            SendMessage(CtlHdl, DTM_READCELLRECT$, DTA_CURRENT$, GetPointer(Rect))
            yPos += seq(Rect [5,1]) + (seq(Rect [6,1]) * 256)
        end
    end else
        // get y+h of control
        cyPos = CtlSize<2> + CtlSize<4>
    end
    
    // get y+h of frame or parent window
    MaxCy = WinSize<2> + WinSize<4>
    
    // Set x and y of calendar window
    Size<1> = xPos
    If Size<1> + Size<3> GT Screen<1> AND (Screen<1> GT Size<1>) then
        // Shift calendar to left to fit on screen
        Size<1> = Screen<1> - Size<3>
    end    
    If cyPos+Size<4> GT MaxCy then
        // Position above control so calendar shows fully
        Size<2> = yPos - Size<4>
    end else    
        Size<2> = cyPos
    end
return


Setup_Filter_Items:

    ItemList            = CreateParam<1>
    SelectedFilterItems = CreateParam<2>
    Swap @VM with @FM in ItemList
    Swap @SVM with @VM in ItemList
    ItemListTemp        = SRP_Rotate_Array(ItemList, @FM)<3>
    SelectAllItem       = 1 : @VM : '(Select All)'  : @VM : '(Select All)' : @VM : @VM : @VM : @VM : @VM : @VM : @VM : @VM : 'Left' : @VM : @VM
    ItemList            = Insert(ItemList, 1, 0, 0, SelectAllItem)
    Set_Property(TreeFilter$, 'OLE.ItemList', ItemList)
    Set_Property(@Window, '@ALL_FILTER_ITEMS', ItemListTemp)
    Set_Property(@Window, '@SELECTED_FILTER_ITEMS', SelectedFilterItems)
    AllSelected         = Sum(SelectedFilterItems) EQ DCount(ItemListTemp, @VM)
    If AllSelected then
        Set_Property(TreeFilter$, 'OLE.ItemChecked[(Select All)]', True$)
    end else
        // Set (Select All) to mixed case
        Set_Property(TreeFilter$, 'OLE.ItemChecked[(Select All)]', 2)
    end
    For Each CheckVal in SelectedFilterItems using @VM setting vPos
        Set_Property(TreeFilter$, 'OLE.ItemChecked[' : vPos : ']', CheckVal)
    Next CheckVal
return


Return_Filter_Items:
    NewSelectedItems    = ''
    ParentControl       = Get_Property(@Window, '@PARENTCONTROL')
    SelectedFilterItems = Get_Property(@Window, '@SELECTED_FILTER_ITEMS')
    
    If Len(ParentControl) then
        Send_Event(ParentControl, 'UPDATE', SelectedFilterItems)
        Post_Event(@Window, 'CLOSE')
    end else
	    End_Dialog(@Window, SelectedFilterItems)
	end
	
	// Since we are ending the window now, there is no need to allow the event chain to continue.
	// If we do, then we will get the "labeled common variable has been freed and is no longer valid" error.	
    EventFlow = EVENT_CONTINUE_NO_SYSTEM$
return

