package org.nightlabs.jfire.jbpm.ui.transition.next; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Locale; import javax.jdo.FetchPlan; import javax.jdo.JDOHelper; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; 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.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.nightlabs.base.ui.composite.XComboComposite; import org.nightlabs.base.ui.composite.XComposite; import org.nightlabs.base.ui.job.Job; import org.nightlabs.jdo.NLJDOHelper; import org.nightlabs.jfire.jbpm.dao.TransitionDAO; import org.nightlabs.jfire.jbpm.graph.def.Statable; import org.nightlabs.jfire.jbpm.graph.def.State; import org.nightlabs.jfire.jbpm.graph.def.StateDefinition; import org.nightlabs.jfire.jbpm.graph.def.Transition; import org.nightlabs.jfire.jbpm.graph.def.id.StateID; import org.nightlabs.jfire.jbpm.ui.JFireJbpmPlugin; import org.nightlabs.jfire.jbpm.ui.resource.Messages; import org.nightlabs.progress.ProgressMonitor; import org.nightlabs.progress.SubProgressMonitor; public class NextTransitionComposite extends XComposite implements ISelectionProvider { private XComboComposite<Transition> nextTransitionCombo; private static final Transition EMPTY_TRANSITION; static { // Create EMPTY transition for allowing the user to deselect a previous selection. @SuppressWarnings("deprecation") StateDefinition stateDefinition = new StateDefinition() { private static final long serialVersionUID = 1L; }; EMPTY_TRANSITION = new Transition(stateDefinition, "empty"); //$NON-NLS-1$ EMPTY_TRANSITION.getName().setText(Locale.ENGLISH, " "); //$NON-NLS-1$ } private Button signalButton; public NextTransitionComposite(Composite parent, int style) { this(parent, style, true); } public NextTransitionComposite(Composite parent, int style, boolean withSignalButton) { super(parent, style, LayoutMode.TIGHT_WRAPPER); getGridLayout().numColumns = 2; getGridData().grabExcessVerticalSpace = false; getGridData().verticalAlignment = SWT.BEGINNING; nextTransitionCombo = new XComboComposite<Transition>(this, SWT.DROP_DOWN | SWT.READ_ONLY, new LabelProvider() { @Override public String getText(Object element) { Transition transition = (Transition) element; return transition.getName().getText(); } }); nextTransitionCombo.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { updateUI(); fireSelectionChangedEvent(); } }); if (withSignalButton) { signalButton = new Button(this, SWT.PUSH); signalButton.setText(Messages.getString("org.nightlabs.jfire.jbpm.ui.transition.next.NextTransitionComposite.signalButton.text")); //$NON-NLS-1$ signalButton.setEnabled(false); signalButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { setEnabled(false); fireSignalEvent(); } }); } } private void updateUI() { if (signalButton != null) signalButton.setEnabled(getSelectedTransition() != null); } private Statable statable; public static final String[] FETCH_GROUPS_TRANSITION = { FetchPlan.DEFAULT, Transition.FETCH_GROUP_NAME }; public Statable getStatable() { return statable; } public void setStatable(final Statable _statable) { Job job = new Job(Messages.getString("org.nightlabs.jfire.jbpm.ui.transition.next.NextTransitionComposite.loadJob.name")) { //$NON-NLS-1$ @Override protected IStatus run(ProgressMonitor monitor) { setStatable(_statable, monitor); return Status.OK_STATUS; } }; job.setRule(JFireJbpmPlugin.stateCompositeSchedulingRule); job.schedule(); } public void setStatable(Statable _statable, ProgressMonitor monitor) { this.statable = _statable; final State state = statable.getStatableLocal().getState(); stateID = (StateID) JDOHelper.getObjectId(state); // fetch the possible further transitions for the current state and filter them with the ITransitionFilters final List<Transition> transitions = filterTransitions(state, new SubProgressMonitor(monitor, 1)); Collections.sort(transitions, new Comparator<Transition>() { @Override public int compare(Transition t1, Transition t2) { return t1.getName().getText().compareTo(t2.getName().getText()); } }); Runnable runnable = new Runnable() { @Override public void run() { if (nextTransitionCombo.isDisposed()) return; nextTransitionCombo.removeAll(); nextTransitionCombo.addElement(EMPTY_TRANSITION); nextTransitionCombo.addElements(transitions); nextTransitionCombo.setSelection(0); setEnabled(true); updateUI(); layout(true); } }; if (Display.getCurrent() == null) Display.getDefault().asyncExec(runnable); else runnable.run(); } private StateID stateID; public StateID getStateID() { return stateID; } private ListenerList signalListeners = new ListenerList(); public void addSignalListener(SignalListener listener) { signalListeners.add(listener); } public void removeSignalListener(SignalListener listener) { signalListeners.remove(listener); } public Transition getSelectedTransition() { if (nextTransitionCombo.getSelectedElement() == EMPTY_TRANSITION) return null; return nextTransitionCombo.getSelectedElement(); } private void fireSignalEvent() { Object[] listeners = signalListeners.getListeners(); if (listeners.length < 1) return; Transition transition = getSelectedTransition(); if (transition == null) return; SignalEvent event = new SignalEvent(this, stateID, getSelectedTransition()); for (Object listener : listeners) { SignalListener l = (SignalListener) listener; l.signal(event); } } private ListenerList transitionFilters = new ListenerList(); public void addTransitionFilter(ITransitionFilter transitionFilter) { transitionFilters.add(transitionFilter); } public void removeTransitionFilter(ITransitionFilter transitionFilter) { transitionFilters.remove(transitionFilter); } protected List<Transition> filterTransitions(State state, ProgressMonitor monitor) { // fetch the possible further transitions for the current state final List<Transition> transitions = new LinkedList<Transition>( TransitionDAO.sharedInstance().getTransitions( stateID, Boolean.TRUE, FETCH_GROUPS_TRANSITION, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, monitor)); Object[] listeners = transitionFilters.getListeners(); Iterator<Transition> transIt = transitions.iterator(); while(transIt.hasNext()) { Transition transition = transIt.next(); boolean doShow = true; for (Object transitionFilter : listeners) { if (!((ITransitionFilter) transitionFilter).acceptTransition(state, transition)) { doShow = false; break; } } if (!doShow) { transIt.remove(); } } return transitions; } private ListenerList selectionChangedListeners = new ListenerList(); private void fireSelectionChangedEvent() { if (selectionChangedListeners.isEmpty()) return; SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection()); for (Object l : selectionChangedListeners.getListeners()) { ISelectionChangedListener listener = (ISelectionChangedListener) l; listener.selectionChanged(event); } } @Override public void addSelectionChangedListener(ISelectionChangedListener listener) { selectionChangedListeners.add(listener); } @Override public ISelection getSelection() { Transition selectedTransition = getSelectedTransition(); if (selectedTransition == null) return new StructuredSelection(new Object[0]); return new StructuredSelection(selectedTransition); } @Override public void removeSelectionChangedListener(ISelectionChangedListener listener) { selectionChangedListeners.remove(listener); } @Override public void setSelection(ISelection selection) { if (!(selection instanceof IStructuredSelection)) throw new IllegalArgumentException("selection is not an instance of " + IStructuredSelection.class.getName() + " but " + (selection == null ? null : selection.getClass().getName())); //$NON-NLS-1$ //$NON-NLS-2$ IStructuredSelection sel = (IStructuredSelection) selection; Object selObj = sel.getFirstElement(); if (selObj instanceof Transition) nextTransitionCombo.setSelection((Transition) selObj); } }