package org.activiti.designer.property;
import java.util.Set;
import org.activiti.designer.Activator;
import org.activiti.designer.PluginImage;
import org.activiti.designer.eclipse.common.ActivitiBPMNDiagramConstants;
import org.activiti.designer.eclipse.common.ActivitiPlugin;
import org.activiti.designer.util.eclipse.ActivitiUiUtil;
import org.activiti.designer.util.property.ActivitiPropertySection;
import org.activiti.designer.util.workspace.ActivitiWorkspaceUtil;
import org.apache.commons.lang.StringUtils;
import org.eclipse.bpmn2.CallActivity;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.graphiti.ui.editor.DiagramEditor;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertyConstants;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetWidgetFactory;
public class PropertyCallActivitySection extends ActivitiPropertySection implements ITabbedPropertyConstants {
private Text callElementText;
private Button callElementButton;
@Override
public void createControls(Composite parent, TabbedPropertySheetPage tabbedPropertySheetPage) {
super.createControls(parent, tabbedPropertySheetPage);
TabbedPropertySheetWidgetFactory factory = getWidgetFactory();
Composite composite = factory.createFlatFormComposite(parent);
FormData data;
callElementButton = factory.createButton(composite, StringUtils.EMPTY, SWT.PUSH);
callElementButton.setImage(Activator.getImage(PluginImage.ACTION_GO));
data = new FormData();
data.right = new FormAttachment(100, -HSPACE);
callElementButton.setLayoutData(data);
callElementButton.addSelectionListener(openListener);
callElementText = factory.createText(composite, ""); //$NON-NLS-1$
data = new FormData();
data.left = new FormAttachment(0, 150);
data.right = new FormAttachment(callElementButton, -HSPACE);
data.top = new FormAttachment(0, VSPACE);
callElementText.setLayoutData(data);
callElementText.addFocusListener(listener);
callElementText.addListener(SWT.CHANGED, new Listener() {
@Override
public void handleEvent(Event arg0) {
evaluateCallElementButtonEnabled();
}
});
CLabel elementLabel = factory.createCLabel(composite, "Called element:"); //$NON-NLS-1$
data = new FormData();
data.left = new FormAttachment(0, 0);
data.right = new FormAttachment(callElementText, -HSPACE);
data.top = new FormAttachment(callElementText, 0, SWT.TOP);
elementLabel.setLayoutData(data);
}
@Override
public void refresh() {
callElementText.removeFocusListener(listener);
PictogramElement pe = getSelectedPictogramElement();
if (pe != null) {
Object bo = Graphiti.getLinkService().getBusinessObjectForLinkedPictogramElement(pe);
// the filter assured, that it is a EClass
if (bo == null)
return;
CallActivity callActivity = (CallActivity) bo;
String calledElement = callActivity.getCalledElement();
callElementText.setText(calledElement == null ? "" : calledElement);
}
callElementText.addFocusListener(listener);
evaluateCallElementButtonEnabled();
}
private void evaluateCallElementButtonEnabled() {
final String callElement = callElementText.getText();
if (StringUtils.isBlank(callElement)) {
disableCallElementButton();
} else {
final Set<IFile> resources = ActivitiWorkspaceUtil.getBPMNResourcesById(callElement);
if (resources.size() > 0) {
enableCallElementButton();
} else {
disableCallElementButton();
}
}
}
private void disableCallElementButton() {
callElementButton.setEnabled(false);
}
private void enableCallElementButton() {
callElementButton.setEnabled(true);
callElementButton.setToolTipText("Click to open the called element's process diagram");
}
private SelectionListener openListener = new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent event) {
final String calledElement = callElementText.getText();
final Set<IFile> resources = ActivitiWorkspaceUtil.getBPMNResourcesById(calledElement);
if (resources.size() == 1) {
// open diagram
openDiagramForBpmnFile(resources.iterator().next());
} else if (resources.size() > 1) {
// TODO open selection dialog, http://jira.codehaus.org/browse/ACT-895
MessageDialog.openInformation(Display.getCurrent().getActiveShell(), "Multiple processes found", String.format(
"There are multiple resources in the workspace that have the call element id of '%s'. Cannot determine which file should be opened.",
calledElement));
} else {
// The button should not have been enabled in the first place
throw new IllegalStateException(String.format("Cannot open diagram for process id '%s' because it can't be found in the workspace", calledElement));
}
}
private void openDiagramForBpmnFile(IFile resource) {
boolean openBpmnFile = true;
IFile activitiFile = null;
// Get the Activiti file to go with the provided resource
final IPath activitiFilePath = resource.getFullPath().removeFileExtension().removeFileExtension()
.addFileExtension(ActivitiBPMNDiagramConstants.DIAGRAM_EXTENSION_RAW);
final IResource activitiResource = ResourcesPlugin.getWorkspace().getRoot().findMember(activitiFilePath);
if (activitiResource != null && activitiResource.exists() && activitiResource instanceof IFile) {
activitiFile = (IFile) activitiResource;
openBpmnFile = false;
}
try {
if (!openBpmnFile) {
IFileEditorInput input = new FileEditorInput(activitiFile);
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().openEditor(input, ActivitiBPMNDiagramConstants.DIAGRAM_EDITOR_ID);
} else {
boolean userChoice = MessageDialog
.openConfirm(
Display.getCurrent().getActiveShell(),
"No diagram file found",
String.format(
"The process with id '%s' was found in the workspace, but its matching diagram file with name '%s' appears to be missing. Would you like to open the BPMN 2.0 XML Editor instead?",
callElementText.getText(), activitiFilePath.lastSegment()));
if (userChoice) {
IFileEditorInput input = new FileEditorInput(resource);
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().openEditor(input, ActivitiBPMNDiagramConstants.BPMN_EDITOR_ID);
}
}
} catch (PartInitException e) {
String error = "Error while opening editor";
IStatus status = new Status(IStatus.ERROR, ActivitiPlugin.getID(), error, e);
ErrorDialog.openError(Display.getCurrent().getActiveShell(), "An error occured", null, status);
return;
}
}
@Override
public void widgetDefaultSelected(SelectionEvent event) {
widgetSelected(event);
}
};
private FocusListener listener = new FocusListener() {
public void focusGained(final FocusEvent e) {
}
public void focusLost(final FocusEvent e) {
PictogramElement pe = getSelectedPictogramElement();
if (pe != null) {
Object bo = Graphiti.getLinkService().getBusinessObjectForLinkedPictogramElement(pe);
if (bo instanceof CallActivity) {
DiagramEditor diagramEditor = (DiagramEditor) getDiagramEditor();
TransactionalEditingDomain editingDomain = diagramEditor.getEditingDomain();
ActivitiUiUtil.runModelChange(new Runnable() {
public void run() {
Object bo = Graphiti.getLinkService().getBusinessObjectForLinkedPictogramElement(getSelectedPictogramElement());
if (bo == null) {
return;
}
String calledElement = callElementText.getText();
CallActivity callActivity = (CallActivity) bo;
callActivity.setCalledElement(calledElement);
}
}, editingDomain, "Model Update");
}
}
}
};
}