Imports System.Collections.ObjectModel
Imports System.IO
Imports EgtBEAMWALL.Core
Imports EgtUILib
Imports EgtWPFLib5

Public Class LeftPanelVM
   Inherits VMBase

#Region "FIELDS & PROPERTIES"

   Private Property m_GridDims As New ObservableCollection(Of GridDimension)
   Public Property GridDims As ObservableCollection(Of GridDimension)
      Get
         Return m_GridDims
      End Get
      Set
         m_GridDims = Value
         NotifyPropertyChanged(NameOf(GridDims))
      End Set
   End Property

   Public ReadOnly Property ViewPage_Visibility As Visibility
      Get
         Return If(Map.refMainMenuVM.SelPage = Pages.VIEW, Visibility.Visible, Visibility.Collapsed)
      End Get
   End Property
   Public ReadOnly Property MachiningPage_Visibility As Visibility
      Get
         Return If(Map.refMainMenuVM.SelPage = Pages.MACHINING, Visibility.Visible, Visibility.Collapsed)
      End Get
   End Property

   Private m_LeftPanel_IsEnabled As Boolean = True
   Public ReadOnly Property LeftPanel_IsEnabled As Boolean
      Get
         Return m_LeftPanel_IsEnabled
      End Get
   End Property

   Public ReadOnly Property CopyPart_IsEnabled As Boolean
      Get
         Return m_LeftPanel_IsEnabled AndAlso Not Map.refShowBeamPanelVM.bShowAll AndAlso Not IsNothing(Map.refProjectVM.BTLStructureVM) AndAlso Not Map.refProjectVM.BTLStructureVM.SelBTLPartsCnt > 1
      End Get
   End Property

   Public ReadOnly Property RemovePart_IsEnabled As Boolean
      Get
         Return m_LeftPanel_IsEnabled
      End Get
   End Property

   Public ReadOnly Property RotatePart_IsEnabled As Boolean
      Get
         Return m_LeftPanel_IsEnabled AndAlso Not IsNothing(Map.refProjectVM) AndAlso Not IsNothing(Map.refProjectVM.BTLStructureVM) AndAlso Map.refProjectVM.BTLStructureVM.SelBTLParts.Count > 1
      End Get
   End Property

   Private ReadOnly Property PartIsSelected As Boolean
      Get
         Return Not IsNothing(Map.refProjectVM) AndAlso Not IsNothing(Map.refProjectVM.BTLStructureVM) AndAlso Not IsNothing(Map.refProjectVM.BTLStructureVM.SelBTLPart)
      End Get
   End Property

   Private ReadOnly Property FeatureIsSelected As Boolean
      Get
         Return PartIsSelected AndAlso Not IsNothing(Map.refProjectVM.BTLStructureVM.SelBTLPart.SelBTLFeatureVM)
      End Get
   End Property

   Public ReadOnly Property CopyFeature_IsEnabled As Boolean
      Get
         Return m_LeftPanel_IsEnabled AndAlso PartIsSelected AndAlso FeatureIsSelected
      End Get
   End Property

   Public ReadOnly Property MacroFeature_IsEnabled As Boolean
      Get
         Return m_LeftPanel_IsEnabled AndAlso PartIsSelected AndAlso FeatureIsSelected
      End Get
   End Property

   Public ReadOnly Property AddFeature_IsEnabled As Boolean
      Get
         Return m_LeftPanel_IsEnabled AndAlso PartIsSelected AndAlso Not IsNothing(Map.refProjectVM.BTLStructureVM) AndAlso Not Map.refProjectVM.BTLStructureVM.SelBTLPartsCnt > 1
      End Get
   End Property

   Public ReadOnly Property RemoveFeature_IsEnabled As Boolean
      Get
         Return m_LeftPanel_IsEnabled AndAlso PartIsSelected AndAlso FeatureIsSelected
      End Get
   End Property

   Public ReadOnly Property SearchFilter_IsEnabled As Boolean
      Get
         Return Not Map.refFreeContourManagerVM.bIsActive
      End Get
   End Property

   ' Definizione comandi
   Private m_cmdNewRawPart As ICommand
   Private m_cmdNewRawPartLast As ICommand
   Private m_cmdAddToRawPart As ICommand
   Private m_cmdCopyPart As ICommand
   Private m_cmdAddPart As ICommand
   Private m_cmdRemovePart As ICommand
   Private m_cmdInvert As ICommand
   Private m_cmdBackRotation As ICommand
   Private m_cmdForwardRotation As ICommand
   Private m_cmdCopyFeature As ICommand
   Private m_cmdMacroFeature As ICommand
   Private m_cmdAddFeature As ICommand
   Private m_cmdRemoveFeature As ICommand

#Region "Messages"

   Public ReadOnly Property SearchFilter_Msg As String
      Get
         Return "Search & Filter"
      End Get
   End Property

   Public ReadOnly Property Section_Msg As String
      Get
         Return EgtMsg(61771)
      End Get
   End Property

   Public ReadOnly Property Group_Msg As String
      Get
         Return EgtMsg(61624)
      End Get
   End Property
   Public ReadOnly Property SubGroup_Msg As String
      Get
         Return EgtMsg(61623)
      End Get
   End Property

   Public ReadOnly Property ParType_Msg As String
      Get
         Return EgtMsg(61950)
      End Get
   End Property

   Public ReadOnly Property ParValue_Msg As String
      Get
         Return EgtMsg(61951)
      End Get
   End Property

   Public ReadOnly Property NewRawPart_ToolTip As String
      Get
         Return EgtMsg(61903)
      End Get
   End Property

   Public ReadOnly Property NewRawPartLast_ToolTip As String
      Get
         Return EgtMsg(61977)
      End Get
   End Property

   Public ReadOnly Property AddToRawPart_ToolTip As String
      Get
         Return EgtMsg(61904)
      End Get
   End Property

   Public ReadOnly Property CopyPart_ToolTip As String
      Get
         Return EgtMsg(61905)
      End Get
   End Property

   Public ReadOnly Property AddPart_ToolTip As String
      Get
         Return EgtMsg(61906)
      End Get
   End Property

   Public ReadOnly Property RemovePart_ToolTip As String
      Get
         Return EgtMsg(61907)
      End Get
   End Property

   Public ReadOnly Property CopyFeature_ToolTip As String
      Get
         Return EgtMsg(61908)
      End Get
   End Property

   Public ReadOnly Property MacroFeature_ToolTip As String
      Get
         Return EgtMsg(61909)
      End Get
   End Property

   Public ReadOnly Property AddFeature_ToolTip As String
      Get
         Return EgtMsg(61910)
      End Get
   End Property

   Public ReadOnly Property RemoveFeature_ToolTip As String
      Get
         Return EgtMsg(61911)
      End Get
   End Property

#End Region    ' Messages

#End Region    'FIELDS & PROPERTIES

   Sub New()
      ' imposto riferimento su mappa
      Map.SetRefLeftPanelVM(Me)
      ' imposto dimensioni colonne/righe della Grid
      DimensionsIniFile.ReadGridDimensions(ConstDims.LEFTPANEL_VIEW, GridDims)
   End Sub

#Region "METHODS"

   Friend Sub UpdateView()
      NotifyPropertyChanged(NameOf(ViewPage_Visibility))
      NotifyPropertyChanged(NameOf(MachiningPage_Visibility))
   End Sub

   Friend Sub SetLeftPanelIsEnabled(bIsEnabled As Boolean)
      m_LeftPanel_IsEnabled = bIsEnabled
      NotifyPropertyChanged(NameOf(LeftPanel_IsEnabled))
      NotifyPropertyChanged(NameOf(CopyPart_IsEnabled))
      NotifyPropertyChanged(NameOf(RemovePart_IsEnabled))
      NotifyPropertyChanged(NameOf(CopyFeature_IsEnabled))
      NotifyPropertyChanged(NameOf(AddFeature_IsEnabled))
      NotifyPropertyChanged(NameOf(RemoveFeature_IsEnabled))
      NotifyPropertyChanged(NameOf(MacroFeature_IsEnabled))
      NotifyPropertyChanged(NameOf(SearchFilter_IsEnabled))
   End Sub

   Friend Sub PartShowAllChanged()
      NotifyPropertyChanged(NameOf(CopyPart_IsEnabled))
      NotifyPropertyChanged(NameOf(RemovePart_IsEnabled))
      NotifyPropertyChanged(NameOf(RotatePart_IsEnabled))
      NotifyPropertyChanged(NameOf(AddFeature_IsEnabled))
   End Sub

   Friend Sub FeatureSelectionChanged()
      NotifyPropertyChanged(NameOf(CopyFeature_IsEnabled))
      NotifyPropertyChanged(NameOf(MacroFeature_IsEnabled))
      NotifyPropertyChanged(NameOf(RemoveFeature_IsEnabled))
   End Sub

#End Region    ' METHODS

#Region "COMMANDS"

#Region "NewRawPart"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property NewRawPart_Command As ICommand
      Get
         If m_cmdNewRawPart Is Nothing Then
            m_cmdNewRawPart = New Command(AddressOf NewRawPartCmd)
         End If
         Return m_cmdNewRawPart
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub NewRawPartCmd()
      NewRawPart(False)
   End Sub

   Public Sub NewRawPart(bLast As Boolean)
      If IsNothing(Map.refProdManagerVM.CurrProd) Then Return
      'Dim SelPart As BTLPartVM = Map.refProjectVM.BTLStructureVM.SelBTLPart
      Dim SelParts As List(Of BTLPartVM) = Map.refProjectVM.BTLStructureVM.SelBTLParts.ToList()
      If IsNothing(SelParts) OrElse SelParts.Count <= 0 Then Return
      ' verifico che abbiano tutti la stessa sezione
      Dim dHSection As Double = SelParts(0).dH
      Dim dWSection As Double = SelParts(0).dW
      For PartIndex = 0 To SelParts.Count - 1
         Dim Part As BTLPartVM = SelParts(PartIndex)
         If Not IsNothing(Part) Then
            If Map.refProjectVM.BTLStructureVM.nPROJTYPE = BWType.BEAM Then
               If Part.dH <> dHSection OrElse Part.dW <> dWSection Then
                  MessageBox.Show(EgtMsg(61970), EgtMsg(30007))
                  Return
               End If
            ElseIf Map.refProjectVM.BTLStructureVM.nPROJTYPE = BWType.WALL Then
               If Part.dH <> dHSection Then
                  MessageBox.Show(EgtMsg(61970), EgtMsg(30007))
                  Return
               End If
            End If
         Else
            SelParts.Remove(Part)
         End If
      Next
      ' se pareti e piu' di uno selezionato, esco
      If Map.refProjectVM.BTLStructureVM.nPROJTYPE = BWType.WALL And SelParts.Count > 1 Then
         MessageBox.Show(EgtMsg(61971), EgtMsg(30007))
         Return
      End If
      ' se nessun grezzo, rendo tutti i pezzi visibili
      If Map.refProjectVM.MachGroupPanelVM.MachGroupVMList.Count = 0 Then
         Map.refProjectVM.BTLStructureVM.ShowAll(False)
      End If
      ' verifico se sono gia' stati messi tutti i pezzi richiesti
      If Not VerifyPartCount(SelParts) Then Return
      Dim dRawL As Double = SelParts(0).dL
      Dim dRawW As Double = SelParts(0).dW
      Dim dStartOffset As Double = 0
      Dim dKerf As Double = 0
      Dim dOffset As Double = WarehouseHelper.GetOffset(Map.refProjectVM.BTLStructureVM.nPROJTYPE)
      ' se tipo di definizione grezzo esplicito
      If WarehouseHelper.GetRawPartDef = 1 OrElse ((Keyboard.Modifiers And ModifierKeys.Shift) = ModifierKeys.Shift AndAlso WarehouseHelper.GetWarehouseType = WarehouseType.BASIC) Then
         ' chiedo lunghezza grezzo
         Dim sWarehouseIniPath As String = Map.refMainWindowVM.MainWindowM.sWarehouseDir & "\" & WH_BASIC_INI_FILE_NAME
         If Map.refProjectVM.BTLStructureVM.nPROJTYPE = MachineType.BEAM Then
            dStartOffset = WarehouseHelper.GetStartOffset()
            dRawL += dStartOffset
         Else
            dKerf = WarehouseHelper.GetKerf()
            dRawL += 2 * dKerf
            dRawW += 2 * dKerf
         End If
         Dim AddRawPartWndVM As New AddRawPartWndVM(Map.refProjectVM.BTLStructureVM.nPROJTYPE, dRawL, dRawW, dStartOffset)
         Dim AddRawPartWnd As New AddRawPartWndV(Application.Current.MainWindow, AddRawPartWndVM)
         If Not AddRawPartWnd.ShowDialog() Then Return
         dRawL = AddRawPartWndVM.VariableList(0).dValue
         dRawW = AddRawPartWndVM.VariableList(1).dValue
         dStartOffset = AddRawPartWndVM.VariableList(1).dValue
         ' se altrimenti definizione grezzo da warehouse
      Else
         If Map.refProjectVM.BTLStructureVM.nPROJTYPE = BWType.BEAM Then
            dStartOffset = WarehouseHelper.GetStartOffset()
         Else
            dKerf = WarehouseHelper.GetKerf()
         End If
         ' se warehouse basic
         Select Case WarehouseHelper.GetWarehouseType()
            Case WarehouseType.BASIC
               WarehouseHelper.GetCurrentDimensions(Map.refProjectVM.BTLStructureVM.nPROJTYPE, dRawW, dRawL)
            Case WarehouseType.MEDIUM
               Dim SectionList As List(Of SParam) = WarehouseHelper.GetSectionList()
               Dim SParamlist As List(Of SParam) = SectionList.FindAll(Function(x) x.SectXMat = SelParts(0).Section)
               If bLast Then
                  Dim LastMaterial As SParam = WarehouseHelper.GetLastMaterial(SelParts(0).Section)
                  If Not IsNothing(LastMaterial) Then
                     dRawL = LastMaterial.dL
                     dRawW = LastMaterial.dW
                  ElseIf SParamlist.Count > 0 Then
                     dRawL = SParamlist(0).dL
                     dRawW = SParamlist(0).dW
                  Else
                     MessageBox.Show(EgtMsg(61975), EgtMsg(30007))
                     Return
                  End If
               Else
                  If SParamlist.Count = 0 Then
                     ' se pareti aumento dimensioni del kerf
                     If Map.refProjectVM.BTLStructureVM.nPROJTYPE = BWType.WALL Then
                        dRawW += (2 * dKerf)
                        dRawL += (2 * dKerf)
                     End If
                     ' apro finestra con solo edit
                     If AddRawPartWnd(AddRawPartWndVM.EditTypes.ONLY_TEXT, SParamlist, dRawW, dRawL, dStartOffset, dOffset, dKerf) Then
                        WarehouseHelper.SetOffset(Map.refProjectVM.BTLStructureVM.nPROJTYPE, dOffset)
                        If Map.refProjectVM.BTLStructureVM.nPROJTYPE = BWType.BEAM Then
                           WarehouseHelper.SetStartOffset(dStartOffset)
                        Else
                           WarehouseHelper.SetKerf(dKerf)
                        End If
                     Else
                        Return
                     End If
                  ElseIf SParamlist.Count > 0 Then
                     ' imposto finestra con anche edit
                     If AddRawPartWnd(AddRawPartWndVM.EditTypes.TEXT_AND_COMBO, SParamlist, dRawW, dRawL, dStartOffset, dOffset, dKerf) Then
                        WarehouseHelper.SetOffset(Map.refProjectVM.BTLStructureVM.nPROJTYPE, dOffset)
                        If Map.refProjectVM.BTLStructureVM.nPROJTYPE = BWType.BEAM Then
                           WarehouseHelper.SetStartOffset(dStartOffset)
                        Else
                           WarehouseHelper.SetKerf(dKerf)
                        End If
                     Else
                        Return
                     End If
                  End If
               End If
         End Select
      End If
      If Map.refProjectVM.BTLStructureVM.nPROJTYPE = MachineType.BEAM Then
         ' verifico se lunghezza barra e' maggiore della lunghezza dei pezzi
         Dim dTotLen As Double = WarehouseHelper.GetStartOffset()
         For PartIndex = 0 To SelParts.Count - 1
            If PartIndex <> 0 Then
               dTotLen += WarehouseHelper.GetOffset(BWType.BEAM)
            End If
            dTotLen += SelParts(PartIndex).dL
         Next
         If dTotLen > dRawL Then
            MessageBox.Show(EgtMsg(61972), EgtMsg(30007))
            Return
         End If
      End If
      ' creo nuovo gruppo di lavorazione
      Map.refMachGroupPanelVM.AddMachGroup()
      Dim nCurrMachGroup As Integer = EgtGetCurrMachGroup()
      Dim sCurrMachGroupName As String = ""
      EgtGetMachGroupName(nCurrMachGroup, sCurrMachGroupName)
      Dim sLogPath As String = Map.refMainWindowVM.MainWindowM.sTempDir & "\RawPartLog.txt"
      ' scrivo dati per variabili P di comunicazione con la macchina in gruppo di lavorazione
      EgtSetInfo(nCurrMachGroup, MGR_RPT_PRODID, Map.refProdManagerVM.CurrProd.nProdId)
      EgtSetInfo(nCurrMachGroup, MGR_RPT_PATTID, nCurrMachGroup)
      If Map.refProjectVM.BTLStructureVM.nPROJTYPE = MachineType.BEAM Then
         ' ordino i pezzi per lunghezza
         SelParts = SelParts.OrderBy(Function(x) x.dL).ToList
         ' creo copie dei pezzi
         Dim nPartDuploIdList As New List(Of Integer)
         For Each Part In SelParts
            Dim nDuploId As Integer = EgtDuploNew(Part.nPartId)
            ' elimino valori calcolo dell'originale
            MyMachGroupPanelVM.DuploRemoveProjCalc(nDuploId)
            ' lo rendo std
            EgtSetMode(nDuploId, GDB_MD.STD)
            nPartDuploIdList.Add(nDuploId)
         Next
         ' scrivo dati costruzione grezzo in gruppo di lavorazione
         EgtSetInfo(nCurrMachGroup, MGR_RPT_BARLEN, dRawL)
         EgtSetInfo(nCurrMachGroup, MGR_RPT_MATERIAL, SelParts(0).sMATERIAL)
         ' scrivo dati di tutti i pezzi
         Dim dPosX As Double = WarehouseHelper.GetStartOffset()
         ' ciclo sui pezzi
         For nIndex = 0 To nPartDuploIdList.Count - 1
            ' se non è primo, aggiungo offset tra barre standard
            If nIndex <> 0 Then
               dPosX += WarehouseHelper.GetOffset(BWType.BEAM)
            End If
            EgtSetInfo(nCurrMachGroup, MGR_RPT_PART & nIndex + 1, nPartDuploIdList(nIndex) & "," & DoubleToString(dPosX, 3))
            ' incremento posizione della sua lunghezza
            dPosX += SelParts(nIndex).dL
         Next
         Dim BeamMachGroup As MyMachGroupVM = Map.refMachGroupPanelVM.GetLastMachGroup()
         ' eseguo script creazione grezzo
         Dim nERR As Integer = 0
         If Not ExecBeam(sLogPath, Map.refMachinePanelVM.SelectedMachine.Name, CalcIntegration.CmdTypes.RAWPART, False) Then
            ' elimino duplo e gruppo di lavorazione
            For Each nDuploId In nPartDuploIdList
               EgtErase(nDuploId)
            Next
            BeamMachGroup.DeleteMachGroup()
            If File.Exists(sLogPath) Then
               Dim LogFile As String() = File.ReadAllLines(sLogPath)
               If LogFile.Count >= 2 AndAlso Not IsNothing(LogFile(1)) Then
                  MessageBox.Show(LogFile(1), EgtMsg(30007), MessageBoxButton.OK, MessageBoxImage.Error)
               End If
            Else
               MessageBox.Show(EgtMsg(61973), EgtMsg(30007), MessageBoxButton.OK, MessageBoxImage.Error)
            End If
            ' se nessun grezzo, rimetto tutti i pezzi invisibili
            If Map.refProjectVM.MachGroupPanelVM.MachGroupVMList.Count = 0 Then
               Map.refProjectVM.BTLStructureVM.HideAll()
            End If
            Return
         End If
         For nDuploIndex = 0 To SelParts.Count - 1
            EgtSetInfo(nPartDuploIdList(nDuploIndex), MGR_PRT_ROT, SelParts(nDuploIndex).nROTATED)
            EgtSetInfo(nPartDuploIdList(nDuploIndex), MGR_PRT_FLIP, SelParts(nDuploIndex).nINVERTED)
         Next
         ' aggiorno contatore pezzi usati in Prod
         For Each SelPart In SelParts
            SelPart.RefreshPartInProd()
         Next
         'aggiorno lista pezzi
         BeamMachGroup.MyMachGroupM.RefreshPartList()
         BeamMachGroup.MyMachGroupM.RefreshGroupData()
         ' aggiorno dati utilizzo barra
         BeamMachGroup.UpdateUsage()
         Core.ViewPanelVM.BWSetView(VT.ISO_SW, False)
      ElseIf Map.refProjectVM.BTLStructureVM.nPROJTYPE = MachineType.WALL Then
         Dim nPartDuploId As Integer = EgtDuploNew(SelParts(0).nPartId)
         ' scrivo dati in gruppo di lavorazione
         Dim dPosX As Double = dKerf
         Dim dPosY As Double = dKerf
         EgtSetInfo(nCurrMachGroup, MGR_RPT_PANELLEN, dRawL)
         EgtSetInfo(nCurrMachGroup, MGR_RPT_PANELWIDTH, dRawW)
         EgtSetInfo(nCurrMachGroup, MGR_RPT_MATERIAL, SelParts(0).sMATERIAL)
         EgtSetInfo(nCurrMachGroup, MGR_RPT_PART & 1,
                    nPartDuploId & "," & DoubleToString(dPosX, 3) & "," & DoubleToString(dPosY, 3) & ",0,0")
         Dim WallMachGroup As MyMachGroupVM = Map.refMachGroupPanelVM.MachGroupVMList(Map.refMachGroupPanelVM.MachGroupVMList.Count - 1)
         ' eseguo script creazione grezzo
         If Not ExecWall(sLogPath, Map.refMachinePanelVM.SelectedMachine.Name, CalcIntegration.CmdTypes.RAWPART, False, False) Then
            ' elimino duplo e gruppo di lavorazione
            EgtErase(nPartDuploId)
            WallMachGroup.DeleteMachGroup()
            If File.Exists(sLogPath) Then
               Dim LogFile As String() = File.ReadAllLines(sLogPath)
               If LogFile.Count >= 2 AndAlso Not IsNothing(LogFile(1)) Then
                  MessageBox.Show(LogFile(1), EgtMsg(30007), MessageBoxButton.OK, MessageBoxImage.Error)
               End If
            Else
               MessageBox.Show(EgtMsg(61973), EgtMsg(30007), MessageBoxButton.OK, MessageBoxImage.Error)
            End If
            ' se nessun grezzo, rimetto tutti i pezzi invisibili
            If Map.refProjectVM.MachGroupPanelVM.MachGroupVMList.Count = 0 Then
               Map.refProjectVM.BTLStructureVM.HideAll(True)
            End If
            Return
         End If
         ' scrivo dati pezzo
         EgtSetInfo(nPartDuploId, MGR_PRT_POSX, dPosX)
         EgtSetInfo(nPartDuploId, MGR_PRT_POSY, dPosY)
         EgtSetInfo(nPartDuploId, MGR_PRT_ROT, SelParts(0).nROTATED)
         EgtSetInfo(nPartDuploId, MGR_PRT_FLIP, SelParts(0).nINVERTED)
         ' aggiorno contatore pezzi usati in Prod
         SelParts(0).RefreshPartInProd()
         ' aggiorno lista pezzi
         WallMachGroup.MyMachGroupM.RefreshPartList()
         WallMachGroup.MyMachGroupM.RefreshGroupData()
         ' aggiorno dati ultilizzo barra
         WallMachGroup.UpdateUsage()
         Core.ViewPanelVM.BWSetView(VT.TOP, False)
      End If
      EgtZoom(ZM.ALL)
   End Sub

   ' funzione che apre finestra di scelta dimensioni grezzo
   Private Function AddRawPartWnd(EditType As AddRawPartWndVM.EditTypes, SParamlist As List(Of SParam), ByRef dRawW As Double, ByRef dRawL As Double,
                                  ByRef dStartOffset As Double, ByRef dOffset As Double, ByRef dKerf As Double) As Boolean
      ' apro finestra con solo edit
      Dim AddRawPartWndVM As New AddRawPartWndVM(EditType, Map.refProjectVM.BTLStructureVM.nPROJTYPE, SParamlist, dRawL, dRawW, dStartOffset, dOffset, dKerf)
      Dim AddRawPartWndV As New AddRawPartWndV(Application.Current.MainWindow, AddRawPartWndVM)
      If Not AddRawPartWndV.ShowDialog() Then Return False
      Select Case Map.refProjectVM.BTLStructureVM.nPROJTYPE
         Case BWType.BEAM
            dRawL = AddRawPartWndVM.VariableList(0).dValue
            dStartOffset = AddRawPartWndVM.VariableList(1).dValue
            dOffset = AddRawPartWndVM.VariableList(2).dValue
         Case BWType.WALL
            dRawW = AddRawPartWndVM.VariableList(0).dValue
            dRawL = AddRawPartWndVM.VariableList(1).dValue
            dKerf = AddRawPartWndVM.VariableList(2).dValue
            dOffset = AddRawPartWndVM.VariableList(3).dValue
      End Select
      ' verifico se il materiale esiste in magazzino o devo aggiungerlo
      Dim CurrSParam As SParam = Nothing
      Select Case EditType
         Case AddRawPartWndVM.EditTypes.ONLY_TEXT
            ' lo aggiungo a lista materiali in magazzino
            CurrSParam = AddRawMaterial(dRawW, dRawL)
         Case AddRawPartWndVM.EditTypes.ONLY_COMBO
            ' non faccio nulla
         Case AddRawPartWndVM.EditTypes.TEXT_AND_COMBO
            ' verifico se lunghezza testo corrisponde a materiale
            If Map.refProjectVM.BTLStructureVM.nPROJTYPE = BWType.BEAM Then
               CurrSParam = SParamlist.FirstOrDefault(Function(x) x.dL = AddRawPartWndVM.VariableList(0).dValue)
            Else
               CurrSParam = SParamlist.FirstOrDefault(Function(x) x.dL = AddRawPartWndVM.VariableList(1).dValue AndAlso x.dW = AddRawPartWndVM.VariableList(0).dValue)
            End If
            If IsNothing(CurrSParam) Then
               ' lo aggiungo a lista materiali in magazzino
               CurrSParam = AddRawMaterial(dRawW, dRawL)
            End If
      End Select
      ' imposto il materiale selezionato come ultimo utilizzato
      SetLastMaterial(CurrSParam.SectXMat, CurrSParam)
      Return True
   End Function

   Private Function AddRawMaterial(dRawW As Double, ByRef dRawL As Double) As SParam
      Dim sWarehousePath As String = Map.refMainWindowVM.MainWindowM.sWarehouseDir & "\" & WH_MEDIUM_INI_FILE_NAME
      Dim nQuantity As Integer = GetMainPrivateProfileInt(S_WAREHOUSE, K_DEFAULTQUANTITY, 1)
      If Map.refProjectVM.BTLStructureVM.nPROJTYPE = MachineType.BEAM Then
         ' creo sParam
         Dim CurrSParam As New SParam(Map.refProjectVM.BTLStructureVM.SelBTLPart.Section, dRawL, nQuantity, False)
         Dim sL As String = String.Empty
         sL = LenToString(CurrSParam.dL, 3)
         ' ricavo l'indice del SecionXMaterial dalla Beam_List
         Dim SectXMatIndex As Integer = GetSectIndexFromSection(MachineType.BEAM, CurrSParam.SectXMat)
         ' ricavo nuovo indice materiale
         Dim ParamIndex As Integer = 1
         Dim sParam As String = ""
         While GetPrivateProfileString(S_BEAM, K_L & ParamIndex, "", sParam, sWarehousePath) > 0
            ParamIndex += 1
         End While
         If SectXMatIndex > 0 Then
            ' lo aggiungo in warehouse
            WritePrivateProfileString(S_BEAM, K_L & ParamIndex,
                                            SectXMatIndex & "," & sL & "," & CurrSParam.nQuantity & "," & If(CurrSParam.bActive, 1, 0),
                                            sWarehousePath)
         Else
            EgtOutLog("Error in material creation, section not found!")
         End If
         Return CurrSParam
      ElseIf Map.refProjectVM.BTLStructureVM.nPROJTYPE = MachineType.WALL Then
         ' creo sParam
         Dim CurrSParam As New SParam(Map.refProjectVM.BTLStructureVM.SelBTLPart.Section, dRawW, dRawL, nQuantity, False)
         Dim sW As String = String.Empty
         Dim sL As String = String.Empty
         sW = LenToString(CurrSParam.dW, 3)
         sL = LenToString(CurrSParam.dL, 3)
         ' ricavo l'indice del SecionXMaterial dalla Wall_List
         Dim SectXMatIndex As Integer = GetSectIndexFromSection(MachineType.WALL, CurrSParam.SectXMat)
         ' ricavo nuovo indice materiale
         Dim ParamIndex As Integer = 1
         Dim sParam As String = ""
         While GetPrivateProfileString(S_WALL, K_S & ParamIndex, "", sParam, sWarehousePath) > 0
            ParamIndex += 1
         End While
         ' lo aggiungo in warehouse
         WritePrivateProfileString(S_WALL, K_S & ParamIndex,
                                            SectXMatIndex & "," & sW & "," & sL & "," & CurrSParam.nQuantity & "," & If(CurrSParam.bActive, 1, 0),
                                            sWarehousePath)
         Return CurrSParam
      End If

      Return Nothing
   End Function

   Private Function VerifyPartCount(SelParts As List(Of BTLPartVM)) As Boolean
      ' verifico se ci sono pezzi da aggiungere
      Dim ToAddList As New List(Of String)
      Dim ToAddVM As New List(Of BTLPartVM)
      For Each SelPart In SelParts
         If Not SelPart.CanAddPartToCount Then
            ToAddList.Add(SelPart.nCNT & EgtMsg(61864) & SelPart.nADDED & EgtMsg(61865))
            ToAddVM.Add(SelPart)
         End If
      Next
      ' se non ci sono, chiedo se aggiungerne uno nuovo
      If ToAddList.Count > 0 Then
         Dim sMessage As String = EgtMsg(61863) & Environment.NewLine
         For Each sPart In ToAddList
            sMessage &= " - " & sPart & Environment.NewLine
         Next
         If MessageBox.Show(sMessage & EgtMsg(61893), "", MessageBoxButton.YesNo, MessageBoxImage.Question) = MessageBoxResult.Yes Then
            For Each PartVM In ToAddVM
               PartVM.AddNewPartToAdded()
            Next
         Else
            Return False
         End If
      End If
      Return True
   End Function

#End Region    ' NewRawPart

#Region "NewRawPartLast"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property NewRawPartLast_Command As ICommand
      Get
         If m_cmdNewRawPartLast Is Nothing Then
            m_cmdNewRawPartLast = New Command(AddressOf NewRawPartLast)
         End If
         Return m_cmdNewRawPartLast
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub NewRawPartLast()
      NewRawPart(True)
   End Sub

#End Region    ' NewRawPartLast

#Region "AddToRawPart"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property AddToRawPart_Command As ICommand
      Get
         If m_cmdAddToRawPart Is Nothing Then
            m_cmdAddToRawPart = New Command(AddressOf AddToRawPart)
         End If
         Return m_cmdAddToRawPart
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub AddToRawPart()
      If IsNothing(Map.refProdManagerVM.CurrProd) Then Return
      Dim SelPart As BTLPartVM = Map.refProjectVM.BTLStructureVM.SelBTLPart
      Dim SelParts As List(Of BTLPartVM) = Map.refProjectVM.BTLStructureVM.SelBTLParts.ToList()
      For Index = 0 To SelParts.Count() - 1
         If IsNothing(SelParts(Index)) Then
            SelParts.RemoveAt(Index)
         End If
      Next
      If IsNothing(SelPart) Then Return
      If IsNothing(SelParts) OrElse SelParts.Count <= 0 Then Return
      Dim SelMachGroup As MyMachGroupVM = Map.refMachGroupPanelVM.SelectedMachGroup
      If IsNothing(SelMachGroup) Then Return
      ' se pareti e piu' di uno selezionato, esco
      If Map.refProjectVM.BTLStructureVM.nPROJTYPE = BWType.WALL And SelParts.Count > 1 Then
         MessageBox.Show(EgtMsg(61971), EgtMsg(30007))
         Return
      End If
      ' se MachGroup gia' mandato in produzione, esco
      If SelMachGroup.nProduction_State >= ItemState.Assigned Then Return
      ' verifico se sono gia' stati messi tutti i pezzi richiesti
      If Not VerifyPartCount(SelParts) Then Return
      ' verifico se impostato gruppo di lavorazione
      Dim nCurrMachgroupId As Integer = EgtGetCurrMachGroup()
      ' se nullo o diverso da quello selezionato in lista
      If nCurrMachgroupId = GDB_ID.NULL OrElse nCurrMachgroupId <> SelMachGroup.Id Then
         ' lo imposto
         EgtSetCurrMachGroup(SelMachGroup.Id)
      End If
      If Map.refProjectVM.BTLStructureVM.nPROJTYPE = MachineType.BEAM Then
         Dim BeamMachGroup As MyMachGroupVM = SelMachGroup
         ' verifico sezione e materiale
         For Each Part In SelParts
            If Part.Section <> BeamMachGroup.Section Then
               MessageBox.Show(EgtMsg(61866), EgtMsg(30007))
               Return
            End If
         Next
         ' verifico lunghezza totale
         If Not VerifyTotLength(BeamMachGroup, SelParts) Then
            MessageBox.Show(EgtMsg(61867), EgtMsg(30007))
            Return
         End If
         If AddPartToBeam(BeamMachGroup, SelParts) Then
            ' aggiorno contatore pezzi usati in Prod
            For Each Part In SelParts
               Part.RefreshPartInProd()
            Next
            ' resetto stato di calc
            SelMachGroup.ResetCalcMachGroup()
         End If
         ' aggiorno dati ultilizzo barra
         BeamMachGroup.UpdateUsage()
         Core.ViewPanelVM.BWSetView(VT.ISO_SW, False)
      ElseIf Map.refProjectVM.BTLStructureVM.nPROJTYPE = MachineType.WALL Then
         Dim WallMachGroup As MyMachGroupVM = SelMachGroup
         ' verifico spessore
         If SelPart.Section <> WallMachGroup.Section Then
            MessageBox.Show(EgtMsg(61868), EgtMsg(30007))
            Return
         End If
         If AddPartToWall(WallMachGroup, SelPart) Then
            ' aggiorno contatore pezzi usati in Prod
            SelPart.RefreshPartInProd()
            ' resetto stato di calc
            SelMachGroup.ResetCalcMachGroup()
         End If
         ' aggiorno dati ultilizzo barra
         WallMachGroup.UpdateUsage()
         Core.ViewPanelVM.BWSetView(VT.TOP, False)
      End If
      EgtZoom(ZM.ALL)
   End Sub

   Friend Function VerifyTotLength(BeamMachGroup As MyMachGroupVM, PartsToAdd As List(Of BTLPartVM)) As Boolean
      Dim dNewPartPos As Double = 0
      If BeamMachGroup.PartVMList.Count > 0 Then
         Dim LastPart As PartVM = BeamMachGroup.PartVMList(BeamMachGroup.PartVMList.Count - 1)
         dNewPartPos += LastPart.dPOSX + LastPart.dL
      End If
      For Each Part In PartsToAdd
         dNewPartPos += WarehouseHelper.GetOffset(BeamMachGroup.nType) + Part.dL
      Next
      Return dNewPartPos < BeamMachGroup.dL
   End Function

   Friend Function AddPartToBeam(BeamMachGroup As MyMachGroupVM, PartsToAdd As List(Of BTLPartVM)) As Boolean
      ' ordino i pezzi da aggiungere
      PartsToAdd = PartsToAdd.OrderBy(Function(x) x.dL).ToList()
      ' creo copie dei pezzi
      Dim nPartDuploIdList As New List(Of Integer)
      For Each Part In PartsToAdd
         Dim nDuploId As Integer = EgtDuploNew(Part.nPartId)
         ' elimino valori calcolo dell'originale
         MyMachGroupPanelVM.DuploRemoveProjCalc(nDuploId)
         ' lo rendo std
         EgtSetMode(nDuploId, GDB_MD.STD)
         nPartDuploIdList.Add(nDuploId)
      Next
      ' calcolo posizione nuovo pezzo per rispettare ordine lunghezze
      Dim nInsertIndex As Integer
      ' scrivo dati di tutti i pezzi
      Dim dPosX As Double = BeamMachGroup.dStartCut
      Dim nPartIndex As Integer = 0
      Dim nIndex As Integer
      ' ciclo sui pezzi
      For nIndex = 0 To BeamMachGroup.PartVMList.Count - 1
         For PartsToAddIndex = nPartIndex To PartsToAdd.Count - 1
            Dim Part As BTLPartVM = PartsToAdd(PartsToAddIndex)
            ' se non ancora aggiunto e lunghezza minore del pezzo corrente, lo aggiungo
            If nPartIndex < nPartDuploIdList.Count() AndAlso BeamMachGroup.PartVMList(nIndex).dL > Part.dL Then
               ' se non è primo, aggiungo offset tra barre standard
               If nIndex <> 0 OrElse nPartIndex <> 0 Then
                  dPosX += WarehouseHelper.GetOffset(BeamMachGroup.nType)
               End If
               EgtSetInfo(BeamMachGroup.Id, MGR_RPT_PART & nIndex + nPartIndex + 1, nPartDuploIdList(nPartIndex) & "," & DoubleToString(dPosX, 3))
               ' incremento posizione della sua lunghezza
               dPosX += Part.dL
               ' conservo indice d'inserimento
               nInsertIndex = nIndex
               nPartIndex += 1
            Else
               Exit For
            End If
         Next
         ' se non è primo, aggiungo offset del pezzo
         If nIndex <> 0 Then
            dPosX += BeamMachGroup.PartVMList(nIndex).dOffset
            ' se sono a indice primo ed è stato aggiunto pezzo nuovo
         ElseIf nIndex = 0 AndAlso nPartIndex > 0 Then
            ' aggiungo offset tra barre standard
            dPosX += WarehouseHelper.GetOffset(BeamMachGroup.nType)
         End If
         EgtSetInfo(BeamMachGroup.Id, MGR_RPT_PART & nIndex + nPartIndex + 1, BeamMachGroup.PartVMList(nIndex).nPartId & "," & DoubleToString(dPosX, 3))
         ' incremento posizione della sua lunghezza
         dPosX += BeamMachGroup.PartVMList(nIndex).dL
      Next
      ' se non è ancora stato aggiunto
      For PartsToAddIndex = nPartIndex To PartsToAdd.Count - 1
         ' aggiungo offset tra barre standard
         dPosX += WarehouseHelper.GetOffset(BeamMachGroup.nType)
         ' lo aggiungo in fondo
         EgtSetInfo(BeamMachGroup.Id, MGR_RPT_PART & nIndex + nPartIndex + 1, nPartDuploIdList(nPartIndex) & "," & DoubleToString(dPosX, 3))
         ' incremento posizione della sua lunghezza
         dPosX += PartsToAdd(nPartIndex).dL
         ' conservo indice d'inserimento
         nInsertIndex = nIndex
         nPartIndex += 1
      Next
      ' elimino vecchio grezzo ed eseguo script creazione nuovo
      Dim nRawId As Integer = EgtGetFirstRawPart()
      While nRawId <> GDB_ID.NULL
         EgtRemoveRawPart(nRawId)
         nRawId = EgtGetFirstRawPart()
      End While
      Dim sLogPath As String = Map.refMainWindowVM.MainWindowM.sTempDir & "\RawPartLog.txt"
      If Not ExecBeam(sLogPath, Map.refMachinePanelVM.SelectedMachine.Name, CalcIntegration.CmdTypes.RAWPART, False) Then
         Return False
      End If
      For nDuploIndex = 0 To PartsToAdd.Count - 1
         EgtSetInfo(nPartDuploIdList(nDuploIndex), MGR_PRT_ROT, PartsToAdd(nDuploIndex).nROTATED)
         EgtSetInfo(nPartDuploIdList(nDuploIndex), MGR_PRT_FLIP, PartsToAdd(nDuploIndex).nINVERTED)
      Next
      ' aggiorno lista pezzi
      BeamMachGroup.MyMachGroupM.RefreshPartList()
      ' seleziono pezzo aggiunto
      If BeamMachGroup.PartVMList.Count > nInsertIndex Then BeamMachGroup.SelPart = BeamMachGroup.PartVMList(nInsertIndex)
      Return True
   End Function

   Friend Function AddPartToWall(WallMachGroup As MyMachGroupVM, PartToAdd As BTLPartVM) As Boolean
      ' creo copia del pezzo
      Dim nPartDuploId As Integer = EgtDuploNew(PartToAdd.nPartId)
      ' lo rendo std
      EgtSetMode(nPartDuploId, GDB_MD.STD)
      ' Posizione di inserimento
      Dim dPosX As Double = WarehouseHelper.GetKerf()
      Dim dPosY As Double = WarehouseHelper.GetKerf()
      ' Se ci sono pezzi già inseriti
      If WallMachGroup.PartVMList.Count > 0 Then
         Dim LastWall As PartVM = WallMachGroup.PartVMList(WallMachGroup.PartVMList.Count - 1)
         Dim LastWallPosX As Double = LastWall.dPOSX
         Dim LastWallPosY As Double = LastWall.PartM.dPOSY
         ' converto posizione ultimo pezzo nel riferimento BL
         Select Case CurrentMachine.NestingCorner
            Case MCH_CR.TL
               LastWallPosY = WallMachGroup.dW - LastWall.dW - LastWall.PartM.dPOSY
            Case MCH_CR.BL
            Case MCH_CR.TR
               LastWallPosX = WallMachGroup.dL - LastWall.dL - LastWall.dPOSX
               LastWallPosY = WallMachGroup.dW - LastWall.dW - LastWall.PartM.dPOSY
            Case MCH_CR.BR
               LastWallPosX = WallMachGroup.dL - LastWall.dL - LastWall.dPOSX
         End Select
         ' verifico se posso metterlo sopra in Y
         Dim NextPosY = LastWallPosY + LastWall.dW + WarehouseHelper.GetOffset(WallMachGroup.nType)
         If WallMachGroup.dW - NextPosY > PartToAdd.dW + 10 Then
            dPosX = LastWallPosX
            dPosY = NextPosY
         Else
            ' altrimenti lo affianco in X
            dPosX = 10
            For i As Integer = 0 To WallMachGroup.PartVMList.Count - 1
               Dim CurrWall As PartVM = WallMachGroup.PartVMList(i)
               Dim CurrWallPosX As Double = CurrWall.dPOSX
               ' converto posizione pezzo corrente nel riferimento BL
               Select Case CurrentMachine.NestingCorner
                  Case MCH_CR.TL
                  Case MCH_CR.BL
                  Case MCH_CR.TR
                     CurrWallPosX = WallMachGroup.dL - CurrWall.dL - CurrWall.dPOSX
                  Case MCH_CR.BR
                     CurrWallPosX = WallMachGroup.dL - CurrWall.dL - CurrWall.dPOSX
               End Select
               Dim NextPosX = CurrWallPosX + CurrWall.dL + WarehouseHelper.GetOffset(WallMachGroup.nType)
               If NextPosX > dPosX Then
                  dPosX = NextPosX
               End If
            Next
            dPosY = 10
         End If
      End If
      ' converto posizione trovata da riferimento BL a quello corrente
      Select Case CurrentMachine.NestingCorner
         Case MCH_CR.TL
            dPosY = WallMachGroup.dW - PartToAdd.dW - dPosY
         Case MCH_CR.BL
         Case MCH_CR.TR
            dPosX = WallMachGroup.dL - PartToAdd.dL - dPosX
            dPosY = WallMachGroup.dW - PartToAdd.dW - dPosY
         Case MCH_CR.BR
            dPosX = WallMachGroup.dL - PartToAdd.dL - dPosX
      End Select
      ' aggiungo il pezzo al grezzo
      If EgtAddPartToRawPart(nPartDuploId, New Point3d(dPosX, dPosY, 0), WallMachGroup.MyMachGroupM.nRawPartId) Then
         EgtSetInfo(nPartDuploId, MGR_PRT_POSX, dPosX)
         EgtSetInfo(nPartDuploId, MGR_PRT_POSY, dPosY)
         EgtSetInfo(nPartDuploId, MGR_PRT_ROT, PartToAdd.nROTATED)
         EgtSetInfo(nPartDuploId, MGR_PRT_FLIP, PartToAdd.nINVERTED)
      Else
         Return False
      End If
      'aggiorno lista pezzi
      WallMachGroup.MyMachGroupM.RefreshPartList()
      ' seleziono pezzo aggiunto
      If WallMachGroup.PartVMList.Count > 0 Then WallMachGroup.SelPart = WallMachGroup.PartVMList.FirstOrDefault(Function(x) x.nPartId = nPartDuploId)
      Return True
   End Function

#End Region    ' AddToRawPart

#Region "CopyPart"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property CopyPart_Command As ICommand
      Get
         If m_cmdCopyPart Is Nothing Then
            m_cmdCopyPart = New Command(AddressOf CopyPart)
         End If
         Return m_cmdCopyPart
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub CopyPart()
      If IsNothing(Map.refProjManagerVM.CurrProj) Then Return
      Dim SelPart As BTLPartVM = Map.refProjectVM.BTLStructureVM.SelBTLPart
      If IsNothing(SelPart) Then Return
      ' creo copia
      Dim NewPart As BTLPartM = SelPart.Copy()
      If Not IsNothing(NewPart) Then
         ' selezione ultimo che e' quello appena creato
         Map.refProjectVM.BTLStructureVM.SetSelBTLPart(Map.refProjectVM.BTLStructureVM.BTLPartVMList(Map.refProjectVM.BTLStructureVM.BTLPartVMList.Count - 1), False, True)
      End If
   End Sub

#End Region    ' CopyPart

#Region "AddPart"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property AddPart_Command As ICommand
      Get
         If m_cmdAddPart Is Nothing Then
            m_cmdAddPart = New Command(AddressOf AddPart)
         End If
         Return m_cmdAddPart
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub AddPart(ByVal param As Object)
      If IsNothing(Map.refProjManagerVM.CurrProj) Then Return
      ' apro finestra di definizione nuovo part
      Dim AddPartWndVM As New AddPartWndVM()
      Dim AddPartWnd As New AddPartWndV(Application.Current.MainWindow, AddPartWndVM)
      If AddPartWnd.ShowDialog() Then
         ' creo nuovo part
         Dim nNewPartId As Integer = EgtBeamCreatePart()
         ' scrivo info proj
         EgtSetInfo(nNewPartId, BTL_PRT_PROJ, Map.refProjManagerVM.CurrProj.nProjId)
         EgtBeamSetPartProdNbr(AddPartWndVM.nPDN)
         If Not IsNothing(AddPartWndVM.sNAM) Then EgtBeamSetPartName(AddPartWndVM.sNAM)
         EgtBeamSetPartCount(AddPartWndVM.nCNT)
         EgtBeamSetPartBox(AddPartWndVM.dL, AddPartWndVM.dH, AddPartWndVM.dW)
         ' se progetto pareti e vista ruotata
         If nType = BWType.WALL AndAlso (CurrentMachine.ViewDir = VT.ISO_NW OrElse CurrentMachine.ViewDir = VT.ISO_NE) Then
            '' ruoto le pareti di 180 per raddrizzarle rispetto alla vista
            'NewPart.Rotation(True, Map.refProjectVM.BTLStructureVM.nPROJTYPE, 180, False)
            ' recupero il box del pezzo
            Dim nBoxLayerId As Integer = EgtGetFirstNameInGroup(nNewPartId, "Box")
            Dim b3Solid As New BBox3d
            EgtGetBBoxGlob(nBoxLayerId, GDB_BB.STANDARD, b3Solid)
            Dim bOk As Boolean = EgtRotate(nNewPartId, b3Solid.Center, Vector3d.Z_AX, 180, GDB_RT.GLOB)
            If bOk Then
               EgtSetInfo(nNewPartId, BTL_PRT_ROTATED, 180)
            End If
         End If
         ' aggiungo dati pezzo
         Dim NewPart As BTLPartM = BTLPartM.CreateBTLPart(nNewPartId)
         ' aggiungo pezzo alla lista
         Map.refProjectVM.BTLStructureVM.BTLStructureM.AddBTLPart(NewPart)
         Dim NewPartVM As BTLPartVM = Map.refProjectVM.BTLStructureVM.BTLPartVMList.FirstOrDefault(Function(x) x.BTLPartM Is NewPart)
         If Not IsNothing(NewPartVM) Then
            EgtZoom(ZM.ALL)
            Map.refProjectVM.BTLStructureVM.SetSelBTLPart(NewPartVM, False, True)
            ' verifico se aggiungere sezione alla lista
            If Not Map.refProjectVM.BTLStructureVM.SectionList.Contains(NewPartVM.Section) Then
               Map.refProjectVM.BTLStructureVM.SectionList.Add(NewPartVM.Section)
            End If
         End If
      End If

   End Sub

#End Region    ' AddPart

#Region "RemovePart"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property RemovePart_Command As ICommand
      Get
         If m_cmdRemovePart Is Nothing Then
            m_cmdRemovePart = New Command(AddressOf RemovePartCmd)
         End If
         Return m_cmdRemovePart
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub RemovePartCmd()
      If IsNothing(Map.refProjManagerVM.CurrProj) Then Return
      If Map.refProjectVM.BTLStructureVM.SelBTLParts.Count > 0 Then
         Dim CurrSelBTLParts As List(Of BTLPartVM) = Map.refProjectVM.BTLStructureVM.SelBTLParts.ToList()
         For RemoveIndex = CurrSelBTLParts.Count - 1 To 0 Step -1
            RemovePart(CurrSelBTLParts(RemoveIndex), RemoveIndex = 0)
            ' imposto vista tutti i pezzi
            'Map.refShowBeamPanelVM.ShowAll(RemoveIndex = 0)
         Next
      End If
   End Sub

   Public Sub RemovePart(BTLPartToDelete As BTLPartVM, bSelPrevious As Boolean)
      ' verifico se ci sono già copie in grezzi
      Dim nDuploCount As Integer = 0
      If EgtDuploCount(BTLPartToDelete.nPartId, nDuploCount) AndAlso nDuploCount > 0 Then
         ' avviso che il pezzo non è cancellabile perchè in produzione
         MessageBox.Show(String.Format(EgtMsg(61929), nDuploCount), EgtMsg(15003), MessageBoxButton.OK, MessageBoxImage.Warning)
         Return
      End If
      ' verifico se rimuovere sezione dalla lista
      If Not Map.refProjectVM.BTLStructureVM.BTLPartVMList.Any(Function(x) x IsNot BTLPartToDelete AndAlso x.Section = BTLPartToDelete.Section) Then
         Map.refProjectVM.BTLStructureVM.SectionList.Remove(BTLPartToDelete.Section)
         Map.refProjectVM.BTLStructureVM.SelSection = SectionXMaterial.Empty
      End If
      ' Eseguo cancellazione
      EgtBeamSetPart(BTLPartToDelete.nPartId)
      If EgtBeamErasePart() Then
         ' seleziono elemento precedente
         Dim Index As Integer = Map.refProjectVM.BTLStructureVM.BTLPartVMList.IndexOf(BTLPartToDelete)
         Dim FilteredIndex As Integer = Map.refProjectVM.BTLStructureVM.BTLPartVMList_View.IndexOf(BTLPartToDelete)
         Map.refProjectVM.BTLStructureVM.SelBTLParts.Remove(BTLPartToDelete)
         If bSelPrevious Then
            If FilteredIndex = 0 Then
               If Map.refProjectVM.BTLStructureVM.BTLPartVMList_View.Count > 1 Then
                  Map.refProjectVM.BTLStructureVM.SetSelBTLPart(Map.refProjectVM.BTLStructureVM.BTLPartVMList_View(1))
               Else
                  Map.refProjectVM.BTLStructureVM.SetSelBTLPart(Nothing)
               End If
            ElseIf FilteredIndex = Map.refProjectVM.BTLStructureVM.BTLPartVMList_View.Count - 1 Then
               If Map.refProjectVM.BTLStructureVM.BTLPartVMList_View.Count > 1 Then
                  Map.refProjectVM.BTLStructureVM.SetSelBTLPart(Map.refProjectVM.BTLStructureVM.BTLPartVMList_View(Map.refProjectVM.BTLStructureVM.BTLPartVMList_View.Count - 2))
               Else
                  Map.refProjectVM.BTLStructureVM.SetSelBTLPart(Nothing)
               End If
            Else
               Map.refProjectVM.BTLStructureVM.SetSelBTLPart(Map.refProjectVM.BTLStructureVM.BTLPartVMList_View(FilteredIndex - 1))
            End If
         End If
         ' rimuovo dalla lista pezzi
         Map.refProjectVM.BTLStructureVM.BTLPartVMList.RemoveAt(Index)
      End If
   End Sub

#End Region    ' RemovePart

#Region "Invert"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property Invert_Command As ICommand
      Get
         If m_cmdInvert Is Nothing Then
            m_cmdInvert = New Command(AddressOf Invert)
         End If
         Return m_cmdInvert
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub Invert()
      If IsNothing(Map.refProjManagerVM.CurrProj) OrElse IsNothing(Map.refProjectVM.BTLStructureVM) Then Return
      ' se modalita' assemblato
      Dim bShowBuilding As Boolean = Map.refShowBeamPanelVM.ShowBuilding_IsChecked
      If bShowBuilding AndAlso Map.refShowBeamPanelVM.bShowAll Then
         ' devo smontarlo prima di ruotare le travi
         Map.refProjectVM.BTLStructureVM.ShowBuilding(False, False)
      End If
      ' inverto i pezzi selezionati
      For Each Part In Map.refProjectVM.BTLStructureVM.SelBTLParts
         Part.Invert()
      Next
      ' se assemblato lo ripristino
      If bShowBuilding Then Map.refProjectVM.BTLStructureVM.ShowBuilding(True, False)
   End Sub

#End Region    ' BackRotation

#Region "BackRotation"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property BackRotation_Command As ICommand
      Get
         If m_cmdBackRotation Is Nothing Then
            m_cmdBackRotation = New Command(AddressOf BackRotation)
         End If
         Return m_cmdBackRotation
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub BackRotation()
      If IsNothing(Map.refProjManagerVM.CurrProj) OrElse IsNothing(Map.refProjectVM.BTLStructureVM) Then Return
      ' salvo sezione impostata
      Dim CurrSection As SectionXMaterial = Map.refProjectVM.BTLStructureVM.SelSection
      ' se modalita' assemblato
      Dim bShowBuilding As Boolean = Map.refShowBeamPanelVM.ShowBuilding_IsChecked
      If bShowBuilding AndAlso Map.refShowBeamPanelVM.bShowAll Then
         ' devo smontarlo prima di ruotare le travi
         Map.refProjectVM.BTLStructureVM.ShowBuilding(False, False)
      End If
      ' ruoto i pezzi selezionati
      For Each Part In Map.refProjectVM.BTLStructureVM.SelBTLParts
         Part.BackRotation(False, False)
      Next
      ' se assemblato lo ripristino
      If bShowBuilding Then Map.refProjectVM.BTLStructureVM.ShowBuilding(True, False)
      ' se progetto travi e sezione precedente diversa da vuota (tutti i pezzi)
      If Map.refProjectVM.BTLStructureVM.nPROJTYPE = BWType.BEAM AndAlso CurrSection <> SectionXMaterial.Empty Then
         ' se esiste, imposto sezione inversa
         Dim InverseSection As SectionXMaterial = Map.refProjectVM.BTLStructureVM.SectionList.FirstOrDefault(Function(x) x.dH = CurrSection.dW AndAlso x.dW = CurrSection.dH AndAlso x.sMaterial(0) = CurrSection.sMaterial(0))
         If Not IsNothing(InverseSection) Then Map.refProjectVM.BTLStructureVM.SetSelSection(InverseSection)
      End If
      EgtDraw()
   End Sub

#End Region    ' BackRotation

#Region "ForwardRotation"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property ForwardRotation_Command As ICommand
      Get
         If m_cmdForwardRotation Is Nothing Then
            m_cmdForwardRotation = New Command(AddressOf ForwardRotation)
         End If
         Return m_cmdForwardRotation
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub ForwardRotation()
      If IsNothing(Map.refProjManagerVM.CurrProj) OrElse IsNothing(Map.refProjectVM.BTLStructureVM) Then Return
      ' salvo sezione impostata
      Dim CurrSection As SectionXMaterial = Map.refProjectVM.BTLStructureVM.SelSection
      ' se modalita' assemblato
      Dim bShowBuilding As Boolean = Map.refShowBeamPanelVM.ShowBuilding_IsChecked
      If bShowBuilding AndAlso Map.refShowBeamPanelVM.bShowAll Then
         ' devo smontarlo prima di ruotare le travi
         Map.refProjectVM.BTLStructureVM.ShowBuilding(False, False)
      End If
      ' ruoto i pezzi selezionati
      For Each Part In Map.refProjectVM.BTLStructureVM.SelBTLParts
         Part.ForwardRotation(False, False)
      Next
      ' se assemblato lo ripristino
      If bShowBuilding Then Map.refProjectVM.BTLStructureVM.ShowBuilding(True, False)
      ' se progetto travi e sezione precedente diversa da vuota (tutti i pezzi)
      If Map.refProjectVM.BTLStructureVM.nPROJTYPE = BWType.BEAM AndAlso CurrSection <> SectionXMaterial.Empty Then
         ' se esiste, imposto sezione inversa
         Dim InverseSection As SectionXMaterial = Map.refProjectVM.BTLStructureVM.SectionList.FirstOrDefault(Function(x) x.dH = CurrSection.dW AndAlso x.dW = CurrSection.dH AndAlso x.sMaterial(0) = CurrSection.sMaterial(0))
         If Not IsNothing(InverseSection) Then Map.refProjectVM.BTLStructureVM.SetSelSection(InverseSection)
      End If
      EgtDraw()
   End Sub

#End Region    ' ForwardRotation

#Region "CopyFeature"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property CopyFeature_Command As ICommand
      Get
         If m_cmdCopyFeature Is Nothing Then
            m_cmdCopyFeature = New Command(AddressOf CopyFeature)
         End If
         Return m_cmdCopyFeature
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub CopyFeature()
      If IsNothing(Map.refProjManagerVM.CurrProj) Then Return
      Dim SelPart As BTLPartVM = Map.refProjectVM.BTLStructureVM.SelBTLPart
      If IsNothing(SelPart) Then Return
      Dim SelFeature As BTLFeatureVM = SelPart.SelBTLFeatureVM
      If IsNothing(SelFeature) Then Return
      ' creo copia
      Dim NewFeature = SelFeature.Copy()
      If Not IsNothing(NewFeature) Then
         SelPart.SelBTLFeatureVM = Map.refProjectVM.BTLStructureVM.SelBTLPart.BTLFeatureVMList.FirstOrDefault(Function(x) x.BTLFeatureM Is NewFeature)
         EgtDuploSetModified(SelPart.nPartId)
      End If
      SelPart.ResetCalcPart()
   End Sub

#End Region    ' CopyFeature

#Region "MacroFeature"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property MacroFeature_Command As ICommand
      Get
         If m_cmdMacroFeature Is Nothing Then
            m_cmdMacroFeature = New Command(AddressOf MacroFeature)
         End If
         Return m_cmdMacroFeature
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub MacroFeature()
      If IsNothing(Map.refProjManagerVM.CurrProj) Then Return
      If IsNothing(Map.refProjectVM.BTLStructureVM.SelBTLPart) Then Return
      ' apro finestra di creazione macro
      Dim MacroFeatureWndVM As New MacroFeatureWndVM()
      Dim MacroFeatureWnd As New MacroFeatureWndV(Application.Current.MainWindow, MacroFeatureWndVM)
      If MacroFeatureWnd.ShowDialog() Then

      End If
   End Sub

#End Region    ' MacroFeature

#Region "AddFeature"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property AddFeature_Command As ICommand
      Get
         If m_cmdAddFeature Is Nothing Then
            m_cmdAddFeature = New Command(AddressOf AddFeature)
         End If
         Return m_cmdAddFeature
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub AddFeature(ByVal param As Object)
      If IsNothing(Map.refProjManagerVM.CurrProj) Then Return
      If IsNothing(Map.refProjectVM.BTLStructureVM.SelBTLPart) Then Return
      ' apro finestra di definizione nuova feature
      Dim AddFeatureWndVM As New AddFeatureWndVM()
      Dim AddFeatureWnd As New AddFeatureWndV(Application.Current.MainWindow, AddFeatureWndVM)
      If AddFeatureWnd.ShowDialog() Then
         Dim NewFeat As BTLFeatureM
         Dim nNewFeatureId As Integer = 0
         Dim bMacroFlag As Boolean = False
         ' verifico se una Macro è selezionata
         If AddFeatureWndVM.MacroList.Count > 0 AndAlso AddFeatureWndVM.nSelMacro >= 0 Then
            ' Creo nuova feature sulla base della Macro selezionata
            ' Creo table e setto variabili
            EgtLuaCreateGlobTable("MACRO")
            EgtLuaSetGlobNumVar("MACRO.L", Map.refProjectVM.BTLStructureVM.SelBTLPart.dBtlL)
            EgtLuaSetGlobNumVar("MACRO.W", Map.refProjectVM.BTLStructureVM.SelBTLPart.dBtlW)
            EgtLuaSetGlobNumVar("MACRO.H", Map.refProjectVM.BTLStructureVM.SelBTLPart.dBtlH)
            EgtLuaSetGlobIntVar("MACRO.PROCID", Map.refProjectVM.BTLStructureVM.SelBTLPart.BTLPartM.NewProcId())
            Dim bOk = EgtLuaExecFile(AddFeatureWndVM.m_MacroFilePathList(AddFeatureWndVM.nSelMacro))
            ' Leggo variabili
            EgtLuaGetGlobIntVar("MACRO.FEATUREID", nNewFeatureId)
            ' Reset lua
            EgtLuaResetGlobVar("MACRO")
            If Not bOk Then
               MessageBox.Show(EgtMsg(61869), EgtMsg(30007))
               Return
            End If
            bMacroFlag = True
         Else
            ' Creo nuova feature (Macro non selezionata)
            NewFeat = BTLFeatureM.CreateBTLFeature(AddFeatureWndVM.nSelPRC.nPRC, AddFeatureWndVM.nSelPRC.nGRP, AddFeatureWndVM.nSelPRC.nSIDE)
            NewFeat.SetDefaultValues()
            Dim vPar() As Double = Nothing
            Dim sPar As String = String.Empty
            Dim vParQ() As String = Nothing
            NewFeat.CalcParamArray(vPar, sPar, vParQ)
            ' aggiorno la feature con nuovo valore
            EgtBeamSetPart(Map.refProjectVM.BTLStructureVM.SelBTLPart.nPartId)
            nNewFeatureId = EgtBeamAddProcess(NewFeat.nSelGRP, NewFeat.nPRC, NewFeat.nSelSIDE, "",
                                              Map.refProjectVM.BTLStructureVM.SelBTLPart.BTLPartM.NewProcId(),
                                              New Frame3d(), vPar, sPar, vParQ, GDB_ID.NULL, GDB_ID.NULL)
            bMacroFlag = False
         End If
         ' se è stata creata
         If nNewFeatureId <> GDB_ID.NULL Then
            EgtDuploSetModified(Map.refProjectVM.BTLStructureVM.SelBTLPart.nPartId)
            ' la aggiungo a struttura BTL corrente
            NewFeat = BTLFeatureM.CreateBTLFeature(Map.refProjectVM.BTLStructureVM.SelBTLPart.BTLPartM, nNewFeatureId)
            If Not bMacroFlag Then NewFeat.SetDefaultValues()
            Map.refProjectVM.BTLStructureVM.SelBTLPart.BTLPartM.AddBTLFeature(NewFeat)
            Map.refProjectVM.BTLStructureVM.SelBTLPart.SelBTLFeatureVM = Map.refProjectVM.BTLStructureVM.SelBTLPart.BTLFeatureVMList.FirstOrDefault(Function(x) x.BTLFeatureM Is NewFeat)
            Map.refProjectVM.BTLStructureVM.SelBTLPart.ResetCalcPart()
         End If
      End If
   End Sub

#End Region    ' AddFeature

#Region "RemoveFeature"

   ''' <summary>
   ''' Returns a command that do Exec.
   ''' </summary>
   Public ReadOnly Property RemoveFeature_Command As ICommand
      Get
         If m_cmdRemoveFeature Is Nothing Then
            m_cmdRemoveFeature = New Command(AddressOf RemoveFeature)
         End If
         Return m_cmdRemoveFeature
      End Get
   End Property

   ''' <summary>
   ''' Execute the Exec.  This method is invoked by the ExecCommand.
   ''' </summary>
   Public Sub RemoveFeature()
      If IsNothing(Map.refProjManagerVM.CurrProj) Then Return
      If IsNothing(Map.refProjectVM.BTLStructureVM.SelBTLPart) Then Return
      If IsNothing(Map.refProjectVM.BTLStructureVM.SelBTLPart.SelBTLFeatureVM) Then Return
      If EgtBeamEraseProcess(Map.refProjectVM.BTLStructureVM.SelBTLPart.SelBTLFeatureVM.nFeatureId) Then
         EgtDuploSetModified(Map.refProjectVM.BTLStructureVM.SelBTLPart.nPartId)
         ' rimuovo dalla lista feature
         Dim Index As Integer = Map.refProjectVM.BTLStructureVM.SelBTLPart.BTLFeatureVMList.IndexOf(Map.refProjectVM.BTLStructureVM.SelBTLPart.SelBTLFeatureVM)
         If Index = 0 Then
            If Map.refProjectVM.BTLStructureVM.SelBTLPart.BTLFeatureVMList.Count > 0 Then
               Map.refProjectVM.BTLStructureVM.SelBTLPart.SelBTLFeatureVM = Map.refProjectVM.BTLStructureVM.SelBTLPart.BTLFeatureVMList(0)
            Else
               Map.refProjectVM.BTLStructureVM.SelBTLPart.SelBTLFeatureVM = Nothing
            End If
         ElseIf Index = Map.refProjectVM.BTLStructureVM.SelBTLPart.BTLFeatureVMList.Count - 1 Then
            If Map.refProjectVM.BTLStructureVM.SelBTLPart.BTLFeatureVMList.Count > 1 Then
               Map.refProjectVM.BTLStructureVM.SelBTLPart.SelBTLFeatureVM = Map.refProjectVM.BTLStructureVM.SelBTLPart.BTLFeatureVMList(Map.refProjectVM.BTLStructureVM.SelBTLPart.BTLFeatureVMList.Count - 2)
            Else
               Map.refProjectVM.BTLStructureVM.SelBTLPart.SelBTLFeatureVM = Nothing
            End If
         Else
            Map.refProjectVM.BTLStructureVM.SelBTLPart.SelBTLFeatureVM = Map.refProjectVM.BTLStructureVM.SelBTLPart.BTLFeatureVMList(Index - 1)
         End If
         Map.refProjectVM.BTLStructureVM.SelBTLPart.BTLFeatureVMList.RemoveAt(Index)
         EgtDraw()
         Map.refProjectVM.BTLStructureVM.SelBTLPart.ResetCalcPart()
      End If
   End Sub

#End Region    ' RemoveFeature

#End Region    ' COMMANDS

End Class
