XData - como manipular dados adicionais nos objetos? (Parte II)

Olá a todos,

Essa é a segunda parte do post sobre como manipular XData no AutoCAD. Se você não tem muita certeza dos conceitos, dê uma olhada no post passado.

Na verdade, nós começamos ao avesso: primeiro aprendemos a ler, e agora que vamos aprender a escrever. A razão disso é que é um pouco mais complexo salvar do que ler, e muito dos conceitos utilizados são compartilhados por ambas as operações.

Primeiramente, devemos registrar nossa aplicação. Para isto, devemos acessar a tabela de registro de aplicações. O código abaixo registra uma aplicação com o nome que passarmos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
static void RegistrarApp(string nome)
{
    var documento = Application.DocumentManager.MdiActiveDocument;
    var banco = documento.Database;

    
    using (var transacao = documento.TransactionManager.StartTransaction())
    {
        var tabela = transacao.GetObject(banco.RegAppTableId, OpenMode.ForRead, false) as RegAppTable;

        if (tabela == null)
            return;

        if (!tabela.Has(nome))
        {
            tabela.UpgradeOpen();
            var registro = new RegAppTableRecord();
            registro.Name = nome;
            tabela.Add(registro);
            transacao.AddNewlyCreatedDBObject(registro, true);
        }
        transacao.Commit();
    }
}

Depois disso, nós precisamos salvar efetivamente a informação que desejamos (no caso, um nome para a linha). Ao código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[CommandMethod("SalvarNome")]
static public void SalvarNome()
{
    var documento = Application.DocumentManager.MdiActiveDocument;
    var editor = documento.Editor;
    var nomeApp = "AppTesteXData";

    var opcoesNome = new PromptStringOptions("\nDigite um nome para a entidade: ");
    opcoesNome.AllowSpaces = true;
    var resultadoNome = editor.GetString(opcoesNome);
    if (resultadoNome.Status != PromptStatus.OK)
    {
        editor.WriteMessage("\nComando abortado.");
    }

    var opcoesSelEntidade = new PromptEntityOptions("\nSelecione uma entidade: ");
    var resultadoEntidade = editor.GetEntity(opcoesSelEntidade);

    if (resultadoEntidade.Status != PromptStatus.OK)
    {
        editor.WriteMessage("\nComando abortado.");
    }

    using (var transacao = documento.TransactionManager.StartTransaction())
    {
        DBObject objeto = transacao.GetObject(resultadoEntidade.ObjectId, OpenMode.ForWrite);
        if(objeto == null) return;
        
        RegistrarApp(nomeApp);
        var buffer = new ResultBuffer(
            new TypedValue((short)DxfCode.ExtendedDataRegAppName, nomeApp),
            new TypedValue((short)DxfCode.ExtendedDataAsciiString, resultadoNome.StringResult)
          );
        objeto.XData = buffer;
        buffer.Dispose();
        transacao.Commit();
        editor.WriteMessage("\nDados salvos com sucesso!");
    }
}

Se você tem acompanhado o blog, a única coisa que pareça novidade é a parte que adiciona o buffer. Bem, é simples de entender. Um TypedValue é uma classe do tipo chave-valor. O DxfCode é apenas um alias para facilitar a obtenção da chave que precisamos. No caso, o primeiro item do buffer é do tipo ExtendedDataRegAppName, que vai carregar o nome que registramos previamente (com o método RegistrarApp), e seu valor é uma string. O segundo item é a string que representa o nome da linha de fato, ou seja, o dado que realmente nos importa. O DxfCode é ExtendedDataAsciiString, ou seja, uma string ASCII que será salva no objeto (é importante lembrar do encoding nesse caso: nada de acentos). Depois, apenas salvamos o buffer no XData da entidade, e pronto. Temos agora o dado salvo na entidade.

Podemos conferir o resultado salvando. Digitamos o comando, selecionamos a entidade e observamos que o comando foi bem sucedido:

Fig. 1 Rodando o comando

Fig. 2 Selecionado a entidade

Fig. 3 OK, nome inserido!

Pronto, agora os dados foram inseridos na nossa entidade. Você pode confiar em mim! Ou… se você não confia tanto :(, pode executar o comando de leitura que criamos no post passado:

Fig. 4 Verificando a inserção

Segue o código completo coberta na série sobre XData:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExemploXDataAutoCAD
{
    public class Main
    {
        [CommandMethod("LerNome")]
        public static void LerNome()
        {
            var documento = Application.DocumentManager.MdiActiveDocument;
            var editor = documento.Editor;

            var opcoes = new PromptEntityOptions("\nSelecione a entidade: ");
            opcoes.SetRejectMessage("\nPor favor, selecione uma reta (Line).");
            opcoes.AddAllowedClass(typeof(Line), false);
            opcoes.AllowNone = false;

            var resultado = editor.GetEntity(opcoes);

            if (resultado.Status != PromptStatus.OK)
            {
                editor.WriteMessage("\nComando abortado.");
                return;
            }

            using (var transacao = documento.TransactionManager.StartTransaction())
            {
                var reta = transacao.GetObject(resultado.ObjectId, OpenMode.ForRead);

                var dados = reta.XData;

                if (dados == null)
                {
                    editor.WriteMessage("\nNão há dados anexados à reta.");
                }
                else
                {
                    foreach (var valor in dados)
                    {
                        editor.WriteMessage("\nTipo: {0} , Valor: {1}", valor.TypeCode.ToString(), valor.Value.ToString());
                    }
                }
            }
        }

        static void RegistrarApp(string nome)
        {
            var documento = Application.DocumentManager.MdiActiveDocument;
            var banco = documento.Database;

            
            using (var transacao = documento.TransactionManager.StartTransaction())
            {
                var tabela = transacao.GetObject(banco.RegAppTableId, OpenMode.ForRead, false) as RegAppTable;

                if (tabela == null)
                    return;

                if (!tabela.Has(nome))
                {
                    tabela.UpgradeOpen();
                    var registro = new RegAppTableRecord();
                    registro.Name = nome;
                    tabela.Add(registro);
                    transacao.AddNewlyCreatedDBObject(registro, true);
                }
                transacao.Commit();
            }
        }

        [CommandMethod("SalvarNome")]
        static public void SalvarNome()
        {
            var documento = Application.DocumentManager.MdiActiveDocument;
            var editor = documento.Editor;
            var nomeApp = "AppTesteXData";

            var opcoesNome = new PromptStringOptions("\nDigite um nome para a entidade: ");
            opcoesNome.AllowSpaces = true;
            var resultadoNome = editor.GetString(opcoesNome);
            if (resultadoNome.Status != PromptStatus.OK)
            {
                editor.WriteMessage("\nComando abortado.");
            }

            var opcoesSelEntidade = new PromptEntityOptions("\nSelecione uma entidade: ");
            var resultadoEntidade = editor.GetEntity(opcoesSelEntidade);

            if (resultadoEntidade.Status != PromptStatus.OK)
            {
                editor.WriteMessage("\nComando abortado.");
            }

            if (resultadoEntidade.ObjectId == ObjectId.Null) return;

            using (var transacao = documento.TransactionManager.StartTransaction())
            {
                DBObject objeto = transacao.GetObject(resultadoEntidade.ObjectId, OpenMode.ForWrite);
   
                RegistrarApp(nomeApp);
                var buffer = new ResultBuffer(
                    new TypedValue((short)DxfCode.ExtendedDataRegAppName, nomeApp),
                    new TypedValue((short)DxfCode.ExtendedDataAsciiString, resultadoNome.StringResult)
                  );
                objeto.XData = buffer;
                buffer.Dispose();
                transacao.Commit();
                editor.WriteMessage("\nDados salvos com sucesso!");
            }
        }
    }
}

Abraço e até a próxima!


comentários utilizando o Disqus