diff options
author | wbeaton | 2005-11-30 04:39:30 +0000 |
---|---|---|
committer | wbeaton | 2005-11-30 04:39:30 +0000 |
commit | bf2548c2801ad91cbeba7160346b66ed8e6637fc (patch) | |
tree | 0447bffc1d63bb2c0cda5bb97c075da8725a120b /Article-Preferences/preferences.htm | |
parent | d7f19153edf2189dfbb204c3a58f4d2081dcb9db (diff) | |
download | articles-bf2548c2801ad91cbeba7160346b66ed8e6637fc.tar.gz articles-bf2548c2801ad91cbeba7160346b66ed8e6637fc.tar.xz articles-bf2548c2801ad91cbeba7160346b66ed8e6637fc.zip |
Added the rest of the existing articles.
Diffstat (limited to 'Article-Preferences/preferences.htm')
-rw-r--r-- | Article-Preferences/preferences.htm | 414 |
1 files changed, 414 insertions, 0 deletions
diff --git a/Article-Preferences/preferences.htm b/Article-Preferences/preferences.htm new file mode 100644 index 0000000..3781132 --- /dev/null +++ b/Article-Preferences/preferences.htm @@ -0,0 +1,414 @@ +<html> + +<head> +<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> + + +<title>Preferences and Properties in the Eclipse Workbench UI</title> +<link rel="stylesheet" type="text/css" href="../default_style.css"> +</head> + +<body> +<DIV align=right><FONT face="Times New Roman, Times, serif" +size=2>Copyright © 2001,2002 Object Technology International, Inc.</FONT> </DIV> +<TABLE border=0 cellPadding=2 cellSpacing=0 width="100%"> + <TBODY> + <TR> + <TD align=left bgColor=#0080c0 colSpan=2 vAlign=top><B><FONT + face=Arial,Helvetica><FONT color=#ffffff> Eclipse Corner + Article</FONT></FONT></B></TD></TR></TBODY></TABLE> +<H1><img align=center +src="images/Idea.jpg" width="120" height="86"> +<center>Preferences in the Eclipse Workbench UI</center></H1> +<blockquote> +<b>Summary</b><br> +In the Eclipse Platform plug-in developers define preference pages for their plug-ins +for use in the Workbench Preferences Dialog. This article explains when to use a +preference and some of the features the Eclipse Platform provides to support +preferences. + <p><b>By Tod Creasey, OTI<br> + </b> August 15, 2002</p> + <p>Editor's note: This article was originally published in December 2001 and + described Eclipse release 1.0. This revision reflects the minor enhancements + made to UI preferences in Eclipse release 2.0.</p> +</blockquote> +<HR width="100%"> + +<h2>Introduction</h2> +<p>The Eclipse Platform has support for preferences that are +persisted along with the workspace. This article will discuss what type of data +should be stored as a preference and will show how to develop and register a +user interface to allow the user to set these preferences as well as how to +store them independent of the workbench by use of the import and export +functions. It will also cover +how to initialize and retrieve preferences for use by other other plug-ins that +use your plug-in. This functionality will be shown using an example that +searches files for bad words. We will set our preferences for this tool +using two preference pages, one simple one to set a highlight color and one more +complex one to set the list of words. +</p> +<h2>When to Use a Preference +</h2> +<p>A preference is data that is persisted between workspace sessions to allow +the user to keep the state of a plug-in consistent between Eclipse sessions. As +of 2.0 Eclipse offers two varieties of preference, UI preferences (the same as +in 1.0) and Core Preferences. This article is concerned only with how to use the +UI preference store. Typical UI preferences are +default values for new instances, colors for editors and paths. Core preferences +are used for values that are not part of the user interface. +</p> +<p>Preferences are not intended to reference any resource currently defined in +the workspace and instead should be used for editors, views or other objects that +perform operations on a resource. Data persisted on a resource instance is better suited to be +a property which will be discussed in a later article. +</p> +<p>A preference can be made available to any plug-in that has your plug-in as a +prerequisite. The usual way to do that is to provide API on your plug-in that +allows for access to the preferences you want to make available. The values of +these preferences are stored in the .metadata/.plugins directory of the +workspace on a per plug-in basis. We demonstrate +how to do this below. +</p> +<h2>The Preference Store and the Plug-in</h2> +<p>Every plug-in has it's own preference store provided by the workspace. For + this example we will define a plug-in and use its preference store for our preferences. + As we are going to use this plug-in within the UI we define it as a subclass + of AbstractUIPlugin. Our constructor (see <img border="0" src="images/tag_2.gif" width="24" height="13">) + will create a singleton to allow easy access to the plug-in instance in the + workbench. We also implement the method initializeDefaultPreferences() to set + up our default values for our two preferences. We are defining a preference + for the bad words and a preference for the color of the highlight. Each preference + value is looked up using a given key. In the code below the keys we are using + are defined by the constants in <img src="images/tag_1.gif" width="24" height="13">. +</p> +<p>The default value should be set for all preferences to be sure that there is + a value to use at all times. A default value also ensures that the UI can provide + a way to reset a preference value back to a reasonable initial setting via the + Restore Defaults button.The default value of the preference should be initialized + in the plug-in so that it is set before any of the UI is created. </p> +<p> IAbstractWorkbenchPlugin defines a method called initializeDefaultPreferences(IPreferenceStore) + which is called when the preference store is created the first time. In this + method (see <img border="0" src="images/tag_3.gif" width="24" height="13">) you should + set the default value for all values that you will be using the preference store + for. We set a default color using the helper methods in the PreferenceConverter + which allows the plug-in developer to set and get values for a preference of + commonly stored types like FontData, Point etc. This API is provided because + preferences are stored and retrieved as Strings in a human readable format in + order to leverage the java properties mechanism. Our more complex bad + words preference is initialized using a set of preselected bad words defined + in the format we are going to store them in as we do not have API on the PreferenceConvertor + to store or retreive arrays of Strings.</p> +<pre>Color color= Display.getDefault().getSystemColor(SWT.COLOR_BLUE); +PreferenceConverter.setDefault(store, HIGHLIGHT_PREFERENCE, color.getRGB());</pre> +<pre>public class BadWordCheckerPlugin extends AbstractUIPlugin { + //The shared instance. + private static BadWordCheckerPlugin plugin; + + //The identifiers for the preferences +<img border="0" src="images/tag_1.gif" width="24" height="13"> public static final String BAD_WORDS_PREFERENCE = "badwords"; + public static final String HIGHLIGHT_PREFERENCE = "highlight"; + + //The default values for the preferences + public static final String DEFAULT_BAD_WORDS = "bug;bogus;hack;"; + public static final int DEFAULT_HIGHLIGHT = SWT.COLOR_BLUE; + + public BadWordCheckerPlugin(IPluginDescriptor descriptor) { + super(descriptor); +<img border="0" src="images/tag_2.gif" width="24" height="13"> plugin = this; + } + + public static BadWordCheckerPlugin getDefault() { + return plugin; + } + + /** + * Initializes a preference store with default preference values + * for this plug-in. + */ + protected void initializeDefaultPreferences(IPreferenceStore store) { +<img border="0" src="images/tag_3.gif" width="24" height="13"> store.setDefault(BAD_WORDS_PREFERENCE, DEFAULT_BAD_WORDS); + Color color= Display.getDefault().getSystemColor(DEFAULT_HIGHLIGHT); + PreferenceConverter.setDefault(store, HIGHLIGHT_PREFERENCE, color.getRGB()); + + } +}</pre> +<h2>Defining Preference Pages in plugin.xml</h2> +<p>Now that we have defined the preference we want to provide a way for the user +to set the preference value. Preference pages for the workbench can be found in +the preferences dialog. The preferences dialog is accessible via the Window->Preferences +menu group. Plug-in developers should add their preference pages to this dialog using the plugin.xml of their +plug-in in order to maintain a consistent look and feel with other Eclipse +plug-ins. The definition of the preference pages within plugin.xml looks like +this: +</p> +<pre><extension point="org.eclipse.ui.preferencePages"> + <page id="BadWordsPreferencePage" +<img border="0" src="images/tag_1.gif" width="24" height="13"> name="Bad Words" +<img border="0" src="images/tag_2.gif" width="24" height="13"> class="org.eclipse.ui.articles.badwordchecker.BadWordsPreferencePage"> + </page> + + <page id="BadWordsColorPreferencePage" + name="Colors" + class="org.eclipse.ui.articles.badwordchecker.BadWordsColorPreferencePage" +<img border="0" src="images/tag_3.gif" width="24" height="13"> category="BadWordsPreferencePage"> + </page> +</extension></pre> +<p>The definition above sets the name (<img border="0" src="images/tag_1.gif" width="24" height="13">) +of the preference page for use in the list +of pages in the preference dialog and also specifies the class(<img border="0" src="images/tag_2.gif" width="24" height="13">) to be +instantiated for creating the preference page. This class must conform to +IWorkbenchPreferencePage.</p> +<p>In the second definition there is a category (<img border="0" src="images/tag_3.gif" width="24" height="13">) +tag which is used to make one +page the child of another in the list in the preferences dialog. Preference +pages can be stored as the children of other pages. This is useful +for keeping a series of pages together that are related to each other and also +reduces the clutter in the workbench preferences page. A page can be made the +child of another page by setting the id of the parent page as the value of the +category field in the plugin.xml. A page with no parent is displayed as a child +with no root.</p> +<p>With the above declarations in our plugin.xml the list of preference pages +shown in the preference dialog will look like Figure 1.</p> +<p align="center"><img border="0" src="images/tree.gif" width="187" height="291"></p> +<p align="center"><b>Figure 1</b>:Preference dialog showing Bad Words and Colors + preferences</p> +<h2>The Color Preference Page +</h2> +<p>The color preference page is an example of a simple page that uses a single +JFace field editor to manage its values. Initially a preference page class is +defined. All +classes used in the preference dialog must conform to IWorkbenchPreferencePage. +Eclipse includes the class PreferencePage which implements most of the necessary API +for a preference page. PreferenceDialog will save the preference store whenever +OK is pressed - if you wish to use PreferencePages in places other than the +default dialog in Window->Preferences be sure that you save the preference +store after changes have been applied.</p> +<p>The class definition for our preference page is:</p> +<pre>class BadWordsColorPreferencePage + extends PreferencePage + implements IWorkbenchPreferencePage</pre> +<p>Once we have defined the page we want to initialize it. IWorkbenchPreferencePage +specifies a message init(IWorkbench) for this purpose. We will not use the Workbench +argument for this page. Our implementation only sets +the preference store for the page.</p> +<pre>public void init(IWorkbench workbench) { + //Initialize the preference store we wish to use + setPreferenceStore(BadWordCheckerPlugin.getDefault().getPreferenceStore()); +}</pre> +<p>The other required method we must implement is createContents(). +All we are going to do is use a ColorFieldEditor +to set our preference. It is also suggested that performDefaults is +implemented so that the current state can be reset to the defaults defined in +the plug-in. We also need to implement performOK so that the settings defined by the user are +stored in the preference store for our plug-in. Our +implementation is simple as the ColorFieldEditor has the code to load defaults +and store the results of an apply for a preference already defined and performOK +and performDefaults can call the corresponding methods on ColorFieldEditor. See +figure 2 for the Colors preference page.</p> +<pre>protected void performDefaults() { + colorEditor.loadDefault(); +} +/** + * Save the color preference to the preference store. + */ +public boolean performOk() { + colorEditor.store(); + return super.performOk(); +}</pre> +<p> </p> +<p align="center"><img border="0" src="images/colorpreference.gif" width="606" height="532"></p> +<p align="center"><b>Figure 2</b>: Preference dialog showing Colors preference +page</p> +<h2>The Bad Words Preference Page +</h2> +<p>We have seen how to do a simple preference page with just a color and categorize it. +Now we will show how to use a complex object as a +preference and still have it persisted by the preference store and editable in a +preference page. For this example +we are going to add a bad words preference which is an array of Strings. +</p> +<p>As the PreferenceConverter does not have API for conversion of arrays of +Strings we will implement it ourselves in the BadWordCheckerPlugin. +By implementing it in the plug-in we put the API for the use of the preference in +a place visible to all objects that have access to this plug-in. Normally we +would use the PreferenceConverter for conversion to and from the storage format.</p> +<p>Methods for getting the default value of the +preference and a getter and a setter are +defined first - getBadWordsDefaultPreference (which returns an array of Strings), +getBadWordsPreference (which also returns an array of Strings) and +setBadWordsPreference which takes an array of Strings as its argument. The +String array is stored in the preference store as a single string separated by semicolons. We choose +semicolons as this character is only ever used as punctuation and will therefore never +be part of a word we are searching for.</p> +<pre>/** + * Return the bad words preference default. + */ +public String[] getDefaultBadWordsPreference(){ + return convert(getPreferenceStore().getDefaultString(BAD_WORDS_PREFERENCE)); +} + +/** + * Returns the bad words preference. + */ +public String[] getBadWordsPreference() { + return convert(getPreferenceStore().getString(BAD_WORDS_PREFERENCE)); +} + +/** + * Converts PREFERENCE_DELIMITER delimited String to a String array. + */ +private String[] convert(String preferenceValue) { + StringTokenizer tokenizer = + new StringTokenizer(preferenceValue, PREFERENCE_DELIMITER); + int tokenCount = tokenizer.countTokens(); + String[] elements = new String[tokenCount]; + for (int i = 0; i < tokenCount; i++) { + elements[i] = tokenizer.nextToken(); + } + + return elements; +} + +/** + * Sets the bad words preference. + */ +public void setBadWordsPreference(String[] elements) { + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < elements.length; i++) { + buffer.append(elements[i]); + buffer.append(PREFERENCE_DELIMITER); + } + getPreferenceStore().setValue(BAD_WORDS_PREFERENCE, buffer.toString()); +} +</pre> +<p>There is no field editor defined in JFace +for editing String arrays so we will define a list that shows the +items with widgets to add and remove them. Our performOK method will send the +current contents of the list to the setBadWordsPreference method and the +performDefaults method will reset the list of strings to be the result of +getDefaultBadWordsPreference. Both methods are defined in BadWordCheckerPlugin. As a List widget takes an array of Strings as its +content we can use the results of these helper methods directly +in conjunction with the methods we defined for the bad words preference in the +plug-in. The performOK and performDefaults for this preference page use these +methods to update the preference and reset the values in the list widget +respectively. See Figure 3 for the Bad Words preference page. +</p> +<pre>/** + * Sets the contents of the nameEntry field to be the default + */ +protected void performDefaults() { + badWordList.setItems(BadWordCheckerPlugin.getDefault().getDefaultBadWordsPreference()); +} +/** + * Saves the author name to the preference store. + */ +public boolean performOk() { + BadWordCheckerPlugin.getDefault().setBadWordsPreference(badWordList.getItems()); + return super.performOk(); +}</pre> +<p align="center"><img border="0" src="images/badwordpreference.gif" width="606" height="532"> +</p> +<p align="center"><b>Figure 3</b>: Preference dialog showing Bad Words preference + page </p> +<h2>Propagating Values With IPropertyChangeListener +</h2> +<p>Frequently a preference is +used to set a value in another object or needs to be applied to an open editor +or view. When this is required you can listen for these changes with an +IPropertyChangeListener. IPropertyChangeListener is a class that is used to add a listener to an +IPropertyStore so that the listener is informed whenever a change is made. Change +notifications are issued whenever a preference is changed in the preference +store with setValue(); this typically happens when the user hits OK or Apply in a +preference dialog, or when a previously saved preference setting is imported.</p> +<p>In the bad word checker example we have implemented a view that displays the +bad words for a file highlighted in the selected Color (see attached code). This +view has a IPropertyChangeListener defined on it that updates the display color +when it changes (see <img border="0" src="images/tag_1.gif" width="24" height="13">). +When the view is created it is added as an IPropertyChangeListener on the +preference store in the init(IViewSite) method (see <img border="0" src="images/tag_2.gif" width="24" height="13">). +We also remove it as a listener on the preference store when we dispose of it so +that any further changes to the preference store do not try and refer to a +disposed page (see <img border="0" src="images/tag_3.gif" width="24" height="13">). +The init(IViewSite) method is defined on IViewPart and the dispose() method is +defined on IWorkbenchPart. +</p> +<pre> +<img border="0" src="images/tag_1.gif" width="24" height="13"> new IPropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + if (event.getProperty().equals(BadWordCheckerPlugin.HIGHLIGHT_PREFERENCE)) { + //Update the colors by clearing the current color, + //updating the view and then disposing the old color. + Color oldForeground = foreground; + foreground = null; + setBadWordHighlights(text.getText()); + oldForeground.dispose(); + } + if (event.getProperty().equals(BadWordCheckerPlugin.BAD_WORDS_PREFERENCE)) + //Only update the text if only the words have changed + setBadWordHighlights(text.getText()); + } +};</pre> + +<pre> +<img border="0" src="images/tag_2.gif" width="24" height="13"> public void init(IViewSite site) throws PartInitException { + super.init(site); + site.getPage().addSelectionListener(...); + BadWordCheckerPlugin + .getDefault() + .getPreferenceStore() + .addPropertyChangeListener(preferenceListener);} +</pre> +<pre> +<img border="0" src="images/tag_3.gif" width="24" height="13"> public void dispose() { + getSite().getPage().removeSelectionListener(...); + BadWordCheckerPlugin + .getDefault() + .getPreferenceStore() + .removePropertyChangeListener(preferenceListener); + if (foreground != null) + foreground.dispose(); + super.dispose(); +} +</pre> + +<h2>Importing and Exporting Preference Settings +</h2> +<p>As of Eclipse 2.0 there is now a facility to import and export your preferences so +that you can reload them when you get a new workspace. This can be done by use +of the Import and Export buttons on the preferences dialog. The currently set +preferences are stored in a .epf file that you specify when you export. Any +preference that is still set to it's default value will not be saved in this +file. When you import from a .epf file any preferences defined in that file will +be set to the value stored. Preferences not stored in the .epf file are not +affected. +</p> +<p>If your preferences just +use the preference store for storing and retrieving values then there is no more +work to do to when writing your preferences as they will be saved and restored +as part of the import and export support for preference stores. Should you need +to have extra functionality executed when preferences are imported you can use +an IPropertyChangeListener +</p> + +<h2>Conclusions +</h2> +<p>In this article we have demonstrated how to use the preferences store and +preferences pages provided by Eclipse to allow a plug-in to maintain and update +preferences between Eclipse sessions and to import and export them using the +preference dialog. By use of the preference store in +conjunction with the preferences dialog and provided field editors a plug-in +developer can quickly put together a user interface for managing preferences. To +find out more about the preferences that Eclipse provides see the Platform +Plug-in Developers Guide in the Help Perspective. The help information is in the +Programmers Guide Preferences and Properties section. +</p> +<p>The full implementation of the example in this article can be found in <a href="preferences.zip">preferences.zip</a>. +</p> + +<p><small>Java and all Java-based trademarks and logos are trademarks or registered +trademarks of Sun Microsystems, Inc. in the United States, other countries, or +both.</small></p> + +</body> + +</html> |