Preferências

O workbench implementa uma arquitetura de preferências genéricas que permite aos plug-ins armazenarem os valores de preferência do usuário e contribua com uma página de preferência no diálogo de preferências do workbench. Nós verificaremos novamente o exemplo da ferramenta leiame para ver como isso é feito e, em seguida, verificaremos algum suporte destacado para construir páginas de preferência.

org.eclipse.ui.preferencePages

O ponto de extensão org.eclipse.ui.preferencePages permite que você contribua com as páginas no diálogo de preferências do workbench (Janela->Preferências). O diálogo de preferências apresenta uma lista hierárquica de entradas de preferência de usuário. Cada entrada exibe uma página de preferência correspondente quando selecionada.

A ferramenta leiame utiliza esse ponto de extensão para incluir a página de preferências de Exemplo Leiame.

<extension
    point = "org.eclipse.ui.preferencePages">
    <page 
        id="org.eclipse.ui.examples.readmetool.Page1"
        class="org.eclipse.ui.examples.readmetool.ReadmePreferencePage"
        name="Readme Example">
    </page>
</extension>

Essa marcação define uma página de preferência chamada "Exemplo de Leiame" que é implementada pela classe ReadmePreferencePage. A classe deve implementar a interface IWorkbenchPreferencePage.

O workbench utiliza um PreferenceManager para manter uma lista de todos os nós na árvore de preferência e suas páginas correspondentes. Essa lista pode ser inicializada a partir de informações no registro de plug-in sem executar qualquer código de plug-in.  Sua contribuição de plug-in para o diálogo de preferência (a entrada "Exemplo de Leiame" à esquerda) é exibida antes de executar qualquer código.

A preferência "Exemplo de Leiame" é incluída no nível superior da árvore de preferência à esquerda.  Por quê? Porque uma contribuição de página de preferência será incluída como uma raiz da árvore, a não ser que um atributo categoria seja especificado. (O nome categoria é algo ambíguo. Talvez um nome melhor seja caminho.) O atributo categoria especifica o id (ou uma seqüência de ids da raiz) da página pai. Por exemplo, a marcação a seguir criaria uma segunda página de preferência da ferramenta leiame, "Página Filho de Exemplo de Leia me," como um filho da página original.

<extension
    point = "org.eclipse.ui.preferencePages">
    <page 
        id="org.eclipse.ui.examples.readmetool.Page1"
        class="org.eclipse.ui.examples.readmetool.ReadmePreferencePage"
        name="Readme Example">
    </page>    
    <page 
        id="org.eclipse.ui.examples.readmetool.Page2"
        class="org.eclipse.ui.examples.readmetool.ReadmePreferencePage2"
        name="Readme Example Child Page"
        category="org.eclipse.ui.examples.readmetool.Page1>
    </page>
</extension>

Assim que o usuário selecionar a entrada para uma página de preferência na árvore à esquerda, o workbench criará e exibirá uma página de preferência utilizando a classe especificada na definição da extensão.  Essa ação é o que ativa o plug-in (se já não estava ativado devido a outra operação do usuário).

Página de Preferência

Definindo a página

Implementar uma página de preferência é similar para criar uma página para um assistente. A página de preferência fornece um método createContents que cria os controles SWT representando o conteúdo da página e inclui os atendentes para qualquer evento de interesse. A página é responsável por criar e retornar a combinação que será parente de todos os controles na página.  O fragmento a seguir mostra os destaques:

protected Control createContents(Composite parent)
{
    ...
    //composite_textField << parent
    Composite composite_textField = createComposite(parent, 2);
    Label label_textField = createLabel(composite_textField, "Text Field"); 
    textField = createTextField(composite_textField);
    pushButton_textField = createPushButton(composite_textField, "Change");

    //composite_tab << parent
    Composite composite_tab = createComposite(parent, 2);
    Label label1 = createLabel(composite_tab, "Radio Button Options");

    tabForward(composite_tab);
    //radio button composite << tab composite
    Composite composite_radioButton = createComposite(composite_tab, 1);
    radioButton1 = createRadioButton(composite_radioButton, "Radio button 1");
    radioButton2 = createRadioButton(composite_radioButton, "Radio button 2");
    radioButton3 = createRadioButton(composite_radioButton, "Radio button 3");
    ...
    initializeValues();
    ...
    return new Composite(parent, SWT.NULL);
}

A maioria dos códigos nesse método é relacionado à criação e colocação dos controles, para não os cortar aqui.  Aqui está como a página correspondente parece:

A outra responsabilidade principal de uma página de preferência é reagir com a mensagem performOk. Normalmente, esse método atualiza e armazena as preferências do usuário e, se necessário, atualiza qualquer outro objeto de plug-in para refletir a alteração nas preferências.

As páginas de preferência devem substituir o método doGetPreferenceStore() para retornar um armazenamento de preferência para guardar seus valores.

Armazenamento de preferência de plug-in

Os armazenamentos de preferência são similares na natureza das definições do diálogo. Na Definições de diálogo, vimos como a classe AbstractUIPlugin mantém as definições do diálogo durante o tempo de vida de um plug-in. A mesma estratégia é empregada para preferências do usuário. O plug-in pode incluir entradas para um armazenamento de preferências e atualizar os valores como o usuário altera as definições na página preferências. A plataforma cuidará de salvar esses valores no diretório de funcionamento do plug-in e de inicializar o armazenamento de preferência a partir das definições salvas.

O código a seguir na ReadmePreferencePage obtém o armazenamento de preferência para oReadmePlugin.

protected IPreferenceStore doGetPreferenceStore() {

 return ReadmePlugin.getDefault().getPreferenceStore();

}

Devido a ReadmePlugin estender a classe AbstractUIPlugin, ele herda automaticamente um armazenamento de preferência. Esse armazenamento de preferência é inicializado a partir de um arquivo de preferência armazenado nesse diretório de plug-in.  A única coisa que ReadmePlugin tem que fazer é implementar um método que inicialize as preferências para seus valores padrão. Esses valores são utilizados na primeira vez em que a página de preferência é exibida ou quando o usuário pressiona o botão Padrões na página preferências.

protected void initializeDefaultPreferences(IPreferenceStore store) {

 // Essas definições mostrarão quando o diálogo Preferências

 // se abre pela primeira vez.

 store.setDefault(IReadmeConstants.PRE_CHECK1, true);

 store.setDefault(IReadmeConstants.PRE_CHECK2, true);

 store.setDefault(IReadmeConstants.PRE_CHECK3, false);

 store.setDefault(IReadmeConstants.PRE_RADIO_CHOICE, 2);

 store.setDefault(IReadmeConstants.PRE_TEXT, "Default text");

}

Nota:  se não houver preferências salvas para um plug-in, o plug-in obterá um armazenamento de preferência vazia.

Recuperando e salvando preferências

Assim que tiver associado o armazenamento de preferência de plug-in com sua página de preferência, é possível implementar a lógica para recuperar e salvar preferências.

As páginas de preferência são responsáveis por inicializar os valores de seus controles utilizando as definições de preferências do armazenamento de preferência. Esse processo é similar à inicialização dos valores de controle do diálogo a partir das definições do diálogo. O ReadmePreferencePage inicializa todos seus controles em um método simples, initializeValues, que é chamado a partir do seu método createContents.

private void initializeValues() {

 IPreferenceStore store = getPreferenceStore();

 checkBox1.setSelection(store.getBoolean(IReadmeConstants.PRE_CHECK1));

 checkBox2.setSelection(store.getBoolean(IReadmeConstants.PRE_CHECK2));

 checkBox3.setSelection(store.getBoolean(IReadmeConstants.PRE_CHECK3));
 ...

Quando o botão OK (ou Aplicar) for pressionado, os valores atuais dos controles na página de preferência deveriam ser armazenados de volta no armazenamento da preferência. O ReadmePreferencePage implementa essa lógica em um método separado, storeValues.

private void storeValues() {

 IPreferenceStore store = getPreferenceStore();

 store.setValue(IReadmeConstants.PRE_CHECK1, checkBox1.getSelection());

 store.setValue(IReadmeConstants.PRE_CHECK2, checkBox2.getSelection());

 store.setValue(IReadmeConstants.PRE_CHECK3, checkBox3.getSelection());

 ...

}

Quando o usuário pressionar o botão Padrões, a plataforma restaurará todos os valores armazenados de preferência para os valores padrão especificados na classe de plug-in. Entretanto, sua página de preferência é responsável por refletir esses valores padrão nos controles na página de preferência. O ReadmePreferencePage implementa isso em initializeDefaults.

private void initializeDefaults() {

 IPreferenceStore store = getPreferenceStore();

 checkBox1.setSelection(store.getDefaultBoolean(IReadmeConstants.PRE_CHECK1));

 checkBox2.setSelection(store.getDefaultBoolean(IReadmeConstants.PRE_CHECK2));

 checkBox3.setSelection(store.getDefaultBoolean(IReadmeConstants.PRE_CHECK3));

 ...

}

Editores de campo

A implementação de uma página de preferência é primariamente código SWT.  O código SWT é utilizado para criar os controles da página de preferência, definir e recuperar os valores dos controles. O pacote org.eclipse.jface.preference fornece classes auxiliares, chamadas de editores de campos, que criam os widgets e implementam a definição de valor e o código de recuperação para os tipos de preferência mais comuns. A plataforma fornece os editores de campo para exibir e atualizar muitos tipos de valor, incluindo boleanos, cores, cadeias, inteiros, fontes e nomes de arquivo.

FieldEditorPreferencePage implementa uma página que utiliza esses editores de campo para exibir e armazenar os valores de preferência na página.

Em vez de criar controles SWT para preencher seus comentários, um FieldEditorPreferencePage cria editores de campos para exibir os conteúdos.

public void createFieldEditors() {

    // A primeira cadeia é o nome-chave de preferência
    // A segunda cadeia é a etiqueta exibida ao lado do widget 
    addField(new BooleanFieldEditor(USE_OLD_MODE, "Utilizar modo antigo",
        getFieldEditorParent()));

    addField(new StringFieldEditor(APPLICATION_NAME, "Nome do aplicativo",
        getFieldEditorParent()));

    addField(new ColorFieldEditor(COLOR, "Text Color", getFieldEditorParent()));
    ...

A cada editor de campo é atribuído o nome da tecla de preferência correspondente e a etiqueta do texto para o controle SWT que será criado. O tipo do controle criado depende do tipo do editor de campo. Por exemplo, um editor de campo boleano cria uma caixa de entrada.

Desde que a página de preferência esteja associada a um armazenamento de preferência (especificado no método doGetPreferenceStore), o código para armazenar os valores atuais, para inicializar os valores de controle do armazenamento de preferência e para recuperar os controles para os valores padrão podem ser todos implementados no FieldEditorPreferencePage.

O FieldEditorPreferencePage utilizará um layout de grade com uma coluna como o layout padrão para os widgets do editor de campo.  Para solicitações de layout especial, é possível substituir o método createContents.