package org.marketcetera.photon.internal.strategy.engine.ui.workbench;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.ControlEnableState;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.dialogs.PropertyPage;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.ui.views.properties.IPropertySourceProvider;
import org.eclipse.ui.views.properties.PropertySheetEntry;
import org.eclipse.ui.views.properties.PropertySheetPage;
import org.eclipse.ui.views.properties.TextPropertyDescriptor;
import org.marketcetera.photon.commons.ui.JFaceUtils;
import org.marketcetera.photon.commons.ui.workbench.DataBindingPropertyPage;
import org.marketcetera.photon.strategy.engine.model.core.DeployedStrategy;
import org.marketcetera.photon.strategy.engine.model.core.StrategyEngine;
import org.marketcetera.photon.strategy.engine.model.core.StrategyEngineConnection;
import org.marketcetera.photon.strategy.engine.model.core.StrategyState;
import org.marketcetera.photon.strategy.engine.ui.StrategyEngineImage;
import org.marketcetera.photon.strategy.engine.ui.StrategyEngineUI;
import org.marketcetera.util.except.ExceptUtils;
import org.marketcetera.util.log.I18NBoundMessage1P;
import org.marketcetera.util.misc.ClassVersion;
/* $License$ */
/**
* {@link PropertyPage} to edit {@link DeployedStrategy} properties.
*
* @author <a href="mailto:will@marketcetera.com">Will Horn</a>
* @version $Id: DeployedStrategyConfigurationPropertyPage.java 16154 2012-07-14 16:34:05Z colin $
* @since 1.0.0
*/
@ClassVersion("$Id: DeployedStrategyConfigurationPropertyPage.java 16154 2012-07-14 16:34:05Z colin $")
public class DeployedStrategyConfigurationPropertyPage extends
DataBindingPropertyPage {
private DeployedStrategy mOriginalStrategy;
private DeployedStrategy mNewStrategy;
private PropertySheetPage mPage;
/**
* Constructor.
*/
public DeployedStrategyConfigurationPropertyPage() {
setImageDescriptor(StrategyEngineImage.STRATEGY_OBJ
.getImageDescriptor());
noDefaultAndApplyButton();
}
@Override
protected Control createContents(Composite parent) {
mOriginalStrategy = (DeployedStrategy) getElement().getAdapter(
DeployedStrategy.class);
// make a copy so cancel works as expected
mNewStrategy = (DeployedStrategy) EcoreUtil.copy(mOriginalStrategy);
Composite composite = new Composite(parent, SWT.NONE);
GridLayoutFactory.fillDefaults().applyTo(composite);
StrategyEngineUI.createDeployedStrategyConfigurationComposite(
composite, getDataBindingContext(), mNewStrategy);
addSeparator(composite);
addParametersSection(composite);
if (mOriginalStrategy.getState().equals(StrategyState.RUNNING)) {
ControlEnableState.disable(composite);
}
return composite;
}
private EMap<String, String> getParameters() {
return mNewStrategy.getParameters();
}
private void addSeparator(Composite parent) {
Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
GridData gridData = new GridData();
gridData.horizontalAlignment = GridData.FILL;
gridData.grabExcessHorizontalSpace = true;
separator.setLayoutData(gridData);
}
private void addParametersSection(Composite parent) {
Font font = parent.getFont();
Composite composite = new Composite(parent, SWT.NONE);
GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);
GridLayoutFactory.swtDefaults().applyTo(composite);
Label label = new Label(composite, SWT.NONE);
label.setFont(font);
label
.setText(Messages.STRATEGY_PROPERTY_PAGE_PARAMETERS_DESCRIPTION__LABEL
.getText());
GridDataFactory.defaultsFor(label).applyTo(label);
// Nest the property sheet page used by the Properties view.
mPage = new PropertySheetPage();
mPage.setPropertySourceProvider(new IPropertySourceProvider() {
@Override
public IPropertySource getPropertySource(Object object) {
if (object instanceof IPropertySource)
return (IPropertySource) object;
return null;
}
});
mPage.createControl(composite);
GridDataFactory.fillDefaults().grab(true, true).applyTo(
mPage.getControl());
// Simulate selection of a root element
mPage.selectionChanged(null, new StructuredSelection(
new StrategyPropertySource(getParameters()))); //$NON-NLS-1$
initPopupMenu();
}
private void initPopupMenu() {
MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
@Override
public void menuAboutToShow(IMenuManager manager) {
final TreeItem[] selection = ((Tree) mPage.getControl())
.getSelection();
// Add
manager.add(new Action(
Messages.STRATEGY_PROPERTY_PAGE_ADD_MENU_ITEM__TEXT
.getText()) {
@Override
public void run() {
addNewProperty();
}
});
// Delete
if (selection.length >= 1) {
manager
.add(new Action(
Messages.STRATEGY_PROPERTY_PAGE_DELETE_MENU_ITEM__TEXT
.getText()) {
@Override
public void run() {
for (int i = 0; i < selection.length; i++) {
final PropertySheetEntry entry = (PropertySheetEntry) selection[i]
.getData();
try {
Method method = PropertySheetEntry.class
.getDeclaredMethod("getDescriptor"); //$NON-NLS-1$
method.setAccessible(true);
IPropertyDescriptor descriptor = (IPropertyDescriptor) method
.invoke(entry);
getParameters().removeKey(
descriptor.getId());
} catch (Exception e) {
throw ExceptUtils.wrapRuntime(e);
}
}
mPage.refresh();
}
});
}
}
});
Menu menu = menuMgr.createContextMenu(mPage.getControl());
mPage.getControl().setMenu(menu);
}
@Override
protected void contributeButtons(Composite parent) {
// A button to add properties
Button addButton = new Button(parent, SWT.PUSH);
addButton.setText(Messages.STRATEGY_PROPERTY_PAGE_ADD_BUTTON__TEXT
.getText());
GridDataFactory.defaultsFor(addButton).applyTo(addButton);
addButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
addNewProperty();
}
});
((GridLayout) parent.getLayout()).numColumns++;
if (mOriginalStrategy.getState().equals(StrategyState.RUNNING)) {
addButton.setEnabled(false);
}
}
private void addNewProperty() {
NewPropertyInputDialog dialog = new NewPropertyInputDialog(
getShell());
if (dialog.open() == IDialogConstants.OK_ID) {
final String key = dialog.getPropertyKey();
if (!getParameters().containsKey(key))
getParameters().put(key, dialog.getPropertyValue());
mPage.refresh();
}
}
@Override
public boolean performOk() {
final StrategyEngine engine = mOriginalStrategy.getEngine();
final String name = engine.getName();
final StrategyEngineConnection connection = engine.getConnection();
IRunnableWithProgress operation = JFaceUtils.wrap(new Callable<Void>() {
@Override
public Void call() throws Exception {
connection.update(mOriginalStrategy, mNewStrategy);
return null;
}
}, Messages.STRATEGY_PROPERTY_PAGE_UPDATE__TASK_NAME.getText(name));
final ProgressMonitorDialog dialog = new ProgressMonitorDialog(
getShell());
final boolean success = JFaceUtils.runModalWithErrorDialog(dialog,
dialog, operation, false, new I18NBoundMessage1P(
Messages.STRATEGY_PROPERTY_PAGE_UPDATE_FAILED, name));
return success;
}
/**
* {@link IPropertySource} for adapting a DeployedStrategy parameters for
* the standard property sheet.
*/
@ClassVersion("$Id: DeployedStrategyConfigurationPropertyPage.java 16154 2012-07-14 16:34:05Z colin $")
private final static class StrategyPropertySource implements
IPropertySource {
private final EMap<String, String> mProperties;
/**
* Constructor.
*
* @param strategy
* the Strategy to adapt
*/
public StrategyPropertySource(EMap<String, String> properties) {
mProperties = properties;
}
@Override
public Object getEditableValue() {
return null;
}
@Override
public IPropertyDescriptor[] getPropertyDescriptors() {
List<IPropertyDescriptor> descriptors = new ArrayList<IPropertyDescriptor>();
for (Map.Entry<String, String> entry : mProperties) {
descriptors.add(new TextPropertyDescriptor(entry.getKey(),
entry.getKey()));
}
return (IPropertyDescriptor[]) descriptors
.toArray(new IPropertyDescriptor[descriptors.size()]);
}
@Override
public Object getPropertyValue(Object id) {
return mProperties.get(id);
}
@Override
public boolean isPropertySet(Object id) {
// no defaults
return false;
}
@Override
public void resetPropertyValue(Object id) {
// no defaults
}
@Override
public void setPropertyValue(Object id, Object value) {
mProperties.put((String) id, (String) value);
}
}
}