package org.nightlabs.jfire.scripting.ui.condition; import java.util.Collection; import java.util.HashMap; import java.util.Map; import org.apache.log4j.Logger; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; 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.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Sash; import org.eclipse.swt.widgets.Text; import org.nightlabs.base.ui.composite.AbstractListComposite; import org.nightlabs.base.ui.composite.XComboComposite; import org.nightlabs.base.ui.composite.XComposite; import org.nightlabs.jfire.scripting.ScriptExecutorJavaScript; import org.nightlabs.jfire.scripting.condition.CombineOperator; import org.nightlabs.jfire.scripting.condition.ConditionContainer; import org.nightlabs.jfire.scripting.condition.GeneratorRegistry; import org.nightlabs.jfire.scripting.condition.ICondition; import org.nightlabs.jfire.scripting.condition.IConditionContainer; import org.nightlabs.jfire.scripting.condition.IConditionGenerator; import org.nightlabs.jfire.scripting.condition.ISimpleCondition; import org.nightlabs.jfire.scripting.condition.Script; import org.nightlabs.jfire.scripting.condition.ScriptConditioner; import org.nightlabs.jfire.scripting.condition.SimpleCondition; import org.nightlabs.jfire.scripting.id.ScriptRegistryItemID; import org.nightlabs.jfire.scripting.ui.resource.Messages; import org.nightlabs.util.CollectionUtil; /** * @author Daniel.Mazurek [at] NightLabs [dot] de * */ public class SimpleScriptEditorComposite extends XComposite { private static final Logger logger = Logger.getLogger(SimpleScriptEditorComposite.class); public SimpleScriptEditorComposite(Collection<ScriptConditioner> scriptConditioners, Composite parent, int style) { super(parent, style); this.scriptConditioners = scriptConditioners; createComposite(this); } public SimpleScriptEditorComposite(Collection<ScriptConditioner> scriptConditioners, Composite parent, int style, LayoutMode layoutMode, LayoutDataMode layoutDataMode) { super(parent, style, layoutMode, layoutDataMode); this.scriptConditioners = scriptConditioners; createComposite(this); } private Collection<ScriptConditioner> scriptConditioners; private Composite conditionArea; private TreeViewer treeViewer; private Text text; private Composite parent; private CombineOperator currentCombineOperator = CombineOperator.LOGICAL_AND; private IConditionContainer rootContainer; private Map<Button, ICondition> button2Condition = new HashMap<Button, ICondition>(); // private Map<ICondition, IConditionContainer> condition2Container = new HashMap<ICondition, IConditionContainer>(); private Map<SimpleConditionComposite, ISimpleCondition> conditionComp2SimpleCondition = new HashMap<SimpleConditionComposite, ISimpleCondition>(); private ICondition condition = null; public ICondition getCondition() { return condition; } // private void createComposite(Composite parent) // { // this.parent = parent; // Composite comp = new XComposite(parent, SWT.BORDER); // comp.setLayout(new GridLayout(2, false)); // GridData compData = new GridData(GridData.FILL_BOTH); // compData.minimumHeight = 150; // compData.minimumWidth = 300; // comp.setLayoutData(compData); // // treeViewer = new TreeViewer(comp, SWT.SINGLE | SWT.FULL_SELECTION); // treeViewer.setContentProvider(new ConditionContentProvider()); // treeViewer.setLabelProvider(new ConditionLabelProvider()); // treeViewer.addSelectionChangedListener(treeSelectionListener); // treeViewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH)); // text = new Text(comp, SWT.BORDER); // text.setEnabled(false); // text.setLayoutData(new GridData(GridData.FILL_BOTH)); // // conditionArea = new XComposite(parent, SWT.BORDER); // setCondition(createSimpleCondition()); // } private void createComposite(Composite parent) { initScriptConditioner(); this.parent = parent; final Composite comp = new XComposite(parent, SWT.BORDER); comp.setLayout(new GridLayout(3, false)); GridData compData = new GridData(GridData.FILL_BOTH); compData.minimumHeight = 100; compData.minimumWidth = 200; comp.setLayoutData (compData); final Sash sash = new Sash(comp, SWT.VERTICAL); final FormLayout form = new FormLayout (); comp.setLayout(form); FormData treeData = new FormData (); treeData.left = new FormAttachment (0, 0); treeData.right = new FormAttachment (sash, 0); treeData.top = new FormAttachment (0, 0); treeData.bottom = new FormAttachment (100, 0); treeViewer = new TreeViewer(comp, SWT.SINGLE | SWT.FULL_SELECTION); treeViewer.setContentProvider(new ConditionContentProvider()); treeViewer.setLabelProvider(new ConditionLabelProvider()); treeViewer.addSelectionChangedListener(treeSelectionListener); treeViewer.getControl().setLayoutData(treeData); final int limit = 20, percent = 50; final FormData sashData = new FormData (); sashData.left = new FormAttachment (percent, 0); sashData.top = new FormAttachment (0, 0); sashData.bottom = new FormAttachment (100, 0); sash.setLayoutData (sashData); sash.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { Rectangle sashRect = sash.getBounds(); Rectangle compRect = comp.getClientArea(); int right = compRect.width - sashRect.width - limit; e.x = Math.max (Math.min (e.x, right), limit); if (e.x != sashRect.x) { sashData.left = new FormAttachment(0, e.x); comp.layout(); } } }); text = new Text(comp, SWT.BORDER | SWT.WRAP); text.setEnabled(false); FormData textData = new FormData (); textData.left = new FormAttachment (sash, 0); textData.right = new FormAttachment (100, 0); textData.top = new FormAttachment (0, 0); textData.bottom = new FormAttachment (100, 0); text.setLayoutData(textData); setCondition(createSimpleCondition()); } private ISimpleCondition createSimpleCondition() { ScriptConditioner sc = scriptConditioners.iterator().next(); ISimpleCondition condition = new SimpleCondition(sc.getScriptRegistryItemID(), sc.getCompareOperators().get(0), sc.getPossibleValues().iterator().next()); return condition; } private IConditionContainer createConditionContainer() { IConditionContainer container = new ConditionContainer(); container.addCondition(createSimpleCondition()); container.addCondition(createSimpleCondition()); container.setCombineOperator(currentCombineOperator); return container; } public void setCondition(ICondition condition) { if (condition != null) { this.condition = condition; treeViewer.setInput(CollectionUtil.createArrayList(condition)); clearMaps(); conditionSelected(condition); treeViewer.collapseAll(); } } private void clearMaps() { button2Condition.clear(); combineCombo2Container.clear(); // condition2Container.clear(); conditionComp2SimpleCondition.clear(); } private ISelectionChangedListener treeSelectionListener = new ISelectionChangedListener(){ public void selectionChanged(SelectionChangedEvent event) { StructuredSelection selection = (StructuredSelection) event.getSelection(); ICondition condition = (ICondition) selection.getFirstElement(); if (condition != null) { conditionSelected(condition); // setCondition(condition); } } }; private void conditionSelected(ICondition condition) { if (conditionArea != null) conditionArea.dispose(); conditionArea = new XComposite(parent, SWT.BORDER); GridData data = new GridData(GridData.FILL_BOTH); data.minimumHeight = 150; conditionArea.setLayoutData(data); createContainerComp(conditionArea, condition); setScriptText(condition); parent.layout(true, true); } // private ScrolledComposite sc; // private void conditionSelected(ICondition condition) // { // if (sc != null) // sc.dispose(); // conditionArea.dispose(); // sc = new ScrolledComposite(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); // sc.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); // conditionArea = new XComposite(sc, SWT.NONE, LayoutMode.TIGHT_WRAPPER); // // conditionArea.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); // createContainerComp(conditionArea, condition); // sc.setContent(conditionArea); // sc.setExpandHorizontal(true); // sc.setExpandVertical(true); // // setScriptText(condition); // parent.layout(true, true); // } private void createSimpleConditionComp(Composite parent, ISimpleCondition condition, IConditionContainer container) { parent.setLayout(new GridLayout(3, false)); SimpleConditionComposite simpleComp = new SimpleConditionComposite(scriptConditioners, parent, SWT.NONE); simpleComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); simpleComp.setSimpleCondition(condition); simpleComp.addConditionChangedListener(conditionChangeListener); Button addButton = new Button(parent, SWT.NONE); addButton.setText(Messages.getString("org.nightlabs.jfire.scripting.ui.condition.SimpleScriptEditorComposite.addButton.text")); //$NON-NLS-1$ Button deleteButton = new Button(parent, SWT.NONE); deleteButton.setText(Messages.getString("org.nightlabs.jfire.scripting.ui.condition.SimpleScriptEditorComposite.deleteButton.text")); //$NON-NLS-1$ if (container == null) deleteButton.setEnabled(false); button2Condition.put(addButton, container); button2Condition.put(deleteButton, condition); conditionComp2SimpleCondition.put(simpleComp, condition); addButton.addSelectionListener(addSimpleConditionListener); deleteButton.addSelectionListener(deleteConditionListener); } private SelectionListener addSimpleConditionListener = new SelectionAdapter(){ @Override public void widgetSelected(SelectionEvent e) { Button b = (Button) e.getSource(); IConditionContainer container = (IConditionContainer) button2Condition.get(b); if (container != null) { container.addCondition(createSimpleCondition()); // condition = container; } else { ICondition oldRoot = condition; IConditionContainer newRoot = new ConditionContainer(); newRoot.addCondition(oldRoot); ISimpleCondition sc = createSimpleCondition(); newRoot.addCondition(sc); newRoot.setCombineOperator(currentCombineOperator); condition = newRoot; rootContainer = newRoot; } setCondition(condition); } }; private SelectionListener deleteConditionListener = new SelectionAdapter(){ @Override public void widgetSelected(SelectionEvent e) { Button b = (Button) e.getSource(); ICondition con = button2Condition.get(b); IConditionContainer container = con.getParent(); if (container != null) { if (container.getConditions().size() > 2) container.removeCondition(con); else { IConditionContainer parentContainer = container.getParent(); if (parentContainer != null) parentContainer.removeCondition(container); else { ICondition con1 = container.getConditions().get(0); ICondition con2 = container.getConditions().get(1); if (con1.equals(con)) condition = con2; if (con2.equals(con)) condition = con1; container.removeCondition(condition); } } } setCondition(condition); } }; private SelectionListener addContainerListener = new SelectionAdapter(){ @Override public void widgetSelected(SelectionEvent e) { Button b = (Button) e.getSource(); IConditionContainer parent = (IConditionContainer) button2Condition.get(b); IConditionContainer container = createConditionContainer(); parent.addCondition(container); setCondition(condition); } }; private SelectionListener deleteContainerListener = new SelectionAdapter(){ @Override public void widgetSelected(SelectionEvent e) { Button b = (Button) e.getSource(); IConditionContainer container = (IConditionContainer) button2Condition.get(b); IConditionContainer parent = container.getParent(); if (parent != null) parent.removeCondition(container); setCondition(condition); } }; private void createContainerComp(Composite parent, ICondition condition) { parent.setLayout(new GridLayout(1, true)); if (condition instanceof ISimpleCondition) { // createSimpleConditionComp(parent, (ISimpleCondition)condition, rootContainer); createSimpleConditionComp(parent, (ISimpleCondition)condition, condition.getParent()); } else if (condition instanceof IConditionContainer) { IConditionContainer container = (IConditionContainer) condition; Group conditionsGroup = new Group(parent, SWT.NONE); conditionsGroup.setText(Messages.getString("org.nightlabs.jfire.scripting.ui.condition.SimpleScriptEditorComposite.conditionsGroup.text")); //$NON-NLS-1$ conditionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); conditionsGroup.setLayout(new GridLayout()); for (ICondition con : container.getConditions()) { if (con instanceof ISimpleCondition) { Composite wrapperComp = new XComposite(conditionsGroup, SWT.NONE, LayoutMode.TIGHT_WRAPPER); // createSimpleConditionComp(wrapperComp, (ISimpleCondition)con, rootContainer); createSimpleConditionComp(wrapperComp, (ISimpleCondition)con, con.getParent()); } else if (con instanceof IConditionContainer){ XComposite containerComp = new XComposite(conditionsGroup, SWT.NONE); containerComp.setLayout(new GridLayout(3, false)); Label label = new Label(containerComp, SWT.NONE); label.setText(Messages.getString("org.nightlabs.jfire.scripting.ui.condition.SimpleScriptEditorComposite.containerCompLabel.text")); //$NON-NLS-1$ Label spacer = new Label(containerComp, SWT.NONE); spacer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); Button deleteContainer = new Button(containerComp, SWT.NONE); deleteContainer.setText(Messages.getString("org.nightlabs.jfire.scripting.ui.condition.SimpleScriptEditorComposite.deleteContainerButton.text")); //$NON-NLS-1$ deleteContainer.addSelectionListener(deleteContainerListener); button2Condition.put(deleteContainer, con); } } createContainerDetailComp(parent, container); } } private ILabelProvider combineOperatorLabelProvider = new LabelProvider() { @Override public String getText(Object element) { if (element instanceof CombineOperator) { CombineOperator combineOperator = (CombineOperator) element; switch (combineOperator) { case LOGICAL_AND: return Messages.getString("org.nightlabs.jfire.scripting.ui.condition.SimpleScriptEditorComposite.combineOperator.and"); //$NON-NLS-1$ case LOGICAL_OR: return Messages.getString("org.nightlabs.jfire.scripting.ui.condition.SimpleScriptEditorComposite.combineOperator.or"); //$NON-NLS-1$ } } return super.getText(element); } }; private Map<XComboComposite<CombineOperator>, IConditionContainer> combineCombo2Container = new HashMap<XComboComposite<CombineOperator>, IConditionContainer>(); private void createContainerDetailComp(Composite parent, IConditionContainer container) { Group containerComp = new Group(parent, SWT.NONE); containerComp.setText(Messages.getString("org.nightlabs.jfire.scripting.ui.condition.SimpleScriptEditorComposite.containerGroupCompLabel.text")); //$NON-NLS-1$ containerComp.setLayout(new GridLayout(5, false)); containerComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); XComboComposite<CombineOperator> combineOperatorCombo = new XComboComposite<CombineOperator>( containerComp, AbstractListComposite.getDefaultWidgetStyle(parent), (String) null, combineOperatorLabelProvider); combineOperatorCombo.setInput( CollectionUtil.enum2List(CombineOperator.LOGICAL_AND) ); combineOperatorCombo.selectElement(container.getCombineOperator()); combineCombo2Container.put(combineOperatorCombo, container); Label l = new Label(containerComp, SWT.NONE); l.setText(Messages.getString("org.nightlabs.jfire.scripting.ui.condition.SimpleScriptEditorComposite.combineOperatorLabel.text")); //$NON-NLS-1$ Label spacer = new Label(containerComp, SWT.NONE); spacer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); Button addContainerButton = new Button(containerComp, SWT.NONE); addContainerButton.setText(Messages.getString("org.nightlabs.jfire.scripting.ui.condition.SimpleScriptEditorComposite.accContainerButton.text")); //$NON-NLS-1$ Button deleteContainerButton = new Button(containerComp, SWT.NONE); deleteContainerButton.setText(Messages.getString("org.nightlabs.jfire.scripting.ui.condition.SimpleScriptEditorComposite.deleteContainerButton.text")); //$NON-NLS-1$ button2Condition.put(addContainerButton, condition); button2Condition.put(deleteContainerButton, condition); addContainerButton.addSelectionListener(addContainerListener); deleteContainerButton.addSelectionListener(deleteContainerListener); combineOperatorCombo.addSelectionListener(combineComboListener); } private SelectionListener combineComboListener = new SelectionAdapter(){ @Override public void widgetSelected(SelectionEvent e) { Control control = (Control) e.getSource(); XComboComposite<CombineOperator> combo = (XComboComposite<CombineOperator>) control.getParent(); IConditionContainer container = combineCombo2Container.get(combo); container.setCombineOperator(combo.getSelectedElement()); setScriptText(condition); } }; class ConditionContentProvider implements ITreeContentProvider { public Object[] getChildren(Object parentElement) { if (parentElement instanceof IConditionContainer) { return ((IConditionContainer)parentElement).getConditions().toArray(); } return new Object[] {}; } public Object getParent(Object element) { if (element instanceof ICondition) { ICondition condition = (ICondition) element; return condition.getParent(); } return null; } public boolean hasChildren(Object element) { if (element instanceof IConditionContainer) { return !((IConditionContainer)element).getConditions().isEmpty(); } return false; } public Object[] getElements(Object inputElement) { if (inputElement instanceof Collection) { return ((Collection<Object>) inputElement).toArray(); } return new Object[] {inputElement}; } public void dispose() { } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } } // class ConditionLabelProvider // extends LabelProvider // { // @Override // public String getText(Object element) // { // if (element instanceof ISimpleCondition) // return ScriptingPlugin.getResourceString("SimpleScriptEditorComposite.ConditionLabelProvider.condition"); // if (element instanceof IConditionContainer) // return ScriptingPlugin.getResourceString("SimpleScriptEditorComposite.ConditionLabelProvider.conditionContainer"); // // return super.getText(element); // } // } class ConditionLabelProvider extends LabelProvider { @Override public String getText(Object element) { if (element instanceof ISimpleCondition) { String label = Messages.getString("org.nightlabs.jfire.scripting.ui.condition.SimpleScriptEditorComposite.conditionNode.text"); //$NON-NLS-1$ return label; } if (element instanceof IConditionContainer) { return String.format(Messages.getString("org.nightlabs.jfire.scripting.ui.condition.SimpleScriptEditorComposite.conditionContainerNode.text"), //$NON-NLS-1$ ((IConditionContainer)element).getConditions().size()); } return super.getText(element); } } private ConditionChangeListener conditionChangeListener = new ConditionChangeListener() { public void conditonChanged(ConditionChangedEvent event) { ISimpleCondition newSimpleCondition = (ISimpleCondition) event.getCondition(); ISimpleCondition oldSimpleCondition = conditionComp2SimpleCondition.get(event.getConditionComposite()); ICondition oldCondition = condition; if (condition instanceof ISimpleCondition && rootContainer == null) { condition = newSimpleCondition; } else if (condition instanceof IConditionContainer) { boolean succesful = replaceCondition((IConditionContainer)condition, oldSimpleCondition, newSimpleCondition); if (!succesful) { logger.error("replacing of condition failed!"); //$NON-NLS-1$ } } treeViewer.setInput(CollectionUtil.createArrayList(condition)); setScriptText(condition); if (logger.isDebugEnabled()) { logger.debug("conditonChanged"); //$NON-NLS-1$ logger.debug("oldSimpleCondition = "+getGenerator().getScriptText(oldSimpleCondition)); //$NON-NLS-1$ logger.debug("newSimpleCondition = "+getGenerator().getScriptText(newSimpleCondition)); //$NON-NLS-1$ logger.debug("oldCondition = "+getGenerator().getScriptText(oldCondition)); //$NON-NLS-1$ logger.debug("newCondition = "+getGenerator().getScriptText(condition)); //$NON-NLS-1$ logger.debug(""); //$NON-NLS-1$ } } }; private boolean replaceCondition(IConditionContainer container, ISimpleCondition original, ISimpleCondition replace) { for (ICondition con : container.getConditions()) { if (con instanceof ISimpleCondition) { if (con.equals(original)) { container.getConditions().set(container.getConditions().indexOf(original), replace); return true; } } else if (con instanceof IConditionContainer) { replaceCondition((IConditionContainer)con, original, replace); } } return false; } private void setScriptText(ICondition condition) { String scriptText = getGenerator().getScriptText(condition); if (scriptText != null) text.setText(scriptText); } private IConditionGenerator generator; private IConditionGenerator getGenerator() { if (generator == null) { // generator = GeneratorRegistry.sharedInstance().getGenerator(getLanguage()); generator = GeneratorRegistry.sharedInstance().getGenerator( getLanguage(), scriptConditioners); } return generator; } private String language = ScriptExecutorJavaScript.LANGUAGE_JAVA_SCRIPT;; protected String getLanguage() { return language; } public Script getScript() { Map<String, ScriptRegistryItemID> imports = new HashMap<String, ScriptRegistryItemID>(); imports = getImports(condition, imports); Script script = new Script(getLanguage(), getGenerator().getScriptText(condition), imports); return script; } public void setScript(Script script) { if (script != null) { language = script.getLanguage(); String scriptText = script.getText(); ICondition condition = getGenerator().getCondition(scriptText, false); setCondition(condition); } } private Map<ScriptRegistryItemID, String> allImports = new HashMap<ScriptRegistryItemID, String>(); private void initScriptConditioner() { // TODO override variableNames for (ScriptConditioner scriptConditioner : scriptConditioners) { allImports.put(scriptConditioner.getScriptRegistryItemID(), scriptConditioner.getVariableName()); } } private Map<String, ScriptRegistryItemID> getImports(ICondition condition, Map<String, ScriptRegistryItemID> imports) { if (condition instanceof ISimpleCondition) { ISimpleCondition simpleCondition = (ISimpleCondition) condition; imports.put(allImports.get(simpleCondition.getScriptRegistryItemID()), simpleCondition.getScriptRegistryItemID()); } else if (condition instanceof IConditionContainer) { IConditionContainer container = (IConditionContainer) condition; for (ICondition con : container.getConditions()) { imports.putAll(getImports(con, imports)); } } return imports; } }