| /*=============================================================================# |
| # Copyright (c) 2010, 2019 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.internal.r.ui.dataeditor; |
| |
| 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.core.runtime.Status; |
| import org.eclipse.jface.action.IContributionItem; |
| import org.eclipse.jface.action.IStatusLineManager; |
| import org.eclipse.jface.action.StatusLineContributionItem; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.ui.IEditorInput; |
| import org.eclipse.ui.IEditorSite; |
| import org.eclipse.ui.IPartListener; |
| import org.eclipse.ui.IWorkbenchCommandConstants; |
| import org.eclipse.ui.IWorkbenchPart; |
| import org.eclipse.ui.IWorkbenchPartSite; |
| import org.eclipse.ui.PartInitException; |
| import org.eclipse.ui.handlers.IHandlerService; |
| import org.eclipse.ui.part.EditorPart; |
| import org.eclipse.ui.services.IServiceLocator; |
| import org.eclipse.ui.statushandlers.StatusManager; |
| import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; |
| import org.eclipse.ui.views.contentoutline.IContentOutlinePage; |
| |
| import org.eclipse.statet.ecommons.ui.workbench.ContextHandlers; |
| import org.eclipse.statet.ecommons.ui.workbench.WorkbenchUIUtils; |
| |
| import org.eclipse.statet.base.ui.contentfilter.IFilterPage; |
| import org.eclipse.statet.internal.r.ui.datafilterview.RDataFilterPage; |
| import org.eclipse.statet.r.ui.RUI; |
| import org.eclipse.statet.r.ui.dataeditor.IRDataEditorInput; |
| import org.eclipse.statet.r.ui.dataeditor.IRDataTableCallbacks; |
| import org.eclipse.statet.r.ui.dataeditor.IRDataTableInput; |
| import org.eclipse.statet.r.ui.dataeditor.RDataTableComposite; |
| import org.eclipse.statet.r.ui.dataeditor.RDataTableSelection; |
| import org.eclipse.statet.r.ui.dataeditor.RLiveDataEditorInput; |
| |
| |
| public class RDataEditor extends EditorPart { // INavigationLocationProvider ? |
| |
| |
| private class ActivationListener implements IPartListener { |
| |
| @Override |
| public void partActivated(final IWorkbenchPart part) { |
| if (part == RDataEditor.this) { |
| updateStatusLine(); |
| } |
| } |
| |
| @Override |
| public void partBroughtToTop(final IWorkbenchPart part) { |
| } |
| |
| @Override |
| public void partClosed(final IWorkbenchPart part) { |
| } |
| |
| @Override |
| public void partOpened(final IWorkbenchPart part) { |
| } |
| |
| @Override |
| public void partDeactivated(final IWorkbenchPart part) { |
| } |
| |
| } |
| |
| private class Callbacks implements IRDataTableCallbacks { |
| |
| |
| @Override |
| public boolean isCloseSupported() { |
| return true; |
| } |
| |
| @Override |
| public void close() { |
| RDataEditor.this.close(false); |
| } |
| |
| @Override |
| public IServiceLocator getServiceLocator() { |
| return getSite(); |
| } |
| |
| @Override |
| public void show(final IStatus status) { |
| StatusManager.getManager().handle(status); |
| } |
| |
| } |
| |
| |
| private RDataTableComposite table; |
| |
| private ContextHandlers handlers; |
| |
| private final ActivationListener activationListener= new ActivationListener(); |
| |
| private RDataEditorOutlinePage outlinePage; |
| |
| private RDataFilterPage filterPage; |
| |
| private final IRDataTableInput.StateListener inputStateListener= new IRDataTableInput.StateListener() { |
| @Override |
| public void tableUnavailable() { |
| close(false); |
| } |
| }; |
| |
| |
| public RDataEditor() { |
| } |
| |
| |
| @Override |
| public void init(final IEditorSite site, final IEditorInput input) throws PartInitException { |
| setSite(site); |
| |
| try { |
| doSetInput(input); |
| } |
| catch (final CoreException e) { |
| throw new PartInitException("The R data editor could not be initialized."); |
| } |
| } |
| |
| @Override |
| public void dispose() { |
| getEditorSite().getWorkbenchWindow().getPartService().removePartListener(this.activationListener); |
| if (this.handlers != null) { |
| this.handlers.dispose(); |
| this.handlers= null; |
| } |
| |
| disposeTableInput(); |
| |
| super.dispose(); |
| } |
| |
| |
| @Override |
| protected void setInput(final IEditorInput input) { |
| setInputWithNotify(input); |
| } |
| |
| @Override |
| protected void setInputWithNotify(final IEditorInput input) { |
| try { |
| doSetInput(input); |
| firePropertyChange(PROP_INPUT); |
| } |
| catch (final CoreException e) { |
| StatusManager.getManager().handle(new Status( |
| IStatus.ERROR, RUI.BUNDLE_ID, "An error occurred when opening the element.", e)); |
| } |
| } |
| |
| protected void doSetInput(final IEditorInput input) throws CoreException { |
| if (input == null) { |
| throw new NullPointerException("input"); |
| } |
| if (!(input instanceof RLiveDataEditorInput)) { |
| throw new CoreException(new Status(IStatus.ERROR, RUI.BUNDLE_ID, -1, |
| NLS.bind("The element ''{0}'' is not supported by the R data editor.", input.getName()), null)); |
| } |
| |
| super.setInput(input); |
| |
| setPartName(input.getName()); |
| setTitleToolTip(input.getToolTipText()); |
| } |
| |
| public RDataTableComposite getRDataTable() { |
| return this.table; |
| } |
| |
| |
| @Override |
| public boolean isDirty() { |
| return false; |
| } |
| |
| @Override |
| public void doSave(final IProgressMonitor monitor) { |
| } |
| |
| @Override |
| public boolean isSaveAsAllowed() { |
| return false; |
| } |
| |
| @Override |
| public void doSaveAs() { |
| } |
| |
| |
| @Override |
| public void createPartControl(final Composite parent) { |
| this.table= new RDataTableComposite(parent, new Callbacks()); |
| getEditorSite().getWorkbenchWindow().getPartService().addPartListener(this.activationListener); |
| |
| final IWorkbenchPartSite site= getSite(); |
| initActions(site, |
| this.handlers= new ContextHandlers(site.getService(IHandlerService.class)) ); |
| |
| initStatusLine(); |
| initTableInput(); |
| } |
| |
| private void initTableInput() { |
| final IRDataEditorInput editorInput= (IRDataEditorInput) getEditorInput(); |
| if (editorInput != null) { |
| final IRDataTableInput tableInput= editorInput.getRDataTableInput(); |
| if (tableInput != null) { |
| tableInput.addStateListener(this.inputStateListener); |
| if (tableInput.isAvailable()) { |
| this.table.setInput(tableInput); |
| } |
| else { |
| close(false); |
| } |
| } |
| } |
| } |
| |
| private void disposeTableInput() { |
| final IRDataEditorInput editorInput= (IRDataEditorInput) getEditorInput(); |
| if (editorInput != null) { |
| final IRDataTableInput tableInput= editorInput.getRDataTableInput(); |
| if (tableInput != null) { |
| tableInput.removeStateListener(this.inputStateListener); |
| } |
| } |
| } |
| |
| protected void initActions(final IServiceLocator serviceLocator, final ContextHandlers handlers) { |
| WorkbenchUIUtils.activateContext(serviceLocator, "org.eclipse.statet.r.contexts.RDataEditor"); //$NON-NLS-1$ |
| |
| { final IHandler2 handler= new RefreshHandler(this.table); |
| handlers.addActivate(IWorkbenchCommandConstants.FILE_REFRESH, handler); |
| } |
| { final IHandler2 handler= new SelectAllHandler(this.table); |
| handlers.addActivate(IWorkbenchCommandConstants.EDIT_SELECT_ALL, handler); |
| } |
| { final IHandler2 handler= new CopyDataHandler(this.table); |
| handlers.addActivate(IWorkbenchCommandConstants.EDIT_COPY, handler); |
| } |
| { final IHandler2 handler= new FindDialogHandler(this); |
| handlers.addActivate(IWorkbenchCommandConstants.EDIT_FIND_AND_REPLACE, handler); |
| } |
| { final IHandler2 handler= new GotoCellHandler(this.table); |
| handlers.addActivate(ITextEditorActionDefinitionIds.LINE_GOTO, handler); |
| } |
| } |
| |
| protected void initStatusLine() { |
| this.table.addSelectionChangedListener(new ISelectionChangedListener() { |
| @Override |
| public void selectionChanged(final SelectionChangedEvent event) { |
| final IStatusLineManager manager= getEditorSite().getActionBars().getStatusLineManager(); |
| final RDataTableSelection selection= (RDataTableSelection) event.getSelection(); |
| updateStatusLine(); |
| if (selection.getAnchorRowLabel() != null) { |
| final StringBuilder sb= new StringBuilder(); |
| sb.append(selection.getAnchorRowLabel()); |
| if (!selection.getAnchorRowLabel().isEmpty() |
| && !selection.getAnchorColumnLabel().isEmpty()) { |
| sb.append(", "); |
| } |
| sb.append(selection.getAnchorColumnLabel()); |
| if (selection.getLastSelectedCellRowLabel() != null) { |
| sb.append(" ("); |
| sb.append(selection.getLastSelectedCellRowLabel()); |
| if (!selection.getLastSelectedCellRowLabel().isEmpty() |
| && !selection.getLastSelectedCellColumnLabel().isEmpty()) { |
| sb.append(", "); |
| } |
| sb.append(selection.getLastSelectedCellColumnLabel()); |
| sb.append(")"); |
| } |
| manager.setMessage(sb.toString()); |
| } |
| else { |
| manager.setMessage(null); |
| } |
| } |
| }); |
| } |
| |
| private void updateStatusLine() { |
| final IStatusLineManager manager= getEditorSite().getActionBars().getStatusLineManager(); |
| final IContributionItem dimItem= manager.find("data.dimension"); |
| final long[] dimension= this.table.getTableDimension(); |
| if (dimItem != null) { |
| ((StatusLineContributionItem) dimItem).setText((dimension != null) ? |
| ("Dim: " + dimension[0] + " × " + dimension[1]) : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| } |
| |
| @Override |
| public void setFocus() { |
| this.table.setFocus(); |
| } |
| |
| public void close(final boolean save) { |
| final Display display= getSite().getShell().getDisplay(); |
| display.asyncExec(new Runnable() { |
| @Override |
| public void run() { |
| getSite().getPage().closeEditor(RDataEditor.this, save); |
| } |
| }); |
| } |
| |
| |
| protected RDataEditorOutlinePage createOutlinePage() { |
| return new RDataEditorOutlinePage(this); |
| } |
| |
| protected RDataFilterPage createFilterPage() { |
| return new RDataFilterPage(this); |
| } |
| |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| public <T> T getAdapter(final Class<T> adapterType) { |
| if (adapterType == RDataTableComposite.class) { |
| return (T) this.table; |
| } |
| if (adapterType == IContentOutlinePage.class) { |
| if (this.outlinePage == null) { |
| this.outlinePage= createOutlinePage(); |
| } |
| return (T) this.outlinePage; |
| } |
| if (adapterType == IFilterPage.class) { |
| if (this.filterPage == null) { |
| this.filterPage= createFilterPage(); |
| } |
| return (T) this.filterPage; |
| } |
| return super.getAdapter(adapterType); |
| } |
| |
| } |