package org.kie.eclipse.navigator.preferences; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.jface.preference.FieldEditor; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.ui.IWorkbenchPropertyPage; import org.eclipse.ui.dialogs.PropertyPage; public abstract class FieldEditorPropertyPage extends PropertyPage implements IWorkbenchPropertyPage, IPropertyChangeListener { /** * Layout constant (value <code>0</code>) indicating that each field editor * is handled as a single component. */ public static final int FLAT = 0; /** * Layout constant (value <code>1</code>) indicating that the field editors' * basic controls are put into a grid layout. */ public static final int GRID = 1; /** * The vertical spacing used by layout styles <code>FLAT</code> and * <code>GRID</code>. */ protected static final int VERTICAL_SPACING = 10; /** * The margin width used by layout styles <code>FLAT</code> and * <code>GRID</code>. */ protected static final int MARGIN_WIDTH = 0; /** * The margin height used by layout styles <code>FLAT</code> and * <code>GRID</code>. */ protected static final int MARGIN_HEIGHT = 0; /** * The field editors, or <code>null</code> if not created yet. */ private List<FieldEditor> fields = null; /** * The layout style; either <code>FLAT</code> or <code>GRID</code>. */ private int style; /** * The first invalid field editor, or <code>null</code> if all field editors * are valid. */ private FieldEditor invalidFieldEditor = null; /** * The parent composite for field editors */ private Composite fieldEditorParent; public FieldEditorPropertyPage() { } public FieldEditorPropertyPage(int style) { this(); this.style = style; } /** * Adds the given field editor to this page. * * @param editor the field editor */ protected void addField(FieldEditor editor) { if (fields == null) { fields = new ArrayList<FieldEditor>(); } // Set the actual preference name based on the current selection // in the Kie Navigator tree view. The preference name is constructed // from the path to the selected tree node by getPreferenceName(). String name = editor.getPreferenceName(); editor.setPreferenceName(getPreferenceName(name)); fields.add(editor); } protected abstract String getPreferenceName(String name); /** * Adjust the layout of the field editors so that they are properly aligned. */ protected void adjustGridLayout() { int numColumns = calcNumberOfColumns(); ((GridLayout) fieldEditorParent.getLayout()).numColumns = numColumns; if (fields != null) { for (int i = 0; i < fields.size(); i++) { FieldEditor fieldEditor = fields.get(i); fieldEditor.fillIntoGrid(fieldEditorParent, numColumns); } } } /** * Applys the font to the field editors managed by this page. */ protected void applyFont() { if (fields != null) { Iterator<FieldEditor> e = fields.iterator(); while (e.hasNext()) { FieldEditor pe = e.next(); // pe.applyFont(); } } } /** * Calculates the number of columns needed to host all field editors. * * @return the number of columns */ private int calcNumberOfColumns() { int result = 0; if (fields != null) { Iterator<FieldEditor> e = fields.iterator(); while (e.hasNext()) { FieldEditor pe = e.next(); result = Math.max(result, pe.getNumberOfControls()); } } return result; } /** * Recomputes the page's error state by calling <code>isValid</code> for * every field editor. */ protected void checkState() { boolean valid = true; invalidFieldEditor = null; // The state can only be set to true if all // field editors contain a valid value. So we must check them all if (fields != null) { int size = fields.size(); for (int i = 0; i < size; i++) { FieldEditor editor = fields.get(i); valid = valid && editor.isValid(); if (!valid) { invalidFieldEditor = editor; break; } } } setValid(valid); } @Override public IPreferenceStore getPreferenceStore() { return org.kie.eclipse.Activator.getDefault().getPreferenceStore(); } /* * (non-Javadoc) Method declared on PreferencePage. */ @Override protected Control createContents(Composite parent) { fieldEditorParent = new Composite(parent, SWT.NULL); GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.marginHeight = 0; layout.marginWidth = 0; fieldEditorParent.setLayout(layout); fieldEditorParent.setFont(parent.getFont()); createFieldEditors(); if (style == GRID) { adjustGridLayout(); } initialize(); checkState(); return fieldEditorParent; } /** * Creates the page's field editors. * <p> * The default implementation of this framework method does nothing. * Subclass must implement this method to create the field editors. * </p> * <p> * Subclasses should call <code>getFieldEditorParent</code> to obtain the * parent control for each field editor. This same parent should not be used * for more than one editor as the parent may change for each field editor * depending on the layout style of the page * </p> */ protected abstract void createFieldEditors(); /** * Gets the initial property page ID based on the current selection. * * @return the page ID string */ protected abstract String getInitialPageId(); /** * The field editor preference page implementation of an * <code>IDialogPage</code> method disposes of this page's controls and * images. Subclasses may override to release their own allocated SWT * resources, but must call <code>super.dispose</code>. */ @Override public void dispose() { super.dispose(); if (fields != null) { Iterator<FieldEditor> e = fields.iterator(); while (e.hasNext()) { FieldEditor pe = e.next(); pe.setPage(null); pe.setPropertyChangeListener(null); pe.setPreferenceStore(null); } } } /** * Returns a parent composite for a field editor. * <p> * This value must not be cached since a new parent may be created each time * this method called. Thus this method must be called each time a field * editor is constructed. * </p> * * @return a parent */ protected Composite getFieldEditorParent() { if (style == FLAT) { // Create a new parent for each field editor Composite parent = new Composite(fieldEditorParent, SWT.NULL); parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); return parent; } // Just return the parent return fieldEditorParent; } /** * Initializes all field editors. */ protected void initialize() { if (fields != null) { Iterator<FieldEditor> e = fields.iterator(); while (e.hasNext()) { FieldEditor pe = e.next(); pe.setPage(this); pe.setPropertyChangeListener(this); pe.setPreferenceStore(getPreferenceStore()); pe.load(); } } } /** * The field editor preference page implementation of a * <code>PreferencePage</code> method loads all the field editors with their * default values. */ @Override protected void performDefaults() { if (fields != null) { Iterator<FieldEditor> e = fields.iterator(); while (e.hasNext()) { FieldEditor pe = e.next(); pe.loadDefault(); } } // Force a recalculation of my error state. checkState(); super.performDefaults(); } /** * The field editor preference page implementation of this * <code>PreferencePage</code> method saves all field editors by calling * <code>FieldEditor.store</code>. Note that this method does not save the * preference store itself; it just stores the values back into the * preference store. * * @see FieldEditor#store() */ @Override public boolean performOk() { if (fields != null) { Iterator<FieldEditor> e = fields.iterator(); while (e.hasNext()) { FieldEditor pe = e.next(); pe.store(); // pe.setPresentsDefaultValue(false); } } return true; } /** * The field editor preference page implementation of this * <code>IPreferencePage</code> (and <code>IPropertyChangeListener</code>) * method intercepts <code>IS_VALID</code> events but passes other events on * to its superclass. */ @Override public void propertyChange(PropertyChangeEvent event) { if (event.getProperty().equals(FieldEditor.IS_VALID)) { boolean newValue = ((Boolean) event.getNewValue()).booleanValue(); // If the new value is true then we must check all field editors. // If it is false, then the page is invalid in any case. if (newValue) { checkState(); } else { invalidFieldEditor = (FieldEditor) event.getSource(); setValid(newValue); } } } /* * (non-Javadoc) Method declared on IDialog. */ @Override public void setVisible(boolean visible) { super.setVisible(visible); if (visible && invalidFieldEditor != null) { invalidFieldEditor.setFocus(); } } }