Java tutorial
/******************************************************************************* * Copyright (c) 2015, 2015 Bruno Medeiros and other Contributors. * 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: * Bruno Medeiros - initial API and implementation *******************************************************************************/ package melnorme.lang.ide.ui.preferences.common; import static melnorme.utilbox.core.Assert.AssertNamespace.assertFail; import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.Map.Entry; import melnorme.lang.ide.ui.preferences.common.IPreferencesDialogComponent.BooleanFieldAdapter; import melnorme.lang.ide.ui.preferences.common.IPreferencesDialogComponent.ComboFieldAdapter; import melnorme.lang.ide.ui.preferences.common.IPreferencesDialogComponent.StringFieldAdapter; import melnorme.lang.tooling.data.IFieldValidator; import melnorme.lang.tooling.data.LocationOrSinglePathValidator; import melnorme.lang.tooling.data.LocationValidator; import melnorme.lang.tooling.data.StatusException; import melnorme.lang.tooling.data.StatusLevel; import melnorme.util.swt.SWTFactoryUtil; import melnorme.util.swt.components.AbstractField; import melnorme.util.swt.components.IFieldValueListener; import melnorme.util.swt.components.fields.ComboBoxField; import melnorme.util.swt.components.fields.DirectoryTextField; import melnorme.util.swt.components.fields.FileTextField; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; /** * This is the preferred way to create Preference pages (as of 2015-02). * * This page delegates apply/cancel/revert to preference components (Usually connected to {@link AbstractField}). */ public abstract class AbstractComponentsPrefPage extends AbstractLangPreferencesPage implements IPreferencesDialog { private final ArrayList<IPreferencesDialogComponent> prefComponents = new ArrayList<>(); private final LinkedHashMap<AbstractField<String>, IFieldValidator<?>> validators = new LinkedHashMap<>(); private StatusException currentStatus = null; public AbstractComponentsPrefPage(IPreferenceStore store) { super(store); } @Override public void setPreferenceStore(IPreferenceStore store) { assertTrue(getPreferenceStore() == null); // Cannot change store after setting. super.setPreferenceStore(store); } @Override public void addComponent(IPreferencesDialogComponent prefComponent) { prefComponents.add(prefComponent); prefComponent.loadFromStore(getPreferenceStore()); } public void loadFromStore() { for (IPreferencesDialogComponent configField : prefComponents) { configField.loadFromStore(getPreferenceStore()); } } public StatusLevel getFieldStatus(AbstractField<String> field) { IFieldValidator<?> validator = validators.get(field); StatusException fieldStatus = LocationValidator.getFieldStatus(validator, field.getFieldValue()); if (fieldStatus == null) { return StatusLevel.OK; } return fieldStatus.getStatusLevel(); } public void connectStringField(String prefKey, AbstractField<String> field, IFieldValidator<?> validator) { addStringComponent(prefKey, field); validators.put(field, validator); field.addValueChangedListener(new IFieldValueListener() { @Override public void fieldValueChanged() { updateStatusMessage(); } }); } protected void updateStatusMessage() { if (!isControlCreated()) { return; } currentStatus = null; setMessage(null); setValid(true); for (Entry<AbstractField<String>, IFieldValidator<?>> entry : validators.entrySet()) { AbstractField<String> field = entry.getKey(); IFieldValidator<?> validator = entry.getValue(); try { validator.getValidatedField(field.getFieldValue()); } catch (StatusException se) { if (currentStatus == null || se.getStatusLevelOrdinal() > currentStatus.getStatusLevelOrdinal()) { currentStatus = se; setMessage(se.getMessage(), statusLevelToMessageType(se.getStatusLevel())); setValid(se.getStatusLevel() != StatusLevel.ERROR); } } } } public static int statusLevelToMessageType(StatusLevel statusLevel) { switch (statusLevel) { case OK: return IMessageProvider.NONE; case INFO: return IMessageProvider.INFORMATION; case WARNING: return IMessageProvider.WARNING; case ERROR: return IMessageProvider.ERROR; } throw assertFail(); } @Override public final void createControl(Composite parent) { super.createControl(parent); updateStatusMessage(); } /* ----------------- ----------------- */ @Override public void performDefaults() { loadStoreDefaults(); super.performDefaults(); } public void loadStoreDefaults() { for (IPreferencesDialogComponent configField : prefComponents) { configField.loadStoreDefaults(getPreferenceStore()); } } @Override public boolean performOk() { saveToStore(); return true; } public void saveToStore() { for (IPreferencesDialogComponent configField : prefComponents) { configField.saveToStore(getPreferenceStore()); } } /* ======================= Helpers: ======================= */ public static Group createOptionsSection(Composite parent, String label, GridData gridData, int numColumns) { Group group = SWTFactoryUtil.createGroup(parent, label, gridData); group.setLayout( GridLayoutFactory.fillDefaults().numColumns(numColumns).spacing(6, 4).margins(6, 4).create()); return group; } public void addStringComponent(String prefKey, AbstractField<String> field) { addComponent(new StringFieldAdapter(prefKey, field)); } public void addBooleanComponent(String prefKey, AbstractField<Boolean> field) { addComponent(new BooleanFieldAdapter(prefKey, field)); } public void addComboComponent(String prefKey, ComboBoxField field) { addComponent(new ComboFieldAdapter(prefKey, field)); } public void addStringComponent(String prefKey, Composite parent, AbstractField<String> field) { addStringComponent(prefKey, field); field.createComponentInlined(parent); } public void addBooleanComponent(String prefKey, Composite parent, AbstractField<Boolean> field) { addBooleanComponent(prefKey, field); field.createComponentInlined(parent); } public void addComboComponent(String prefKey, Composite parent, ComboBoxField field) { addComboComponent(prefKey, field); field.createComponentInlined(parent); } public void connectFileField(String prefKey, AbstractField<String> stringField, boolean allowSinglePath, String fieldNamePrefix) { LocationValidator validator = allowSinglePath ? new LocationOrSinglePathValidator(fieldNamePrefix) : new LocationValidator(fieldNamePrefix); validator.fileOnly = true; connectStringField(prefKey, stringField, validator); } public void connectDirectoryField(String prefKey, AbstractField<String> stringField, boolean allowSinglePath, String fieldNamePrefix) { LocationValidator validator = allowSinglePath ? new LocationOrSinglePathValidator(fieldNamePrefix) : new LocationValidator(fieldNamePrefix); validator.directoryOnly = true; connectStringField(prefKey, stringField, validator); } public FileTextField createFileComponent(Group group, String label, String prefKey, boolean allowSinglePath) { FileTextField pathField = new FileTextField(label); pathField.createComponentInlined(group); connectFileField(prefKey, pathField, allowSinglePath, label); return pathField; } public DirectoryTextField createDirectoryComponent(Group group, String label, String prefKey, boolean allowSinglePath) { DirectoryTextField pathField = new DirectoryTextField(label); pathField.createComponentInlined(group); connectDirectoryField(prefKey, pathField, allowSinglePath, label); return pathField; } }