/* ****************************************************************************** * Copyright (c) 2006-2012 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ package org.xmind.ui.properties; import java.util.HashMap; import java.util.Map; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.SafeRunner; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; public abstract class PropertyEditor { /** * Identifier and enability property name for action 'copy'. */ public static final String COPY = "copy"; //$NON-NLS-1$ /** * Identifier and enability property name for action 'cut'. */ public static final String CUT = "cut"; //$NON-NLS-1$ /** * Identifier and enability property name for action 'paste'. */ public static final String PASTE = "paste"; //$NON-NLS-1$ /** * Identifier and enability property name for action 'selectAll'. */ public static final String SELECT_ALL = "selectAll"; //$NON-NLS-1$ /** * Identifier and enability property name for action 'delete'. */ public static final String DELETE = "delete"; //$NON-NLS-1$ /** * Identifier and enability property name for action 'undo'. */ public static final String UNDO = "undo"; //$NON-NLS-1$ /** * Identifier and enability property name for action 'redo'. */ public static final String REDO = "redo"; //$NON-NLS-1$ /** * Property 'value'. * * @see #setValue(Object) * @see #getValue() */ public static final String VALUE = "value"; //$NON-NLS-1$ /** * Property 'activated'. * * @see #isActivated() * @see #activate() * @see #deactivate() */ public static final String ACTIVATED = "activated"; //$NON-NLS-1$ /** * Property 'dirty'. * * @see #isDirty() */ public static final String DIRTY = "dirty"; //$NON-NLS-1$ private Control control = null; private Object value = null; private boolean activated = false; private boolean dirty = false; private ListenerList editingListeners = new ListenerList(); private ListenerList propertyChangeListeners = new ListenerList(); private Map<String, Boolean> actionEnabilities = new HashMap<String, Boolean>( 7); public void create(Composite parent) { control = createControl(parent); Assert.isNotNull(control); deactivateWidget(); } public void dispose() { if (control != null && !control.isDisposed()) { control.dispose(); } control = null; } protected abstract Control createControl(Composite parent); public Control getControl() { return control; } public void setFocus() { if (control != null && !control.isDisposed()) { control.setFocus(); } } public void setBackground(Color color) { } public void setForeground(Color color) { } public void setFont(Font font) { } protected static void setAllControlsBackground(Control control, Color color) { if (control != null && !control.isDisposed()) { control.setBackground(color); if (control instanceof Composite) { for (Control c : ((Composite) control).getChildren()) { setAllControlsBackground(c, color); } } } } protected static void setAllControlsForeground(Control control, Color color) { if (control != null && !control.isDisposed()) { control.setForeground(color); if (control instanceof Composite) { for (Control c : ((Composite) control).getChildren()) { setAllControlsForeground(c, color); } } } } protected static void setAllControlsFont(Control control, Font font) { if (control != null && !control.isDisposed()) { control.setFont(font); if (control instanceof Composite) { for (Control c : ((Composite) control).getChildren()) { setAllControlsFont(c, font); } } } } public void setValue(Object value) { Object oldValue = getValue(); internalSetValue(value); setValueToWidget(value); clearDirty(); Object newValue = getValue(); if (oldValue != newValue && (oldValue == null || !oldValue.equals(newValue))) { firePropertyChange(VALUE, oldValue, newValue); } } protected void changeValue(Object newValue) { Object oldValue = getValue(); internalSetValue(newValue); markDirty(); if (oldValue != newValue && (oldValue == null || !oldValue.equals(newValue))) { firePropertyChange(VALUE, oldValue, newValue); } } protected final void internalSetValue(Object value) { this.value = value; } protected abstract void setValueToWidget(Object value); public Object getValue() { return this.value; } public void activate() { if (isActivated()) return; this.activated = true; activateWidget(); firePropertyChange(ACTIVATED, Boolean.valueOf(false), Boolean.valueOf(true)); } public void deactivate() { if (!isActivated()) return; this.activated = false; deactivateWidget(); firePropertyChange(ACTIVATED, Boolean.valueOf(true), Boolean.valueOf(false)); } protected void activateWidget() { if (control != null && !control.isDisposed()) { control.setVisible(true); } } protected void deactivateWidget() { if (control != null && !control.isDisposed()) { control.setVisible(false); } } public boolean isActivated() { return activated; } public boolean isDirty() { return dirty; } protected void markDirty() { boolean oldDirty = this.dirty; this.dirty = true; if (oldDirty != this.dirty) { firePropertyChange(DIRTY, Boolean.valueOf(oldDirty), Boolean.valueOf(this.dirty)); } } protected void clearDirty() { boolean oldDirty = this.dirty; this.dirty = false; if (oldDirty != this.dirty) { firePropertyChange(DIRTY, Boolean.valueOf(oldDirty), Boolean.valueOf(this.dirty)); } } public void addEditingListener(IEditingListener listener) { editingListeners.add(listener); } public void removeEditingListener(IEditingListener listener) { editingListeners.remove(listener); } public void addPropertyChangeListener(IPropertyChangeListener listener) { propertyChangeListeners.add(listener); } public void removePropertyChangeListener(IPropertyChangeListener listener) { propertyChangeListeners.remove(listener); } public void performAction(String actionId) { } public boolean isActionEnabled(String actionId) { Boolean enabled = actionEnabilities.get(actionId); return enabled != null && enabled.booleanValue(); } protected void setActionEnabled(String actionId, boolean enabled) { boolean oldEnabled = isActionEnabled(actionId); actionEnabilities.put(actionId, Boolean.valueOf(enabled)); boolean newEnabled = isActionEnabled(actionId); if (oldEnabled != newEnabled) { firePropertyChange(actionId, Boolean.valueOf(oldEnabled), Boolean.valueOf(newEnabled)); } } protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { final PropertyChangeEvent event = new PropertyChangeEvent(this, propertyName, oldValue, newValue); Object[] listeners = propertyChangeListeners.getListeners(); for (int i = 0; i < listeners.length; i++) { final IPropertyChangeListener listener = (IPropertyChangeListener) listeners[i]; SafeRunner.run(new SafeRunnable() { public void run() throws Exception { listener.propertyChange(event); } }); } } protected void fireApplyEditorValue() { Object[] listeners = editingListeners.getListeners(); for (int i = 0; i < listeners.length; i++) { final IEditingListener listener = (IEditingListener) listeners[i]; SafeRunner.run(new SafeRunnable() { public void run() throws Exception { listener.editingFinished(); } }); } } protected void fireCancelEditing() { Object[] listeners = editingListeners.getListeners(); for (int i = 0; i < listeners.length; i++) { final IEditingListener listener = (IEditingListener) listeners[i]; SafeRunner.run(new SafeRunnable() { public void run() throws Exception { listener.editingCanceled(); } }); } } }