package org.openlca.app.editors.graphical;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.draw2d.ConnectionLayer;
import org.eclipse.draw2d.Layer;
import org.eclipse.draw2d.LayeredPane;
import org.eclipse.draw2d.StackLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.KeyHandler;
import org.eclipse.gef.KeyStroke;
import org.eclipse.gef.MouseWheelHandler;
import org.eclipse.gef.MouseWheelZoomHandler;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.editparts.ScalableRootEditPart;
import org.eclipse.gef.editparts.ZoomManager;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.actions.DeleteAction;
import org.eclipse.gef.ui.actions.GEFActionConstants;
import org.eclipse.gef.ui.actions.UpdateAction;
import org.eclipse.gef.ui.actions.ZoomInAction;
import org.eclipse.gef.ui.actions.ZoomOutAction;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.ui.IWorkbenchPart;
import org.openlca.app.components.ModelTransfer;
import org.openlca.app.editors.graphical.action.ActionFactory;
import org.openlca.app.editors.graphical.action.ActionIds;
import org.openlca.app.editors.graphical.action.EditorAction;
import org.openlca.app.editors.graphical.model.AppEditPartFactory;
import org.openlca.app.editors.graphical.model.ProductSystemNode;
import org.openlca.app.rcp.RcpActivator;
public class GraphicalViewerConfigurator {
public static final double[] ZOOM_LEVELS = new double[] { 0.01, 0.1, 0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 3.0, 5.0, 10.0 };
private GraphicalViewer viewer;
private ActionRegistry actionRegistry;
private CommandStack commandStack;
private ProductSystemNode model;
private Collection<String> actionExtensionIds = new HashSet<>();
GraphicalViewerConfigurator(GraphicalViewer viewer) {
this.viewer = viewer;
}
void setActionRegistry(ActionRegistry actionRegistry) {
this.actionRegistry = actionRegistry;
}
void setCommandStack(CommandStack commandStack) {
this.commandStack = commandStack;
}
void setModel(ProductSystemNode model) {
this.model = model;
}
void initializeGraphicalViewer() {
viewer.setRootEditPart(new ScalableRootEditPart() {
@Override
protected LayeredPane createPrintableLayers() {
LayeredPane pane = new LayeredPane();
Layer layer = new ConnectionLayer();
layer.setPreferredSize(new Dimension(5, 5));
pane.add(layer, CONNECTION_LAYER);
layer = new Layer();
layer.setOpaque(false);
layer.setLayoutManager(new StackLayout());
pane.add(layer, PRIMARY_LAYER);
return pane;
}
});
Transfer transferType = ModelTransfer.getInstance();
DropTarget dropTarget = new DropTarget(viewer.getControl(), DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_DEFAULT);
dropTarget.setTransfer(new Transfer[] { transferType });
dropTarget.addDropListener(new GraphDropListener(model, transferType, commandStack));
viewer.setContents(model);
}
void configureGraphicalViewer() {
viewer.setEditPartFactory(new AppEditPartFactory());
ScalableRootEditPart rootEditPart = new ScalableRootEditPart();
viewer.setRootEditPart(rootEditPart);
}
List<String> configureActions() {
registerStaticActions();
List<String> updateableActions = new ArrayList<>();
updateableActions.add(ActionIds.BUILD_SUPPLY_CHAIN_MENU);
updateableActions.add(ActionIds.REMOVE_SUPPLY_CHAIN);
updateableActions.add(ActionIds.REMOVE_ALL_CONNECTIONS);
updateableActions.add(org.eclipse.ui.actions.ActionFactory.DELETE.getId());
updateableActions.add(ActionIds.OPEN);
updateableActions.add(ActionIds.MARK);
updateableActions.add(ActionIds.UNMARK);
updateableActions.add(ActionIds.SEARCH_PROVIDERS);
updateableActions.add(ActionIds.SEARCH_RECIPIENTS);
updateableActions.add(ActionIds.OPEN_MINIATURE_VIEW);
List<String> updateableActionExtensions = configureActionExtensions();
updateableActions.addAll(updateableActionExtensions);
return updateableActions;
}
/**
* Get the action extension points and register them as actions in the
* graphical viewer
*/
private List<String> configureActionExtensions() {
List<String> updateableActions = new ArrayList<>();
List<Action> actions = loadActionExtensions();
for (Action action : actions) {
if (action instanceof EditorAction)
((EditorAction) action).setEditor(model.editor);
actionRegistry.registerAction(action);
if (action instanceof UpdateAction)
updateableActions.add(action.getId());
actionExtensionIds.add(action.getId());
}
return updateableActions;
}
private void registerStaticActions() {
final ProductSystemGraphEditor editor = model.editor;
actionRegistry.registerAction(ActionFactory.buildSupplyChainMenu(editor));
actionRegistry.registerAction(ActionFactory.removeSupplyChain(editor));
actionRegistry.registerAction(ActionFactory.removeAllConnections(editor));
actionRegistry.registerAction(ActionFactory.mark(editor));
actionRegistry.registerAction(ActionFactory.unmark(editor));
actionRegistry.registerAction(ActionFactory.saveImage(editor));
actionRegistry.registerAction(ActionFactory.expandAll(editor));
actionRegistry.registerAction(ActionFactory.collapseAll(editor));
actionRegistry.registerAction(ActionFactory.maximizeAll(editor));
actionRegistry.registerAction(ActionFactory.minimizeAll(editor));
actionRegistry.registerAction(ActionFactory.layoutMenu(editor));
actionRegistry.registerAction(ActionFactory.searchProviders(editor));
actionRegistry.registerAction(ActionFactory.searchRecipients(editor));
actionRegistry.registerAction(ActionFactory.open(editor));
actionRegistry.registerAction(ActionFactory.openMiniatureView(editor));
actionRegistry.registerAction(ActionFactory.showOutline());
actionRegistry.registerAction(new ZoomInAction(getZoomManager()));
actionRegistry.registerAction(new ZoomOutAction(getZoomManager()));
DeleteAction delAction = new DeleteAction((IWorkbenchPart) editor) {
@Override
protected ISelection getSelection() {
return editor.getSite().getWorkbenchWindow().getSelectionService().getSelection();
}
};
actionRegistry.registerAction(delAction);
}
void configureZoomManager() {
getZoomManager().setZoomLevels(ZOOM_LEVELS);
getZoomManager().setZoomAnimationStyle(ZoomManager.ANIMATE_ZOOM_IN_OUT);
viewer.setProperty(MouseWheelHandler.KeyGenerator.getKey(SWT.NONE), MouseWheelZoomHandler.SINGLETON);
}
void configureKeyHandler() {
KeyHandler keyHandler = new KeyHandler();
IAction delete = actionRegistry.getAction(org.eclipse.ui.actions.ActionFactory.DELETE.getId());
IAction zoomIn = actionRegistry.getAction(GEFActionConstants.ZOOM_IN);
IAction zoomOut = actionRegistry.getAction(GEFActionConstants.ZOOM_OUT);
keyHandler.put(KeyStroke.getPressed(SWT.DEL, 127, 0), delete);
keyHandler.put(KeyStroke.getPressed('+', SWT.KEYPAD_ADD, 0), zoomIn);
keyHandler.put(KeyStroke.getPressed('-', SWT.KEYPAD_SUBTRACT, 0), zoomOut);
viewer.setKeyHandler(keyHandler);
}
void configureContextMenu() {
MenuProvider provider = new MenuProvider(viewer, actionRegistry);
provider.setActionExtensions(actionExtensionIds);
viewer.setContextMenu(provider);
}
private ZoomManager getZoomManager() {
return getRootEditPart().getZoomManager();
}
private ScalableRootEditPart getRootEditPart() {
return (ScalableRootEditPart) viewer.getRootEditPart();
}
private List<Action> loadActionExtensions() {
List<Action> adapters = new ArrayList<>();
IConfigurationElement[] elements = Platform.getExtensionRegistry().getConfigurationElementsFor(
"org.openlca.app.editors.graphical.actions");
for (IConfigurationElement element : elements) {
Action action = loadAction(element);
if (action == null)
continue;
adapters.add(action);
}
return adapters;
}
private Action loadAction(IConfigurationElement element) {
try {
return (Action) element.createExecutableExtension("class");
} catch (ClassCastException | CoreException e) {
IStatus status = new Status(IStatus.ERROR, RcpActivator.PLUGIN_ID,
"Error while loading action extensions for graphical editor", e);
RcpActivator.getDefault().getLog().log(status);
return null;
}
}
}