org.apache.wicket.extensions.wizard.Wizard Maven / Gradle / Ivy
Show all versions of wicket-extensions Show documentation
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.wicket.extensions.wizard;
import org.apache.wicket.Component;
import org.apache.wicket.feedback.ContainerFeedbackMessageFilter;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.IFormSubmittingComponent;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.request.resource.PackageResourceReference;
/**
* A wizard is a dialog component that takes users through a number of steps to complete a task. It
* has common functionality like a next, previous, finish and cancel button, and it uses a
* {@link IWizardModel} to navigate through the steps.
*
* Before you can use the wizard component, it needs to be initialized with a model. You do this by
* calling {@link #init(IWizardModel)} with the wizard model you intent to use.
*
*
*
* This default implementation should be useful for basic cases, if the layout is exactly what you
* need. If you want to provide your own layout and/ or have more or less components (e.g. you want
* to additionally provide an overview component), you can override this class and add the
* components you want yourself using methods like {@link #newButtonBar(String)} et-cetera.
*
*
* @author Eelco Hillenius
*/
public class Wizard extends Panel implements IWizardModelListener, IWizard
{
/** Component id of the buttons panel as used by the default wizard panel. */
public static final String BUTTONS_ID = "buttons";
/** Component id of the feedback panel as used by the default wizard panel. */
public static final String FEEDBACK_ID = "feedback";
/** Component id of the header panel as used by the default wizard panel. */
public static final String HEADER_ID = "header";
/** Component id of the overview panel as used by the default wizard panel. */
public static final String OVERVIEW_ID = "overview";
/** Component id of the form as used by the default wizard panel. */
public static final String FORM_ID = "form";
/**
* Component id of the view panel (where the main wizard contents go) as used by the default
* wizard panel.
*/
public static final String VIEW_ID = "view";
private static final long serialVersionUID = 1L;
/**
* The form in which the view is nested, and on which the wizard buttons work.
*/
private Form> form;
/** The wizard model. */
private IWizardModel wizardModel;
private final boolean addDefaultCssStyle;
/**
* Construct. Adds the default style.
*
* If you override this class, it makes sense to call this constructor (super(id)), then - in
* your constructor - construct a transition model and then call {@link #init(IWizardModel)} to
* initialize the wizard.
*
*
* This constructor is not meant for normal clients of this class
*
*
* @param id
* The component model
*/
public Wizard(final String id)
{
this(id, true);
}
/**
* Construct.
*
* If you override this class, it makes sense to call this constructor (super(id)), then - in
* your constructor - construct a transition model and then call {@link #init(IWizardModel)} to
* initialize the wizard.
*
*
* This constructor is not meant for normal clients of this class
*
*
* @param id
* The component model
* @param addDefaultCssStyle
* Whether to add the {@link #addDefaultCssStyle() default style}
*/
public Wizard(final String id, final boolean addDefaultCssStyle)
{
super(id);
this.addDefaultCssStyle = addDefaultCssStyle;
}
/**
* Construct with a transition model. Adds the default style.
*
* For most clients, this is typically the right constructor to use.
*
*
* @param id
* The component id
* @param wizardModel
* The transitions model
*/
public Wizard(final String id, final IWizardModel wizardModel)
{
this(id, wizardModel, true);
}
/**
* Construct with a transition model.
*
* For most clients, this is typically the right constructor to use.
*
*
* @param id
* The component id
* @param wizardModel
* The transitions model
* @param addDefaultCssStyle
* Whether to add the {@link #addDefaultCssStyle() default style}
*/
public Wizard(final String id, final IWizardModel wizardModel, final boolean addDefaultCssStyle)
{
super(id);
init(wizardModel);
this.addDefaultCssStyle = addDefaultCssStyle;
}
/**
* Will let the wizard contribute a CSS include to the page's header. It will add Wizard.css
* from this package. This method is typically called by the class that creates the wizard.
*
* @param response
*/
public void addDefaultCssStyle(final IHeaderResponse response)
{
response.renderCSSReference(new PackageResourceReference(Wizard.class, "Wizard.css"));
}
@Override
public void renderHead(final IHeaderResponse response)
{
super.renderHead(response);
if (addDefaultCssStyle)
{
addDefaultCssStyle(response);
}
}
/**
* Convenience method to get the active step from the model.
*
* @return The active step
*/
public final IWizardStep getActiveStep()
{
return getWizardModel().getActiveStep();
}
/**
* Gets the form in which the view is nested, and on which the wizard buttons work.
*
* @return The wizard form
*/
public Form> getForm()
{
return form;
}
/**
* @see org.apache.wicket.extensions.wizard.IWizard#getWizardModel()
*/
public final IWizardModel getWizardModel()
{
return wizardModel;
}
/**
* Turn versioning off for wizards. This works best when the wizard is not
* accessed from bookmarkable pages, so that the url doesn't change at all.
*
* @return False
* @see org.apache.wicket.Component#isVersioned()
*/
@Override
public boolean isVersioned()
{
return false;
}
/**
* @see org.apache.wicket.extensions.wizard.IWizardModelListener#onActiveStepChanged(org.apache.wicket.extensions.wizard.IWizardStep)
*/
public void onActiveStepChanged(final IWizardStep newStep)
{
form.replace(newStep.getView(VIEW_ID, this, this));
form.replace(newStep.getHeader(HEADER_ID, this, this));
}
/**
* Called when the wizard is canceled.
*/
public void onCancel()
{
}
/**
* Called when the wizard is finished.
*/
public void onFinish()
{
}
/**
* Initialize this wizard with a transition model.
*
* If you constructed this wizard using a constructor without the transitions model argument,
* you must call this method prior to actually using it.
*
*
* @param wizardModel
*/
protected void init(final IWizardModel wizardModel)
{
if (wizardModel == null)
{
throw new IllegalArgumentException("argument wizardModel must be not null");
}
this.wizardModel = wizardModel;
form = newForm(FORM_ID);
addOrReplace(form);
// dummy view to be replaced
form.addOrReplace(new WebMarkupContainer(HEADER_ID));
form.addOrReplace(newFeedbackPanel(FEEDBACK_ID));
// add dummy view; will be replaced on initialization
form.addOrReplace(new WebMarkupContainer(VIEW_ID));
form.addOrReplace(newButtonBar(BUTTONS_ID));
form.addOrReplace(newOverviewBar(OVERVIEW_ID));
wizardModel.addListener(this);
// reset model to prepare for action
wizardModel.reset();
}
/**
* Create a new button bar. Clients can override this method to provide a custom button bar.
*
* @param id
* The id to be used to construct the component
*
* @return A new button bar
*/
protected Component newButtonBar(final String id)
{
return new WizardButtonBar(id, this);
}
/**
* Create a new feedback panel. Clients can override this method to provide a custom feedback
* panel.
*
* @param id
* The id to be used to construct the component
*
* @return A new feedback panel
*/
protected Component newFeedbackPanel(final String id)
{
return new FeedbackPanel(id, new ContainerFeedbackMessageFilter(this));
}
/**
* Create a new form. Clients can override this method to provide a custom {@link Form}.
*
* @param
* The form's model object type
*
* @param id
* The id to be used to construct the component
* @return a new form
*/
protected Form newForm(final String id)
{
return new Form(id);
}
@Override
protected void onBeforeRender()
{
super.onBeforeRender();
Component buttonBar = form.get(BUTTONS_ID);
if (buttonBar instanceof IDefaultButtonProvider)
{
IFormSubmittingComponent defaultButton = ((IDefaultButtonProvider)buttonBar).getDefaultButton(wizardModel);
form.setDefaultButton(defaultButton);
}
}
/**
* Create a new overview bar. Clients can override this method to provide a custom bar.
*
* @param id
* The id to be used to construct the component
*
* @return A new overview bar
*/
protected Component newOverviewBar(final String id)
{
// return a dummy component by default as we don't have an overview
// component
return new WebMarkupContainer(id).setVisible(false);
}
}