/*******************************************************************************
* Copyright (c) 2006-2013 The RCP Company and others.
* 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:
* The RCP Company - initial API and implementation
*******************************************************************************/
package com.rcpcompany.uibindings.navigator.internal.views;
import java.util.List;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.part.ISetSelectionTarget;
import org.eclipse.ui.part.ViewPart;
import com.rcpcompany.uibindings.IManager;
import com.rcpcompany.uibindings.model.utils.BasicUtils;
import com.rcpcompany.uibindings.navigator.IEditorPart;
import com.rcpcompany.uibindings.navigator.IEditorPartContext;
import com.rcpcompany.uibindings.navigator.IEditorPartDescriptor;
import com.rcpcompany.uibindings.navigator.IEditorPartFactory;
import com.rcpcompany.uibindings.navigator.IEditorPartView;
import com.rcpcompany.uibindings.navigator.INavigatorManager;
import com.rcpcompany.uibindings.navigator.internal.Activator;
import com.rcpcompany.uibindings.navigator.internal.NavigatorConstants;
import com.rcpcompany.uibindings.navigator.internal.handlers.SelectEditorPartMenuContributor;
import com.rcpcompany.uibindings.utils.IBindingObjectInformation;
import com.rcpcompany.uibindings.utils.IGlobalNavigationManager.IGetSelectionTarget;
import com.rcpcompany.utils.logging.LogUtils;
import com.rcpcompany.utils.selection.SelectionUtils;
/**
* The base view for editor parts.
*
* @author Tonny Madsen, The RCP Company
*/
public class BaseEditorView extends ViewPart implements ISetSelectionTarget, IGetSelectionTarget, IEditorPartView {
/**
* The parent Composite for the current editor part - if any
*/
/* package */Composite myParent;
/**
* The parent Composite from {@link IViewPart#createPartControl(Composite)}.
*/
/* package */Composite myViewPartParent;
/**
* Whether this editor is currently pinned.
* <p>
* If the editor is pinned, it will not react to selection changes and a new editor is created
* instead of reusing an existing editor.
*/
/* package */boolean myIsPinned = INavigatorManager.Factory.getManager().isPinEditorByDefault();
/**
* The current editor part descriptor.
*/
private/* package */IEditorPartDescriptor myCurrentDescriptor;
/**
* The current editor part for this editor.
*/
/* package */IEditorPart myCurrentEditorPart = null;
/**
* The current base observable value of the editor.
* <p>
* The type of the value is based on the model type of the current editor descriptor.
*/
/* package */IObservableValue myCurrentValue;
/**
* The factory context used in {@link IEditorPartFactory}.
*/
private final IEditorPartContext myFactoryContext = new IEditorPartContext() {
@Override
public IWorkbenchPart getWorkbenchPart() {
return BaseEditorView.this;
}
@Override
public Composite getParent() {
return myParent;
};
@Override
public IObservableValue getCurrentValue() {
return myCurrentValue;
}
@Override
public IEditorPartDescriptor getDescriptor() {
return getCurrentDescriptor();
}
};
/**
* Constructs and returns a editor container.
*/
public BaseEditorView() {
}
@Override
public void createPartControl(Composite parent) {
myViewPartParent = parent;
// final ISelectionService ss = getSite().getWorkbenchWindow().getSelectionService();
// ss.addPostSelectionListener(mySelectionListener);
// selectReveal(ss.getSelection());
}
@Override
public void dispose() {
cleanEditorPart();
// final ISelectionService ss = getSite().getWorkbenchWindow().getSelectionService();
// ss.removePostSelectionListener(mySelectionListener);
super.dispose();
}
@Override
public void activateView() {
getSite().getPage().activate(this);
}
@Override
public void setFocus() {
myViewPartParent.setFocus();
}
@Override
public void selectReveal(ISelection selection) {
if (Activator.getDefault().TRACE_EDITOR_PARTS_LIFECYCLE) {
LogUtils.debug(this, IBindingObjectInformation.Factory.getLongName(selection));
}
if (myCurrentEditorPart != null && isPinned()) return;
final List<EObject> list = SelectionUtils.computeSelection(selection, EObject.class);
if (list.isEmpty()) return;
setCurrentObject(list.get(0));
}
@Override
public ISelection getCurrentSelection() {
if (myCurrentValue == null) return StructuredSelection.EMPTY;
return new StructuredSelection(myCurrentValue.getValue());
}
@Override
public EObject getCurrentObject() {
if (myCurrentValue != null) return (EObject) myCurrentValue.getValue();
return null;
}
/**
* Updates the editor when the current object changes
*
* @param obj the new current object of the editor
*/
@Override
public void setCurrentObject(final EObject obj) {
final IEditorPartDescriptor desc = INavigatorManager.Factory.getManager().getEditorPartDescriptor(obj);
if (Activator.getDefault().TRACE_EDITOR_PARTS_LIFECYCLE) {
LogUtils.debug(this, "Descriptor found: " + obj + "\n-> " + desc);
}
/*
* Iff we have the same descriptor and the current editor can accept changes in the object,
* then just change the object without re-creating the editor part... Otherwise go the long
* route and first dispose and then re-create the editor part.
*/
if (desc == myCurrentDescriptor
&& ((myCurrentEditorPart != null && myCurrentEditorPart.canAcceptObjectChanges()) || (myCurrentValue != null && BasicUtils
.equals(obj, myCurrentValue.getValue())))) {
/*
* The editor part itself did not change... just update the observable value.
*/
if (myCurrentValue != null) {
if (Activator.getDefault().TRACE_EDITOR_PARTS_LIFECYCLE) {
LogUtils.debug(this, "Editor part value changed to " + obj);
}
BusyIndicator.showWhile(myParent.getDisplay(), new Runnable() {
public void run() {
myCurrentValue.setValue(obj);
}
});
final IBindingObjectInformation info = IBindingObjectInformation.Factory.createObjectInformation(
(EObject) myCurrentValue.getValue(), null);
setPartName(info.getName() + ": " + getCurrentDescriptor().getName());
}
return;
}
/*
* No new descriptor....
*/
if (desc == null) return;
if (Activator.getDefault().TRACE_EDITOR_PARTS_LIFECYCLE) {
LogUtils.debug(this, "Editor part description\n" + myCurrentDescriptor + "\n-> " + desc);
}
cleanEditorPart();
/*
* - create the observable value for the editor part based on the type of the editor
* descriptor
*/
myCurrentValue = new WritableValue(obj, obj.eClass());
IManager.Factory.getManager().startMonitorObservableDispose(myCurrentValue, this);
setCurrentDescriptor(desc);
/*
* - create the editor part itself
*
* If it fails, the clean up again...
*/
final IEditorPartFactory factory = desc.getFactory().getObject();
try {
if (factory != null) {
myParent = new Composite(myViewPartParent, SWT.NONE);
myParent.setLayout(new FillLayout());
try {
BusyIndicator.showWhile(myParent.getDisplay(), new Runnable() {
public void run() {
myCurrentEditorPart = factory.createEditorPart(myFactoryContext);
}
});
} catch (final Exception ex) {
LogUtils.error(factory, "Error detected during editor creation", ex);
}
myViewPartParent.layout(true);
}
if (getCurrentDescriptor() == null) {
LogUtils.error(factory, "Editor Part Factory returned null");
}
} catch (final Exception ex) {
LogUtils.error(factory, ex);
}
if (myCurrentEditorPart == null) {
if (Activator.getDefault().TRACE_EDITOR_PARTS_LIFECYCLE) {
LogUtils.debug(this, "Failed");
}
cleanEditorPart();
setPartName("");
setTitleImage(null);
return;
}
/*
* - Update the view part info
*/
final IBindingObjectInformation info = IBindingObjectInformation.Factory.createObjectInformation(
(EObject) myCurrentValue.getValue(), null);
setPartName(info.getName() + ": " + getCurrentDescriptor().getName());
Image image = null;
if (image == null && getCurrentDescriptor().getImage() != null) {
getCurrentDescriptor().getImage().getImage();
}
if (image == null) {
image = info.getImage();
}
setTitleImage(image);
}
/**
*
*/
private void cleanEditorPart() {
/*
* - Clean up after the previous editor part
*/
if (myCurrentEditorPart != null) {
myCurrentEditorPart.dispose();
if (!myViewPartParent.isDisposed()) {
for (final Control c : myViewPartParent.getChildren()) {
c.dispose();
}
}
}
if (myCurrentValue != null && !myCurrentValue.isDisposed()) {
IManager.Factory.getManager().stopMonitorObservableDispose(myCurrentValue);
myCurrentValue.dispose();
}
myCurrentValue = null;
myCurrentEditorPart = null;
setCurrentDescriptor(null);
}
@Override
public void setPinned(boolean pinned) {
myIsPinned = pinned;
}
@Override
public boolean isPinned() {
return myIsPinned;
}
/**
* Sets the current descriptor.
*
* @param desciptor the current descriptor to set
*/
public void setCurrentDescriptor(IEditorPartDescriptor desciptor) {
myCurrentDescriptor = desciptor;
/*
* Make all select editor parts update themselves...
*/
final ICommandService commandService = (ICommandService) getSite().getService(ICommandService.class);
commandService.refreshElements(NavigatorConstants.SELECT_EDITOR_PART_COMMAND, null);
}
/**
* Returns the current descriptor.
*
* @return the current descriptor
*/
@Override
public IEditorPartDescriptor getCurrentDescriptor() {
return myCurrentDescriptor;
}
/**
* Selection lister that simply updated the current selection of the editor.
*/
private final ISelectionListener mySelectionListener = new ISelectionListener() {
@Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
/*
* The changes that results from this part is ignoreed.
*/
if (part == BaseEditorView.this) return;
selectReveal(selection);
}
};
private SelectEditorPartMenuContributor mySelectEditorPartFactoryItem;
}