Reader small image

You're reading from  Eclipse Plug-in Development Beginner's Guide - Second Edition

Product typeBook
Published inAug 2016
Reading LevelExpert
Publisher
ISBN-139781783980697
Edition2nd Edition
Languages
Tools
Right arrow
Author (1)
Alex Blewitt
Alex Blewitt
author image
Alex Blewitt

contacted on 30 aug 16 _____________ Dr Alex Blewitt has over 20 years of experience in Objective-C and has been using Apple frameworks since NeXTstep 3.0. He upgraded his NeXTstation for a TiBook when Apple released Mac OS X in 2001 and has been developing on it ever since. Alex currently works for an investment bank in London, writes for the on-line technology news site InfoQ and has published two other books for Packt publishing. He also has a number of apps on the Apple AppStore through Bandlem Limited. When he's not working on technology, and if the weather is nice, he likes to go flying from the nearby Cranfield airport. Alex writes regularly at his blog, http://alblue.bandlem.com, as well tweeting regularly from Twitter as @alblue. Acknowledgements This book would not have been possible without the ongoing love and support of my wife Amy, who has helped me through both the highs and lows of life. She gave me the freedom to work during the many late nights and weekends that it takes to produce a book and its associated code repository. She truly is the Lem of my life. I'd also like to thank my parents, Ann and Derek, for their encouragement and support during my formative years. It was this work ethic that allowed me to start my technology career as a teenager and to incorporate my first company before I was 25. I'd also like to congratulate them on their 50th wedding anniversary in 2015, and I look forward to reaching that goal with Amy. Thanks are due especially to the reviewer of this version of the book: Antonio Bello, as well as the previous version of this book: Nate Cook, James Robert and Arvid Gerstmann, who provided excellent feedback on the contents of this book during development and caught many errors in both the text and code. Any remaining errors are my own. I'd also like to thank my children Sam and Holly for inspiring me and hope that they too can achieve anything that they set their minds to. Finally, I'd like to thank Ben Moseley and Eren Kotan, both of whom introduced me to NeXT in the first place and set my career going on a twenty year journey to this book.
Read more about Alex Blewitt

Right arrow

Chapter 5. Working with Preferences

Preferences – customizing the runtime

An IDE is powerful if it provides a number of different utility windows to help the developer as they do their job. It becomes more powerful when they can customize it to their tastes, whether it is something as simple as colors or more targeted as filters. The preference store in Eclipse allows users to customize it in the way they want.

In this chapter, we will:

  • Read and write preferences from a PreferenceStore

  • Create a PreferencePage using FieldEditors

Eclipse Preferences


A user preference is a stored configuration option that persists between different Eclipse runtimes. Preferences are simple values (such as int, String, and boolean) and are identified with a String key, typically associated with the plug-in's identifier. Preferences can also be edited via a standard preference panel, contributed through an extension point.

They can also be imported and exported from an Eclipse workbench by navigating to File | Import/Export | Preferences, and saved with an epf extension (short for Eclipse Preference File).

Time for action – persisting a value


To save and load preferences, an instance of Preferences (from the org.osgi.service.prefs package) is typically obtained from an instance of InstanceScope (from the org.eclipse.core.runtime.preferences package). The INSTANCE singleton returns an instance of Preferences that has a getNode method. This returns a store that can be used to persist key/value pairs.

  1. Open the Activator of the com.packtpub.e4.clock.ui plug-in.

  2. Add the following to the start method to count the number of times the plug-in has been launched:

    // import org.osgi.service.prefs.Preferences;
    // import org.eclipse.core.runtime.preferences.InstanceScope;
    // ^ add these if necessary to top of the class
    Preferences preferences =
     InstanceScope.INSTANCE.getNode("com.packtpub.e4.clock.ui");
    int launchCount = preferences.getInt("launchCount", 0)+1;
    System.out.println("I have been launched "+launchCount+" times");
    preferences.putInt("launchCount", launchCount);
    preferences.sync();
  3. Run the target...

Time for action – injecting preferences


The top-level preferences store can be injected into the object by using standard dependency injection techniques, using the IEclipsePreferences interface. The underlying nodes can also be injected by using an @Preferences annotation, specifying the node path of interest.

  1. Add the org.eclipse.e4.core.di.extensions package to the manifest of the com.packtpub.e4.clock.ui project, which contains the @Preferences annotation.

  2. In the TimeZoneTreeView class, add a new field of type IEclipsePreferences called preferences. Annotate it with @Inject and @Preferences(nodePath = "com.packtpub.e4.clock.ui"):

    @Preference(nodePath = "com.packtpub.e4.clock.ui")
    @Inject
    IEclipsePreferences preferences;

    Note

    The IEclipsePreferences interface is a subtype of the Preferences interface used in the previous section. However, the @Preference annotation requires that the IEclipsePreferences type be used here; otherwise a runtime exception will occur.

  3. In the create method, print a...

Time for action – injecting individual preferences


Although it is possible to inject an entire preference node, sometimes it is more convenient to inject just a single preference value. This can reduce the amount of code needed to extract and use a preference value. In addition, this can remove the runtime dependency on IEclipsePreferences, which can make the code more portable.

  1. Replace the injected IEclipsePreferences node with an int launchCount field, and append value = "launchCount" to the @Preferences annotation:

    @Preference(nodePath = "com.packtpub.e4.clock.ui",
     value = "launchCount")
    @Inject
    // IEclipsePreferences preferences;
    int launchCount;
  2. Update the print message to use the launchCount value directly:

    System.out.println("Launch count is: " + launchCount);
  3. Run the target Eclipse instance, and open the Time Zone Tree View. In the Console view, there should be a Launch count is: message with the same value as before.

What just happened?

Instead of injecting the entire preferences node...

Time for action – responding to preference changes


In order to react when preferences are changed, it is necessary to inject the preference value as part of a method call. When the preference value is changed, the method will be invoked again with the new value.

  1. Remove the annotations associated with the launchCount instance field.

  2. Create a setLaunchCount method that takes an int argument and assigns it to the launchCount instance field.

    Tip

    Type setL and press Ctrl + space to suggest creating this method automatically.

  3. Add the @Inject annotation to the setLaunchCount method.

  4. Add the @Preference(nodePath = "com.packtpub.e4.clock.ui", value = "launchCount") annotation to the method argument. The resulting method will look like this:

    int launchCount;
    
    @Inject
    public void setLaunchCount(
     @Preference(nodePath = "com.packtpub.e4.clock.ui",
       value = "launchCount") int launchCount) {
      this.launchCount = launchCount;
    }
  5. Run the target Eclipse instance, and open the Time Zone Tree View. In the Console...

Preference pages


Preference pages are a type of user interface used in the Eclipse workbench that allow the user to search and change preferences. These are contributed as extensions of the org.eclipse.ui.preferencePages point, and can present preferences with a number of standard editors or with custom content.

Time for action – creating a preference page


Although preferences can be stored programmatically, users will typically change them through the user interface. The canonical way of presenting preferences is through a preference page in Eclipse, which can be accessed through the Preferences menu. A preference page implements the IPreferencePage interface, but the easiest way is to use the FieldEditorPreferencePage as a superclass, which provides most of the standard plug-in behavior needed, along with the IWorkbenchPreferencePage interface.

  1. Open the plugin.xml of the com.packtpub.e4.clock.ui plug-in. To declare a new preference page, use the org.eclipse.ui.preferencePages extension point. Add the following:

    <extension point="org.eclipse.ui.preferencePages">
      <page name="Clock"
            class="com.packtpub.e4.clock.ui.ClockPreferencePage"
            id="com.packtpub.e4.clock.ui.preference.page"/>
    </extension>

    Note

    The same effect can be achieved by editing plugin.xml in the editor...

Time for action – creating warning and error messages


In free-form text fields, it's sometimes possible to enter a value that isn't valid. For example, when asking for an e-mail address, it might be necessary to validate it against some kind of regular expression such as .+@.+ to provide a simple check.

  1. To test the default validation, run the target Eclipse instance and go to the Clock preference page. Type some text in the numeric field. A warning message, Value must be an integer, will be displayed:

  2. To add validation, create a new field called offset that allows values between -14 and +12 (by default, IntegerFieldEditor validates against the 0..MAX_INT range). Add the following to the createFieldEditors method:

    IntegerFieldEditor offset = new IntegerFieldEditor("offset","Current offset from GMT", getFieldEditorParent());offset.setValidRange(-14, +12);addField(offset);
  3. Run the target Eclipse instance, go to the Clock preference page, and type in an invalid value:

What just happened?

Each field...

Time for action: choosing from a list


Although free text may be appropriate for some types of preference, choosing from a set of values may be more appropriate for other types. A ComboFieldEditor instance can be used to present the user with a selection of time zones, from which the user can set their favorite ZoneId. The combo drop-down is built from an array of pairs of strings; the first string in each pair is the display label, while the second value in each pair is the string identifier that will be persisted in the preferences store.

  1. In the ClockPreferencePage method createFieldEditors, add the following code to populate a ComboFieldEditor with the list of ZoneId elements:

    protected void createFieldEditors() {// ...
      String[][] data = ZoneId.getAvailableZoneIds() //
       .stream().sorted().map(s -> new String[] { s, s }) //
       .collect(Collectors.toList()).toArray(new String[][] {});addField(new ComboFieldEditor("favorite","Favorite time zone", data, getFieldEditorParent()));}
  2. Run the...

Time for action – aligning field editors with a grid


The preference values weren't lined up as might be expected. This is because the default preference field editor uses a FLAT style of rendering, which simply lays out the fields similar to a vertical RowLayout.

  1. Change it to be a more natural look by specifying a GRID style of rendering:

    public ClockPreferencePage() {
      super(GRID);
    }
  2. Now, when the preference page is displayed, it will look more natural:

What just happened?

The default FLAT style does not render well. It was added in 2007 before the popularity of the grid layout increased and typically needs to be overridden to provide a decent user interface experience. Switching to GRID does this, by working out the label length and field lengths and setting up the split accordingly. Furthermore, the view is resizable, with the fields taking up additional stretch space.

If the layout needs further customization or the widget set needs to be extended, then it is possible to create a plain...

Time for action – placing the preferences page


When the preference page is created, if it does not specify a location (known as a category in the plugin.xml file and manifest editor), it is inserted into the top level. This is appropriate for some kinds of project (for example, Mylyn, Java, and Plug-in Development); but many plug-ins should contribute into an existing location in the preference page tree.

  1. Preference pages can be nested by specifying the parent preference page's ID. To move the Clock preference page underneath the General preference page, specify org.eclipse.ui.preferencePages.Workbench as the category:

    <extension point="org.eclipse.ui.preferencePages">
    <page name="Clock"id="com.packtpub.e4.clock.ui.preference.page"category="org.eclipse.ui.preferencePages.Workbench"class="com.packtpub.e4.clock.ui.ClockPreferencePage"/>
    </extension>
  2. Run the target Eclipse instance and look at the Preferences. The Clock preference page should now be under the General tree node...

Time for action: using other field editors


The FieldEditorPreferencePage supports other types of field editors. These different types include BooleanFieldEditor, ColorFieldEditor, ScaleFieldEditor, FileFieldEditor, DirectoryFieldEditor, PathEditor, and RadioGroupFieldEditor. Add a sample of each of these types to the Clock preference page to find out what they can store.

  1. Open the createFieldEditors method of ClockPreferencePage and add the following at the bottom of the method:

    addField(new BooleanFieldEditor("tick", "Boolean value",
    getFieldEditorParent()));
    addField(new ColorFieldEditor("color", "Favorite color",
    getFieldEditorParent()));
    addField(new ScaleFieldEditor("scale", "Scale",
    getFieldEditorParent(), 0, 360, 10, 90));
    addField(new FileFieldEditor("file", "Pick a file",
    getFieldEditorParent()));
    addField(new DirectoryFieldEditor("dir", "Pick a directory",
    getFieldEditorParent()));
    addField(new PathEditor("path", "Path",
    "Directory", getFieldEditorParent()));
    addField(new RadioGroupFieldEditor...

Time for action – searching for preferences


Eclipse has a search field in the preferences list. This is defined not from the UI but from a separate keyword extension instead. The keyword has an id and a label. The label is a space-separated list of words that can be used in the filtering dialog.

  1. To add the offset and timezone keywords to ClockPreferencePage, create a new extension point in plugin.xml for org.eclipse.ui.keywords:

    <extension point="org.eclipse.ui.keywords">
    <keyword id="com.packtpub.e4.clock.ui.keywords"label="offset timezone"/>
    </extension>
  2. Now associate these keywords with the preference page itself:

    <extension point="org.eclipse.ui.preferencePages">
    <page name="Clock" ... ><keywordReference id="com.packtpub.e4.clock.ui.keywords"/>
    </page>
    </extension>
  3. Run the target Eclipse instance, go to the Preferences page, and type timezone or offset in the search box. The Clock preference page should be shown in both cases:

What just happened...

Summary


We covered the mechanisms that Eclipse uses to store metadata values. A preference store is the key/value pair mechanism used by preference pages as well as interacted with programmatically from headless plug-ins.

In the next chapter, we will see how to work with Resource objects inside Eclipse.

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Eclipse Plug-in Development Beginner's Guide - Second Edition
Published in: Aug 2016Publisher: ISBN-13: 9781783980697
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime

Author (1)

author image
Alex Blewitt

contacted on 30 aug 16 _____________ Dr Alex Blewitt has over 20 years of experience in Objective-C and has been using Apple frameworks since NeXTstep 3.0. He upgraded his NeXTstation for a TiBook when Apple released Mac OS X in 2001 and has been developing on it ever since. Alex currently works for an investment bank in London, writes for the on-line technology news site InfoQ and has published two other books for Packt publishing. He also has a number of apps on the Apple AppStore through Bandlem Limited. When he's not working on technology, and if the weather is nice, he likes to go flying from the nearby Cranfield airport. Alex writes regularly at his blog, http://alblue.bandlem.com, as well tweeting regularly from Twitter as @alblue. Acknowledgements This book would not have been possible without the ongoing love and support of my wife Amy, who has helped me through both the highs and lows of life. She gave me the freedom to work during the many late nights and weekends that it takes to produce a book and its associated code repository. She truly is the Lem of my life. I'd also like to thank my parents, Ann and Derek, for their encouragement and support during my formative years. It was this work ethic that allowed me to start my technology career as a teenager and to incorporate my first company before I was 25. I'd also like to congratulate them on their 50th wedding anniversary in 2015, and I look forward to reaching that goal with Amy. Thanks are due especially to the reviewer of this version of the book: Antonio Bello, as well as the previous version of this book: Nate Cook, James Robert and Arvid Gerstmann, who provided excellent feedback on the contents of this book during development and caught many errors in both the text and code. Any remaining errors are my own. I'd also like to thank my children Sam and Holly for inspiring me and hope that they too can achieve anything that they set their minds to. Finally, I'd like to thank Ben Moseley and Eren Kotan, both of whom introduced me to NeXT in the first place and set my career going on a twenty year journey to this book.
Read more about Alex Blewitt