/***********************************************************************
* Copyright (c) 2008, 2009 Anyware Technologies, Obeo, CEA LIST
*
* 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:
* Anyware Technologies - initial API and implementation
* Obeo
* CEA LIST - synchronization between selection and outline content
*
**********************************************************************/
package org.eclipse.papyrus.infra.gmfdiag.outline;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.RootEditPart;
import org.eclipse.gef.editparts.ScalableFreeformRootEditPart;
import org.eclipse.gmf.runtime.diagram.ui.render.editparts.RenderedDiagramRootEditPart;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.papyrus.infra.core.contentoutline.IPapyrusContentOutlinePage;
import org.eclipse.papyrus.infra.core.editor.BackboneException;
import org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.gmfdiag.outline.internal.Activator;
import org.eclipse.papyrus.infra.gmfdiag.outline.internal.Messages;
import org.eclipse.papyrus.infra.gmfdiag.outline.overview.OverviewComposite;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.part.Page;
import org.eclipse.ui.plugin.AbstractUIPlugin;
/**
* An outline in order to navigate in current diagram.
*
* @author David Sciamma
* @author Jacques Lescot
* @author Jerome Benois
* @author Yann Tanguy
*/
public class DiagramOutline extends Page implements IPapyrusContentOutlinePage, ISelectionListener {
protected EditingDomain editingDomain;
private IMultiDiagramEditor multiEditor;
private SashForm sashComp;
private DiagramNavigator navigator;
/** Current selection */
private RenderedDiagramRootEditPart root = null;
private Diagram diagram = null;
/** Outline mode */
public final static int SHOW_TREE = 1;
public final static int SHOW_OVERVIEW = 2;
public final static int SHOW_BOTH = 0;
private Composite overview;
/** Actions */
private IAction showTreeAction;
private IAction showOverviewAction;
private IAction showAllAction;
public DiagramOutline() {
super();
}
/**
* {@inheritDoc}
*/
public void init(IMultiDiagramEditor multiEditor) throws BackboneException {
// Get TransactionalEditingDomain
try {
this.editingDomain = multiEditor.getServicesRegistry().getService(TransactionalEditingDomain.class);
} catch (ServiceException e) {
throw new BackboneException("Can't get TransactionalEditingDomain", e);
}
// Set multieditor.
this.multiEditor = multiEditor;
// Add listener to detect selection change
multiEditor.getSite().getPage().addPostSelectionListener(this);
}
/**
* {@inheritDoc}
*/
@Override
public void createControl(Composite parent) {
// Create SashForm
sashComp = new SashForm(parent, SWT.VERTICAL);
sashComp.setLayoutData(new GridData(GridData.FILL_BOTH));
// Update selection (diagram and root edit part in active EditorTile)
refreshSelection();
// Create Overview
if(root != null) {
overview = createOverview(sashComp, root);
overview.setLayoutData(new GridData(GridData.FILL_BOTH));
}
// Create Navigator
navigator = createNavigator(sashComp, getSite());
if(diagram != null) {
navigator.getTreeViewer().setInput(diagram);
}
// Slip SashForm in two sections
if(overview != null) {
sashComp.setWeights(new int[]{ 30, 70 });
}
createActions();
}
/**
* Create the composite that shows an overview of the model
*
* @param parent
* the parent
* @param rootEditPart
* the root edit part
* @return the overview composite
*/
protected Composite createOverview(Composite parent, ScalableFreeformRootEditPart rootEditPart) {
return new OverviewComposite(parent, rootEditPart);
}
/**
* Add the actions to the view toolbar
*/
protected void createActions() {
IToolBarManager tbm = getSite().getActionBars().getToolBarManager();
tbm.add(new Separator());
createShowOutlineActions(tbm);
}
/**
* Create the show outline actions in the given tool bar manager.
*
* @param tbm
* the outline tool bar manager
*/
private void createShowOutlineActions(IToolBarManager tbm) {
// Show Tree action
showTreeAction = new Action(Messages.DiagramOutline_ShowNavigator, IAction.AS_RADIO_BUTTON) {
@Override
public void run() {
if(navigator != null && !navigator.isDisposed()) {
performShowAction();
}
}
};
showTreeAction.setToolTipText(showTreeAction.getText());
showTreeAction.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/elcl16/tree_co.gif")); //$NON-NLS-1$
tbm.add(showTreeAction);
// Show overview action
showOverviewAction = new Action(Messages.DiagramOutline_ShowOverview, IAction.AS_RADIO_BUTTON) {
@Override
public void run() {
if(overview != null && !overview.isDisposed()) {
performShowAction();
}
}
};
showOverviewAction.setToolTipText(showOverviewAction.getText());
showOverviewAction.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/elcl16/overview_co.gif")); //$NON-NLS-1$
tbm.add(showOverviewAction);
// Show All (Tree and Overview) action
showAllAction = new Action(Messages.DiagramOutline_ShowBoth, IAction.AS_RADIO_BUTTON) {
@Override
public void run() {
if(sashComp != null && !sashComp.isDisposed()) {
performShowAction();
}
}
};
showAllAction.setToolTipText(showAllAction.getText());
showAllAction.setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/elcl16/all_co.gif")); //$NON-NLS-1$
tbm.add(showAllAction);
// Set overview as default choice
showOverviewAction.setChecked(true);
performShowAction();
}
private DiagramNavigator createNavigator(Composite parent, IPageSite pageSite) {
return new DiagramNavigator(parent, pageSite);
}
@Override
public Control getControl() {
return sashComp;
}
@Override
public void setFocus() {
getControl().setFocus();
}
public void addSelectionChangedListener(ISelectionChangedListener listener) {
if(navigator != null && !navigator.isDisposed()) {
navigator.getTreeViewer().addSelectionChangedListener(listener);
}
}
public ISelection getSelection() {
return navigator.getTreeViewer().getSelection();
}
public void removeSelectionChangedListener(ISelectionChangedListener listener) {
if(navigator != null && !navigator.isDisposed()) {
navigator.getTreeViewer().removeSelectionChangedListener(listener);
}
}
public void setSelection(ISelection selection) {
navigator.getTreeViewer().setSelection(selection);
}
@Override
public void dispose() {
super.dispose();
// Navigator, overview... can be null
if(navigator != null) {
navigator.dispose();
}
if(overview != null) {
overview.dispose();
}
if(multiEditor != null) {
// Remove selection change listener
multiEditor.getSite().getPage().removePostSelectionListener(this);
}
}
/**
* {@inheritDoc}
*/
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
// Update selection (diagram and root edit part in active EditorTile)
refreshSelection();
// Refresh outline contents content with the new selection
refresh();
}
/**
* Refresh the selected root edit part and diagram
*/
private void refreshSelection() {
if(multiEditor.getActiveEditor() != null) {
GraphicalViewer viewer = (GraphicalViewer)multiEditor.getActiveEditor().getAdapter(GraphicalViewer.class);
if( viewer == null)
{ // In case of an editor that is not GEF based.
root = null;
diagram = null;
return;
}
RootEditPart rootEditPart = viewer.getRootEditPart();
if(rootEditPart instanceof RenderedDiagramRootEditPart) {
root = (RenderedDiagramRootEditPart)rootEditPart;
if(rootEditPart.getContents() != null) {
diagram = (Diagram)rootEditPart.getContents().getModel();
} else {
diagram = null;
}
} else {
root = null;
diagram = null;
}
} else {
root = null;
diagram = null;
}
}
/**
* Refresh the outline view
*/
private void refresh() {
// Trash and re-Create Overview
if((overview != null) && !(overview.isDisposed())) {
overview.dispose();
}
if(root != null) {
overview = createOverview(sashComp, root);
overview.setLayoutData(new GridData(GridData.FILL_BOTH));
}
// Update navigator content
if(diagram != null) {
navigator.getTreeViewer().setInput(diagram);
}
// Slip SashForm in two sections
if((overview != null) && !(overview.isDisposed())) {
sashComp.setWeights(new int[]{ 30, 70 });
}
// Refresh outline without changing mode
performShowAction();
}
/**
* Show outline in selected mode
*/
private void performShowAction() {
// Select the kind of outline to show content
Control control = null;
control = null;
switch(getShowActionMode()) {
case SHOW_TREE:
control = navigator;
break;
case SHOW_OVERVIEW:
control = overview;
break;
case SHOW_BOTH:
control = null;
break;
default:
control = overview;
}
// Update outline view
if(sashComp != null && !sashComp.isDisposed()) {
sashComp.setMaximizedControl(control);
}
}
/**
* Get current contents representation of the outline
*
* @return current Outline show mode
*/
private int getShowActionMode() {
int showActionMode = -1;
if(showTreeAction.isChecked()) {
showActionMode = SHOW_TREE;
}
if(showOverviewAction.isChecked()) {
showActionMode = SHOW_OVERVIEW;
}
if(showAllAction.isChecked()) {
showActionMode = SHOW_BOTH;
}
return showActionMode;
}
}