/******************************************************************************* | |
* Copyright (c) 2011-2013 EclipseSource Muenchen GmbH and others. | |
* | |
* 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: | |
* Eugen Neufeld - initial API and implementation | |
* | |
*******************************************************************************/ | |
package org.eclipse.emf.ecp.internal.editor; | |
import org.eclipse.emf.common.notify.AdapterFactory; | |
import org.eclipse.emf.common.notify.Notification; | |
import org.eclipse.emf.common.util.Diagnostic; | |
import org.eclipse.emf.ecore.EObject; | |
import org.eclipse.emf.ecore.EStructuralFeature; | |
import org.eclipse.emf.ecore.util.Diagnostician; | |
import org.eclipse.emf.ecp.edit.ECPAbstractControl; | |
import org.eclipse.emf.ecp.edit.ECPControlContext; | |
import org.eclipse.emf.ecp.edit.ECPControlFactory; | |
import org.eclipse.emf.ecp.edit.internal.swt.util.SWTControl; | |
import org.eclipse.emf.ecp.edit.util.ECPModelElementChangeListener; | |
import org.eclipse.emf.ecp.editor.IEditorCompositeProvider; | |
import org.eclipse.emf.ecp.internal.editor.descriptor.AnnotationHiddenDescriptor; | |
import org.eclipse.emf.ecp.internal.editor.descriptor.AnnotationPositionDescriptor; | |
import org.eclipse.emf.ecp.internal.editor.descriptor.AnnotationPriorityDescriptor; | |
import org.eclipse.emf.edit.provider.AdapterFactoryItemDelegator; | |
import org.eclipse.emf.edit.provider.ComposedAdapterFactory; | |
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor; | |
import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory; | |
import org.eclipse.jface.layout.GridDataFactory; | |
import org.eclipse.jface.layout.GridLayoutFactory; | |
import org.eclipse.swt.SWT; | |
import org.eclipse.swt.custom.SashForm; | |
import org.eclipse.swt.layout.GridLayout; | |
import org.eclipse.swt.widgets.Composite; | |
import org.eclipse.swt.widgets.Display; | |
import org.eclipse.swt.widgets.Label; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.Collections; | |
import java.util.Comparator; | |
import java.util.HashMap; | |
import java.util.Iterator; | |
import java.util.LinkedHashMap; | |
import java.util.List; | |
import java.util.Map; | |
/** | |
* @author Eugen Neufeld | |
*/ | |
public class FormEditorComposite implements IEditorCompositeProvider { | |
private ECPModelElementChangeListener modelElementChangeListener; | |
/** | |
* Default Constructor. | |
* | |
* @param modelElementContext the {@link ECPControlContext} | |
*/ | |
public FormEditorComposite(ECPControlContext modelElementContext) { | |
this.modelElementContext = modelElementContext; | |
addModelElementListener(); | |
} | |
/** | |
* | |
*/ | |
private void addModelElementListener() { | |
modelElementChangeListener = new ECPModelElementChangeListener(modelElementContext.getModelElement()) { | |
@Override | |
public void onChange(Notification notification) { | |
Display.getDefault().asyncExec(new Runnable() { | |
public void run() { | |
updateLiveValidation(); | |
} | |
}); | |
} | |
}; | |
} | |
private final ECPControlContext modelElementContext; | |
private Map<EStructuralFeature, ECPAbstractControl> meControls = new LinkedHashMap<EStructuralFeature, ECPAbstractControl>(); | |
private Map<ECPAbstractControl, Diagnostic> valdiatedControls = new HashMap<ECPAbstractControl, Diagnostic>(); | |
private List<IItemPropertyDescriptor> leftColumnAttributes = new ArrayList<IItemPropertyDescriptor>(); | |
private List<IItemPropertyDescriptor> rightColumnAttributes = new ArrayList<IItemPropertyDescriptor>(); | |
private List<IItemPropertyDescriptor> bottomAttributes = new ArrayList<IItemPropertyDescriptor>(); | |
private Composite leftColumnComposite; | |
private Composite rightColumnComposite; | |
private Composite bottomComposite; | |
private ComposedAdapterFactory composedAdapterFactory; | |
/** {@inheritDoc} */ | |
public Composite createUI(Composite parent) { | |
Composite topComposite = new Composite(parent, SWT.NONE); | |
topComposite.setBackground(parent.getBackground()); | |
topComposite.setBackgroundMode(SWT.INHERIT_DEFAULT); | |
topComposite.setLayout(new GridLayout()); | |
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(topComposite); | |
sortAndOrderAttributes(); | |
if (!rightColumnAttributes.isEmpty()) { | |
SashForm topSash = new SashForm(topComposite, SWT.HORIZONTAL); | |
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(topSash); | |
// toolkit.adapt(topSash, true, true); | |
topSash.setSashWidth(4); | |
leftColumnComposite = new Composite(topSash, SWT.NONE); | |
rightColumnComposite = new Composite(topSash, SWT.NONE); | |
GridLayoutFactory.fillDefaults().numColumns(1).equalWidth(false).extendedMargins(5, 2, 5, 5) | |
.applyTo(rightColumnComposite); | |
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).applyTo(rightColumnComposite); | |
int[] topWeights = { 50, 50 }; | |
topSash.setWeights(topWeights); | |
} else { | |
leftColumnComposite = new Composite(topComposite, SWT.NONE); | |
} | |
GridLayoutFactory.fillDefaults().numColumns(1).equalWidth(false).extendedMargins(2, 5, 5, 5) | |
.applyTo(leftColumnComposite); | |
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).applyTo(leftColumnComposite); | |
bottomComposite = new Composite(topComposite, SWT.NONE); | |
GridLayoutFactory.fillDefaults().numColumns(1).equalWidth(false).extendedMargins(0, 0, 0, 0) | |
.applyTo(bottomComposite); | |
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(bottomComposite); | |
// Sort and order attributes | |
// Create attributes | |
createAttributes(leftColumnComposite, leftColumnAttributes); | |
if (!rightColumnAttributes.isEmpty()) { | |
createAttributes(rightColumnComposite, rightColumnAttributes); | |
} | |
createAttributes(bottomComposite, bottomAttributes); | |
updateLiveValidation(); | |
return topComposite; | |
} | |
/** | |
* Filters attributes marked with "hidden=true" annotation. | |
* | |
* @param propertyDescriptors | |
* property descriptors to filter | |
*/ | |
private void filterHiddenAttributes(Collection<IItemPropertyDescriptor> propertyDescriptors) { | |
Iterator<IItemPropertyDescriptor> iterator = propertyDescriptors.iterator(); | |
AnnotationHiddenDescriptor visibilityDescriptor = new AnnotationHiddenDescriptor(); | |
while (iterator.hasNext()) { | |
IItemPropertyDescriptor descriptor = iterator.next(); | |
if (visibilityDescriptor.getValue(descriptor, modelElementContext.getModelElement())) { | |
iterator.remove(); | |
} | |
} | |
} | |
private void sortAndOrderAttributes() { | |
composedAdapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE); | |
composedAdapterFactory = new ComposedAdapterFactory(new AdapterFactory[] { composedAdapterFactory, | |
new ReflectiveItemProviderAdapterFactory() }); | |
AdapterFactoryItemDelegator adapterFactoryItemDelegator = new AdapterFactoryItemDelegator( | |
composedAdapterFactory); | |
List<IItemPropertyDescriptor> propertyDescriptors = adapterFactoryItemDelegator | |
.getPropertyDescriptors(modelElementContext.getModelElement()); | |
if (propertyDescriptors != null) { | |
filterHiddenAttributes(propertyDescriptors); | |
AnnotationPositionDescriptor positionDescriptor = new AnnotationPositionDescriptor(); | |
for (IItemPropertyDescriptor itemPropertyDescriptor : propertyDescriptors) { | |
String value = positionDescriptor.getValue(itemPropertyDescriptor, | |
modelElementContext.getModelElement()); | |
if (value.equals("left")) { | |
leftColumnAttributes.add(itemPropertyDescriptor); | |
} else if (value.equals("right")) { | |
rightColumnAttributes.add(itemPropertyDescriptor); | |
} else if (value.equals("bottom")) { | |
bottomAttributes.add(itemPropertyDescriptor); | |
} else { | |
leftColumnAttributes.add(itemPropertyDescriptor); | |
} | |
} | |
final HashMap<IItemPropertyDescriptor, Double> priorityMap = new HashMap<IItemPropertyDescriptor, Double>(); | |
AnnotationPriorityDescriptor priorityDescriptor = new AnnotationPriorityDescriptor(); | |
for (IItemPropertyDescriptor itemPropertyDescriptor : propertyDescriptors) { | |
priorityMap.put(itemPropertyDescriptor, | |
priorityDescriptor.getValue(itemPropertyDescriptor, modelElementContext.getModelElement())); | |
} | |
Comparator<IItemPropertyDescriptor> comparator = new Comparator<IItemPropertyDescriptor>() { | |
public int compare(IItemPropertyDescriptor o1, IItemPropertyDescriptor o2) { | |
return Double.compare(priorityMap.get(o1), priorityMap.get(o2)); | |
} | |
}; | |
Collections.sort(leftColumnAttributes, comparator); | |
Collections.sort(rightColumnAttributes, comparator); | |
Collections.sort(bottomAttributes, comparator); | |
} | |
} | |
private void createAttributes(Composite column, List<IItemPropertyDescriptor> attributes) { | |
Composite attributeComposite = new Composite(column, SWT.NONE); | |
attributeComposite.setBackgroundMode(SWT.INHERIT_DEFAULT); | |
GridLayoutFactory.fillDefaults().numColumns(2).applyTo(attributeComposite); | |
GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.BEGINNING).indent(10, 0) | |
.applyTo(attributeComposite); | |
ECPControlFactory controlFactory = Activator.getDefault().getECPControlFactory(); | |
if (controlFactory == null) { | |
Activator.getDefault().ungetECPControlFactory(); | |
return; | |
} | |
for (IItemPropertyDescriptor itemPropertyDescriptor : attributes) { | |
SWTControl control = controlFactory.createControl(SWTControl.class, itemPropertyDescriptor, | |
modelElementContext); | |
if (control == null) { | |
continue; | |
} | |
int numColumnSpan = 2; | |
if (control.showLabel()) { | |
Label label = new Label(attributeComposite, SWT.NONE); | |
// label.setBackground(attributeComposite.getBackground()); | |
label.setText(itemPropertyDescriptor.getDisplayName(modelElementContext.getModelElement())); | |
label.setToolTipText(itemPropertyDescriptor.getDescription(modelElementContext.getModelElement())); | |
GridDataFactory.fillDefaults().align(SWT.BEGINNING, SWT.CENTER).applyTo(label); | |
numColumnSpan--; | |
} | |
Composite composite = control.createControl(attributeComposite); | |
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).span(numColumnSpan, 1) | |
.applyTo(composite); | |
meControls.put( | |
(EStructuralFeature) itemPropertyDescriptor.getFeature(modelElementContext.getModelElement()), control); | |
Activator.getDefault().ungetECPControlFactory(); | |
} | |
} | |
/** {@inheritDoc} */ | |
public void dispose() { | |
for (ECPAbstractControl control : meControls.values()) { | |
control.dispose(); | |
} | |
meControls.clear(); | |
modelElementChangeListener.remove(); | |
composedAdapterFactory.dispose(); | |
} | |
/** {@inheritDoc} */ | |
public void updateLiveValidation() { | |
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(modelElementContext.getModelElement()); | |
List<ECPAbstractControl> affectedControls = new ArrayList<ECPAbstractControl>(); | |
for (Iterator<Diagnostic> i = diagnostic.getChildren().iterator(); i.hasNext();) { | |
Diagnostic childDiagnostic = i.next(); | |
Object object = childDiagnostic.getData().get(0); | |
if (object instanceof EObject) { | |
EObject eObject = (EObject) object; | |
if (eObject != modelElementContext.getModelElement()) { | |
continue; | |
} | |
} | |
if (childDiagnostic.getData().size() < 2) { | |
continue; | |
} | |
ECPAbstractControl meControl = meControls.get(childDiagnostic.getData().get(1)); | |
if (meControl == null) { | |
continue; | |
} | |
affectedControls.add(meControl); | |
if (valdiatedControls.containsKey(meControl)) { | |
if (childDiagnostic.getSeverity() != valdiatedControls.get(meControl).getSeverity()) { | |
meControl.handleValidation(childDiagnostic); | |
valdiatedControls.put(meControl, childDiagnostic); | |
} | |
} else { | |
meControl.handleValidation(childDiagnostic); | |
valdiatedControls.put(meControl, childDiagnostic); | |
} | |
} | |
Map<ECPAbstractControl, Diagnostic> temp = new HashMap<ECPAbstractControl, Diagnostic>(); | |
temp.putAll(valdiatedControls); | |
for (Map.Entry<ECPAbstractControl, Diagnostic> entry : temp.entrySet()) { | |
ECPAbstractControl meControl = entry.getKey(); | |
if (!affectedControls.contains(meControl)) { | |
valdiatedControls.remove(meControl); | |
meControl.resetValidation(); | |
} | |
} | |
} | |
/** {@inheritDoc} */ | |
public void focus() { | |
leftColumnComposite.setFocus(); | |
} | |
} |