/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.ui.common.wizard;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.designer.ui.common.util.WizardUtil;
/**
* <p>
* An extension of Wizard that provides the following additional features:
* </p>
* <ul>
* <li>Dynamic manipulation of pages during wizard execution.</li>
* </ul>
* <p>
* </p>
*
* @since 8.0
*/
public abstract class AbstractWizard extends Wizard {
// ============================================================================================================================
// Constants
private static final String WIDTH = "width"; //$NON-NLS-1$
private static final String HEIGHT = "height"; //$NON-NLS-1$
// ============================================================================================================================
// Variables
private final List pgs;
// ============================================================================================================================
// Constructors
/**
* <p>
* </p>
*
* @since 4.0
*/
public AbstractWizard( final AbstractUIPlugin plugin,
final String title,
final ImageDescriptor image ) {
this.pgs = new ArrayList();
WizardUtil.initialize(this, plugin, title, image);
}
// ============================================================================================================================
// Overridden Methods
/**
* <p>
* </p>
*
* @see org.eclipse.jface.wizard.Wizard#addPage(org.eclipse.jface.wizard.IWizardPage)
* @since 4.0
*/
@Override
public final void addPage( final IWizardPage page ) {
addPage(page, this.pgs.size());
}
/**
* <p>
* </p>
*
* @since 4.0
*/
public final void addPage( final IWizardPage page,
final int index ) {
CoreArgCheck.isNotNull(page);
CoreArgCheck.isNonNegative(index);
this.pgs.add(index, page);
page.setWizard(this);
}
/**
* <p>
* </p>
*
* @see org.eclipse.jface.wizard.Wizard#canFinish()
* @since 4.0
*/
@Override
public boolean canFinish() {
// Can finish if all pages are complete
for (final Iterator iter = this.pgs.iterator(); iter.hasNext();) {
if (!((IWizardPage)iter.next()).isPageComplete()) {
return false;
}
}
return true;
}
/**
* Indicates if the wizard can go to the page after the specified page.
*
* @param thePage the page requested to flip to the next page
* @return <code>true</code> if can go to next page; <code>false</code> otherwise.
* @since 4.1
*/
public boolean canFlipToNextPage( final IWizardPage thePage ) {
final int index = indexOf(thePage);
return ((index != -1) && thePage.isPageComplete() && ((getPageCount() - 1) > index));
}
/**
* <p>
* </p>
*
* @see org.eclipse.jface.wizard.Wizard#createPageControls(org.eclipse.swt.widgets.Composite)
* @since 4.0
*/
@Override
public void createPageControls( final Composite pageContainer ) {
// Default behavior is to size to previously saved size
createPageControls(pageContainer, true);
}
/**
* <p>
* </p>
*
* @see org.eclipse.jface.wizard.Wizard#createPageControls(org.eclipse.swt.widgets.Composite)
* @since 4.0
*/
public void createPageControls( final Composite pageContainer,
final boolean restorePrevSize ) {
CoreArgCheck.isNotNull(pageContainer);
for (final Iterator iter = this.pgs.iterator(); iter.hasNext();) {
final IWizardPage pg = (IWizardPage)iter.next();
pg.createControl(pageContainer);
// page is responsible for ensuring the created control is accessible
// via getControl.
Assert.isNotNull(pg.getControl());
}
// Add resize listener to container that will save size in settings when user changes it
final IDialogSettings settings = getDialogSettings();
final Shell shell = getShell();
shell.addControlListener(new ControlAdapter() {
@Override
public void controlResized( final ControlEvent event ) {
if (shell.isVisible()) {
final Point size = shell.getSize();
settings.put(WIDTH, size.x);
settings.put(HEIGHT, size.y);
}
}
});
// Restore container's previous size if desired
if (restorePrevSize) {
try {
shell.setSize(settings.getInt(WIDTH), settings.getInt(HEIGHT));
shell.layout();
// reposition shell if necessary when bounds are off-screen
final Rectangle screenSize = shell.getDisplay().getClientArea();
final Rectangle bounds = shell.getBounds();
int newX = -1;
int newY = -1;
if (bounds.x + bounds.width > screenSize.width) {
newX = bounds.x - (bounds.width + bounds.x - screenSize.width);
}
if (bounds.y + bounds.height > screenSize.height) {
newY = bounds.y - (bounds.height + bounds.y - screenSize.height);
}
if ((newX != -1) || (newY != -1)) {
shell.setLocation((newX == -1) ? bounds.x : newX, (newY == -1) ? bounds.y : newY);
}
} catch (final NumberFormatException ignored) {
// Not even worth logging
}
}
}
/**
* <p>
* </p>
*
* @see org.eclipse.jface.wizard.Wizard#dispose()
* @since 4.0
*/
@Override
public void dispose() {
for (final Iterator iter = this.pgs.iterator(); iter.hasNext();) {
((IWizardPage)iter.next()).dispose();
}
super.dispose();
}
/**
* <p>
* </p>
*
* @since 4.0
*/
public abstract boolean finish();
/**
* <p>
* </p>
*
* @see org.eclipse.jface.wizard.Wizard#getNextPage(org.eclipse.jface.wizard.IWizardPage)
* @since 4.0
*/
@Override
public IWizardPage getNextPage( final IWizardPage page ) {
CoreArgCheck.isNotNull(page);
final int ndx = indexOf(page);
// Return null if last page or page not found
if (ndx == this.pgs.size() - 1 || ndx < 0) {
return null;
}
return (IWizardPage)this.pgs.get(ndx + 1);
}
/**
* <p>
* </p>
*
* @see org.eclipse.jface.wizard.Wizard#getPage(java.lang.String)
* @since 4.0
*/
@Override
public final IWizardPage getPage( final String name ) {
CoreArgCheck.isNotNull(name);
for (final Iterator iter = this.pgs.iterator(); iter.hasNext();) {
final IWizardPage pg = (IWizardPage)iter.next();
if (name.equals(pg.getName())) {
return pg;
}
}
return null;
}
/**
* <p>
* </p>
*
* @see org.eclipse.jface.wizard.Wizard#getPageCount()
* @since 4.0
*/
@Override
public int getPageCount() {
return this.pgs.size();
}
/**
* <p>
* </p>
*
* @see org.eclipse.jface.wizard.Wizard#getPages()
* @since 4.0
*/
@Override
public final IWizardPage[] getPages() {
return (IWizardPage[])this.pgs.toArray(new IWizardPage[this.pgs.size()]);
}
/**
* <p>
* </p>
*
* @see org.eclipse.jface.wizard.Wizard#getPreviousPage(org.eclipse.jface.wizard.IWizardPage)
* @since 4.0
*/
@Override
public IWizardPage getPreviousPage( final IWizardPage page ) {
CoreArgCheck.isNotNull(page);
final int ndx = indexOf(page);
// Return null if last page or page not found
if (ndx <= 0) {
return null;
}
return (IWizardPage)this.pgs.get(ndx - 1);
}
// ============================================================================================================================
// Property Methods
/**
* <p>
* </p>
*
* @see org.eclipse.jface.wizard.Wizard#getStartingPage()
* @since 4.0
*/
@Override
public final IWizardPage getStartingPage() {
if (this.pgs.size() == 0) {
return null;
}
return (IWizardPage)this.pgs.get(0);
}
/**
* Gets the page index of the specified page.
*
* @param thePage the page whose index is being requested
* @return the page index or -1 if not found
* @since 4.1
*/
public int indexOf( final IWizardPage thePage ) {
return this.pgs.indexOf(thePage);
}
// ============================================================================================================================
// MVC Controller Methods
/**
* <p>
* </p>
*
* @see org.eclipse.jface.wizard.Wizard#needsPreviousAndNextButtons()
* @since 4.0
*/
@Override
public final boolean needsPreviousAndNextButtons() {
return (super.needsPreviousAndNextButtons() || this.pgs.size() > 1);
}
/**
* <p>
* </p>
*
* @see org.eclipse.jface.wizard.Wizard#performFinish()
* @since 4.0
*/
@Override
public final boolean performFinish() {
final boolean finished = finish();
if (finished) {
WizardUtil.saveSettings(this);
}
return finished;
}
/**
* <p>
* </p>
*
* @since 4.0
*/
public final void removePage( final IWizardPage page ) {
CoreArgCheck.isNotNull(page);
this.pgs.remove(page);
}
}