Skip to content

Commit

Permalink
Add bi-directional selection support for transitions - Task #1044
Browse files Browse the repository at this point in the history
- selecting a transition in the simulator highlights the corresponding
  transition in the diagram
- selecting a transition in the diagram selects the transition in the
  transition viewer
  • Loading branch information
pchrszon-dlr committed Aug 28, 2023
1 parent 8e2f270 commit 5b5974b
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
import org.eclipse.graphiti.tb.IToolBehaviorProvider;
import org.eclipse.graphiti.util.ColorConstant;
import org.eclipse.graphiti.util.IColorConstant;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.PlatformUI;

import de.dlr.sc.virsat.model.extension.statemachines.model.State;
import de.dlr.sc.virsat.model.extension.statemachines.model.Transition;
import de.dlr.sc.virsat.model.extension.statemachines.statespace.StateSpaceExplorer;
import de.dlr.sc.virsat.model.extension.statemachines.statespace.TraceState;
import de.dlr.sc.virsat.model.extension.statemachines.ui.diagram.features.StateMachineDoubleClickFeature;
import de.dlr.sc.virsat.model.extension.statemachines.ui.views.SimulatorView;
Expand All @@ -31,9 +33,10 @@
* Implements the tool behavior provider to catch double click events
*
*/
public class StateMachineDiagramToolBehaviorProvider extends DefaultToolBehaviorProvider implements IToolBehaviorProvider {
public class StateMachineDiagramToolBehaviorProvider extends DefaultToolBehaviorProvider implements IToolBehaviorProvider {

private static final IColorConstant SELECTED_STATE_BACKGROUND = new ColorConstant(255, 255, 255);
private static final IColorConstant SELECTED_TRANSITION_FOREGROUND = new ColorConstant(255, 128, 0);

/**
* @param diagramTypeProvider
Expand All @@ -59,19 +62,29 @@ public IDecorator[] getDecorators(PictogramElement pe) {
var selectionService = activeWorkbenchWindow.getSelectionService();
var selection = selectionService.getSelection(SimulatorView.ID);

if (selection != null && selection instanceof StructuredSelection) {
if (selection != null && selection instanceof IStructuredSelection) {
var featureProvider = getFeatureProvider();
var bo = featureProvider.getBusinessObjectForPictogramElement(pe);
var selectedElement = ((StructuredSelection) selection).getFirstElement();

if (bo instanceof State && selectedElement instanceof TraceState) {
var state = (State) bo;
var localStates = ((TraceState) selectedElement).getSystemState().getLocalStates();

if (localStates.contains(state)) {
var decorator = new ColorDecorator();
decorator.setBackgroundColor(SELECTED_STATE_BACKGROUND);
return new IDecorator[] { decorator };
for (var selectedElement : (IStructuredSelection) selection) {
if (selectedElement instanceof TraceState && bo instanceof State) {
var state = (State) bo;
var localStates = ((TraceState) selectedElement).getSystemState().getLocalStates();

if (localStates.contains(state)) {
var decorator = new ColorDecorator();
decorator.setBackgroundColor(SELECTED_STATE_BACKGROUND);
return new IDecorator[] { decorator };
}
} else if (selectedElement instanceof StateSpaceExplorer.SystemTransition && bo instanceof Transition) {
var transition = (Transition) bo;
var localTransitions = ((StateSpaceExplorer.SystemTransition) selectedElement).getLocalTransitions();

if (localTransitions.contains(transition)) {
var decorator = new ColorDecorator();
decorator.setForegroundColor(SELECTED_TRANSITION_FOREGROUND);
return new IDecorator[] { decorator };
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

import org.eclipse.graphiti.mm.pictograms.Diagram;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IPartListener;
Expand All @@ -22,6 +22,7 @@
import de.dlr.sc.virsat.graphiti.ui.diagram.editor.VirsatDiagramEditor;
import de.dlr.sc.virsat.graphiti.util.DiagramHelper;
import de.dlr.sc.virsat.model.dvlm.structural.StructuralElementInstance;
import de.dlr.sc.virsat.model.extension.statemachines.statespace.StateSpaceExplorer;
import de.dlr.sc.virsat.model.extension.statemachines.statespace.TraceState;
import de.dlr.sc.virsat.model.extension.statemachines.ui.views.SimulatorView;

Expand All @@ -41,12 +42,15 @@ public void init(IEditorSite site, IEditorInput input) throws PartInitException
selectionListener = new ISelectionListener() {
@Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
if (!(selection instanceof StructuredSelection)) {
if (!(selection instanceof IStructuredSelection)) {
return;
}

if (((StructuredSelection) selection).getFirstElement() instanceof TraceState) {
getDiagramTypeProvider().getDiagramBehavior().refresh();
for (var selectedElement : (IStructuredSelection) selection) {
if (selectedElement instanceof TraceState
|| selectedElement instanceof StateSpaceExplorer.SystemTransition) {
getDiagramTypeProvider().getDiagramBehavior().refresh();
}
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.jface.viewers.IDoubleClickListener;
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.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
Expand Down Expand Up @@ -78,10 +79,83 @@ public class SimulatorView extends ViewPart {
private List<StateMachine> input;
private StateSpaceExplorer explorer;

private ISelectionListener selectionListener;
private SelectionIntermediate selectionIntermediate;
private ISelectionListener stateMachineSelectionListener;
private ISelectionListener transitionSelectionListener;
private boolean isDisposed;


/**
* The SelectionIntermediate combines the selections of the simulator's viewers. It acts as the SelectionProvider for this view.
* @author chrs_ph
*/
private class SelectionIntermediate implements ISelectionProvider, ISelectionChangedListener {
private final List<ISelectionChangedListener> listeners;
private ISelection selection;

private TraceState selectedTraceState;
private StateSpaceExplorer.SystemTransition selectedTransition;

SelectionIntermediate() {
listeners = new ArrayList<>();
selection = StructuredSelection.EMPTY;
}

@Override
public void addSelectionChangedListener(ISelectionChangedListener listener) {
listeners.add(listener);
}

@Override
public ISelection getSelection() {
return selection;
}

@Override
public void removeSelectionChangedListener(ISelectionChangedListener listener) {
listeners.remove(listener);
}

@Override
public void setSelection(ISelection selection) {
this.selection = selection;
}

@Override
public void selectionChanged(SelectionChangedEvent event) {
if (event.getSelectionProvider() == traceViewer) {
selectedTraceState = (TraceState) event.getStructuredSelection().getFirstElement();
} else if (event.getSelectionProvider() == transitionViewer) {
selectedTransition = (StateSpaceExplorer.SystemTransition) event.getStructuredSelection().getFirstElement();
}

updateSelection();
notifyListeners();
}

private void notifyListeners() {
var event = new SelectionChangedEvent(this, selection);
listeners.stream().forEach(listener -> listener.selectionChanged(event));
}

/**
* Builds a new StructuredSelection combining the selections of the viewers.
*/
private void updateSelection() {
var selections = new ArrayList<Object>(2);

if (selectedTraceState != null) {
selections.add(selectedTraceState);
}

if (selectedTransition != null) {
selections.add(selectedTransition);
}

setSelection(new StructuredSelection(selections));
}
}

private class SystemStateColumnLabelProvider extends ColumnLabelProvider {
private StateMachine stateMachine;

Expand Down Expand Up @@ -119,7 +193,10 @@ public void createPartControl(final Composite parent) {
createActionBar();
addListeners();

getSite().setSelectionProvider(traceViewer);
selectionIntermediate = new SelectionIntermediate();
traceViewer.addSelectionChangedListener(selectionIntermediate);
transitionViewer.addSelectionChangedListener(selectionIntermediate);
getSite().setSelectionProvider(selectionIntermediate);
}

@Override
Expand All @@ -129,8 +206,13 @@ public void setFocus() {

@Override
public void dispose() {
if (isDisposed) {
return;
}

isDisposed = true;
getSite().getPage().removeSelectionListener(selectionListener);
getSite().getPage().removeSelectionListener(stateMachineSelectionListener);
getSite().getPage().removeSelectionListener(transitionSelectionListener);
super.dispose();
}

Expand All @@ -152,6 +234,7 @@ private Composite createViewers(Composite parent) {
private TableViewer createTraceViewer(Composite parent) {
var tableViewer = new TableViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
tableViewer.getTable().setHeaderVisible(true);
tableViewer.getTable().setLinesVisible(true);
tableViewer.setContentProvider(ArrayContentProvider.getInstance());
tableViewer.setInput(trace);

Expand All @@ -175,6 +258,7 @@ public String getText(Object element) {
private TableViewer createTransitionViewer(Composite parent) {
var tableViewer = new TableViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
tableViewer.getTable().setHeaderVisible(true);
tableViewer.getTable().setLinesVisible(true);
tableViewer.setContentProvider(ArrayContentProvider.getInstance());
tableViewer.setInput(transitions);

Expand Down Expand Up @@ -257,7 +341,7 @@ private void createActionBar() {
* Creates and adds all event listeners.
*/
private void addListeners() {
selectionListener = new ISelectionListener() {
stateMachineSelectionListener = new ISelectionListener() {
@Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
if (!(selection instanceof IStructuredSelection)) {
Expand Down Expand Up @@ -295,8 +379,30 @@ public void selectionChanged(IWorkbenchPart part, ISelection selection) {
}
}
};
getSite().getPage().addSelectionListener(selectionListener);
isDisposed = false;
getSite().getPage().addSelectionListener(stateMachineSelectionListener);

transitionSelectionListener = new ISelectionListener() {
@Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
if (!(selection instanceof IStructuredSelection)) {
return;
}

var selectedElement = ((IStructuredSelection) selection).getFirstElement();

if (selectedElement instanceof GraphitiShapeEditPart) {
var sep = (GraphitiShapeEditPart) selectedElement;
var bo = sep.getFeatureProvider().getBusinessObjectForPictogramElement(sep.getPictogramElement());
if (bo instanceof Transition) {
var localTransition = (Transition) bo;
transitions.stream().filter(t -> t.getLocalTransitions().contains(localTransition)).findFirst().ifPresent(t -> {
transitionViewer.setSelection(new StructuredSelection(t));
});
}
}
}
};
getSite().getPage().addSelectionListener(transitionSelectionListener);

traceViewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
Expand Down

0 comments on commit 5b5974b

Please sign in to comment.