| /******************************************************************************* |
| * Copyright (c) 2007, 2018 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Johannes Michler <orgler@gmail.com> - Bug 321568 - [ui] Preference for automatic-update-reminder doesn't work in multilanguage-environments |
| *******************************************************************************/ |
| package org.eclipse.equinox.internal.p2.ui.sdk.scheduler; |
| |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.jface.dialogs.IDialogSettings; |
| import org.eclipse.jface.dialogs.PopupDialog; |
| import org.eclipse.jface.layout.GridDataFactory; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.preference.PreferenceDialog; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.MouseListener; |
| import org.eclipse.swt.events.SelectionListener; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.*; |
| import org.eclipse.ui.dialogs.PreferencesUtil; |
| import org.eclipse.ui.progress.WorkbenchJob; |
| |
| /** |
| * AutomaticUpdatesPopup is an async popup dialog for notifying the user of |
| * updates. |
| * |
| * @since 3.4 |
| */ |
| public class AutomaticUpdatesPopup extends PopupDialog { |
| public static final String[] ELAPSED_VALUES = { PreferenceConstants.PREF_REMIND_30Minutes, |
| PreferenceConstants.PREF_REMIND_60Minutes, PreferenceConstants.PREF_REMIND_240Minutes }; |
| public static final String[] ELAPSED_LOCALIZED_STRINGS = { |
| AutomaticUpdateMessages.AutomaticUpdateScheduler_30Minutes, |
| AutomaticUpdateMessages.AutomaticUpdateScheduler_60Minutes, |
| AutomaticUpdateMessages.AutomaticUpdateScheduler_240Minutes }; |
| private static final long MINUTE = 60 * 1000L; |
| private static final String PREFS_HREF = "PREFS"; //$NON-NLS-1$ |
| private static final String DIALOG_SETTINGS_SECTION = "AutomaticUpdatesPopup"; //$NON-NLS-1$ |
| private static final int POPUP_OFFSET = 20; |
| |
| IPreferenceStore prefs; |
| long remindDelay = -1L; |
| IPropertyChangeListener prefListener; |
| WorkbenchJob remindJob; |
| boolean downloaded; |
| Composite dialogArea; |
| Link remindLink; |
| MouseListener clickListener; |
| |
| public AutomaticUpdatesPopup(Shell parentShell, boolean alreadyDownloaded, IPreferenceStore prefs) { |
| super(parentShell, PopupDialog.INFOPOPUPRESIZE_SHELLSTYLE | SWT.MODELESS, false, true, true, false, false, |
| AutomaticUpdateMessages.AutomaticUpdatesPopup_UpdatesAvailableTitle, null); |
| downloaded = alreadyDownloaded; |
| this.prefs = prefs; |
| remindDelay = computeRemindDelay(); |
| clickListener = MouseListener |
| .mouseDownAdapter(e -> AutomaticUpdatePlugin.getDefault().getAutomaticUpdater().launchUpdate()); |
| } |
| |
| @Override |
| protected Control createDialogArea(Composite parent) { |
| dialogArea = new Composite(parent, SWT.NONE); |
| dialogArea.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| GridLayout layout = new GridLayout(); |
| layout.numColumns = 1; |
| dialogArea.setLayout(layout); |
| dialogArea.addMouseListener(clickListener); |
| |
| // The "click to update" label |
| Label infoLabel = new Label(dialogArea, SWT.NONE); |
| if (downloaded) |
| infoLabel.setText(AutomaticUpdateMessages.AutomaticUpdatesPopup_ClickToReviewDownloaded); |
| else |
| infoLabel.setText(AutomaticUpdateMessages.AutomaticUpdatesPopup_ClickToReviewNotDownloaded); |
| infoLabel.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| infoLabel.addMouseListener(clickListener); |
| |
| createRemindSection(dialogArea); |
| |
| return dialogArea; |
| |
| } |
| |
| private void createRemindSection(Composite parent) { |
| remindLink = new Link(parent, SWT.MULTI | SWT.WRAP | SWT.RIGHT); |
| updateRemindText(); |
| remindLink.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> { |
| PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(getShell(), |
| PreferenceConstants.PREF_PAGE_AUTO_UPDATES, null, null); |
| dialog.open(); |
| |
| })); |
| remindLink.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| } |
| |
| private void updateRemindText() { |
| if (prefs.getBoolean(PreferenceConstants.PREF_REMIND_SCHEDULE)) |
| remindLink.setText(NLS.bind(AutomaticUpdateMessages.AutomaticUpdatesPopup_RemindAndPrefLink, new String[] { |
| getElapsedTimeString(prefs.getString(PreferenceConstants.PREF_REMIND_ELAPSED)), PREFS_HREF })); |
| else |
| remindLink.setText(AutomaticUpdateMessages.AutomaticUpdatesPopup_PrefLinkOnly); |
| remindLink.getParent().layout(true); |
| } |
| |
| protected IDialogSettings getDialogBoundsSettings() { |
| IDialogSettings settings = AutomaticUpdatePlugin.getDefault().getDialogSettings(); |
| IDialogSettings section = settings.getSection(DIALOG_SETTINGS_SECTION); |
| if (section == null) { |
| section = settings.addNewSection(DIALOG_SETTINGS_SECTION); |
| } |
| return section; |
| } |
| |
| @Override |
| public int open() { |
| prefListener = event -> handlePreferenceChange(event); |
| prefs.addPropertyChangeListener(prefListener); |
| return super.open(); |
| } |
| |
| @Override |
| public boolean close() { |
| return close(true); |
| } |
| |
| public boolean close(boolean remind) { |
| if (remind && prefs.getBoolean(PreferenceConstants.PREF_REMIND_SCHEDULE)) |
| scheduleRemindJob(); |
| else |
| cancelRemindJob(); |
| if (prefListener != null) { |
| prefs.removePropertyChangeListener(prefListener); |
| prefListener = null; |
| } |
| return super.close(); |
| |
| } |
| |
| void scheduleRemindJob() { |
| // Cancel any pending remind job if there is one |
| if (remindJob != null) |
| remindJob.cancel(); |
| // If no updates have been found, there is nothing to remind |
| if (remindDelay < 0) |
| return; |
| remindJob = new WorkbenchJob(AutomaticUpdateMessages.AutomaticUpdatesPopup_ReminderJobTitle) { |
| @Override |
| public IStatus runInUIThread(IProgressMonitor monitor) { |
| if (monitor.isCanceled()) |
| return Status.CANCEL_STATUS; |
| open(); |
| return Status.OK_STATUS; |
| } |
| }; |
| remindJob.setSystem(true); |
| remindJob.setPriority(Job.INTERACTIVE); |
| remindJob.schedule(remindDelay); |
| |
| } |
| |
| /* |
| * Computes the number of milliseconds for the delay in reminding the user of |
| * updates |
| */ |
| long computeRemindDelay() { |
| if (prefs.getBoolean(PreferenceConstants.PREF_REMIND_SCHEDULE)) { |
| String elapsed = prefs.getString(PreferenceConstants.PREF_REMIND_ELAPSED); |
| for (int d = 0; d < ELAPSED_VALUES.length; d++) |
| if (ELAPSED_VALUES[d].equals(elapsed)) |
| switch (d) { |
| case 0: |
| // 30 minutes |
| return 30 * MINUTE; |
| case 1: |
| // 60 minutes |
| return 60 * MINUTE; |
| case 2: |
| // 240 minutes |
| return 240 * MINUTE; |
| } |
| } |
| return -1L; |
| } |
| |
| void cancelRemindJob() { |
| if (remindJob != null) { |
| remindJob.cancel(); |
| remindJob = null; |
| } |
| } |
| |
| @Override |
| protected void configureShell(Shell newShell) { |
| super.configureShell(newShell); |
| newShell.setText(AutomaticUpdateMessages.AutomaticUpdatesPopup_UpdatesAvailableTitle); |
| } |
| |
| @Override |
| protected Point getInitialLocation(Point initialSize) { |
| Shell parent = getParentShell(); |
| Point parentSize, parentLocation; |
| |
| if (parent != null) { |
| parentSize = parent.getSize(); |
| parentLocation = parent.getLocation(); |
| } else { |
| Rectangle bounds = getShell().getDisplay().getBounds(); |
| parentSize = new Point(bounds.width, bounds.height); |
| parentLocation = new Point(0, 0); |
| } |
| // We have to take parent location into account because SWT considers all |
| // shell locations to be in display coordinates, even if the shell is parented. |
| return new Point(parentSize.x - initialSize.x + parentLocation.x - POPUP_OFFSET, |
| parentSize.y - initialSize.y + parentLocation.y - POPUP_OFFSET); |
| } |
| |
| void handlePreferenceChange(PropertyChangeEvent event) { |
| if (PreferenceConstants.PREF_REMIND_SCHEDULE.equals(event.getProperty())) { |
| // Reminders turned on |
| if (prefs.getBoolean(PreferenceConstants.PREF_REMIND_SCHEDULE)) { |
| if (remindLink == null) |
| createRemindSection(dialogArea); |
| else { |
| updateRemindText(); |
| getShell().layout(true, true); |
| } |
| computeRemindDelay(); |
| scheduleRemindJob(); |
| } else { // reminders turned off |
| if (remindLink != null) { |
| updateRemindText(); |
| getShell().layout(true, true); |
| } |
| cancelRemindJob(); |
| } |
| } else if (PreferenceConstants.PREF_REMIND_ELAPSED.equals(event.getProperty())) { |
| // Reminding schedule changed |
| computeRemindDelay(); |
| scheduleRemindJob(); |
| } |
| } |
| |
| /* |
| * Overridden so that clicking in the title menu area closes the dialog. Also |
| * creates a close box menu in the title area. |
| */ |
| @Override |
| protected Control createTitleMenuArea(Composite parent) { |
| Composite titleComposite = (Composite) super.createTitleMenuArea(parent); |
| titleComposite.addMouseListener(clickListener); |
| |
| ToolBar toolBar = new ToolBar(titleComposite, SWT.FLAT); |
| ToolItem closeButton = new ToolItem(toolBar, SWT.PUSH, 0); |
| |
| GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(toolBar); |
| closeButton.setImage( |
| AutomaticUpdatePlugin.getDefault().getImageRegistry().get((AutomaticUpdatePlugin.IMG_TOOL_CLOSE))); |
| closeButton.setHotImage( |
| AutomaticUpdatePlugin.getDefault().getImageRegistry().get((AutomaticUpdatePlugin.IMG_TOOL_CLOSE_HOT))); |
| closeButton.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> close())); |
| // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=177183 |
| toolBar.addMouseListener(MouseListener.mouseDownAdapter(e -> close())); |
| return titleComposite; |
| } |
| |
| /* |
| * Overridden to adjust the span of the title label. Reachy, reachy.... |
| */ |
| @Override |
| protected Control createTitleControl(Composite parent) { |
| Control control = super.createTitleControl(parent); |
| Object data = control.getLayoutData(); |
| if (data instanceof GridData) { |
| ((GridData) data).horizontalSpan = 1; |
| } |
| return control; |
| } |
| |
| public static String getElapsedTimeString(String elapsedTimeKey) { |
| for (int i = 0; i < AutomaticUpdatesPopup.ELAPSED_VALUES.length; i++) { |
| if (AutomaticUpdatesPopup.ELAPSED_VALUES[i].equals(elapsedTimeKey)) |
| return AutomaticUpdatesPopup.ELAPSED_LOCALIZED_STRINGS[i]; |
| } |
| return AutomaticUpdatesPopup.ELAPSED_LOCALIZED_STRINGS[0]; |
| } |
| } |