/*!
* 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.designer.core.editor.drilldown.basic;
import org.pentaho.reporting.designer.core.ReportDesignerContext;
import org.pentaho.reporting.designer.core.editor.drilldown.DrillDownParameterTable;
import org.pentaho.reporting.designer.core.editor.drilldown.model.DrillDownModel;
import org.pentaho.reporting.designer.core.editor.drilldown.model.DrillDownParameter;
import org.pentaho.reporting.libraries.base.util.StringUtils;
import org.pentaho.ui.xul.XulComponent;
import org.pentaho.ui.xul.XulDomContainer;
import org.pentaho.ui.xul.binding.Binding;
import org.pentaho.ui.xul.binding.BindingFactory;
import org.pentaho.ui.xul.binding.DefaultBindingFactory;
import org.pentaho.ui.xul.dom.Document;
import javax.swing.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
public class DefaultXulDrillDownController implements XulDrillDownController {
private class TableModelBinding implements PropertyChangeListener {
/**
* This method gets called when a bound property is changed.
*
* @param evt A PropertyChangeEvent object describing the event source and the property that has changed.
*/
public void propertyChange( final PropertyChangeEvent evt ) {
wrapper.setDrillDownParameter( filterParameter( table.getDrillDownParameter() ) );
}
}
protected class RefreshParameterTask implements Runnable {
public RefreshParameterTask() {
}
/**
* When an object implementing interface <code>Runnable</code> is used to create a thread, starting the thread
* causes the object's <code>run</code> method to be called in that separately executing thread.
* <p/>
* The general contract of the method <code>run</code> is that it may take any action whatsoever.
*
* @see Thread#run()
*/
public void run() {
refresh();
}
}
private String name;
private XulDomContainer xulDomContainer;
private DrillDownParameterTable table;
private DrillDownModelWrapper wrapper;
private ReportDesignerContext reportDesignerContext;
public DefaultXulDrillDownController() {
}
protected DrillDownParameter[] filterParameter( final DrillDownParameter[] parameter ) {
final ArrayList<DrillDownParameter> list = new ArrayList<DrillDownParameter>( parameter.length );
for ( int i = 0; i < parameter.length; i++ ) {
final DrillDownParameter downParameter = parameter[ i ];
if ( StringUtils.isEmpty( downParameter.getFormulaFragment() ) ) {
continue;
}
list.add( downParameter );
}
return list.toArray( new DrillDownParameter[ list.size() ] );
}
public DrillDownModel getModel() {
return wrapper.getModel();
}
public String getName() {
return name;
}
public void setName( final String name ) {
this.name = name;
}
public XulDomContainer getXulDomContainer() {
return xulDomContainer;
}
public void setXulDomContainer( final XulDomContainer xulDomContainer ) {
this.xulDomContainer = xulDomContainer;
}
public ReportDesignerContext getReportDesignerContext() {
return reportDesignerContext;
}
public void init( final ReportDesignerContext reportDesignerContext,
final DrillDownModel model,
final String[] fields ) {
if ( model == null ) {
throw new NullPointerException();
}
if ( reportDesignerContext == null ) {
throw new NullPointerException();
}
if ( fields == null ) {
throw new NullPointerException();
}
this.reportDesignerContext = reportDesignerContext;
final Document doc = this.xulDomContainer.getDocumentRoot();
final DefaultBindingFactory bindingFactory = new DefaultBindingFactory();
bindingFactory.setDocument( doc );
bindingFactory.setBindingType( Binding.Type.BI_DIRECTIONAL );
wrapper = new DrillDownModelWrapper( model );
final XulComponent pathElement = doc.getElementById( "path" );//NON-NLS
if ( pathElement != null ) {
bindingFactory.createBinding( wrapper, DrillDownModel.DRILL_DOWN_PATH_PROPERTY, "path", "value" );//NON-NLS
}
final XulComponent configElement = doc.getElementById( "config" );//NON-NLS
if ( configElement != null ) {
bindingFactory.createBinding( wrapper, DrillDownModel.DRILL_DOWN_CONFIG_PROPERTY, "config", "value" );//NON-NLS
}
final XulComponent linkTargetElement = doc.getElementById( "link-target" );//NON-NLS
if ( linkTargetElement != null ) {
bindingFactory.createBinding( wrapper, DrillDownModel.TARGET_FORMULA_PROPERTY, "link-target", "value" );//NON-NLS
}
final XulComponent linkTooltipElement = doc.getElementById( "link-tooltip" );//NON-NLS
if ( linkTooltipElement != null ) {
bindingFactory
.createBinding( wrapper, DrillDownModel.TOOLTIP_FORMULA_PROPERTY, "link-tooltip", "value" );//NON-NLS
}
final XulComponent previewElement = doc.getElementById( "preview" );//NON-NLS
if ( previewElement != null ) {
final BindingFactory singleSourceBinding = new DefaultBindingFactory();
singleSourceBinding.setBindingType( Binding.Type.ONE_WAY );
singleSourceBinding.setDocument( doc );
singleSourceBinding.createBinding( wrapper, "preview", "preview", "value" );//NON-NLS
}
// we manage the binding between the table and the outside world manually
wrapper.refresh();
final XulComponent paramTableElement = doc.getElementById( "parameter-table" );//NON-NLS
if ( paramTableElement instanceof XulDrillDownParameterTable ) {
final XulDrillDownParameterTable parameterTable = (XulDrillDownParameterTable) paramTableElement;
table = parameterTable.getTable();
table.setExtraFields( fields );
table.setReportDesignerContext( reportDesignerContext );
table.setDrillDownParameter( model.getDrillDownParameter() );
table.setHideParameterUi( model.getDrillDownConfig().endsWith( "-no-parameter" ) );
table.addPropertyChangeListener( DrillDownParameterTable.DRILL_DOWN_PARAMETER_PROPERTY, new TableModelBinding() );
}
if ( model.isLimitedEditor() ) {
final XulComponent tooltipAndTargetElement = doc.getElementById( "tooltip-and-target-panel" );//NON-NLS
if ( tooltipAndTargetElement != null ) {
tooltipAndTargetElement.setVisible( false );
}
}
SwingUtilities.invokeLater( new RefreshParameterTask() );
}
protected DrillDownModelWrapper getWrapper() {
return wrapper;
}
/**
* A generic way of returning data from event handlers... can we do better than this? Handle return values from
* invoked methods? possibly?
*
* @return any data associated with events that have been executed.
*/
public Object getData() {
return getModel();
}
/**
* A generic way of passing data to the event handler. It seems we should maybe accept parameters instead of doing
* this.
*
* @param data any data events may want to operate on.
*/
public void setData( final Object data ) {
}
protected DrillDownParameterTable getTable() {
return table;
}
public void refresh() {
getTable().refreshParameterData();
}
public void deactivate() {
}
}