/*******************************************************************************
* Copyright (c) 2007 Spring IDE Developers
* 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:
* Spring IDE Developers - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.webflow.ui.graph.parts;
import java.util.Map;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.draw2d.graph.CompoundDirectedGraph;
import org.eclipse.draw2d.graph.Node;
import org.eclipse.draw2d.graph.Subgraph;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.NodeEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.requests.DirectEditRequest;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;
import org.springframework.ide.eclipse.webflow.core.model.IActionElement;
import org.springframework.ide.eclipse.webflow.core.model.IAttributeMapper;
import org.springframework.ide.eclipse.webflow.core.model.IExceptionHandler;
import org.springframework.ide.eclipse.webflow.core.model.IInlineFlowState;
import org.springframework.ide.eclipse.webflow.core.model.IState;
import org.springframework.ide.eclipse.webflow.core.model.ISubflowState;
import org.springframework.ide.eclipse.webflow.core.model.IWebflowModelElement;
import org.springframework.ide.eclipse.webflow.core.model.IWebflowState;
import org.springframework.ide.eclipse.webflow.ui.graph.actions.EditPropertiesAction;
import org.springframework.ide.eclipse.webflow.ui.graph.figures.CompoundStateFigure;
import org.springframework.ide.eclipse.webflow.ui.graph.figures.SubgraphFigure;
import org.springframework.ide.eclipse.webflow.ui.graph.model.WebflowModelLabelDecorator;
import org.springframework.ide.eclipse.webflow.ui.graph.model.WebflowModelLabelProvider;
import org.springframework.ide.eclipse.webflow.ui.graph.policies.FlowStateLayoutEditPolicy;
import org.springframework.ide.eclipse.webflow.ui.graph.policies.StateContainerEditPolicy;
import org.springframework.ide.eclipse.webflow.ui.graph.policies.StateContainerHighlightEditPolicy;
import org.springframework.ide.eclipse.webflow.ui.graph.policies.StateEditPolicy;
import org.springframework.ide.eclipse.webflow.ui.graph.policies.StateNodeEditPolicy;
/**
* @author Christian Dupuis
*/
public abstract class ChildrenStatePart extends AbstractStatePart implements
NodeEditPart {
protected static ILabelProvider labelProvider = new DecoratingLabelProvider(
new WebflowModelLabelProvider(), new WebflowModelLabelDecorator());
protected WebflowModelLabelProvider eLabelProvider = new WebflowModelLabelProvider();
protected void applyChildrenResults(CompoundDirectedGraph graph, Map map) {
for (int i = 0; i < getChildren().size(); i++) {
AbstractStatePart part = (AbstractStatePart) getChildren().get(i);
part.applyGraphResults(graph, map);
}
}
protected void applyMaxWidths() {
int width = 0;
for (int i = 0; i < getChildren().size(); i++) {
AbstractStatePart part = (AbstractStatePart) getChildren().get(i);
if (part.getModel() instanceof IActionElement
|| part.getModel() instanceof IExceptionHandler
|| part.getModel() instanceof IAttributeMapper) {
Rectangle rec = part.getFigure().getBounds();
if (rec.width >= width) {
width = rec.width;
}
}
}
for (int i = 0; i < getChildren().size(); i++) {
AbstractStatePart part = (AbstractStatePart) getChildren().get(i);
if (part.getModel() instanceof IActionElement
|| part.getModel() instanceof IExceptionHandler
|| part.getModel() instanceof IAttributeMapper) {
Rectangle rect = part.getFigure().getBounds();
rect.width = width;
part.getFigure().setBounds(rect);
}
}
}
protected void applyChildrenResultsToOwn(CompoundDirectedGraph graph,
Map map) {
Node n = (Node) map.get(this);
int bottom = -1;
for (int i = 0; i < getChildren().size(); i++) {
AbstractStatePart part = (AbstractStatePart) getChildren().get(i);
if (part.getFigure().getBounds().bottom() > bottom) {
bottom = part.getFigure().getBounds().getBottom().y;
}
}
if (bottom > -1) {
int top = getFigure().getBounds().getTop().y;
int height = bottom - top + 7 + 7;
getFigure().setBounds(new Rectangle(n.x, n.y, n.width, height));
}
}
protected void applyGraphResults(CompoundDirectedGraph graph, Map map) {
applyOwnResults(graph, map);
applyChildrenResults(graph, map);
applyChildrenResultsToOwn(graph, map);
}
protected void applyOwnResults(CompoundDirectedGraph graph, Map map) {
Node n = (Node) map.get(this);
if (getModelChildren() != null && getModelChildren().size() > 0) {
getFigure().setBounds(new Rectangle(n.x, n.y, n.width, n.height));
}
else {
int height = ((CompoundStateFigure) getFigure()).getHeader()
.getPreferredSize().height;
if (height < 20) {
getFigure().setBounds(new Rectangle(n.x, n.y, n.width, 23));
}
else {
getFigure().setBounds(new Rectangle(n.x, n.y, n.width, 33));
}
}
for (int i = 0; i < getSourceConnections().size(); i++) {
StateTransitionPart trans = (StateTransitionPart) getSourceConnections()
.get(i);
trans.applyGraphResults(graph, map);
}
}
@SuppressWarnings("unchecked")
public void contributeNodesToGraph(CompoundDirectedGraph graph, Subgraph s,
Map map) {
GraphAnimation.recordInitialState(getContentPane());
Subgraph me = new Subgraph(this, s);
IState state = (IState) getModel();
if (!(state instanceof IWebflowState)) {
int index = -1;
int stateCount = ((IWebflowState) state.getElementParent())
.getStates().size();
if (state instanceof IInlineFlowState) {
index = ((IWebflowState) state.getElementParent())
.getInlineFlowStates().indexOf(state)
+ stateCount;
}
else {
index = ((IWebflowState) state.getElementParent()).getStates()
.indexOf(state);
}
me.setRowConstraint(index);
}
me.outgoingOffset = 5;
me.incomingOffset = 5;
IFigure fig = getFigure();
if (fig instanceof SubgraphFigure) {
me.width = fig.getPreferredSize(me.width, me.height).width;
me.height = fig.getPreferredSize().height;
me.insets.top = ((CompoundStateFigure) getFigure()).getHeader()
.getPreferredSize().height + 5;
me.insets.left = 5;
me.insets.right = 5;
me.insets.bottom = 15;
}
me.innerPadding = new Insets(0, 0, 0, 4);
// me.setPadding(new Insets(10, 50, 50, 0));
map.put(this, me);
graph.nodes.add(me);
for (int i = 0; i < getChildren().size(); i++) {
AbstractStatePart activity = (AbstractStatePart) getChildren().get(
i);
activity.contributeNodesToGraph(graph, me, map);
}
}
protected void createEditPolicies() {
installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE,
new StateNodeEditPolicy());
installEditPolicy(EditPolicy.COMPONENT_ROLE, new StateEditPolicy());
installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE,
new StateContainerHighlightEditPolicy());
installEditPolicy(EditPolicy.CONTAINER_ROLE,
new StateContainerEditPolicy());
installEditPolicy(EditPolicy.LAYOUT_ROLE,
new FlowStateLayoutEditPolicy());
installEditPolicy(EditPolicy.DIRECT_EDIT_ROLE, null);
}
protected IFigure createFigure() {
CompoundStateFigure figure = new CompoundStateFigure((IWebflowModelElement) getModel());
((Label) figure.getHeader())
.setIcon(labelProvider.getImage(getModel()));
((Label) figure.getHeader()).setIconTextGap(5);
((Label) figure.getHeader()).setIconAlignment(PositionConstants.TOP);
return figure;
}
private boolean directEditHitTest(Point requestLoc) {
return false;
}
public IFigure getContentPane() {
if (getFigure() instanceof SubgraphFigure)
return ((SubgraphFigure) getFigure()).getContents();
return getFigure();
}
public void performRequest(Request request) {
if (request.getType() == RequestConstants.REQ_DIRECT_EDIT) {
if (request instanceof DirectEditRequest
&& !directEditHitTest(((DirectEditRequest) request)
.getLocation().getCopy()))
return;
performDirectEdit();
}
else if (request.getType().equals(RequestConstants.REQ_OPEN)) {
IEditorPart editor = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage()
.getActiveEditor();
ActionRegistry actionRegistry = (ActionRegistry) editor
.getAdapter(ActionRegistry.class);
IAction action = actionRegistry
.getAction(EditPropertiesAction.EDITPROPERTIES);
if (action != null && action.isEnabled()) {
action.run();
}
}
}
protected void refreshVisuals() {
((Label) ((SubgraphFigure) getFigure()).getHeader())
.setText(labelProvider.getText(getModel()));
((Label) ((SubgraphFigure) getFigure()).getHeader())
.setIcon(labelProvider.getImage(getModel()));
((Label) ((SubgraphFigure) getFigure()).getHeader()).setIconTextGap(5);
((Label) ((SubgraphFigure) getFigure()).getHeader())
.setToolTip(new Label(eLabelProvider.getText(getModel(), true, true, true)));
getFigure().repaint();
}
public void setSelected(int value) {
super.setSelected(value);
if (!(getModel() instanceof IWebflowState)
|| getModel() instanceof ISubflowState) {
SubgraphFigure sf = (SubgraphFigure) getFigure();
sf.setSelected(value != SELECTED_NONE);
}
}
}