| /*=============================================================================# |
| # Copyright (c) 2010, 2017 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.r.console.ui.tools; |
| |
| import static org.eclipse.statet.r.launching.RRunDebugPreferenceConstants.ASK; |
| import static org.eclipse.statet.r.launching.RRunDebugPreferenceConstants.AUTO; |
| import static org.eclipse.statet.r.launching.RRunDebugPreferenceConstants.DISABLED; |
| import static org.eclipse.statet.r.launching.RRunDebugPreferenceConstants.PREF_RENV_CHECK_UPDATE; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| |
| 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.core.runtime.preferences.InstanceScope; |
| import org.eclipse.jface.dialogs.IDialogConstants; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.events.SelectionListener; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.ui.statushandlers.StatusManager; |
| |
| import org.eclipse.statet.ecommons.preferences.core.util.PreferenceUtils; |
| import org.eclipse.statet.ecommons.ts.core.SystemRunnable; |
| import org.eclipse.statet.ecommons.ts.core.Tool; |
| import org.eclipse.statet.ecommons.ts.core.ToolService; |
| import org.eclipse.statet.ecommons.ui.util.LayoutUtil; |
| import org.eclipse.statet.ecommons.ui.util.UIAccess; |
| |
| import org.eclipse.statet.internal.r.console.ui.Messages; |
| import org.eclipse.statet.internal.r.console.ui.RConsoleUIPlugin; |
| import org.eclipse.statet.nico.core.runtime.ToolProcess; |
| import org.eclipse.statet.nico.ui.util.ToolMessageDialog; |
| import org.eclipse.statet.r.console.core.AbstractRDataRunnable; |
| import org.eclipse.statet.r.console.core.IRDataAdapter; |
| import org.eclipse.statet.r.console.core.RConsoleTool; |
| import org.eclipse.statet.r.console.core.RProcess; |
| import org.eclipse.statet.r.core.RCore; |
| import org.eclipse.statet.r.core.pkgmanager.IRPkgChangeSet; |
| import org.eclipse.statet.r.core.pkgmanager.IRPkgManager; |
| import org.eclipse.statet.r.core.pkgmanager.IRPkgManager.Event; |
| import org.eclipse.statet.r.core.renv.IREnvConfiguration; |
| import org.eclipse.statet.r.core.rhelp.rj.RJREnvIndexChecker; |
| import org.eclipse.statet.r.core.rhelp.rj.RJREnvIndexUpdater; |
| import org.eclipse.statet.r.nico.impl.RjsController; |
| |
| |
| public class REnvIndexAutoUpdater { |
| |
| |
| public static void connect(final RProcess process, final IRPkgManager manager) { |
| final IREnvConfiguration rEnvConfig= process |
| .getAdapter(IREnvConfiguration.class); |
| if (rEnvConfig != null) { |
| final CheckRunnable checker= new CheckRunnable(process, manager, |
| new RJREnvIndexChecker(rEnvConfig) ); |
| process.getQueue().addOnIdle(checker, 1100); |
| return; |
| } |
| } |
| |
| |
| public static final class UpdateRunnable extends AbstractRDataRunnable { |
| |
| |
| private final boolean completely; |
| |
| |
| public UpdateRunnable(final boolean completely) { |
| super("r/index/update", Messages.REnvIndex_Update_task); //$NON-NLS-1$ |
| this.completely= completely; |
| } |
| |
| |
| @Override |
| public boolean changed(final int event, final Tool tool) { |
| if (event == MOVING_FROM) { |
| return false; |
| } |
| return true; |
| } |
| |
| @Override |
| protected void run(final IRDataAdapter r, |
| final IProgressMonitor monitor) throws CoreException { |
| IREnvConfiguration rEnvConfig= r.getTool().getAdapter(IREnvConfiguration.class); |
| if (rEnvConfig != null) { |
| rEnvConfig= rEnvConfig.getReference().getConfig(); |
| if (rEnvConfig != null) { |
| final String remoteAddress= r.getWorkspaceData().getRemoteAddress(); |
| final Map<String, String> properties= new HashMap<>(); |
| if (remoteAddress != null) { |
| properties.put("renv.hostname", remoteAddress); //$NON-NLS-1$ |
| } |
| |
| final IRPkgManager rPkgManager= RCore.getRPkgManager(rEnvConfig.getReference()); |
| rPkgManager.check(IRPkgManager.NONE, r, monitor); |
| |
| r.handleStatus(new Status(IStatus.INFO, RConsoleUIPlugin.BUNDLE_ID, -1, |
| Messages.REnvIndex_Update_Started_message, null ), monitor); |
| final RJREnvIndexUpdater updater= new RJREnvIndexUpdater(rEnvConfig); |
| final IStatus status= updater.update(r, this.completely, properties, monitor); |
| r.handleStatus(status, monitor); |
| } |
| } |
| } |
| } |
| |
| |
| private static class AskDialog extends ToolMessageDialog { |
| |
| |
| private Button rememberSessionControl; |
| private Button rememberGloballyControl; |
| |
| private boolean rememberSession; |
| private boolean rememberGlobally; |
| |
| |
| public AskDialog(final ToolProcess tool, final String message) { |
| super(tool, null, Messages.REnvIndex_CheckDialog_title, null, message, QUESTION, |
| new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL }, 0); |
| } |
| |
| |
| @Override |
| protected Control createMessageArea(final Composite parent) { |
| super.createMessageArea(parent); |
| |
| LayoutUtil.addGDDummy(parent); |
| final Composite composite= new Composite(parent, SWT.NONE); |
| composite.setLayout(LayoutUtil.createCompositeGrid(1)); |
| |
| { final Label label= new Label(composite, SWT.NONE); |
| label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); |
| label.setText(Messages.REnvIndex_CheckDialog_Remember_label); |
| } |
| { final Button button= new Button(composite, SWT.CHECK); |
| final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, false); |
| gd.horizontalIndent= LayoutUtil.defaultIndent(); |
| button.setLayoutData(gd); |
| button.setText(Messages.REnvIndex_CheckDialog_RememberSession_label); |
| this.rememberSessionControl= button; |
| } |
| { final Button button= new Button(composite, SWT.CHECK); |
| final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, false); |
| gd.horizontalIndent= LayoutUtil.defaultIndent(); |
| button.setLayoutData(gd); |
| button.setText(Messages.REnvIndex_CheckDialog_RememberGlobally_label); |
| this.rememberGloballyControl= button; |
| } |
| |
| this.rememberGloballyControl.addSelectionListener(new SelectionListener() { |
| @Override |
| public void widgetSelected(final SelectionEvent e) { |
| if (AskDialog.this.rememberGloballyControl.getSelection()) { |
| AskDialog.this.rememberSessionControl.setSelection(false); |
| } |
| } |
| @Override |
| public void widgetDefaultSelected(final SelectionEvent e) { |
| } |
| }); |
| this.rememberSessionControl.addSelectionListener(new SelectionListener() { |
| @Override |
| public void widgetSelected(final SelectionEvent e) { |
| if (AskDialog.this.rememberSessionControl.getSelection()) { |
| AskDialog.this.rememberGloballyControl.setSelection(false); |
| } |
| } |
| @Override |
| public void widgetDefaultSelected(final SelectionEvent e) { |
| } |
| }); |
| |
| return composite; |
| } |
| |
| |
| @Override |
| public boolean close() { |
| this.rememberGlobally= this.rememberGloballyControl.getSelection(); |
| this.rememberSession= this.rememberSessionControl.getSelection(); |
| |
| return super.close(); |
| } |
| |
| } |
| |
| private static class CheckRunnable implements SystemRunnable, IRPkgManager.Listener { |
| |
| |
| private final RProcess process; |
| |
| private final RJREnvIndexChecker checker; |
| |
| private final IRPkgManager manager; |
| private boolean changed; |
| |
| private String sessionSetting; |
| |
| |
| public CheckRunnable(final RProcess process, final IRPkgManager manager, final RJREnvIndexChecker checker) { |
| this.process= process; |
| this.manager= manager; |
| this.changed= true; |
| this.checker= checker; |
| |
| this.manager.addListener(this); |
| } |
| |
| |
| @Override |
| public String getTypeId() { |
| return "r/index/check"; //$NON-NLS-1$ |
| } |
| |
| @Override |
| public String getLabel() { |
| return Messages.REnvIndex_Check_task; |
| } |
| |
| @Override |
| public boolean canRunIn(final Tool tool) { |
| return (tool.isProvidingFeatureSet(RConsoleTool.R_DATA_FEATURESET_ID)); |
| } |
| |
| @Override |
| public boolean changed(final int event, final Tool tool) { |
| if (event == MOVING_FROM) { |
| return false; |
| } |
| if (event == BEING_ABANDONED) { |
| this.manager.removeListener(this); |
| } |
| return true; |
| } |
| |
| @Override |
| public void handleChange(final Event event) { |
| if ((event.pkgsChanged() & IRPkgManager.INSTALLED) != 0) { |
| final IRPkgChangeSet changeSet= event.getInstalledPkgChangeSet(); |
| if (changeSet != null && !changeSet.getNames().isEmpty()) { |
| this.changed= true; |
| } |
| } |
| } |
| |
| @Override |
| public void run(final ToolService service, |
| final IProgressMonitor monitor) throws CoreException { |
| final RjsController r= (RjsController) service; // interface? |
| if (r.isBusy() || !r.isDefaultPrompt() || !this.changed ) { |
| return; |
| } |
| this.changed= false; |
| try { |
| final String global= PreferenceUtils.getInstancePrefs().getPreferenceValue(PREF_RENV_CHECK_UPDATE).intern(); |
| |
| if (global == DISABLED |
| || (global == ASK && this.sessionSetting == DISABLED) ) { |
| return; |
| } |
| final int check= this.checker.check(r, monitor); |
| final String message; |
| |
| if (this.checker.wasAlreadyReported()) { |
| return; |
| } |
| switch (check) { |
| case RJREnvIndexChecker.NOT_AVAILABLE: |
| case RJREnvIndexChecker.UP_TO_DATE: |
| return; |
| case RJREnvIndexChecker.PACKAGES: |
| message= NLS.bind(((this.checker.getNewPackageCount() + this.checker.getChangedPackageCount()) == 1) ? |
| Messages.REnvIndex_Check_Changed_singular_message : |
| Messages.REnvIndex_Check_Changed_plural_message, |
| this.checker.getNewPackageCount(), this.checker.getChangedPackageCount()); |
| break; |
| case RJREnvIndexChecker.COMPLETE: |
| message= Messages.REnvIndex_Check_NoIndex_message; |
| break; |
| default: |
| return; |
| } |
| |
| if (global != AUTO && this.sessionSetting == null) { |
| final AtomicBoolean update= new AtomicBoolean(); |
| UIAccess.getDisplay().syncExec(new Runnable() { |
| @Override |
| public void run() { |
| final AskDialog dialog= new AskDialog(CheckRunnable.this.process, message); |
| update.set(dialog.open() == 0); |
| if (dialog.rememberGlobally) { |
| PreferenceUtils.setPrefValue(InstanceScope.INSTANCE, |
| PREF_RENV_CHECK_UPDATE, update.get() ? AUTO : DISABLED); |
| } |
| else if (dialog.rememberSession) { |
| CheckRunnable.this.sessionSetting= update.get() ? AUTO : DISABLED; |
| } |
| } |
| }); |
| if (!update.get()) { |
| return; |
| } |
| } |
| |
| // schedule update |
| service.getTool().getQueue().add(new UpdateRunnable(false)); |
| } |
| catch (final CoreException e) { |
| if (e.getStatus().getSeverity() == IStatus.CANCEL) { |
| throw e; |
| } |
| StatusManager.getManager().handle(new Status(IStatus.ERROR, RConsoleUIPlugin.BUNDLE_ID, -1, |
| Messages.REnvIndex_Check_error_message, e )); |
| } |
| } |
| } |
| |
| |
| } |