11.3. Adding Auto-login PreferencesEven though previously entered login information is now saved, users often appreciate the option to log in automatically at startup. The Hyperbola application can present this option directly from the login dialog, as shown in Figure 11-5, or from a Preferences dialog, as shown in Figure 11-7. Let's do both! Figure 11-5. Login dialog with the auto-login preference
11.3.1. Creating a Preference PagePreference pages contain a grab bag of application settings that users normally do not have to change. They are there to allow specific configuration of your application. Basic support for preference pages in Eclipse is provided by JFace. This support is extended by the Workbench to allow contributing preference pages in a plugin.xml. The Workbench also adds helper widgets useful in building preference pages. To add a preference page for the auto-login preference, you first need to define a preference page extension for the Workbench's org.eclipse.ui. preferencePages extension point. Preference pages contributed this way automatically appear in the Workbench's standard Preferences dialog. You have added extensions a few times by now, so we will skim over it quickly here. Open the Hyperbola plug-in editor and flip to the Extensions page and click Add.... Choose the org.eclipse.ui.preferencePages extension point and click Finish. That creates the extension. Right-click on the extension itself and choose New > page. Once you have the page element, fill in the details as shown in Figure 11-6. For the class field, use the normal trick of clicking on the class link to create a skeleton for the preference page class. Figure 11-6. Preference page extension point
All preference pages must implement the interface IWorkbenchPreferencePage by either subclassing PreferencePage or FieldEditorPreferencePage. The skeleton you created likely subclassed PreferencePagechange this to subclass FieldEditorPreferencePage. Field editors are very useful controls that are linked to underlying preferences. FieldEditorPreferencePage has various helpers for creating FieldEditors. For the Hyperbola application, all we want to do is display a check box that allows toggling the auto-login preference. The resulting preference page is shown in Figure 11-7. The following code snippet shows the source for that preference page. org.eclipsercp.hyperbola/GeneralPreferencePage public class GeneralPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { public static final String AUTO_LOGIN = "prefs_auto_login"; private ScopedPreferenceStore preferences; public GeneralPreferencePage() { super(GRID); preferences = new ScopedPreferenceStore( new ConfigurationScope(),Application.PLUGIN_ID); setPreferenceStore(preferences); } public void init(IWorkbench workbench) { } protected void createFieldEditors() { BooleanFieldEditor boolEditor = new BooleanFieldEditor( AUTO_LOGIN, "Login automatically at startup", getFieldEditorParent() ); addField(boolEditor); } public boolean performOk() { try { preferences.save(); } catch (IOException e) { HyperbolaUtils.log( "Unable to save general preference page preferences", e); } return super.performOk(); } } Figure 11-7. Standard Preferences dialog
When the preference page is constructed, a ScopedPreferenceStore is created to wrap the configuration scoped preferences for the Hyperbola plug-in. This is a backwards-compatible layer that allows using preferences with FieldEditors. The FieldEditor APIs pre-date the use of the Runtime preferences and thus are not compatible without a helper class. When the page is drawn, createFieldEditors() is called by the Workbench. The BooleanFieldEditor here is given the key for the auto-login preference. It then reads and writes that preference automatically. When the user clicks the Apply button, the preferences are saved to disk. 11.3.2. Adding the ActionNow that the preference page is defined, you have to add an action that opens the Preferences dialog. The Workbench provides an action called ActionFactory.PREFERENCES that opens the standard Preferences dialog and shows all registered preference pages. Update Hyperbola's ActionBarAdvisor to create and place the preferences action. The snippet below shows the relevant lines and leaves you to place them accordingly. org.eclipsercp.hyperbola/ApplicationActionBarAdvisor
public void makeActions(IWorkbenchWindow window) {
...
preferencesAction = ActionFactory.PREFERENCES.create(window);
register(preferencesAction);
}
protected void fillMenuBar(IMenuManager menuBar) {
MenuManager hyperbolaMenu = new MenuManager("&Hyperbola",
"hyperbola");
...
hyperbolaMenu.add(preferencesAction);
}Start the Hyperbola application and select Hyperbola > Preferences to see the Preferences dialog, as shown in Figure 11-7. 11.3.3. Accessing PreferencesTo implement auto-login, Hyperbola must be updated to check the preference value and react accordingly, as shown in the snippet below. org.eclipsercp.hyperbola/Application private boolean login(final Session session) { boolean firstTry = true; LoginDialog loginDialog = new LoginDialog(null); while (session.getConnection() == null || !session.getConnection().isAuthenticated()) { Preferences preferences = new ConfigurationScope().getNode(Application.PLUGIN_ID); boolean auto_login = preferences.getBoolean( GeneralPreferencePage.AUTO_LOGIN, true); ConnectionDetails details = loginDialog.getConnectionDetails(); if (!auto_login || details == null || !firstTry) { if (loginDialog.open() != Window.OK) return false; details = loginDialog.getConnectionDetails(); } firstTry = false; session.setConnectionDetails(details); ... } 11.3.4. Default Preference ValuesThe preference page is up and working, but there is still one last detail to addressthe default value of the auto-login preference. The Workbench provides a default preferences scope called DefaultScope, which contains default values for preferences. Having a default scope and searching multiple scopes allows you to have defaults for a preference initialized in the DefaultScope but customized in another scope. There is also an extension point called org.eclipse.runtime.preferences that can be used to register a class that initializes default preference values. The preference initializer ensures that a plug-in's preferences are initialized before another plug-in can access them. Let's add a preference initializer for the Hyperbola application that sets the auto-login default to false. First, add an extension to the org.eclipse.runtime.preferences.initializer extension point. For the class attribute, create a class called PreferenceInitializer. The implementation for this preference initializer is shown below. Eclipse ensures that the preference initializer is run before any preferences are accessed in the node that matches this plug-in's id. This implies that each plug-in is storing its preferences under a node with its plug-in id. org.eclipsercp.hyperbola/PreferenceInitializer public class PreferenceInitializer extends AbstractPreferenceInitializer { public PreferenceInitializer() { super(); } public void initializeDefaultPreferences() { IEclipsePreferences defaults = new DefaultScope().getNode(Application.PLUGIN_ID); defaults.putBoolean(GeneralPreferencePage.AUTO_LOGIN, false); } } 11.3.5. Preferences on the Login DialogAlthough the auto-login preference is available in the Preferences dialog, it's convenient to also allow the user to set this preference in context, for example, when he is using the login dialog. This is very easy to add. In the LoginDialog method createDialogArea(Composite), create an extra check box that is initialized with the preference value. Then, when the state of the check box changes, update the preference value, as shown in the following snippet: org.eclipsercp.hyperbola/LoginDialog final Button autoLogin = new Button(composite, SWT.CHECK); autoLogin.setText("Login &automatically at startup"); autoLogin.setLayoutData( new GridData(SWT.BEGINNING, SWT.CENTER, true, true, 2, 1)); autoLogin.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { IEclipsePreferences prefs = new ConfigurationScope().getNode(Application.PLUGIN_ID); prefs.putBoolean( GeneralPreferencePage.AUTO_LOGIN, autoLogin.getSelection()); } }); Preferences preferences = new ConfigurationScope(). getNode(Application.PLUGIN_ID); boolean auto_login = preferences.getBoolean( GeneralPreferencePage.AUTO_LOGIN, true); autoLogin.setSelection(auto_login); |