/*******************************************************************************
* <copyright>
*
* Copyright (c) 2005, 2010 SAP AG.
* 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:
* SAP AG - initial API, implementation and documentation
*
* </copyright>
*
*******************************************************************************/
package org.activiti.designer.property;
import org.activiti.bpmn.model.Artifact;
import org.activiti.bpmn.model.BaseElement;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.Lane;
import org.activiti.bpmn.model.Pool;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.TextAnnotation;
import org.activiti.designer.util.TextUtil;
import org.activiti.designer.util.editor.Bpmn2MemoryModel;
import org.activiti.designer.util.editor.ModelHandler;
import org.activiti.designer.util.property.ActivitiPropertySection;
import org.apache.commons.lang.StringUtils;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.graphiti.features.IFeature;
import org.eclipse.graphiti.features.IUpdateFeature;
import org.eclipse.graphiti.features.context.IContext;
import org.eclipse.graphiti.features.context.impl.CustomContext;
import org.eclipse.graphiti.features.context.impl.UpdateContext;
import org.eclipse.graphiti.features.impl.AbstractFeature;
import org.eclipse.graphiti.mm.algorithms.MultiText;
import org.eclipse.graphiti.mm.pictograms.ConnectionDecorator;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.FreeFormConnection;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.mm.pictograms.Shape;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertyConstants;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetWidgetFactory;
/** TODO: rename this to GeneralSection as it contains basic things on the 'General' tab. */
public class PropertyBpmnSection extends ActivitiPropertySection implements ITabbedPropertyConstants {
private Composite composite;
private Text idText;
private CLabel nameLabel;
private Text nameText;
@Override
public void createControls(Composite parent, TabbedPropertySheetPage tabbedPropertySheetPage) {
super.createControls(parent, tabbedPropertySheetPage);
TabbedPropertySheetWidgetFactory factory = getWidgetFactory();
composite = factory.createFlatFormComposite(parent);
FormData data;
idText = factory.createText(composite, ""); //$NON-NLS-1$
data = new FormData();
data.left = new FormAttachment(0, 120);
data.right = new FormAttachment(100, -HSPACE);
data.top = new FormAttachment(0, VSPACE);
idText.setLayoutData(data);
CLabel idLabel = factory.createCLabel(composite, "Id:", SWT.WRAP); //$NON-NLS-1$
data = new FormData();
data.left = new FormAttachment(0, 0);
data.right = new FormAttachment(idText, -HSPACE);
data.top = new FormAttachment(idText, 0, SWT.CENTER);
idLabel.setLayoutData(data);
nameText = factory.createText(composite, ""); //$NON-NLS-1$
data = new FormData();
data.left = new FormAttachment(0, 120);
data.right = new FormAttachment(100, -HSPACE);
data.top = new FormAttachment(idText, VSPACE);
nameText.setLayoutData(data);
nameLabel = factory.createCLabel(composite, "Name:", SWT.WRAP); //$NON-NLS-1$
data = new FormData();
data.left = new FormAttachment(0, 0);
data.right = new FormAttachment(nameText, -HSPACE);
data.top = new FormAttachment(nameText, 0, SWT.CENTER);
nameLabel.setLayoutData(data);
}
@Override
public void refresh() {
nameText.removeModifyListener(listener);
idText.removeModifyListener(listener);
PictogramElement pe = getSelectedPictogramElement();
if (pe != null) {
Object bo = getBusinessObject(pe);
// the filter assured, that it is a EClass
if (bo == null) {
return;
}
String name = null;
if (bo instanceof FlowElement) {
name = ((FlowElement) bo).getName();
} else if (bo instanceof Pool) {
name = ((Pool) bo).getName();
} else if (bo instanceof Lane) {
name = ((Lane) bo).getName();
} else if (bo instanceof Artifact) {
// text annotations do not have a name
nameText.setVisible(false);
nameLabel.setVisible(false);
}
String id = ((BaseElement) bo).getId();
nameText.setText(name == null ? "" : name);
idText.setText(id == null ? "" : id);
idText.addModifyListener(listener);
nameText.addModifyListener(listener);
}
}
private ModifyListener listener = new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
final PictogramElement pe = getSelectedPictogramElement();
if (pe == null) {
return;
}
final Object bo = getBusinessObject(pe);
if (!(bo instanceof BaseElement) || bo instanceof TextAnnotation) {
// we need to exclude the text annotation here, although it is a base element
// because it's text is handled differently and by the corresponding property
// PropertyTextAnnotationSection
// if we do not ignore this here, the text will get lost during activation
// of the base property sheet.
return;
}
if (e.getSource() == idText) {
String id = ((BaseElement) bo).getId();
if (StringUtils.isEmpty(id) || id.equals(idText.getText()) == false) {
IFeature feature = new AbstractFeature(getDiagramTypeProvider().getFeatureProvider()) {
@Override
public void execute(IContext context) {
BaseElement element = (BaseElement) bo;
updateParentLane(element.getId(), idText.getText());
updateFlows(element, idText.getText());
element.setId(idText.getText());
}
@Override
public boolean canExecute(IContext context) {
return true;
}
};
CustomContext context = new CustomContext();
execute(feature, context);
}
} else if (e.getSource() == nameText) {
final String name = getName(bo);
if (StringUtils.isEmpty(name) || name.equals(nameText.getText()) == false) {
IFeature feature = new AbstractFeature(getDiagramTypeProvider().getFeatureProvider()) {
@Override
public void execute(IContext context) {
setName(bo, nameText.getText());
UpdateContext updateContext = new UpdateContext(pe);
IUpdateFeature updateFeature = getDiagramTypeProvider().getFeatureProvider().getUpdateFeature(updateContext);
if(updateFeature != null) {
updateFeature.update(updateContext);
}
if (pe instanceof ContainerShape) {
ContainerShape cs = (ContainerShape) pe;
for (Shape shape : cs.getChildren()) {
if (shape.getGraphicsAlgorithm() instanceof Text) {
org.eclipse.graphiti.mm.algorithms.Text text = (org.eclipse.graphiti.mm.algorithms.Text) shape.getGraphicsAlgorithm();
text.setValue(nameText.getText());
}
if (shape.getGraphicsAlgorithm() instanceof MultiText) {
MultiText text = (MultiText) shape.getGraphicsAlgorithm();
text.setValue(nameText.getText());
}
}
}
if (!(getSelectedPictogramElement() instanceof FreeFormConnection)) {
return;
}
EList<ConnectionDecorator> decoratorList = ((FreeFormConnection) getSelectedPictogramElement()).getConnectionDecorators();
for (ConnectionDecorator decorator : decoratorList) {
if (decorator.getGraphicsAlgorithm() instanceof org.eclipse.graphiti.mm.algorithms.MultiText) {
org.eclipse.graphiti.mm.algorithms.MultiText text = (org.eclipse.graphiti.mm.algorithms.MultiText) decorator.getGraphicsAlgorithm();
text.setValue(nameText.getText());
TextUtil.setTextSize(nameText.getText(), text);
}
}
}
@Override
public boolean canExecute(IContext context) {
return true;
}
};
CustomContext context = new CustomContext();
execute(feature, context);
}
}
}
};
protected void updateParentLane(String oldElementId, String newElementId) {
Bpmn2MemoryModel model = ModelHandler.getModel(EcoreUtil.getURI(getDiagram()));
for (Process process : model.getBpmnModel().getProcesses()) {
for (Lane lane : process.getLanes()) {
if (lane.getFlowReferences().contains(oldElementId)) {
lane.getFlowReferences().remove(oldElementId);
lane.getFlowReferences().add(newElementId);
return;
}
}
}
}
protected void updateFlows(BaseElement element, String newElementId) {
if (element instanceof FlowNode) {
FlowNode flowNode = (FlowNode) element;
for (SequenceFlow sequenceFlow : flowNode.getIncomingFlows()) {
sequenceFlow.setTargetRef(newElementId);
}
for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
sequenceFlow.setSourceRef(newElementId);
}
}
}
protected String getName(Object bo) {
String name = null;
if (bo instanceof FlowElement) {
name = ((FlowElement) bo).getName();
} else if (bo instanceof Pool) {
name = ((Pool) bo).getName();
} else if (bo instanceof Lane) {
name = ((Lane) bo).getName();
}
return name;
}
protected void setName(Object bo, String name) {
if (bo instanceof FlowElement) {
((FlowElement) bo).setName(name);
} else if (bo instanceof Pool) {
((Pool) bo).setName(name);
} else if (bo instanceof Lane) {
((Lane) bo).setName(name);
}
}
}