|  | <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 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="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> December 15, 2001</p> | 
|  | </blockquote> | 
|  | <HR width="100%"> | 
|  |  | 
|  | <h2>Introduction</h2> | 
|  | <p>The Eclipse Platform has support for user defined preferences that are | 
|  | persisted along with the workbench. 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. 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 documents 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 workbench sessions to allow | 
|  | the user to keep the state of a plug-in consistent between Eclipse sessions. Typical preferences are | 
|  | default values for new instances, colors for editors and paths, or processing | 
|  | information for operations performed on data (such as a build path for a Java™ | 
|  | file). | 
|  | </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 | 
|  | workbench 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 UI plug-in has it's own preference store provided by the workbench. 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="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="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="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="tag_1.gif" width="24" height="13">	public static final String BAD_WORDS_PREFERENCE = | 
|  | "org.eclipse.ui.articles.badwordchecker.badwords"; | 
|  | public static final String HIGHLIGHT_PREFERENCE = | 
|  | "org.eclipse.ui.articles.badwordchecker.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; | 
|  |  | 
|  | /** | 
|  | * The constructor. | 
|  | */ | 
|  | public BadWordCheckerPlugin(IPluginDescriptor descriptor) { | 
|  | super(descriptor); | 
|  | <img border="0" src="tag_2.gif" width="24" height="13">		plugin = this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the shared instance. | 
|  | */ | 
|  | public static BadWordCheckerPlugin getDefault() { | 
|  | return plugin; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Initializes a preference store with default preference values | 
|  | * for this plug-in. | 
|  | * @param store the preference store to fill | 
|  | */ | 
|  | protected void initializeDefaultPreferences(IPreferenceStore store) { | 
|  | <img border="0" src="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="org.eclipse.ui.articles.BadWordsPreference" | 
|  | <img border="0" src="tag_1.gif" width="24" height="13"> 		name="Bad Words" | 
|  | <img border="0" src="tag_2.gif" width="24" height="13">    		class="org.eclipse.ui.articles.badwordchecker.BadWordsPreferencePage"> | 
|  | </page> | 
|  |  | 
|  | <page id="org.eclipse.ui.articles.BadWordsColorPreference" | 
|  | name="Colors" | 
|  | class="org.eclipse.ui.articles.badwordchecker.BadWordsColorPreferencePage" | 
|  | <img border="0" src="tag_3.gif" width="24" height="13">		category="org.eclipse.ui.articles.BadWordsPreference"> | 
|  | </page> | 
|  | </extension></pre> | 
|  | <p>The definition above sets the name (<img border="0" src="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="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="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:</p> | 
|  | <p align="center"><img border="0" src="tree.jpg" width="179" height="284"></p> | 
|  | <p align="center">The Preference Dialog Tree with the Bad Words and Color Page | 
|  | Added</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. The class definition for our preference page is:</p> | 
|  | <pre>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.</p> | 
|  | <pre>/** | 
|  | * Performs special processing when this page's Restore Defaults button has | 
|  | * been pressed. | 
|  | * Sets the contents of the color field to the default value in the preference | 
|  | * store. | 
|  | */ | 
|  | protected void performDefaults() { | 
|  | colorEditor.loadDefault(); | 
|  | } | 
|  | /** | 
|  | * Method declared on IPreferencePage. 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="colorpreference.jpg" width="598" height="541"></p> | 
|  | <p align="center">The Color 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 are 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 | 
|  | * as an array of Strings. | 
|  | * @return String[] | 
|  | */ | 
|  | public String[] getDefaultBadWordsPreference(){ | 
|  | return convert(getPreferenceStore().getDefaultString(BAD_WORDS_PREFERENCE)); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Return the bad words preference as an array of | 
|  | * Strings. | 
|  | * @return String[] | 
|  | */ | 
|  | public String[] getBadWordsPreference() { | 
|  | return convert(getPreferenceStore().getString(BAD_WORDS_PREFERENCE)); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Convert the supplied PREFERENCE_DELIMITER delimited | 
|  | * String to a String array. | 
|  | * @return String[] | 
|  | */ | 
|  | 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; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Set the bad words preference | 
|  | * @param String [] elements - the Strings to be | 
|  | * 	converted to the preference value | 
|  | */ | 
|  | 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 from 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. | 
|  | </p> | 
|  | <pre>/** | 
|  | * Performs special processing when this page's Restore Defaults button has been pressed. | 
|  | * Sets the contents of the nameEntry field to | 
|  | * be the default | 
|  | */ | 
|  | protected void performDefaults() { | 
|  | badWordList.setItems(BadWordCheckerPlugin.getDefault().getDefaultBadWordsPreference()); | 
|  | } | 
|  | /** | 
|  | * Method declared on IPreferencePage. Save 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="badwordpreference.jpg" width="596" height="539"> | 
|  | </p> | 
|  | <p align="center">The Bad Word Preference Dialog | 
|  | </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. 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> |