/******************************************************************************* * Copyright (c) 2000, 2017 IBM Corporation 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.dltk.ui.browsing; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExecutableExtension; import org.eclipse.core.runtime.IPath; import org.eclipse.dltk.core.DLTKCore; import org.eclipse.dltk.core.DLTKLanguageManager; import org.eclipse.dltk.core.IDLTKLanguageToolkit; import org.eclipse.dltk.core.IModelElement; import org.eclipse.dltk.core.IPackageDeclaration; import org.eclipse.dltk.core.IScriptFolder; import org.eclipse.dltk.core.ISourceModule; import org.eclipse.dltk.core.ModelException; import org.eclipse.dltk.internal.ui.actions.BuildActionGroup; import org.eclipse.dltk.internal.ui.actions.CCPActionGroup; import org.eclipse.dltk.internal.ui.actions.CompositeActionGroup; import org.eclipse.dltk.internal.ui.actions.ImportActionGroup; import org.eclipse.dltk.internal.ui.actions.NewWizardsActionGroup; import org.eclipse.dltk.internal.ui.actions.refactoring.RefactorActionGroup; import org.eclipse.dltk.internal.ui.editor.EditorUtility; import org.eclipse.dltk.internal.ui.search.SearchUtil; import org.eclipse.dltk.internal.ui.workingsets.WorkingSetFilterActionGroup; import org.eclipse.dltk.ui.DLTKUIPlugin; import org.eclipse.dltk.ui.IWorkingCopyManager; import org.eclipse.dltk.ui.ModelElementLabelProvider; import org.eclipse.dltk.ui.ModelElementSorter; import org.eclipse.dltk.ui.ScriptElementImageProvider; import org.eclipse.dltk.ui.ScriptElementLabels; import org.eclipse.dltk.ui.actions.CustomFiltersActionGroup; import org.eclipse.dltk.ui.actions.OpenEditorActionGroup; import org.eclipse.dltk.ui.actions.OpenViewActionGroup; import org.eclipse.dltk.ui.actions.SearchActionGroup; import org.eclipse.dltk.ui.infoviews.AbstractInfoView; import org.eclipse.dltk.ui.viewsupport.AppearanceAwareLabelProvider; import org.eclipse.dltk.ui.viewsupport.DecoratingModelLabelProvider; import org.eclipse.dltk.ui.viewsupport.IViewPartInputProvider; import org.eclipse.dltk.ui.viewsupport.ProblemTableViewer; import org.eclipse.dltk.ui.viewsupport.ScriptUILabelProvider; import org.eclipse.dltk.ui.viewsupport.StatusBarUpdater; import org.eclipse.dltk.ui.viewsupport.StyledDecoratingModelLabelProvider; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IStatusLineManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.search.internal.ui.Messages; import org.eclipse.search.ui.ISearchResultViewPart; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IMemento; import org.eclipse.ui.IPartListener2; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartReference; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.IWorkingSetManager; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionContext; import org.eclipse.ui.actions.ActionGroup; import org.eclipse.ui.contexts.IContextActivation; import org.eclipse.ui.contexts.IContextService; import org.eclipse.ui.part.IShowInSource; import org.eclipse.ui.part.ShowInContext; import org.eclipse.ui.part.ViewPart; import org.eclipse.ui.texteditor.ITextEditor; public abstract class ScriptBrowsingPart extends ViewPart implements IMenuListener, ISelectionListener, IViewPartInputProvider, IExecutableExtension { private static final String TAG_SELECTED_ELEMENTS = "selectedElements"; //$NON-NLS-1$ private static final String TAG_SELECTED_ELEMENT = "selectedElement"; //$NON-NLS-1$ private static final String TAG_LOGICAL_PACKAGE = "logicalPackage"; //$NON-NLS-1$ private static final String TAG_SELECTED_ELEMENT_PATH = "selectedElementPath"; //$NON-NLS-1$ private ScriptUILabelProvider fLabelProvider; private ILabelProvider fTitleProvider; private StructuredViewer fViewer; private IMemento fMemento; private ScriptElementTypeComparator fTypeComparator; // Actions private WorkingSetFilterActionGroup fWorkingSetFilterActionGroup; private boolean fHasWorkingSetFilter = true; private boolean fHasCustomFilter = true; private OpenEditorActionGroup fOpenEditorGroup; private CCPActionGroup fCCPActionGroup; private BuildActionGroup fBuildActionGroup; private ToggleLinkingAction fToggleLinkingAction; protected CompositeActionGroup fActionGroups; private IContextActivation fContextActivation; // Filters private CustomFiltersActionGroup fCustomFiltersActionGroup; protected IWorkbenchPart fPreviousSelectionProvider; protected Object fPreviousSelectedElement; // Linking private boolean fLinkingEnabled; /* * Ensure selection changed events being processed only if initiated by user * interaction with this part. */ private boolean fProcessSelectionEvents = true; private IPartListener2 fPartListener = new IPartListener2() { @Override public void partActivated(IWorkbenchPartReference ref) { } @Override public void partBroughtToTop(IWorkbenchPartReference ref) { } @Override public void partInputChanged(IWorkbenchPartReference ref) { } @Override public void partClosed(IWorkbenchPartReference ref) { } @Override public void partDeactivated(IWorkbenchPartReference ref) { } @Override public void partOpened(IWorkbenchPartReference ref) { } @Override public void partVisible(IWorkbenchPartReference ref) { if (ref != null && ref.getId() == getSite().getId()) { fProcessSelectionEvents = true; IWorkbenchPage page = getSite().getWorkbenchWindow() .getActivePage(); if (page != null) selectionChanged(page.getActivePart(), page.getSelection()); } } @Override public void partHidden(IWorkbenchPartReference ref) { if (ref != null && ref.getId() == getSite().getId()) fProcessSelectionEvents = false; } }; private IDLTKLanguageToolkit fToolkit; public ScriptBrowsingPart() { super(); initLinkingEnabled(); } /* * Implements method from IViewPart. */ @Override public void init(IViewSite site, IMemento memento) throws PartInitException { super.init(site, memento); fMemento = memento; } /* * Implements method from IViewPart. */ @Override public void saveState(IMemento memento) { if (fViewer == null) { // part has not been created if (fMemento != null) // Keep the old state; memento.putMemento(fMemento); return; } if (fHasWorkingSetFilter) fWorkingSetFilterActionGroup.saveState(memento); if (fHasCustomFilter) fCustomFiltersActionGroup.saveState(memento); saveSelectionState(memento); saveLinkingEnabled(memento); } private void saveLinkingEnabled(IMemento memento) { memento.putInteger(getLinkToEditorKey(), fLinkingEnabled ? 1 : 0); } private void saveSelectionState(IMemento memento) { Object elements[] = ((IStructuredSelection) fViewer.getSelection()) .toArray(); if (elements.length > 0) { IMemento selectionMem = memento.createChild(TAG_SELECTED_ELEMENTS); for (int i = 0; i < elements.length; i++) { IMemento elementMem = selectionMem .createChild(TAG_SELECTED_ELEMENT); Object o = elements[i]; if (o instanceof IModelElement) elementMem.putString(TAG_SELECTED_ELEMENT_PATH, ((IModelElement) elements[i]) .getHandleIdentifier()); else if (o instanceof LogicalPackage) { IScriptFolder[] packages = ((LogicalPackage) o) .getScriptFolders(); for (int j = 0; j < packages.length; j++) { IMemento packageMem = elementMem .createChild(TAG_LOGICAL_PACKAGE); packageMem.putString(TAG_SELECTED_ELEMENT_PATH, packages[j].getHandleIdentifier()); } } } } } protected void restoreState(IMemento memento) { if (fHasWorkingSetFilter) fWorkingSetFilterActionGroup.restoreState(memento); if (fHasCustomFilter) fCustomFiltersActionGroup.restoreState(memento); if (fHasCustomFilter || fHasWorkingSetFilter) { fViewer.getControl().setRedraw(false); fViewer.refresh(); fViewer.getControl().setRedraw(true); } } private ISelection restoreSelectionState(IMemento memento) { if (memento == null) return null; IMemento childMem; childMem = memento.getChild(TAG_SELECTED_ELEMENTS); if (childMem != null) { ArrayList list = new ArrayList(); IMemento[] elementMem = childMem.getChildren(TAG_SELECTED_ELEMENT); for (int i = 0; i < elementMem.length; i++) { String javaElementHandle = elementMem[i] .getString(TAG_SELECTED_ELEMENT_PATH); if (javaElementHandle == null) { // logical package IMemento[] packagesMem = elementMem[i] .getChildren(TAG_LOGICAL_PACKAGE); LogicalPackage lp = null; for (int j = 0; j < packagesMem.length; j++) { javaElementHandle = packagesMem[j] .getString(TAG_SELECTED_ELEMENT_PATH); Object pack = DLTKCore.create(javaElementHandle); if (pack instanceof IScriptFolder && ((IScriptFolder) pack).exists()) { if (lp == null) lp = new LogicalPackage((IScriptFolder) pack); else lp.add((IScriptFolder) pack); } } if (lp != null) list.add(lp); } else { IModelElement element = DLTKCore.create(javaElementHandle); if (element != null && element.exists()) list.add(element); } } return new StructuredSelection(list); } return null; } private void restoreLinkingEnabled(IMemento memento) { Integer val = memento.getInteger(getLinkToEditorKey()); if (val != null) { fLinkingEnabled = val.intValue() != 0; } } /* * (non-Javadoc) * * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt. * widgets .Composite) */ @Override public void createPartControl(Composite parent) { Assert.isTrue(fViewer == null); fTypeComparator = new ScriptElementTypeComparator(); // Setup viewer fViewer = createViewer(parent); initDragAndDrop(); fLabelProvider = createLabelProvider(); fViewer.setLabelProvider(createDelegatingLabelProvider(fLabelProvider)); fViewer.setComparator(createModelElementComparator()); fViewer.setUseHashlookup(true); fTitleProvider = createTitleProvider(); createContextMenu(); getSite().setSelectionProvider(fViewer); if (fMemento != null) { // initialize linking state before creating the // actions restoreLinkingEnabled(fMemento); } createActions(); // call before registering for selection changes addKeyListener(); if (fMemento != null) restoreState(fMemento); getSite().setSelectionProvider(fViewer); // Status line IStatusLineManager slManager = getViewSite().getActionBars() .getStatusLineManager(); fViewer.addSelectionChangedListener(createStatusBarUpdater(slManager)); hookViewerListeners(); // Filters addFilters(); // Initialize viewer input fViewer.setContentProvider(createContentProvider()); setInitialInput(); // Initialize selection setInitialSelection(); fMemento = null; // Listen to page changes getViewSite().getPage().addPostSelectionListener(this); getViewSite().getPage().addPartListener(fPartListener); fillActionBars(getViewSite().getActionBars()); IContextService ctxService = getSite() .getService(IContextService.class); if (ctxService != null) { fContextActivation = ctxService .activateContext(DLTKUIPlugin.CONTEXT_VIEWS); } setHelp(); } @SuppressWarnings("unchecked") @Override public <T> T getAdapter(Class<T> key) { if (key == IShowInSource.class) { return (T) getShowInSource(); } // if (key == IContextProvider.class) // return JavaUIHelp.getHelpContextProvider(this, getHelpContextId()); return super.getAdapter(key); } /** * Returns the <code>IShowInSource</code> for this view. * * @return returns the <code>IShowInSource</code> */ protected IShowInSource getShowInSource() { return () -> new ShowInContext(null, getSite().getSelectionProvider().getSelection()); } /** * @since 5.2 */ protected ILabelProvider createDelegatingLabelProvider( ScriptUILabelProvider provider) { DecoratingModelLabelProvider labelprovider = createDecoratingLabelProvider( provider); if (labelprovider != null) return labelprovider; return new StyledDecoratingModelLabelProvider(provider); } /** * @deprecated override * org.eclipse.dltk.ui.browsing.ScriptBrowsingPart.createDelegatingLabelProvider * (ScriptUILabelProvider) instead */ @Deprecated protected DecoratingModelLabelProvider createDecoratingLabelProvider( ScriptUILabelProvider provider) { // XXX: Work in progress for problem decorator being a workbench // decorator// // return new ExcludingDecoratingLabelProvider(provider, decorationMgr, // "org.eclipse.jdt.ui.problem.decorator"); //$NON-NLS-1$ return null; } protected ModelElementSorter createModelElementComparator() { return new ModelElementSorter(); } protected StatusBarUpdater createStatusBarUpdater( IStatusLineManager slManager) { return new StatusBarUpdater(slManager); } protected void createContextMenu() { MenuManager menuManager = new MenuManager("#PopupMenu"); //$NON-NLS-1$ menuManager.setRemoveAllWhenShown(true); menuManager.addMenuListener(this); Menu contextMenu = menuManager.createContextMenu(fViewer.getControl()); fViewer.getControl().setMenu(contextMenu); getSite().registerContextMenu(menuManager, fViewer); } protected void initDragAndDrop() { // int ops = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK; // // drop // Transfer[] dropTransfers = new Transfer[] { LocalSelectionTransfer // .getInstance() }; // TransferDropTargetListener[] dropListeners = new // TransferDropTargetListener[] { new SelectionTransferDropAdapter( // fViewer) }; // fViewer.addDropSupport(ops | DND.DROP_DEFAULT, dropTransfers, // new DelegatingDropAdapter(dropListeners)); // // // Drag // Transfer[] dragTransfers = new Transfer[] { // LocalSelectionTransfer.getInstance(), // ResourceTransfer.getInstance() }; // TransferDragSourceListener[] dragListeners = new // TransferDragSourceListener[] { // new SelectionTransferDragAdapter(fViewer), // new ResourceTransferDragAdapter(fViewer) }; // fViewer.addDragSupport(ops, dragTransfers, new DLTKViewerDragAdapter( // fViewer, dragListeners)); } protected void fillActionBars(IActionBars actionBars) { IToolBarManager toolBar = actionBars.getToolBarManager(); fillToolBar(toolBar); if (fHasWorkingSetFilter) fWorkingSetFilterActionGroup .fillActionBars(getViewSite().getActionBars()); actionBars.updateActionBars(); fActionGroups.fillActionBars(actionBars); if (fHasCustomFilter) fCustomFiltersActionGroup.fillActionBars(actionBars); IMenuManager menu = actionBars.getMenuManager(); menu.add(fToggleLinkingAction); } // ---- IWorkbenchPart // ------------------------------------------------------ @Override public void setFocus() { fViewer.getControl().setFocus(); } @Override public void dispose() { if (fContextActivation != null) { IContextService ctxService = getSite() .getService(IContextService.class); if (ctxService != null) { ctxService.deactivateContext(fContextActivation); } } if (fViewer != null) { getViewSite().getPage().removePostSelectionListener(this); getViewSite().getPage().removePartListener(fPartListener); fViewer = null; } if (fActionGroups != null) fActionGroups.dispose(); if (fWorkingSetFilterActionGroup != null) { fWorkingSetFilterActionGroup.dispose(); } super.dispose(); } /** * Adds the KeyListener */ protected void addKeyListener() { fViewer.getControl().addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent event) { handleKeyReleased(event); } }); } protected void handleKeyReleased(KeyEvent event) { if (event.stateMask != 0) return; int key = event.keyCode; if (key == SWT.F5) { IAction action = fBuildActionGroup.getRefreshAction(); if (action.isEnabled()) action.run(); } } // ---- Adding Action to Toolbar ------------------------------------------- protected void fillToolBar(IToolBarManager tbm) { } /* * (non-Javadoc) * * @see * org.eclipse.jface.action.IMenuListener#menuAboutToShow(org.eclipse.jface * .action.IMenuManager) */ @Override public void menuAboutToShow(IMenuManager menu) { DLTKUIPlugin.createStandardGroups(menu); IStructuredSelection selection = (IStructuredSelection) fViewer .getSelection(); int size = selection.size(); Object element = selection.getFirstElement(); if (size == 1) addOpenNewWindowAction(menu, element); fActionGroups.setContext(new ActionContext(selection)); fActionGroups.fillContextMenu(menu); fActionGroups.setContext(null); } private void addOpenNewWindowAction(IMenuManager menu, Object element) { if (element instanceof IModelElement) { element = ((IModelElement) element).getResource(); } if (!(element instanceof IContainer)) return; // menu.appendToGroup(IContextMenuConstants.GROUP_OPEN, // new PatchedOpenInNewWindowAction( // getSite().getWorkbenchWindow(), (IContainer) element)); } protected IDLTKLanguageToolkit getToolkit() { return this.fToolkit; } protected void createActions() { fActionGroups = new CompositeActionGroup( new ActionGroup[] { new NewWizardsActionGroup(this.getSite()), fOpenEditorGroup = new OpenEditorActionGroup(this), new OpenViewActionGroup(this), fCCPActionGroup = new CCPActionGroup(this), // new GenerateActionGroup(this), new RefactorActionGroup(this, null), new ImportActionGroup(this), fBuildActionGroup = new BuildActionGroup(this), new SearchActionGroup(this, this.getToolkit()) }); if (fHasWorkingSetFilter) { String viewId = getConfigurationElement().getAttribute("id"); //$NON-NLS-1$ Assert.isNotNull(viewId); IPropertyChangeListener workingSetListener = event -> doWorkingSetChanged( event); fWorkingSetFilterActionGroup = new WorkingSetFilterActionGroup( getSite(), workingSetListener); fViewer.addFilter( fWorkingSetFilterActionGroup.getWorkingSetFilter()); } // Custom filter group if (fHasCustomFilter) fCustomFiltersActionGroup = new CustomFiltersActionGroup(this, fViewer); fToggleLinkingAction = new ToggleLinkingAction(this); } private void doWorkingSetChanged(PropertyChangeEvent event) { String property = event.getProperty(); if (IWorkingSetManager.CHANGE_WORKING_SET_NAME_CHANGE.equals(property)) updateTitle(); else if (IWorkingSetManager.CHANGE_WORKING_SET_CONTENT_CHANGE .equals(property)) { updateTitle(); fViewer.getControl().setRedraw(false); fViewer.refresh(); fViewer.getControl().setRedraw(true); } } /** * Returns the shell to use for opening dialogs. Used in this class, and in * the actions. * * @return returns the shell */ Shell getShell() { return fViewer.getControl().getShell(); } protected final Display getDisplay() { return fViewer.getControl().getDisplay(); } /** * Returns the selection provider. * * @return the selection provider */ ISelectionProvider getSelectionProvider() { return fViewer; } /** * Answers if the given <code>element</code> is a valid input for this part. * * @param element * the object to test * @return <code>true</code> if the given element is a valid input */ abstract protected boolean isValidInput(Object element); /** * Answers if the given <code>element</code> is a valid element for this * part. * * @param element * the object to test * @return <code>true</code> if the given element is a valid element */ protected boolean isValidElement(Object element) { if (!(element instanceof IModelElement)) { return false; } Object input = getViewer().getInput(); if (input == null) return false; if (input instanceof Collection) return ((Collection) input).contains(element); else return input.equals(element); } private boolean isInputResetBy(Object newInput, Object input, IWorkbenchPart part) { if (newInput == null) return part == fPreviousSelectionProvider; if (input instanceof IModelElement && newInput instanceof IModelElement) return getTypeComparator().compare(newInput, input) > 0; if ((newInput instanceof List) && (part instanceof PackagesView)) return true; else return false; } private boolean isInputResetBy(IWorkbenchPart part) { if (!(part instanceof ScriptBrowsingPart)) return true; Object thisInput = getViewer().getInput(); Object partInput = ((ScriptBrowsingPart) part).getViewer().getInput(); if (thisInput instanceof Collection) thisInput = ((Collection) thisInput).iterator().next(); if (partInput instanceof Collection) partInput = ((Collection) partInput).iterator().next(); if (thisInput instanceof IModelElement && partInput instanceof IModelElement) return getTypeComparator().compare(partInput, thisInput) > 0; else return true; } protected boolean isAncestorOf(Object ancestor, Object element) { if (element instanceof IModelElement && ancestor instanceof IModelElement) return !element.equals(ancestor) && internalIsAncestorOf( (IModelElement) ancestor, (IModelElement) element); if (element instanceof IModelElement && ancestor instanceof List) { List l = (List) ancestor; for (Iterator iterator = l.iterator(); iterator.hasNext();) { IModelElement anc = (IModelElement) iterator.next(); if (element.equals(anc) && internalIsAncestorOf(anc, (IModelElement) element)) { return true; } } } return false; } private boolean internalIsAncestorOf(IModelElement ancestor, IModelElement element) { if (element != null) return element.equals(ancestor) || internalIsAncestorOf(ancestor, element.getParent()); else return false; } private boolean isSearchResultView(IWorkbenchPart part) { return SearchUtil.isSearchPlugInActivated() && part instanceof ISearchResultViewPart; } protected boolean needsToProcessSelectionChanged(IWorkbenchPart part, ISelection selection) { if (!fProcessSelectionEvents || part == this || isSearchResultView(part) || part instanceof AbstractInfoView) { if (part == this) fPreviousSelectionProvider = part; return false; } return true; } @Override public void selectionChanged(IWorkbenchPart part, ISelection selection) { if (!needsToProcessSelectionChanged(part, selection)) return; if (fToggleLinkingAction.isChecked() && (part instanceof ITextEditor)) { setSelectionFromEditor(part, selection); return; } if (!(selection instanceof IStructuredSelection)) return; // Set selection Object selectedElement = getSingleElementFromSelection(selection); if (selectedElement != null && (part == null || part.equals(fPreviousSelectionProvider)) && selectedElement.equals(fPreviousSelectedElement)) return; fPreviousSelectedElement = selectedElement; Object currentInput = getViewer().getInput(); if (selectedElement != null && selectedElement.equals(currentInput)) { Object elementToSelect = findElementToSelect(selectedElement); if (elementToSelect != null && getTypeComparator() .compare(selectedElement, elementToSelect) < 0) setSelection(new StructuredSelection(elementToSelect), true); else if (elementToSelect == null && (this instanceof MembersView)) { setSelection(StructuredSelection.EMPTY, true); fPreviousSelectedElement = StructuredSelection.EMPTY; } fPreviousSelectionProvider = part; return; } // Clear input if needed if (part != fPreviousSelectionProvider && selectedElement != null && !selectedElement.equals(currentInput) && isInputResetBy(selectedElement, currentInput, part)) { if (!isAncestorOf(selectedElement, currentInput)) setInput(null); fPreviousSelectionProvider = part; return; } else if (selection.isEmpty() && !isInputResetBy(part)) { fPreviousSelectionProvider = part; return; } else if (selectedElement == null && part == fPreviousSelectionProvider) { setInput(null); fPreviousSelectionProvider = part; return; } fPreviousSelectionProvider = part; // Adjust input and set selection and adjustInputAndSetSelection(selectedElement); } void setHasWorkingSetFilter(boolean state) { fHasWorkingSetFilter = state; } void setHasCustomSetFilter(boolean state) { fHasCustomFilter = state; } protected Object getInput() { return fViewer.getInput(); } protected void setInput(Object input) { setViewerInput(input); updateTitle(); } boolean isLinkingEnabled() { return fLinkingEnabled; } private void initLinkingEnabled() { fLinkingEnabled = DLTKUIPlugin.getDefault().getPreferenceStore() .getBoolean(getLinkToEditorKey()); } private void setViewerInput(Object input) { fProcessSelectionEvents = false; fViewer.setInput(input); fProcessSelectionEvents = true; } void updateTitle() { setTitleToolTip(getToolTipText(fViewer.getInput())); } /** * Returns the tool tip text for the given element. * * @param element * the element * @return the tooltip for the element */ String getToolTipText(Object element) { String result; if (!(element instanceof IResource)) { result = ScriptElementLabels.getDefault().getTextLabel(element, AppearanceAwareLabelProvider.DEFAULT_TEXTFLAGS); } else { IPath path = ((IResource) element).getFullPath(); if (path.isRoot()) { result = getConfigurationElement().getAttribute("name"); //$NON-NLS-1$ } else { result = path.makeRelative().toString(); } } if (fWorkingSetFilterActionGroup == null || fWorkingSetFilterActionGroup.getWorkingSet() == null) return result; IWorkingSet ws = fWorkingSetFilterActionGroup.getWorkingSet(); String wsstr = Messages.format( ScriptBrowsingMessages.JavaBrowsingPart_toolTip, new String[] { ws.getLabel() }); if (result.length() == 0) return wsstr; return Messages.format(ScriptBrowsingMessages.JavaBrowsingPart_toolTip2, new String[] { result, ws.getLabel() }); } /* * (non-Javadoc) * * @see org.eclipse.ui.part.WorkbenchPart#getTitleToolTip() */ @Override public String getTitleToolTip() { if (fViewer == null) return super.getTitleToolTip(); return getToolTipText(fViewer.getInput()); } protected final StructuredViewer getViewer() { return fViewer; } protected final void setViewer(StructuredViewer viewer) { fViewer = viewer; } protected ScriptUILabelProvider createLabelProvider() { return new AppearanceAwareLabelProvider( AppearanceAwareLabelProvider.DEFAULT_TEXTFLAGS, AppearanceAwareLabelProvider.DEFAULT_IMAGEFLAGS | ScriptElementImageProvider.SMALL_ICONS, DLTKUIPlugin.getDefault().getPreferenceStore()); } protected ILabelProvider createTitleProvider() { return new ModelElementLabelProvider( ModelElementLabelProvider.SHOW_BASICS | ModelElementLabelProvider.SHOW_SMALL_ICONS); } protected final ILabelProvider getLabelProvider() { return fLabelProvider; } protected final ILabelProvider getTitleProvider() { return fTitleProvider; } /** * Creates the viewer of this part. * * @param parent * the parent for the viewer * @return the created viewer */ protected StructuredViewer createViewer(Composite parent) { return new ProblemTableViewer(parent, SWT.MULTI); } protected int getLabelProviderFlags() { return ModelElementLabelProvider.SHOW_BASICS | ModelElementLabelProvider.SHOW_OVERLAY_ICONS | ModelElementLabelProvider.SHOW_SMALL_ICONS | ModelElementLabelProvider.SHOW_VARIABLE | ModelElementLabelProvider.SHOW_PARAMETERS; } /** * Adds filters the viewer of this part. */ protected void addFilters() { // default is to have no filters } /** * Creates the content provider of this part. * * @return the content provider */ protected IContentProvider createContentProvider() { return new ScriptBrowsingContentProvider(true, this, this.getToolkit()); } protected void setInitialInput() { // Use the selection, if any ISelection selection = getSite().getPage().getSelection(); Object input = getSingleElementFromSelection(selection); if (!(input instanceof IModelElement)) { // Use the input of the page input = getSite().getPage().getInput(); if (!(input instanceof IModelElement) && input instanceof IAdaptable) input = ((IAdaptable) input).getAdapter(IModelElement.class); } setInput(findInputForJavaElement((IModelElement) input)); } protected void setInitialSelection() { // Use the selection, if any Object input; IWorkbenchPage page = getSite().getPage(); ISelection selection = null; if (page != null) selection = page.getSelection(); if (selection instanceof ITextSelection) { IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench() .getActiveWorkbenchWindow(); IWorkbenchPage activePage = activeWorkbenchWindow.getActivePage(); if (activePage != null) { Object part = activePage.getActivePart(); if (part instanceof IEditorPart) { setSelectionFromEditor((IEditorPart) part); if (fViewer.getSelection() != null) return; } } } // Use saved selection from memento if (selection == null || selection.isEmpty()) selection = restoreSelectionState(fMemento); if (selection == null || selection.isEmpty()) { // Use the input of the page input = getSite().getPage().getInput(); if (!(input instanceof IModelElement)) { if (input instanceof IAdaptable) input = ((IAdaptable) input) .getAdapter(IModelElement.class); else return; } selection = new StructuredSelection(input); } selectionChanged(null, selection); } protected final void setHelp() { // JavaUIHelp.setHelp(fViewer, getHelpContextId()); } /** * Returns the context ID for the Help system * * @return the string used as ID for the Help context */ abstract protected String getHelpContextId(); /** * Returns the preference key for the link to editor setting. * * @return the string used as key into the preference store */ abstract protected String getLinkToEditorKey(); /** * Adds additional listeners to this view. This method can be overridden but * should call super. */ protected void hookViewerListeners() { fViewer.addPostSelectionChangedListener(event -> { if (!fProcessSelectionEvents) return; fPreviousSelectedElement = getSingleElementFromSelection( event.getSelection()); IWorkbenchPage page = getSite().getPage(); if (page == null) return; if (page.equals(DLTKUIPlugin.getActivePage()) && ScriptBrowsingPart.this.equals(page.getActivePart())) { linkToEditor((IStructuredSelection) event.getSelection()); } }); fViewer.addOpenListener(event -> { IAction open = fOpenEditorGroup.getOpenAction(); if (open.isEnabled()) { open.run(); restoreSelection(); } }); } void restoreSelection() { // Default is to do nothing } void adjustInputAndSetSelection(Object o) { if (!(o instanceof IModelElement || o instanceof List)) { if (o == null) setInput(null); setSelection(StructuredSelection.EMPTY, true); return; } if (o instanceof IModelElement) { IModelElement je = (IModelElement) o; IModelElement elementToSelect = findElementToSelect(je); IModelElement newInput = findInputForJavaElement(je); IModelElement oldInput = null; if (getInput() instanceof IModelElement) oldInput = (IModelElement) getInput(); if (elementToSelect == null && !isValidInput(newInput) && (newInput == null && !isAncestorOf(je, oldInput))) // Clear input setInput(null); else if (mustSetNewInput(elementToSelect, oldInput, newInput)) { // Adjust input to selection setInput(newInput); } if (elementToSelect != null && elementToSelect.exists()) setSelection(new StructuredSelection(elementToSelect), true); else setSelection(StructuredSelection.EMPTY, true); } else { setSelection(new StructuredSelection(o), true); setInput(o); } } /** * Compute if a new input must be set. * * @param elementToSelect * the element to select * @param oldInput * old input * @param newInput * new input * @return <code>true</code> if the input has to be set * @since 3.0 */ private boolean mustSetNewInput(IModelElement elementToSelect, IModelElement oldInput, IModelElement newInput) { return (newInput == null || !newInput.equals(oldInput)) && (elementToSelect == null || oldInput == null || (!((elementToSelect instanceof IPackageDeclaration) && (elementToSelect.getParent() .equals(oldInput.getParent())) && (!isAncestorOf(getViewPartInput(), elementToSelect))))); } /** * Finds the closest Java element which can be used as input for this part * and has the given Java element as child * * @param je * the Java element for which to search the closest input * @return the closest Java element used as input for this part */ protected IModelElement findInputForJavaElement(IModelElement je) { if (je == null || !je.exists()) return null; if (isValidInput(je)) return je; return findInputForJavaElement(je.getParent()); } protected final Object findElementToSelect(Object obj) { if (obj instanceof IModelElement) return findElementToSelect((IModelElement) obj); else if (obj instanceof List) { return obj; } return null; } /** * Finds the element which has to be selected in this part. * * @param je * the Java element which has the focus * @return returns the element to select */ abstract protected IModelElement findElementToSelect(IModelElement je); protected final Object getSingleElementFromSelection(ISelection selection) { if (!(selection instanceof IStructuredSelection) || selection.isEmpty()) return null; Iterator iter = ((IStructuredSelection) selection).iterator(); Object firstElement = iter.next(); if (!(firstElement instanceof IModelElement)) { if (firstElement instanceof IMarker) firstElement = ((IMarker) firstElement).getResource(); if (firstElement instanceof IAdaptable) { IModelElement je = ((IAdaptable) firstElement) .getAdapter(IModelElement.class); if (je == null && firstElement instanceof IFile) { IContainer parent = ((IFile) firstElement).getParent(); if (parent != null) return parent.getAdapter(IModelElement.class); else return null; } else return je; } else return firstElement; } Object currentInput = getViewer().getInput(); List elements = new ArrayList(); if (currentInput == null || !currentInput .equals(findInputForJavaElement((IModelElement) firstElement))) if (iter.hasNext() && selection instanceof StructuredSelection) { // multi-selection and view is empty return ((StructuredSelection) selection).toList(); } else // OK: single selection and view is empty return firstElement; // be nice to multi-selection while (iter.hasNext()) { Object element = iter.next(); if (!(element instanceof IModelElement)) return null; if (!currentInput .equals(findInputForJavaElement((IModelElement) element))) return null; } return firstElement; } /** * Gets the typeComparator. * * @return Returns a JavaElementTypeComparator */ protected Comparator getTypeComparator() { return fTypeComparator; } /** * Links to editor (if option enabled) * * @param selection * the selection */ private void linkToEditor(IStructuredSelection selection) { Object obj = selection.getFirstElement(); if (selection.size() == 1) { IEditorPart part = EditorUtility.isOpenInEditor(obj); if (part != null) { IWorkbenchPage page = getSite().getPage(); page.bringToTop(part); if (obj instanceof IModelElement) EditorUtility.revealInEditor(part, (IModelElement) obj); } } } void setSelectionFromEditor(IWorkbenchPart part) { if (!fProcessSelectionEvents || !linkBrowsingViewSelectionToEditor() || !(part instanceof IEditorPart)) return; IWorkbenchPartSite site = part.getSite(); if (site == null) return; ISelectionProvider provider = site.getSelectionProvider(); if (provider != null) setSelectionFromEditor(part, provider.getSelection()); } private void setSelectionFromEditor(IWorkbenchPart part, ISelection selection) { if (part instanceof IEditorPart) { IModelElement element = null; if (selection instanceof IStructuredSelection) { Object obj = getSingleElementFromSelection(selection); if (obj instanceof IModelElement) element = (IModelElement) obj; } IEditorInput ei = ((IEditorPart) part).getEditorInput(); if (selection instanceof ITextSelection) { int offset = ((ITextSelection) selection).getOffset(); element = getElementAt(ei, offset); } if (element != null) { adjustInputAndSetSelection(element); return; } if (ei instanceof IFileEditorInput) { IFile file = ((IFileEditorInput) ei).getFile(); IModelElement je = file.getAdapter(IModelElement.class); if (je == null) { IContainer container = ((IFileEditorInput) ei).getFile() .getParent(); if (container != null) je = container.getAdapter(IModelElement.class); } if (je == null) { setSelection(null, false); return; } adjustInputAndSetSelection(je); } /* * else if (ei instanceof IClassFileEditorInput) { IClassFile cf * = ((IClassFileEditorInput) ei).getClassFile(); * adjustInputAndSetSelection(cf); } */ } } /** * Returns the element contained in the EditorInput * * @param input * the editor input * @return the input element */ Object getElementOfInput(IEditorInput input) { if (input instanceof IFileEditorInput) return ((IFileEditorInput) input).getFile(); if (input != null) return DLTKUIPlugin.getEditorInputModelElement(input); return null; } void setSelection(ISelection selection, boolean reveal) { if (selection != null && selection.equals(fViewer.getSelection())) return; fProcessSelectionEvents = false; fViewer.setSelection(selection, reveal); fProcessSelectionEvents = true; } /** * @param input * the editor input * @param offset * the offset in the file * @return the element at the given offset */ protected IModelElement getElementAt(IEditorInput input, int offset) { IWorkingCopyManager manager = DLTKUIPlugin.getDefault() .getWorkingCopyManager(); ISourceModule unit = manager.getWorkingCopy(input); if (unit != null) try { if (unit.isConsistent()) return unit.getElementAt(offset); else { /* * XXX: We should set the selection later when the CU is * reconciled. see * https://bugs.eclipse.org/bugs/show_bug.cgi?id=51290 */ } } catch (ModelException ex) { // fall through } return null; } // protected IType getTypeForCU(ISourceModule cu) { // // Use primary type if possible // IType primaryType = cu.findPrimaryType(); // if (primaryType != null) // return primaryType; // // // Use first top-level type // try { // IType[] types = cu.getTypes(); // if (types.length > 0) // return types[0]; // else // return null; // } catch (ModelException ex) { // return null; // } // } void setProcessSelectionEvents(boolean state) { fProcessSelectionEvents = state; } /* * (non-Javadoc) * * @seeorg.eclipse.jdt.internal.ui.viewsupport.IViewPartInputProvider# * getViewPartInput() */ @Override public Object getViewPartInput() { if (fViewer != null) { return fViewer.getInput(); } return null; } protected void setActionGroups(CompositeActionGroup actionGroups) { fActionGroups = actionGroups; } protected void setBuildActionGroup(BuildActionGroup actionGroup) { fBuildActionGroup = actionGroup; } protected void setCCPActionGroup(CCPActionGroup actionGroup) { fCCPActionGroup = actionGroup; } protected void setCustomFiltersActionGroup( CustomFiltersActionGroup customFiltersActionGroup) { fCustomFiltersActionGroup = customFiltersActionGroup; } protected boolean hasCustomFilter() { return fHasCustomFilter; } protected boolean hasWorkingSetFilter() { return fHasWorkingSetFilter; } protected void setOpenEditorGroup(OpenEditorActionGroup openEditorGroup) { fOpenEditorGroup = openEditorGroup; } protected OpenEditorActionGroup getOpenEditorGroup() { return fOpenEditorGroup; } protected BuildActionGroup getBuildActionGroup() { return fBuildActionGroup; } protected CCPActionGroup getCCPActionGroup() { return fCCPActionGroup; } private boolean linkBrowsingViewSelectionToEditor() { return isLinkingEnabled(); } public void setLinkingEnabled(boolean enabled) { fLinkingEnabled = enabled; DLTKUIPlugin.getDefault().getPreferenceStore() .setValue(getLinkToEditorKey(), enabled); if (enabled) { IEditorPart editor = getSite().getPage().getActiveEditor(); if (editor != null) { setSelectionFromEditor(editor); } } } @Override public void setInitializationData(IConfigurationElement config, String propertyName, Object data) { super.setInitializationData(config, propertyName, data); String nature = null; if (data instanceof String) { nature = (String) data; } else if (data instanceof Map) { nature = (String) ((Map) data).get("nature"); //$NON-NLS-1$ } if (nature != null) { this.fToolkit = DLTKLanguageManager.getLanguageToolkit(nature); } else { throw new RuntimeException( ScriptBrowsingMessages.ScriptBrowsingPart_natureAttributeMustBeSpecifiedAndCorrect); } } }