/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.reporting.engine.classic.wizard.ui.xul.components;
import org.pentaho.reporting.engine.classic.core.AbstractReportDefinition;
import org.pentaho.reporting.engine.classic.core.AttributeNames;
import org.pentaho.reporting.engine.classic.core.MasterReport;
import org.pentaho.reporting.engine.classic.core.SubReport;
import org.pentaho.reporting.engine.classic.core.designtime.DesignTimeContext;
import org.pentaho.reporting.engine.classic.core.modules.gui.base.PreviewDialog;
import org.pentaho.reporting.engine.classic.core.modules.gui.commonswing.ExceptionDialog;
import org.pentaho.reporting.engine.classic.wizard.WizardProcessorUtil;
import org.pentaho.reporting.engine.classic.wizard.model.WizardSpecification;
import org.pentaho.reporting.engine.classic.wizard.ui.xul.Messages;
import org.pentaho.reporting.engine.classic.wizard.ui.xul.WizardEditorModel;
import org.pentaho.reporting.libraries.base.util.DebugLog;
import org.pentaho.reporting.libraries.designtime.swing.LibSwingUtil;
import org.pentaho.ui.xul.XulDomContainer;
import org.pentaho.ui.xul.binding.Binding;
import org.pentaho.ui.xul.binding.BindingConvertor;
import org.pentaho.ui.xul.binding.BindingFactory;
import org.pentaho.ui.xul.containers.XulDeck;
import org.pentaho.ui.xul.impl.AbstractXulEventHandler;
import java.awt.*;
import java.util.ArrayList;
/**
* The wizard-controler manages the navigation between the wizard-panes. All panes are organized as a list, where each
* panel cannot be enabled if the previous panels are not valid or enabled.
* <p/>
* It is possible to jump back to previous steps and change values there. In some cases, this will just update the
* model, but in some cases this will invalidate the subsequent steps (for instance, if the query has been changed).
*
* @author William Seyler
*/
public class LinearWizardController extends AbstractXulEventHandler implements WizardController {
// Binding converters
private class BackButtonBindingConverter extends BindingConvertor<Integer, Boolean> {
/* (non-Javadoc)
* @see org.pentaho.ui.xul.binding.BindingConvertor#sourceToTarget(java.lang.Object)
*/
@Override
public Boolean sourceToTarget( final Integer value ) {
return !( value > 0 );
}
/* (non-Javadoc)
* @see org.pentaho.ui.xul.binding.BindingConvertor#targetToSource(java.lang.Object)
*/
@Override
public Integer targetToSource( final Boolean value ) {
return null;
}
}
private static final Messages messages = Messages.getInstance();
private static final String DISABLED_PROPERTY_NAME = "disabled"; //$NON-NLS-1$
private static final String VALID_PROPERTY_NAME = "valid"; //$NON-NLS-1$
private static final String NOT_DISABLED_PROPERTY = "!disabled"; //$NON-NLS-1$
private static final String NEXT_BTN_ELEMENT_ID = "next_btn"; //$NON-NLS-1$
private static final String BACK_BTN_ELEMENT_ID = "back_btn"; //$NON-NLS-1$
private static final String FINISH_BTN_ELEMENT_ID = "finish_btn"; //$NON-NLS-1$
private static final String CONTENT_DECK_ELEMENT_ID = "content_deck"; //$NON-NLS-1$
private ArrayList<WizardStep> steps;
private WizardEditorModel editorModel;
private int activeStep = -1; // bogus active step
private boolean canceled;
private boolean finished;
private XulDomContainer mainXULContainer;
private BindingFactory bf;
private Binding nextButtonBinding, finishedButtonBinding; // previewButtonBinding;
private DesignTimeContext designTimeContext;
public LinearWizardController( final WizardEditorModel editorModel,
final BindingFactory bf ) {
this.steps = new ArrayList<WizardStep>();
this.editorModel = editorModel;
this.bf = bf;
}
/**
* @param designTimeContext
*/
public void setDesignTimeContext( final DesignTimeContext designTimeContext ) {
this.designTimeContext = designTimeContext;
for ( final WizardStep step : steps ) {
step.setDesignTimeContext( designTimeContext );
}
}
public WizardEditorModel getEditorModel() {
return editorModel;
}
public void addStep( final AbstractWizardStep step ) {
if ( step == null ) {
throw new NullPointerException();
}
step.setEditorModel( editorModel );
steps.add( step );
}
public void removeStep( final WizardStep step ) {
steps.remove( step );
}
public WizardStep getStep( final int step ) {
return steps.get( step );
}
public int getStepCount() {
return steps.size();
}
public void setActiveStep( final int step ) {
final int oldActiveStep = this.activeStep;
if ( oldActiveStep >= 0 ) {
final WizardStep deactivatingWizardStep = steps.get( oldActiveStep );
if ( !deactivatingWizardStep.stepDeactivating() ) {
DebugLog.log( deactivatingWizardStep.getStepName() + ": Canceled setActiveStep()" ); //$NON-NLS-1$
return;
}
}
this.activeStep = step;
final WizardStep activatingWizardStep = steps.get( activeStep );
updateBindings();
activatingWizardStep.stepActivating();
// update the controller panel
final XulDeck deck = (XulDeck) mainXULContainer.getDocumentRoot().getElementById( CONTENT_DECK_ELEMENT_ID );
deck.setSelectedIndex( activeStep );
this.firePropertyChange( ACTIVE_STEP_PROPERTY_NAME, oldActiveStep, this.activeStep );
}
public int getActiveStep() {
return activeStep;
}
public void initialize() {
if ( steps.isEmpty() ) {
throw new IllegalStateException(
messages.getString( "LINEAR_WIZARD_CONTROLLER.Empty_Steps_Error" ) ); //$NON-NLS-1$
}
for ( final WizardStep wizardStep : steps ) {
wizardStep.setBindings();
}
bf.setBindingType( Binding.Type.ONE_WAY );
bf.createBinding( this, ACTIVE_STEP_PROPERTY_NAME, BACK_BTN_ELEMENT_ID, DISABLED_PROPERTY_NAME,
new BackButtonBindingConverter() );
// bf.createBinding(this, ACTIVE_STEP_PROPERTY_NAME, STEP_PANEL_ELEMENT_ID, SELECTED_INDEX_PROPERTY_NAME);
setActiveStep( 0 ); // Fires the events to update the buttons
setCancelled( false );
setFinished( false );
}
protected void updateBindings() {
// Destroy any old bindings
if ( nextButtonBinding != null ) {
nextButtonBinding.destroyBindings();
}
if ( finishedButtonBinding != null ) {
finishedButtonBinding.destroyBindings();
}
// if (previewButtonBinding != null) {
// previewButtonBinding.destroyBindings();
// }
// Create new binding to the current wizard panel
bf.setBindingType( Binding.Type.ONE_WAY );
nextButtonBinding =
bf.createBinding( getStep( getActiveStep() ), VALID_PROPERTY_NAME, NEXT_BTN_ELEMENT_ID, NOT_DISABLED_PROPERTY );
finishedButtonBinding =
bf.createBinding( getStep( getActiveStep() ), FINISHABLE_PROPERTY_NAME, FINISH_BTN_ELEMENT_ID,
NOT_DISABLED_PROPERTY );
// previewButtonBinding = bf.createBinding(getStep(getActiveStep()), PREVIEWABLE_PROPERTY_NAME,
// PREVIEW_BTN_ELEMENT_ID, NOT_DISABLED_PROPERTY);
try {
nextButtonBinding.fireSourceChanged();
finishedButtonBinding.fireSourceChanged();
// previewButtonBinding.fireSourceChanged();
} catch ( Exception e ) {
if ( designTimeContext == null ) {
ExceptionDialog.showExceptionDialog( null, "Error", e.getMessage(), e );
} else {
designTimeContext.error( e );
}
}
}
public void cancel() {
setCancelled( true );
setFinished( false );
}
public void setCancelled( final boolean canceled ) {
final boolean oldCanceled = this.canceled;
this.canceled = canceled;
this.firePropertyChange( CANCELLED_PROPERTY_NAME, oldCanceled, this.canceled );
}
public boolean isCancelled() {
return canceled;
}
public void finish() {
setFinished( true );
setCancelled( false );
}
public boolean isFinished() {
return finished;
}
public void setFinished( final boolean finished ) {
final boolean oldFinished = this.finished;
this.finished = finished;
this.firePropertyChange( FINISHED_PROPERTY_NAME, oldFinished, this.finished );
}
// Button click methods
public void next() {
setActiveStep( getActiveStep() + 1 );
}
public void back() {
setActiveStep( getActiveStep() - 1 );
}
public void preview() {
// At some point some parts of this should probably be XULified
final PreviewDialog dialog;
if ( designTimeContext != null ) {
final Window window = designTimeContext.getParentWindow();
if ( window instanceof Dialog ) {
dialog = new PreviewDialog( (Dialog) window );
} else if ( window instanceof Frame ) {
dialog = new PreviewDialog( (Frame) window );
} else {
dialog = new PreviewDialog();
}
} else {
dialog = new PreviewDialog();
}
dialog.setTitle( messages.getString( "LINEAR_WIZARD_CONTROLLER.Report_Preview" ) );
dialog.setModal( false );
try {
final AbstractReportDefinition reportDefinition = editorModel.getReportDefinition();
final AbstractReportDefinition element = (AbstractReportDefinition) reportDefinition.derive();
final WizardSpecification spec = editorModel.getReportSpec();
element.setAttribute( AttributeNames.Wizard.NAMESPACE, "enable", Boolean.TRUE );
WizardProcessorUtil.applyWizardSpec( element, (WizardSpecification) spec.clone() );
WizardProcessorUtil.ensureWizardProcessorIsAdded( element, null );
if ( element instanceof MasterReport ) {
dialog.setReportJob( (MasterReport) element );
} else {
final MasterReport report = new MasterReport();
report.getReportHeader().addSubReport( (SubReport) element );
dialog.setReportJob( report );
}
dialog.pack();
LibSwingUtil.centerDialogInParent( dialog );
dialog.setVisible( true );
} catch ( Exception e ) {
if ( designTimeContext != null ) {
designTimeContext.error( e );
} else {
ExceptionDialog.showExceptionDialog( null, "Error", e.getMessage(), e );
}
}
}
// Stuff for XUL
@Override
public String getName() {
return "wizard_controller"; //$NON-NLS-1$
}
public void onLoad() {
DebugLog.log( "called onLoad()" ); //$NON-NLS-1$
initialize();
}
/**
* @param mainWizardContainer
*/
public void registerMainXULContainer( final XulDomContainer mainWizardContainer ) {
mainXULContainer = mainWizardContainer;
bf.setDocument( mainWizardContainer.getDocumentRoot() );
}
public void setBindingFactory( final BindingFactory bf ) {
this.bf = bf;
}
/* (non-Javadoc)
* @see org.pentaho.reporting.engine.classic.wizard.ui.xul.components.WizardController#getBindingFactory()
*/
public BindingFactory getBindingFactory() {
return bf;
}
}