/**
* Copyright 2014 SAP AG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spotter.eclipse.ui.navigator;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.navigator.CommonViewer;
import org.eclipse.ui.navigator.ILinkHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spotter.eclipse.ui.Activator;
import org.spotter.eclipse.ui.editors.AbstractSpotterEditorInput;
import org.spotter.eclipse.ui.handlers.IHandlerMediator;
import org.spotter.eclipse.ui.handlers.OpenHandler;
import org.spotter.eclipse.ui.menu.IOpenable;
import org.spotter.eclipse.ui.providers.NavigatorContentProvider;
import org.spotter.eclipse.ui.util.SpotterUtils;
/**
* A helper class that links a selection in the Navigator to the corresponding
* active editor and vice-versa if the "Link with Editor" option is enabled.
*
* @author Denis Knoepfle
*
*/
public class LinkHelper implements ILinkHelper {
private static final Logger LOGGER = LoggerFactory.getLogger(LinkHelper.class);
@Override
public IStructuredSelection findSelection(IEditorInput anInput) {
if (!(anInput instanceof AbstractSpotterEditorInput)) {
throw new RuntimeException("Invalid input type");
}
AbstractSpotterEditorInput input = (AbstractSpotterEditorInput) anInput;
IProject correspondingProject = input.getProject();
String editorId = input.getEditorId();
NavigatorContentProvider provider = Activator.getDefault().getNavigatorContentProvider();
CommonViewer viewer = provider.getViewer();
Object[] parentObjects = provider.getChildren(viewer.getInput());
for (Object rawParent : parentObjects) {
ISpotterProjectElement parent = (ISpotterProjectElement) rawParent;
if (parent.getProject().equals(correspondingProject)) {
ISpotterProjectElement element = recursiveElementSearch(editorId, parent);
if (element != null) {
// found a valid matching selection, so make it visible
if (viewer.testFindItem(element) == null) {
expandToElement(viewer, element);
}
viewer.reveal(element);
return new StructuredSelection(element);
}
break;
}
}
return null;
}
private ISpotterProjectElement recursiveElementSearch(String editorId, ISpotterProjectElement parent) {
NavigatorContentProvider provider = Activator.getDefault().getNavigatorContentProvider();
if (!provider.hasChildren(parent)) {
return null;
}
Object[] rawChildren = provider.getChildren(parent);
Activator.getDefault().getNavigatorViewer().refresh(parent);
for (Object rawChild : rawChildren) {
ISpotterProjectElement element = (ISpotterProjectElement) rawChild;
IOpenable openHandler = getOpenHandler(rawChild);
if (openHandler != null) {
if (editorId.equals(openHandler.getOpenId())) {
return element;
}
}
element = recursiveElementSearch(editorId, element);
if (element != null) {
return element;
}
}
return null;
}
private void expandToElement(CommonViewer viewer, ISpotterProjectElement element) {
ISpotterProjectElement parent = element;
List<ISpotterProjectElement> ancestorList = new ArrayList<>();
while (!SpotterProjectParent.class.isInstance(parent)) {
parent = (ISpotterProjectElement) parent.getParent();
ancestorList.add(parent);
}
for (int i = ancestorList.size() - 1; i >= 0; i--) {
viewer.expandToLevel(ancestorList.get(i), 1);
}
}
@Override
public void activateEditor(IWorkbenchPage aPage, IStructuredSelection aSelection) {
Object rawElement = aSelection.getFirstElement();
IOpenable openHandler = getOpenHandler(rawElement);
if (!(rawElement instanceof ISpotterProjectElement) || openHandler == null) {
return;
}
if (!aPage.isEditorAreaVisible()) {
aPage.setEditorAreaVisible(true);
}
ISpotterProjectElement element = (ISpotterProjectElement) rawElement;
IProject project = element.getProject();
for (IEditorReference reference : aPage.getEditorReferences()) {
try {
IEditorInput editorInput = reference.getEditorInput();
if (editorInput instanceof AbstractSpotterEditorInput) {
AbstractSpotterEditorInput input = (AbstractSpotterEditorInput) editorInput;
if (project.equals(input.getProject()) && input.getEditorId().equals(openHandler.getOpenId())) {
aPage.activate(reference.getEditor(true));
return;
}
}
} catch (PartInitException e) {
LOGGER.warn("Skipping editor reference: failed to retrieve corresponding editor input");
}
}
}
private IOpenable getOpenHandler(Object rawElement) {
IOpenable openHandler = null;
IHandlerMediator mediator = SpotterUtils.toHandlerMediator(rawElement);
if (mediator != null) {
Object handler = mediator.getHandler(OpenHandler.OPEN_COMMAND_ID);
if (handler instanceof IOpenable) {
openHandler = (IOpenable) handler;
}
}
return openHandler;
}
}