/*******************************************************************************
* Copyright (c) 2009 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
* Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.ui.wizards;
import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.wizard.IWizard;
import org.eclipse.jface.wizard.IWizardContainer;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.php.internal.ui.PHPUIMessages;
import org.eclipse.php.internal.ui.PHPUiPlugin;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class FragmentedWizard implements IWizard {
private static final byte FINISH = 2;
private static final byte CANCEL = 3;
private List<IWizardPage> pages;
private boolean addingPages;
private Map<WizardFragment, FragmentedWizardPage> fragmentData = new HashMap<WizardFragment, FragmentedWizardPage>();
protected WizardModel wizardModel;
private IWizardContainer container = null;
private boolean needsProgressMonitor = false;
private boolean forcePreviousAndNextButtons = false;
private boolean isHelpAvailable = false;
private Image defaultImage = null; // XXX: never set
private RGB titleBarColor = null; // XXX: never set
private String windowTitle = null;
private IDialogSettings dialogSettings = null;
private WizardFragment rootFragment;
private WizardFragment currentFragment;
private IStatus status;
private Composite pageContainerHook = null;
/**
* Create a new TaskWizard with the given title and root fragment.
*
* @param title
* a title
* @param rootFragment
* a root fragment
*/
public FragmentedWizard(String title, WizardFragment rootFragment) {
this(title, rootFragment, null);
setWindowTitle(title);
}
/**
* Create a new TaskWizard with the given title, root fragment, and task
* model.
*
* @param title
* a title
* @param rootFragment
* a root fragment
* @param taskModel
* a task model
*/
public FragmentedWizard(String title, WizardFragment rootFragment, WizardModel taskModel) {
super();
if (title != null)
setWindowTitle(title);
this.rootFragment = rootFragment;
this.wizardModel = taskModel;
if (taskModel == null)
this.wizardModel = new WizardModel();
setNeedsProgressMonitor(true);
setForcePreviousAndNextButtons(true);
}
public void setWizardModel(WizardModel taskModel) {
this.wizardModel = taskModel;
}
public WizardModel getWizardModel() {
return wizardModel;
}
public void setRootFragment(WizardFragment rootFragment) {
this.rootFragment = rootFragment;
}
public WizardFragment getRootFragment() {
return rootFragment;
}
/**
* Cancel the client selection.
*
* @return boolean
*/
@Override
public boolean performCancel() {
final List<WizardFragment> list = getAllWizardFragments();
IRunnableWithProgress runnable = new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException {
try {
Iterator<WizardFragment> iterator = list.iterator();
while (iterator.hasNext())
executeTask((WizardFragment) iterator.next(), CANCEL, monitor);
} catch (CoreException ce) {
throw new InvocationTargetException(ce);
}
}
};
Throwable t = null;
try {
if (getContainer() != null)
getContainer().run(true, true, runnable);
else
runnable.run(new NullProgressMonitor());
return true;
} catch (InvocationTargetException te) {
t = te.getCause();
} catch (Exception e) {
t = e;
}
PHPUiPlugin.log(new Status(IStatus.ERROR, PHPUiPlugin.ID, 0, "Error cancelling task wizard", t)); //$NON-NLS-1$
if (t instanceof CoreException) {
openError(t.getLocalizedMessage(), ((CoreException) t).getStatus());
} else
openError(t.getLocalizedMessage());
return false;
}
/*
* Open a dialog window.
*
* @param message java.lang.String
*/
private static void openError(final String message) {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
Shell shell = Display.getDefault().getActiveShell();
MessageDialog.openError(shell, PHPUIMessages.FragmentedWizard_0, message);
}
});
}
/*
* Open a dialog window.
*
* @param message java.lang.String
*
* @param status IStatus
*/
private static void openError(final String message, final IStatus status) {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
Shell shell = Display.getDefault().getActiveShell();
ErrorDialog.openError(shell, PHPUIMessages.FragmentedWizard_1, message, status);
}
});
}
@Override
public boolean performFinish() {
if (currentFragment != null)
currentFragment.exit();
final WizardFragment cFragment = currentFragment;
status = Status.OK_STATUS;
final List<WizardFragment> list = getAllWizardFragments();
IRunnableWithProgress runnable = new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) {
// enter & exit the remaining pages
int index = list.indexOf(cFragment);
while (index > 0 && index < list.size() - 1) {
final WizardFragment fragment = (WizardFragment) list.get(++index);
try {
Display.getDefault().syncExec(new Runnable() {
@Override
public void run() {
FragmentedWizardPage page = getFragmentData(fragment);
if (page.getControl() == null && pageContainerHook != null) {
page.createControl(pageContainerHook);
page.getControl().setVisible(false);
}
fragment.enter();
fragment.exit();
}
});
} catch (Exception e) {
PHPUiPlugin.log(new Status(IStatus.ERROR, PHPUiPlugin.ID, 0, "Could not enter/exit page", e)); //$NON-NLS-1$
}
}
if (useJob()) {
class FinishWizardJob extends Job {
public FinishWizardJob() {
super(getJobTitle());
}
@Override
public boolean belongsTo(Object family) {
return "org.eclipse.wst.server.ui.family".equals(family); //$NON-NLS-1$
}
@Override
public IStatus run(IProgressMonitor monitor2) {
try {
Iterator<WizardFragment> iterator = list.iterator();
while (iterator.hasNext())
executeTask(iterator.next(), FINISH, monitor2);
} catch (CoreException ce) {
Status status = new Status(IStatus.ERROR, PHPUiPlugin.ID, 0, ce.getLocalizedMessage(),
null);
PHPUiPlugin.log(status);
return status;
}
return Status.OK_STATUS;
}
}
FinishWizardJob job = new FinishWizardJob();
job.setUser(true);
job.schedule();
} else {
Iterator<WizardFragment> iterator = list.iterator();
while (iterator.hasNext())
try {
WizardFragment fragment = (WizardFragment) iterator.next();
if (!executeTask(fragment, FINISH, monitor)) {
FragmentedWizardPage page = getFragmentData(fragment);
String message = MessageFormat.format(PHPUIMessages.FragmentedWizard_2,
page.getTitle());
status = new Status(IStatus.ERROR, PHPUiPlugin.ID, message);
}
} catch (CoreException e) {
PHPUiPlugin.log(e);
}
}
}
};
Throwable t = null;
try {
if (getContainer() != null)
getContainer().run(true, true, runnable);
else
runnable.run(new NullProgressMonitor());
if (status.getSeverity() != IStatus.OK) {
((WizardDialog) getContainer()).setErrorMessage(status.getMessage());
return false;
}
return true;
} catch (InvocationTargetException te) {
PHPUiPlugin.log(new Status(IStatus.ERROR, PHPUiPlugin.ID, 0, "Error finishing task wizard", te)); //$NON-NLS-1$
t = te.getCause();
} catch (Exception e) {
PHPUiPlugin.log(new Status(IStatus.ERROR, PHPUiPlugin.ID, 0, "Error finishing task wizard 2", e)); //$NON-NLS-1$
t = e;
}
if (t instanceof CoreException) {
openError(t.getLocalizedMessage(), ((CoreException) t).getStatus());
} else if (t instanceof NullPointerException)
openError(PHPUIMessages.FragmentedWizard_7);
else
openError(t.getLocalizedMessage());
return false;
}
public void addPage(IWizardPage page) {
pages.add(page);
page.setWizard(this);
}
protected boolean executeTask(WizardFragment fragment, byte type, IProgressMonitor monitor) throws CoreException {
if (fragment == null) {
return true;
}
if (type == FINISH) {
return fragment.performFinish(monitor);
} else if (type == CANCEL) {
fragment.performCancel(monitor);
}
return true;
}
protected WizardFragment getCurrentWizardFragment() {
return currentFragment;
}
protected void switchWizardFragment(WizardFragment newFragment) {
List<WizardFragment> list = getAllWizardFragments();
int oldIndex = list.indexOf(currentFragment);
int newIndex = list.indexOf(newFragment);
if (oldIndex == newIndex)
return;
if (currentFragment != null)
currentFragment.exit();
if (oldIndex < newIndex)
oldIndex++;
else
oldIndex--;
while (oldIndex != newIndex) {
WizardFragment fragment = (WizardFragment) list.get(oldIndex);
fragment.enter();
fragment.exit();
if (oldIndex < newIndex)
oldIndex++;
else
oldIndex--;
}
currentFragment = newFragment;
currentFragment.enter();
}
private List<WizardFragment> getAllWizardFragments() {
List<WizardFragment> list = new ArrayList<WizardFragment>();
list.add(rootFragment);
addSubWizardFragments(rootFragment, list);
Iterator<WizardFragment> iterator = list.iterator();
while (iterator.hasNext()) {
WizardFragment fragment = (WizardFragment) iterator.next();
if (!wizardModel.equals(fragment.getWizardModel())) {
fragment.setWizardModel(wizardModel);
}
}
return list;
}
private void addSubWizardFragments(WizardFragment fragment, List<WizardFragment> list) {
Iterator<?> iterator = fragment.getChildFragments().iterator();
while (iterator.hasNext()) {
WizardFragment child = (WizardFragment) iterator.next();
list.add(child);
addSubWizardFragments(child, list);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.IWizard#addPages()
*/
@Override
public void addPages() {
if (addingPages)
return;
try {
addingPages = true;
pages = new ArrayList<IWizardPage>();
Iterator<WizardFragment> iterator = getAllWizardFragments().iterator();
while (iterator.hasNext()) {
WizardFragment fragment = (WizardFragment) iterator.next();
FragmentedWizardPage page = getFragmentData(fragment);
if (fragment.hasComposite()) {
if (page == null) {
page = new FragmentedWizardPage(fragment);
fragmentData.put(fragment, page);
}
addPage(page);
}
}
} catch (Exception e) {
PHPUiPlugin.log(new Status(IStatus.ERROR, PHPUiPlugin.ID, 0, "Error adding fragments to wizard", e)); //$NON-NLS-1$
} finally {
addingPages = false;
}
}
/*
* private static void updateWizardPages() { try { current.updatePages();
* current.getContainer().updateButtons(); } catch (Exception e) {
* Trace.trace(Trace.SEVERE, "Error updating wizard pages", e); } }
*/
private FragmentedWizardPage getFragmentData(WizardFragment fragment) {
try {
FragmentedWizardPage page = (FragmentedWizardPage) fragmentData.get(fragment);
if (page != null)
return page;
} catch (Exception e) {
PHPUiPlugin.log(new Status(IStatus.ERROR, PHPUiPlugin.ID, 0, "Error getting fragment data", e)); //$NON-NLS-1$
}
return null;
}
protected void updatePages() {
addPages();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.IWizard#canFinish()
*/
@Override
public boolean canFinish() {
// Default implementation is to check if all pages are complete.
for (int i = 0; i < pages.size(); i++) {
if (!((IWizardPage) pages.get(i)).isPageComplete())
return false;
}
return true;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.IWizard#createPageControls(org.eclipse.swt.
* widgets .Composite)
*/
@Override
public void createPageControls(Composite pageContainer) {
this.pageContainerHook = pageContainer;
// the default behavior is to create all the pages controls
for (int i = 0; i < pages.size(); i++) {
IWizardPage page = (IWizardPage) pages.get(i);
page.createControl(pageContainer);
page.getControl().setVisible(false);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.IWizard#dispose()
*/
@Override
public void dispose() {
// notify pages
for (int i = 0; i < pages.size(); i++) {
((IWizardPage) pages.get(i)).dispose();
}
// dispose of image
if (defaultImage != null) {
defaultImage.dispose();
defaultImage = null;
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.IWizard#getContainer()
*/
@Override
public IWizardContainer getContainer() {
return container;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.IWizard#getDefaultPageImage()
*/
@Override
public Image getDefaultPageImage() {
return defaultImage;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.IWizard#getDialogSettings()
*/
@Override
public IDialogSettings getDialogSettings() {
return dialogSettings;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.wizard.IWizard#getNextPage(org.eclipse.jface.wizard
* .IWizardPage)
*/
@Override
public IWizardPage getNextPage(IWizardPage page) {
int index = pages.indexOf(page);
if (index == pages.size() - 1 || index == -1)
// last page or page not found
return null;
return (IWizardPage) pages.get(index + 1);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.IWizard#getPage(java.lang.String)
*/
@Override
public IWizardPage getPage(String name) {
for (int i = 0; i < pages.size(); i++) {
IWizardPage page = (IWizardPage) pages.get(i);
String pageName = page.getName();
if (pageName.equals(name))
return page;
}
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.IWizard#getPageCount()
*/
@Override
public int getPageCount() {
return pages.size();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.IWizard#getPages()
*/
@Override
public IWizardPage[] getPages() {
return (IWizardPage[]) pages.toArray(new IWizardPage[pages.size()]);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.wizard.IWizard#getPreviousPage(org.eclipse.jface.wizard
* .IWizardPage)
*/
@Override
public IWizardPage getPreviousPage(IWizardPage page) {
int index = pages.indexOf(page);
if (index == 0 || index == -1)
// first page or page not found
return null;
return (IWizardPage) pages.get(index - 1);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.IWizard#getStartingPage()
*/
@Override
public IWizardPage getStartingPage() {
if (pages.size() == 0)
return null;
return (IWizardPage) pages.get(0);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.IWizard#getTitleBarColor()
*/
@Override
public RGB getTitleBarColor() {
return titleBarColor;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.IWizard#getWindowTitle()
*/
@Override
public String getWindowTitle() {
return windowTitle;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.IWizard#isHelpAvailable()
*/
@Override
public boolean isHelpAvailable() {
return isHelpAvailable;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.IWizard#needsPreviousAndNextButtons()
*/
@Override
public boolean needsPreviousAndNextButtons() {
return forcePreviousAndNextButtons || pages.size() > 1;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.IWizard#needsProgressMonitor()
*/
@Override
public boolean needsProgressMonitor() {
return needsProgressMonitor;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.wizard.IWizard#setContainer(org.eclipse.jface.wizard
* .IWizardContainer)
*/
@Override
public void setContainer(IWizardContainer wizardContainer) {
this.container = wizardContainer;
}
public void setDialogSettings(IDialogSettings settings) {
dialogSettings = settings;
}
public void setNeedsProgressMonitor(boolean b) {
needsProgressMonitor = b;
}
public void setForcePreviousAndNextButtons(boolean b) {
forcePreviousAndNextButtons = b;
}
public void setWindowTitle(String title) {
windowTitle = title;
}
protected boolean useJob() {
return false;
}
protected String getJobTitle() {
return getWindowTitle();
}
}