/*******************************************************************************
* Copyright (c) 2014 Mentor Graphics 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:
* Mentor Graphics - initial API and implementation
*******************************************************************************/
package com.codesourcery.internal.installer.ui.pages;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import com.codesourcery.installer.IInstallConsoleProvider;
import com.codesourcery.installer.IInstallData;
import com.codesourcery.installer.IInstallDescription;
import com.codesourcery.installer.IInstallMode;
import com.codesourcery.installer.IInstalledProduct;
import com.codesourcery.installer.Installer;
import com.codesourcery.installer.console.ConsoleYesNoPrompter;
import com.codesourcery.installer.ui.BrowseDefaultEditor;
import com.codesourcery.installer.ui.BrowseDirectoryDefaultEditor;
import com.codesourcery.installer.ui.IInstallSummaryProvider;
import com.codesourcery.installer.ui.InstallWizardPage;
import com.codesourcery.internal.installer.InstallManager;
import com.codesourcery.internal.installer.InstallMessages;
import com.codesourcery.internal.installer.InstallUtils;
/**
* Page that prompts for the installation folder
* This page supports the console.
*/
public class InstallFolderPage extends InstallWizardPage implements IInstallSummaryProvider, IInstallConsoleProvider {
/** Folder text */
protected BrowseDefaultEditor valueEditor;
/** Default installation folder */
private String defaultFolder;
/** Installation folder */
private String folder;
/** Install context */
private IInstallDescription installDescription;
/** Warning console prompter */
private ConsoleYesNoPrompter warningConsolePrompter;
/** Main area of page */
private Composite area;
/** Install area of page */
private Composite installArea;
/**
* Constructor
*
* @param pageName Page name
* @param title Page title
* @param defaultFolder Default folder or <code>null</code>.
* @param installDescription Install description
*/
public InstallFolderPage(String pageName, String title, String defaultFolder, IInstallDescription installDescription) {
super(pageName, title);
this.defaultFolder = defaultFolder;
if (this.defaultFolder == null) {
this.defaultFolder = "";
}
setFolder(this.defaultFolder);
this.installDescription = installDescription;
}
/**
* Returns the install description.
*
* @return Install description
*/
protected IInstallDescription getInstallDescription() {
return installDescription;
}
/**
* Returns the default installation directory.
*
* @return Default directory
*/
protected String getDefaultFolder() {
return defaultFolder;
}
/**
* Returns the install folder.
*
* @return Install folder
*/
protected String getFolder() {
// If UI is available, get folder from it
if (valueEditor != null) {
folder = valueEditor.getText().trim();
}
return folder;
}
/**
* Sets the install folder.
*
* @param folder Install folder
*/
protected void setFolder(String folder) {
this.folder = folder.trim();
// Update UI if available
if (valueEditor != null) {
valueEditor.setText(folder);
}
}
/**
* Enables or disables the folder editor.
*
* @param enabled <code>true</code> to enable, <code>false</code> to disable.
*/
protected void setFolderEnabled(boolean enabled) {
valueEditor.setEnabled(enabled);
}
public IStatus[] verifyInstallLocation() {
if (getInstallMode().isMirror()) {
return new IStatus[0];
}
else {
InstallManager manager = (InstallManager)Installer.getDefault().getInstallManager();
return (manager.verifyInstallLocation(new Path(getFolder())));
}
}
@Override
public Control createContents(Composite parent) {
area = new Composite(parent, SWT.NONE);
area.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
area.setLayout(new GridLayout(1, false));
installArea = new Composite(area, SWT.NONE);
GridLayout layout = new GridLayout(1, true);
layout.marginHeight = layout.marginWidth = 0;
installArea.setLayout(layout);
installArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
// Install folder label
Label folderLabel = new Label(installArea, SWT.NONE);
folderLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
String installFolderText = getInstallDescription().getText(IInstallDescription.TEXT_INSTALL_FOLDER, InstallMessages.InstallFolder);
folderLabel.setText(installFolderText);
valueEditor = new BrowseDirectoryDefaultEditor(installArea, SWT.NONE, true, true, getFolder());
valueEditor.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
valueEditor.getEditor().addModifyListener(new ModifyListener() {
@SuppressWarnings("synthetic-access")
@Override
public void modifyText(ModifyEvent e) {
hideStatus();
setPageComplete(true);
stopAutoUpdate();
}
});
valueEditor.getRestoreButton().addSelectionListener(new SelectionAdapter() {
@SuppressWarnings("synthetic-access")
@Override
public void widgetSelected(SelectionEvent e) {
validate();
}
});
valueEditor.getBrowseButton().addSelectionListener(new SelectionAdapter() {
@SuppressWarnings("synthetic-access")
@Override
public void widgetSelected(SelectionEvent e) {
validate();
}
});
valueEditor.setBrowseMessage(InstallMessages.SelectInstallFolderMessage);
return area;
}
/**
* Shows or hides the install section of the page.
*
* @param show <code>true</code> to show, <code>false</code> to hide
*/
protected void showInstallArea(boolean show) {
GridData data = (GridData)installArea.getLayoutData();
if (data.exclude == show) {
data.exclude = !show;
if (!show) {
installArea.setSize(0, 0);
}
area.layout(true);
}
}
@Override
public void setActive(IInstallData data) {
super.setActive(data);
// If an installed product has been setup, update the install folder
IInstalledProduct installedProduct = Installer.getDefault().getInstallManager().getInstalledProduct();
if (installedProduct != null) {
setFolder(installedProduct.getInstallLocation().toOSString());
}
}
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
// If an installed product has been setup, disable the install folder editing
setFolderEnabled(Installer.getDefault().getInstallManager().getInstalledProduct() == null);
}
@Override
public String getInstallSummary() {
if (getInstallMode().isMirror()) {
return null;
}
else {
return InstallMessages.SummaryInstallFolder + getFolder() + "\n\n";
}
}
@Override
public void saveInstallData(IInstallData data) throws CoreException {
final IPath installLocation = InstallUtils.resolvePath(getFolder());
final Exception[] error = new Exception[] { null };
runOperation(InstallMessages.PreparingInstall, new Runnable() {
@Override
public void run() {
try {
// Set install location
Installer.getDefault().getInstallManager().setInstallLocation(installLocation, null);
} catch (Exception e) {
error[0] = e;
}
}
});
// Error creating install location
if (error[0] != null) {
Installer.fail(error[0].getLocalizedMessage());
}
}
/**
* Returns if status has errors.
*
* @param status Status
* @return <code>true</code> if any status is an error,
* <code>false</code> if all status are warning or information.
*/
private boolean statusContainsErrors(IStatus[] status) {
boolean hasErrors = false;
for (IStatus s : status) {
if (s.getSeverity() == IStatus.ERROR) {
hasErrors = true;
break;
}
}
return hasErrors;
}
@Override
public boolean validate() {
boolean valid = true;
boolean recheck = false;
// Verify install location
IStatus[] status = verifyInstallLocation();
if (status.length > 0) {
// Status has errors
if (statusContainsErrors(status)) {
valid = false;
recheck = true;
setPageComplete(false);
}
// If only warnings or information, the page is valid if has already
// been displayed.
else {
valid = (getStatus() != null);
setPageComplete(true);
// Append an additional information status with a message to continue
IStatus[] newStatus = new IStatus[status.length + 1];
System.arraycopy(status, 0, newStatus, 0, status.length);
newStatus[status.length] = new Status(IStatus.INFO, Installer.ID, InstallMessages.Error_NextToContinue);
status = newStatus;
}
showStatus(status);
}
else {
hideStatus();
valid = true;
setPageComplete(true);
}
// Start auto-update to periodically re-check in case conditions changed
// to cause validation to succeed.
if (recheck) {
startAutoUpdate();
}
else {
stopAutoUpdate();
}
return valid;
}
/**
* Returns the console message.
*
* @return Message
*/
protected String getConsoleMessage() {
StringBuilder buffer = new StringBuilder();
buffer.append(InstallMessages.InstallFolder);
buffer.append('\n');
buffer.append(NLS.bind(InstallMessages.InstallFolderPageConsoleInstallFolder, getFolder()));
buffer.append("\n\n");
buffer.append(InstallMessages.ConsolePressEnterOrChange);
buffer.append('\n');
return buffer.toString();
}
@Override
public String getConsoleResponse(String input) throws IllegalArgumentException {
String response = null;
// Don't prompt for install folder if mirror operation
if (getInstallMode().isMirror())
return response;
// Warning prompter active
if (warningConsolePrompter != null) {
response = warningConsolePrompter.getConsoleResponse(input);
// Continue
if (warningConsolePrompter.getResult()) {
return null;
}
// Do not continue
else {
warningConsolePrompter = null;
input = null;
}
}
// Initial message
if (input == null) {
if (Installer.getDefault().getInstallManager().getInstalledProduct() == null) {
response = getConsoleMessage();
}
}
// Response
else {
// Continue with folder
if (input.isEmpty()) {
// Verify install location
IStatus[] status = verifyInstallLocation();
if (status.length > 0) {
StringBuffer buffer = new StringBuffer();
for (IStatus s : status) {
if (buffer.length() == 0)
buffer.append('\n');
buffer.append(s.getMessage());
}
// Result contains errors
if (statusContainsErrors(status)) {
response = buffer.toString();
}
// Show warnings and/or information and prompt to continue
else {
warningConsolePrompter = new ConsoleYesNoPrompter(buffer.toString(),
InstallMessages.Continue, true);
response = warningConsolePrompter.getConsoleResponse(null);
}
}
else {
response = null;
}
}
// Change folder
else {
setFolder(input);
response = getConsoleMessage();
}
}
return response;
}
@Override
public boolean isSupported() {
// If an installed product has been set, don't prompt for install location
if (Installer.getDefault().getInstallManager().getInstalledProduct() != null) {
return false;
}
// Otherwise, show page for an installation that is not already set up
// for an update or upgrade to an existing product.
else {
IInstallMode mode = Installer.getDefault().getInstallManager().getInstallMode();
return (mode.isInstall() && !mode.isUpdate() && !mode.isUpgrade() && !mode.isMirror());
}
}
@Override
protected void autoUpdate() {
validate();
}
}