blob: 02044da04039e113dd450a431c6e83dd80e44219 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 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.ui.dialogs;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
/**
* The common superclass for wizard import and export pages.
* <p>
* This class is not intended to be subclassed outside of the workbench.
* </p>
*/
public abstract class WizardDataTransferPage extends WizardPage implements
Listener, IOverwriteQuery {
// constants
protected static final int SIZING_TEXT_FIELD_WIDTH = 250;
protected static final int COMBO_HISTORY_LENGTH = 5;
/**
* Creates a new wizard page.
*
* @param pageName the name of the page
*/
protected WizardDataTransferPage(String pageName) {
super(pageName);
}
/**
* Adds an entry to a history, while taking care of duplicate history items
* and excessively long histories. The assumption is made that all histories
* should be of length <code>WizardDataTransferPage.COMBO_HISTORY_LENGTH</code>.
*
* @param history the current history
* @param newEntry the entry to add to the history
*/
protected String[] addToHistory(String[] history, String newEntry) {
java.util.ArrayList l = new java.util.ArrayList(Arrays.asList(history));
addToHistory(l, newEntry);
String[] r = new String[l.size()];
l.toArray(r);
return r;
}
/**
* Adds an entry to a history, while taking care of duplicate history items
* and excessively long histories. The assumption is made that all histories
* should be of length <code>WizardDataTransferPage.COMBO_HISTORY_LENGTH</code>.
*
* @param history the current history
* @param newEntry the entry to add to the history
*/
protected void addToHistory(List history, String newEntry) {
history.remove(newEntry);
history.add(0, newEntry);
// since only one new item was added, we can be over the limit
// by at most one item
if (history.size() > COMBO_HISTORY_LENGTH)
history.remove(COMBO_HISTORY_LENGTH);
}
/**
* Return whether the user is allowed to enter a new container name or just
* choose from existing ones.
* <p>
* Subclasses must implement this method.
* </p>
*
* @return <code>true</code> if new ones are okay, and <code>false</code>
* if only existing ones are allowed
*/
protected abstract boolean allowNewContainerName();
/**
* Creates a new label with a bold font.
*
* @param parent the parent control
* @param text the label text
* @return the new label control
*/
protected Label createBoldLabel(Composite parent, String text) {
Label label = new Label(parent, SWT.NONE);
label.setFont(JFaceResources.getBannerFont());
label.setText(text);
GridData data = new GridData();
data.verticalAlignment = GridData.FILL;
data.horizontalAlignment = GridData.FILL;
label.setLayoutData(data);
return label;
}
/**
* Creates the import/export options group controls.
* <p>
* The <code>WizardDataTransferPage</code> implementation of this method does
* nothing. Subclasses wishing to define such components should reimplement
* this hook method.
* </p>
*
* @param optionsGroup the parent control
*/
protected void createOptionsGroupButtons(Group optionsGroup) {
}
/**
* Creates a new label with a bold font.
*
* @param parent the parent control
* @param text the label text
* @return the new label control
*/
protected Label createPlainLabel(Composite parent, String text) {
Label label = new Label(parent, SWT.NONE);
label.setText(text);
label.setFont(parent.getFont());
GridData data = new GridData();
data.verticalAlignment = GridData.FILL;
data.horizontalAlignment = GridData.FILL;
label.setLayoutData(data);
return label;
}
/**
* Creates a horizontal spacer line that fills the width of its container.
*
* @param parent the parent control
*/
protected void createSpacer(Composite parent) {
Label spacer = new Label(parent, SWT.NONE);
GridData data = new GridData();
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.BEGINNING;
spacer.setLayoutData(data);
}
/**
* Returns whether this page is complete. This determination is made based upon
* the current contents of this page's controls. Subclasses wishing to include
* their controls in this determination should override the hook methods
* <code>validateSourceGroup</code> and/or <code>validateOptionsGroup</code>.
*
* @return <code>true</code> if this page is complete, and <code>false</code> if
* incomplete
* @see #validateSourceGroup
* @see #validateOptionsGroup
*/
protected boolean determinePageCompletion() {
boolean complete = validateSourceGroup() && validateDestinationGroup()
&& validateOptionsGroup();
// Avoid draw flicker by not clearing the error
// message unless all is valid.
if (complete)
setErrorMessage(null);
return complete;
}
/**
* Get a path from the supplied text widget.
* @return org.eclipse.core.runtime.IPath
*/
protected IPath getPathFromText(Text textField) {
String text = textField.getText();
//Do not make an empty path absolute so as not to confuse with the root
if (text.length() == 0)
return new Path(text);
return (new Path(text)).makeAbsolute();
}
/**
* Queries the user to supply a container resource.
*
* @return the path to an existing or new container, or <code>null</code> if the
* user cancelled the dialog
*/
protected IPath queryForContainer(IContainer initialSelection, String msg) {
return queryForContainer(initialSelection, msg, null);
}
/**
* Queries the user to supply a container resource.
*
* @return the path to an existing or new container, or <code>null</code> if the
* user cancelled the dialog
*/
protected IPath queryForContainer(IContainer initialSelection, String msg,
String title) {
ContainerSelectionDialog dialog = new ContainerSelectionDialog(
getControl().getShell(), initialSelection,
allowNewContainerName(), msg);
if (title != null)
dialog.setTitle(title);
dialog.showClosedProjects(false);
dialog.open();
Object[] result = dialog.getResult();
if (result != null && result.length == 1) {
return (IPath) result[0];
}
return null;
}
/**
* The <code>WizardDataTransfer</code> implementation of this
* <code>IOverwriteQuery</code> method asks the user whether the existing
* resource at the given path should be overwritten.
*
* @param pathString
* @return the user's reply: one of <code>"YES"</code>, <code>"NO"</code>, <code>"ALL"</code>,
* or <code>"CANCEL"</code>
*/
public String queryOverwrite(String pathString) {
Path path = new Path(pathString);
String messageString;
//Break the message up if there is a file name and a directory
//and there are at least 2 segments.
if (path.getFileExtension() == null || path.segmentCount() < 2)
messageString = NLS.bind(IDEWorkbenchMessages.WizardDataTransfer_existsQuestion, pathString);
else
messageString = NLS.bind(IDEWorkbenchMessages.WizardDataTransfer_overwriteNameAndPathQuestion, path.lastSegment(),
path.removeLastSegments(1).toOSString());
final MessageDialog dialog = new MessageDialog(getContainer()
.getShell(), IDEWorkbenchMessages.Question,
null, messageString, MessageDialog.QUESTION, new String[] {
IDialogConstants.YES_LABEL,
IDialogConstants.YES_TO_ALL_LABEL,
IDialogConstants.NO_LABEL,
IDialogConstants.NO_TO_ALL_LABEL,
IDialogConstants.CANCEL_LABEL }, 0);
String[] response = new String[] { YES, ALL, NO, NO_ALL, CANCEL };
//run in syncExec because callback is from an operation,
//which is probably not running in the UI thread.
getControl().getDisplay().syncExec(new Runnable() {
public void run() {
dialog.open();
}
});
return dialog.getReturnCode() < 0 ? CANCEL : response[dialog
.getReturnCode()];
}
/**
* Displays a Yes/No question to the user with the specified message and returns
* the user's response.
*
* @param message the question to ask
* @return <code>true</code> for Yes, and <code>false</code> for No
*/
protected boolean queryYesNoQuestion(String message) {
MessageDialog dialog = new MessageDialog(getContainer().getShell(),
IDEWorkbenchMessages.Question,
(Image) null, message, MessageDialog.NONE,
new String[] { IDialogConstants.YES_LABEL,
IDialogConstants.NO_LABEL }, 0);
// ensure yes is the default
return dialog.open() == 0;
}
/**
* Restores control settings that were saved in the previous instance of this
* page.
* <p>
* The <code>WizardDataTransferPage</code> implementation of this method does
* nothing. Subclasses may override this hook method.
* </p>
*/
protected void restoreWidgetValues() {
}
/**
* Saves control settings that are to be restored in the next instance of
* this page.
* <p>
* The <code>WizardDataTransferPage</code> implementation of this method does
* nothing. Subclasses may override this hook method.
* </p>
*/
protected void saveWidgetValues() {
}
/**
* Determine if the page is complete and update the page appropriately.
*/
protected void updatePageCompletion() {
boolean pageComplete = determinePageCompletion();
setPageComplete(pageComplete);
if (pageComplete) {
setMessage(null);
}
}
/**
* Updates the enable state of this page's controls.
* <p>
* The <code>WizardDataTransferPage</code> implementation of this method does
* nothing. Subclasses may extend this hook method.
* </p>
*/
protected void updateWidgetEnablements() {
}
/**
* Returns whether this page's destination specification controls currently all
* contain valid values.
* <p>
* The <code>WizardDataTransferPage</code> implementation of this method returns
* <code>true</code>. Subclasses may reimplement this hook method.
* </p>
*
* @return <code>true</code> indicating validity of all controls in the
* destination specification group
*/
protected boolean validateDestinationGroup() {
return true;
}
/**
* Returns whether this page's options group's controls currently all contain
* valid values.
* <p>
* The <code>WizardDataTransferPage</code> implementation of this method returns
* <code>true</code>. Subclasses may reimplement this hook method.
* </p>
*
* @return <code>true</code> indicating validity of all controls in the options
* group
*/
protected boolean validateOptionsGroup() {
return true;
}
/**
* Returns whether this page's source specification controls currently all
* contain valid values.
* <p>
* The <code>WizardDataTransferPage</code> implementation of this method returns
* <code>true</code>. Subclasses may reimplement this hook method.
* </p>
*
* @return <code>true</code> indicating validity of all controls in the
* source specification group
*/
protected boolean validateSourceGroup() {
return true;
}
/**
* Create the options specification widgets.
*
* @param parent org.eclipse.swt.widgets.Composite
*/
protected void createOptionsGroup(Composite parent) {
// options group
Group optionsGroup = new Group(parent, SWT.NONE);
GridLayout layout = new GridLayout();
optionsGroup.setLayout(layout);
optionsGroup.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL
| GridData.GRAB_HORIZONTAL));
optionsGroup.setText(IDEWorkbenchMessages.WizardExportPage_options);
optionsGroup.setFont(parent.getFont());
createOptionsGroupButtons(optionsGroup);
}
/**
* Display an error dialog with the specified message.
*
* @param message the error message
*/
protected void displayErrorDialog(String message) {
MessageDialog.openError(getContainer().getShell(),
getErrorDialogTitle(), message);
}
/**
* Display an error dislog with the information from the
* supplied exception.
* @param exception Throwable
*/
protected void displayErrorDialog(Throwable exception) {
String message = exception.getMessage();
//Some system exceptions have no message
if (message == null)
message = NLS.bind(IDEWorkbenchMessages.WizardDataTransfer_exceptionMessage, exception);
displayErrorDialog(message);
}
/**
* Get the title for an error dialog. Subclasses should
* override.
*/
protected String getErrorDialogTitle() {
return IDEWorkbenchMessages.WizardExportPage_internalErrorTitle;
}
}