VERSION 5.00
Object = "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0"; "MSCOMCTL.OCX"
Begin VB.UserControl RecommendedArea 
   Appearance      =   0  'Flat
   BackColor       =   &H80000005&
   ClientHeight    =   8055
   ClientLeft      =   0
   ClientTop       =   0
   ClientWidth     =   14205
   DrawMode        =   14  'Copy Pen
   ScaleHeight     =   8055
   ScaleWidth      =   14205
   Begin Project1.ToolbarControl tlb_main 
      Height          =   690
      Left            =   0
      TabIndex        =   0
      Top             =   0
      Width           =   13725
      _ExtentX        =   24209
      _ExtentY        =   1217
   End
   Begin VB.Frame frm_frames 
      Height          =   7215
      Index           =   1
      Left            =   0
      TabIndex        =   1
      Top             =   720
      Width           =   13725
      Begin VB.Frame frm_frames 
         Height          =   1395
         Index           =   5
         Left            =   90
         TabIndex        =   43
         Top             =   180
         Width           =   5745
         Begin VB.TextBox txt_search 
            Height          =   288
            Left            =   1380
            MaxLength       =   40
            TabIndex        =   46
            Top             =   210
            Width           =   4215
         End
         Begin VB.CommandButton btn_next 
            Caption         =   "#Find Next"
            Height          =   345
            Left            =   3060
            TabIndex        =   45
            Top             =   870
            Width           =   1212
         End
         Begin VB.CommandButton btn_cancelFind 
            Caption         =   "#Cancel"
            Height          =   345
            Left            =   4410
            TabIndex        =   44
            Top             =   870
            Width           =   1212
         End
         Begin VB.Label lbl_labels 
            Caption         =   "#Find"
            Height          =   255
            Index           =   16
            Left            =   150
            TabIndex        =   47
            Top             =   270
            Width           =   1215
         End
      End
      Begin VB.Frame frm_frames 
         Caption         =   "#Filter "
         Height          =   855
         Index           =   0
         Left            =   90
         TabIndex        =   3
         Top             =   720
         Width           =   13545
         Begin Project1.ArmCombobox cbo_MBL 
            Height          =   345
            Left            =   60
            TabIndex        =   4
            Top             =   420
            Width           =   2205
            _ExtentX        =   3889
            _ExtentY        =   609
         End
         Begin Project1.ArmCombobox cbo_PF 
            Height          =   345
            Left            =   2310
            TabIndex        =   5
            Top             =   420
            Width           =   2205
            _ExtentX        =   3889
            _ExtentY        =   609
         End
         Begin Project1.ArmCombobox cbo_PP 
            Height          =   345
            Left            =   4530
            TabIndex        =   6
            Top             =   420
            Width           =   2205
            _ExtentX        =   3889
            _ExtentY        =   609
         End
         Begin Project1.ArmCombobox cbo_PE 
            Height          =   345
            Left            =   6750
            TabIndex        =   7
            Top             =   420
            Width           =   2205
            _ExtentX        =   3889
            _ExtentY        =   609
         End
         Begin Project1.ArmCombobox cbo_SF 
            Height          =   345
            Left            =   8970
            TabIndex        =   8
            Top             =   420
            Width           =   2205
            _ExtentX        =   3889
            _ExtentY        =   609
         End
         Begin Project1.ArmCombobox cbo_SH 
            Height          =   345
            Left            =   11190
            TabIndex        =   9
            Top             =   420
            Width           =   2205
            _ExtentX        =   3889
            _ExtentY        =   609
         End
         Begin VB.Label lbl_labels 
            Alignment       =   2  'Center
            Caption         =   "#Base material"
            Height          =   255
            Index           =   1
            Left            =   60
            TabIndex        =   15
            Top             =   180
            Width           =   2205
         End
         Begin VB.Label lbl_labels 
            Alignment       =   2  'Center
            Caption         =   "#Product family"
            Height          =   255
            Index           =   2
            Left            =   2280
            TabIndex        =   14
            Top             =   180
            Width           =   2205
         End
         Begin VB.Label lbl_labels 
            Alignment       =   2  'Center
            Caption         =   "#Pattern"
            Height          =   255
            Index           =   3
            Left            =   4500
            TabIndex        =   13
            Top             =   180
            Width           =   2205
         End
         Begin VB.Label lbl_labels 
            Alignment       =   2  'Center
            Caption         =   "#Edge detail/Product"
            Height          =   255
            Index           =   4
            Left            =   6720
            TabIndex        =   12
            Top             =   180
            Width           =   2205
         End
         Begin VB.Label lbl_labels 
            Alignment       =   2  'Center
            Caption         =   "#Surface"
            Height          =   255
            Index           =   5
            Left            =   8940
            TabIndex        =   11
            Top             =   180
            Width           =   2205
         End
         Begin VB.Label lbl_labels 
            Alignment       =   2  'Center
            Caption         =   "#Shape"
            Height          =   255
            Index           =   6
            Left            =   11160
            TabIndex        =   10
            Top             =   180
            Width           =   2205
         End
      End
      Begin Project1.ArmGrid grd_list 
         Height          =   5385
         Left            =   90
         TabIndex        =   2
         Top             =   1740
         Width           =   13545
         _ExtentX        =   23892
         _ExtentY        =   9499
      End
      Begin Project1.ArmCombobox cbo_category 
         Height          =   345
         Left            =   1920
         TabIndex        =   16
         Top             =   300
         Width           =   3015
         _ExtentX        =   5318
         _ExtentY        =   609
      End
      Begin VB.Label lbl_labels 
         Caption         =   "#Category"
         Height          =   255
         Index           =   0
         Left            =   120
         TabIndex        =   17
         Top             =   360
         Width           =   1815
      End
   End
   Begin VB.Frame frm_frames 
      Height          =   7215
      Index           =   2
      Left            =   0
      TabIndex        =   18
      Top             =   690
      Width           =   13725
      Begin Project1.ArmGrid grd_areaSAP 
         Height          =   2235
         Left            =   90
         TabIndex        =   36
         Top             =   4920
         Width           =   6975
         _ExtentX        =   12303
         _ExtentY        =   3942
      End
      Begin VB.Frame frm_frames 
         Height          =   3465
         Index           =   3
         Left            =   90
         TabIndex        =   35
         Top             =   1410
         Width           =   13515
         Begin VB.PictureBox pic_Out 
            AutoSize        =   -1  'True
            Height          =   480
            Left            =   6360
            ScaleHeight     =   420
            ScaleWidth      =   420
            TabIndex        =   42
            Top             =   1830
            Width           =   480
         End
         Begin VB.PictureBox pic_In 
            AutoSize        =   -1  'True
            Height          =   480
            Left            =   6360
            ScaleHeight     =   420
            ScaleWidth      =   420
            TabIndex        =   41
            Top             =   1110
            Width           =   480
         End
         Begin Project1.ArmTreeView tvw_recommSelected 
            Height          =   2805
            Left            =   8220
            TabIndex        =   38
            Top             =   480
            Width           =   4305
            _ExtentX        =   7594
            _ExtentY        =   4948
         End
         Begin Project1.ArmTreeView tvw_recommNotSelected 
            Height          =   2805
            Left            =   600
            TabIndex        =   37
            Top             =   480
            Width           =   4305
            _ExtentX        =   7594
            _ExtentY        =   4948
         End
         Begin VB.Label lbl_labels 
            Alignment       =   2  'Center
            Caption         =   "#Selected"
            Height          =   255
            Index           =   15
            Left            =   8220
            TabIndex        =   40
            Top             =   210
            Width           =   4215
         End
         Begin VB.Label lbl_labels 
            Alignment       =   2  'Center
            Caption         =   "#Not selected"
            Height          =   255
            Index           =   14
            Left            =   600
            TabIndex        =   39
            Top             =   210
            Width           =   4215
         End
      End
      Begin VB.Frame frm_frames 
         Height          =   825
         Index           =   4
         Left            =   90
         TabIndex        =   19
         Top             =   150
         Width           =   13545
         Begin VB.TextBox txt_Category 
            Height          =   288
            Left            =   120
            Locked          =   -1  'True
            TabIndex        =   26
            Top             =   420
            Width           =   1815
         End
         Begin VB.TextBox txt_BaseMaterial 
            Height          =   288
            Left            =   2040
            Locked          =   -1  'True
            TabIndex        =   25
            Top             =   420
            Width           =   1815
         End
         Begin VB.TextBox txt_Family 
            Height          =   288
            Left            =   3960
            Locked          =   -1  'True
            TabIndex        =   24
            Top             =   420
            Width           =   1815
         End
         Begin VB.TextBox txt_pattern 
            Height          =   288
            Left            =   5880
            Locked          =   -1  'True
            TabIndex        =   23
            Top             =   420
            Width           =   1815
         End
         Begin VB.TextBox txt_edge 
            Height          =   288
            Left            =   7800
            Locked          =   -1  'True
            TabIndex        =   22
            Top             =   420
            Width           =   1815
         End
         Begin VB.TextBox txt_shape 
            Height          =   288
            Left            =   11610
            Locked          =   -1  'True
            TabIndex        =   21
            Top             =   420
            Width           =   1815
         End
         Begin VB.TextBox txt_surface 
            Height          =   288
            Left            =   9690
            Locked          =   -1  'True
            TabIndex        =   20
            Top             =   420
            Width           =   1815
         End
         Begin VB.Label lbl_labels 
            Alignment       =   2  'Center
            Caption         =   "#Edge"
            Height          =   252
            Index           =   11
            Left            =   7800
            TabIndex        =   33
            Top             =   180
            Width           =   1815
         End
         Begin VB.Label lbl_labels 
            Alignment       =   2  'Center
            Caption         =   "#Family"
            Height          =   252
            Index           =   9
            Left            =   3960
            TabIndex        =   32
            Top             =   180
            Width           =   1815
         End
         Begin VB.Label lbl_labels 
            Alignment       =   2  'Center
            Caption         =   "#Category"
            Height          =   252
            Index           =   7
            Left            =   120
            TabIndex        =   31
            Top             =   180
            Width           =   1815
         End
         Begin VB.Label lbl_labels 
            Alignment       =   2  'Center
            Caption         =   "#Base material"
            Height          =   255
            Index           =   8
            Left            =   2040
            TabIndex        =   30
            Top             =   180
            Width           =   1815
         End
         Begin VB.Label lbl_labels 
            Alignment       =   2  'Center
            Caption         =   "#Pattern"
            Height          =   252
            Index           =   10
            Left            =   5880
            TabIndex        =   29
            Top             =   180
            Width           =   1815
         End
         Begin VB.Label lbl_labels 
            Alignment       =   2  'Center
            Caption         =   "#Surface"
            Height          =   255
            Index           =   12
            Left            =   9690
            TabIndex        =   28
            Top             =   180
            Width           =   1815
         End
         Begin VB.Label lbl_labels 
            Alignment       =   2  'Center
            Caption         =   "#Shape"
            Height          =   255
            Index           =   13
            Left            =   11610
            TabIndex        =   27
            Top             =   180
            Width           =   1815
         End
      End
      Begin MSComctlLib.TabStrip tbs_Area 
         Height          =   375
         Left            =   90
         TabIndex        =   34
         Top             =   1050
         Width           =   13515
         _ExtentX        =   23839
         _ExtentY        =   661
         _Version        =   393216
         BeginProperty Tabs {1EFB6598-857C-11D1-B16A-00C0F0283628} 
            NumTabs         =   1
            BeginProperty Tab1 {1EFB659A-857C-11D1-B16A-00C0F0283628} 
               Caption         =   "Recommended"
               ImageVarType    =   2
            EndProperty
         EndProperty
      End
   End
   Begin VB.Menu mnu_copyPopup 
      Caption         =   ""
      Begin VB.Menu mnu_copyFrom 
         Caption         =   "#copy from"
      End
      Begin VB.Menu mnu_copyTo 
         Caption         =   "#copy to"
      End
      Begin VB.Menu mnu_copyNow 
         Caption         =   "#copy now"
      End
   End
End
Attribute VB_Name = "RecommendedArea"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
' **************************************************************************************************
' **************************************** TOOL CONSTANTS ******************************************
' **************************************************************************************************
Private Const SEP1 As String = "®"
Private Const SEP2 As String = "©"
Private Const SEP As String = SEP1 + SEP2
Private Const C_APPNAME As String = "REA" ' for error log
Private Const C_SCREENNAME As String = "RecommendedArea"    ' for loading screen constants
Private Const C_TOOLBARFACE_ITEM_LST As String = "0"
Private Const C_TOOLBARFACE_ITEM_MTNC As String = "1"
Private Const C_TOOLBARFACE_ITEM_VIEW As String = "2"

' ****************************************** TOOL CONSTANTS ***************************************


' **************************************************************************************************
' **************************************** USER DEFINED ERRORS *************************************
' **************************************************************************************************
Private Enum ArmErr
    DBCnxFailed = vbObjectError + 1 ' Unable to connect to the database
    CPTAlreadyInitialized = vbObjectError + 2   ' We try to initialize a component that is already initialized
    CPTNotInitialized = vbObjectError + 3       ' We try to use or free that is not initialized yet
    InvalidArgument = vbObjectError + 4
    PropertyNotSet = vbObjectError + 5
    CompFncFailed = vbObjectError + 6          ' when component function fail
    QuietException = vbObjectError + 7              ' do not display error message
End Enum
' *************************************** USER DEFINED ERRORS **************************************

' **************************************************************************************************
' *************************************** CONTROL MEMBERS ******************************************
' **************************************************************************************************
Dim ml_U_Code As Long               ' if this is user loging app, needed to log errors into A_Log
Dim ms_LoginName As String
Dim ms_Language_Code As String
Dim mb_Initialized As Boolean   ' True if the component is already initialized
Dim mo_userRights As UserRights_t   ' rights assigned for current user
Dim mu_ActiveMode As ArmScreenMode
Dim ml_detailTreeCursor As Long     ' cursor to hold all data
Dim ml_detailSelectedCursor As Long ' holds selected data
Dim ms_Title As String              ' title of user control - can be assigned as Caption to the parent form or title for printing

Private Type UserRights_t
    allowUpdate As Boolean
End Type

Private Enum ArmScreenMode
  smMain
  smUpdate
  smView
  smSearch
End Enum

#If LIVE = 1 Then
    Dim mo_Db As Object
#Else
    Dim mo_Db As ARMSYSCOMLib.ArmDb
#End If

' *************************************** CONTROL MEMBERS ******************************************
Public Event quit()
Public Event ShowHelp()
Public Event PrintGrid(ByVal ao_grid As ArmGrid)

' mb_Initialized is a read-only property, indicates the status of the component
Public Property Get Initialized() As Boolean
    Initialized = mb_Initialized
End Property

Public Property Let U_Code(ByVal al_U_code As Long)
On Error GoTo ErrHandler
    
    If Initialized Then Call Err.Raise(ArmErr.CPTAlreadyInitialized)
    
    ml_U_Code = al_U_code
    Exit Property
ErrHandler:
    Call ErrorHandler("U_Code(Let)")
End Property

Public Property Let LoginName(ByVal as_loginName As String)
On Error GoTo ErrHandler
    
    If Initialized Then Call Err.Raise(ArmErr.CPTAlreadyInitialized)
    
    ms_LoginName = as_loginName
    Exit Property
ErrHandler:
    Call ErrorHandler("LoginName(Let)")
End Property

Public Property Let Language_Code(as_Language_code As String)
On Error GoTo ErrHandler
    
    If Initialized Then Call Err.Raise(ArmErr.CPTAlreadyInitialized)
    If Len(as_Language_code) <> 1 Then Call Err.Raise(ArmErr.InvalidArgument, "", "Language_code must contains only 1 char")
    
    ms_Language_Code = as_Language_code
    Exit Property
ErrHandler:
    Call ErrorHandler("Language(Let)")
End Property

Public Property Set Db(ByRef ao_Db As ArmDb)
On Error GoTo ErrHandler
    
    If Initialized Then Call Err.Raise(ArmErr.CPTAlreadyInitialized)
    If ao_Db Is Nothing Then Call Err.Raise(ArmErr.InvalidArgument)
    
    Set mo_Db = ao_Db
    Exit Property
ErrHandler:
    Call ErrorHandler("Db(Set)")
End Property

Public Property Get Title() As String
    Title = ms_Title
End Property

Private Property Get armComboBoxKey(ByVal ao_ComboBox As ArmCombobox) As String
On Error GoTo ErrHandler
    If ao_ComboBox.SelectedItem Is Nothing Then
        armComboBoxKey = ""
    Else
        armComboBoxKey = ao_ComboBox.SelectedItem.Key
    End If
    Exit Property
ErrHandler:
    Call ErrorHandler("armComboBoxKey(get)")
End Property

Private Property Let CopyTo(ByVal al_Index As Long)
On Error GoTo ErrHandler
    mnu_copyTo.Tag = CStr(al_Index)
    
    ' remove last value
    mnu_copyTo.Caption = CutRightNumber(mnu_copyTo.Caption)
    
    ' display new
    If al_Index <> -1 Then
        mnu_copyTo.Caption = mnu_copyTo.Caption & " " & mnu_copyTo.Tag
    End If
    Exit Property
ErrHandler:
    Call ErrorHandler("copyTo(let)")
End Property

Private Property Get CopyTo() As Long
On Error GoTo ErrHandler
    If mnu_copyTo.Tag = "" Then
        CopyTo = -1
    Else
        Debug.Assert (isNumeric(mnu_copyTo.Tag))
        CopyTo = CLng(mnu_copyTo.Tag)
    End If
    Exit Property
ErrHandler:
    Call ErrorHandler("copyTo(get)")
End Property

Private Property Let copyFrom(ByVal al_Index As Long)
On Error GoTo ErrHandler
    mnu_copyFrom.Tag = CStr(al_Index)

    ' remove last value
    mnu_copyFrom.Caption = CutRightNumber(mnu_copyFrom.Caption)
    
    ' display new
    If al_Index <> -1 Then
        mnu_copyFrom.Caption = mnu_copyFrom.Caption & " " & mnu_copyFrom.Tag
    End If
    Exit Property
ErrHandler:
    Call ErrorHandler("copyFrom(let)")
End Property

Private Property Get copyFrom() As Long
On Error GoTo ErrHandler
    If mnu_copyFrom.Tag = "" Then
        copyFrom = -1
    Else
        Debug.Assert (isNumeric(mnu_copyFrom.Tag))
        copyFrom = CLng(mnu_copyFrom.Tag)
    End If
    Exit Property
ErrHandler:
    Call ErrorHandler("copyFrom(get)")
End Property

Public Sub Load_A_Com()
    
On Error GoTo ErrHandler
    If Initialized Then Call Err.Raise(ArmErr.CPTAlreadyInitialized)
    If mo_Db Is Nothing Then Call Err.Raise(ArmErr.PropertyNotSet, "", "mo_Db")
    If Len(ms_Language_Code) < 1 Then Call Err.Raise(ArmErr.PropertyNotSet, "", "ms_Language_Code")

    ml_detailTreeCursor = 0
    
    Call GetUserRight(mo_userRights)
    
    ' set pictures
    pic_In.Picture = LoadResPicture(37, 1)
    pic_Out.Picture = LoadResPicture(24, 1)
    
    Set cbo_Category.ArmDb = mo_Db
    Set cbo_MBL.ArmDb = mo_Db
    Set cbo_PE.ArmDb = mo_Db
    Set cbo_PF.ArmDb = mo_Db
    Set cbo_PP.ArmDb = mo_Db
    Set cbo_SF.ArmDb = mo_Db
    Set cbo_SH.ArmDb = mo_Db
    Set tlb_main.ArmDb = mo_Db
    Set grd_List.ArmDb = mo_Db
    Set grd_areaSAP.ArmDb = mo_Db
    Set tvw_recommSelected.ArmDb = mo_Db
    Set tvw_recommNotSelected.ArmDb = mo_Db
    
    Call cbo_Category.Load_A_Com
    Call cbo_MBL.Load_A_Com
    Call cbo_PE.Load_A_Com
    Call cbo_PF.Load_A_Com
    Call cbo_PP.Load_A_Com
    Call cbo_SF.Load_A_Com
    Call cbo_SH.Load_A_Com
    Call tlb_main.Load_A_Com
    Call grd_List.Load_A_Com
    Call grd_areaSAP.Load_A_Com
    Call tvw_recommSelected.Load_A_Com
    Call tvw_recommNotSelected.Load_A_Com
    
    ' Initialize the toolbar
    tlb_main.Language = ms_Language_Code
    tvw_recommSelected.Language = ms_Language_Code
    tvw_recommNotSelected.Language = ms_Language_Code
    
    ' init controls
    Call InitComponents
    Call LoadLabels(UserControl.Controls, C_SCREENNAME, ms_Language_Code)
    Call ChangeCharset(UserControl.Controls, GetCodePageFromLanguage(mo_Db, ms_Language_Code))
    
    
    ' set layout
    Call InitCtrlSize
    Call FillCombos
    
    mb_Initialized = True
    
    ' display starting face
    Call UpdateUI(ArmScreenMode.smMain)
    
    Exit Sub

ErrHandler:
    Call ErrorMessage("Load_A_Com()")
    
End Sub

Public Sub Unload_A_Com()
On Error GoTo ErrHandler

    If Not Initialized Then Call Err.Raise(ArmErr.CPTNotInitialized)
    
    Call cbo_Category.Unload_A_Com
    Call cbo_MBL.Unload_A_Com
    Call cbo_PE.Unload_A_Com
    Call cbo_PF.Unload_A_Com
    Call cbo_PP.Unload_A_Com
    Call cbo_SF.Unload_A_Com
    Call cbo_SH.Unload_A_Com
    Call tlb_main.Unload_A_Com
    Call grd_List.Unload_A_Com
    Call grd_areaSAP.Unload_A_Com
    Call tvw_recommSelected.Unload_A_Com
    Call tvw_recommNotSelected.Unload_A_Com

    If ml_detailTreeCursor <> 0 Then
        Call mo_Db.Close(ml_detailTreeCursor)
        ml_detailTreeCursor = 0
    End If
    
    If ml_detailSelectedCursor <> 0 Then
        Call mo_Db.Close(ml_detailSelectedCursor)
        ml_detailSelectedCursor = 0
    End If
    
    Set mo_Db = Nothing
    
    Exit Sub

ErrHandler:
    If ml_detailTreeCursor <> 0 Then
        Call mo_Db.Close(ml_detailTreeCursor)
        ml_detailTreeCursor = 0
    End If
    If ml_detailSelectedCursor <> 0 Then
        Call mo_Db.Close(ml_detailSelectedCursor)
        ml_detailSelectedCursor = 0
    End If
    
    Set mo_Db = Nothing
    Call ErrorHandler("Unload_A_Com()")
    
End Sub

Private Sub UpdateUI(ByVal au_Mode As ArmScreenMode)
On Error GoTo ErrHandler

    ' set active face
    mu_ActiveMode = au_Mode

    ' apply face
    Dim lo_ctrl As Object

    ' hide all frames
    For Each lo_ctrl In frm_frames
        lo_ctrl.Visible = False
    Next

    ' we have clean screen we can display proper controls
    Select Case mu_ActiveMode
        Case smMain
            Set lo_ctrl = GetControl(frm_frames, "frm_main")
            lo_ctrl.Visible = True
            
            Set lo_ctrl = GetControl(frm_frames, "frm_filter")
            lo_ctrl.Visible = True
            
            cbo_Category.Visible = True
            lbl_labels(0).Visible = True

            grd_List.Enabled = True
            
            tlb_main.Enabled = True
    
            Call tlb_main.DisplayFace(C_TOOLBARFACE_ITEM_LST)
            tlb_main.ButtonVisible("B") = mo_userRights.allowUpdate
            tlb_main.ButtonVisible("X") = mo_userRights.allowUpdate
        Case smUpdate
            ' we are in Update section
            Set lo_ctrl = GetControl(frm_frames, "frm_detail")
            lo_ctrl.Visible = True
            Set lo_ctrl = GetControl(frm_frames, "frm_detailSelORnot")
            lo_ctrl.Visible = True
            Set lo_ctrl = GetControl(frm_frames, "frm_detailFilter")
            lo_ctrl.Visible = True
            
            pic_In.Visible = True
            pic_Out.Visible = True
            
            Call tlb_main.DisplayFace(C_TOOLBARFACE_ITEM_MTNC)
        Case smView
            ' we are in PreView section
            Set lo_ctrl = GetControl(frm_frames, "frm_detail")
            lo_ctrl.Visible = True
            Set lo_ctrl = GetControl(frm_frames, "frm_detailSelORnot")
            lo_ctrl.Visible = True
            Set lo_ctrl = GetControl(frm_frames, "frm_detailFilter")
            lo_ctrl.Visible = True
            
            pic_In.Visible = False
            pic_Out.Visible = False
            
            Call tlb_main.DisplayFace(C_TOOLBARFACE_ITEM_VIEW)
        Case smSearch
            ' search screen
            Set lo_ctrl = GetControl(frm_frames, "frm_main")
            lo_ctrl.Visible = True
            Set lo_ctrl = GetControl(frm_frames, "frm_find")
            lo_ctrl.Visible = True
            
            cbo_Category.Visible = False
            lbl_labels(0).Visible = False
            
            grd_List.Enabled = False

            tlb_main.Enabled = False

        Case Else
            Debug.Assert (False)
    End Select
    
    ' to display face immidiatelly
    UserControl.Refresh
    Exit Sub
ErrHandler:
    Call ErrorHandler("UpdateUI()")
End Sub


' ************************************************************************************
' **************************** FRAMEWORK FUNCTIONS ***********************************
' ************************************************************************************

Private Sub InitComponents()
Const CL_REQUEST_TB As String = "SELECT Info FROM Toolbars_Definitions WHERE ID=$id$"


On Error GoTo ErrHandler
    Dim lo_ctrl As Object
    Dim ll_tlbCursor As Long
    
    ' init toolbar
    ll_tlbCursor = mo_Db.OpenSQL(Replace(CL_REQUEST_TB, "$id$", 137))
    Call tlb_main.SetToolbarInfoStringParameters(mo_Db.GetFields(ll_tlbCursor, "info"), "001")
    Call mo_Db.Close(ll_tlbCursor)
    ll_tlbCursor = 0
    
    ' init tags for all controls
    frm_frames(0).Tag = "frm_filter"
    frm_frames(1).Tag = "frm_main"
    frm_frames(2).Tag = "frm_detail"
    frm_frames(3).Tag = "frm_detailSelORnot"
    frm_frames(4).Tag = "frm_detailFilter"
    frm_frames(5).Tag = "frm_find"
    
    lbl_labels(0).Tag = "lbl_category"
    lbl_labels(1).Tag = "lbl_baseMaterial"
    lbl_labels(2).Tag = "lbl_productFamily"
    lbl_labels(3).Tag = "lbl_pattern"
    lbl_labels(4).Tag = "lbl_edgeDetail"
    lbl_labels(5).Tag = "lbl_surface"
    lbl_labels(6).Tag = "lbl_shape"
    lbl_labels(7).Tag = "lbl_category"
    lbl_labels(8).Tag = "lbl_baseMaterial"
    lbl_labels(9).Tag = "lbl_productFamily"
    lbl_labels(10).Tag = "lbl_pattern"
    lbl_labels(11).Tag = "lbl_edgeDetail"
    lbl_labels(12).Tag = "lbl_surface"
    lbl_labels(13).Tag = "lbl_shape"
    lbl_labels(14).Tag = "lbl_notSelected"
    lbl_labels(15).Tag = "lbl_selected"
    lbl_labels(16).Tag = "lbl_find"
    
    tbs_Area.Tag = "tbs_Area"
    
    grd_List.Tag = "grd_list"
    grd_areaSAP.Tag = "grd_areaSAP"
    
    mnu_copyFrom.Tag = "mnu_copyFrom"
    mnu_copyTo.Tag = "mnu_copyTo"
    mnu_copyNow.Tag = "mnu_copyNow"
    
    btn_cancelFind.Tag = "btn_cancelFind"
    btn_next.Tag = "btn_next"
    
    ' Initialize the grids
    grd_List.FreeSelect = True
    grd_List.UnBound = False
    grd_List.FreeSelect = False
    grd_List.AllowSort = True
    grd_List.AllowExcelExport = True
    grd_List.ExportTitles = True
    grd_List.MultiSelect = False
    grd_List.Title = "#Product templates"
    
    If Not grd_List.SetColumns(Array( _
      "CGCODE®©0®©1®©CG_code®©#CG_code", _
      "BMLCODE®©0®©1®©BML_code®©#CG_code", _
      "PFCODE®©0®©1®©PF_code®©#PF_code", _
      "PPCODE®©0®©1®©PP_code®©#PP_code", _
      "PECODE®©0®©1®©PE_code®©#PE_code", _
      "SFCODE®©0®©1®©SF_code®©#SF_code", _
      "SHCODE®©0®©1®©SH_code®©#SH_code", _
      "CGDESC®©1600®©0®©CG_desc®©#Category", _
      "BMLDESC®©1600®©0®©BML_desc®©#Base material", _
      "PFDESC®©1600®©0®©PF_desc®©#Product family", _
      "PPDESC®©1600®©0®©PP_desc®©#Pattern", _
      "PEDESC®©1600®©0®©PE_desc®©#Edge detail/ Product", _
      "SFDESC®©1600®©0®©SF_desc®©#Surface", _
      "SHDESC®©1600®©0®©SH_desc®©#Shape", _
      "RECOM®©1050®©0®©recom®©#Recommen." _
      )) Then
        Call Err.Raise(CompFncFailed, "grd_list.SetColumns")
    End If
    
    grd_areaSAP.UnBound = False
    grd_areaSAP.FreeSelect = False
    grd_areaSAP.AllowSort = True
    grd_areaSAP.AllowExcelExport = False
    grd_areaSAP.ExportTitles = False
    grd_areaSAP.MultiSelect = False
    grd_areaSAP.Title = ""
    
    If Not grd_areaSAP.SetColumns(Array( _
      "SAPCODE®©1800®©1®©bi_sap_code®©#SAP_code", _
      "ITEMDESC®©4580®©0®©bi_desc®©#Item description" _
      )) Then
        Call Err.Raise(CompFncFailed, "grd_areaSAP.SetColumns")
    End If
    
    cbo_Category.Request = "EXEC Categories_cbo '" & ms_Language_Code & "'"
    cbo_Category.FirstBlankItem = True
    cbo_MBL.FirstBlankItem = True
    cbo_PE.FirstBlankItem = True
    cbo_PF.FirstBlankItem = True
    cbo_PP.FirstBlankItem = True
    cbo_SF.FirstBlankItem = True
    cbo_SH.FirstBlankItem = True
    
    ' init treeView
    tvw_recommNotSelected.AllowCheckboxes = False
    tvw_recommNotSelected.UseImages = True
    tvw_recommNotSelected.StartDemandLevel = 1
    tvw_recommNotSelected.Levels = 2
    ' Picture display by level
    tvw_recommNotSelected.Images = Array(1, 3)
    ' Picture displayed when the node is selected
    tvw_recommNotSelected.SelectedImages = Array(2, 3)
    tvw_recommNotSelected.NodeDataSizes = Array(3, 2)

    tvw_recommSelected.AllowCheckboxes = False
    tvw_recommSelected.UseImages = True
    tvw_recommSelected.StartDemandLevel = 1
    tvw_recommSelected.Levels = 2
    ' Picture display by level
    tvw_recommSelected.Images = Array(1, 3)
    ' Picture displayed when the node is selected
    tvw_recommSelected.SelectedImages = Array(2, 3)
    tvw_recommSelected.NodeDataSizes = Array(3, 2)

    
' set textboxes readonly
    txt_BaseMaterial.Locked = True
    txt_Category.Locked = True
    txt_edge.Locked = True
    txt_family.Locked = True
    txt_pattern.Locked = True
    txt_shape.Locked = True
    txt_surface.Locked = True
    
    Exit Sub
ErrHandler:
    If ll_tlbCursor <> 0 Then
        Call mo_Db.Close(ll_tlbCursor)
        ll_tlbCursor = 0
    End If
    Call ErrorHandler("InitComponents()")
End Sub

Private Sub InitCtrlSize()
On Error GoTo ErrHandler

    Dim lLeft As Long, lTop As Long, lWidth As Long, lHeight As Long
    
    lLeft = 0
    lTop = 0
    lWidth = UserControl.Extender.Width - lLeft - 120
    Call tlb_main.Move(lLeft, lTop, lWidth)
    
    lTop = lTop + tlb_main.Height
    lHeight = UserControl.Extender.Height - lTop
    Call frm_frames(1).Move(lLeft, lTop, lWidth, lHeight)
    Call frm_frames(2).Move(lLeft, lTop, lWidth, lHeight)
    
    lTop = frm_frames(0).Top + frm_frames(0).Height + 60
    lLeft = 60
    lWidth = frm_frames(1).Width - lLeft - 60
    lHeight = lHeight - lTop - 60
    Call grd_List.Move(lLeft, lTop, lWidth, lHeight)
    
    lLeft = 60
    Call grd_areaSAP.Move(lLeft, frm_frames(2).Height - grd_areaSAP.Height - 60)
    
    lWidth = frm_frames(2).Width - lLeft - 60
    lTop = frm_frames(3).Top
    lHeight = grd_areaSAP.Top - lTop - 60
    Call frm_frames(3).Move(lLeft, lTop, lWidth, lHeight)
    
    lWidth = (frm_frames(3).Width - pic_In.Width) / 2 - 120
    lHeight = frm_frames(3).Height - tvw_recommNotSelected.Top - 60
    Call lbl_labels(14).Move(lLeft, lbl_labels(14).Top, lWidth)
    Call tvw_recommNotSelected.Move(lLeft, tvw_recommNotSelected.Top, lWidth, lHeight)
    
    lLeft = tvw_recommNotSelected.Left + tvw_recommNotSelected.Width + 60
    Call pic_In.Move(lLeft, pic_In.Top)
    Call pic_Out.Move(lLeft, pic_Out.Top)
    
    lLeft = pic_In.Left + pic_In.Width + 60
    Call lbl_labels(15).Move(lLeft, lbl_labels(15).Top, lWidth)
    Call tvw_recommSelected.Move(lLeft, tvw_recommSelected.Top, lWidth, lHeight)
    
    
    Exit Sub
ErrHandler:
    Call ErrorHandler("InitCtrlSize()")
End Sub

' Load the labels of a containers
Public Sub LoadLabels(ByRef aControls As Variant, ByVal as_ScreenName As String, ByVal as_Language As String)

On Error GoTo ErrHandler

    Dim lIdx As Long, lCount As Long, lLabels As Long
    Dim lControl As Control
    
    lLabels = OpenSQLSafe(mo_Db, "exec Screen_Csts '" & as_ScreenName & "','" & as_Language & "'")
    Debug.Assert (lLabels <> 0)
    
    lCount = aControls.Count - 1
    
    For lIdx = 0 To lCount
        Set lControl = aControls.Item(lIdx)
            Select Case UCase(TypeName(lControl))
                Case "LABEL", "FRAME", "COMMANDBUTTON", "OPTIONBUTTON", "MENU"
                    If lControl.Tag <> "" Then
                        If mo_Db.Find(lLabels, "FIELD_NAME", lControl.Tag, , 1) >= 0 Then
                            lControl.Caption = mo_Db.GetFields(lLabels, "LOCAL_TEXT")
                        End If
                        ' once translation is done and control is not in array CLEAR tag
                        If Not TypeOf lControl Is Frame And Not TypeOf lControl Is Label Then
                            lControl.Tag = ""
                        End If
                    End If
                Case "ARMGRID"
                    If mo_Db.Find(lLabels, "FIELD_NAME", lControl.Tag, , 1) >= 0 Then
                        Dim ls_Text As String
                        Dim ll_titleIndex As Long
                        
                        ls_Text = mo_Db.GetFields(lLabels, "LOCAL_TEXT")
                        ll_titleIndex = InStr(1, ls_Text, SEP)
                        
                        If Not lControl.LoadConstants(ptStatic, Left(ls_Text, ll_titleIndex - 1) & SEP & "LEFT", ctTopGrid) Then
                            Call Err.Raise(CompFncFailed, "ArmGrid.LoadConstants", "Screen constant error.")
                        End If
                        
                        If Not lControl.LoadConstants(ptStatic, right(ls_Text, Len(ls_Text) - ll_titleIndex - 1), ctColumns) Then
                            Call Err.Raise(CompFncFailed, "ArmGrid.LoadConstants", "Screen constant error.")
                        End If
                    End If
                    ' once translation is done and control is not in array CLEAR tag
                    lControl.Tag = ""
                Case "TABSTRIP"
                    If mo_Db.Find(lLabels, "FIELD_NAME", lControl.Tag, , 1) >= 0 Then
                        Dim lsa_TextArr() As String
                        Dim ll_Index As Long
                        
                        lsa_TextArr = Split(mo_Db.GetFields(lLabels, "LOCAL_TEXT"), SEP)
                        
                        For ll_Index = LBound(lsa_TextArr, 1) To UBound(lsa_TextArr, 1)
                            lControl.Tabs(ll_Index + 1).Caption = lsa_TextArr(ll_Index)
                        Next
                    End If
                    ' once translation is done and control is not in array CLEAR tag
                    lControl.Tag = ""
                Case "MSFLEXGRID", "TOOLBARCONTROL", "TEXTBOX", "COMMANDBUTTON", "ARMCHECKVIEW", "ARMCOMBOBOX", "A_CALOCX", "OPTIONBUTTON", "ARMTREEVIEW", "LISTBOX", "PICTUREBOX", "TOOLBR", "SPINBUTTON"
                    ' Do nothing !
                Case Else
                    'debug.print "LoadLabels " & UCase(TypeName(lControl))
            End Select
        Set lControl = Nothing
    Next
    
    ' SPECIAL INITIALIZATION
    ' Title
    If mo_Db.Find(lLabels, "FIELD_NAME", "title", , 1) >= 0 Then
        ms_Title = mo_Db.GetFields(lLabels, "LOCAL_TEXT")
    End If

    mo_Db.Close (lLabels)

    Exit Sub

ErrHandler:
    Call ErrorHandler("LoadLabels")
End Sub

' as_Name is first part of Tag definition string
Private Function GetControl(ByVal ao_array As Object, ByVal as_Name As String) As Object
On Error GoTo ErrHandler
    Dim lo_ctrl As Object
    For Each lo_ctrl In ao_array
        If StrComp(lo_ctrl.Tag, as_Name, vbTextCompare) = 0 Then
            Set GetControl = lo_ctrl
            Exit For
        End If
    Next
    Exit Function
ErrHandler:
    Call ErrorHandler("GetControl()")
End Function

Private Function CutRightNumber(as_Str As String) As String
On Error GoTo ErrHandler
    Dim ll_Index As Long
    CutRightNumber = as_Str
    ll_Index = InStrRev(as_Str, " ")
    If ll_Index <> 0 Then
        If isNumeric(right(as_Str, Len(as_Str) - ll_Index)) Then
            CutRightNumber = Left(as_Str, ll_Index - 1)
        End If
    End If
    Exit Function
ErrHandler:
    Call ErrorHandler("CutRightNumber()")
End Function


Private Sub FillCombos()
On Error GoTo ErrHandler
    Call cbo_MBL.Clear
    Call cbo_PF.Clear
    Call cbo_PP.Clear
    Call cbo_PE.Clear
    Call cbo_SF.Clear
    Call cbo_SH.Clear
    
    If Not cbo_Category.SelectedItem Is Nothing Then
        Dim ls_reqExt As String
        ls_reqExt = "'" & cbo_Category.SelectedItem.Key & "', '" & ms_Language_Code & "'"
        
        cbo_MBL.Request = "EXEC Base_Material_Link_cbo " & ls_reqExt
        cbo_MBL.Enabled = Not IsEmpty(cbo_Category.SelectedItem.Key)
        cbo_PF.Request = "EXEC Products_Families_cbo " & ls_reqExt
        cbo_PF.Enabled = cbo_MBL.Enabled
        cbo_PP.Request = "EXEC Products_Patterns_cbo " & ls_reqExt
        cbo_PP.Enabled = cbo_MBL.Enabled
        cbo_PE.Request = "EXEC Products_Edges_cbo " & ls_reqExt
        cbo_PE.Enabled = cbo_MBL.Enabled
        cbo_SF.Request = "EXEC Surfaces_cbo " & ls_reqExt
        cbo_SF.Enabled = cbo_MBL.Enabled
        cbo_SH.Request = "EXEC Shapes_cbo " & ls_reqExt
        cbo_SH.Enabled = cbo_MBL.Enabled
    Else
        cbo_MBL.Enabled = False
        cbo_PF.Enabled = False
        cbo_PP.Enabled = False
        cbo_PE.Enabled = False
        cbo_SF.Enabled = False
        cbo_SH.Enabled = False
    End If
    Call FillMainGrid(grd_List, True)
    
    Exit Sub
ErrHandler:
    Call ErrorHandler("FillCombos()")
End Sub

Private Sub FillMainGrid(ByVal ao_grid As Object, ByVal ab_reloadIcon As Boolean)
On Error GoTo ErrHandler
Const REQ = "EXEC REA_main_lst '$cbo_category$', '$cbo_MBL$', '$cbo_PF$', '$cbo_PP$', '$cbo_PE$', '$cbo_SF$', '$cbo_SH$', '$tlb_main.Language$'"
    
    CopyTo = -1
    copyFrom = -1
    
    ' clear grid and change codepage if needed
    Call ClearGrid(ao_grid, GetCodePageFromLanguage(mo_Db, tlb_main.Language))
    
    If Not ao_grid.Load(ReplacePlaceholders(REQ), True, , , ab_reloadIcon) Then
        Call Err.Raise(CompFncFailed, "ao_grid.Load")
    End If
    Exit Sub
ErrHandler:
    Call ErrorHandler("FillMainGrid()")
End Sub

Private Sub FillSapGrid(ByVal ao_grid As ArmGrid, ByVal ab_reloadIcon As Boolean)
On Error GoTo ErrHandler
Const REQ = "EXEC area_manager_sap_code_t_lst '$CGCODE$', '$BMLCODE$', '$PFCODE$', '$PPCODE$', '$PECODE$', '$SFCODE$', '$SHCODE$', '$LANG$'"
    
    ao_grid.ClearGrid
    
    Dim ls_req As String
    ls_req = ReplaceGridPlaceholders(grd_List, grd_List.Row, REQ)
    ls_req = Replace(ls_req, "$LANG$", ms_Language_Code)

    If Not ao_grid.Load(ls_req, True, , , ab_reloadIcon) Then
        Call Err.Raise(CompFncFailed, "ao_grid.Load")
    End If
    Exit Sub
ErrHandler:
    Call ErrorHandler("FillSapGrid()")
End Sub

Private Sub ClearGrid(ByVal ao_grid As Object, ByVal al_CodePage As Long)
On Error GoTo ErrHandler
    ao_grid.ClearGrid
    If ao_grid.codepage <> al_CodePage And al_CodePage <> -1 Then
        ao_grid.codepage = al_CodePage
        
        Dim lo_array As Collection
        Set lo_array = New Collection
        
        ' change codepage of controls
        Call lo_array.Add(ao_grid)
        Call lo_array.Add(txt_search)
        Call ChangeCharset(lo_array, al_CodePage)
        Set lo_array = Nothing
    End If

    Exit Sub
ErrHandler:
    Call ErrorHandler("ClearGrid()")
End Sub

Private Function ReplacePlaceholders(ByVal as_Str As String) As String
On Error GoTo ErrHandler
    Dim ls_str As String
    ls_str = Replace(as_Str, "$cbo_category$", armComboBoxKey(cbo_Category))
    ls_str = Replace(ls_str, "$cbo_MBL$", armComboBoxKey(cbo_MBL))
    ls_str = Replace(ls_str, "$cbo_PF$", armComboBoxKey(cbo_PF))
    ls_str = Replace(ls_str, "$cbo_PP$", armComboBoxKey(cbo_PP))
    ls_str = Replace(ls_str, "$cbo_PE$", armComboBoxKey(cbo_PE))
    ls_str = Replace(ls_str, "$cbo_SF$", armComboBoxKey(cbo_SF))
    ls_str = Replace(ls_str, "$cbo_SH$", armComboBoxKey(cbo_SH))
    ls_str = Replace(ls_str, "$tlb_main.Language$", tlb_main.Language)
    
    ReplacePlaceholders = ls_str
    Exit Function
ErrHandler:
    Call ErrorHandler("ReplacePlaceholders()")
End Function

Private Function ReplaceGridPlaceholders(ByVal ao_grid As ArmGrid, ByVal al_Row As Long, ByVal as_string As String) As String
On Error GoTo ErrHandler
    Dim ls_retVal As String
    Dim lo_Column As ArmColumn
    Dim ll_Index As Long
    
    ls_retVal = as_string
    For ll_Index = 0 To ao_grid.Cols - 1
      Set lo_Column = ao_grid.Columns(ll_Index)
      ls_retVal = Replace(ls_retVal, "$" & lo_Column.Name & "$", SqlStr(lo_Column.GetData(al_Row)), , , vbTextCompare)
    Next
    ReplaceGridPlaceholders = ls_retVal
    Exit Function
ErrHandler:
     Call ErrorHandler("ReplaceGridPlaceholders()")
End Function

Private Sub Item_UpdateInit()
On Error GoTo ErrHandler
    
    Call Item_DetailInit
    Call UpdateUI(ArmScreenMode.smUpdate)
    
    Exit Sub
ErrHandler:
    Call ErrorHandler("Item_UpdateInit()")
End Sub

Private Sub Item_ViewInit()
On Error GoTo ErrHandler
    
    Call Item_DetailInit
    Call UpdateUI(ArmScreenMode.smView)
    
    Exit Sub
ErrHandler:
    Call ErrorHandler("Item_ViewInit()")
End Sub

Private Sub Item_DetailInit()
Const REQ = "EXEC REA_possibleAreaSelected '$CGCODE$', '$BMLCODE$', '$PFCODE$', '$PPCODE$', '$PECODE$', '$SFCODE$', '$SHCODE$', '$LANG$'"

On Error GoTo ErrHandler
    Debug.Assert (grd_List.Row <> -1)
    
    txt_Category.Text = grd_List.SelectedLine(0, "CGDESC")
    txt_BaseMaterial.Text = grd_List.SelectedLine(0, "BMLDESC")
    txt_family.Text = grd_List.SelectedLine(0, "PFDESC")
    txt_pattern.Text = grd_List.SelectedLine(0, "PPDESC")
    txt_edge.Text = grd_List.SelectedLine(0, "PEDESC")
    txt_shape.Text = grd_List.SelectedLine(0, "SHDESC")
    txt_surface.Text = grd_List.SelectedLine(0, "SFDESC")

    Call FillSapGrid(grd_areaSAP, False)
    
    Dim ls_req As String
    
    ls_req = ReplaceGridPlaceholders(grd_List, grd_List.Row, REQ)
    ls_req = Replace(ls_req, "$LANG$", ms_Language_Code)

    ' open detail cursor
    Debug.Assert (ml_detailSelectedCursor = 0)
    ml_detailSelectedCursor = OpenSQLSafe(mo_Db, ls_req)

    Call ResetDetail
    
    Exit Sub
ErrHandler:
    Call ErrorHandler("Item_DetailInit()")
End Sub

Private Sub ResetDetail()
On Error GoTo ErrHandler
    Debug.Assert (ml_detailSelectedCursor <> 0)

    ' reset treeView
    tvw_recommNotSelected.Visible = False
    tvw_recommSelected.Visible = False
    
    Call InitTV(tvw_recommNotSelected, ms_Language_Code, ml_detailTreeCursor)

    ' reset treeView
    Call tvw_recommSelected.Clear
    ' restore treeviews
    Dim ll_i  As Long
    ll_i = 1
    Do While ll_i <= tvw_recommNotSelected.Count
        If tvw_recommNotSelected.Nodes(ll_i).Parent Is Nothing Then
            ' this is root node
            Debug.Assert (tvw_recommNotSelected.Nodes(ll_i).Tag.ml_Level = 0)
            Debug.Assert (tvw_recommNotSelected.Nodes(ll_i).Tag.Length() = 2)
            If mo_Db.Find(ml_detailSelectedCursor, "PAC_code", tvw_recommNotSelected.Nodes(ll_i).Tag.IDValue) >= 0 Then
                ' this node is selected
                Call tvw_recommNotSelected.Nodes(ll_i).Tag.SetData(2, 1)
                Call CreateNodeCopy(tvw_recommNotSelected.Nodes(ll_i), tvw_recommSelected)
                
                ' remove node from notSelected
                Call tvw_recommNotSelected.RemoveNode(tvw_recommNotSelected.Nodes(ll_i))
                ll_i = ll_i - 1
            Else
                Call tvw_recommNotSelected.Nodes(ll_i).Tag.SetData(2, 0)
            End If
        End If
        ll_i = ll_i + 1
    Loop
    
    tvw_recommNotSelected.Visible = True
    tvw_recommSelected.Visible = True

    Exit Sub
ErrHandler:
    Call ErrorHandler("ResetDetail()")
End Sub

Private Sub InitTV(ByVal ao_tv As ArmTreeView, ByVal as_langCode As String, ByRef al_Cursor As Long)
Const REQall = "EXEC REA_possibleArea_tvw '$LANG$'"
On Error GoTo ErrHandler
    
    Call ao_tv.Clear
    If al_Cursor = 0 Then
        ' open cursor for all tree nodes
        al_Cursor = OpenSQLSafe(mo_Db, Replace(REQall, "$LANG$", as_langCode))
        Debug.Assert (al_Cursor <> 0)
    End If
    
    ao_tv.NodeRequests = al_Cursor
    
    If Not ao_tv.LoadTree(LoadTypeTree) Then
        Call Err.Raise(CompFncFailed, "ao_tv.LoadTree")
    End If
    
    Dim ll_Index As Long
    For ll_Index = 1 To ao_tv.Count
        If ao_tv.Nodes(ll_Index).Parent Is Nothing Then Call ao_tv.ExpandNode(ao_tv.Nodes(ll_Index))
    Next
    If ao_tv.Count <> 0 Then Call ao_tv.Nodes(1).EnsureVisible

    Exit Sub
ErrHandler:
    Call ErrorHandler("InitTV()")
End Sub

' update changes against database
Private Sub Item_Update()
On Error GoTo ErrHandler

    Call Item_UpdateDB
    
    Exit Sub
ErrHandler:
    Call ErrorHandler("Item_Update()")
End Sub

Private Sub Item_UpdateDB()
Const REQins = "EXEC REA_Products_Possible_ins '$PACCODE$', '$CGCODE$', '$BMLCODE$', '$PFCODE$', '$PPCODE$', '$PECODE$', '$SFCODE$', '$SHCODE$', '$LOGIN_NAME$', '$LANG$'"
Const REQdel = "EXEC REA_Products_Possible_del '$PACCODE$', '$CGCODE$', '$BMLCODE$', '$PFCODE$', '$PPCODE$', '$PECODE$', '$SFCODE$', '$SHCODE$'"
Const tranBegin As String = "BEGIN TRANSACTION REA_UPD"
Const tranCommit As String = "COMMIT TRANSACTION REA_UPD"
Const tranRollBack As String = "ROLLBACK TRANSACTION REA_UPD"

On Error GoTo ErrHandler
    Dim ll_i As Long
    Dim ls_req As String
    Dim lb_inTransaction As Boolean

    lb_inTransaction = False
    ' start transaction
    
    Call ExecuteSQLSafe(mo_Db, tranBegin)

    lb_inTransaction = True
    
    For ll_i = 1 To tvw_recommNotSelected.Count
        If tvw_recommNotSelected.Nodes(ll_i).Parent Is Nothing Then
            ' this is root node
            Debug.Assert (tvw_recommNotSelected.Nodes(ll_i).Tag.ml_Level = 0)
            Debug.Assert (tvw_recommNotSelected.Nodes(ll_i).Tag.Length() = 2)
            If tvw_recommNotSelected.Nodes(ll_i).Tag.GetData(2) = 1 Then
                ' this node was moved from selected
                ' link will be removed from database
                ls_req = ReplaceGridPlaceholders(grd_List, grd_List.Row, REQdel)
                ls_req = Replace(ls_req, "$PACCODE$", tvw_recommNotSelected.Nodes(ll_i).Tag.IDValue)
                Call ExecuteSQLSafe(mo_Db, ls_req)
                ' check records afffected
                If mo_Db.SQLRowsAffected = 0 Then
                    Call Err.Raise(CompFncFailed, "mo_Db.SQLRowsAffected", "Error in update Recommended area. Refresh detail and try again please.")
                End If

            End If
            
        End If
    Next
    
    For ll_i = 1 To tvw_recommSelected.Count
        If tvw_recommSelected.Nodes(ll_i).Parent Is Nothing Then
            ' this is root node
            Debug.Assert (tvw_recommSelected.Nodes(ll_i).Tag.ml_Level = 0)
            Debug.Assert (tvw_recommSelected.Nodes(ll_i).Tag.Length() = 2)
            If tvw_recommSelected.Nodes(ll_i).Tag.GetData(2) = 0 Then
                ' this node was moved from notSelected
                ' link will be inserted to database
                ls_req = ReplaceGridPlaceholders(grd_List, grd_List.Row, REQins)
                ls_req = Replace(ls_req, "$PACCODE$", tvw_recommSelected.Nodes(ll_i).Tag.IDValue)
                ls_req = Replace(ls_req, "$LOGIN_NAME$", ms_LoginName)
                ls_req = Replace(ls_req, "$LANG$", ms_Language_Code)
                
                Call ExecuteSQLSafe(mo_Db, ls_req)
                ' check records afffected
                If mo_Db.SQLRowsAffected <> 1 Then
                    Call Err.Raise(CompFncFailed, "mo_Db.SQLRowsAffected", "Error in update Recommended area. Refresh detail and try again please.")
                End If

            End If
            
        End If
    Next
    
    ' commit transaction
    Call ExecuteSQLSafe(mo_Db, tranCommit)
    lb_inTransaction = False
    Exit Sub
ErrHandler:
    If lb_inTransaction Then
        ' rollback transaction
        If Not mo_Db.ExecuteSQL(tranRollBack) Then
            Call UpdateError(True)
            MsgBox (GetDbError(mo_Db))
            Call UpdateError(False)
        End If
    End If
    Call ErrorHandler("Item_UpdateDB()")
End Sub

Private Sub CloseDetailCursor(ByRef al_Cursor As Long)
On Error GoTo ErrHandler
    Debug.Assert (al_Cursor <> 0)
    Call mo_Db.Close(al_Cursor)
    al_Cursor = 0
    Exit Sub
ErrHandler:
    If al_Cursor <> 0 Then
        Call mo_Db.Close(al_Cursor)
        al_Cursor = 0
    End If
    Call ErrorHandler("CloseDetailCursor()")
End Sub

Private Sub Item_ExitToGrid(ByVal ao_grid As ArmGrid)
On Error GoTo ErrHandler
    ' update recomm. grid column
    ao_grid.CurrentLine("RECOM") = IIf(tvw_recommSelected.Count = 0, "", "X")
    
    ' close detail cursor
    Call CloseDetailCursor(ml_detailSelectedCursor)
    ' close tree cursor
    Call CloseDetailCursor(ml_detailTreeCursor)
    
    
    ' prepare user interface for main screen
    Call UpdateUI(ArmScreenMode.smMain)
    
    Exit Sub
ErrHandler:
    Call ErrorHandler("Item_ExitToGrid()")
End Sub

' ************************************************************************************

' ************************************************************************************
' *************************** INTERNATIONAL FUNCTIONS ********************************
' ************************************************************************************

Private Function GetCodePageFromLanguage(ByRef ao_Armdb As Object, ByVal as_Language As String) As Long
On Error GoTo ErrHandler
Const C_REQ As String = "SELECT Code_Page FROM Language WHERE Language_Code = '$LANG_CODE$'"
    Dim ls_req As String
    Dim ll_Cursor As Long
    Dim ll_codePage As Long
    
    ls_req = Replace(C_REQ, "$LANG_CODE$", as_Language)

    ll_Cursor = OpenSQLSafe(ao_Armdb, ls_req)
    Debug.Assert (ll_Cursor <> 0)
    
    ll_codePage = CLng(ao_Armdb.GetFields(ll_Cursor, "Code_Page"))
    Call ao_Armdb.Close(ll_Cursor)
    GetCodePageFromLanguage = ll_codePage
    Exit Function
    
ErrHandler:
    If ll_Cursor <> 0 Then Call ao_Armdb.Close(ll_Cursor)
    Call ErrorHandler("GetCodePageFromLanguage()")
End Function


'convert code page into charset integer
Private Function GetCharSetFromCodePage(ByVal al_CodePage As Long) As Long

On Error GoTo ErrHandler

    Select Case CStr(al_CodePage)
        Case 932 ' Japanese
            GetCharSetFromCodePage = 128
        Case 936 ' Simplified Chinese
            GetCharSetFromCodePage = 134
        Case 949 ' Korean
            GetCharSetFromCodePage = 129
        Case 950 ' Traditional Chinese
            GetCharSetFromCodePage = 136
        Case 1250 ' Eastern Europe
            GetCharSetFromCodePage = 238
        Case 1251 ' Russian
            GetCharSetFromCodePage = 204
        Case 1252 ' Western European Languages
            GetCharSetFromCodePage = 0
        Case 1253 ' Greek
            GetCharSetFromCodePage = 161
        Case 1254 ' Turkish
            GetCharSetFromCodePage = 162
        Case 1255 ' Hebrew
            GetCharSetFromCodePage = 177
        Case 1256 ' Arabic
            GetCharSetFromCodePage = 178
        Case 1257 ' Baltic
            GetCharSetFromCodePage = 186
        Case Else
            GetCharSetFromCodePage = 0
    End Select
    
    Exit Function
    
ErrHandler:
    Call ErrorHandler("GetCharSetFromCodePage()")
End Function


Private Sub ChangeCharset(ByRef ao_Container As Object, Optional ByVal aCodePage As String = "")

On Error GoTo ErrHandler
   
    Dim lc_Control As Control
    Dim ls_Charset As String
    
    On Error Resume Next
    If aCodePage = "" Then
'    ls_Charset = GetCharSetFromCodePage(GetDefaultConfigCode("Capture_Cfg", "Charset"))
    ls_Charset = GetCharSetFromCodePage(aCodePage)
    Else
        ls_Charset = GetCharSetFromCodePage(aCodePage)
    End If
    
    If ls_Charset <> "" Then
        For Each lc_Control In ao_Container
            Select Case UCase(TypeName(lc_Control))
            Case "TABSTRIP", "TEXTBOX", "LABEL", "FRAME", "COMMANDBUTTON", _
                  "LISTVIEW", "CHECKBOX", "OPTIONBUTTON", _
                  "ARMCHECKVIEW", "ARMTREEVIEW", "ARMGRID", "ARMCOMBOBOX", "ARMCHECKVIEW0"
                lc_Control.Font.Name = "Arial"
                lc_Control.Font.Charset = ls_Charset
            Case "A_SEEK", "A_SRCHTXT"
                lc_Control.Charset = ls_Charset
            End Select
        Next
    End If
    
    Exit Sub

ErrHandler:
    Call ErrorHandler("LoadLabels")
    
End Sub


' ************************************************************************************

' ************************************************************************************
' **************************** DB-ACCESS FUNCTIONS ***********************************
' ************************************************************************************
#If LIVE = 1 Then
Private Sub ExecuteSQLSafe(ByVal ao_Db As Object, ByVal as_req As String)
#Else
Private Sub ExecuteSQLSafe(ByVal ao_Db As ARMSYSCOMLib.ArmDb, ByVal as_req As String)
#End If

    If Not ao_Db.ExecuteSQL(as_req) Then
        Call Err.Raise(CompFncFailed, "ExecuteSQLSafe", "SQL Error: " & GetDbError(ao_Db))
    End If

End Sub

#If LIVE = 1 Then
Private Function OpenSQLSafe(ByVal ao_Db As Object, ByVal as_req As String) As Long
#Else
Private Function OpenSQLSafe(ByVal ao_Db As ARMSYSCOMLib.ArmDb, ByVal as_req As String) As Long
#End If

    OpenSQLSafe = ao_Db.OpenSQL(as_req)
    
    If OpenSQLSafe = 0 Then Call Err.Raise(CompFncFailed, "OpenSQLSafe", "SQL Error: " & GetDbError(ao_Db))

End Function

Private Function SqlStr(ByVal as_Str As String, Optional ByVal al_maxLen As Long = 8000) As String
    SqlStr = Replace(Left(as_Str, IIf(Len(as_Str) <= al_maxLen, Len(as_Str), al_maxLen)), "'", "''")
End Function

' ************************************************************************************


' ************************************************************************************
' ********************** ERROR-HANDLING SUPPORT FUNCTIONS ****************************
' ************************************************************************************
#If LIVE = 1 Then
Private Function GetDbError(ByVal lo_Db As Object) As String
#Else
Private Function GetDbError(ByVal lo_Db As ARMSYSCOMLib.ArmDb) As String
#End If
On Error GoTo ErrHandler
    If IsArray(lo_Db.SQLErrorMessages) Then
        Debug.Assert (IsArray(lo_Db.SQLErrorCodes))
        ' Display errors msgBox
        GetDbError = Join(lo_Db.SQLErrorCodes, ",") & vbCrLf & Join(lo_Db.SQLErrorMessages, vbCrLf)
    Else
        ' ExecuteSQL failed but no error message?
        GetDbError = "Unknown error"
    End If
    Exit Function
ErrHandler:
    Call ErrorHandler("GetDbError()")
End Function

' Standard error handler
Private Sub ErrorHandler(ByVal as_Fct As String)
    Call Err.Raise(Err.Number, as_Fct & SEP1 & Err.Source, Err.Description)
End Sub

' display standard error message
Private Sub ErrorMessage(ByVal as_Fct As String)
    If Err.Number = QuietException Then Exit Sub
    Dim ll_oldMP As MousePointerConstants
    
    'save mouse pointer
    ll_oldMP = Screen.MousePointer
    Screen.MousePointer = vbDefault
    
    Dim ls_ErrSource As String
    Dim ls_ErrDescription As String
    ls_ErrSource = as_Fct & SEP1 & Err.Source
    ls_ErrDescription = Err.Description
    
    Call LogMessage(App.ProductName & " exception raised. Err.Number:" & Err.Number & ", Err.Source:" & ls_ErrSource & ", Err.Description " & ls_ErrDescription & ".", "E", False)
    Call MsgBox("Error occured, please contact IT" & vbCrLf & ls_ErrSource & vbCrLf & "Description: " & ls_ErrDescription, , "Error message: " & as_Fct)
    
    'restore mouse pointer
    Screen.MousePointer = ll_oldMP
End Sub


Private Sub LogMessage(ByVal as_logMsg As String, Optional ByVal as_logType As String = "I", Optional ab_throwException As Boolean = True)
On Error GoTo ErrHandler
Const InsertReq As String = "INSERT INTO A_Log (U_code, Z_creation_date, Source , Log_type, Log_Msg ) VALUES ($UCODE$, GETDATE(), '$APP$', '$LOGTYPE$', '$MSG$')"
    Dim ls_req As String
    Dim ll_Cursor As Long
    
    ls_req = Replace(InsertReq, "$UCODE$", CStr(ml_U_Code))
    ls_req = Replace(ls_req, "$APP$", SqlStr(C_APPNAME & " " & App.Title & " " & App.Major & "." & App.Minor & "." & App.Revision, 50))
    ls_req = Replace(ls_req, "$MSG$", SqlStr(as_logMsg, 4000))
    ls_req = Replace(ls_req, "$LOGTYPE$", SqlStr(as_logType), 1)
    
    Call ExecuteSQLSafe(mo_Db, ls_req)
    
    Exit Sub
ErrHandler:
    If ab_throwException Then Call ErrorHandler("LogMessage()")
End Sub

' procedure save/restore err object
Private Sub UpdateError(Optional ab_saveError As Boolean = False)
Static ls_ErrDesc As String
Static ls_ErrSource As String
Static ll_errNum As Long
    
    If ab_saveError Then
        ls_ErrDesc = Err.Description
        ls_ErrSource = Err.Source
        ll_errNum = Err.Number
    Else
        Err.Description = ls_ErrDesc
        Err.Source = ls_ErrSource
        Err.Number = ll_errNum
    End If
End Sub
' ************************************************************************************

' ************************************************************************************
' ***************************** SECURITY FUNCTIONS ***********************************
' ************************************************************************************

Private Sub GetUserRight(ByRef ao_rights As UserRights_t)
Const C_REQ As String = "EXEC Check_Security 'products_possible', '$LOGINNAME$'"
On Error GoTo ErrorHandler
    Dim ll_Cursor As Long
    
' default user rights
    ao_rights.allowUpdate = False

' check admin
    ll_Cursor = OpenSQLSafe(mo_Db, Replace(C_REQ, "$LOGINNAME$", SqlStr(ms_LoginName)))
    Debug.Assert (ll_Cursor <> 0)
    
    Call mo_Db.First(ll_Cursor)
    While Not mo_Db.EOF(ll_Cursor)
        Select Case mo_Db.GetFields(ll_Cursor, "Action")
        Case "Update"
            ao_rights.allowUpdate = True
        Case Else
            Debug.Assert (False)
        End Select
        Call mo_Db.Next(ll_Cursor)
    Wend
    
    Call mo_Db.Close(ll_Cursor)
    ll_Cursor = 0
    
    Exit Sub
ErrorHandler:
    If ll_Cursor <> 0 Then Call mo_Db.Close(ll_Cursor)
    Call ErrorHandler("GetUserRight()")
End Sub

' ************************************************************************************


' ************************************************************************************
' ******************************** EVENTS HANDLERS ***********************************
' ************************************************************************************

Private Sub btn_cancelFind_Click()
On Error GoTo ErrHandler
    Dim lo_ctrl As Object
    Screen.MousePointer = vbHourglass
    Call UpdateUI(ArmScreenMode.smMain)
    ' make selected whole line
    grd_List.Row = grd_List.Row
    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
    Screen.MousePointer = vbDefault
    Call ErrorMessage("btn_cancelFind_Click()")
End Sub

Private Sub btn_next_Click()
On Error GoTo ErrHandler
    Screen.MousePointer = vbHourglass
    
    If txt_search.Text <> "" Then
        If grd_List.SearchText(btn_next.Tag = "", txt_search.Text) <> -1 Then
            btn_next.Tag = "X"
        Else
            btn_next.Tag = ""
            Call MsgBox("Cannot find matching data", vbOKOnly)
        End If
    End If
    Screen.MousePointer = vbDefault
    Exit Sub

ErrHandler:
    Screen.MousePointer = vbDefault
    Call ErrorMessage("cmd_next_Click")
End Sub

Private Sub cbo_category_ComboItemSelected()
On Error GoTo ErrHandler
    Screen.MousePointer = vbHourglass
    Call FillCombos
    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
    Screen.MousePointer = vbDefault
    Call ErrorMessage("cbo_category_ComboItemSelected()")
End Sub

Private Sub cbo_MBL_ComboItemSelected()
On Error GoTo ErrHandler
    Screen.MousePointer = vbHourglass
    Call FillMainGrid(grd_List, True)
    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
    Screen.MousePointer = vbDefault
    Call ErrorMessage("cbo_MBL_ComboItemSelected()")
End Sub

Private Sub cbo_PE_ComboItemSelected()
On Error GoTo ErrHandler
    Screen.MousePointer = vbHourglass
    Call FillMainGrid(grd_List, True)
    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
    Screen.MousePointer = vbDefault
    Call ErrorMessage("cbo_PE_ComboItemSelected()")
End Sub

Private Sub cbo_PF_ComboItemSelected()
On Error GoTo ErrHandler
    Screen.MousePointer = vbHourglass
    Call FillMainGrid(grd_List, True)
    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
    Screen.MousePointer = vbDefault
    Call ErrorMessage("cbo_PF_ComboItemSelected()")
End Sub

Private Sub cbo_PP_ComboItemSelected()
On Error GoTo ErrHandler
    Screen.MousePointer = vbHourglass
    Call FillMainGrid(grd_List, True)
    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
    Screen.MousePointer = vbDefault
    Call ErrorMessage("cbo_PP_ComboItemSelected()")
End Sub

Private Sub cbo_SF_ComboItemSelected()
On Error GoTo ErrHandler
    Screen.MousePointer = vbHourglass
    Call FillMainGrid(grd_List, True)
    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
    Screen.MousePointer = vbDefault
    Call ErrorMessage("cbo_SF_ComboItemSelected()")
End Sub

Private Sub cbo_SH_ComboItemSelected()
On Error GoTo ErrHandler
    Screen.MousePointer = vbHourglass
    Call FillMainGrid(grd_List, True)
    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
    Screen.MousePointer = vbDefault
    Call ErrorMessage("cbo_SH_ComboItemSelected()")
End Sub

Private Sub grd_list_DblClick()
On Error GoTo ErrHandler
    Screen.MousePointer = vbHourglass
    Call Item_ViewInit
    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
    Screen.MousePointer = vbDefault
    Call ErrorMessage("grd_list_DblClick()")
End Sub

Private Sub mnu_copyFrom_Click()
On Error GoTo ErrHandler
    If grd_List.Row = -1 Then Exit Sub

    Screen.MousePointer = vbHourglass
    If grd_List.CurrentLine("RECOM") = "X" Then
        copyFrom = grd_List.Row
    Else
        copyFrom = -1
        MsgBox "This line does not have data associated"
    End If

    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
    Screen.MousePointer = vbDefault
    Call ErrorMessage("mnu_copyFrom_Click()")
End Sub

Private Sub mnu_copyNow_Click()
Const REQcpy = "EXEC REA_Products_Possible_cpy '$LOGIN_NAME$',"
Const REQupend = "'$CGCODE$','$BMLCODE$','$PFCODE$','$PPCODE$','$PECODE$','$SFCODE$','$SHCODE$'"
On Error GoTo ErrHandler
    If CopyTo = -1 Then Exit Sub
    If copyFrom = -1 Then Exit Sub
    
    Screen.MousePointer = vbHourglass
    ' copy all records from Products_Possible
    
    Dim ls_req As String
    ls_req = Replace(REQcpy, "$LOGIN_NAME$", ms_LoginName) & ReplaceGridPlaceholders(grd_List, copyFrom, REQupend)
    ls_req = ls_req & "," & ReplaceGridPlaceholders(grd_List, CopyTo, REQupend)

    Call ExecuteSQLSafe(mo_Db, ls_req)

    If mo_Db.SQLRowsAffected = 0 Then
        ' No data copied?
        Call Err.Raise(CompFncFailed, "mo_Db.SQLRowsAffected", "No data were copied.")
    End If
    
    ' update grid
    grd_List.Data(CLng(mnu_copyTo.Tag), "RECOM") = "X"
    CopyTo = -1

    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
    Screen.MousePointer = vbDefault
    Call ErrorMessage("mnu_copyNow_Click()")
End Sub

Private Sub mnu_copyTo_Click()
On Error GoTo ErrHandler
    If grd_List.Row = -1 Then Exit Sub

    Screen.MousePointer = vbHourglass
    If grd_List.CurrentLine("RECOM") = "" Then
        CopyTo = grd_List.Row
    Else
        CopyTo = -1
        MsgBox "This line already have data associated"
    End If

    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
    Screen.MousePointer = vbDefault
    Call ErrorMessage("mnu_copyTo_Click()")
End Sub

Private Sub pic_In_Click()
On Error GoTo ErrHandler
    If tvw_recommNotSelected.SelectedItem Is Nothing Then Exit Sub
    If tvw_recommNotSelected.SelectedItem.Tag.ml_Level <> 0 Then Exit Sub
    
    Screen.MousePointer = vbHourglass
    
    ' insert into selected
    Call CreateNodeCopy(tvw_recommNotSelected.SelectedItem, tvw_recommSelected)
    
    ' remove node from notSelected
    Call tvw_recommNotSelected.RemoveNode(tvw_recommNotSelected.SelectedItem)
    
    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
    Screen.MousePointer = vbDefault
    Call ErrorMessage("pic_In_Click()")
End Sub

Private Sub pic_Out_Click()
On Error GoTo ErrHandler
    If tvw_recommSelected.SelectedItem Is Nothing Then Exit Sub
    If tvw_recommSelected.SelectedItem.Tag.ml_Level <> 0 Then Exit Sub
    
    Screen.MousePointer = vbHourglass

    ' insert into notSelected
    Call CreateNodeCopy(tvw_recommSelected.SelectedItem, tvw_recommNotSelected)
    
    ' remove node from selected
    Call tvw_recommSelected.RemoveNode(tvw_recommSelected.SelectedItem)
    
    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
    Screen.MousePointer = vbDefault
    Call ErrorMessage("pic_Out_Click()")
End Sub

Private Sub CreateNodeCopy(ByVal ao_Node As Node, ByVal lo_destTreeView As ArmTreeView, Optional ByVal ao_ParentNode As Node = Nothing)
On Error GoTo ErrHandler
    Dim lo_SelNodeInfo As NodeInfo
    Set lo_SelNodeInfo = ao_Node.Tag
    
    ' add a copy of ao_node into lo_destTreeView
    Set ao_ParentNode = lo_destTreeView.AddNode(ao_ParentNode, lo_SelNodeInfo.mo_Node.Key, lo_SelNodeInfo.TextValue, lo_SelNodeInfo.ImageIndex, lo_SelNodeInfo.SelectedImageIndex, lo_destTreeView.LoadType, lo_SelNodeInfo.SortIndex)
    Debug.Assert (Not ao_ParentNode Is Nothing)
    Call ao_ParentNode.Tag.CopyDataDef(lo_SelNodeInfo)
    
    Call ao_ParentNode.Tag.SetNodeDataSize(lo_SelNodeInfo.Length())
    
    ' copy data
    Dim ll_i As Long
    For ll_i = 0 To ao_ParentNode.Tag.Length()
        Call ao_ParentNode.Tag.SetData(ll_i, lo_SelNodeInfo.GetData(ll_i))
    Next
    
    Call lo_destTreeView.ExpandNode(ao_ParentNode)
    
    ' add copy of child nodes
    Set ao_Node = ao_Node.Child
    
    Do While Not (ao_Node Is Nothing)
        Call CreateNodeCopy(ao_Node, lo_destTreeView, ao_ParentNode)
        Set ao_Node = ao_Node.Next
    Loop
    
    Exit Sub
ErrHandler:
    Call ErrorHandler("CreateNodeCopy()")
End Sub

Private Sub tlb_main_action(ByVal as_Role As String, as_Language As String)
On Error GoTo ErrHandler
    Screen.MousePointer = vbHourglass
    Select Case as_Role
    Case "B"              ' EDIT AUTHORISED PERSON PROPERTIES
        If grd_List.Row <> -1 Then
            Call Item_UpdateInit
        End If
    Case "F"              ' REFRESH GRID
        Call grd_List.Refresh
    Case "M"              ' SEARCH GRID
        ' reset to start search from beginning of grid
        btn_next.Tag = ""
        Call UpdateUI(ArmScreenMode.smSearch)
        Call txt_search.SetFocus
        txt_search.SelStart = 0
        txt_search.SelLength = Len(txt_search.Text)
        
    Case "D"              ' PRINT
        RaiseEvent PrintGrid(grd_List)
    Case "L"              ' LANGUAGE CHANGED
        Call FillMainGrid(grd_List, True)
    Case "X"              ' POPUP MENU TO COPY/PASTE
        Screen.MousePointer = vbDefault
        Call tlb_main.ShowPopup(mnu_copyPopup, as_Role)
        Screen.MousePointer = vbHourglass
    Case "H"              ' ACCEPT CHANGES
        Call Item_Update
        Call Item_ExitToGrid(grd_List)
    Case "I"              ' CLEAR CHANGES
        Call ResetDetail
    Case "T"              ' CLOSE SCREEN/CANCEL
        ' close detail cursor
        Call CloseDetailCursor(ml_detailSelectedCursor)
        ' close tree cursor
        Call CloseDetailCursor(ml_detailTreeCursor)
        Call UpdateUI(ArmScreenMode.smMain)
    Case "Q"              ' QUIT
        RaiseEvent quit
    Case "S"              ' HELP
        RaiseEvent ShowHelp
    End Select

    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
    Screen.MousePointer = vbDefault
    Call ErrorMessage("tlb_main_action()")
End Sub

Public Sub Move(ByVal aLeft As Single, ByVal aTop As Single, ByVal aWidth As Single, ByVal aHeight As Single)
    Call UserControl.Extender.Move(aLeft, aTop, aWidth, aHeight)
End Sub

Public Property Let Visible(ByVal aVisible As Boolean)
    UserControl.Extender.Visible = aVisible
End Property


