blob: 577bf5d3b0c49765278354399dfbbf82f25cfd32 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 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
* Kaloyan Raev, kaloyan.raev@sap.com - bug 213927
*******************************************************************************/
package org.eclipse.wst.common.frameworks.internal.datamodel.ui;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.wizard.IWizard;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.PlatformUI;
import org.eclipse.wst.common.frameworks.datamodel.DataModelEvent;
import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
import org.eclipse.wst.common.frameworks.datamodel.IDataModelListener;
import org.eclipse.wst.common.frameworks.internal.ui.ValidationStatus;
/**
* This class is EXPERIMENTAL and is subject to substantial changes.
*/
public abstract class DataModelWizardPage extends WizardPage implements Listener, IDataModelListener {
protected static final int NEXT = 1;
protected static final int PREVIOUS = 2;
protected static final int COMPOSITE_BORDER = SWT.NULL;
private ValidationStatus status = new ValidationStatus();
private boolean isValidating = false;
protected boolean isFirstTimeToPage = true;
protected IDataModel model;
private Map validationMap;
private String[] validationPropertyNames;
protected DataModelSynchHelper synchHelper;
private String infopopID;
private DataModelWizard wizard;
private IWizardPage previousPage;
/**
* J2EEWizardPage constructor comment.
*
* @param pageName
* java.lang.String
*/
protected DataModelWizardPage(IDataModel model, String pageName) {
super(pageName);
this.model = model;
model.addListener(this);
synchHelper = initializeSynchHelper(model);
}
/**
* @return
*/
public DataModelSynchHelper initializeSynchHelper(IDataModel dm) {
return new DataModelSynchHelper(dm);
}
/**
* J2EEWizardPage constructor comment.
*
* @param pageName
* java.lang.String
* @param title
* java.lang.String
* @param titleImage
* org.eclipse.jface.resource.ImageDescriptor
*/
protected DataModelWizardPage(IDataModel model, String pageName, String title, org.eclipse.jface.resource.ImageDescriptor titleImage) {
super(pageName, title, titleImage);
this.model = model;
model.addListener(this);
synchHelper = initializeSynchHelper(model);
}
/**
* Creates the top level control for this dialog page under the given parent composite. This
* method has been abstract and it uses the template pattern to get the correct items setup in
* the correct order. See the set of methods below that are called in this method.
* <p>
* Implementors are responsible for ensuring that the created control can be accessed via
* <code>getControl</code>
* </p>
*
* @param parent
* the parent composite
*/
public final void createControl(Composite parent) {
Composite top = createTopLevelComposite(parent);
addExtendedControls(top);
setControl(top);
setupInfopop(top);
setDefaults();
addListeners();
initializeValidationProperties();
}
private void addExtendedControls(Composite top) {
IWizard _wizard = getWizard();
if (_wizard instanceof DataModelWizard) {
PageExtensionManager pageExtensionManager = ((DataModelWizard) _wizard).getPageExtensionManager();
pageExtensionManager.createAdditionalControls(top, model, getName());
}
}
private void initializeValidationProperties() {
validationPropertyNames = getValidationPropertyNames();
if (validationPropertyNames == null || validationPropertyNames.length == 0)
validationMap = Collections.EMPTY_MAP;
else {
validationMap = new HashMap(validationPropertyNames.length);
for (int i = 0; i < validationPropertyNames.length; i++)
validationMap.put(validationPropertyNames[i], new Integer(i));
}
}
public boolean canFlipToNextPage() {
// TODO why is that last getNextPage() call here???
return isPageComplete() && ((null != wizard && wizard.getPageGroupManager().hasNextPage() || null != getNextPage()));
}
/*
* (non-Javadoc) Method declared on IWizardPage.
*/
public void setWizard(IWizard newWizard) {
super.setWizard(newWizard);
if (newWizard instanceof DataModelWizard) {
wizard = (DataModelWizard) newWizard;
}
}
public IWizardPage getPreviousPage() {
return previousPage;
}
public void setPreviousPage(IWizardPage page) {
super.setPreviousPage(page);
previousPage = page;
}
/**
* Subclass should return the model property names that need to be validated on this page in the
* order that they should present their messages.
*
* @return
*/
protected abstract String[] getValidationPropertyNames();
/**
* Return the top level Composite for this page.
*/
protected abstract Composite createTopLevelComposite(Composite parent);
/**
* Set up info pop hooks if set.
*/
protected void setupInfopop(Control parent) {
if (getInfopopID() != null)
PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, getInfopopID());
}
/**
* Setup the default values for this page. Subclasses should override to provide appropriate
* defaults.
*/
protected void setDefaults() {
restoreDefaultSettings();
}
/**
* Subclasses should implement this method if they have default settings that have been stored
* and need to be restored.
*
* @see storeDefaultSettings()
*/
protected void restoreDefaultSettings() {
}
/**
* Add Listeners to controls at this point to avoid unnecessary events. Subclasses should
* override to add listeners to its controls.
*/
protected void addListeners() {
}
/**
* The page is being made current and visible. Subclasses may extend.
*/
protected void enter() {
try {
// Check to see if we are moving back one page.
if (null != wizard && wizard.getPreviousPage(wizard.getPageGroupManager().getCurrentPage()) == this) {
wizard.getPageGroupManager().moveBackOnePage();
}
validatePage(showValidationErrorsOnEnter());
} finally {
isFirstTimeToPage = false;
}
}
/**
* The default behavior is to return true unless it is the first time entering this page in
* which case we check to see if there is a previous page and return true if there is not.
* Subclasses should override if they do not want this default behavior.
*/
protected boolean showValidationErrorsOnEnter() {
return !isFirstTimeToPage();
}
/**
* The default behavior is to return true unless it is the first time entering this page in
* which case we check to see if there is a previous page and return true if there is not.
* Subclasses should override if they do not want this default behavior.
*
* @deprecated - use showValidatoinErrorsOnEnter instead
*/
protected boolean shouldValidateOnEnter() {
return showValidationErrorsOnEnter();
}
/**
* Exiting the page. Subclasses may extend.
*/
protected void exit() {
}
protected boolean getStatus(Integer key) {
return status.hasError(key);
}
/**
* Sent when an event that the receiver has registered for occurs. If a subclass overrides this
* method, it must call super.
*
* @param event
* the event which occurred
*/
public void handleEvent(org.eclipse.swt.widgets.Event event) {
}
/**
* Set the error message for this page based on the last error in the ValidationStatus.
*/
protected void setErrorMessage() {
String error = status.getLastErrMsg();
if (error == null) {
if (getErrorMessage() != null)
setErrorMessage((String) null);
String warning = status.getLastWarningMsg();
if (warning == null) {
if (getMessage() != null && getMessageType() == IMessageProvider.WARNING)
setMessage(null, IMessageProvider.WARNING);
else {
String info = status.getLastInfoMsg();
if (info == null) {
if (getMessage() != null && getMessageType() == IMessageProvider.INFORMATION)
setMessage(null, IMessageProvider.INFORMATION);
} else if (!info.equals(getMessage())) {
setMessage(info, IMessageProvider.INFORMATION);
}
}
} else if (!warning.equals(getMessage()))
setMessage(warning, IMessageProvider.WARNING);
} else if (!error.equals(getErrorMessage()))
setErrorMessage(error);
}
protected void setErrorStatus(Integer key, String errorMessage) {
status.setErrorStatus(key, errorMessage);
}
protected void setWarningStatus(Integer key, String warningMessage) {
status.setWarningStatus(key, warningMessage);
}
protected void setInfoStatus(Integer key, String infoMessage) {
status.setInfoStatus(key, infoMessage);
}
protected void setOKStatus(Integer key) {
status.setOKStatus(key);
}
/**
* The <code>DialogPage</code> implementation of this <code>IDialogPage</code> method sets
* the control to the given visibility state. Subclasses may extend.
*/
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible) {
enter();
} else
exit();
}
/**
* This should be called by the Wizard just prior to running the performFinish operation.
* Subclasses should override to store their default settings.
*/
public void storeDefaultSettings() {
}
/**
* The page is now being validated. At this time, each control is validated and then the
* controls are updated based on the results in the ValidationStatus which was updated during
* <code>validateControls()</code>. Finally, it will display the last error message and it
* will set the page complete. Subclasses will not typically override this method.
*/
protected void validatePage() {
validatePage(true);
}
protected void validatePage(boolean showMessage) {
if (!isValidating) {
isValidating = true;
try {
validateControlsBase();
updateControls();
if (showMessage)
setErrorMessage();
setPageComplete(status.getLastErrMsg() == null);
} finally {
isValidating = false;
}
}
}
/**
* Validate individual controls. Use validation keys to keep track of errors.
*
* @see setOKStatus(Integer) and setErrorMessage(Integer, String)
*/
protected final String validateControlsBase() {
if (!validationMap.isEmpty()) {
String propName;
for (int i = 0; i < validationPropertyNames.length; i++) {
propName = validationPropertyNames[i];
Integer valKey = (Integer) validationMap.get(propName);
if (valKey != null)
validateProperty(propName, valKey);
if (!getStatus(valKey))
return propName;
}
}
return null;
}
/**
* @param propertyName
* @param validationkey
*/
private void validateProperty(String propertyName, Integer validationKey) {
setOKStatus(validationKey);
IStatus status1 = model.validateProperty(propertyName);
if (!status1.isOK()) {
String message = status1.isMultiStatus() ? status1.getChildren()[0].getMessage() : status1.getMessage();
switch (status1.getSeverity()) {
case IStatus.ERROR :
setErrorStatus(validationKey, message);
break;
case IStatus.WARNING :
setWarningStatus(validationKey, message);
break;
case IStatus.INFO :
setInfoStatus(validationKey, message);
break;
}
}
}
/**
* Update the enablement of controls after validation. Sublcasses should check the status of
* validation keys to determine enablement.
*/
protected void updateControls() {
}
/**
* Gets the isFirstTimeToPage.
*
* @return Returns a boolean
*/
protected boolean isFirstTimeToPage() {
return isFirstTimeToPage;
}
// protected void setJavaStatusMessage(IStatus javaStatus, Integer statusKey, String message) {
// if (javaStatus.getSeverity() == IStatus.WARNING)
// setWarningStatus(statusKey, message);
// else
// setErrorStatus(statusKey, message);
// }
/**
* @param b
*/
public void setFirstTimeToPage(boolean b) {
isFirstTimeToPage = b;
}
private boolean gotDataModelWizard = false;
private DataModelWizard dataModelWizard = null;
protected DataModelWizard getDataModelWizard(){
if(!gotDataModelWizard){
gotDataModelWizard = true;
IWizard wizard = getWizard();
if(wizard instanceof DataModelWizard){
dataModelWizard = (DataModelWizard)wizard;
}
}
return dataModelWizard;
}
/*
* If a property changes that we want to validate, force validation on this page.
*
* @see org.eclipse.wst.common.frameworks.internal.operation.WTPOperationDataModelListener#propertyChanged(java.lang.String,
* java.lang.Object, java.lang.Object)
*/
public void propertyChanged(final DataModelEvent event) {
DataModelWizard w = getDataModelWizard();
if(w == null || !w.isExecuting())
{
final Runnable uiChanges = new Runnable()
{
public void run()
{
String propertyName = event.getPropertyName();
if (validationPropertyNames != null && (event.getFlag() == DataModelEvent.VALUE_CHG || (!isPageComplete() && event.getFlag() == DataModelEvent.VALID_VALUES_CHG))) {
for (int i = 0; i < validationPropertyNames.length; i++) {
if (validationPropertyNames[i].equals(propertyName)) {
validatePage(showValidationErrorsOnEnter());
break;
}
}
}
}
};
if(Thread.currentThread() == Display.getDefault().getThread()){
uiChanges.run();
} else {
Display.getDefault().asyncExec(uiChanges);
}
}
}
/**
* @return Returns the model.
*/
protected IDataModel getDataModel() {
return model;
}
public void dispose() {
super.dispose();
if (synchHelper != null) {
synchHelper.dispose();
synchHelper = null;
}
}
protected String getInfopopID() {
return infopopID;
}
public void setInfopopID(String infopopID) {
this.infopopID = infopopID;
}
}