Java tutorial
/*=============================================================================# # Copyright (c) 2009-2015 Stephan Wahlbrink (WalWare.de) 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: # Stephan Wahlbrink - initial API and implementation #=============================================================================*/ package de.walware.statet.r.internal.objectbrowser; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.commands.IHandler2; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.action.IContributionManager; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TreePath; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IMemento; import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbenchCommandConstants; import org.eclipse.ui.PartInitException; import org.eclipse.ui.commands.IElementUpdater; import org.eclipse.ui.contexts.IContextService; import org.eclipse.ui.handlers.CollapseAllHandler; import org.eclipse.ui.handlers.IHandlerService; import org.eclipse.ui.menus.CommandContributionItemParameter; import org.eclipse.ui.menus.UIElement; import org.eclipse.ui.part.ViewPart; import org.eclipse.ui.progress.IWorkbenchSiteProgressService; import de.walware.ecommons.FastList; import de.walware.ecommons.collections.ConstArrayList; import de.walware.ecommons.ltk.IElementName; import de.walware.ecommons.ltk.ui.IElementNameProvider; import de.walware.ecommons.ltk.ui.sourceediting.ISourceEditorCommandIds; import de.walware.ecommons.ltk.ui.util.ViewerDragSupport; import de.walware.ecommons.models.core.util.IElementPartition; import de.walware.ecommons.ts.ITool; import de.walware.ecommons.ts.IToolRunnable; import de.walware.ecommons.ui.SharedUIResources; import de.walware.ecommons.ui.actions.HandlerContributionItem; import de.walware.ecommons.ui.actions.SearchContributionItem; import de.walware.ecommons.ui.components.StatusInfo; import de.walware.ecommons.ui.util.ColumnHoverManager; import de.walware.ecommons.ui.util.ColumnHoverStickyManager; import de.walware.ecommons.ui.util.ColumnWidgetTokenOwner; import de.walware.ecommons.ui.util.DialogUtil; import de.walware.ecommons.ui.util.InformationDispatchHandler; import de.walware.ecommons.ui.util.LayoutUtil; import de.walware.ecommons.ui.util.PostSelectionProviderProxy; import de.walware.ecommons.ui.util.StatusLineMessageManager; import de.walware.ecommons.ui.util.TreeSelectionProxy; import de.walware.ecommons.ui.util.UIAccess; import de.walware.statet.base.ui.StatetImages; import de.walware.statet.nico.core.runtime.ToolProcess; import de.walware.statet.nico.core.util.IToolProvider; import de.walware.statet.nico.core.util.IToolRetargetable; import de.walware.statet.nico.ui.IToolRegistry; import de.walware.statet.nico.ui.IToolRegistryListener; import de.walware.statet.nico.ui.NicoUI; import de.walware.statet.nico.ui.ToolSessionUIData; import de.walware.statet.nico.ui.actions.ToolRetargetableHandler; import de.walware.rj.data.RObject; import de.walware.rj.data.RReference; import de.walware.statet.r.console.core.AbstractRDataRunnable; import de.walware.statet.r.console.core.IRDataAdapter; import de.walware.statet.r.console.core.RConsoleTool; import de.walware.statet.r.console.core.RProcess; import de.walware.statet.r.console.core.RWorkspace; import de.walware.statet.r.console.core.RWorkspace.ICombinedREnvironment; import de.walware.statet.r.core.data.ICombinedRElement; import de.walware.statet.r.core.model.RElementComparator; import de.walware.statet.r.core.model.RElementName; import de.walware.statet.r.internal.ui.RUIPlugin; import de.walware.statet.r.internal.ui.rtools.RunPrintInR; import de.walware.statet.r.ui.RLabelProvider; import de.walware.statet.r.ui.rtool.RElementInfoHoverCreator; import de.walware.statet.r.ui.rtool.RElementInfoTask; public class ObjectBrowserView extends ViewPart implements IToolProvider { private static final String FILTER_USERSPACEONLY_SETTINGS_KEY = "filter.only_userspace.enabled"; //$NON-NLS-1$ private static final String FILTER_INTERNALINCLUDE_SETTINGS_KEY = "filter.include_internal.enabled"; //$NON-NLS-1$ private static final String SORT_BYTYPE_SETTINGS_KEY = "sort.by_name.enabled"; //$NON-NLS-1$ static final RElementComparator ELEMENTNAME_COMPARATOR = new RElementComparator(); private static final ViewerComparator TYPE_COMPARATOR = new SortByTypeComparator(); private static final String OPEN_COMMAND_ID = "org.eclipse.jdt.ui.edit.text.java.open.editor"; //$NON-NLS-1$ private class RefreshWorkspaceR extends AbstractRDataRunnable { public RefreshWorkspaceR() { super("r/objectbrowser/refreshWorkspace.force", "Update Object Browser"); //$NON-NLS-1$ } @Override public boolean changed(final int event, final ITool tool) { if (event == MOVING_FROM) { return false; } return true; } @Override protected void run(final IRDataAdapter r, final IProgressMonitor monitor) throws CoreException { boolean current; synchronized (processLock) { current = (r.getTool() != getTool()); } final IWorkbenchSiteProgressService progressService = (IWorkbenchSiteProgressService) getViewSite() .getService(IWorkbenchSiteProgressService.class); if (current && progressService != null) { progressService.incrementBusy(); } try { fInputUpdater.forceOnWorkspaceChange(); r.refreshWorkspaceData(RWorkspace.REFRESH_COMPLETE, monitor); } finally { if (current && progressService != null) { progressService.decrementBusy(); } } } } private class RefreshHandler extends ToolRetargetableHandler { private final ElementUpdater fUpdater = new ElementUpdater(IWorkbenchCommandConstants.FILE_REFRESH); public RefreshHandler() { super(ObjectBrowserView.this, ObjectBrowserView.this.getSite()); init(); } @Override protected Object doExecute(final ExecutionEvent event) { scheduleUpdateAll(); return null; } @Override protected void doRefresh() { super.doRefresh(); fUpdater.schedule(); } } private class FilterUserspaceHandler extends AbstractHandler implements IElementUpdater { @Override public Object execute(final ExecutionEvent event) throws ExecutionException { fFilterUserspace = !fFilterUserspace; fSettings.put(FILTER_USERSPACEONLY_SETTINGS_KEY, fFilterUserspace); fInputUpdater.forceUpdate(process); fInputUpdater.schedule(); return null; } @Override public void updateElement(final UIElement element, final Map parameters) { element.setChecked(fFilterUserspace); } } private class FilterInternalHandler extends AbstractHandler implements IElementUpdater { @Override public Object execute(final ExecutionEvent event) throws ExecutionException { fFilterIncludeInternal = !fFilterIncludeInternal; fSettings.put(FILTER_INTERNALINCLUDE_SETTINGS_KEY, fFilterIncludeInternal); updateFilter(); return null; } @Override public void updateElement(final UIElement element, final Map parameters) { element.setChecked(fFilterIncludeInternal); } } private class SortByTypeHandler extends AbstractHandler implements IElementUpdater { @Override public Object execute(final ExecutionEvent event) throws ExecutionException { fSortByType = !fSortByType; fSettings.put(SORT_BYTYPE_SETTINGS_KEY, fSortByType); updateSorter(); return null; } @Override public void updateElement(final UIElement element, final Map parameters) { element.setChecked(fSortByType); } } private class TreeElementSelection extends TreeSelectionProxy implements IElementNameProvider { public TreeElementSelection(final ITreeSelection selection) { super(selection); } @Override public IElementName getElementName(final Object selectionElement) { if (selectionElement instanceof TreePath) { return ObjectBrowserView.this.getElementName((TreePath) selectionElement); } return null; } } private class TreeSelectionProvider extends PostSelectionProviderProxy { public TreeSelectionProvider() { super(fTreeViewer); } @Override protected ISelection getSelection(final ISelection originalSelection) { return new TreeElementSelection((ITreeSelection) originalSelection); } } private class HoverManager extends ColumnHoverManager { HoverManager() { super(fTreeViewer, fTokenOwner, new RElementInfoHoverCreator()); final ColumnHoverStickyManager stickyManager = new ColumnHoverStickyManager(fTokenOwner, this); getInternalAccessor().setInformationControlReplacer(stickyManager); } @Override protected Object prepareHoverInformation(final ViewerCell cell) { final TreePath treePath = cell.getViewerRow().getTreePath(); final RElementName elementName = getElementName(treePath); if (elementName != null && elementName.getNamespace() != null) { return elementName; } return null; } @Override protected Object getHoverInformation(final Object element) { if (element instanceof RElementName && process != null) { final RElementInfoTask updater = new RElementInfoTask((RElementName) element); return updater.load(process, getSubjectControl()); } return null; } } private TreeViewer fTreeViewer; private TreeSelectionProvider fTreeSelectionProvider; private ColumnWidgetTokenOwner fTokenOwner; private Clipboard fClipboard; private StatusLineMessageManager statusLine; private IDialogSettings fSettings; final Object processLock = new Object(); private RProcess process; // note: we write only in ui thread private IToolRegistryListener fToolRegistryListener; private final FastList<IToolRetargetable> fToolListenerList = new FastList<IToolRetargetable>( IToolRetargetable.class); private final RefreshWorkspaceR fManualRefreshRunnable = new RefreshWorkspaceR(); private final ContentJob fInputUpdater = new ContentJob(this); private ContentProvider contentProvider; private boolean fFilterUserspace; private boolean fFilterIncludeInternal; private String fFilterText; private boolean fSortByType; private SearchContributionItem fSearchTextItem; private boolean fFilterUserspaceActivated; private CopyElementNameHandler fCopyElementNameHandler; private DeleteHandler fDeleteElementHandler; private PrintHandler fPrintElementHandler; private IHandler2 fOpenInEditorHandler; private Object fCurrentInfoObject; private ColumnHoverManager fHoveringController; private AbstractHandler fSearchStartHandler; private HandlerContributionItem fRefreshToolbarItem; private HandlerContributionItem fRefreshMenuItem; private boolean fRefreshDirtyIndicator; public ObjectBrowserView() { } @Override public void init(final IViewSite site, final IMemento memento) throws PartInitException { super.init(site, memento); this.statusLine = new StatusLineMessageManager(site.getActionBars().getStatusLineManager()); fSettings = DialogUtil.getDialogSettings(RUIPlugin.getDefault(), "ObjectBrowser"); fFilterUserspaceActivated = fFilterUserspace = fSettings.getBoolean(FILTER_USERSPACEONLY_SETTINGS_KEY); fFilterIncludeInternal = fSettings.getBoolean(FILTER_INTERNALINCLUDE_SETTINGS_KEY); fSortByType = fSettings.getBoolean(SORT_BYTYPE_SETTINGS_KEY); } @Override public void saveState(final IMemento memento) { super.saveState(memento); fSettings = DialogUtil.getDialogSettings(RUIPlugin.getDefault(), "ObjectBrowser"); } @Override public void createPartControl(final Composite parent) { parent.setLayout(LayoutUtil.applySashDefaults(new GridLayout(), 1)); fTreeViewer = new TreeViewer(parent, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI); fTreeViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 3)); fTreeViewer.setUseHashlookup(true); fTreeSelectionProvider = new TreeSelectionProvider(); fTreeViewer.setLabelProvider(new RLabelProvider(RLabelProvider.COUNT) { @Override protected String getEnvCountInfo(final ICombinedREnvironment envir) { final StringBuilder textBuilder = getTextBuilder(); textBuilder.append(" ("); //$NON-NLS-1$ final ContentInput input = ObjectBrowserView.this.contentProvider.getInput(); if (input != null && input.hasEnvFilter()) { final Object[] children = input.getEnvFilterChildren(envir); if (children != null) { textBuilder.append(children.length); } else { textBuilder.append('-'); } textBuilder.append('/'); } textBuilder.append(envir.getLength()); textBuilder.append(')'); return textBuilder.toString(); } }); fTreeViewer.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(final DoubleClickEvent event) { final IStructuredSelection selection = (IStructuredSelection) event.getSelection(); if (selection.size() != 1) { return; } final Object element = selection.getFirstElement(); if (element instanceof RObject) { final RObject object = (RObject) element; switch (object.getRObjectType()) { case RObject.TYPE_ENV: case RObject.TYPE_LIST: case RObject.TYPE_DATAFRAME: case RObject.TYPE_S4OBJECT: case RObject.TYPE_REFERENCE: fTreeViewer.setExpandedState(element, !fTreeViewer.getExpandedState(element)); } } } }); fTreeSelectionProvider.addPostSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(final SelectionChangedEvent event) { updateSelectionInfo((ITreeSelection) event.getSelection()); } }); this.contentProvider = new ContentProvider(); fTreeViewer.setContentProvider(this.contentProvider); updateSorter(); fTreeViewer.setInput(this); fTokenOwner = new ColumnWidgetTokenOwner(fTreeViewer); fHoveringController = new HoverManager(); fHoveringController.setSizeConstraints(100, 12, false, true); fHoveringController.install(fTreeViewer.getTree()); createActions(); hookContextMenu(); getSite().setSelectionProvider(fTreeSelectionProvider); final ViewerDragSupport dragSupport = new ViewerDragSupport(fTreeViewer); dragSupport.addDragSourceListener(new ViewerDragSupport.TextDragSourceListener(fTreeViewer)); dragSupport.init(); // listen on console changes final IToolRegistry toolRegistry = NicoUI.getToolRegistry(); fToolRegistryListener = new IToolRegistryListener() { @Override public void toolSessionActivated(final ToolSessionUIData sessionData) { final ToolProcess process = sessionData.getProcess(); UIAccess.getDisplay().syncExec(new Runnable() { @Override public void run() { connect(process); } }); } @Override public void toolTerminated(final ToolSessionUIData sessionData) { final ToolProcess process = sessionData.getProcess(); UIAccess.getDisplay().syncExec(new Runnable() { @Override public void run() { if (process == getTool()) { connect(null); } } }); } }; toolRegistry.addListener(fToolRegistryListener, getViewSite().getPage()); connect(toolRegistry.getActiveToolSession(getViewSite().getPage()).getProcess()); } TreeViewer getViewer() { return fTreeViewer; } private void createActions() { final IHandlerService handlerService = (IHandlerService) getSite().getService(IHandlerService.class); final IContextService contexts = (IContextService) getSite().getService(IContextService.class); contexts.activateContext("de.walware.ecommons.base.contexts.StructuredElementViewer"); //$NON-NLS-1$ final RefreshHandler refreshHandler = new RefreshHandler(); handlerService.activateHandler(IWorkbenchCommandConstants.FILE_REFRESH, refreshHandler); final CollapseAllHandler collapseAllHandler = new CollapseAllHandler(fTreeViewer); handlerService.activateHandler(CollapseAllHandler.COMMAND_ID, collapseAllHandler); fCopyElementNameHandler = new CopyElementNameHandler(this); handlerService.activateHandler(ISourceEditorCommandIds.COPY_ELEMENT_NAME, fCopyElementNameHandler); handlerService.activateHandler(IWorkbenchCommandConstants.EDIT_COPY, fCopyElementNameHandler); fDeleteElementHandler = new DeleteHandler(this); handlerService.activateHandler(IWorkbenchCommandConstants.EDIT_DELETE, fDeleteElementHandler); fPrintElementHandler = new PrintHandler(this); handlerService.activateHandler(RunPrintInR.COMMAND_ID, fPrintElementHandler); final InformationDispatchHandler infoHandler = new InformationDispatchHandler(fTokenOwner); handlerService.activateHandler(InformationDispatchHandler.COMMAND_ID, infoHandler); fOpenInEditorHandler = new OpenInEditorHandler(); handlerService.activateHandler(OPEN_COMMAND_ID, fOpenInEditorHandler); fSearchTextItem = new SearchContributionItem("search.text", //$NON-NLS-1$ SearchContributionItem.VIEW_TOOLBAR, true) { @Override protected void search() { fFilterText = getText(); updateFilter(); } }; fSearchTextItem.setToolTip("Filter Elements"); fSearchTextItem.setSizeControl(fTreeViewer.getControl().getParent()); fSearchTextItem.setResultControl(fTreeViewer.getTree()); fSearchStartHandler = new AbstractHandler() { @Override public Object execute(final ExecutionEvent arg0) { fSearchTextItem.show(); return null; } }; handlerService.activateHandler(IWorkbenchCommandConstants.EDIT_FIND_AND_REPLACE, fSearchStartHandler); // add next/previous handler final ToggleAutoRefreshHandler autoRefreshHandler = new ToggleAutoRefreshHandler(this); final IActionBars actionBars = getViewSite().getActionBars(); final IMenuManager viewMenu = actionBars.getMenuManager(); final IToolBarManager viewToolbar = actionBars.getToolBarManager(); viewMenu.add(new HandlerContributionItem(new CommandContributionItemParameter(getSite(), "Filter.OnlyUserspace", HandlerContributionItem.NO_COMMAND_ID, null, //$NON-NLS-1$ null, null, null, "Show non-&package Variables only", null, null, HandlerContributionItem.STYLE_CHECK, null, false), new FilterUserspaceHandler())); viewMenu.add(new HandlerContributionItem(new CommandContributionItemParameter(getSite(), "Filter.IncludeInternal", HandlerContributionItem.NO_COMMAND_ID, null, //$NON-NLS-1$ null, null, null, "Show &Internal Variables ('.*')", null, null, HandlerContributionItem.STYLE_CHECK, null, false), new FilterInternalHandler())); viewMenu.add(new HandlerContributionItem(new CommandContributionItemParameter(getSite(), "Sort.ByType", //$NON-NLS-1$ HandlerContributionItem.NO_COMMAND_ID, null, null, null, null, "Sort by &Type", null, null, HandlerContributionItem.STYLE_CHECK, null, false), new SortByTypeHandler())); viewMenu.add(new Separator()); final HandlerContributionItem autoRefreshItem = new HandlerContributionItem( new CommandContributionItemParameter(getSite(), null, HandlerContributionItem.NO_COMMAND_ID, null, null, null, null, "Refresh &automatically", null, null, HandlerContributionItem.STYLE_CHECK, null, false), autoRefreshHandler); viewMenu.add(autoRefreshItem); fRefreshMenuItem = new HandlerContributionItem( new CommandContributionItemParameter(getSite(), null, IWorkbenchCommandConstants.FILE_REFRESH, null, StatetImages.getDescriptor(StatetImages.TOOL_REFRESH), StatetImages.getDescriptor(StatetImages.TOOLD_REFRESH), null, "&Refresh", null, null, HandlerContributionItem.STYLE_PUSH, null, false), refreshHandler); viewMenu.add(fRefreshMenuItem); viewMenu.addMenuListener(new IMenuListener() { @Override public void menuAboutToShow(final IMenuManager manager) { autoRefreshItem.update(); } }); viewToolbar.add(fSearchTextItem); viewToolbar.add(new Separator()); fRefreshToolbarItem = new HandlerContributionItem(new CommandContributionItemParameter(getSite(), "Refresh", //$NON-NLS-1$ IWorkbenchCommandConstants.FILE_REFRESH, null, StatetImages.getDescriptor(StatetImages.TOOL_REFRESH), StatetImages.getDescriptor(StatetImages.TOOLD_REFRESH), null, null, null, null, HandlerContributionItem.STYLE_PUSH, null, false), refreshHandler); fRefreshToolbarItem.setVisible(false); viewToolbar.add(fRefreshToolbarItem); viewToolbar.add(new HandlerContributionItem( new CommandContributionItemParameter(getSite(), "Collapse.All", CollapseAllHandler.COMMAND_ID, null, //$NON-NLS-1$ null, null, null, null, null, null, HandlerContributionItem.STYLE_PUSH, null, false), collapseAllHandler)); } void updateAutoRefresh(final boolean enabled) { if (this.process == null || this.process.isTerminated()) { return; } if (enabled) { updateDirty(false); } else { updateDirty(this.process.getWorkspaceData().isROBjectDBDirty()); } if (fRefreshToolbarItem.isVisible() != enabled) { return; } fRefreshToolbarItem.setVisible(!enabled); final IContributionManager manager = fRefreshToolbarItem.getParent(); manager.update(true); fSearchTextItem.resize(); } void updateDirty(final boolean enabled) { if (fRefreshDirtyIndicator == enabled) { return; } final ImageDescriptor icon = (enabled) ? RUIPlugin.getDefault().getImageRegistry().getDescriptor(RUIPlugin.IMG_LOCTOOL_REFRESH_RECOMMENDED) : StatetImages.getDescriptor(StatetImages.TOOL_REFRESH); fRefreshToolbarItem.setIcon(icon); fRefreshMenuItem.setIcon(icon); fRefreshDirtyIndicator = enabled; } private void hookContextMenu() { final MenuManager menuManager = new MenuManager("ContextMenu", //$NON-NLS-1$ "de.walware.statet.r.menus.RObjectBrowserContextMenu"); //$NON-NLS-1$ menuManager.setRemoveAllWhenShown(true); menuManager.addMenuListener(new IMenuListener() { @Override public void menuAboutToShow(final IMenuManager m) { contextMenuAboutToShow(m); } }); final Menu contextMenu = menuManager.createContextMenu(fTreeViewer.getTree()); fTreeViewer.getTree().setMenu(contextMenu); getSite().registerContextMenu(menuManager, fTreeViewer); } private void contextMenuAboutToShow(final IMenuManager m) { m.add(new HandlerContributionItem( new CommandContributionItemParameter(getSite(), null, OPEN_COMMAND_ID, null, null, null, null, "Open in Data &Viewer", null, null, HandlerContributionItem.STYLE_PUSH, null, true), fOpenInEditorHandler)); m.add(new Separator("edit")); m.add(new HandlerContributionItem( new CommandContributionItemParameter(getSite(), "Copy.ElementName", //$NON-NLS-1$ ISourceEditorCommandIds.COPY_ELEMENT_NAME, null, null, null, null, null, null, null, HandlerContributionItem.STYLE_PUSH, null, false), fCopyElementNameHandler)); m.add(new HandlerContributionItem( new CommandContributionItemParameter(getSite(), "Delete", IWorkbenchCommandConstants.EDIT_DELETE, //$NON-NLS-1$ null, null, null, null, null, null, null, HandlerContributionItem.STYLE_PUSH, null, false), fDeleteElementHandler)); m.add(new Separator()); m.add(new HandlerContributionItem( new CommandContributionItemParameter(getSite(), null, RunPrintInR.COMMAND_ID, null, null, null, null, null, null, null, HandlerContributionItem.STYLE_PUSH, null, false), fPrintElementHandler)); m.add(new Separator(SharedUIResources.ADDITIONS_MENU_ID)); } /** May only be called in UI thread */ public void connect(final ToolProcess tool) { if (this.process == tool) { return; } final RProcess oldProcess = this.process; if (oldProcess != null) { oldProcess.getWorkspaceData().removePropertyListener(fInputUpdater); } synchronized (this.processLock) { this.process = (RProcess) ((tool != null && tool.isProvidingFeatureSet(RConsoleTool.R_DATA_FEATURESET_ID)) ? tool : null); } if (fHoveringController != null) { fHoveringController.stop(); } if (oldProcess != null) { clearInfo(); oldProcess.getQueue().remove(new IToolRunnable[] { fManualRefreshRunnable }); } if (!UIAccess.isOkToUse(fTreeViewer)) { return; } for (final IToolRetargetable listener : fToolListenerList.toArray()) { listener.setTool(this.process); } fInputUpdater.forceUpdate(this.process); if (this.process != null) { this.process.getWorkspaceData().addPropertyListener(fInputUpdater); updateAutoRefresh(this.process.getWorkspaceData().isAutoRefreshEnabled()); } fInputUpdater.schedule(); } @Override public RProcess getTool() { return process; } public ITreeSelection getSelection() { return (ITreeSelection) fTreeViewer.getSelection(); } public boolean getShowInternal() { return fFilterIncludeInternal; } public boolean getShowConsenseUserspace() { return fFilterUserspace; } public String getSearchText() { return fFilterText; } @Override public void addToolRetargetable(final IToolRetargetable action) { fToolListenerList.add(action); } @Override public void removeToolRetargetable(final IToolRetargetable action) { fToolListenerList.remove(action); } @Override public Object getAdapter(final Class required) { if (required.equals(ITool.class)) { return process; } return super.getAdapter(required); } private void scheduleUpdateAll() { if (process != null) { process.getQueue().add(fManualRefreshRunnable); } } /** May only be called in UI thread (called by update job) */ void updateViewer(final List<ICombinedREnvironment> updateEnvirs, final ContentInput input) { if (!UIAccess.isOkToUse(fTreeViewer)) { return; } fHoveringController.stop(); this.contentProvider.setInput(input); final boolean changed = input.processChanged; ISelection selection = null; if (changed) { input.processChanged = false; } /*else*/ if (input.showCondensedUserspace != fFilterUserspaceActivated) { // If filter is changed, we have to retain the selection manually selection = fTreeViewer.getSelection(); } fFilterUserspaceActivated = input.showCondensedUserspace; final Set<RReference> previousReferences = this.contentProvider.resetUsedReferences(); if (updateEnvirs != null) { for (final ICombinedREnvironment entry : updateEnvirs) { fTreeViewer.refresh(entry, true); } if (!previousReferences.isEmpty()) { final Set<RReference> usedReferences = this.contentProvider.getUsedReferences(); ITER_REFS: for (final RReference reference : previousReferences) { if (!usedReferences.contains(reference)) { // Update the envir copy in the viewer, if it refers to an updated envir for (final ICombinedREnvironment entry : updateEnvirs) { if (entry.getHandle() == reference.getHandle()) { fTreeViewer.refresh(reference, true); // reference is readded automatically to new set, if necessary continue ITER_REFS; } } // Keep/readd the reference, if it refers to an envir in the search path for (final ICombinedREnvironment entry : input.searchEnvirs) { if (entry.getHandle() == reference.getHandle()) { usedReferences.add(reference); continue ITER_REFS; } } } } } } else { fTreeViewer.refresh(true); } // Adapt and set selection if (selection != null && !selection.isEmpty()) { final ITreeSelection s = (ITreeSelection) selection; TreePath[] paths = s.getPaths(); int j = 0; for (int i = 0; i < paths.length; i++) { final TreePath oldPath = paths[i]; final int count = oldPath.getSegmentCount(); final int shift = (input.showCondensedUserspace) ? -1 : +1; if (count + shift < 1) { continue; } final Object[] newPath = new Object[count + shift]; for (int k = (shift == -1) ? +1 : 0; k < count; k++) { newPath[k + shift] = oldPath.getSegment(k); } if (shift == +1) { newPath[0] = ContentProvider.getCombinedRElement(newPath[1]).getModelParent(); } paths[j++] = new TreePath(newPath); } fTreeViewer.setSelection(new TreeSelection((j < paths.length) ? Arrays.copyOf(paths, j) : paths), true); } // Expand Global_Env, if it is a new process and has valid input EXPAND_GLOBALENV: if (changed && !input.showCondensedUserspace && input.rootElements != null && input.rootElements.length > 0) { for (Object element : input.rootElements) { if (fTreeViewer.getExpandedState(element)) { break EXPAND_GLOBALENV; } } fTreeViewer.expandToLevel(new TreePath(new Object[] { input.rootElements[0] }), 1); } } private void updateFilter() { fInputUpdater.schedule(); } private void updateSorter() { fTreeViewer.setComparator(fSortByType ? TYPE_COMPARATOR : null); } private void updateSelectionInfo(final ITreeSelection selection) { final Object previousInfoObject = fCurrentInfoObject; fCurrentInfoObject = null; final RProcess tool = getTool(); if (tool == null) { return; } if (selection.size() == 1) { fCurrentInfoObject = selection.getFirstElement(); final TreePath treePath = selection.getPaths()[0]; final IElementName elementName = getElementName(treePath); final String name = (elementName != null) ? elementName.getDisplayName() : null; if (name != null) { if (fCurrentInfoObject.equals(previousInfoObject)) { clearInfo(); } this.statusLine.setSelectionMessage(new StatusInfo(IStatus.OK, NLS.bind("{0} \u2012 {1}", name, tool.getLabel(ITool.DEFAULT_LABEL)))); //$NON-NLS-1$ return; } } clearInfo(); if (selection.size() > 1) { this.statusLine.setSelectionMessage( new StatusInfo(IStatus.OK, NLS.bind("{0} items selected", selection.size()))); return; } this.statusLine.setSelectionMessage(null); } private void clearInfo() { } /** * Returns a shared clipboard resource, which can be used by actions of this view. * * @return a clipboard object. */ Clipboard getClipboard() { if (fClipboard == null) { fClipboard = new Clipboard(Display.getCurrent()); } return fClipboard; } StatusLineMessageManager getStatusLine() { return this.statusLine; } @Override public void setFocus() { fTreeViewer.getControl().setFocus(); } @Override public void dispose() { if (fToolRegistryListener != null) { NicoUI.getToolRegistry().removeListener(fToolRegistryListener); fToolRegistryListener = null; } if (this.process != null) { this.process.getWorkspaceData().removePropertyListener(fInputUpdater); this.process.getQueue().remove(new IToolRunnable[] { fManualRefreshRunnable }); } fInputUpdater.cancel(); if (fHoveringController != null) { fHoveringController.dispose(); fHoveringController = null; } if (fSearchStartHandler != null) { fSearchStartHandler.dispose(); fSearchStartHandler = null; } if (fCopyElementNameHandler != null) { fCopyElementNameHandler.dispose(); fCopyElementNameHandler = null; } if (fPrintElementHandler != null) { fPrintElementHandler.dispose(); fPrintElementHandler = null; } for (final IToolRetargetable listener : fToolListenerList.toArray()) { listener.setTool(null); } super.dispose(); if (fClipboard != null) { fClipboard.dispose(); fClipboard = null; } } public RElementName getElementName(final TreePath treePath) { if (treePath.getSegmentCount() == 0) { return null; } int segmentIdx = 0; if (!fFilterUserspaceActivated) { if (treePath.getSegmentCount() == 1) { // search path item return ContentProvider.getCombinedRElement(treePath.getFirstSegment()).getElementName(); } else { // main name at 1 segmentIdx = 1; } } final List<RElementName> names = new ArrayList<RElementName>(treePath.getSegmentCount() - segmentIdx + 1); final ICombinedRElement first = ContentProvider.getCombinedRElement(treePath.getSegment(segmentIdx++)); names.add(first.getModelParent().getElementName()); names.add(first.getElementName()); while (segmentIdx < treePath.getSegmentCount()) { final Object object = treePath.getSegment(segmentIdx++); if (object instanceof IElementPartition) { continue; } final ICombinedRElement rElement = ContentProvider.getCombinedRElement(object); names.add(rElement.getElementName()); } return RElementName.concat(new ConstArrayList<RElementName>(names)); } }