A estrutura de texto da plataforma define um modelo de documento para o texto e fornece um visualizador que exibe texto utilizando este modelo. Nós iniciaremos examinando o exemplo de editor Java e como ele utiliza esse modelo. Nós não focalizaremos a mecânica básica de registrar uma extensão do editor, pois já vimos isso na seção que descreve o org.eclipse.ui.editors. Em vez disso, veremos as especificações de como a classe do editor é implementada no exemplo.
No workbench, um editor é normalmente aberto quando o usuário seleciona um elemento de domínio (como um arquivo ou um elemento armazenado dentro de um arquivo archive) e o abre. Quando o editor é criado, ele é associado a uma entrada do editor (IEditorInput), que descreve o objeto que está sendo editado.
O exemplo de editor Java é aberto quando o usuário abre um arquivo com a extensão "*.jav". Nesse caso, a entrada para o editor é um IFileEditorInput. A estrutura de texto da plataforma assume pouco sobre a entrada do editor em si. Ela funciona com um modelo de apresentação, denominado IDocument, para a entrada, para que possa exibir e manipular eficazmente o texto.
Isso significa que deve haver uma maneira de mapear a partir de um modelo de domínio esperado (a entrada do editor) para o modelo de apresentação. Esse mapeamento é definido em um IDocumentProvider. Para uma determinada entrada do editor, o provedor de documento retorna um IDocument apropriado.
O exemplo do editor Java define um JavaDocumentProvider que retorna o documento apropriado. Como é o relacionamento entre o provedor de documento apropriado e a extensão "*.jav" estabelecida? Isso é feito na extensão org.eclipse.ui.documentProviders. Essa extensão é utilizada para definir mapeamentos entre tipos de arquivos e provedores de documento. O exemplo define seu provedor de documento, conforme a seguir:
<extension point="org.eclipse.ui.documentProviders"> <provider extensions="jav" class="org.eclipse.ui.examples.javaeditor.JavaDocumentProvider" id="org.eclipse.ui.examples.javaeditor.JavaDocumentProvider"> </provider> </extension>
Quando o usuário abre um arquivo com a extensão especificada, o workbench gerencia os detalhes de criação da instância do provedor de documento. O workbench cria uma instância do provedor de documento apenas uma vez e compartilha esta instância entre diferentes editores.
Não é necessário que o plug-in utilize esse ponto de extensão para registrar seu provedor de documento. Uma outra maneira de associar um provedor de documento a um editor é permitir que o próprio plug-in gerencie o provedor de documento. Isso é geralmente feito em sua classe de plug-in. Quando um elemento de entrada é definido em seu editor, o editor solicita sua classe de plug-in para o provedor de documento apropriado. O plug-in pode gerenciar a criação e as referências ao provedor de documento. Essa técnica pode ser preferível quando há inicialização especial ou outro processamento envolvido com o provedor de documento. Consulte ClassFileEditor nas ferramentas JDT para obter um exemplo.
Depois que o provedor de documento apropriado for associado a um editor, sua tarefa principal é criar um documento a partir da entrada do editor e configurar um objeto apropriado para dividir o documento em partições.
Vamos ver os documentos e partições no JavaDocumentProvider. Quando um documento é criado, um IDocumentPartitioner é criado e definido no documento.
protected IDocument createDocument(Object element) throws CoreException { IDocument document= super.createDocument(element); if (document != null) { IDocumentPartitioner partitioner= createJavaPartitioner(); document.setDocumentPartitioner(partitioner); partitioner.connect(document); } return document; }
O particionador é responsável por dividir o documento em regiões não-sobrepostas denominadas partições. As partições (representadas em ITypedRegion) são úteis para tratar seções diferentes do documento de modo distinto em relação aos recursos, como realce de sintaxe ou formatação.
No caso do exemplo de editor Java, o documento é dividido em partições que representam os comentários de javadoc, comentários de várias linhas e outros. Cada região é atribuída a um tipo de conteúdo e sua posição no documento. As posições são atualizadas enquanto o usuário edita o texto.
Compete a cada editor determinar a implementação apropriada para um particionador de documento. O suporte é fornecido em org.eclipse.jface.text.rules para a varredura baseada em regras do documento. Utilizar um scanner baseado em regras permite que um editor utilize o DefaultPartitioner fornecido pela estrutura.
private IDocumentPartitioner createJavaPartitioner() { return new DefaultPartitioner(getJavaPartitionScanner(), TYPES); }
RuleBasedPartitionScanner é a superclasse para os scanners baseados em regras. As subclasses são responsáveis por enumerar e implementar as regras que devem ser utilizadas para diferenciar os símbolos, como delimitadores de linha, espaço em branco e padrões genéricos ao varrer um documento. O JavaPartitionScanner do exemplo define regras para diferenciar comentários de linha única, constantes de caracteres, javadoc, comentários de várias linhas e palavras. Isso é feito no construtor do scanner:
public JavaPartitionScanner() { super(); IToken javaDoc= new Token(JAVA_DOC); IToken comment= new Token(JAVA_MULTILINE_COMMENT); List rules= new ArrayList(); // Adicionar regra para comentários de linha única. rules.add(new EndOfLineRule("//", Token.UNDEFINED)); // Adicionar regra para cadeias e constantes de caracteres. rules.add(new SingleLineRule("\"", "\"", Token.UNDEFINED, '\\')); rules.add(new SingleLineRule("'", "'", Token.UNDEFINED, '\\')); // Adicionar regra de palavra em caixa especial. rules.add(new WordPredicateRule(comment)); // Adicionar regras para comentários de várias linhas e javadoc. rules.add(new MultiLineRule("/**", "*/", javaDoc, (char) 0, true)); rules.add(new MultiLineRule("/*", "*/", comment, (char) 0, true)); IPredicateRule[] result= new IPredicateRule[rules.size()]; rules.toArray(result); setPredicateRules(result); }
Consulte as classes em org.eclipse.jface.text.rules para obter detalhes adicionais sobre como definir regras e os tipos de regras disponíveis. Nós veremos novamente os scanners quando examinarmos a coloração da sintaxe.
Além de fornecer um documento apropriado para uma entrada do editor, uma outra tarefa importante de um provedor de documento é fornecer um IAnnotationModel apropriado para ser utilizado com uma entrada do editor. Este modelo é utilizado para gerenciar anotações anexadas aos documentos. Deixando que o provedor de documento forneça o modelo, seu editor pode utilizar um modelo apropriado para o tipo de conteúdo. Nós veremos mais exatamente as anotações e como elas são apresentadas na próxima seção.