/* * This file is part of the OpenJML plugin project. * Copyright (c) 2004-2013 David R. Cok */ package org.jmlspecs.openjml.eclipse; import java.util.HashMap; import java.util.Map; import java.util.Properties; import org.eclipse.jface.preference.BooleanFieldEditor; import org.eclipse.jface.preference.ComboFieldEditor; import org.eclipse.jface.preference.FieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.StringFieldEditor; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import org.jmlspecs.openjml.eclipse.widgets.ButtonFieldEditor; import org.jmlspecs.openjml.eclipse.widgets.LabelFieldEditor; /** * This class creates a Preferences page in Eclipse * This page hold data needed for CodeSonar and Eclipse interaction * <P> * The preferences page manages various JML and OpenJML and plug-in specific * options. As usual these are stored in the preferences store. * Some project specific properties are stored differently. * <P> * The key used for preferences is the same as the key used in System properties. * <P> * Notes: Field editors are a convenient way to create a preferences page, * but not quite convenient enough on a couple of counts. * <UL> * <LI> We need to observe when fields are changed. The normal way to do this * would be to register a listener, but only one listener is allowed, and * the implementation of FieldEditorPreferencePage overwrites (during initialize()) * any listener added when a field editor is created. * <LI> So we have to put the propertyChange call on the derived SettingsPage * itself, which means that it is the same listener for all fields. * <LI> There is insufficient access to FieldEditorPreferencePage functionality * such as the list of all fields or being able to force loads and stores. * </UL> */ /* To add a new Preference do the following, using the existing contents of * the files as a guide: * a) Declare a key in Options.java * b) Add a declaration in Messages.java * c) Add a preference field in PreferencesPage.java, which uses the key from * Options.java and the String from Messages.java * d) Add a property in messages.properties that will initialize the variable in * Messages.java * e) In OpenJMLInterface.getOptions, convert the Preference into an OpenJML * option, as appropriate. */ public class PreferencesPage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { public PreferencesPage() { super(FLAT); // No descriptive text needed. setDescription("Options for OpenJML"); } public void init(IWorkbench workbench) { setPreferenceStore(Activator.getDefault().getPreferenceStore()); } /** A mapping of option keys to field names */ protected Map<String,FieldEditor> fieldMap = new HashMap<String,FieldEditor>(); /** Overridden to add the field to the fieldMap */ @Override public void addField(FieldEditor field) { super.addField(field); fieldMap.put(field.getPreferenceName(), field); } /** Overriding performOk() callback in order to maintain copies * of the option values appropriately. This is called when * 'Apply' or 'OK' is clicked. */ @Override public boolean performOk() { super.performOk(); Options.cache(); return true; } /** The method that constructs all the editors and arranges them on the * settings page. */ @Override protected void createFieldEditors() { // JML MouseListener listener = new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { Properties properties = Utils.getProperties(); for (Map.Entry<Object,Object> entry : properties.entrySet()) { Object keyobj = entry.getKey(); if (!(keyobj instanceof String)) continue; String key = (String)keyobj; if (!(entry.getValue() instanceof String)) continue; String value = (String)entry.getValue(); if (key.contains(Env.OPENJML)) { if (Options.uiverboseness) { Log.log("Reading property: " + key + " = " + value); //$NON-NLS-1$ //$NON-NLS-2$ } FieldEditor field = fieldMap.get(key); if (field != null) { if (field instanceof BooleanFieldEditor) { getPreferenceStore().setValue(key,!value.isEmpty()); } else if (field instanceof StringFieldEditor) { getPreferenceStore().setValue(key,value); } else if (field instanceof ComboFieldEditor) { getPreferenceStore().setValue(key,value); // FIXME - how do we know it is a valid value } else { Log.errorKey("openjml.ui.unknown.field.editor",null,field.getClass(),key,value); //$NON-NLS-1$ } } else { // Assume anything else has a String value getPreferenceStore().setValue(key,value); } } else { // There are lots of these - mostly Java or Eclipse related //Log.log("Ignoring property " + key + "=" + value); } } Options.cache(); initialize(); } }; addField(new ButtonFieldEditor(Options.updateKey,"", //$NON-NLS-1$ Messages.OpenJMLUI_PreferencesPage_UpdateFromPropertiesFiles, listener, getFieldEditorParent()) ); addField(new LabelFieldEditor("zzzzz.JML","",SWT.NONE, //$NON-NLS-1$ //$NON-NLS-2$ getFieldEditorParent())); addField(new LabelFieldEditor("zzzzz.JML",Messages.OpenJMLUI_PreferencesPage_JmlOptions,SWT.SEPARATOR|SWT.HORIZONTAL, //$NON-NLS-1$ getFieldEditorParent())); addField(new BooleanFieldEditor(Options.nullableByDefaultKey, Messages.OpenJMLUI_PreferencesPage_NullableByDefault, getFieldEditorParent())); addField(new BooleanFieldEditor(Options.strictKey, Messages.OpenJMLUI_PreferencesPage_strictCheck, getFieldEditorParent())); addField(new BooleanFieldEditor(Options.noCheckPurityKey, Messages.OpenJMLUI_PreferencesPage_SkipPurityCheck, getFieldEditorParent())); addField(new BooleanFieldEditor(Options.showNotImplementedKey, Messages.OpenJMLUI_PreferencesPage_WarnAboutNonImplementedConstructs, getFieldEditorParent())); addField(new BooleanFieldEditor(Options.checkSpecsPathKey, Messages.OpenJMLUI_PreferencesPage_CheckSpecificationPath, getFieldEditorParent())); addField(new BooleanFieldEditor(Options.noInternalSpecsKey, Messages.OpenJMLUI_PreferencesPage_UseExternalSystemSpecs, getFieldEditorParent())); addField(new StringFieldEditor(Options.optionalKeysKey, Messages.OpenJMLUI_PreferencesPage_OptionalAnnotationKeys, getFieldEditorParent())); addField(new StringFieldEditor(Options.otherOptionsKey, Messages.OpenJMLUI_PreferencesPage_OtherOptions, getFieldEditorParent())); // ESC addField(new LabelFieldEditor("zzzzz.ESC","",SWT.NONE, //$NON-NLS-1$ //$NON-NLS-2$ getFieldEditorParent())); addField(new LabelFieldEditor("zzzzz.ESC",Messages.OpenJMLUI_PreferencesPage_OptionsRelatingToESC,SWT.SEPARATOR|SWT.HORIZONTAL, //$NON-NLS-1$ getFieldEditorParent())); addField(new BooleanFieldEditor(Options.enableESCKey, Messages.OpenJMLUI_PreferencesPage_EnableAutoESCChecking, getFieldEditorParent())); addField(new ComboFieldEditor(Options.escMaxWarningsKey, Messages.OpenJMLUI_PreferencesPage_MaxWarnings, new String[][]{ {"all", Integer.toString(Integer.MAX_VALUE) }, //$NON-NLS-1$ {"1","1"}, //$NON-NLS-1$ //$NON-NLS-2$ {"2","2"}, //$NON-NLS-1$ //$NON-NLS-2$ {"3","3"}, //$NON-NLS-1$ //$NON-NLS-2$ {"4","4"}, //$NON-NLS-1$ //$NON-NLS-2$ {"5","5"}, //$NON-NLS-1$ //$NON-NLS-2$ {"6","6"}, //$NON-NLS-1$ //$NON-NLS-2$ {"7","7"}, //$NON-NLS-1$ //$NON-NLS-2$ {"8","8"}, //$NON-NLS-1$ //$NON-NLS-2$ {"9","9"}, //$NON-NLS-1$ //$NON-NLS-2$ }, getFieldEditorParent())); addField(new StringFieldEditor(Options.timeoutKey, Messages.OpenJMLUI_PreferencesPage_timeout, getFieldEditorParent())); // addField(new BooleanFieldEditor(Options.traceKey, Messages.OpenJMLUI_PreferencesPage_Trace, // getFieldEditorParent())); // addField(new BooleanFieldEditor(Options.subexpressionsKey, Messages.OpenJMLUI_PreferencesPage_Subexpressions, // getFieldEditorParent())); addField(new ComboFieldEditor(Options.feasibilityKey, Messages.OpenJMLUI_PreferencesPage_Feasibility, new String[][]{ {"all", "all" }, //$NON-NLS-1$ {"preconditions","preconditions"}, //$NON-NLS-1$ //$NON-NLS-2$ {"exit", "exit"}, //$NON-NLS-1$ //$NON-NLS-2$ {"none", "none"}, //$NON-NLS-1$ //$NON-NLS-2$ }, getFieldEditorParent())); // RAC addField(new LabelFieldEditor("zzzzz.RAC","",SWT.NONE, //$NON-NLS-1$ //$NON-NLS-2$ getFieldEditorParent())); addField(new LabelFieldEditor("zzzzz.RAC",Messages.OpenJMLUI_PreferencesPage_OptionsRelatingToRAC,SWT.SEPARATOR|SWT.HORIZONTAL, //$NON-NLS-1$ getFieldEditorParent())); addField(new BooleanFieldEditor(Options.enableRacKey, Messages.OpenJMLUI_PreferencesPage_EnableAutoRuntimeAssertionChecking, getFieldEditorParent())); addField(new BooleanFieldEditor(Options.noInternalRuntimeKey, Messages.OpenJMLUI_PreferencesPage_UseExternalRuntimeLibrary, getFieldEditorParent())); addField(new BooleanFieldEditor(Options.compileToJavaAssert, Messages.OpenJMLUI_PreferencesPage_CompileToJavaAssert, getFieldEditorParent())); addField(new BooleanFieldEditor(Options.racCheckJavaFeatures, Messages.OpenJMLUI_PreferencesPage_racCheckJavaFeatures, getFieldEditorParent())); addField(new BooleanFieldEditor(Options.racCheckAssumptions, Messages.OpenJMLUI_PreferencesPage_racCheckAssumptions, getFieldEditorParent())); addField(new BooleanFieldEditor(Options.racPreconditionEntry, Messages.OpenJMLUI_PreferencesPage_racPreconditionEntry, getFieldEditorParent())); addField(new BooleanFieldEditor(Options.racNoShowSource, Messages.OpenJMLUI_PreferencesPage_racNoShowSource, getFieldEditorParent())); addField(new BooleanFieldEditor(Options.showNotExecutableKey, Messages.OpenJMLUI_PreferencesPage_WarnAboutNonExecutableConstructs, getFieldEditorParent())); addField(new StringFieldEditor(Options.racbinKey, Messages.OpenJMLUI_PreferencesPage_DirectoryForRACOutput, getFieldEditorParent())); // Debug and verbosity addField(new LabelFieldEditor("zzzzz.VERBOSE","",SWT.NONE, //$NON-NLS-1$ //$NON-NLS-2$ getFieldEditorParent())); addField(new LabelFieldEditor("zzzzz.VERBOSE",Messages.OpenJMLUI_PreferencesPage_VerbosenessAndDebugging,SWT.SEPARATOR|SWT.HORIZONTAL, //$NON-NLS-1$ getFieldEditorParent())); addField(new BooleanFieldEditor(Options.javaverboseKey, Messages.OpenJMLUI_PreferencesPage_JavaVerbose, getFieldEditorParent())); addField(new BooleanFieldEditor(Options.showKey, Messages.OpenJMLUI_PreferencesPage_Show, getFieldEditorParent())); addField(new ComboFieldEditor(Options.verbosityKey, Messages.OpenJMLUI_PreferencesPage_VerbosityLevel, new String[][]{ {Messages.OpenJMLUI_PreferencesPage_quiet, Integer.toString(Utils.QUIET) }, {Messages.OpenJMLUI_PreferencesPage_normal, Integer.toString(Utils.NORMAL)}, {Messages.OpenJMLUI_PreferencesPage_progress, Integer.toString(Utils.PROGRESS)}, {Messages.OpenJMLUI_PreferencesPage_verbose, Integer.toString(Utils.VERBOSE)}, {Messages.OpenJMLUI_PreferencesPage_debug, Integer.toString(Utils.DEBUG)}}, getFieldEditorParent())); addField(new BooleanFieldEditor(Options.showErrorPopupsKey, Messages.OpenJMLUI_PreferencesPage_ShowErrorPopups, getFieldEditorParent())); addField(new BooleanFieldEditor(Options.uiverbosityKey, Messages.OpenJMLUI_PreferencesPage_UIVerbose, getFieldEditorParent())); } }