Commits

sk  committed 57865bb

(no commit message)

  • Participants

Comments (0)

Files changed (19)

+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.lispdev.preferences</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

File .settings/org.eclipse.jdt.core.prefs

+#Mon Jul 06 14:45:35 BST 2009
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6

File META-INF/MANIFEST.MF

+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Preferences
+Bundle-SymbolicName: org.lispdev.preferences
+Bundle-Version: 0.0.0.qualifier
+Bundle-Activator: org.lispdev.preferences.Plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.core.resources;bundle-version="3.5.0"
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Export-Package: org.lispdev.preferences,
+ org.lispdev.preferences.fields

File build.properties

+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .
+How to use preferences:
+
+Instantiate PreferencesService class with the name of language (for example "CL").
+In editor plugin the class is instantiated at plugin startup. Also right after
+PreferenceService initialization call init() function of Preference class (see
+next para) to register default values.
+
+Create enum class to keep preference items (see Preference class: org.lispdev.editor.preferences.Preference).
+This class creates preference items. Each item has preference id, name, tooltip, type and default value.
+Type is one of the PreferenceType.
+
+Create preference page by extending ItemPreferencesPage. The page have to implement createFieldEditors, which
+should populate protected itemEditors list. There are two ways to add editors - one is creating an editor
+manually and adding it to the list. The other, much simpler is to call addDefaultItemField function with
+a corresponding item. Depending on item type its default editor will be created and associated with the item.
+Add extension to org.eclipse.ui.preferencePages extension point. In extension refer to
+the class of this page.
+
+Register and unregister objects with preference items. An object should implement ItemListener interface.
+To add object to an item listener, get hold of the corresponding enum, get item from it, and add the object as a
+listener at creation or when necessary:
+     Preference.COLOR_INNER.item().addListener(EditorPlugin.get().getPreferences(), this);
+Preference change events are processed by handleChange function of ItemListener interface.
+Finally cleanup by unregistering the object from items it listens to:
+    Preference.COLOR_INNER.item().removeListener(this);
+

File src/org/lispdev/preferences/ItemEditorFactory.java

+package org.lispdev.preferences;
+
+import org.eclipse.jface.preference.FieldEditor;
+import org.eclipse.swt.widgets.Composite;
+import org.lispdev.preferences.fields.BooleanItemEditor;
+import org.lispdev.preferences.fields.ColorItemEditor;
+import org.lispdev.preferences.fields.NumberItemEditor;
+import org.lispdev.preferences.fields.StringItemEditor;
+
+public class ItemEditorFactory
+{
+  static public FieldEditor getEditor(PreferenceItem item, Composite parent,
+      PreferencesService service)
+  {
+    switch( item.type )
+    {
+      case BOOLEAN :
+        return new BooleanItemEditor(item, parent, service);
+      case INT :
+      case LONG :
+      case DOUBLE :
+      case FLOAT :
+        return new NumberItemEditor(item, parent, service);
+      case STRING :
+        return new StringItemEditor(item, parent, service);
+      case COLOR :
+        return new ColorItemEditor(item, parent, service);
+      default :
+        return null;
+    }
+  }
+}

File src/org/lispdev/preferences/ItemListener.java

+package org.lispdev.preferences;
+
+public interface ItemListener
+{
+  void handleChange(PreferenceItem item, Object oldValue, Object newValue);
+}

File src/org/lispdev/preferences/ItemPreferencesPage.java

+package org.lispdev.preferences;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.preference.FieldEditor;
+import org.eclipse.jface.preference.FieldEditorPreferencePage;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+public abstract class ItemPreferencesPage extends FieldEditorPreferencePage
+implements IWorkbenchPreferencePage
+{
+  protected Composite fieldEditors;
+  protected PreferencesService service;
+  protected List<FieldEditor> itemEditors;
+
+  /**
+   * @param service preference service for the page
+   * @param style either <code>GRID</code> or <code>FLAT</code>
+   * @param title title for the page
+   * @param image image for the page or <code>null</code> if none
+   */
+  public ItemPreferencesPage(PreferencesService service, int style,
+      String title, ImageDescriptor image)
+  {
+    super(title,image,style);
+    this.service = service;
+  }
+
+  @Override
+  protected Control createContents(Composite parent)
+  {
+    itemEditors = new ArrayList<FieldEditor>();
+    Composite result = new Composite(parent, SWT.NULL);
+    final GridLayout layout = new GridLayout();
+    layout.numColumns = 1;
+    layout.marginHeight = 0;
+    layout.marginWidth = 0;
+    result.setLayout(layout);
+    result.setFont(parent.getFont());
+
+    fieldEditors = (Composite)super.createContents(result);
+
+    return result;
+  }
+
+  protected void addDefaultItemField(PreferenceItem item)
+  {
+    FieldEditor e = ItemEditorFactory.getEditor(
+        item,getFieldEditorParent(), service);
+    itemEditors.add(e);
+    addField(e);
+  }
+
+}

File src/org/lispdev/preferences/Plugin.java

+package org.lispdev.preferences;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ *
+ */
+public class Plugin extends AbstractUIPlugin
+{
+
+  // The plug-in ID
+  public static final String ID = "org.lispdev.preferences";
+
+  // The shared instance
+  private static Plugin plugin;
+
+  /**
+   * The constructor
+   */
+  public Plugin()
+  {}
+
+  private static Display getDisplay()
+  {
+    Display display = Display.getCurrent();
+    //may be null if outside the UI thread
+    if (display == null)
+       display = Display.getDefault();
+    return display;
+ }
+
+  public Color colorBlack = getDisplay().getSystemColor(SWT.COLOR_BLACK);
+  public Color colorWhite = getDisplay().getSystemColor(SWT.COLOR_WHITE);
+  public Color colorRed = getDisplay().getSystemColor(SWT.COLOR_RED);
+  public Color colorBluish;
+  public Color colorGreenish;
+  public Color colorLightGray;
+
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see
+   * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
+   * )
+   */
+  @Override
+  public void start(BundleContext context) throws Exception
+  {
+    super.start(context);
+    plugin = this;
+    colorBluish = new Color(null, 175, 207, 239);;
+    colorGreenish = new Color(null, 0, 127, 239);
+    colorLightGray = new Color(null, 224, 223, 226);
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see
+   * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
+   * )
+   */
+  @Override
+  public void stop(BundleContext context) throws Exception
+  {
+    colorBluish.dispose();
+    colorGreenish.dispose();
+    colorLightGray.dispose();
+    plugin = null;
+    super.stop(context);
+  }
+
+  /**
+   * Returns the shared instance
+   *
+   * @return the shared instance
+   */
+  public static Plugin get()
+  {
+    return plugin;
+  }
+}

File src/org/lispdev/preferences/PreferenceItem.java

+package org.lispdev.preferences;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
+import org.eclipse.jface.resource.StringConverter;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.RGB;
+
+public class PreferenceItem
+{
+  final public String id;
+  final public PreferenceType type;
+  final public Object defaultValue;
+  final public String label;
+  final public String tooltip;
+
+  private Map<ItemListener, PreferenceServiceListener> listeners =
+    Collections.synchronizedMap( new HashMap<ItemListener, PreferenceServiceListener>() );
+
+
+  public PreferenceItem(String id, PreferenceType type, Object defaultValue,
+      String label, String tooltip)
+  {
+    this.id = id;
+    this.type = type;
+    this.defaultValue = defaultValue;
+    this.label = label;
+    this.tooltip = tooltip;
+  }
+
+  public void set(boolean setDefault, PreferencesService service, Object value)
+  {
+    switch( type )
+    {
+      case BOOLEAN:
+        if( value instanceof Boolean )
+        {
+          service.setBooleanPreference(setDefault, id, (Boolean)value);
+        }
+        else if ( value instanceof String )
+        {
+          service.setBooleanPreference(setDefault, id,
+              StringConverter.asBoolean((String)value));
+        }
+        break;
+      case INT:
+        if( value instanceof Number )
+        {
+          service.setIntPreference(setDefault, id, (Integer)value);
+        }
+        else if ( value instanceof String )
+        {
+          service.setIntPreference(setDefault,
+              id, Integer.parseInt((String)value) );
+        }
+        else
+        {
+          Assert.isLegal(false, "Bad value object");
+        }
+        break;
+      case LONG:
+        if( value instanceof Number )
+        {
+          service.setLongPreference(setDefault, id, (Long)value);
+        }
+        else if ( value instanceof String )
+        {
+          service.setLongPreference(setDefault,
+              id, Long.parseLong((String)value) );
+        }
+        else
+        {
+          Assert.isLegal(false, "Bad value object");
+        }
+        break;
+      case DOUBLE:
+        if( value instanceof Number )
+        {
+          service.setDoublePreference(setDefault, id, (Double)value);
+        }
+        else if ( value instanceof String )
+        {
+          service.setDoublePreference(setDefault,
+              id, Double.parseDouble((String)value));
+        }
+        else
+        {
+          Assert.isLegal(false, "Bad value object");
+        }
+        break;
+      case FLOAT:
+        if( value instanceof Number )
+        {
+          service.setFloatPreference(setDefault, id, (Float)value);
+        }
+        else if ( value instanceof String )
+        {
+          service.setFloatPreference(setDefault,
+              id, Float.parseFloat((String)value));
+        }
+        else
+        {
+          Assert.isLegal(false, "Bad value object");
+        }
+        break;
+      case COLOR:
+        if( value instanceof RGB )
+        {
+          service.setStringPreference(setDefault,
+              id, StringConverter.asString((RGB)value));
+        }
+        else if ( value instanceof String )
+        {
+          RGB r = StringConverter.asRGB((String)value);
+          set(setDefault, service, r);
+        }
+        else
+        {
+          Assert.isLegal(false, "Bad value object");
+        }
+        break;
+      case FONT:
+        if( value instanceof FontData[] )
+        {
+          service.setStringPreference(setDefault, id,
+              StringConverter.asString((FontData[])value) );
+        }
+        else if ( value instanceof String )
+        {
+          FontData[] fd = StringConverter.asFontDataArray((String)value);
+          set(setDefault, service, fd);
+        }
+        else
+        {
+          Assert.isLegal(false, "Bad value object");
+        }
+        break;
+      default:
+        if( value instanceof String )
+        {
+          service.setStringPreference(setDefault, id, (String)value);
+        }
+        else
+        {
+          Assert.isLegal(false, "Bad value object");
+        }
+    }
+  }
+
+  private Object get(boolean getDefault, PreferencesService service)
+  {
+    switch( type )
+    {
+      case BOOLEAN:
+        return Boolean.valueOf(service.getBooleanPreference(getDefault, id));
+      case INT:
+        return Integer.valueOf(service.getIntPreference(getDefault, id));
+      case LONG:
+        return Long.valueOf(service.getLongPreference(getDefault, id));
+      case DOUBLE:
+        return Double.valueOf(service.getDoublePreference(getDefault, id));
+      case FLOAT:
+        return Float.valueOf(service.getFloatPreference(getDefault, id));
+      case COLOR:
+        return StringConverter.asRGB(service.getStringPreference(getDefault, id));
+      case FONT:
+        return StringConverter.asFontDataArray(service.getStringPreference(getDefault, id));
+      default:
+        return service.getStringPreference(getDefault, id);
+    }
+  }
+
+  public Object getDefault(PreferencesService service)
+  {
+    return get(true, service);
+  }
+
+  public Object get(PreferencesService service)
+  {
+    return get(false, service);
+  }
+
+  /**
+   * True if preference is not set at the level which is current for service.
+   * I.e. if it is requested at this level, it will be obtained from a parent.
+   */
+  public boolean isDefault(PreferencesService service)
+  {
+    return service.isDefault(id);
+  }
+
+  /**
+   * Clears preference at the level which is current for the service.
+   * @param service
+   */
+  public void clear(PreferencesService service)
+  {
+    service.clearPreference(id);
+  }
+
+  public void initDefault(PreferencesService service)
+  {
+    set(true, service, defaultValue);
+  }
+
+  /**
+   * disposes listeners
+   */
+  public void dispose()
+  {
+    for( PreferenceServiceListener psl : listeners.values() )
+    {
+      psl.dispose();
+    }
+  }
+
+  /**
+   * Can have one listener per il. If there is one exist
+   *  (even for different service) it is removed.
+   * @param service
+   * @param il
+   */
+  public void addListener(PreferencesService service, ItemListener il)
+  {
+    PreferenceServiceListener old = listeners.get(il);
+    if( old != null )
+    {
+      old.dispose();
+    }
+    listeners.put(il, new PreferenceServiceListener(service, this, il));
+  }
+
+  public void removeListener(ItemListener il)
+  {
+    PreferenceServiceListener old = listeners.remove(il);
+    if( old != null )
+    {
+      old.dispose();
+    }
+  }
+
+  private class PreferenceServiceListener  implements IPreferenceChangeListener
+  {
+    private final PreferenceItem fKey;
+    private final IEclipsePreferences prefs;
+    private final ItemListener iListener;
+
+    public PreferenceServiceListener(PreferencesService service,
+        PreferenceItem key, ItemListener listener)
+    {
+      fKey = key;
+      prefs = service.getPreferences();
+
+      prefs.addPreferenceChangeListener(this);
+      iListener = listener;
+    }
+
+    public void preferenceChange(PreferenceChangeEvent event)
+    {
+      if( !event.getKey().equals(fKey.id) ) return;
+      handleChange(event.getOldValue(), event.getNewValue());
+    }
+
+    public void dispose()
+    {
+      prefs.removePreferenceChangeListener(this);
+    }
+
+    private void handleChange(Object oldValue, Object newValue)
+    {
+      iListener.handleChange(fKey, oldValue, newValue);
+    }
+  }
+
+}

File src/org/lispdev/preferences/PreferenceType.java

+package org.lispdev.preferences;
+
+public enum PreferenceType
+{
+  BOOLEAN, COLOR, DOUBLE, FLOAT, INT, LONG, STRING, DIR, DIRLIST, FILE, FONT;
+}

File src/org/lispdev/preferences/PreferencesService.java

+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation. All rights reserved. This program and the
+ * accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors: Robert Fuhrer (rfuhrer@watson.ibm.com) - initial API and
+ * implementation
+ *
+ * Modified (simplified) for Lispdev: Sergey Kolos.
+ *******************************************************************************/
+
+package org.lispdev.preferences;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
+import org.osgi.service.prefs.BackingStoreException;
+
+/**
+ * Utility class to work with Eclipse preference services.
+ */
+public class PreferencesService
+{
+
+  /**
+   * Preferences are associated with this language.
+   */
+  private final String languageName;
+
+  IPreferencesService preferencesService = null;
+  IEclipsePreferences preferencesRoot = null;
+
+  /**
+   * workspace scope
+   */
+  private InstanceScope instanceScope = new InstanceScope();
+  /**
+   * default values scope
+   */
+  private DefaultScope defaultScope = new DefaultScope();
+
+  /**
+   * Create preferences service associated with this language
+   *
+   * @param languageName
+   */
+  public PreferencesService(String languageName)
+  {
+    this.languageName = languageName;
+    preferencesService = Platform.getPreferencesService();
+    preferencesRoot = (preferencesService != null) ? preferencesService
+        .getRootNode() : null;
+  }
+
+  public String getLanguageName()
+  {
+    return languageName;
+  }
+
+  /**
+   * @return preferences for instance scope
+   */
+  public IEclipsePreferences getPreferences()
+  {
+    return getNode(false);
+  }
+
+  /**
+   * @return preferences corresponding to default (when getDefault is true) or
+   *         instance scopes
+   */
+  private IEclipsePreferences getNode(boolean getDefault)
+  {
+    return (getDefault ? defaultScope.getNode(languageName) : instanceScope
+        .getNode(languageName));
+  }
+
+  /*
+   * Documentary interlude:
+   *
+   * The methods to get an applicable preference by type make use of the
+   * corresponding type-specific "get" methods in the Eclipse
+   * PreferencesService. Those methods take a qualifier (i.e., that designates a
+   * name space), a key, a default value, and a (possibly empty) list of scope
+   * contexts to be checked ahead of the standard contexts that are
+   * automatically checked in the standard order (project, instance,
+   * configuration, and default).
+   *
+   * Recall that, while the PreferencesService allows preference values to be
+   * gotten, it provides no way to set preference values. The setting of
+   * preference values has to be done through preference nodes that are
+   * associated with scope contexts.
+   *
+   * For LispDev we work only with preferences at default and instance levels.
+   * So when we want to save preference, it is definitely instance.
+   *
+   * We would like to be able to use a single qualifier to get the preferences
+   * for a particular language (e.g., qualifier "CL" for language CL). When we
+   * set a preference, we can provide just such a simple qualifier since we know
+   * the language name, e.g., in setIntPreference(String key, int value) we can
+   * get the scope for the instance level, get the preferences node for the
+   * language-name qualifier, and set the value in the node. That's simple. The
+   * instance level path to the target preference node in the preferences model
+   * is /root/instance/<languageName>.
+   */
+
+  /**
+   * @param getDefault
+   * @param key
+   * @return stored preferences value or default, or false if undefined
+   */
+  public boolean getBooleanPreference(boolean getDefault, String key)
+  {
+    if( getDefault )
+    {
+      return getNode(true).getBoolean(key, false);
+    }
+    else
+    {
+      return preferencesService.getBoolean(languageName, key, false, null);
+    }
+  }
+
+  /**
+   * @param getDefault
+   * @param key
+   * @return stored preferences value or default, or byte[0] if undefined
+   */
+  public byte[] getByteArrayPreference(boolean getDefault, String key)
+  {
+    if( !getDefault )
+    {
+      byte[] result = getNode(false).getByteArray(key, new byte[0]);
+      if( result.length != 0 )
+      {
+        return result;
+      }
+    }
+    return getNode(true).getByteArray(key, new byte[0]);
+  }
+
+  /**
+   * @param getDefault
+   * @param key
+   * @return stored preferences value or default, or 0. if undefined
+   */
+  public double getDoublePreference(boolean getDefault, String key)
+  {
+    if( getDefault )
+    {
+      return getNode(true).getDouble(key, 0);
+    }
+    return preferencesService.getDouble(languageName, key, 0, null);
+  }
+
+  /**
+   * @param getDefault
+   * @param key
+   * @return stored preferences value or default, or 0. if undefined
+   */
+  public float getFloatPreference(boolean getDefault, String key)
+  {
+    if( getDefault )
+    {
+      return getNode(true).getFloat(key, 0);
+    }
+    return preferencesService.getFloat(languageName, key, 0, null);
+  }
+
+  /**
+   * @param getDefault
+   * @param key
+   * @return stored preferences value or default, or 0 if undefined
+   */
+  public int getIntPreference(boolean getDefault, String key)
+  {
+    if( getDefault )
+    {
+      return getNode(true).getInt(key, 0);
+    }
+    return preferencesService.getInt(languageName, key, 0, null);
+  }
+
+  /**
+   * @param getDefault
+   * @param key
+   * @return stored preferences value or default, or 0 if undefined
+   */
+  public long getLongPreference(boolean getDefault, String key)
+  {
+    if( getDefault )
+    {
+      return getNode(true).getLong(key, 0);
+    }
+    return preferencesService.getLong(languageName, key, 0, null);
+  }
+
+  /**
+   * @param getDefault
+   * @param key
+   * @return stored preferences value or default, or null if undefined
+   */
+  public String getStringPreference(boolean getDefault, String key)
+  {
+    if( getDefault )
+    {
+      return getNode(true).get(key, null);
+    }
+    return preferencesService.getString(languageName, key, null, null);
+  }
+
+  /*
+   * Set preferences at a given level by type
+   */
+
+  /**
+   * Set value at default or instance scopes depending on setDefault param.
+   *
+   * @param setDefault
+   *          if true, sets default scope, otherwise - instance
+   * @param key
+   * @param value
+   */
+  public void setBooleanPreference(boolean setDefault, String key, boolean value)
+  {
+    IEclipsePreferences node = getNode(setDefault);
+    node.putBoolean(key, value);
+    try
+    {
+      node.flush();
+    }
+    catch(BackingStoreException e)
+    {
+      System.out.println("PreferencesService."
+          + "setByteArrayPreference(String, boolean):"
+          + "  BackingStoreException");
+      System.out.println("\tkey = " + key + "; value = " + value);
+    }
+  }
+
+  /**
+   * Set value at default or instance scopes depending on setDefault param.
+   *
+   * @param setDefault
+   *          if true, sets default scope, otherwise - instance
+   * @param key
+   * @param value
+   */
+  public void setByteArrayPreference(boolean setDefault, String key,
+      byte[] value)
+  {
+    IEclipsePreferences node = getNode(setDefault);
+    node.putByteArray(key, value);
+    try
+    {
+      node.flush();
+    }
+    catch(BackingStoreException e)
+    {
+      System.out.println("PreferencesService."
+          + "setByteArrayPreference(String, byte[]):  "
+          + "BackingStoreException");
+      System.out.println("\tkey = " + key + "; value = " + value);
+    }
+  }
+
+  /**
+   * Set value at default or instance scopes depending on setDefault param.
+   *
+   * @param setDefault
+   *          if true, sets default scope, otherwise - instance
+   * @param key
+   * @param value
+   */
+  public void setDoublePreference(boolean setDefault, String key, double value)
+  {
+    IEclipsePreferences node = getNode(setDefault);
+    node.putDouble(key, value);
+    try
+    {
+      node.flush();
+    }
+    catch(BackingStoreException e)
+    {
+      System.out.println("PreferencesService."
+          + "setDoublePreference(String, double):  " + "BackingStoreException");
+      System.out.println("\tkey = " + key + "; value = " + value);
+    }
+  }
+
+  /**
+   * Set value at default or instance scopes depending on setDefault param.
+   *
+   * @param setDefault
+   *          if true, sets default scope, otherwise - instance
+   * @param key
+   * @param value
+   */
+  public void setFloatPreference(boolean setDefault, String key, float value)
+  {
+    IEclipsePreferences node = getNode(setDefault);
+    node.putFloat(key, value);
+    try
+    {
+      node.flush();
+    }
+    catch(BackingStoreException e)
+    {
+      System.out.println("PreferencesService."
+          + "setFloatPreference(String, float):  " + "BackingStoreException");
+      System.out.println("\tkey = " + key + "; value = " + value);
+    }
+  }
+
+  /**
+   * Set value at default or instance scopes depending on setDefault param.
+   *
+   * @param setDefault
+   *          if true, sets default scope, otherwise - instance
+   * @param key
+   * @param value
+   */
+  public void setIntPreference(boolean setDefault, String key, int value)
+  {
+    IEclipsePreferences node = getNode(setDefault);
+    node.putInt(key, value);
+    try
+    {
+      node.flush();
+    }
+    catch(BackingStoreException e)
+    {
+      System.out.println("PreferencesService."
+          + "setIntPreference(String, int):  " + "BackingStoreException");
+      System.out.println("\tkey = " + key + "; value = " + value);
+    }
+  }
+
+  /**
+   * Set value at default or instance scopes depending on setDefault param.
+   *
+   * @param setDefault
+   *          if true, sets default scope, otherwise - instance
+   * @param key
+   * @param value
+   */
+  public void setLongPreference(boolean setDefault, String key, long value)
+  {
+    IEclipsePreferences node = getNode(setDefault);
+    node.putLong(key, value);
+    try
+    {
+      node.flush();
+    }
+    catch(BackingStoreException e)
+    {
+      System.out.println("PreferencesService.set."
+          + "LongPreference(String, long):  BackingStoreException");
+      System.out.println("\tkey = " + key + "; value = " + value);
+    }
+  }
+
+  /**
+   * Set value at default or instance scopes depending on setDefault param.
+   *
+   * @param setDefault
+   *          if true, sets default scope, otherwise - instance
+   * @param key
+   * @param value
+   */
+  public void setStringPreference(boolean setDefault, String key, String value)
+  {
+    IEclipsePreferences node = getNode(setDefault);
+    node.put(key, value);
+    try
+    {
+      node.flush();
+    }
+    catch(BackingStoreException e)
+    {
+      System.out.println("PreferencesService."
+          + "setStringPreference(String, String):  " + "BackingStoreException");
+      System.out.println("\tkey = " + key + "; value = " + value);
+    }
+  }
+
+  /**
+   * Clears preferences corresponding to the language at instance scope.
+   *
+   * @return preferences that were cleared
+   */
+  public IEclipsePreferences clearPreferences()
+  {
+    IEclipsePreferences node = instanceScope.getNode(languageName);
+    try
+    {
+      if( node != null )
+      {
+        // node.clear();
+        String[] keys = node.keys();
+        for(int i = 0; i < keys.length; i++)
+        {
+          node.remove(keys[i]);
+        }
+        node.flush(); // SMS 28 Nov 2006
+      }
+    }
+    catch(BackingStoreException e)
+    {
+      System.out.println("PreferencesService.setPreferences():  "
+          + "BackingStoreException clearing existing preferences;"
+          + " attempting to add new preferences anyway");
+    }
+
+    return node;
+  }
+
+  /**
+   * Clear the specific preference associated with a given key.
+   *
+   * @return the cleared value (may be null)
+   */
+  public String clearPreference(String key)
+  {
+    IEclipsePreferences node = instanceScope.getNode(languageName);
+    if( node == null ) return null;
+    String preference = node.get(key, null);
+    node.remove(key);
+    try
+    {
+      node.flush();
+    }
+    catch(BackingStoreException e)
+    {
+      System.err.println("PreferencesService.clearPreference(String):"
+          + "  BackingStoreException trying to"
+          + " flush node with cleared preference;\n" + "; key = " + key + "\n"
+          + "\tclearing may not have a persistent effect");
+    }
+    return preference;
+  }
+
+  /*
+   * Other useful things
+   */
+
+  /**
+   * @param key
+   * @return true if value is not set at instance scope
+   */
+  public boolean isDefault(String key)
+  {
+    Assert.isLegal(key != null);
+    IEclipsePreferences node = instanceScope.getNode(languageName);
+    return (node.get(key, null) == null);
+  }
+
+  /**
+   * @param key
+   * @return true if there is a value set at default or instance scopes
+   */
+  public boolean isDefined(String key)
+  {
+    if( !isDefault(key) )
+    {
+      return true;
+    }
+    IEclipsePreferences node = defaultScope.getNode(languageName);
+    return (node.get(key, null) != null);
+  }
+
+  public IEclipsePreferences getRootNode()
+  {
+    return preferencesService.getRootNode();
+  }
+
+  public abstract class PreferenceServiceListener implements
+      IPreferenceChangeListener
+  {
+    private final String fKey;
+    private final IEclipsePreferences fWSLevel;
+
+    PreferenceServiceListener(PreferencesService service, String key)
+    {
+      fKey = key;
+      fWSLevel = service.getPreferences();
+
+      fWSLevel.addPreferenceChangeListener(this);
+    }
+
+    public void preferenceChange(PreferenceChangeEvent event)
+    {
+      if( !event.getKey().equals(fKey) ) return;
+      handleChange(event.getOldValue(), event.getNewValue());
+    }
+
+    public void dispose()
+    {
+      fWSLevel.removePreferenceChangeListener(this);
+    }
+
+    protected abstract void handleChange(Object oldValue, Object newValue);
+  }
+
+  public abstract class StringPreferenceListener extends
+      PreferenceServiceListener
+  {
+    public StringPreferenceListener(PreferencesService service, String key)
+    {
+      super(service, key);
+    }
+
+    @Override
+    protected final void handleChange(Object oldValue, Object newValue)
+    {
+      changed((String)oldValue, (String)newValue);
+    }
+
+    public abstract void changed(String oldValue, String newValue);
+  }
+
+  public abstract class BooleanPreferenceListener extends
+      PreferenceServiceListener
+  {
+    public BooleanPreferenceListener(PreferencesService service, String key)
+    {
+      super(service, key);
+    }
+
+    @Override
+    protected final void handleChange(Object oldValue, Object newValue)
+    {
+      changed(Boolean.parseBoolean((String)oldValue), Boolean
+          .parseBoolean((String)newValue));
+    }
+
+    public abstract void changed(boolean oldValue, boolean newValue);
+  }
+
+  public abstract class IntegerPreferenceListener extends
+      PreferenceServiceListener
+  {
+    public IntegerPreferenceListener(PreferencesService service, String key)
+    {
+      super(service, key);
+    }
+
+    @Override
+    protected final void handleChange(Object oldValue, Object newValue)
+    {
+      changed(Integer.parseInt((String)oldValue), Integer
+          .parseInt((String)newValue));
+    }
+
+    public abstract void changed(int oldValue, int newValue);
+  }
+
+}

File src/org/lispdev/preferences/fields/BooleanItemEditor.java

+package org.lispdev.preferences.fields;
+
+import java.lang.reflect.Field;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.preference.BooleanFieldEditor;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.lispdev.preferences.PreferenceItem;
+import org.lispdev.preferences.PreferenceType;
+import org.lispdev.preferences.PreferencesService;
+
+public class BooleanItemEditor extends BooleanFieldEditor implements ItemField
+{
+  private PreferencesService service;
+  private Composite parent;
+  private PreferenceItem item;
+
+  public BooleanItemEditor(PreferenceItem item, Composite parent,
+      PreferencesService service)
+  {
+    super(item.id, item.label, parent);
+    Assert.isLegal(item.type == PreferenceType.BOOLEAN);
+    this.parent = parent;
+    this.item = item;
+    this.service = service;
+    getChangeControl(parent).setToolTipText(item.tooltip);
+  }
+
+  @Override
+  public Composite parent()
+  {
+    return parent;
+  }
+
+  /**
+   * wasSelected is a private field in boolean field editor, which is used
+   * in protected doLoad, doLoadDefault and other places. So I set it
+   * using reflection.
+   */
+  private void setWasSelected(boolean value)
+  {
+    try
+    {
+      Field fWasSelected =
+        BooleanFieldEditor.class.getDeclaredField("wasSelected");
+      fWasSelected.setAccessible(true);
+      fWasSelected.setBoolean(this, value);
+    }
+    catch(Exception e)
+    {
+      e.printStackTrace();
+    }
+  }
+
+  @Override
+  protected void doLoad()
+  {
+    Button checkBox = getChangeControl(parent);
+    if( checkBox != null )
+    {
+      boolean value = (Boolean)item.get(service);
+      checkBox.setSelection(value);
+      setWasSelected(value);
+    }
+  }
+
+  @Override
+  protected void doLoadDefault()
+  {
+    Button checkBox = getChangeControl(parent);
+    if( checkBox != null )
+    {
+      boolean value = (Boolean)item.getDefault(service);
+      checkBox.setSelection(value);
+      setWasSelected(value);
+    }
+  }
+
+  @Override
+  protected void doStore()
+  {
+    item.set(false, service, getBooleanValue());
+  }
+
+  // these need for reflection
+
+  @Override
+  protected void adjustForNumColumns(int numColumns)
+  {
+    super.adjustForNumColumns(numColumns);
+  }
+
+  @Override
+  protected void doFillIntoGrid(Composite parent, int numColumns)
+  {
+    super.doFillIntoGrid(parent, numColumns);
+  }
+
+  @Override
+  public void load()
+  {
+    setPresentsDefaultValue(false);
+    doLoad();
+    refreshValidState();
+  }
+
+  @Override
+  public void loadDefault()
+  {
+    setPresentsDefaultValue(true);
+    doLoadDefault();
+    refreshValidState();
+  }
+
+  @Override
+  public void store()
+  {
+    if (presentsDefaultValue())
+    {
+      item.clear(service);
+    }
+    else
+    {
+      doStore();
+    }
+  }
+
+  @Override
+  public PreferenceItem item()
+  {
+    return item;
+  }
+
+}

File src/org/lispdev/preferences/fields/ColorItemEditor.java

+package org.lispdev.preferences.fields;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.preference.ColorFieldEditor;
+import org.eclipse.jface.preference.ColorSelector;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Composite;
+import org.lispdev.preferences.PreferenceItem;
+import org.lispdev.preferences.PreferenceType;
+import org.lispdev.preferences.PreferencesService;
+
+public class ColorItemEditor extends ColorFieldEditor implements ItemField
+{
+  private PreferencesService service;
+  private PreferenceItem item;
+  private Composite parent;
+
+  public ColorItemEditor(PreferenceItem item, Composite parent,
+      PreferencesService service)
+  {
+    super(item.id, item.label, parent);
+    Assert.isLegal(item.type == PreferenceType.COLOR);
+    this.service = service;
+    this.item = item;
+    this.parent = parent;
+    getChangeControl(parent).setToolTipText(item.tooltip);
+    getLabelControl().setToolTipText(item.tooltip);
+  }
+
+  @Override
+  public PreferenceItem item()
+  {
+    return item;
+  }
+
+  @Override
+  public Composite parent()
+  {
+    return parent;
+  }
+
+  @Override
+  protected void doLoad()
+  {
+    ColorSelector color = getColorSelector();
+    if ( color == null)
+    {
+      return;
+    }
+    color.setColorValue((RGB)item.get(service));
+  }
+
+  @Override
+  protected void doLoadDefault()
+  {
+    ColorSelector color = getColorSelector();
+    if ( color == null)
+    {
+      return;
+    }
+    color.setColorValue((RGB)item.getDefault(service));
+  }
+
+  @Override
+  protected void doStore()
+  {
+    ColorSelector color = getColorSelector();
+    if ( color == null)
+    {
+      return;
+    }
+    item.set(false, service, color.getColorValue());
+  }
+
+  @Override
+  public void load()
+  {
+    setPresentsDefaultValue(false);
+    doLoad();
+    refreshValidState();
+  }
+
+  @Override
+  public void loadDefault()
+  {
+    setPresentsDefaultValue(true);
+    doLoadDefault();
+    refreshValidState();
+  }
+
+  @Override
+  public void store()
+  {
+    if (presentsDefaultValue())
+    {
+      item.clear(service);
+    }
+    else
+    {
+      doStore();
+    }
+  }
+
+}

File src/org/lispdev/preferences/fields/FontItemEditor.java

+package org.lispdev.preferences.fields;
+
+import java.lang.reflect.Method;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.preference.FontFieldEditor;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.widgets.Composite;
+import org.lispdev.preferences.PreferenceItem;
+import org.lispdev.preferences.PreferenceType;
+import org.lispdev.preferences.PreferencesService;
+
+public class FontItemEditor extends FontFieldEditor implements ItemField
+{
+  protected PreferencesService service;
+  protected PreferenceItem item;
+  protected Composite parent;
+
+  protected FontItemEditor(PreferenceItem item, Composite parent,
+      PreferencesService service, boolean check)
+  {
+    super(item.id, item.label, parent);
+    Assert.isLegal(false,"Class is not finished - doStore");
+    if( check ) Assert.isLegal(item.type == PreferenceType.STRING);
+    this.service = service;
+    this.item = item;
+    this.parent = parent;
+    getChangeControl(parent).setToolTipText(item.tooltip);
+    getLabelControl().setToolTipText(item.tooltip);
+  }
+
+
+  @Override
+  public PreferenceItem item()
+  {
+    return item;
+  }
+
+  @Override
+  public Composite parent()
+  {
+    return parent;
+  }
+
+  /**
+   * call private in parent by reflection
+   */
+  private void doUpdateFont(FontData[] font)
+  {
+    try
+    {
+      Method m = FontFieldEditor.class.getDeclaredMethod("updateFont",
+          new Class[]{font.getClass()});
+      m.setAccessible(true);
+      m.invoke(this, new Object[]{font});
+    }
+    catch(Exception e)
+    {
+      e.printStackTrace();
+    }
+  }
+
+  @Override
+  protected void doLoad()
+  {
+    doUpdateFont((FontData[])item.get(service));
+  }
+
+  @Override
+  protected void doLoadDefault()
+  {
+    doUpdateFont((FontData[])item.getDefault(service));
+  }
+
+  @Override
+  protected void doStore()
+  {
+
+ //   item.set(service, color.getColorValue());
+  }
+
+  @Override
+  public void load()
+  {
+    setPresentsDefaultValue(false);
+    doLoad();
+    refreshValidState();
+  }
+
+  @Override
+  public void loadDefault()
+  {
+    setPresentsDefaultValue(true);
+    doLoadDefault();
+    refreshValidState();
+  }
+
+  @Override
+  public void store()
+  {
+    if (presentsDefaultValue())
+    {
+      item.clear(service);
+    }
+    else
+    {
+      doStore();
+    }
+  }
+
+}

File src/org/lispdev/preferences/fields/ItemField.java

+package org.lispdev.preferences.fields;
+
+import org.eclipse.swt.widgets.Composite;
+import org.lispdev.preferences.PreferenceItem;
+
+public interface ItemField
+{
+  PreferenceItem item();
+  Composite parent();
+}

File src/org/lispdev/preferences/fields/NumberItemEditor.java

+package org.lispdev.preferences.fields;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.swt.widgets.Composite;
+import org.lispdev.preferences.PreferenceItem;
+import org.lispdev.preferences.PreferenceType;
+import org.lispdev.preferences.PreferencesService;
+
+public class NumberItemEditor extends StringItemEditor
+{
+  public NumberItemEditor(PreferenceItem item, Composite parent,
+      PreferencesService service)
+  {
+    super(item, parent, service, false);
+    Assert.isLegal(item.type == PreferenceType.INT
+        || item.type == PreferenceType.LONG
+        || item.type == PreferenceType.DOUBLE
+        || item.type == PreferenceType.FLOAT);
+  }
+
+}

File src/org/lispdev/preferences/fields/StringItemEditor.java

+package org.lispdev.preferences.fields;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.preference.StringFieldEditor;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Text;
+import org.lispdev.preferences.PreferenceItem;
+import org.lispdev.preferences.PreferenceType;
+import org.lispdev.preferences.PreferencesService;
+
+public class StringItemEditor extends StringFieldEditor implements ItemField
+{
+  protected PreferencesService service;
+  protected PreferenceItem item;
+  protected Composite parent;
+
+  protected StringItemEditor(PreferenceItem item, Composite parent,
+      PreferencesService service, boolean check)
+  {
+    super(item.id, item.label, parent);
+    if( check ) Assert.isLegal(item.type == PreferenceType.STRING);
+    this.service = service;
+    this.item = item;
+    this.parent = parent;
+    getTextControl(parent).setToolTipText(item.tooltip);
+    getLabelControl().setToolTipText(item.tooltip);
+  }
+
+  @Override
+  public PreferenceItem item()
+  {
+    return item;
+  }
+
+  @Override
+  public Composite parent()
+  {
+    return parent;
+  }
+
+  public StringItemEditor(PreferenceItem item, Composite parent,
+      PreferencesService service)
+  {
+    this(item,parent,service,true);
+  }
+
+  @Override
+  protected void doLoad()
+  {
+    Text text = getTextControl();
+    if( text != null )
+    {
+      oldValue = String.valueOf(item.get(service));
+      text.setText(oldValue);
+    }
+  }
+
+  @Override
+  protected void doLoadDefault()
+  {
+    Text text = getTextControl();
+    if( text != null )
+    {
+      text.setText(String.valueOf(item.getDefault(service)));
+    }
+    valueChanged();
+  }
+
+  @Override
+  protected void doStore()
+  {
+    Text text = getTextControl();
+    if( text != null )
+    {
+      item.set(false, service, text.getText());
+    }
+  }
+
+  @Override
+  public void load()
+  {
+    setPresentsDefaultValue(false);
+    doLoad();
+    refreshValidState();
+  }
+
+  @Override
+  public void loadDefault()
+  {
+    setPresentsDefaultValue(true);
+    doLoadDefault();
+    refreshValidState();
+  }
+
+  @Override
+  public void store()
+  {
+    if (presentsDefaultValue())
+    {
+      item.clear(service);
+    }
+    else
+    {
+      doStore();
+    }
+  }
+
+
+}