blob: 04b6cd51c9de495c9923a422cfebaaecc6d08ea3 [file] [log] [blame]
package org.eclipse.fx.ecp.ui.controls.multi;
import java.net.URL;
import java.util.Collection;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.control.SkinBase;
import javafx.scene.image.ImageView;
import javafx.scene.input.DragEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.VBox;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
import org.eclipse.fx.ecp.ui.ECPControl;
import org.eclipse.fx.ecp.ui.ECPModelElementOpener;
import org.eclipse.fx.ecp.ui.ECPUIPlugin;
import org.eclipse.fx.ecp.ui.controls.ECPControlBase;
import org.eclipse.fx.emf.edit.ui.dnd.LocalTransfer;
import org.osgi.framework.Bundle;
@SuppressWarnings("all")
public class MultiControl extends ECPControlBase {
protected EList<Object> values;
protected VBox controlsBox;
protected ECPControlBase addControl;
protected Command addReferenceCommand;
protected ECPModelElementOpener modelElementOpener;
class Skin extends SkinBase<MultiControl> {
protected Skin(MultiControl multiControl) {
super(multiControl);
}
}
public MultiControl(final IItemPropertyDescriptor propertyDescriptor, final EObject modelElement, final EditingDomain editingDomain, ECPModelElementOpener modelElementOpener) {
super(propertyDescriptor, modelElement, editingDomain);
this.modelElementOpener = modelElementOpener;
setSkin(new Skin(this));
values = (EList<Object>) modelElement.eGet(feature);
VBox vBox = new VBox();
getChildren().add(vBox);
vBox.setSpacing(4);
controlsBox = new VBox();
vBox.getChildren().add(controlsBox);
// TODO move to css
controlsBox.setSpacing(4);
for (int i = 0; i < values.size(); i++) {
controlsBox.getChildren().add(createEmbeddedControl(propertyDescriptor, modelElement, editingDomain, i));
}
if (feature.getEType() instanceof EEnum) {
vBox.getChildren().add(addControl = new EnumAddControl(propertyDescriptor, modelElement, editingDomain));
} else if (feature.getEType() instanceof EDataType) {
vBox.getChildren().add(addControl = new TextFieldAddControl(propertyDescriptor, modelElement, editingDomain));
} else if (feature.getEType() instanceof EObject) {
vBox.getChildren().add(addControl = new ReferenceAddControl(propertyDescriptor, modelElement, editingDomain));
setOnDragOver(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent event) {
Object object = LocalTransfer.INSTANCE.getObject();
Command command = object instanceof Collection<?> ? AddCommand.create(editingDomain, modelElement, feature,
(Collection<?>) object) : AddCommand.create(editingDomain, modelElement, feature, object);
if (command.canExecute()) {
addReferenceCommand = command;
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
} else {
addReferenceCommand = null;
}
}
});
setOnDragDropped(new EventHandler<DragEvent>() {
@Override
public void handle(DragEvent arg0) {
if (addReferenceCommand != null)
editingDomain.getCommandStack().execute(addReferenceCommand);
}
});
}
}
@Override
public void dispose() {
// dispose the embedded controls
for (Node control : controlsBox.getChildren())
((AbstractEmbeddedControl) control).dispose();
// and the add-control
addControl.dispose();
super.dispose();
}
@Override
protected AdapterImpl createModelElementAdapter() {
return new AdapterImpl() {
@Override
public void notifyChanged(Notification msg) {
if (msg.getFeature() == feature) {
final int position = msg.getPosition();
ObservableList<Node> children = controlsBox.getChildren();
switch (msg.getEventType()) {
case Notification.ADD:
controlsBox.getChildren().add(createEmbeddedControl(propertyDescriptor, modelElement, editingDomain, position));
break;
case Notification.REMOVE: {
AbstractEmbeddedControl control = (AbstractEmbeddedControl) children.get(position);
control.dispose();
children.remove(control);
}
break;
case Notification.MOVE:
case Notification.SET:
case Notification.UNSET:
break;
case Notification.ADD_MANY:
while (children.size() < values.size())
children.add(createEmbeddedControl(propertyDescriptor, modelElement, editingDomain, 0));
break;
case Notification.REMOVE_MANY:
while (children.size() > values.size()) {
AbstractEmbeddedControl control = (AbstractEmbeddedControl) children.get(0);
control.dispose();
children.remove(control);
}
break;
default:
throw new UnsupportedOperationException();
}
for (int i = 0; i < children.size(); i++) {
Node node = children.get(i);
if (node instanceof AbstractEmbeddedControl)
((AbstractEmbeddedControl) node).setIndex(i);
}
}
}
};
}
private AbstractEmbeddedControl createEmbeddedControl(final IItemPropertyDescriptor propertyDescriptor,
final EObject modelElement, final EditingDomain editingDomain, int i) {
if (feature instanceof EReference) {
return new EmbeddedReferenceControl(propertyDescriptor, modelElement, editingDomain, i, modelElementOpener);
} else if (feature.getEType() instanceof EEnum) {
return new EmbeddedEnumControl(propertyDescriptor, modelElement, editingDomain, i);
} else {
Class<?> instanceClass = feature.getEType().getInstanceClass();
if (Boolean.class.isAssignableFrom(instanceClass)) {
return new EmbeddedCheckboxControl(propertyDescriptor, modelElement, editingDomain, i);
} else if (Number.class.isAssignableFrom(instanceClass)
|| (instanceClass.isPrimitive() && instanceClass != boolean.class && instanceClass != char.class)) {
return new EmbeddedNumberFieldControl(propertyDescriptor, modelElement, editingDomain, i);
} else {
return new EmbeddedTextFieldControl(propertyDescriptor, modelElement, editingDomain, i);
}
}
}
public static ImageView getImage(String resourcePath) {
Bundle bundle = Platform.getBundle(ECPUIPlugin.PLUGIN_ID);
Path path = new Path(resourcePath);
URL url = FileLocator.find(bundle, path, null);
return new ImageView(url.toExternalForm());
}
public static class Factory implements ECPControl.Factory {
@Override
public ECPControlBase createControl(IItemPropertyDescriptor itemPropertyDescriptor, EObject modelElement, EditingDomain editingDomain, ECPModelElementOpener modelElementOpener) {
return new MultiControl(itemPropertyDescriptor, modelElement, editingDomain, modelElementOpener);
}
}
@Override
protected void update() {
// TODO Auto-generated method stub
}
}