| /******************************************************************************* |
| * Copyright (c) 2004, 2008 Tasktop Technologies and others. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * https://www.eclipse.org/legal/epl-2.0 |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Tasktop Technologies - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.mylyn.internal.pde.ui; |
| |
| import java.lang.reflect.Field; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| import org.eclipse.core.internal.resources.Workspace; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.jface.text.TextSelection; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.ITreeViewerListener; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.jface.viewers.TreeExpansionEvent; |
| import org.eclipse.jface.viewers.TreeViewer; |
| import org.eclipse.mylyn.commons.core.StatusHandler; |
| import org.eclipse.mylyn.context.core.IInteractionElement; |
| import org.eclipse.mylyn.context.ui.AbstractContextUiBridge; |
| import org.eclipse.pde.internal.core.text.plugin.PluginObjectNode; |
| import org.eclipse.pde.internal.ui.editor.FormOutlinePage; |
| import org.eclipse.pde.internal.ui.editor.ISortableContentOutlinePage; |
| import org.eclipse.pde.internal.ui.editor.PDEFormEditor; |
| import org.eclipse.pde.internal.ui.editor.PDESourcePage; |
| import org.eclipse.pde.internal.ui.editor.SourceOutlinePage; |
| import org.eclipse.pde.internal.ui.editor.plugin.ManifestEditor; |
| import org.eclipse.pde.internal.ui.editor.plugin.PluginInputContext; |
| import org.eclipse.ui.IEditorInput; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.IEditorReference; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.PartInitException; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.forms.editor.FormEditor; |
| import org.eclipse.ui.ide.IDE; |
| import org.eclipse.ui.texteditor.AbstractTextEditor; |
| |
| /** |
| * @author Mik Kersten |
| * @author Shawn Minto |
| */ |
| public class PdeUiBridge extends AbstractContextUiBridge { |
| |
| private final TreeViewerListener treeSelectionChangedListener; |
| |
| public PdeUiBridge() { |
| treeSelectionChangedListener = new TreeViewerListener(); |
| } |
| |
| /** |
| * @see org.eclipse.mylyn.context.ui.AbstractContextUiBridge#open(org.eclipse.mylyn.context.core.IInteractionElement) |
| */ |
| @Override |
| public void open(IInteractionElement node) { |
| // get the handle of the node |
| String handle = node.getHandleIdentifier(); |
| |
| int first = handle.indexOf(";"); //$NON-NLS-1$ |
| String filename = ""; //$NON-NLS-1$ |
| if (first == -1) { |
| filename = handle; |
| } else { |
| filename = handle.substring(0, first); |
| } |
| |
| try { |
| // get the file |
| IPath path = new Path(filename); |
| IFile f = (IFile) ((Workspace) ResourcesPlugin.getWorkspace()).newResource(path, IResource.FILE); |
| |
| // open the xml file looking at the proper line |
| IEditorPart editor = openInEditor(f, true); |
| |
| // if the editor is null, we had a problem and should return |
| if (editor == null) { |
| StatusHandler.log(new Status(IStatus.WARNING, PdeUiBridgePlugin.ID_PLUGIN, |
| "Unable to open editor for file: " + filename)); //$NON-NLS-1$ |
| return; |
| } |
| |
| // get the contents and create a new document so that we can get |
| // the offsets to highlight |
| // String content = XmlNodeHelper.getContents(f.getContents()); |
| // |
| // IDocument d = new Document(content); |
| |
| // if(first != -1){ |
| // int start = Integer.parseInt(handle.substring(first + 1)); |
| // |
| // // get the offsets for the element |
| // int startOffset = d.getLineOffset(start); |
| // int length = 0; |
| // |
| // // set the selection if the selection provider is not null |
| // ISelectionProvider selectionProvider = |
| // editor.getEditorSite().getSelectionProvider(); |
| // if(selectionProvider != null) |
| // selectionProvider.setSelection(new TextSelection(startOffset, |
| // length)); |
| // } |
| |
| } catch (Exception e) { |
| // ContextCorePlugin.log(e, "ERROR OPENING XML EDITOR\n" + |
| // e.getMessage()); |
| } |
| } |
| |
| /** |
| * Open a file in the appropriate editor |
| * |
| * @param file |
| * The IFile to open |
| * @param activate |
| * Whether to activate the editor or not |
| * @return The IEditorPart that the file opened in |
| * @throws PartInitException |
| */ |
| private IEditorPart openInEditor(IFile file, boolean activate) throws PartInitException { |
| if (file != null) { |
| IWorkbenchPage p = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); |
| if (p != null && file.exists()) { |
| IEditorPart editorPart = IDE.openEditor(p, file, activate); |
| // initializeHighlightRange(editorPart); |
| return editorPart; |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public void close(IInteractionElement node) { |
| IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); |
| if (page != null) { |
| IEditorReference[] references = page.getEditorReferences(); |
| for (IEditorReference reference : references) { |
| IEditorPart part = reference.getEditor(false); |
| if (part != null) { |
| // HACK: find better way to get the filename other than the tooltip |
| if (("/" + part.getTitleToolTip()).equals(node.getHandleIdentifier())) { //$NON-NLS-1$ |
| if (part instanceof FormEditor) { |
| ((FormEditor) part).close(true); |
| } else if (part instanceof AbstractTextEditor) { |
| ((AbstractTextEditor) part).close(true); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| @Override |
| public boolean acceptsEditor(IEditorPart editorPart) { |
| return editorPart instanceof ManifestEditor; |
| } |
| |
| /** |
| * HACK: use a lot of reflection to get the TreeViewer |
| */ |
| @Override |
| public List<TreeViewer> getContentOutlineViewers(IEditorPart editor) { |
| if (editor instanceof PDEFormEditor) { |
| PDESourcePage sp = null; |
| List<TreeViewer> viewers = new ArrayList<TreeViewer>(2); |
| if ((sp = (PDESourcePage) ((PDEFormEditor) editor).findPage(PluginInputContext.CONTEXT_ID)) != null) { |
| ISortableContentOutlinePage page = sp.getContentOutline(); |
| if (page != null && page.getControl() != null) { |
| try { |
| if (page instanceof SourceOutlinePage) { |
| // get the tree viewer for the outline |
| Class<?> clazz2 = page.getClass(); |
| Field field2 = clazz2.getDeclaredField("viewer"); //$NON-NLS-1$ |
| field2.setAccessible(true); |
| Object f2 = field2.get(page); |
| if (f2 != null && f2 instanceof TreeViewer) { |
| viewers.add((TreeViewer) f2); |
| } |
| } |
| } catch (Exception e) { |
| StatusHandler.log(new Status(IStatus.ERROR, PdeUiBridgePlugin.ID_PLUGIN, |
| "Failed to get tree viewers", e)); //$NON-NLS-1$ |
| return null; |
| } |
| } |
| } |
| |
| try { |
| // get the current page of the outline |
| Class<?> clazz = PDEFormEditor.class; |
| Field field = null; |
| try { |
| field = clazz.getDeclaredField("formOutline"); //$NON-NLS-1$ |
| } catch (NoSuchFieldException e) { |
| field = clazz.getDeclaredField("fFormOutline"); //$NON-NLS-1$ |
| } |
| field.setAccessible(true); |
| Object f = field.get(editor); |
| if (f != null && f instanceof FormOutlinePage) { |
| // get the tree viewer for the outline |
| Class<?> clazz2 = FormOutlinePage.class; |
| Field field2 = null; |
| try { |
| field2 = clazz2.getDeclaredField("treeViewer"); //$NON-NLS-1$ |
| } catch (NoSuchFieldException e) { |
| field2 = clazz2.getDeclaredField("fTreeViewer"); //$NON-NLS-1$ |
| } |
| field2.setAccessible(true); |
| Object f2 = field2.get(f); |
| if (f2 != null && f2 instanceof TreeViewer) { |
| TreeViewer treeViewer = (TreeViewer) f2; |
| viewers.add(treeViewer); |
| } |
| } |
| } catch (Exception e) { |
| StatusHandler.log(new Status(IStatus.ERROR, PdeUiBridgePlugin.ID_PLUGIN, "Could not get PDE outline", e)); //$NON-NLS-1$ |
| return Collections.emptyList(); |
| } |
| |
| // add a listener so that when the selection changes, the view is |
| // refreshed to attempt to keep the ui model the same as the |
| // taskscape one |
| for (TreeViewer viewer : viewers) { |
| viewer.addSelectionChangedListener(treeSelectionChangedListener); |
| viewer.addTreeListener(treeSelectionChangedListener); |
| } |
| |
| return viewers; |
| } |
| return Collections.emptyList(); |
| } |
| |
| public void refreshOutline(Object element, boolean updateLabels, boolean setSelection) { |
| IEditorPart editorPart = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); |
| List<TreeViewer> treeViewers = getContentOutlineViewers(editorPart); |
| for (TreeViewer treeViewer : treeViewers) { |
| if (treeViewer != null) { |
| if (element == null) { |
| treeViewer.getControl().setRedraw(false); |
| treeViewer.refresh(true); |
| treeViewer.getControl().setRedraw(true); |
| treeViewer.expandAll(); |
| } else if (element instanceof PluginObjectNode) { |
| treeViewer.getControl().setRedraw(false); |
| treeViewer.refresh(element, true); |
| treeViewer.getControl().setRedraw(true); |
| treeViewer.expandAll(); |
| } |
| } |
| } |
| |
| } |
| |
| /** |
| * Class to listen to the tree views to attempt to refresh them more frequently to keep the ui model consistant with |
| * the user selections |
| * |
| * @author Shawn Minto |
| */ |
| private class TreeViewerListener implements ISelectionChangedListener, ITreeViewerListener { |
| public void selectionChanged(SelectionChangedEvent event) { |
| Object o = event.getSource(); |
| if (o instanceof TreeViewer) { |
| ((TreeViewer) o).refresh(); |
| ((TreeViewer) o).expandAll(); |
| } |
| } |
| |
| public void treeCollapsed(TreeExpansionEvent event) { |
| Object o = event.getSource(); |
| if (o instanceof TreeViewer) { |
| ((TreeViewer) o).refresh(); |
| } |
| |
| } |
| |
| public void treeExpanded(TreeExpansionEvent event) { |
| Object o = event.getSource(); |
| if (o instanceof TreeViewer) { |
| ((TreeViewer) o).refresh(); |
| } |
| } |
| } |
| |
| @Override |
| public Object getObjectForTextSelection(TextSelection selection, IEditorPart editor) { |
| return null; |
| } |
| |
| @Override |
| public IInteractionElement getElement(IEditorInput input) { |
| return null; |
| } |
| |
| @Override |
| public String getContentType() { |
| return PdeStructureBridge.CONTENT_TYPE; |
| } |
| } |