blob: ed8c1a0424e072a82e29d664b361a821e9498ab5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2008 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.equinox.internal.p2.ui.sdk.updates;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.equinox.internal.p2.ui.sdk.ProvSDKMessages;
import org.eclipse.equinox.internal.p2.ui.sdk.ProvSDKUIActivator;
import org.eclipse.equinox.internal.p2.ui.sdk.prefs.PreferenceConstants;
import org.eclipse.equinox.internal.provisional.p2.ui.ProvUIImages;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.PopupDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
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 = {ProvSDKMessages.AutomaticUpdateScheduler_30Minutes, ProvSDKMessages.AutomaticUpdateScheduler_60Minutes, ProvSDKMessages.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;
Preferences prefs;
long remindDelay = -1L;
IPropertyChangeListener prefListener;
WorkbenchJob remindJob;
boolean downloaded;
Composite dialogArea;
Link remindLink;
MouseListener clickListener;
public AutomaticUpdatesPopup(Shell parentShell, boolean alreadyDownloaded, Preferences prefs) {
super(parentShell, PopupDialog.INFOPOPUPRESIZE_SHELLSTYLE | SWT.MODELESS, false, true, false, false, ProvSDKMessages.AutomaticUpdatesPopup_UpdatesAvailableTitle, null);
downloaded = alreadyDownloaded;
this.prefs = prefs;
remindDelay = computeRemindDelay();
clickListener = new MouseAdapter() {
public void mouseDown(MouseEvent e) {
ProvSDKUIActivator.getDefault().getAutomaticUpdater().launchUpdate();
}
};
}
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(ProvSDKMessages.AutomaticUpdatesPopup_ClickToReviewDownloaded);
else
infoLabel.setText(ProvSDKMessages.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(new SelectionAdapter() {
public void widgetSelected(SelectionEvent 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(ProvSDKMessages.AutomaticUpdatesPopup_RemindAndPrefLink, new String[] {prefs.getString(PreferenceConstants.PREF_REMIND_ELAPSED), PREFS_HREF}));
else
remindLink.setText(ProvSDKMessages.AutomaticUpdatesPopup_PrefLinkOnly);
remindLink.getParent().layout(true);
}
protected IDialogSettings getDialogBoundsSettings() {
IDialogSettings settings = ProvSDKUIActivator.getDefault().getDialogSettings();
IDialogSettings section = settings.getSection(DIALOG_SETTINGS_SECTION);
if (section == null) {
section = settings.addNewSection(DIALOG_SETTINGS_SECTION);
}
return section;
}
public int open() {
prefListener = new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
handlePreferenceChange(event);
}
};
prefs.addPropertyChangeListener(prefListener);
return super.open();
}
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(ProvSDKMessages.AutomaticUpdatesPopup_ReminderJobTitle) {
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.length; d++)
if (ELAPSED[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;
}
}
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(ProvSDKMessages.AutomaticUpdatesPopup_UpdatesAvailableTitle);
}
/**
* (non-Javadoc)
*
* @see org.eclipse.jface.window.Window#getInitialLocation(org.eclipse.swt.graphics.Point)
*/
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.
*/
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(ProvUIImages.getImage(ProvUIImages.IMG_TOOL_CLOSE));
closeButton.setHotImage(ProvUIImages.getImage(ProvUIImages.IMG_TOOL_CLOSE_HOT));
closeButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
close();
}
});
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=177183
toolBar.addMouseListener(new MouseAdapter() {
public void mouseDown(MouseEvent e) {
close();
}
});
return titleComposite;
}
/*
* Overridden to adjust the span of the title label.
* Reachy, reachy....
* (non-Javadoc)
* @see org.eclipse.jface.dialogs.PopupDialog#createTitleControl(org.eclipse.swt.widgets.Composite)
*/
protected Control createTitleControl(Composite parent) {
Control control = super.createTitleControl(parent);
Object data = control.getLayoutData();
if (data instanceof GridData) {
((GridData) data).horizontalSpan = 1;
}
return control;
}
}