package net.enilink.komma.edit.ui.views;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.enilink.commons.ui.editor.EditorForm;
import net.enilink.commons.ui.editor.IEditorPart;
import net.enilink.komma.core.IValue;
import net.enilink.komma.edit.domain.IEditingDomainProvider;
import net.enilink.komma.edit.ui.util.PartListener2Adapter;
import net.enilink.komma.model.IModel;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.part.IContributedContentsView;
import org.eclipse.ui.part.ViewPart;
public class AbstractEditingDomainView extends ViewPart implements
IContributedContentsView {
private class Listener extends PartListener2Adapter implements
ISelectionListener {
@Override
public void partActivated(IWorkbenchPartReference partRef) {
IWorkbenchPart part = partRef.getPart(false);
if (AbstractEditingDomainView.this == part) {
if (!active) {
active = true;
if (setInputOnActivate) {
editorForm.setInput(null);
editPart.setInput(model);
editorForm.refreshStale();
setInputOnActivate = false;
}
if (selectionOnActivate != null) {
if (editorForm.setInput(selectionOnActivate)) {
editorForm.refreshStale();
}
selectionOnActivate = null;
}
}
} else if (part != null) {
setWorkbenchPart(part);
}
}
@Override
public void partVisible(IWorkbenchPartReference partRef) {
IWorkbenchPart part = partRef.getPart(false);
if (AbstractEditingDomainView.this == part && !active) {
partActivated(partRef);
}
}
@Override
public void partClosed(IWorkbenchPartReference partRef) {
if (part != null && part.equals(partRef.getPart(false))
&& !PlatformUI.getWorkbench().isClosing()) {
setWorkbenchPart(null);
}
}
@Override
public void partDeactivated(IWorkbenchPartReference partRef) {
}
@Override
public void partHidden(IWorkbenchPartReference partRef) {
IWorkbenchPart part = partRef.getPart(false);
if (AbstractEditingDomainView.this == part) {
active = false;
}
}
@Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
if (part != AbstractEditingDomainView.this
&& selection instanceof IStructuredSelection
&& !selection.equals(selectionProvider.getSelection())) {
Object selected = ((IStructuredSelection) selection)
.getFirstElement();
// allow arbitrary selections to be adapted to IValue objects
if (selected != null && !(selected instanceof IValue)) {
Object adapter = Platform.getAdapterManager().getAdapter(
selected, IValue.class);
if (adapter != null) {
selected = adapter;
}
}
if (selected != null) {
if (active) {
if (editorForm.setInput(selected)) {
editorForm.refreshStale();
}
} else {
selectionOnActivate = selected;
}
}
}
}
}
private class SelectionProvider extends SelectionProviderAdapter {
public void setInternalSelection(ISelection selection) {
// set selection without propagating to other parts
super.setSelection(selection);
}
@Override
public void setSelection(ISelection selection) {
// try to propagate selection to interested parts
if (selection instanceof IStructuredSelection) {
Object selected = ((IStructuredSelection) selection)
.getFirstElement();
if (editorForm.setInput(selected)) {
// input was accepted, selection changed events are
// automatically triggered by the respective part
return;
}
}
// input was not accepted by any part, so we can't do anything
}
}
private boolean active = true;
private IEditingDomainProvider editingDomainProvider;
private EditorForm editorForm;
private AbstractEditingDomainPart editPart;
private Listener listener;
protected IModel model;
protected IWorkbenchPart part;
private Object selectionOnActivate;
private SelectionProvider selectionProvider = new SelectionProvider();
private boolean setInputOnActivate;
private List<String> redirectedActionIds = new ArrayList<>();
@Override
public void createPartControl(Composite parent) {
parent.setLayout(new FillLayout());
editorForm = new EditorForm(parent) {
@Override
public void fireSelectionChanged(IEditorPart firingPart,
final ISelection selection) {
selectionProvider.setInternalSelection(selection);
super.fireSelectionChanged(firingPart, selection);
}
@Override
@SuppressWarnings("rawtypes")
public Object getAdapter(Class adapter) {
if (IWorkbenchPartSite.class.equals(adapter)
|| IViewSite.class.equals(adapter)) {
return getViewSite();
}
if (IToolBarManager.class.equals(adapter)) {
return getViewSite().getActionBars().getToolBarManager();
}
if (IEditingDomainProvider.class.equals(adapter)) {
return editingDomainProvider;
} else if (IViewerMenuSupport.class.equals(adapter)) {
if (part instanceof IViewerMenuSupport) {
return (IViewerMenuSupport) part;
} else if (part != null) {
return part.getAdapter(IViewerMenuSupport.class);
}
}
return delegatedGetAdapter(adapter);
}
};
editorForm.addPart(editPart);
editorForm.getWidgetFactory().adapt(parent);
editPart.createContents(parent);
installSelectionProvider();
this.listener = new Listener();
getSite().getPage().addPartListener(listener);
getSite().getPage().addSelectionListener(listener);
IWorkbenchPart editor = getSite().getPage().getActiveEditor();
if (editor != null) {
setWorkbenchPart(editor);
// on creation of this part, make sure it is made aware of the
// current selection to avoid it being empty
if (this.model != null) {
this.listener.selectionChanged(editor, editor.getSite()
.getSelectionProvider().getSelection());
}
}
// redirect to editor actions
List<ActionFactory> actionFactories = Arrays.asList(
ActionFactory.DELETE, ActionFactory.CUT, ActionFactory.COPY,
ActionFactory.PASTE, ActionFactory.UNDO, ActionFactory.REDO);
IActionBars myBars = getViewSite().getActionBars();
for (ActionFactory af : actionFactories) {
if (myBars.getGlobalActionHandler(af.getId()) == null) {
redirectedActionIds.add(af.getId());
}
}
}
protected Object delegatedGetAdapter(Class<?> adapter) {
return null;
}
@Override
public void dispose() {
if (editorForm != null) {
editorForm.dispose();
editorForm = null;
}
if (listener != null) {
getSite().getPage().removeSelectionListener(listener);
getSite().getPage().removePartListener(listener);
listener = null;
}
super.dispose();
}
@SuppressWarnings("rawtypes")
@Override
public Object getAdapter(Class adapter) {
Object result = null;
if (IEditingDomainProvider.class.equals(adapter)) {
return editingDomainProvider;
}
if (IContributedContentsView.class.equals(adapter)) {
return this;
}
return result == null ? super.getAdapter(adapter) : result;
}
@Override
public IWorkbenchPart getContributingPart() {
return part;
}
public AbstractEditingDomainPart getEditPart() {
return editPart;
}
protected void installSelectionProvider() {
getSite().setSelectionProvider(selectionProvider);
}
protected boolean setEditingDomainProvider(
IEditingDomainProvider editingDomainProvider, IWorkbenchPart part) {
IEditingDomainProvider lastProvider = this.editingDomainProvider;
if (editingDomainProvider == null) {
this.part = null;
this.editingDomainProvider = null;
} else if (lastProvider != null
&& lastProvider.getEditingDomain() != null
&& lastProvider.getEditingDomain().equals(
editingDomainProvider.getEditingDomain())) {
if (part instanceof org.eclipse.ui.IEditorPart) {
// prefer editors over other parts since they are able to
// provide additional functionality like IViewerMenuSupport
this.part = part;
}
return false;
} else {
this.part = part;
this.editingDomainProvider = editingDomainProvider;
}
return true;
}
public void setEditPart(AbstractEditingDomainPart viewPart) {
this.editPart = viewPart;
}
@Override
public void setFocus() {
editorForm.setFocus();
}
protected void setWorkbenchPart(final IWorkbenchPart part) {
boolean domainChanged = false;
if (part == null) {
domainChanged = setEditingDomainProvider(null, null);
} else if (part instanceof IEditingDomainProvider) {
domainChanged = setEditingDomainProvider(
(IEditingDomainProvider) part, part);
} else {
IEditingDomainProvider provider = (IEditingDomainProvider) part
.getAdapter(IEditingDomainProvider.class);
if (provider != null) {
domainChanged = setEditingDomainProvider(provider, part);
}
}
IModel model = part != null ? (IModel) part.getAdapter(IModel.class)
: null;
boolean changed = domainChanged;
if (domainChanged || model != null) {
changed |= this.model != model || this.model != null
&& !this.model.equals(model);
this.model = model;
}
if (changed) {
// redirect unbound global actions to editor actions
IActionBars myBars = getViewSite().getActionBars();
if (part != null && part.getSite() instanceof IEditorSite) {
IActionBars editorBars = ((IEditorSite) part.getSite())
.getActionBars();
for (String id : redirectedActionIds) {
myBars.setGlobalActionHandler(id,
editorBars.getGlobalActionHandler(id));
}
}
myBars.updateActionBars();
}
if (changed && editPart != null) {
selectionProvider.setInternalSelection(StructuredSelection.EMPTY);
if (active || this.model == null) {
editorForm.setInput(null);
editPart.setInput(this.model);
editorForm.refreshStale();
} else {
setInputOnActivate = true;
}
}
}
}