'//////////////////////////////////////////////////////////////////////////////
'//
'//  Copyright 2025 Autodesk, Inc.  All rights reserved.
'//
'//  Use of this software is subject to the terms of the Autodesk license 
'//  agreement provided at the time of installation or download, or which 
'//  otherwise accompanies this software in either electronic or hard copy form.   
'//
'//////////////////////////////////////////////////////////////////////////////
'

Imports SymBBAuto
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Interop

Public Class frmTitleBorder
    Dim m_titleBorderDescriptor As McadTitleBorderDescriptor
    Dim m_border As McadBorder
    Dim m_title As McadTitle
    Dim m_titleBorder As McadTitleBorder
    Dim m_app As AcadApplication = Library.COM.getActiveObject("AutoCAD.Application.26")
    Dim m_activedoc As AcadDocument = m_app.ActiveDocument

    'define and get the symbol manager
    Dim symbb As McadSymbolBBMgr = m_activedoc.Application.GetInterfaceObject("SymBBAuto.McadSymbolBBMgr.27")
    Dim m_titleBorderMgr As McadTitleBorderMgr = symbb.TitleBorderMgr
    Dim m_titleBorders As McadTitleBorders = m_titleBorderMgr.TitleBorders
    Dim m_titleBorderContext As McadTitleBorderContext = m_titleBorderMgr.NewContext
    Dim m_standardMgr As McadStandardMgr = symbb.StandardMgr
    Dim m_standard As McadStandard = m_standardMgr.CurrentStandard
    Dim m_titleBorderStandard As McadTitleBorderStandard = m_standard.TitleBorderStandard

    Dim count As Integer = m_titleBorders.Count
    Dim tabselindex As Integer = 0
    Dim modifyindex As Integer = 0
    Dim ed As Autodesk.AutoCAD.EditorInput.Editor = Application.DocumentManager.MdiActiveDocument.Editor

    Private Sub btnCreate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCreate.Click
        'hide dialog box
        Me.Hide()

        'new descriptor and context
        m_titleBorderDescriptor = m_titleBorderMgr.NewDescriptor
        m_titleBorderContext = m_titleBorderMgr.NewContext

        GetTitleBorderNames()

        'set scale
        If (Not tbScale.Text = String.Empty) Then
            m_titleBorderDescriptor.TitleBorderScale = CType(tbScale.Text, Double)
        End If

        'set options
        m_titleBorderContext.BaseScale = ckBaseScale.Checked
        m_titleBorderContext.DwgDefault = ckDefault.Checked
        m_titleBorderContext.MoveObjects = ckMove.Checked
        m_titleBorderContext.Rescale = ckRescale.Checked
        m_titleBorderContext.RetrieveFromAsmProp = ckAssembly.Checked
        m_titleBorderContext.RetrieveFromPartRef = ckReference.Checked
        'set AutomaticPlacement and ThawAllLayers only when Move Objects is checked
        If m_titleBorderContext.MoveObjects Then
            m_titleBorderContext.AutomaticPlacement = ckAutomatic.Checked
            m_titleBorderContext.ThawAllLayers = ckThaw.Checked
        End If

        'get the positon for title border
        Dim pt As Object
        Try
            pt = m_activedoc.Utility.GetPoint(, "Location for title border:")
        Catch ex As Exception
            Return
        End Try

        m_titleBorderDescriptor.Position = pt
        'check if there are objects existed
        If (m_activedoc.ModelSpace.Count > 0) Then
            If (m_titleBorderContext.MoveObjects) Then
                MoveObjects()
            End If
        End If

        CreateTitleBorder()

        If (ckReference.Checked) Then
            GetReference()
        End If

        Me.Show()

    End Sub

    Private Sub listView_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles listView.SelectedIndexChanged
        If (listView.Items.Count = 0) Then
            Return
        End If

        'set enabled property of all buttons
        btnModify.Enabled = True
        btnDelete.Enabled = True
        tabctr.Enabled = True
        lsvTitleAttrs.Enabled = True
        lsvBorderAttrs.Enabled = True
        tbAttrValue.Enabled = True
        btnDefAttrs.Enabled = True
        btnApply.Enabled = True
        cbTitle.Enabled = True
        cbFormat.Enabled = True
        tbScale.Enabled = True
        ckBaseScale.Enabled = True
        ckDefault.Enabled = True
        ckRescale.Enabled = True
        ckAssembly.Enabled = True
        ckReference.Enabled = True
        ckMove.Enabled = True
        ckReference.Checked = False

        If (listView.SelectedItems.Count = 0) Then
            Return
        End If

        'get selected item
        Dim index As Integer = listView.SelectedItems(0).Index
        'get selected title border
        m_titleBorder = m_titleBorders.Item(index)
        'get selected title border descriptor
        m_titleBorderDescriptor = m_titleBorder.Descriptor
        'get selected title
        m_title = m_titleBorderDescriptor.Title
        'get selected border
        m_border = m_titleBorderDescriptor.Border

        FillCombox()

        'set title and border's names
        SetTitleBorderNames()

        'get scale
        tbScale.Text = m_titleBorderDescriptor.TitleBorderScale
        'get border and title attributes if they have

        GetAllAttributes()

        'get options
        ckBaseScale.Checked = m_titleBorderContext.BaseScale
        ckDefault.Checked = m_titleBorderContext.DwgDefault
        ckRescale.Checked = m_titleBorderContext.Rescale
        ckAssembly.Checked = m_titleBorderContext.RetrieveFromAsmProp
        ckReference.Checked = m_titleBorderContext.RetrieveFromPartRef
        ckMove.Checked = True
        ckAutomatic.Checked = True
        ckThaw.Checked = m_titleBorderContext.ThawAllLayers

    End Sub

    Private Sub btnDelete_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelete.Click
        Dim i As Integer
        i = listView.SelectedIndices(0)
        'delete
        m_titleBorderMgr.DeleteTitleBorder(m_titleBorder)

        'update drawing
        ed.UpdateScreen()
        listView.Items.RemoveAt(i)

        If (listView.Items.Count <> 0) Then
            'select the last one after deleting successfully
            listView.Items.Item(listView.Items.Count - 1).Selected = True
            listView.Focus()
        Else
            'set some controls are not enabled when there is no title border in the list
            btnCreate.Enabled = True
            btnDelete.Enabled = False
            lsvTitleAttrs.Items.Clear()
            lsvBorderAttrs.Items.Clear()
            btnApply.Enabled = False
            tabctr.Enabled = False
            lsvTitleAttrs.Enabled = False
            lsvBorderAttrs.Enabled = False
            tbAttrValue.Enabled = False
            btnDefAttrs.Enabled = False
            btnModify.Enabled = False
            tbScale.Text = String.Empty
            ckBaseScale.Checked = False
            ckDefault.Checked = False
            ckRescale.Checked = False
            ckAssembly.Checked = False
            ckReference.Checked = False
            ckMove.Checked = False
        End If
    End Sub

    Private Sub ckMove_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ckMove.CheckedChanged
        If (Not ckMove.Checked) Then
            'when moveObjects is not checked, the AutomaticPlacement and ThawAllLayers are not checked
            ckAutomatic.Checked = False
            ckThaw.Checked = False
            ckAutomatic.Enabled = False
            ckThaw.Enabled = False
        Else
            ckAutomatic.Enabled = True
            ckThaw.Enabled = True
        End If
    End Sub

    Private Sub btnModify_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnModify.Click
        GetTitleBorderNames()

        'modify scale
        m_titleBorderDescriptor.TitleBorderScale = tbScale.Text
        m_titleBorder.Modify()

        'modify titleborder attributes
        ModifyTitleBorderAttrs()

        'modify options
        m_titleBorderContext.BaseScale = ckBaseScale.Checked
        m_titleBorderContext.DwgDefault = ckDefault.Checked
        m_titleBorderContext.Rescale = ckRescale.Checked
        m_titleBorderContext.RetrieveFromAsmProp = ckAssembly.Checked
        m_titleBorderContext.RetrieveFromPartRef = ckReference.Checked
        m_titleBorderContext.MoveObjects = ckMove.Checked
        If m_titleBorderContext.MoveObjects Then
            m_titleBorderContext.AutomaticPlacement = ckAutomatic.Checked
            m_titleBorderContext.ThawAllLayers = ckThaw.Checked
        End If

        If (ckReference.Checked) Then
            Me.Hide()
            GetReference()
        End If

        m_titleBorder.Modify(m_titleBorderContext)
        Me.Close()
    End Sub

    Private Sub ModifyTitleBorderAttrs()
        If tabselindex = 1 Then
            'set border attribute
            Dim attrB As Object
            attrB = m_border.Attributes
            If VarType(attrB) <> VariantType.Object Then
                attrB(modifyindex, 1) = tbAttrValue.Text
                m_border.Attributes = attrB
            End If
        Else
            'set title attribute
            Dim attrT As Object
            attrT = m_title.Attributes
            If VarType(attrT) <> VariantType.Object Then
                attrT(modifyindex, 1) = tbAttrValue.Text
                m_title.Attributes = attrT
            End If
        End If
    End Sub

    Private Sub GetAllAttributes()
        'get border attributes if it has
        lsvBorderAttrs.Items.Clear()
        Dim attrB As Object
        attrB = m_border.Attributes
        Dim tp As VariantType
        Dim i As Integer
        tp = VarType(attrB)
        If (tp <> VariantType.Object) Then
            For i = LBound(attrB) To UBound(attrB)
                lsvBorderAttrs.Items.Insert(i, attrB(i, 0))
                lsvBorderAttrs.Items(i).SubItems.Add(attrB(i, 1))
            Next i
            If (tabselindex = 1) Then
                lsvBorderAttrs.Items(0).Selected = True
                tbAttrValue.Text = attrB(0, 1)
            End If
        End If

        'get title attributes
        lsvTitleAttrs.Items.Clear()
        Dim attrT As Object
        attrT = m_title.Attributes
        tp = VarType(attrT)
        If (tp <> VariantType.Object) Then
            For i = LBound(attrT) To UBound(attrT)
                lsvTitleAttrs.Items.Insert(i, attrT(i, 0))
                lsvTitleAttrs.Items(i).SubItems.Add(attrT(i, 1))
            Next i
            If (tabselindex) Then
                lsvTitleAttrs.Items(0).Selected = True
                tbAttrValue.Text = attrT(0, 1)
            End If
        End If
    End Sub

    Private Sub GetTitleBorderNames()
        'get border name
        Dim paperFormats As Object
        paperFormats = m_titleBorderStandard.PaperFormats

        Dim i As Integer
        For i = LBound(paperFormats) To UBound(paperFormats)
            If (cbFormat.SelectedItem = paperFormats(i, 0)) Then
                m_titleBorderDescriptor.Border.Name = paperFormats(i, 1).ToString()
            End If
        Next i

        'get title name
        Dim titles As Object
        titles = m_titleBorderStandard.TitleBlocks
        For i = LBound(titles) To UBound(titles)
            If (cbTitle.SelectedItem = titles(i, 0)) Then
                m_titleBorderDescriptor.Title.Name = titles(i, 1).ToString()
            End If
        Next i
    End Sub

    Private Sub SetTitleBorderNames()
        'set border name
        Dim paperFormats As Object
        paperFormats = m_titleBorderStandard.PaperFormats

        Dim i As Integer
        For i = LBound(paperFormats) To UBound(paperFormats)
            If (m_titleBorderDescriptor.Border.Name = paperFormats(i, 1)) Then
                cbFormat.SelectedItem = paperFormats(i, 0)
            End If
        Next i

        'set title name
        Dim titles As Object
        titles = m_titleBorderStandard.TitleBlocks
        For i = LBound(titles) To UBound(titles)
            If (m_titleBorderDescriptor.Title.Name = titles(i, 1)) Then
                cbTitle.SelectedItem = titles(i, 0)
            End If
        Next i
    End Sub

    Private Sub FillCombox()
        'get title name
        Dim titles As Object
        titles = m_titleBorderStandard.TitleBlocks
        cbTitle.Items.Clear()

        Dim i As Integer
        For i = LBound(titles) To UBound(titles)
            If (cbTitle.Items.Contains(titles(i, 0)) = False) Then
                cbTitle.Items.Add(titles(i, 0))
            End If
        Next i

        'get paper formats
        Dim paperFormats As Object
        paperFormats = m_titleBorderStandard.PaperFormats
        For i = LBound(paperFormats) To UBound(paperFormats)
            If (cbFormat.Items.Contains(paperFormats(i, 0)) = False) Then
                cbFormat.Items.Add(paperFormats(i, 0))
            End If
        Next i
    End Sub

    Private Sub GetReference()
        'Declare our filter entries this way.
        'We build them the same way in ObjectARX.
        'DxfCode.Start (equal to 0) - This is for 'Entity Name'
        Dim values() As TypedValue = {
            New TypedValue(DxfCode.Start, "ACMPARTREF")
            }
        Dim sfilter As New SelectionFilter(values) ' Create the filter using our values...
        Dim Opts As New PromptSelectionOptions()
        Opts.MessageForAdding = "Select a partRef"

        Dim res As PromptSelectionResult
        res = ed.GetSelection(Opts, sfilter)
        If res.Status = PromptStatus.Error Then
            MsgBox("No part ref selected!")
            Me.Show()
            Return
        End If
        If (res.Status = PromptStatus.Cancel) Then
            Return
        End If

        Dim SS As Autodesk.AutoCAD.EditorInput.SelectionSet = res.Value
        Dim idarray As ObjectId() = SS.GetObjectIds()
        Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database
        Dim tm As Autodesk.AutoCAD.DatabaseServices.TransactionManager = db.TransactionManager
        Dim index As Integer

        'start transaction
        Dim myT As Transaction = tm.StartTransaction()
        Try
            Dim id As ObjectId
            For Each id In idarray
                'get part ref object id
                Dim entity As Entity = tm.GetObject(id, OpenMode.ForRead, True)
                index = Integer.Parse(entity.ObjectId().OldIdPtr.ToString())
            Next id
        Finally
            myT.Dispose()
        End Try
        m_titleBorderContext.SetPartReference(index)

    End Sub

    Private Sub MoveObjects()
        'get objects
        'set the selection options
        Dim SelOpts As New PromptSelectionOptions()
        Dim res As PromptSelectionResult
        SelOpts.AllowDuplicates = True
        'make the selection
        res = ed.GetSelection(SelOpts)
        'there are no objects selected
        If res.Status = PromptStatus.Error Then
            Return
        End If

        If res.Status = PromptStatus.Cancel Then
            Return
        End If
        'get ids of objects that are selected
        Dim ss As Autodesk.AutoCAD.EditorInput.SelectionSet = res.Value
        Dim idArray As Autodesk.AutoCAD.DatabaseServices.ObjectId() = ss.GetObjectIds()
        Dim ids(0 To idArray.Length - 1) As Integer
        Dim index As Integer = 0

        'get new point where objects will move
        Dim newPos As Object
        Try
            newPos = m_activedoc.Utility.GetPoint(, "Location for objects:")
        Catch ex As Exception
            Return
        End Try

        Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database
        Dim tm As Autodesk.AutoCAD.DatabaseServices.TransactionManager = db.TransactionManager
        'start a transaction
        Dim myT As Transaction = tm.StartTransaction()
        Try
            Dim id As ObjectId
            For Each id In idArray
                Dim entity As Entity = tm.GetObject(id, OpenMode.ForRead, True)
                ids(index) = Integer.Parse(entity.ObjectId().OldIdPtr.ToString())
                index = index + 1
            Next id
        Finally
            myT.Dispose()
        End Try
        'set move objects 
        m_titleBorderContext.MoveObjects = True
        m_titleBorderContext.SetMoveObjects(ids, newPos)

    End Sub

    Private Sub CreateTitleBorder()
        'create title border
        m_titleBorder = m_titleBorderMgr.CreateTitleBorder(m_titleBorderDescriptor, m_titleBorderContext)

        'display in the list
        count = count + 1
        listView.Items.Add("TitleBorder" + count.ToString())
        listView.Items(listView.Items.Count - 1).Selected = True
        'set focus 
        listView.Focus()
        ckMove.Checked = True
    End Sub

    Private Sub frmTitleBorder_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim count As Integer
        count = m_titleBorders.Count

        'there is no title border
        listView.Items.Clear()
        If (count = 0) Then
            btnDelete.Enabled = False
            lsvTitleAttrs.Items.Clear()
            lsvBorderAttrs.Items.Clear()
            tbAttrValue.Text = String.Empty
            tabctr.Enabled = False
            lsvTitleAttrs.Enabled = False
            lsvBorderAttrs.Enabled = False
            tbAttrValue.Enabled = False
            btnApply.Enabled = False
            btnDefAttrs.Enabled = False
            btnModify.Enabled = False

            FillCombox()

            'select the first item
            Dim bName As Object = cbFormat.Items(0)
            cbFormat.SelectedItem = bName
            bName = cbTitle.Items(0)
            cbTitle.SelectedItem = bName
            Return
        End If

        ckAutomatic.Checked = True
        'add all title borders to list view
        Dim i As Integer
        For i = 0 To count - 1
            listView.Items.Add("TitleBorder" + (i + 1).ToString())
        Next i
        listView.Items.Item(0).Selected = True
        listView.Focus()
    End Sub

    Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
        Me.Close()
    End Sub

    Private Sub tabctr_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tabctr.SelectedIndexChanged
        tabselindex = tabctr.SelectedIndex
        'title attributes
        If (tabselindex = 0) And (lsvTitleAttrs.Items.Count > 0) Then
            'When there are some items, Value text box, Apply button and Default Attributes button 
            'will be enabled.
            tbAttrValue.Enabled = True
            btnApply.Enabled = True
            btnDefAttrs.Enabled = True
            lsvTitleAttrs.Items(0).Selected = True
            tbAttrValue.Text = lsvTitleAttrs.Items(0).SubItems(1).Text
            'When there are no items, Value text box, Apply button and Default Attributes button 
            'will be disabled.
        ElseIf (tabselindex = 0) And (lsvTitleAttrs.Items.Count = 0) Then
            tbAttrValue.Clear()
            tbAttrValue.Enabled = False
            btnApply.Enabled = False
            btnDefAttrs.Enabled = False
            'border attributes
        ElseIf (tabselindex = 1) And (lsvBorderAttrs.Items.Count > 0) Then
            'When there are some items, Value text box, Apply button and Default Attributes button 
            'will be enabled.
            tbAttrValue.Enabled = True
            btnApply.Enabled = True
            btnDefAttrs.Enabled = True
            lsvBorderAttrs.Items(0).Selected = True
            tbAttrValue.Text = lsvBorderAttrs.Items(0).SubItems(1).Text
            'When there are no items, Value text box, Apply button and Default Attributes button 
            'will be disabled.
        ElseIf (tabselindex = 1) And (lsvBorderAttrs.Items.Count = 0) Then
            tbAttrValue.Clear()
            tbAttrValue.Enabled = False
            btnApply.Enabled = False
            btnDefAttrs.Enabled = False
        End If
    End Sub

    Private Sub lsvTitleattrs_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lsvTitleAttrs.SelectedIndexChanged
        'get selected attribute's value
        If lsvTitleAttrs.SelectedIndices.Count > 0 Then
            modifyindex = lsvTitleAttrs.SelectedIndices(0)
            tbAttrValue.Text = lsvTitleAttrs.SelectedItems(0).SubItems(1).Text
        End If
    End Sub

    Private Sub btnDefAttrs_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDefAttrs.Click
        'set to default attributes
        If tabselindex = 0 Then
            If Not m_titleBorderDescriptor.Title.SetToDefaultAttributes() Then
                MsgBox("title attributes can not set to default.")
            End If
        ElseIf tabselindex = 1 Then
            If Not m_titleBorderDescriptor.Border.SetToDefaultAttributes() Then
                MsgBox("border attributes can not set to default.")
            End If
        End If

        'if modification is not successful, a message box will pop up
        If Not m_titleBorder.Modify() Then
            MsgBox("modify titleborder failed.")
        End If

        'update title and border attributes displayed in their each list view control. 
        'get border attributes if it has
        GetAllAttributes()

        'update drawing
        ed.UpdateScreen()
        tbAttrValue.Text = String.Empty
    End Sub

    Private Sub btnApply_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnApply.Click
        'modify titleborder attributes
        ModifyTitleBorderAttrs()

        m_titleBorderContext.MoveObjects = False
        If Not m_titleBorder.Modify(m_titleBorderContext) Then
            MsgBox("modify titleborder failed.")
        End If

        'update drawing
        ed.UpdateScreen()

        'update title and border attributes displayed in their each list view control. 
        If tabselindex = 0 Then
            Dim attT As Object
            attT = m_title.Attributes
            lsvTitleAttrs.Items(modifyindex).SubItems(1).Text = attT(modifyindex, 1)
            lsvTitleAttrs.Focus()
        Else
            Dim attB As Object
            attB = m_border.Attributes
            lsvBorderAttrs.Items(modifyindex).SubItems(1).Text = attB(modifyindex, 1)
            lsvBorderAttrs.Focus()
        End If
    End Sub

    Private Sub lsvBorderAttrs_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles lsvBorderAttrs.SelectedIndexChanged
        'get select border attribute's value
        If lsvBorderAttrs.SelectedIndices.Count > 0 Then
            modifyindex = lsvBorderAttrs.SelectedIndices(0)
            tbAttrValue.Text = lsvBorderAttrs.SelectedItems(0).SubItems(1).Text
        End If
    End Sub

    Private Sub ckReference_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ckReference.CheckedChanged
        'when it is checked, the Assembly must be not checked it is disabled.
        If (ckReference.Checked) Then
            ckAssembly.Checked = False
            ckAssembly.Enabled = False
        Else
            ckAssembly.Enabled = True
        End If
    End Sub

    Private Sub ckAssembly_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ckAssembly.CheckedChanged
        'when it is checked, the Reference must be not checked it is disabled.
        If (ckAssembly.Checked) Then
            ckReference.Checked = False
            ckReference.Enabled = False
        Else
            ckReference.Enabled = True
        End If
    End Sub
End Class