blob: 63753adcab790ef0268d63ad47a1dd1dd6449e18 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 Zoltan Ujhelyi and Daniel Varro.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Zoltan Ujhelyi - initial API and implementation
*******************************************************************************/
package org.eclipse.viatra2.visualisation.patterns;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.Machine;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.GTPattern;
import org.eclipse.viatra2.visualisation.IVisualisationDescriptor;
import org.eclipse.viatra2.visualisation.ViatraColoredLabelProvider;
import org.eclipse.viatra2.visualisation.ViatraGraphViewer;
import org.eclipse.viatra2.visualisation.VisualisationPlugin;
import org.eclipse.viatra2.visualisation.common.extensions.FilterConfiguration;
import org.eclipse.viatra2.visualisation.common.extensions.NamedElement;
import org.eclipse.viatra2.visualisation.common.extensions.VisualisationPreset;
import org.eclipse.viatra2.visualisation.layouts.IViatraLayoutAlgorithm;
import org.eclipse.viatra2.visualisation.patterns.actions.PatternProviderGroup;
import org.eclipse.viatra2.visualisation.patterns.sources.PatternContentProvider;
import org.eclipse.viatra2.visualisation.patterns.sources.PatternLabelProvider;
import org.eclipse.viatra2.visualisation.view.ViatraVisualisationView;
import org.eclipse.zest.core.widgets.ZestStyles;
import org.eclipse.zest.layouts.LayoutAlgorithm;
import org.eclipse.zest.layouts.LayoutStyles;
import org.eclipse.zest.layouts.algorithms.CompositeLayoutAlgorithm;
import org.eclipse.zest.layouts.algorithms.GridLayoutAlgorithm;
import org.eclipse.zest.layouts.algorithms.HorizontalShift;
/**
* <p>
* Describes a pattern graph visualisation task. The data model of the
* visualisation is a {@link Machine}, and basically its patterns are displayed
* as graphs.
* </p>
* <p>
* The descriptor allows the storage of several different views of a single
* machine in a path (stored as a stack), and allows basic back-navigation using
* it.
* </p>
* @author Zoltan Ujhelyi
*/
public class PatternGraphDescriptor implements IVisualisationDescriptor,
ITabbedPropertySheetPageContributor {
PatternGraphViewer gv;
PatternProviderGroup providers = new PatternProviderGroup();
PatternContentProvider contentProvider = providers.getDefaultProvider();
PatternLabelProvider labelProvider = new PatternLabelProvider();
Machine machine;
String machineName;
Hashtable<String, GTPattern> patternStorage;
Combo list;
LayoutAlgorithm layout;
ArrayList<LocationElement> locationStack = new ArrayList<LocationElement>();
int locationID = 0;
// Actions
Action previousViewerAction = new Action() {
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.action.Action#run()
*/
@Override
public void run() {
if (locationID > 0) popItem();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.action.Action#isEnabled()
*/
@Override
public boolean isEnabled() {
return locationID > 1;
}
};
private List<ViewerFilter> filters = new ArrayList<ViewerFilter>();
/**
* Initializes the pattern graph descriptor.
*/
public PatternGraphDescriptor() {
previousViewerAction.setText("Back");
previousViewerAction.setToolTipText("Displays the previous view");
previousViewerAction.setImageDescriptor(VisualisationPlugin
.imageDescriptorFromPlugin(VisualisationPlugin.PLUGIN_ID,
"icons/nav_backward.gif"));
previousViewerAction.setEnabled(false);
}
/**
* Sets the machine connected to the descriptor. The machine contains a list
* of all elements to visualise.
* @param machine
* the {@link Machine} machine to set
*/
public void setMachine(Machine machine) {
this.machine = machine;
patternStorage = new Hashtable<String, GTPattern>();
for (GTPattern pattern : machine.getGtPatternDefinitions()) {
patternStorage.put(pattern.getName(), pattern);
}
machineName = machine.getName();
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.viatra2.visualisation.IVisualisationDescriptor#
* addMenuContributions(org.eclipse.jface.action.IMenuManager)
*/
public void addMenuContributions(IMenuManager manager) {
providers.fillContextMenu(manager);
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.viatra2.visualisation.IVisualisationDescriptor#
* addToolbarContributions(org.eclipse.jface.action.IToolBarManager)
*/
public void addToolbarContributions(IToolBarManager manager) {
manager.add(previousViewerAction);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.viatra2.visualisation.IVisualisationDescriptor#clearGraphModel
* ()
*/
public void clearGraphModel() {
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.viatra2.visualisation.IVisualisationDescriptor#getAdapter
* (java.lang.Class)
*/
public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
if (adapter == IPropertySheetPage.class)
return new TabbedPropertySheetPage(this);
return null;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.viatra2.visualisation.IVisualisationDescriptor#getViewer()
*/
public ViatraGraphViewer getViewer() {
return gv;
}
private ViatraGraphViewer initializeViewer(Composite parent) {
gv = new PatternGraphViewer(parent, SWT.NONE);
GridLayoutAlgorithm gridLayout = new GridLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING
| LayoutStyles.ENFORCE_BOUNDS);
layout = new CompositeLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING,
new LayoutAlgorithm[] {
new GridLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING),
new HorizontalShift(
LayoutStyles.NO_LAYOUT_NODE_RESIZING) });
gv.setCompoundLayout(layout);
gv.setLayoutAlgorithm(gridLayout);
gv.setContentProvider(contentProvider);
gv.setLabelProvider(labelProvider);
gv.setNodeStyle(ZestStyles.NODES_NO_LAYOUT_RESIZE);
gv.setDescriptor(this);
//TODO this is needed for findGraphNode to work in doubleclicklistener
gv.setUseHashlookup(false);
pushItem(machine);
return gv;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.viatra2.visualisation.IVisualisationDescriptor#removeSelection
* ()
*/
public void removeSelection() {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.services.IDisposable#dispose()
*/
public void dispose() {
}
/**
* Explicitly sets the previousViewerAction item's enabled property. This
* call is required (it is not enough to rely on the isEnabled() method of
* the Action).
*/
private void setViewerActionEnabled() {
if (locationStack.size() > 1) {
previousViewerAction.setEnabled(true);
} else {
previousViewerAction.setEnabled(false);
}
}
/**
* Increases the location stack of the descriptor by adding a new item to it
* and updates the graph viewer to represent this new location. The new item
* can be an item already present in the stack.
* @param location
* the new location item
*/
public void pushItem(Object location) {
if (locationStack.isEmpty()
|| !locationStack.get(locationID - 1).getInputElement().equals(
location)) {
LocationElement element = new LocationElement();
element.setInputElement(location);
locationStack.add(locationID, element);
locationID++;
}
gv.setInput(location);
gv.refresh();
if (location instanceof Machine) {
list.setText(((Machine) location).getName());
} else if (location instanceof GTPattern) {
list.setText(((GTPattern) location).getName());
}
setViewerActionEnabled();
}
/**
* Selects the top location from the location stack and removes it. It also
* updates the graph viewer to represent the selected location.
*/
public void popItem() {
locationID--;
LocationElement element = locationStack.get(locationID);
Object location = element.getInputElement();
locationStack.remove(locationID);
gv.setInput(location);
gv.refresh();
if (location instanceof Machine) {
list.setText(((Machine) location).getName());
} else if (location instanceof GTPattern) {
list.setText(((GTPattern) location).getName());
}
setViewerActionEnabled();
}
public String getContributorId() {
return ViatraVisualisationView.viewId;
}
public void createFormContributions(Composite parent) {
FormToolkit toolkit = new FormToolkit(parent.getDisplay());
ScrolledForm form = toolkit.createScrolledForm(parent);
createHeaderRegion(form, toolkit);
FillLayout layout = new FillLayout();
layout.marginHeight = 10;
layout.marginWidth = 4;
form.getBody().setLayout(layout);
Section section = toolkit.createSection(form.getBody(),
Section.NO_TITLE);
initializeViewer(section);
section.setClient(gv.getGraphControl());
}
private void createHeaderRegion(ScrolledForm form, FormToolkit toolkit) {
form.setText(machineName);
Composite header = new Composite(form.getForm().getHead(), SWT.NONE);
GridLayout glayout = new GridLayout();
glayout.marginWidth = glayout.marginHeight = 0;
glayout.numColumns = 2;
header.setLayout(glayout);
header.setBackgroundMode(SWT.INHERIT_DEFAULT);
form.setHeadClient(header);
Label label = new Label(header, SWT.NONE);
label.setText("Element to visualise");
list = new Combo(header, SWT.DROP_DOWN | SWT.READ_ONLY);
toolkit.adapt(list);
list.add(machineName);
for (GTPattern pattern : patternStorage.values()) {
list.add(pattern.getName());
}
list.setText(machineName);
list.addSelectionListener(new SelectionAdapter() {
/*
* (non-Javadoc)
*
* @see
* org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse
* .swt.events.SelectionEvent)
*/
@Override
public void widgetSelected(SelectionEvent e) {
String text = list.getText();
if (text == null) return;
if (text.equals(machineName)) {
if (!gv.getInput().equals(machine)) {
pushItem(machine);
}
return;
}
if (patternStorage.containsKey(text)) {
GTPattern pattern = patternStorage.get(text);
if (!gv.getInput().equals(pattern)) {
pushItem(pattern);
}
return;
}
}
});
GridData data = new GridData();
data.widthHint = 200;
list.setLayoutData(data);
toolkit.adapt(header);
toolkit.decorateFormHeading(form.getForm());
}
public void setLayoutAlgorithm(IViatraLayoutAlgorithm algorithm) {
for (ViewerFilter filter : filters) {
gv.removeFilter(filter);
}
gv.setCompoundLayout(algorithm.getAlgorithm());
// filters = algorithm.getFilters();
for (ViewerFilter filter : filters) {
gv.addFilter(filter);
}
gv.applyLayout();
}
public void setVisualisationPreset(VisualisationPreset vp) {
for (ViewerFilter filter : filters) {
gv.removeFilter(filter);
}
gv.setCompoundLayout(vp.layout.element.getAlgorithm());
filters.clear();
for (NamedElement<ViewerFilter> _filter : vp.filters.filters) {
gv.addFilter(_filter.element);
filters.add(_filter.element);
}
// gv.setLabelProvider(vp.labelprovider.element);
gv.applyLayout();
gv.refresh();
}
public void setLabelProvider(ViatraColoredLabelProvider provider) {
setLabelProvider(provider, true);
}
public void setLabelProvider(ViatraColoredLabelProvider provider, boolean doRefresh) {
// FIXME Istvan: ignore this call for now,
// in order to avoid using incompatible label providers for pattern graph visualization
//gv.setLabelProvider(provider);
//gv.refresh();
}
public void setFilterConfiguration(FilterConfiguration fc) {
setFilterConfiguration(fc, true);
}
public void setFilterConfiguration(FilterConfiguration fc, boolean doRefresh) {
for (ViewerFilter filter : filters) {
gv.removeFilter(filter);
}
filters.clear();
for (NamedElement<ViewerFilter> _filter : fc.filters) {
gv.addFilter(_filter.element);
filters.add(_filter.element);
}
gv.refresh();
}
@Override
public void refreshGraph() {
gv.refresh();
}
@Override
public void redrawGraph() {
gv.applyLayout();
}
}