Imports System.Collections.ObjectModel
Imports EgtWPFLib5
Imports EgtUILib
Imports EgtBEAMWALL.Core
Imports System.Collections.Specialized
Imports System.ComponentModel
Imports System.Windows.Threading

Public Class BTLPartVM
   Inherits VMBase

#Region "FIELDS & PROPERTIES"

   Private WithEvents m_BTLPartM As BTLPartM
   Public ReadOnly Property BTLPartM As BTLPartM
      Get
         Return m_BTLPartM
      End Get
   End Property
   Private m_BTLStructureM As BTLStructureM

   Private m_IsSelected As Boolean
   Public Property IsSelected As Boolean
      Get
         Return m_IsSelected
      End Get
      Set(value As Boolean)
         m_IsSelected = value
         Map.refProjectVM.BTLStructureVM.UpdateSelBTLParts()
      End Set
   End Property
   Friend Sub SetIsSelected(value As Boolean, Optional bByOptim As Boolean = False)
      m_IsSelected = value
      Map.refProjectVM.BTLStructureVM.UpdateSelBTLParts(False, bByOptim)
      NotifyPropertyChanged(NameOf(IsSelected))
   End Sub

   Public ReadOnly Property nPartId As Integer
      Get
         Return m_BTLPartM.nPartId
      End Get
   End Property

   Public Property nPDN As Integer
      Get
         Return m_BTLPartM.nPDN
      End Get
      Set(value As Integer)
         m_BTLPartM.nPDN = value
      End Set
   End Property

   Public Property bDO As Boolean
      Get
         Return m_BTLPartM.bDO
      End Get
      Set(value As Boolean)
         m_BTLPartM.bDO = value
         EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_DO, If(value, 1, 0))
         NotifyPropertyChanged(NameOf(Calc_BorderBrush))
      End Set
   End Property

   Public Property sNAM As String
      Get
         Return m_BTLPartM.sNAM
      End Get
      Set(value As String)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_NAM, value) Then
            m_BTLPartM.sNAM = value
         End If
         NotifyPropertyChanged(NameOf(sNAM))
      End Set
   End Property

   Private Function SetBtlLHW(dBtlL As Double, dBtlH As Double, dBtlW As Double) As Boolean
      Dim OldSection As SectionXMaterial = Section
      ' verifico se ci sono già copie in grezzi
      Dim nDuploCount As Integer = 0
      If EgtDuploCount(m_BTLPartM.nPartId, nDuploCount) AndAlso nDuploCount > 0 Then
         ' se modalità travi e trave 
         If Map.refProjectVM.BTLStructureVM.nPROJTYPE = BWType.BEAM OrElse
            Map.refProjectVM.BTLStructureVM.nPROJTYPE = BWType.WALL Then
            If dBtlW <> m_BTLPartM.dBtlW OrElse dBtlH <> m_BTLPartM.dBtlH OrElse dBtlL <> m_BTLPartM.dBtlL Then
               ' se pezzo gia' in produzione
               Dim DuploList As New List(Of Integer)
               EgtDuploList(m_BTLPartM.nPartId, DuploList)
               Dim bDuploInProduction As Boolean = False
               For Each DuploId In DuploList
                  Dim nSwapItem As Integer = GDB_ID.NULL
                  Dim sSwapItem As String = String.Empty
                  EgtGetInfo(DuploId, "!LST", sSwapItem)
                  Dim LSTValues() As String = sSwapItem.Split(","c)
                  If Not IsNothing(LSTValues(LSTValues.Count - 1)) AndAlso Integer.TryParse(LSTValues(LSTValues.Count - 1), nSwapItem) AndAlso nSwapItem > 0 Then
                     Dim nMachgroupId As Integer = EgtGetParent(EgtGetParent(EgtGetParent(nSwapItem)))
                     If nMachgroupId = GDB_ID.NULL Then
                        EgtOutLog("Trovato Duplo Ghost")
                     Else
                        Dim MachGroupModel = DbControllers.m_MachGroupController.FindByMachGroupId(Map.refProjManagerVM.CurrProj.nProdId, nMachgroupId)
                        If MachGroupModel.State > ItemState.ND Then
                           bDuploInProduction = True
                           Exit For
                        End If
                     End If
                  End If
               Next
               If bDuploInProduction Then
                  MessageBox.Show("Impossible change dimension because already in production!", "", MessageBoxButton.OK, MessageBoxImage.Exclamation)
                  Return False
               End If
               ' lo impedisco
               ' avviso che tutti i pezzi verranno tolti dai grezzi e chiedo di confermare
               If MessageBox.Show(String.Format(EgtMsg(61851), nDuploCount), EgtMsg(15003), MessageBoxButton.YesNo, MessageBoxImage.Information) = MessageBoxResult.Yes Then
                  MyMachGroupPanelM.DuploSetToDelete(m_BTLPartM.nPartId)
               Else
                  ' reimposto vecchio valore
                  Return False
               End If
            End If
         End If
      End If

      ' verifico se solido attivo
      Dim bShowSolid As Boolean = Map.refShowBeamPanelVM.ShowSolid_IsChecked
      If bShowSolid Then Map.refProjectVM.BTLStructureVM.ShowSolid(GDB_ID.NULL, False, False)

      If Not EgtBeamSetPartBox(dBtlL, dBtlH, dBtlW, False) Then Return False

      ' imposto modificato per copie
      EgtDuploSetModified(m_BTLPartM.nPartId)
      ' ricalcolo tutte le feature contenute
      UpdateFeatures()
      ' setto part da ricalcolare
      ResetCalcTotalPart()
      m_BTLPartM.dBtlL = dBtlL
      m_BTLPartM.dBtlH = dBtlH
      m_BTLPartM.dBtlW = dBtlW
      ' aggiorno sezioni
      Map.refProjectVM.BTLStructureVM.UpdateSection(Section, OldSection)
      ' eventualmente ripristino solido
      If bShowSolid Then Map.refProjectVM.BTLStructureVM.ShowSolid(GDB_ID.NULL, True, False)
      EgtDraw()

      Return True
   End Function

   Private Function GetOrigFrameGroup(nPartId As Integer) As Integer
      Dim nCOP As Integer = GDB_ID.NULL
      Dim nBAS As Integer = GDB_ID.NULL
      EgtGetInfo(nPartId, "!COP", nCOP)
      EgtGetInfo(nPartId, "!BAS", nBAS)
      If nCOP = GDB_ID.NULL Then
         Return nBAS
      Else
         EgtGetInfo(nCOP, "!BAS", nBAS)
         Return nBAS
      End If
   End Function

   Public Property sL As String
      Get
         Dim nOrigGroupId As Integer = nPartId
         If Map.refMainMenuVM.SelPage = Pages.VIEW AndAlso EgtBeamGetBuildingIsOn() AndAlso Map.refShowBeamPanelVM.bShowAll Then
            nOrigGroupId = GetOrigFrameGroup(nPartId)
         End If
         Dim frBeam As New Frame3d
         EgtGetGroupGlobFrame(nOrigGroupId, frBeam)
         If IsX(frBeam.VersX(), EPS_SMALL) Then
            Return LenToString(m_BTLPartM.dBtlL, 3)
         ElseIf IsX(frBeam.VersY(), EPS_SMALL) Then
            Return LenToString(m_BTLPartM.dBtlH, 3)
         Else
            Return LenToString(m_BTLPartM.dBtlW, 3)
         End If
      End Get
      Set(value As String)
         Dim dVal As Double
         If StringToLenAdv(value, dVal, True) Then
            Dim dBtlL = m_BTLPartM.dBtlL
            Dim dBtlW = m_BTLPartM.dBtlW
            Dim dBtlH = m_BTLPartM.dBtlH
            Dim frBeam As New Frame3d
            EgtGetGroupGlobFrame(nPartId, frBeam)
            If IsX(frBeam.VersX(), EPS_SMALL) Then
               dBtlL = dVal
            ElseIf IsX(frBeam.VersY(), EPS_SMALL) Then
               dBtlH = dVal
            Else
               dBtlW = dVal
            End If
            SetBtlLHW(dBtlL, dBtlH, dBtlW)
         End If
         NotifyPropertyChanged(NameOf(sL))
         NotifyPropertyChanged(NameOf(sH))
         NotifyPropertyChanged(NameOf(sW))
         ResetCalcTotalPart()
      End Set
   End Property
   Public ReadOnly Property dL As Double
      Get
         Dim frBeam As New Frame3d
         EgtGetGroupGlobFrame(nPartId, frBeam)
         If IsX(frBeam.VersX(), EPS_SMALL) Then
            Return m_BTLPartM.dBtlL
         ElseIf IsX(frBeam.VersY(), EPS_SMALL) Then
            Return m_BTLPartM.dBtlH
         Else
            Return m_BTLPartM.dBtlW
         End If
      End Get
   End Property
   Public ReadOnly Property dBtlL As Double
      Get
         Return m_BTLPartM.dBtlL
      End Get
   End Property

   Public Property sW As String
      Get
         Dim nOrigGroupId As Integer = nPartId
         If Map.refMainMenuVM.SelPage = Pages.VIEW AndAlso EgtBeamGetBuildingIsOn() AndAlso Map.refShowBeamPanelVM.bShowAll Then
            nOrigGroupId = GetOrigFrameGroup(nPartId)
         End If
         Dim frBeam As New Frame3d
         EgtGetGroupGlobFrame(nOrigGroupId, frBeam)
         If IsY(frBeam.VersX(), EPS_SMALL) Then
            Return LenToString(m_BTLPartM.dBtlL, 3)
         ElseIf IsY(frBeam.VersY(), EPS_SMALL) Then
            Return LenToString(m_BTLPartM.dBtlH, 3)
         Else
            Return LenToString(m_BTLPartM.dBtlW, 3)
         End If
      End Get
      Set(value As String)
         Dim dVal As Double
         If StringToLenAdv(value, dVal, True) Then
            Dim dBtlL = m_BTLPartM.dBtlL
            Dim dBtlW = m_BTLPartM.dBtlW
            Dim dBtlH = m_BTLPartM.dBtlH
            Dim frBeam As New Frame3d
            EgtGetGroupGlobFrame(nPartId, frBeam)
            If IsY(frBeam.VersX(), EPS_SMALL) Then
               dBtlL = dVal
            ElseIf IsY(frBeam.VersY(), EPS_SMALL) Then
               dBtlH = dVal
            Else
               dBtlW = dVal
            End If
            SetBtlLHW(dBtlL, dBtlH, dBtlW)
         End If
         NotifyPropertyChanged(NameOf(sL))
         NotifyPropertyChanged(NameOf(sH))
         NotifyPropertyChanged(NameOf(sW))
         ResetCalcTotalPart()
      End Set
   End Property
   Public ReadOnly Property dW As Double
      Get
         Dim frBeam As New Frame3d
         EgtGetGroupGlobFrame(nPartId, frBeam)
         If IsY(frBeam.VersX(), EPS_SMALL) Then
            Return m_BTLPartM.dBtlL
         ElseIf IsY(frBeam.VersY(), EPS_SMALL) Then
            Return m_BTLPartM.dBtlH
         Else
            Return m_BTLPartM.dBtlW
         End If
      End Get
   End Property
   Public ReadOnly Property dBtlW As Double
      Get
         Return m_BTLPartM.dBtlW
      End Get
   End Property

   Public Property sH As String
      Get
         Dim nOrigGroupId As Integer = nPartId
         If Map.refMainMenuVM.SelPage = Pages.VIEW AndAlso EgtBeamGetBuildingIsOn() AndAlso Map.refShowBeamPanelVM.bShowAll Then
            nOrigGroupId = GetOrigFrameGroup(nPartId)
         End If
         Dim frBeam As New Frame3d
         EgtGetGroupGlobFrame(nOrigGroupId, frBeam)
         If IsZ(frBeam.VersX(), EPS_SMALL) Then
            Return LenToString(m_BTLPartM.dBtlL, 3)
         ElseIf IsZ(frBeam.VersY(), EPS_SMALL) Then
            Return LenToString(m_BTLPartM.dBtlH, 3)
         Else
            Return LenToString(m_BTLPartM.dBtlW, 3)
         End If
      End Get
      Set(value As String)
         Dim dVal As Double
         If StringToLenAdv(value, dVal, True) Then
            Dim dBtlL = m_BTLPartM.dBtlL
            Dim dBtlW = m_BTLPartM.dBtlW
            Dim dBtlH = m_BTLPartM.dBtlH
            Dim frBeam As New Frame3d
            EgtGetGroupGlobFrame(nPartId, frBeam)
            If IsZ(frBeam.VersX(), EPS_SMALL) Then
               dBtlL = dVal
            ElseIf IsZ(frBeam.VersY(), EPS_SMALL) Then
               dBtlH = dVal
            Else
               dBtlW = dVal
            End If
            SetBtlLHW(dBtlL, dBtlH, dBtlW)
         End If
         NotifyPropertyChanged(NameOf(sL))
         NotifyPropertyChanged(NameOf(sH))
         NotifyPropertyChanged(NameOf(sW))
         ResetCalcTotalPart()
      End Set
   End Property
   Public ReadOnly Property dH As Double
      Get
         Dim frBeam As New Frame3d
         EgtGetGroupGlobFrame(nPartId, frBeam)
         If IsZ(frBeam.VersX(), EPS_SMALL) Then
            Return m_BTLPartM.dBtlL
         ElseIf IsZ(frBeam.VersY(), EPS_SMALL) Then
            Return m_BTLPartM.dBtlH
         Else
            Return m_BTLPartM.dBtlW
         End If
      End Get
   End Property
   Public ReadOnly Property dBtlH As Double
      Get
         Return m_BTLPartM.dBtlH
      End Get
   End Property

#Region "Parametri pezzo"

   Public Property nSINGLEMEMBERNUM As Integer
      Get
         Return m_BTLPartM.nSINGLEMEMBERNUM
      End Get
      Set(value As Integer)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_SINGLEMEMBERNUM, value) Then
            m_BTLPartM.nSINGLEMEMBERNUM = value
         Else
            NotifyPropertyChanged("nSINGLEMEMBERNUM")
         End If
      End Set
   End Property

   Public Property sASSEMBLYNUM As String
      Get
         Return m_BTLPartM.sASSEMBLYNUM
      End Get
      Set(value As String)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_ASSEMBLYNUM, value) Then
            m_BTLPartM.sASSEMBLYNUM = value
         Else
            NotifyPropertyChanged("sASSEMBLYNUM")
         End If
      End Set
   End Property

   Public Property nORDERNUM As Integer
      Get
         Return m_BTLPartM.nORDERNUM
      End Get
      Set(value As Integer)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_ORDERNUM, value) Then
            m_BTLPartM.nORDERNUM = value
         Else
            NotifyPropertyChanged("nORDERNUM")
         End If
      End Set
   End Property

   Public Property sDESIGN As String
      Get
         Return m_BTLPartM.sDESIGN
      End Get
      Set(value As String)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_DESIGNATION, value) Then
            m_BTLPartM.sDESIGN = value
         Else
            NotifyPropertyChanged("sDESIGN")
         End If
      End Set
   End Property

   Public Property sANNOT As String
      Get
         Return m_BTLPartM.sANNOT
      End Get
      Set(value As String)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_ANNOTATION, value) Then
            m_BTLPartM.sANNOT = value
         Else
            NotifyPropertyChanged("sANNOT")
         End If
      End Set
   End Property

   Public Property sSTOREY As String
      Get
         Return m_BTLPartM.sSTOREY
      End Get
      Set(value As String)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_STOREY, value) Then
            m_BTLPartM.sSTOREY = value
         Else
            NotifyPropertyChanged("sSTOREY")
         End If
      End Set
   End Property

   Public Property sGROUP As String
      Get
         Return m_BTLPartM.sGROUP
      End Get
      Set(value As String)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_GROUP, value) Then
            m_BTLPartM.sGROUP = value
         Else
            NotifyPropertyChanged("sGROUP")
         End If
      End Set
   End Property

   Public Property sPACKAGE As String
      Get
         Return m_BTLPartM.sPACKAGE
      End Get
      Set(value As String)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_PACKAGE, value) Then
            m_BTLPartM.sPACKAGE = value
         Else
            NotifyPropertyChanged("sPACKAGE")
         End If
      End Set
   End Property

   Public Property sMATERIAL As String
      Get
         Return m_BTLPartM.sMATERIAL
      End Get
      Set(value As String)
         If value <> m_BTLPartM.sMATERIAL Then
            If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_MATERIAL, value) Then
               ' verifico se ci sono altri pezzi con la sezione vecchia
               Dim bOtherSection As Boolean = Map.refProjectVM.BTLStructureVM.BTLPartVMList.Any(Function(x) x IsNot Me AndAlso x.Section = Section)
               Dim OldSection As SectionXMaterial = Nothing
               If Not bOtherSection Then
                  ' recupero indice
                  OldSection = Map.refProjectVM.BTLStructureVM.SectionList.FirstOrDefault(Function(x) x = Section)
               End If
               m_BTLPartM.sMATERIAL = value
               ' aggiorno sezione
               If bOtherSection Then
                  ' se sezione nuova non presente
                  If Not Map.refProjectVM.BTLStructureVM.SectionList.Contains(Section) Then
                     ' creo nuova sezione
                     Map.refProjectVM.BTLStructureVM.SectionList.Add(Section)
                  End If
               Else
                  ' se sezione nuova gia' presente
                  If Map.refProjectVM.BTLStructureVM.SectionList.Contains(Section) Then
                     ' cancello sezione vecchia
                     Map.refProjectVM.BTLStructureVM.SectionList.Remove(OldSection)
                  Else
                     ' altrimenti la modifico
                     If Not IsNothing(OldSection) Then
                        OldSection.sMaterial.Clear()
                        OldSection.sMaterial.Add(sMATERIAL)
                     End If
                  End If
               End If
            End If
            NotifyPropertyChanged(NameOf(sMATERIAL))
         End If
      End Set
   End Property

   Public Property sTIMBERGRADE As String
      Get
         Return m_BTLPartM.sTIMBERGRADE
      End Get
      Set(value As String)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_TIMBERGRADE, value) Then
            m_BTLPartM.sTIMBERGRADE = value
         Else
            NotifyPropertyChanged("sTIMBERGRADE")
         End If
      End Set
   End Property

   Public Property sQUALITYGRADE As String
      Get
         Return m_BTLPartM.sQUALITYGRADE
      End Get
      Set(value As String)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_QUALITYGRADE, value) Then
            m_BTLPartM.sQUALITYGRADE = value
         Else
            NotifyPropertyChanged("sQUALITYGRADE")
         End If
      End Set
   End Property

   Public ReadOnly Property PartColour As Brush
      Get
         Return New SolidColorBrush(Color.FromArgb(m_BTLPartM.colCOLOR.ToColor().A,
                                                   CByte(m_BTLPartM.colCOLOR.R),
                                                   CByte(m_BTLPartM.colCOLOR.G),
                                                   CByte(m_BTLPartM.colCOLOR.B)))
      End Get
   End Property

   Public Property sCOLRGB As String
      Get
         Return m_BTLPartM.colCOLOR.R & "," &
                m_BTLPartM.colCOLOR.G & "," &
                m_BTLPartM.colCOLOR.B & "," &
                nCOLA
      End Get
      Set(value As String)
         Dim sValArray() As String = value.Split(",")
         If sValArray.Count() >= 4 Then
            m_BTLPartM.m_colCOLOR.R = Color3d.Clamp(sValArray(0), 0, 255)
            m_BTLPartM.m_colCOLOR.G = Color3d.Clamp(sValArray(1), 0, 255)
            m_BTLPartM.m_colCOLOR.B = Color3d.Clamp(sValArray(2), 0, 255)
            m_BTLPartM.m_colCOLOR.A = Color3d.Clamp(nCOLA, 0, 100)
            EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_COLOUR, m_BTLPartM.colCOLOR.ToString())
         Else
            NotifyPropertyChanged("sCOLRGB")
         End If
      End Set
   End Property

   Public Property nCOLA As Integer
      Get
         Return m_BTLPartM.colCOLOR.A
      End Get
      Set(value As Integer)
         If m_BTLPartM.colCOLOR.A <> value Then
            m_BTLPartM.m_colCOLOR.A = Color3d.Clamp(value, 0, 100)
            EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_COLOUR, m_BTLPartM.colCOLOR.ToString())
            NotifyPropertyChanged("nCOLA")
            NotifyPropertyChanged("PartColour")
         End If
      End Set
   End Property

   Public Property dPLANINGLEN As String
      Get
         Return LenToString(m_BTLPartM.dPLANINGLEN, 3)
      End Get
      Set(value As String)
         Dim dTempPlaningLen As Double
         If StringToLenAdv(value, dTempPlaningLen, True) AndAlso EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_PLANINGLENGTH, dTempPlaningLen) Then
            m_BTLPartM.dPLANINGLEN = dTempPlaningLen
         Else
            NotifyPropertyChanged("dPLANINGLEN")
         End If
      End Set
   End Property

   Public Property dSTARTOFFSET As String
      Get
         Return LenToString(m_BTLPartM.dSTARTOFFSET, 3)
      End Get
      Set(value As String)
         Dim dTempStartOffset As Double
         If StringToLenAdv(value, dTempStartOffset, True) AndAlso EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_STARTOFFSET, dTempStartOffset) Then
            m_BTLPartM.dSTARTOFFSET = dTempStartOffset
         Else
            NotifyPropertyChanged("dSTARTOFFSET")
         End If
      End Set
   End Property

   Public Property dENDOFFSET As String
      Get
         Return LenToString(m_BTLPartM.dENDOFFSET, 3)
      End Get
      Set(value As String)
         Dim dTempEndOffset As Double
         If StringToLenAdv(value, dTempEndOffset, True) AndAlso EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_ENDOFFSET, dTempEndOffset) Then
            m_BTLPartM.dENDOFFSET = dTempEndOffset
         Else
            NotifyPropertyChanged("dENDOFFSET")
         End If
      End Set
   End Property

   Public ReadOnly Property ocUID As ObservableCollection(Of Integer)
      Get
         Return m_BTLPartM.ocUID
      End Get
   End Property

   Public Property SelUID As Integer
      Get
         Return m_BTLPartM.SelUID
      End Get
      Set(value As Integer)
         If m_BTLPartM.SelUID <> value Then
            m_BTLPartM.m_refTransf = m_BTLPartM.refTransfList(value)
            m_BTLPartM.SelUID = value
            NotifyPropertyChanged("TransfOrig")
            NotifyPropertyChanged("TransfVersX")
            NotifyPropertyChanged("TransfVersY")
         Else
            NotifyPropertyChanged("SelUID")
         End If
      End Set
   End Property

   Public Property TransfOrig As String
      Get
         If SelUID >= 0 AndAlso
            SelUID < m_BTLPartM.refTransfList.Count AndAlso
            Not IsNothing(m_BTLPartM.refTransfList(SelUID)) Then
            Return LenToString(m_BTLPartM.refTransfList(SelUID).Orig().x, 3) & "," &
                   LenToString(m_BTLPartM.refTransfList(SelUID).Orig().y, 3) & "," &
                   LenToString(m_BTLPartM.refTransfList(SelUID).Orig().z, 3)
         Else
            Return Nothing
         End If
      End Get
      Set(value As String)
         Dim sValArray() As String = value.Split(",")
         Dim ptOri As New Point3d
         If sValArray.Count() >= 3 AndAlso
            StringToLenAdv(sValArray(0), ptOri.x, True) AndAlso
            StringToLenAdv(sValArray(1), ptOri.y, True) AndAlso
            StringToLenAdv(sValArray(2), ptOri.z, True) AndAlso
            m_BTLPartM.refTransf.ChangeOrigin(ptOri) Then
            EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_TRANSFORMATION & (SelUID + 1), LenToString(m_BTLPartM.refTransf.Orig.x, 3) & "," &
                                                                         LenToString(m_BTLPartM.refTransf.Orig.y, 3) & "," &
                                                                         LenToString(m_BTLPartM.refTransf.Orig.z, 3) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersX.x, 6) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersX.y, 6) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersX.z, 6) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersY.x, 6) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersY.y, 6) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersY.z, 6))
         Else
            NotifyPropertyChanged("TransfOrig")
         End If
      End Set
   End Property
   Public Property TransfVersX As String
      Get
         If SelUID >= 0 AndAlso
            SelUID < m_BTLPartM.refTransfList.Count AndAlso
            Not IsNothing(m_BTLPartM.refTransfList(SelUID)) Then
            Return DoubleToString(m_BTLPartM.refTransfList(SelUID).VersX().x, 6) & "," &
                   DoubleToString(m_BTLPartM.refTransfList(SelUID).VersX().y, 6) & "," &
                   DoubleToString(m_BTLPartM.refTransfList(SelUID).VersX().z, 6)
         Else
            Return Nothing
         End If
      End Get
      Set(value As String)
         Dim ptOri As New Point3d(m_BTLPartM.refTransf.Orig())
         Dim vtVersY As New Vector3d(m_BTLPartM.refTransf.VersY())
         Dim sValArray() As String = value.Split(",")
         Dim vtVersX As New Vector3d
         If sValArray.Count() >= 3 AndAlso
            StringToDoubleAdv(sValArray(0), vtVersX.x, True) AndAlso
            StringToDoubleAdv(sValArray(1), vtVersX.y, True) AndAlso
            StringToDoubleAdv(sValArray(2), vtVersX.z, True) AndAlso
            m_BTLPartM.refTransf.Setup(ptOri, ptOri + vtVersX, ptOri + vtVersY) Then
            EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_TRANSFORMATION & (SelUID + 1), LenToString(m_BTLPartM.refTransf.Orig.x, 3) & "," &
                                                                         LenToString(m_BTLPartM.refTransf.Orig.y, 3) & "," &
                                                                         LenToString(m_BTLPartM.refTransf.Orig.z, 3) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersX.x, 6) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersX.y, 6) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersX.z, 6) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersY.x, 6) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersY.y, 6) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersY.z, 6))
            NotifyPropertyChanged("TransfVersX")
            NotifyPropertyChanged("TransfVersY")
         Else
            NotifyPropertyChanged("TransfVersX")
         End If
      End Set
   End Property
   Public Property TransfVersY As String
      Get
         If SelUID >= 0 AndAlso
            SelUID < m_BTLPartM.refTransfList.Count AndAlso
            Not IsNothing(m_BTLPartM.refTransfList(SelUID)) Then
            Return DoubleToString(m_BTLPartM.refTransfList(SelUID).VersY().x, 6) & "," &
                   DoubleToString(m_BTLPartM.refTransfList(SelUID).VersY().y, 6) & "," &
                   DoubleToString(m_BTLPartM.refTransfList(SelUID).VersY().z, 6)
         Else
            Return Nothing
         End If
      End Get
      Set(value As String)
         Dim ptOri As New Point3d(m_BTLPartM.refTransf.Orig())
         Dim vtVersX As New Vector3d(m_BTLPartM.refTransf.VersX())
         Dim sValArray() As String = value.Split(",")
         Dim vtVersY As New Vector3d
         If sValArray.Count() >= 3 AndAlso
            StringToDoubleAdv(sValArray(0), vtVersY.x, True) AndAlso
            StringToDoubleAdv(sValArray(1), vtVersY.y, True) AndAlso
            StringToDoubleAdv(sValArray(2), vtVersY.z, True) AndAlso
            m_BTLPartM.refTransf.Setup(ptOri, ptOri + vtVersX, ptOri + vtVersY) Then
            EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_TRANSFORMATION & (SelUID + 1), LenToString(m_BTLPartM.refTransf.Orig.x, 3) & "," &
                                                                         LenToString(m_BTLPartM.refTransf.Orig.y, 3) & "," &
                                                                         LenToString(m_BTLPartM.refTransf.Orig.z, 3) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersX.x, 6) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersX.y, 6) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersX.z, 6) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersY.x, 6) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersY.y, 6) & "," &
                                                                         DoubleToString(m_BTLPartM.refTransf.VersY.z, 6))
            NotifyPropertyChanged("TransfVersX")
            NotifyPropertyChanged("TransfVersY")
         Else
            NotifyPropertyChanged("TransfVersY")
         End If
      End Set
   End Property

   Public ReadOnly Property ocCAMBERSIDE As ObservableCollection(Of Integer)
      Get
         Return m_BTLPartM.ocCAMBERSIDE
      End Get
   End Property

   Public Property SelCAMBERSIDE As Integer
      Get
         Return m_BTLPartM.SelCAMBERSIDE
      End Get
      Set(value As Integer)
         Dim sValArray() As String = CamberParams.Split(",")
         If sValArray.Count() >= 4 AndAlso
            StringToLenAdv(sValArray(0), m_BTLPartM.m_dCamberLen1, True) AndAlso
            StringToLenAdv(sValArray(1), m_BTLPartM.m_dCamberLen2, True) AndAlso
            StringToLenAdv(sValArray(2), m_BTLPartM.m_dCamberLen3, True) AndAlso
            StringToLenAdv(sValArray(3), m_BTLPartM.m_dCamberCross3, True) AndAlso
            EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_CAMBER, "SIDE: " & (value + 1) &
                                                  " P01: " & sValArray(0) &
                                                  " P02: " & sValArray(1) &
                                                  " P03: " & sValArray(2) &
                                                  " P04: " & sValArray(3)) Then
            m_BTLPartM.SelCAMBERSIDE = value
         Else
            NotifyPropertyChanged("SelCAMBERSIDE")
         End If
      End Set
   End Property

   Public Property CamberParams As String
      Get
         Return LenToString(m_BTLPartM.m_dCamberLen1, 3) & "," &
                LenToString(m_BTLPartM.m_dCamberLen2, 3) & "," &
                LenToString(m_BTLPartM.m_dCamberLen3, 3) & "," &
                LenToString(m_BTLPartM.m_dCamberCross3, 3)
      End Get
      Set(value As String)
         Dim sValArray() As String = value.Split(",")
         If sValArray.Count() >= 4 AndAlso
            StringToLenAdv(sValArray(0), m_BTLPartM.m_dCamberLen1, True) AndAlso
            StringToLenAdv(sValArray(1), m_BTLPartM.m_dCamberLen2, True) AndAlso
            StringToLenAdv(sValArray(2), m_BTLPartM.m_dCamberLen3, True) AndAlso
            StringToLenAdv(sValArray(3), m_BTLPartM.m_dCamberCross3, True) Then
            EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_CAMBER, " SIDE: " & (SelCAMBERSIDE + 1) &
                                                  " P01: " & sValArray(0) &
                                                  " P02: " & sValArray(1) &
                                                  " P03: " & sValArray(2) &
                                                  " P04: " & sValArray(3))
         Else
            NotifyPropertyChanged("CamberParams")
         End If
      End Set
   End Property

   Public ReadOnly Property ocREFSIDEFIXCLAMP As ObservableCollection(Of Object)
      Get
         Return m_BTLPartM.ocREFSIDEFIXCLAMP
      End Get
   End Property

   Public Property SelREFSIDEFIXCLAMP As Integer
      Get
         Return m_BTLPartM.SelREFSIDEFIXCLAMP
      End Get
      Set(value As Integer)
         Dim nValue As Integer = IdNameStruct.IdFromInd(value, ocREFSIDEFIXCLAMP)
         Dim sValue As String = ocREFSIDEFIXCLAMP(nValue).Name '[Enum].GetName(GetType(PartOffset_RefSideFixClamp), nValue)

         Dim sValArray() As String = PartOffsetParams.Split(",")
         If sValArray.Count() >= 4 AndAlso
            StringToLenAdv(sValArray(0), m_BTLPartM.m_dPartOffsetSide1, True) AndAlso
            StringToLenAdv(sValArray(1), m_BTLPartM.m_dPartOffsetSide2, True) AndAlso
            StringToLenAdv(sValArray(2), m_BTLPartM.m_dPartOffsetSide3, True) AndAlso
            StringToLenAdv(sValArray(3), m_BTLPartM.m_dPartOffsetSide4, True) AndAlso
            EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_PARTOFFSET, " P04: " & sValue &
                                                      " P11: " & sValArray(0) &
                                                      " P12: " & sValArray(1) &
                                                      " P13: " & sValArray(2) &
                                                      " P14: " & sValArray(3)) Then
            m_BTLPartM.SelREFSIDEFIXCLAMP = value
         Else
            NotifyPropertyChanged("SelREFSIDEFIXCLAMP")
         End If
      End Set
   End Property

   Public Property PartOffsetParams As String
      Get
         Return LenToString(m_BTLPartM.m_dPartOffsetSide1, 3) & "," &
                LenToString(m_BTLPartM.m_dPartOffsetSide2, 3) & "," &
                LenToString(m_BTLPartM.m_dPartOffsetSide3, 3) & "," &
                LenToString(m_BTLPartM.m_dPartOffsetSide4, 3)
      End Get
      Set(value As String)
         Dim nValue As Integer = IdNameStruct.IdFromInd(SelREFSIDEFIXCLAMP, ocREFSIDEFIXCLAMP)
         Dim sValue As String = ocREFSIDEFIXCLAMP(nValue).Name '[Enum].GetName(GetType(PartOffset_RefSideFixClamp), nValue)

         Dim sValArray() As String = value.Split(",")
         If sValArray.Count() >= 4 AndAlso
            StringToLenAdv(sValArray(0), m_BTLPartM.m_dPartOffsetSide1, True) AndAlso
            StringToLenAdv(sValArray(1), m_BTLPartM.m_dPartOffsetSide2, True) AndAlso
            StringToLenAdv(sValArray(2), m_BTLPartM.m_dPartOffsetSide3, True) AndAlso
            StringToLenAdv(sValArray(3), m_BTLPartM.m_dPartOffsetSide4, True) Then
            EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_PARTOFFSET, " P04: " & sValue &
                                                      " P11: " & sValArray(0) &
                                                      " P12: " & sValArray(1) &
                                                      " P13: " & sValArray(2) &
                                                      " P14: " & sValArray(3))
         Else
            NotifyPropertyChanged("PartOffsetParams")
         End If
      End Set
   End Property

   Public ReadOnly Property ocPROCESSINGQUALITY As ObservableCollection(Of Object)
      Get
         Return m_BTLPartM.ocPROCESSINGQUALITY
      End Get
   End Property

   Public Property SelPROCESSINGQUALITY As Integer
      Get
         Return m_BTLPartM.SelPROCESSINGQUALITY
      End Get
      Set(value As Integer)
         Dim nValue As Integer = IdNameStruct.IdFromInd(value, ocPROCESSINGQUALITY)
         Dim sValue As String = [Enum].GetName(GetType(ProcessingQuality), nValue)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_PROCESSINGQUALITY, sValue) Then
            m_BTLPartM.SelPROCESSINGQUALITY = value
         Else
            NotifyPropertyChanged("SelPROCESSINGQUALITY")
         End If
      End Set
   End Property

   Public ReadOnly Property ocRECESS As ObservableCollection(Of Object)
      Get
         Return m_BTLPartM.ocRECESS
      End Get
   End Property

   Public Property SelRECESS As Integer
      Get
         Return m_BTLPartM.SelRECESS
      End Get
      Set(value As Integer)
         Dim nValue As Integer = IdNameStruct.IdFromInd(value, ocRECESS)
         Dim sValue As String = [Enum].GetName(GetType(Recess), nValue)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_RECESS, sValue) Then
            m_BTLPartM.SelRECESS = value
         Else
            NotifyPropertyChanged("SelRECESS")
         End If
      End Set
   End Property

   Public ReadOnly Property ocSTOREYTYPE As ObservableCollection(Of Object)
      Get
         Return m_BTLPartM.ocSTOREYTYPE
      End Get
   End Property

   Public Property SelSTOREYTYPE As Integer
      Get
         Return m_BTLPartM.SelSTOREYTYPE
      End Get
      Set(value As Integer)
         Dim nValue As Integer = IdNameStruct.IdFromInd(value, ocSTOREYTYPE)
         Dim sValue As String = [Enum].GetName(GetType(StoreyType), nValue)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_STOREYTYPE, sValue) Then
            m_BTLPartM.SelSTOREYTYPE = value
         Else
            NotifyPropertyChanged("SelSTOREYTYPE")
         End If
      End Set
   End Property

   Public Property sELEMENTNUM As String
      Get
         Return m_BTLPartM.sELEMENTNUM
      End Get
      Set(value As String)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_ELEMENTNUM, value) Then
            m_BTLPartM.sELEMENTNUM = value
         Else
            NotifyPropertyChanged("sELEMENTNUM")
         End If
      End Set
   End Property

   Public Property nLAYER As Integer
      Get
         Return m_BTLPartM.nLAYER
      End Get
      Set(value As Integer)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_LAYER, value) Then
            m_BTLPartM.nLAYER = value
         Else
            NotifyPropertyChanged("nLAYER")
         End If
      End Set
   End Property

   Public Property sMODULENUM As String
      Get
         Return m_BTLPartM.sMODULENUM
      End Get
      Set(value As String)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_MODULENUM, value) Then
            m_BTLPartM.sMODULENUM = value
         Else
            NotifyPropertyChanged("sMODULENUM")
         End If
      End Set
   End Property

   'Protected m_sUSERATTRIBUTE As String
   'Public Property sUSERATTRIBUTE As String
   '    Get
   '        Return m_sUSERATTRIBUTE
   '    End Get
   '    Set(value As String)
   '        If EgtSetInfo(m_nPartId, BTL_PRT_USERATTRIBUTE, value) Then
   '            m_sUSERATTRIBUTE = value
   '        Else
   '            NotifyPropertyChanged("sUSERATTRIBUTE")
   '        End If
   '    End Set
   'End Property

   Public Property sCOMMENT As String
      Get
         Return m_BTLPartM.sCOMMENT
      End Get
      Set(value As String)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_COMMENT, value) Then
            m_BTLPartM.sCOMMENT = value
         Else
            NotifyPropertyChanged("sCOMMENT")
         End If
      End Set
   End Property

   Public Property GrainDirection As String
      Get
         Return DoubleToString(m_BTLPartM.refGrainDir.x, 6) & "," &
                DoubleToString(m_BTLPartM.refGrainDir.y, 6) & "," &
                DoubleToString(m_BTLPartM.refGrainDir.z, 6)
      End Get
      Set(value As String)
         Dim sValArray() As String = value.Split(",")
         Dim dX, dY, dZ As Double
         If sValArray.Count() >= 3 AndAlso
            StringToDoubleAdv(sValArray(0), dX, True) AndAlso
            StringToDoubleAdv(sValArray(1), dY, True) AndAlso
            StringToDoubleAdv(sValArray(2), dZ, True) Then
            m_BTLPartM.refGrainDir = New Vector3d(dX, dY, dZ)
            EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_GRAINDIR, sValArray(0) & "," &
                                                    sValArray(1) & "," &
                                                    sValArray(2) & ";" &
                                                    If(bGRAINDIRALIGN, 1, 0))
         Else
            NotifyPropertyChanged("GrainDirection")
         End If
      End Set
   End Property

   Public Property bGRAINDIRALIGN As Boolean
      Get
         Return m_BTLPartM.bGRAINDIRALIGN
      End Get
      Set(value As Boolean)
         Dim sValArray() As String = GrainDirection.Split(",")
         If sValArray.Count() >= 3 AndAlso
            StringToDoubleAdv(sValArray(0), m_BTLPartM.refGrainDir.x, True) AndAlso
            StringToDoubleAdv(sValArray(1), m_BTLPartM.refGrainDir.y, True) AndAlso
            StringToDoubleAdv(sValArray(2), m_BTLPartM.refGrainDir.z, True) AndAlso
            EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_GRAINDIR, sValArray(0) & "," &
                                                    sValArray(1) & "," &
                                                    sValArray(2) & ";" &
                                                    If(value, 1, 0)) Then
            m_BTLPartM.bGRAINDIRALIGN = value
            NotifyPropertyChanged("bGRAINDIRALIGN")
         End If
      End Set
   End Property

   Public ReadOnly Property ocREFSIDE As ObservableCollection(Of Integer)
      Get
         Return m_BTLPartM.ocREFSIDE
      End Get
   End Property

   Public Property SelREFSIDE As Integer
      Get
         Return m_BTLPartM.SelREFSIDE
      End Get
      Set(value As Integer)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_REFSIDE, (value + 1) & ";" & If(bREFSIDEALIGN, 1, 0)) Then
            m_BTLPartM.SelREFSIDE = value
         Else
            NotifyPropertyChanged("SelREFSIDE")
         End If
      End Set
   End Property

   Public Property bREFSIDEALIGN As Boolean
      Get
         Return m_BTLPartM.bREFSIDEALIGN
      End Get
      Set(value As Boolean)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_REFSIDE, (SelREFSIDE + 1) & ";" & If(value, 1, 0)) Then
            m_BTLPartM.bREFSIDEALIGN = value
            NotifyPropertyChanged("bREFSIDEALIGN")
         End If
      End Set
   End Property

   Public ReadOnly Property ocALIGNLOCATION As ObservableCollection(Of Object)
      Get
         Return m_BTLPartM.ocALIGNLOCATION
      End Get
   End Property

   Public Property SelALIGNLOCATION As Integer
      Get
         Return m_BTLPartM.SelALIGNLOCATION
      End Get
      Set(value As Integer)
         Dim nValue As Integer = IdNameStruct.IdFromInd(value, ocALIGNLOCATION)
         Dim sValueLoc As String = [Enum].GetName(GetType(AlignmentLocation), nValue)
         nValue = IdNameStruct.IdFromInd(SelALIGNENDTYPE, ocALIGNENDTYPE)
         Dim sValueEnd As String = [Enum].GetName(GetType(AlignmentEndtype), nValue)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_ALIGNMENT, sValueLoc & ": " & sValueEnd) Then
            m_BTLPartM.SelALIGNLOCATION = value
         Else
            NotifyPropertyChanged("SelALIGNLOCATION")
         End If
      End Set
   End Property

   Public ReadOnly Property ocALIGNENDTYPE As ObservableCollection(Of Object)
      Get
         Return m_BTLPartM.ocALIGNENDTYPE
      End Get
   End Property

   Public Property SelALIGNENDTYPE As Integer
      Get
         Return m_BTLPartM.SelALIGNENDTYPE
      End Get
      Set(value As Integer)
         Dim nValue As Integer = IdNameStruct.IdFromInd(SelALIGNLOCATION, ocALIGNLOCATION)
         Dim sValueLoc As String = [Enum].GetName(GetType(AlignmentLocation), nValue)
         nValue = IdNameStruct.IdFromInd(value, ocALIGNENDTYPE)
         Dim sValueEnd As String = [Enum].GetName(GetType(AlignmentEndtype), nValue)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_ALIGNMENT, sValueLoc & ": " & sValueEnd) Then
            m_BTLPartM.SelALIGNENDTYPE = value
         Else
            NotifyPropertyChanged("SelALIGNENDTYPE")
         End If
      End Set
   End Property

   Public ReadOnly Property ocMATERIALTYPEGRP As ObservableCollection(Of Object)
      Get
         Return m_BTLPartM.ocMATERIALTYPEGRP
      End Get
   End Property

   Public Property SelMATERIALTYPEGRP As Integer
      Get
         Return m_BTLPartM.SelMATERIALTYPEGRP
      End Get
      Set(value As Integer)
         Dim nValue As Integer = IdNameStruct.IdFromInd(value, ocMATERIALTYPEGRP)
         Dim sValue As String = ocMATERIALTYPEGRP(nValue).Name '[Enum].GetName(GetType(MaterialType), nValue)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_MATERIALTYPE, sValue & ": " & sMATERIALTYPESPEC) Then
            m_BTLPartM.SelMATERIALTYPEGRP = value
         Else
            NotifyPropertyChanged("SelMATERIALTYPEGRP")
         End If
      End Set
   End Property

   Public Property sMATERIALTYPESPEC As String
      Get
         Return m_BTLPartM.sMATERIALTYPESPEC
      End Get
      Set(value As String)
         Dim nValue As Integer = IdNameStruct.IdFromInd(SelMATERIALTYPEGRP, ocMATERIALTYPEGRP)
         Dim sValue As String = ocMATERIALTYPEGRP(nValue).Name '[Enum].GetName(GetType(MaterialType), nValue)
         If EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_MATERIALTYPE, sValue & ": " & value) Then
            m_BTLPartM.sMATERIALTYPESPEC = value
         Else
            NotifyPropertyChanged("sMATERIALTYPESPEC")
         End If
      End Set
   End Property

#End Region ' Parametri pezzo

   Public Property sCNT As String
      Get
         Return m_BTLPartM.nCNT
      End Get
      Set(value As String)
         Dim nTempCNT As Integer
         If Integer.TryParse(value, nTempCNT) AndAlso nTempCNT > 0 AndAlso EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_CNT, value) Then
            m_BTLPartM.nCNT = nTempCNT
         End If
         NotifyPropertyChanged(NameOf(sCNT))
      End Set
   End Property
   Public ReadOnly Property nCNT As Integer
      Get
         Return m_BTLPartM.nCNT
      End Get
   End Property

   Public Property sADDED As String
      Get
         Return m_BTLPartM.nADDED
      End Get
      Set(value As String)
         Dim nTempADDED As Integer
         ' verificare che non venga inserito unn numero minore di quelli gia' in prod!!!!! e dare messagio!!!
         If Integer.TryParse(value, nTempADDED) AndAlso nTempADDED >= 0 Then
            If nTempADDED >= nINPROD Then
               m_BTLPartM.nADDED = nTempADDED
            Else
               MessageBox.Show(EgtMsg(61857), "", MessageBoxButton.OK, MessageBoxImage.Warning)
            End If
         End If
         NotifyPropertyChanged(NameOf(sADDED))
      End Set
   End Property
   Public ReadOnly Property nADDED As Integer
      Get
         Return m_BTLPartM.nADDED
      End Get
   End Property

   Public ReadOnly Property nINPROD As Integer
      Get
         Dim nTotInProd As Integer = m_BTLPartM.nINPROD
         ' recupero numero di scrap
         Dim nProjId As Integer = GDB_ID.NULL
         EgtGetInfo(nPartId, PROJ, nProjId)
         Dim nScrapCnt As Integer = DbControllers.m_ProjController.getCountItemState(nProjId, nPartId, ItemState.Scrapped)
         If nScrapCnt > 0 Then nTotInProd -= nScrapCnt
         Return nTotInProd
      End Get
   End Property
   Public ReadOnly Property Foreground As SolidColorBrush
      Get
         Return If(nINPROD = nCNT + nADDED, Brushes.Green, Brushes.Black)
      End Get
   End Property
   Public ReadOnly Property FontWeight As FontWeight
      Get
         Return If(nINPROD = nCNT + nADDED, FontWeights.Bold, FontWeights.Normal)
      End Get
   End Property

   Public Property nDONE As Integer
      Get
         Dim nTotDone As Integer = 0
         ' recupero pezzi lavorati da Db
         Dim nProjId As Integer = GDB_ID.NULL
         EgtGetInfo(nPartId, PROJ, nProjId)
         Dim nDoneCnt As Integer = DbControllers.m_ProjController.getCountItemState(nProjId, nPartId, ItemState.Produced)
         Return nDoneCnt
      End Get
      Set(value As Integer)
         Dim nTempDONE As Integer
         If Integer.TryParse(value, nTempDONE) AndAlso nTempDONE > 0 AndAlso EgtSetInfo(m_BTLPartM.nPartId, BTL_PRT_DONE, value) Then
            m_BTLPartM.nDONE = nTempDONE
         End If
         NotifyPropertyChanged(NameOf(nDONE))
      End Set
   End Property

   Public ReadOnly Property Background As SolidColorBrush
      Get
         If nDONE = nCNT + nADDED Then
            Return Brushes.Yellow
         ElseIf nDONE > 0 AndAlso nDONE < nCNT + nADDED Then
            Return Brushes.Orange
         Else
            Return Brushes.White
         End If
      End Get
   End Property

   Public ReadOnly Property sINVERTED As String
      Get
         Return m_BTLPartM.nINVERTED & "°"
      End Get
   End Property

   Public ReadOnly Property nINVERTED As Integer
      Get
         Return m_BTLPartM.nINVERTED
      End Get
   End Property

   Public Property bLockInversion As Boolean
      Get
         Return m_BTLPartM.bLockInversion
      End Get
      Set(value As Boolean)
         If EgtSetInfo(nPartId, LOCK_FLIP, value) Then
            m_BTLPartM.bLockInversion = value
            NotifyPropertyChanged(NameOf(bLockInversion))
         End If
      End Set
   End Property

   Public ReadOnly Property sROTATED As String
      Get
         Return m_BTLPartM.nROTATED & "°"
      End Get
   End Property

   Public ReadOnly Property nROTATED As Integer
      Get
         Return m_BTLPartM.nROTATED
      End Get
   End Property

   Public Property bLockRotation As Boolean
      Get
         Return m_BTLPartM.bLockRotation
      End Get
      Set(value As Boolean)
         If EgtSetInfo(nPartId, LOCK_ROT, value) Then
            m_BTLPartM.bLockRotation = value
            NotifyPropertyChanged(NameOf(bLockRotation))
         End If
      End Set
   End Property

   Public ReadOnly Property nCALC_ERR As Integer
      Get
         Return m_BTLPartM.nCALC_ERR
      End Get
   End Property

   Public ReadOnly Property nCALC_FALL As Integer
      Get
         Return m_BTLPartM.nCALC_FALL
      End Get
   End Property

   Public ReadOnly Property sCALC_MSG As String
      Get
         NotifyPropertyChanged(NameOf(CALC_MSG_Visibility))
         Return m_BTLPartM.sCALC_MSG
      End Get
   End Property

   Public Property nCALC_ROT As Integer
      Get
         Return m_BTLPartM.nCALC_ROT
      End Get
      Set(value As Integer)
         m_BTLPartM.nCALC_ROT = value
      End Set
   End Property

   Public Property nCALC_TIME As Integer
      Get
         Return m_BTLPartM.nCALC_TIME
      End Get
      Set(value As Integer)
         m_BTLPartM.nCALC_TIME = value
      End Set
   End Property

   Public Property nGlobalState As CalcStates
      Get
         Return m_BTLPartM.nGlobalState
      End Get
      Set(value As CalcStates)
         m_BTLPartM.nGlobalState = value
      End Set
   End Property

   Public ReadOnly Property nFeaturesGlobalState As CalcStates
      Get
         Return m_BTLPartM.nFeaturesGlobalState
      End Get
   End Property

   Public Property nState As CalcStates
      Get
         Return m_BTLPartM.nState
      End Get
      Set(value As CalcStates)
         m_BTLPartM.nState = value
      End Set
   End Property

   Public ReadOnly Property Calc_BorderBrush As SolidColorBrush
      Get
         If Not m_BTLPartM.bDO Then Return Brushes.Aqua
         Select Case m_BTLPartM.nGlobalState
            Case CalcStates.ERROR_, CalcStates.COLLISION
               Return Brushes.Red
            Case CalcStates.WARNING
               Return Brushes.Orange
            Case CalcStates.INFO, CalcStates.OK
               Return Brushes.Green
            Case CalcStates.NOTCALCULATED
               Return Brushes.LightGray
            Case Else
               Return Brushes.Red
         End Select
      End Get
   End Property

   Public ReadOnly Property CALC_ROT_Visibility As Visibility
      Get
         Return If(m_BTLPartM.nCALC_ROT <> 0, Visibility.Visible, Visibility.Collapsed)
      End Get
   End Property

   Public ReadOnly Property CALC_FALL_Visibility As Visibility
      Get
         Return If(m_BTLPartM.nCALC_FALL <> 0, Visibility.Visible, Visibility.Collapsed)
      End Get
   End Property

   Public ReadOnly Property CALC_ERR_Letter As String
      Get
         Select Case m_BTLPartM.m_nGlobalState
            Case CalcStates.COLLISION
               Return "c"
            Case CalcStates.ERROR_
               Return "e"
            Case CalcStates.WARNING
               Return "w"
            Case CalcStates.INFO
               Return "i"
            Case Else
               Return ""
         End Select
      End Get
   End Property

   Public ReadOnly Property CALC_ERR_Foreground As SolidColorBrush
      Get
         Select Case m_BTLPartM.m_nGlobalState
            Case CalcStates.ERROR_, CalcStates.COLLISION
               Return Brushes.Red
            Case CalcStates.WARNING
               Return Brushes.Orange
            Case CalcStates.INFO
               Return Brushes.Green
            Case Else
               Return Brushes.Red
         End Select
      End Get
   End Property

   Public ReadOnly Property CALC_MSG_Visibility As Visibility
      Get
         Return If(String.IsNullOrWhiteSpace(m_BTLPartM.sCALC_MSG), Visibility.Collapsed, Visibility.Visible)
      End Get
   End Property

   Public ReadOnly Property Section As SectionXMaterial
      Get
         Dim nOrigGroupId As Integer = nPartId
         If Map.refMainMenuVM.SelPage = Pages.VIEW AndAlso EgtBeamGetBuildingIsOn() AndAlso Map.refShowBeamPanelVM.bShowAll Then
            nOrigGroupId = GetOrigFrameGroup(nPartId)
         End If
         Dim frBeam As New Frame3d
         EgtGetGroupGlobFrame(nOrigGroupId, frBeam)
         Dim dL As Double
         If IsX(frBeam.VersX(), EPS_SMALL) Then
            dL = m_BTLPartM.dBtlL
         ElseIf IsX(frBeam.VersY(), EPS_SMALL) Then
            dL = m_BTLPartM.dBtlH
         Else
            dL = m_BTLPartM.dBtlW
         End If
         Dim dW As Double
         If IsY(frBeam.VersX(), EPS_SMALL) Then
            dW = m_BTLPartM.dBtlL
         ElseIf IsY(frBeam.VersY(), EPS_SMALL) Then
            dW = m_BTLPartM.dBtlH
         Else
            dW = m_BTLPartM.dBtlW
         End If
         Dim dH As Double
         If IsZ(frBeam.VersX(), EPS_SMALL) Then
            dH = m_BTLPartM.dBtlL
         ElseIf IsZ(frBeam.VersY(), EPS_SMALL) Then
            dH = m_BTLPartM.dBtlH
         Else
            dH = m_BTLPartM.dBtlW
         End If
         Return New SectionXMaterial(dW, dH, dL, m_BTLPartM.sMATERIAL)
      End Get
   End Property

   Public Property dUnitVolume As Double
      Get
         Return BTLPartM.dVolume
      End Get
      Set(value As Double)
         If EgtSetInfo(nPartId, BTL_PRT_VOLUME, value) Then
            m_BTLPartM.dVolume = value
         Else
            NotifyPropertyChanged(NameOf(dUnitVolume))
         End If
      End Set
   End Property

   Public ReadOnly Property sUnitVolume As String
      Get
         Return If(EgtUiUnitsAreMM(), DoubleToString(dUnitVolume / 1000000000, 3), DoubleToString(dUnitVolume * (12 / ONEINCH), 3))
      End Get
   End Property

   Public ReadOnly Property sTotVolume As String
      Get
         Return If(EgtUiUnitsAreMM(), DoubleToString(dUnitVolume * (nCNT + nADDED) / 1000000000, 3), DoubleToString(dUnitVolume * (12 / ONEINCH) * nCNT, 3))
      End Get
   End Property

   Public ReadOnly Property sUnitTime As String
      Get
         Return TimeSpan.FromSeconds(nCALC_TIME).ToString()
      End Get
   End Property

   Public ReadOnly Property sTotTime As String
      Get
         Return TimeSpan.FromSeconds(nCALC_TIME * (nCNT + nADDED)).ToString()
      End Get
   End Property

   Public Property bDOALL As Boolean?
      Get
         If BTLFeatureVMList.Count = 0 Then Return False
         Dim bTemp As Boolean = BTLFeatureVMList(0).bDO
         For FeatureIndex = 1 To BTLFeatureVMList.Count - 1
            If BTLFeatureVMList(FeatureIndex).bDO <> bTemp Then Return Nothing
         Next
         Return bTemp
      End Get
      Set(value As Boolean?)
         If BTLFeatureVMList.Count = 0 Then
            NotifyPropertyChanged(NameOf(bDOALL))
            Return
         End If
         ' imposto modalita' update multiplo
         BTLFeatureVM.bDO_MultipleUpdate = True
         For FeatureIndex = 0 To BTLFeatureVMList.Count - 1
            If FeatureIndex = BTLFeatureVMList.Count - 1 Then
               ' reset modalita' update multiplo
               BTLFeatureVM.bDO_MultipleUpdate = False
            End If
            Dim Feature As BTLFeatureVM = BTLFeatureVMList(FeatureIndex)
            Feature.bDO = value
         Next
      End Set
   End Property

   ' lista delle feature del pezzo
   Private m_BTLFeatureVMList_ViewSource As CollectionViewSource = Nothing
   Private m_BTLFeatureVMList_View As ListCollectionView = Nothing
   Public m_BTLFeatureVMList As ObservableCollection(Of BTLFeatureVM)
   Public Property BTLFeatureVMList As ObservableCollection(Of BTLFeatureVM)
      Get
         Return m_BTLFeatureVMList
      End Get
      Set(value As ObservableCollection(Of BTLFeatureVM))
         m_BTLFeatureVMList = value
      End Set
   End Property
   Public ReadOnly Property BTLFeatureVMList_View As ListCollectionView
      Get
         Return m_BTLFeatureVMList_View
      End Get
   End Property

   Public m_SelBTLFeatureVM As BTLFeatureVM
   Public Property SelBTLFeatureVM As BTLFeatureVM
      Get
         Return m_SelBTLFeatureVM
      End Get
      Set(value As BTLFeatureVM)
         m_SelBTLFeatureVM = value
         If Map.refMainMenuVM.SelPage = Pages.VIEW Then
            If Not IsNothing(m_SelBTLFeatureVM) Then
               DirectCast(m_SelBTLFeatureVM, BTLFeatureVM).SelGeomFeature()
               ' imposto path disegno da mostrare in BottomPanel
               Map.refBottomPanelVM.SetCurrDraw(DirectCast(m_SelBTLFeatureVM, BTLFeatureVM).sDrawPath)
               ' seleziono pagina BottomPanel
               Map.refBottomPanelVM.SetSelPartFeatureTab(BottomPanelVM.PartFeatureTab.FEATURE)
               ' deseleziono i parametri
               If Not IsNothing(SelBTLFeatureVM.SelPBTLParam) Then SelBTLFeatureVM.SelPBTLParam = Nothing
               ' rinfresco bottoni freecontour
               m_SelBTLFeatureVM.RefreshFCMBtnVisibility()
               ' aggiorno stato abilitazione del bottone modifica free contour
               Map.refFeatureManagerVM.SetEditIsEnabled()
               Map.refFeatureManagerVM.NotifyPropertyChanged(NameOf(Map.refFeatureManagerVM.Priority_Visibility))
            Else
               EgtDeselectAll()
            End If
            Map.refLeftPanelVM.FeatureSelectionChanged()
         End If
         EgtDraw()
         NotifyPropertyChanged(NameOf(SelBTLFeatureVM))
      End Set
   End Property

   Private m_Calc_PartEnd As Boolean = False
   Public ReadOnly Property Calc_PartEnd As Boolean
      Get
         Return m_Calc_PartEnd
      End Get
   End Property

   ' Definizione comandi
   Private m_cmdInvert As ICommand
   Private m_cmdBackRotation As ICommand
   Private m_cmdForwardRotation As ICommand
   Private m_cmdXRotation As ICommand
   Private m_cmdPartColour As ICommand

#Region "MESSAGES"

   Public ReadOnly Property DO_Msg As String
      Get
         Return EgtMsg(61602)
      End Get
   End Property

   Public ReadOnly Property NAM_Msg As String
      Get
         Return EgtMsg(61603)
      End Get
   End Property

#End Region

#End Region    ' FIELDS & PROPERTIES

#Region "CONSTRUCTOR"

   Sub New(BTLPartM As BTLPartM, BTLStructureM As BTLStructureM)
      m_BTLPartM = BTLPartM
      AddHandler m_BTLPartM.BTLFeatureAdded, AddressOf OnBTLFeatureAdded
      m_BTLStructureM = BTLStructureM
      CreateBTLFeatureVMList()
      m_BTLFeatureVMList_ViewSource = New CollectionViewSource With {.Source = m_BTLFeatureVMList}
      m_BTLFeatureVMList_View = m_BTLFeatureVMList_ViewSource.View
      m_BTLFeatureVMList_View.CustomSort = New FeatureSorter
      m_BTLFeatureVMList_View.Filter = AddressOf FeatureFilter
      ' Aggiorno check DOALL
      NotifyPropertyChanged(NameOf(bDOALL))
      ' Aggiorno stato da stati feature
      CalcGlobalUpdate()
      NotifyPropertyChanged(NameOf(CALC_FALL_Visibility))
   End Sub

   Private Function FeatureFilter(Feature As Object) As Boolean
      Return BTLFeatureVMList.IndexOf(Feature) < 30
   End Function

   Public Class FeatureSorter
      Implements IComparer

      Public Function Compare(x As Object, y As Object) As Integer Implements IComparer.Compare
         Dim FeatureX As BTLFeatureVM = x
         Dim FeatureY As BTLFeatureVM = y
         Return -FeatureX.nCALC_ERR.CompareTo(FeatureY.nCALC_ERR)
      End Function

   End Class

#End Region    ' CONSTRUCTOR

#Region "METHODS"

   Private Sub CreateBTLFeatureVMList()
      Dim all As List(Of BTLFeatureVM) = (From BTLFeatureM In m_BTLPartM.GetBTLFeatures()
                                          Select New BTLFeatureVM(BTLFeatureM, m_BTLPartM)).ToList()

      For Each BTLFeatureVM As BTLFeatureVM In all
         AddHandler BTLFeatureVM.PropertyChanged, AddressOf OnBTLFeatureVMPropertyChanged
         For Each BTLParamVM As BTLParamVM In BTLFeatureVM.PBTLParamVMList
            AddHandler BTLParamVM.PropertyChanged, AddressOf OnBTLPParamVMPropertyChanged
         Next
         AddHandler BTLFeatureVM.PBTLParamVMList.CollectionChanged, AddressOf OnBTLPParamVMListChanged
         For Each BTLParamVM As BTLParamVM In BTLFeatureVM.QBTLParamVMList
            AddHandler BTLParamVM.PropertyChanged, AddressOf OnBTLQParamVMPropertyChanged
         Next
         AddHandler BTLFeatureVM.QBTLParamVMList.CollectionChanged, AddressOf OnBTLQParamVMListChanged
      Next

      m_BTLFeatureVMList = New ObservableCollection(Of BTLFeatureVM)(all)
      AddHandler m_BTLFeatureVMList.CollectionChanged, AddressOf OnBTLFeatureVMListChanged
   End Sub

   Public Sub Rotation(IsPositive As Boolean, SelectedMachineType As MachineType, Optional bRedraw As Boolean = True, Optional dAng As Double = 90, Optional bVerifyDuplo As Boolean = True)
      Dim OldSection As SectionXMaterial = Section
      If m_BTLPartM.Rotation(IsPositive, SelectedMachineType, bRedraw, dAng) Then
         ' aggiorno visualizzazione dimensioni
         NotifyPropertyChanged(NameOf(sW))
         NotifyPropertyChanged(NameOf(sH))
         NotifyPropertyChanged(NameOf(sL))
         ' setto part e tutte le feature da ricalcolare
         ResetCalcTotalPart()
         ' aggiorno sezioni
         Map.refProjectVM.BTLStructureVM.UpdateSection(Section, OldSection)
      End If
      NotifyPropertyChanged(NameOf(sROTATED))
   End Sub

   ' funzione che aggiorna lo stato e gli errori dopo calcolo
   Friend Sub CalcPartUpdate(ERR As Integer, ROT As Integer, MSG As String)
      EgtSetInfo(nPartId, ITG_PROJ_ERR, ERR, True)
      EgtSetInfo(nPartId, ITG_PROJ_MSG, MSG, True)
      EgtSetInfo(nPartId, ITG_PROJ_ROT, ROT, True)
      m_BTLPartM.nCALC_ERR = ERR
      m_BTLPartM.nCALC_ROT = ROT
      m_BTLPartM.sCALC_MSG = MSG
      Select Case ERR
         Case 0
            nState = CalcStates.OK
         Case 22
            nState = CalcStates.COLLISION
         Case 17, 19
            nState = CalcStates.WARNING
         Case < 0
            nState = CalcStates.INFO
         Case > 0
            nState = CalcStates.ERROR_
      End Select
      NotifyPropertyChanged(NameOf(Calc_BorderBrush))
      NotifyPropertyChanged(NameOf(CALC_ERR_Letter))
      NotifyPropertyChanged(NameOf(CALC_ERR_Foreground))
      NotifyPropertyChanged(NameOf(sCALC_MSG))
   End Sub

   Friend Sub ResetCalcPart()
      EgtRemoveInfo(nPartId, ITG_PROJ_ERR)
      EgtRemoveInfo(nPartId, ITG_PROJ_MSG)
      EgtRemoveInfo(nPartId, ITG_PROJ_ROT)
      EgtRemoveInfo(nPartId, ITG_PROJ_FALL)
      m_BTLPartM.nGlobalState = CalcStates.NOTCALCULATED
      m_BTLPartM.nState = CalcStates.NOTCALCULATED
      m_BTLPartM.nCALC_GlobalERR = 0
      m_BTLPartM.nCALC_ERR = 0
      m_BTLPartM.nCALC_ROT = 0
      m_BTLPartM.nCALC_FALL = 0
      m_BTLPartM.sCALC_MSG = ""
      ' aggiorno lista feature in iconcina calcolo
      BTLFeatureVMList_View.Refresh()
      NotifyPropertyChanged(NameOf(Calc_BorderBrush))
      NotifyPropertyChanged(NameOf(CALC_FALL_Visibility))
      NotifyPropertyChanged(NameOf(CALC_ROT_Visibility))
      NotifyPropertyChanged(NameOf(CALC_ERR_Letter))
      NotifyPropertyChanged(NameOf(CALC_ERR_Foreground))
      NotifyPropertyChanged(NameOf(sCALC_MSG))
   End Sub

   Friend Sub ResetCalcTotalPart()
      ResetCalcPart()
      For Each Feature In m_BTLFeatureVMList
         Feature.ResetCalcFeature()
      Next
   End Sub

   Friend Sub CalcFallUpdate(FALL As Integer)
      EgtSetInfo(nPartId, ITG_PROJ_FALL, FALL, True)
      m_BTLPartM.nCALC_FALL = FALL
      NotifyPropertyChanged(NameOf(CALC_FALL_Visibility))
   End Sub

   Friend Sub CalcTimeUpdate(TIME As Integer)
      EgtSetInfo(nPartId, ITG_PROJ_TIME, TIME, True)
      m_BTLPartM.nCALC_TIME = TIME
      NotifyPropertyChanged(NameOf(sTotTime))
      NotifyPropertyChanged(NameOf(sUnitTime))
   End Sub

   ' funzione che aggiorna lo stato e gli errori dopo calcolo
   Friend Sub CalcGlobalUpdate(Optional bFeatureFirst As Boolean = False)
      m_BTLPartM.nCALC_GlobalERR = nCALC_ERR
      m_BTLPartM.nGlobalState = nState
      m_BTLPartM.nFeaturesGlobalState = CalcStates.NOTCALCULATED
      If nState > CalcStates.NOTCALCULATED Then
         For Each Feature In BTLFeatureVMList
            If Not Feature.bDO And Not bFeatureFirst Then
               If Feature.nState = CalcStates.COLLISION AndAlso Feature.nState > m_BTLPartM.nGlobalState Then
                  m_BTLPartM.nGlobalState = Feature.nState
                  m_BTLPartM.nCALC_GlobalERR = Feature.nCALC_ERR
               Else
                  Continue For
               End If
            End If
            If ((Feature.nState = CalcStates.NOTCALCULATED And nState < CalcStates.WARNING) Or Not Feature.bDO) And bFeatureFirst Then
               m_BTLPartM.nGlobalState = Feature.nState
               m_BTLPartM.nCALC_GlobalERR = Feature.nCALC_ERR
               EgtRemoveInfo(nPartId, ITG_PROJ_ERR)
               Exit For
            ElseIf Feature.nState = CalcStates.NOTCALCULATED And nState < CalcStates.WARNING Then
               m_BTLPartM.nGlobalState = Feature.nState
               m_BTLPartM.nCALC_GlobalERR = Feature.nCALC_ERR
               EgtRemoveInfo(nPartId, ITG_PROJ_ERR)
               Exit For
            ElseIf Feature.nState > m_BTLPartM.nGlobalState Then
               m_BTLPartM.nGlobalState = Feature.nState
               m_BTLPartM.nCALC_GlobalERR = Feature.nCALC_ERR
            End If
            If Feature.nState > m_BTLPartM.nFeaturesGlobalState Then
               m_BTLPartM.nFeaturesGlobalState = Feature.nState
            End If
            If Feature.nCALC_ROT <> 0 Then
               m_BTLPartM.m_nCALC_ROT = Feature.nCALC_ROT
            End If
         Next
         If m_BTLPartM.nGlobalState = CalcStates.NOTCALCULATED Then
            EgtRemoveInfo(nPartId, ITG_PROJ_ERR)
         End If
      End If
      NotifyPropertyChanged(NameOf(Calc_BorderBrush))
      NotifyPropertyChanged(NameOf(CALC_ROT_Visibility))
      NotifyPropertyChanged(NameOf(CALC_ERR_Letter))
      NotifyPropertyChanged(NameOf(CALC_ERR_Foreground))
      NotifyPropertyChanged(NameOf(sCALC_MSG))
      m_Calc_PartEnd = True
   End Sub

   Friend Sub ResetCalcPartEnd()
      m_Calc_PartEnd = False
   End Sub

   Public Function Copy() As BTLPartM
      ' creo nuovo part
      Dim nNewPartId As Integer = EgtBeamCreatePart()
      If nNewPartId = GDB_ID.NULL Then Return Nothing
      ' scrivo info proj
      EgtSetInfo(nNewPartId, BTL_PRT_PROJ, Map.refProjManagerVM.CurrProj.nProjId)
      EgtBeamSetPartProdNbr(m_BTLStructureM.NewPDN())
      EgtBeamSetPartName(m_BTLPartM.sNAM)
      EgtBeamSetPartCount(m_BTLPartM.nCNT)
      EgtBeamSetPartBox(m_BTLPartM.dBtlL, m_BTLPartM.dBtlH, m_BTLPartM.dBtlW)

      EgtSetInfo(nNewPartId, BTL_PRT_DO, m_BTLPartM.bDO)
      EgtSetInfo(nNewPartId, BTL_PRT_CNT, m_BTLPartM.m_nCNT)
      EgtSetInfo(nNewPartId, BTL_PRT_ADDED, m_BTLPartM.m_nADDED)
      EgtSetInfo(nNewPartId, BTL_PRT_ASSEMBLYNUM, m_BTLPartM.m_sASSEMBLYNUM)
      EgtSetInfo(nNewPartId, BTL_PRT_ORDERNUM, m_BTLPartM.m_nORDERNUM)
      EgtSetInfo(nNewPartId, BTL_PRT_DESIGNATION, m_BTLPartM.m_sDESIGN)
      EgtSetInfo(nNewPartId, BTL_PRT_ANNOTATION, m_BTLPartM.m_sANNOT)
      EgtSetInfo(nNewPartId, BTL_PRT_STOREY, m_BTLPartM.m_sSTOREY)
      EgtSetInfo(nNewPartId, BTL_PRT_GROUP, m_BTLPartM.m_sGROUP)
      EgtSetInfo(nNewPartId, BTL_PRT_PACKAGE, m_BTLPartM.m_sPACKAGE)
      EgtSetInfo(nNewPartId, BTL_PRT_TIMBERGRADE, m_BTLPartM.m_sTIMBERGRADE)
      EgtSetInfo(nNewPartId, BTL_PRT_QUALITYGRADE, m_BTLPartM.m_sQUALITYGRADE)
      EgtSetInfo(nNewPartId, BTL_PRT_COLOUR, m_BTLPartM.m_colCOLOR.ToString())
      EgtSetInfo(nNewPartId, BTL_PRT_PLANINGLENGTH, m_BTLPartM.m_dPLANINGLEN)
      EgtSetInfo(nNewPartId, BTL_PRT_STARTOFFSET, m_BTLPartM.m_dSTARTOFFSET)
      EgtSetInfo(nNewPartId, BTL_PRT_ENDOFFSET, m_BTLPartM.m_dENDOFFSET)
      Dim ind As Integer = 1
      For Each UIDItem In m_BTLPartM.m_ocUID
         EgtSetInfo(nNewPartId, BTL_PRT_UID & ind, UIDItem)
         EgtSetInfo(nNewPartId, BTL_PRT_TRANSFORMATION & ind, LenToString(m_BTLPartM.refTransf.Orig.x, 3) & "," &
                                                              LenToString(m_BTLPartM.refTransf.Orig.y, 3) & "," &
                                                              LenToString(m_BTLPartM.refTransf.Orig.z, 3) & "," &
                                                              DoubleToString(m_BTLPartM.refTransf.VersX.x, 6) & "," &
                                                              DoubleToString(m_BTLPartM.refTransf.VersX.y, 6) & "," &
                                                              DoubleToString(m_BTLPartM.refTransf.VersX.z, 6) & "," &
                                                              DoubleToString(m_BTLPartM.refTransf.VersY.x, 6) & "," &
                                                              DoubleToString(m_BTLPartM.refTransf.VersY.y, 6) & "," &
                                                              DoubleToString(m_BTLPartM.refTransf.VersY.z, 6))
      Next
      EgtSetInfo(nNewPartId, BTL_PRT_CAMBER, " SIDE: " & (m_BTLPartM.SelCAMBERSIDE + 1) &
                                             " P01: " & LenToString(m_BTLPartM.m_dCamberLen1, 3) &
                                             " P02: " & LenToString(m_BTLPartM.m_dCamberLen2, 3) &
                                             " P03: " & LenToString(m_BTLPartM.m_dCamberLen3, 3) &
                                             " P04: " & LenToString(m_BTLPartM.m_dCamberCross3, 3))
      Dim nValue As Integer = IdNameStruct.IdFromInd(m_BTLPartM.SelREFSIDEFIXCLAMP, ocREFSIDEFIXCLAMP)
      Dim sValue As String = ocREFSIDEFIXCLAMP(nValue).Name
      EgtSetInfo(nNewPartId, BTL_PRT_PARTOFFSET, " P04: " & sValue &
                                                 " P11: " & m_BTLPartM.m_dPartOffsetSide1 &
                                                 " P12: " & m_BTLPartM.m_dPartOffsetSide2 &
                                                 " P13: " & m_BTLPartM.m_dPartOffsetSide3 &
                                                 " P14: " & m_BTLPartM.m_dPartOffsetSide4)
      If m_BTLPartM.m_SelPROCESSINGQUALITY > -1 Then
         nValue = IdNameStruct.IdFromInd(m_BTLPartM.m_SelPROCESSINGQUALITY, ocPROCESSINGQUALITY)
         sValue = [Enum].GetName(GetType(ProcessingQuality), nValue)
         EgtSetInfo(nNewPartId, BTL_PRT_PROCESSINGQUALITY, sValue)
      End If
      If m_BTLPartM.m_SelRECESS > -1 Then
         nValue = IdNameStruct.IdFromInd(m_BTLPartM.m_SelRECESS, ocRECESS)
         sValue = [Enum].GetName(GetType(Recess), nValue)
         EgtSetInfo(nNewPartId, BTL_PRT_RECESS, sValue)
      End If
      If m_BTLPartM.m_SelSTOREYTYPE > -1 Then
         nValue = IdNameStruct.IdFromInd(m_BTLPartM.m_SelSTOREYTYPE, ocSTOREYTYPE)
         sValue = [Enum].GetName(GetType(StoreyType), nValue)
         EgtSetInfo(nNewPartId, BTL_PRT_STOREYTYPE, sValue)
      End If
      EgtSetInfo(nNewPartId, BTL_PRT_ELEMENTNUM, m_BTLPartM.m_sELEMENTNUM)
      EgtSetInfo(nNewPartId, BTL_PRT_LAYER, m_BTLPartM.m_nLAYER)
      EgtSetInfo(nNewPartId, BTL_PRT_MODULENUM, m_BTLPartM.m_sMODULENUM)
      'EgtSetInfo(nNewPartId, BTL_PRT_USERATTRIBUTE, m_sUSERATTRIBUTE)
      EgtSetInfo(nNewPartId, BTL_PRT_COMMENT, m_BTLPartM.m_sCOMMENT)
      EgtSetInfo(nNewPartId, BTL_PRT_GRAINDIR, m_BTLPartM.refGrainDir.x & "," &
                                               m_BTLPartM.refGrainDir.y & "," &
                                               m_BTLPartM.refGrainDir.z & ";" &
                                               If(m_BTLPartM.bGRAINDIRALIGN, 1, 0))
      EgtSetInfo(nNewPartId, BTL_PRT_REFSIDE, (m_BTLPartM.m_SelREFSIDE + 1) & ";" & If(m_BTLPartM.bREFSIDEALIGN, 1, 0))

      nValue = IdNameStruct.IdFromInd(m_BTLPartM.SelALIGNLOCATION, ocALIGNLOCATION)
      Dim sValueLoc As String = [Enum].GetName(GetType(AlignmentLocation), nValue)
      nValue = IdNameStruct.IdFromInd(SelALIGNENDTYPE, ocALIGNENDTYPE)
      Dim sValueEnd As String = [Enum].GetName(GetType(AlignmentEndtype), nValue)
      EgtSetInfo(nNewPartId, BTL_PRT_ALIGNMENT, sValueLoc & ": " & sValueEnd)

      nValue = IdNameStruct.IdFromInd(m_BTLPartM.SelMATERIALTYPEGRP, ocMATERIALTYPEGRP)
      sValue = ocMATERIALTYPEGRP(nValue).Name
      EgtSetInfo(nNewPartId, BTL_PRT_MATERIALTYPE, sValue & ": " & m_BTLPartM.sMATERIALTYPESPEC)

      EgtSetInfo(nNewPartId, BTL_PRT_ROTATED, m_BTLPartM.nROTATED)
      EgtSetInfo(nNewPartId, BTL_PRT_INVERTED, m_BTLPartM.nINVERTED)
      EgtSetInfo(nNewPartId, BTL_PRT_MATERIAL, m_BTLPartM.m_sMATERIAL)

      ' aggiungo dati pezzo
      Dim NewPart As BTLPartM = BTLPartM.CreateBTLPart(nNewPartId)
      'aggiungo tutte le sue feature
      For Each Feature In m_BTLFeatureVMList
         Feature.Copy(NewPart)
      Next
      ' recupero box del pezzo
      Dim b3Part As New BBox3d
      EgtGetBBoxGlob(nNewPartId, GDB_BB.STANDARD, b3Part)
      ' ripristino le rotazioni di ROT e FLIP
      If Map.refProjectVM.BTLStructureVM.nPROJTYPE = BWType.BEAM Then
         EgtRotate(nNewPartId, b3Part.Center, Vector3d.X_AX, nROTATED)
         EgtRotate(nNewPartId, b3Part.Center, Vector3d.Z_AX, nINVERTED)
      Else
         EgtRotate(nNewPartId, b3Part.Center, -Vector3d.Z_AX, nROTATED)
         EgtRotate(nNewPartId, b3Part.Center, Vector3d.X_AX, nINVERTED)
      End If
      ' aggiungo pezzo alla lista
      m_BTLStructureM.AddBTLPart(NewPart)
      Return NewPart
   End Function

   ' funzione che aggiorna tutte le feature dopo modifica dimensioni pezzo
   Private Sub UpdateFeatures()
      ' ricalcolo tutte le feature contenute
      For Each Feature In m_BTLFeatureVMList
         Feature.BTLFeatureM.UpdateParams(False)
         ' setto feature da ricalcolare
         Feature.ResetCalcFeature()
      Next
      EgtBeamUpdatePart()
   End Sub

   Friend Sub AddNewPartToAdded(Optional PartQty As Integer = 1)
      m_BTLPartM.nADDED += PartQty
      NotifyPropertyChanged(NameOf(sADDED))
   End Sub

   'Friend Sub AddPartToProd(Optional PartQty As Integer = 1)
   '   m_BTLPartM.nINPROD += PartQty
   '   NotifyPropertyChanged(NameOf(sADDED))
   'End Sub

   Friend Sub RefreshPartInProd()
      NotifyPropertyChanged(NameOf(nINPROD))
      NotifyPropertyChanged(NameOf(Foreground))
      NotifyPropertyChanged(NameOf(FontWeight))
   End Sub

   Friend Function CanAddPartToCount(Optional Qty As Integer = 1, Optional ByRef Added As Integer = 0) As Boolean
      ' verifico se ci sono pezzi da aggiungere
      Added = Math.Min(Qty, m_BTLPartM.nCNT + m_BTLPartM.nADDED - m_BTLPartM.nINPROD)
      Return Qty = Added
   End Function

   ' funzione che dato l'Id di un Part(Duplo) restituisce il BTLPart di origine
   Friend Shared Function RetrieveBTLPartFromPart(nPartId As Integer) As BTLPartVM
      Dim BTLPartId As Integer = MyMachGroupPanelM.DuploGetOriginal(nPartId)
      Return Map.refProjectVM.BTLStructureVM.BTLPartVMList.FirstOrDefault(Function(x) x.nPartId = BTLPartId)
   End Function

   ' funzione che calcola il volume del pezzo
   Friend Sub CalcBTLPartVolume()
      Select Case Map.refProjectVM.BTLStructureVM.nPROJTYPE
         Case MachineType.BEAM
            dUnitVolume = dBtlH * dBtlW * dBtlL
         Case MachineType.WALL
            Dim nOutlineLayerId As Integer = EgtGetFirstNameInGroup(nPartId, OUTLINE)
            ' cerco Id feature
            Dim nOutlineFeatureId = GDB_ID.NULL
            For Each Feature In BTLFeatureVMList
               If Feature.nPRC = 251 Then nOutlineFeatureId = Feature.nFeatureId
               Exit For
            Next
            ' recupero AuxId
            If nOutlineFeatureId <> GDB_ID.NULL Then
               Dim nAuxId As Integer = 0
               If EgtGetInfo(nOutlineFeatureId, BTL_FTR_AUXID, nAuxId) Then
                  nOutlineFeatureId += nAuxId
               End If
               ' calcolo area 
               Dim dArea As Double = 0
               Dim vtN As New Vector3d
               Dim dDist As Double = 0
               EgtCurveArea(nOutlineFeatureId, vtN, dDist, dArea)
               dUnitVolume = dArea * dH
            Else
               dUnitVolume = dBtlH * dBtlW * dBtlL
            End If
      End Select
   End Sub

#End Region    ' METHODS

#Region "COMMANDS"

#Region "Invert"

   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

   Public Sub Invert()
      ' eseguo inversione
      m_BTLPartM.Inversion(Map.refProjectVM.BTLStructureVM.nPROJTYPE)
      ' setto part e tutte le feature da ricalcolare
      ResetCalcTotalPart()
      EgtDraw()
      ' imposto lock
      bLockInversion = True
      NotifyPropertyChanged(NameOf(sINVERTED))
   End Sub

#End Region ' Invert

#Region "BackRotation"

   Public ReadOnly Property BackRotation_Command As ICommand
      Get
         If m_cmdBackRotation Is Nothing Then
            m_cmdBackRotation = New Command(AddressOf BackRotationCmd)
         End If
         Return m_cmdBackRotation
      End Get
   End Property

   Public Sub BackRotationCmd()
      BackRotation(True)
   End Sub

   Public Sub BackRotation(Optional bUpdateSection As Boolean = False, Optional bRedraw As Boolean = True)
      ' salvo sezione impostata
      Dim CurrSection As SectionXMaterial = Map.refProjectVM.BTLStructureVM.SelSection
      ' ruoto
      Rotation(False, Map.refProjectVM.BTLStructureVM.nPROJTYPE, bRedraw)
      ' imposto lock
      bLockRotation = True
      ' se progetto travi e sezione precedente diversa da vuota (tutti i pezzi)
      If bUpdateSection AndAlso 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
   End Sub

#End Region ' BackRotation

#Region "ForwardRotation"

   Public ReadOnly Property ForwardRotation_Command As ICommand
      Get
         If m_cmdForwardRotation Is Nothing Then
            m_cmdForwardRotation = New Command(AddressOf ForwardRotationCmd)
         End If
         Return m_cmdForwardRotation
      End Get
   End Property

   Public Sub ForwardRotationCmd(Optional bUpdateSection As Boolean = False)
      ForwardRotation(True)
   End Sub

   Public Sub ForwardRotation(Optional bUpdateSection As Boolean = False, Optional bRedraw As Boolean = True)
      ' salvo sezione impostata
      Dim CurrSection As SectionXMaterial = Map.refProjectVM.BTLStructureVM.SelSection
      Rotation(True, Map.refProjectVM.BTLStructureVM.nPROJTYPE, bRedraw)
      ' imposto lock
      bLockRotation = True
      ' se progetto travi e sezione precedente diversa da vuota (tutti i pezzi)
      If bUpdateSection AndAlso 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
   End Sub

#End Region ' ForwardRotation

   ' Comando inutilizzato ma conservato per eventuale rotazione a causa di importazione con rotazione sbagliata
#Region "XRotation"

   Public ReadOnly Property XRotation_Command As ICommand
      Get
         If m_cmdXRotation Is Nothing Then
            m_cmdXRotation = New Command(AddressOf XRotation)
         End If
         Return m_cmdXRotation
      End Get
   End Property

   Public Sub XRotation()
      If Map.refProjectVM.BTLStructureVM.nPROJTYPE <> MachineType.WALL Then Return
      Dim OldSection As SectionXMaterial = Section
      ' recupero il box del pezzo
      Dim nLs As Integer = EgtGetFirstNameInGroup(nPartId, "Box")
      Dim b3Solid As New BBox3d
      EgtGetBBoxGlob(nLs, GDB_BB.STANDARD, b3Solid)
      If b3Solid.IsEmpty() Then
         EgtOutLog("ERROR: Box non definito per la trave " & sNAM)
         Return
      End If
      Dim vtAxes As Vector3d = Vector3d.X_AX
      ' eseguo rotazione di 90 gradi 
      If EgtRotate(nPartId, b3Solid.Center, vtAxes, 90, GDB_RT.GLOB) Then
         ' imposto modificato per copie
         EgtDuploSetModified(nPartId)
      End If
      ' aggiorno visualizzazione dimensioni
      NotifyPropertyChanged(NameOf(sW))
      NotifyPropertyChanged(NameOf(sH))
      NotifyPropertyChanged(NameOf(sL))
      ' setto part e tutte le feature da ricalcolare
      ResetCalcTotalPart()
      ' aggiorno sezioni
      Map.refProjectVM.BTLStructureVM.UpdateSection(Section, OldSection)
   End Sub

#End Region ' XRotation

#Region "PartColour"

   Public ReadOnly Property PartColour_Command As ICommand
      Get
         If m_cmdPartColour Is Nothing Then
            m_cmdPartColour = New Command(AddressOf PartColourCmd)
         End If
         Return m_cmdPartColour
      End Get
   End Property

   Public Sub PartColourCmd()
      Dim PartColor As New Color3d(192, 192, 192)
      ' Eseguo modifica con dialogo
      If SelectColor(m_BTLPartM.colCOLOR, PartColor) Then
         'm_colCOLOR = PartColor
         sCOLRGB = PartColor.ToString
         NotifyPropertyChanged("PartColour")
      End If
   End Sub

#End Region ' PartColour

   Private Function SelectColor(Col As Color3d, ByRef NewCol As Color3d) As Boolean
      ' Creo dialogo colori
      Dim ColorDlg As New System.Windows.Forms.ColorDialog
      ColorDlg.FullOpen = True
      ColorDlg.Color = Col.ToColor()
      ' Visualizzo dialogo
      If ColorDlg.ShowDialog() <> Forms.DialogResult.OK Then Return False
      ' Recupero colore scelto
      NewCol.FromString(ColorDlg.Color.R & "," & ColorDlg.Color.G & "," & ColorDlg.Color.B & "," & ColorDlg.Color.A) 'NewCol.FromColor(ColorDlg.Color)
      Return True
   End Function

#End Region    ' COMMANDS

#Region "EVENTS"

   Private Sub OnBTLFeatureAdded(sender As Object, e As BTLFeatureAddedEventArgs)
      Dim BTLFeatureVM As BTLFeatureVM = New BTLFeatureVM(e.NewBTLFeature, m_BTLPartM)
      BTLFeatureVMList.Add(BTLFeatureVM)
   End Sub

   Private Sub OnBTLFeatureVMListChanged(sender As Object, e As NotifyCollectionChangedEventArgs)
      If Not IsNothing(e.NewItems) AndAlso e.NewItems.Count > 0 Then
         For Each BTLFeatureVM As BTLFeatureVM In e.NewItems
            AddHandler BTLFeatureVM.PropertyChanged, AddressOf OnBTLFeatureVMPropertyChanged
         Next
      End If
      If Not IsNothing(e.OldItems) AndAlso e.OldItems.Count > 0 Then
         For Each BTLFeatureVM As BTLFeatureVM In e.OldItems
            RemoveHandler BTLFeatureVM.PropertyChanged, AddressOf OnBTLFeatureVMPropertyChanged
            m_BTLPartM.BTLFeatureMList.Remove(BTLFeatureVM.BTLFeatureM)
         Next
      End If
   End Sub
   Private Sub OnBTLPParamVMListChanged(sender As Object, e As NotifyCollectionChangedEventArgs)
      If Not IsNothing(e.NewItems) AndAlso e.NewItems.Count > 0 Then
         For Each BTLParamVM As BTLParamVM In e.NewItems
            AddHandler BTLParamVM.PropertyChanged, AddressOf OnBTLPParamVMPropertyChanged
         Next
      End If
      If Not IsNothing(e.OldItems) AndAlso e.OldItems.Count > 0 Then
         For Each BTLParamVM As BTLParamVM In e.OldItems
            RemoveHandler BTLParamVM.PropertyChanged, AddressOf OnBTLPParamVMPropertyChanged
         Next
      End If
   End Sub
   Private Sub OnBTLQParamVMListChanged(sender As Object, e As NotifyCollectionChangedEventArgs)
      If Not IsNothing(e.NewItems) AndAlso e.NewItems.Count > 0 Then
         For Each BTLParamVM As BTLParamVM In e.NewItems
            AddHandler BTLParamVM.PropertyChanged, AddressOf OnBTLQParamVMPropertyChanged
         Next
      End If
      If Not IsNothing(e.OldItems) AndAlso e.OldItems.Count > 0 Then
         For Each BTLParamVM As BTLParamVM In e.OldItems
            RemoveHandler BTLParamVM.PropertyChanged, AddressOf OnBTLQParamVMPropertyChanged
         Next
      End If
   End Sub

   Private Sub OnBTLFeatureVMPropertyChanged(sender As Object, e As PropertyChangedEventArgs)
      Select Case e.PropertyName
         Case NameOf(sender.nSelGRP), NameOf(sender.nSelSIDE)
            CalcGlobalUpdate(True)
            ' imposto path disegno da mostrare in BottomPanel
            Dim SelPBTLParam As BTLParamVM = Map.refProjectVM.BTLStructureVM.SelBTLPart.SelBTLFeatureVM.SelPBTLParam
            If Not IsNothing(SelPBTLParam) Then Map.refBottomPanelVM.SetCurrDraw(SelPBTLParam.sDrawPath)
         Case NameOf(sender.bDO), NameOf(sender.sPriority)
            NotifyPropertyChanged(NameOf(bDOALL))
            ' setto pezzo da ricalcolare
            'ResetCalcTotalPart()
            CalcGlobalUpdate(True)
      End Select
   End Sub
   Private Sub OnBTLPParamVMPropertyChanged(sender As Object, e As PropertyChangedEventArgs)
      Select Case e.PropertyName
         Case NameOf(sender.dValue), NameOf(sender.sValue)
            CalcGlobalUpdate(True)
      End Select
   End Sub
   Private Sub OnBTLQParamVMPropertyChanged(sender As Object, e As PropertyChangedEventArgs)
      Select Case e.PropertyName
         Case NameOf(sender.dValue), NameOf(sender.sValue)
            CalcGlobalUpdate(True)
      End Select
   End Sub

#End Region

End Class
