/*! * 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.report; import org.pentaho.reporting.designer.core.editor.ReportDocumentContext; import org.pentaho.reporting.designer.core.editor.ReportRenderContext; import org.pentaho.reporting.designer.core.editor.report.layouting.CrosstabRenderer; import org.pentaho.reporting.designer.core.editor.report.layouting.ElementRenderer; import org.pentaho.reporting.designer.core.editor.report.layouting.RootBandRenderer; import org.pentaho.reporting.designer.core.model.ModelUtility; import org.pentaho.reporting.engine.classic.core.AbstractReportDefinition; import org.pentaho.reporting.engine.classic.core.CrosstabGroup; import org.pentaho.reporting.engine.classic.core.CrosstabOtherGroupBody; import org.pentaho.reporting.engine.classic.core.Element; import org.pentaho.reporting.engine.classic.core.Group; import org.pentaho.reporting.engine.classic.core.GroupBody; import org.pentaho.reporting.engine.classic.core.GroupDataBody; import org.pentaho.reporting.engine.classic.core.PageDefinition; import org.pentaho.reporting.engine.classic.core.RelationalGroup; import org.pentaho.reporting.engine.classic.core.ReportElement; import org.pentaho.reporting.engine.classic.core.RootLevelBand; import org.pentaho.reporting.engine.classic.core.SubGroupBody; import org.pentaho.reporting.engine.classic.core.event.ReportModelEvent; import org.pentaho.reporting.engine.classic.core.event.ReportModelListener; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.EventListenerList; import java.util.ArrayList; /** * Todo: Document me! * * @author Thomas Morgner */ public class RootBandRenderingModel { private class ModelUpdateListener implements ReportModelListener { public void nodeChanged( final ReportModelEvent event ) { if ( event.isNodeDeleteEvent() || event.isNodeAddedEvent() ) { final Object o = event.getParameter(); if ( o instanceof Group || o instanceof GroupBody || o instanceof RootLevelBand ) { refresh(); return; } } if ( event.getType() == ReportModelEvent.NODE_STRUCTURE_CHANGED ) { if ( event.getElement() instanceof RootLevelBand ) { refresh(); } } if ( event.getType() == ReportModelEvent.NODE_PROPERTIES_CHANGED ) { final Object element = event.getElement(); if ( element instanceof RootLevelBand ) { final RootLevelBand band = (RootLevelBand) element; final boolean modelHide = ModelUtility.isHideInLayoutGui( band ); final boolean stateShow = isShown( band ); if ( modelHide == stateShow ) { refresh(); } } } } } private class RendererChangeHandler implements ChangeListener { public void stateChanged( final ChangeEvent e ) { fireReportRenderEvent(); } } private ArrayList<ElementRenderer> rootBandComponents; private ReportDocumentContext renderContext; private AbstractReportDefinition report; private EventListenerList eventListenerList; private RendererChangeHandler rendererChangeHandler; public RootBandRenderingModel( final ReportRenderContext renderContext ) { if ( renderContext == null ) { throw new NullPointerException(); } this.rendererChangeHandler = new RendererChangeHandler(); this.eventListenerList = new EventListenerList(); this.rootBandComponents = new ArrayList<ElementRenderer>(); this.renderContext = renderContext; this.report = renderContext.getReportDefinition(); this.report.addReportModelListener( new ModelUpdateListener() ); refresh(); } protected boolean isShown( final ReportElement element ) { if ( element == null ) { throw new NullPointerException(); } final int length = rootBandComponents.size(); for ( int i = 0; i < length; i++ ) { final ElementRenderer renderer = rootBandComponents.get( i ); if ( renderer.getRepresentationId() == element.getObjectID() ) { return true; } } return false; } public void addChangeListener( final ChangeListener changeListener ) { eventListenerList.add( ChangeListener.class, changeListener ); } public void removeChangeListener( final ChangeListener changeListener ) { eventListenerList.remove( ChangeListener.class, changeListener ); } public void addReportRenderListener( final ReportRenderListener changeListener ) { eventListenerList.add( ReportRenderListener.class, changeListener ); } public void removeReportRenderListener( final ReportRenderListener changeListener ) { eventListenerList.remove( ReportRenderListener.class, changeListener ); } protected void fireReportRenderEvent() { final ReportRenderEvent ce = new ReportRenderEvent( this ); final ReportRenderListener[] changeListeners = eventListenerList.getListeners( ReportRenderListener.class ); for ( int i = 0; i < changeListeners.length; i++ ) { final ReportRenderListener listener = changeListeners[ i ]; listener.layoutChanged( ce ); } } protected void fireChangeEvent() { final ChangeEvent ce = new ChangeEvent( this ); final ChangeListener[] changeListeners = eventListenerList.getListeners( ChangeListener.class ); for ( int i = 0; i < changeListeners.length; i++ ) { final ChangeListener listener = changeListeners[ i ]; listener.stateChanged( ce ); } } // todo Codesmell public ReportDocumentContext getRenderContext() { return renderContext; } public ElementRenderer[] getAllRenderers() { return rootBandComponents.toArray( new ElementRenderer[ rootBandComponents.size() ] ); } protected void refresh() { if ( report == null ) { clearRenderers(); fireChangeEvent(); return; } final ArrayList<ElementRenderer> rootBandComponents = new ArrayList<ElementRenderer>( 20 ); if ( renderContext.isBandedContext() ) { if ( ModelUtility.isHideInLayoutGui( report.getPageHeader() ) == false ) { rootBandComponents.add( new RootBandRenderer( report.getPageHeader(), renderContext ) ); } } if ( ModelUtility.isHideInLayoutGui( report.getReportHeader() ) == false ) { rootBandComponents.add( new RootBandRenderer( report.getReportHeader(), renderContext ) ); } final Group[] groups = collectGroups(); for ( int i = 0; i < groups.length; i++ ) { final Group group = groups[ i ]; if ( group instanceof RelationalGroup ) { final RelationalGroup relationalGroup = (RelationalGroup) group; if ( ModelUtility.isHideInLayoutGui( relationalGroup.getHeader() ) == false ) { rootBandComponents.add( new RootBandRenderer( relationalGroup.getHeader(), renderContext ) ); } } final Element bodyElement = group.getBody(); if ( bodyElement instanceof GroupDataBody ) { final GroupDataBody body = (GroupDataBody) bodyElement; if ( ModelUtility.isHideInLayoutGui( body.getDetailsHeader() ) == false ) { rootBandComponents.add( new RootBandRenderer( body.getDetailsHeader(), renderContext ) ); } if ( ModelUtility.isHideInLayoutGui( body.getNoDataBand() ) == false ) { rootBandComponents.add( new RootBandRenderer( body.getNoDataBand(), renderContext ) ); } if ( ModelUtility.isHideInLayoutGui( body.getItemBand() ) == false ) { rootBandComponents.add( new RootBandRenderer( body.getItemBand(), renderContext ) ); } if ( ModelUtility.isHideInLayoutGui( body.getDetailsFooter() ) == false ) { rootBandComponents.add( new RootBandRenderer( body.getDetailsFooter(), renderContext ) ); } break; } else if ( group instanceof CrosstabGroup ) { rootBandComponents.add( new CrosstabRenderer( (CrosstabGroup) group, renderContext ) ); break; } } for ( int i = groups.length - 1; i >= 0; i -= 1 ) { final Group group = groups[ i ]; if ( group instanceof RelationalGroup ) { final RelationalGroup relationalGroup = (RelationalGroup) group; if ( ModelUtility.isHideInLayoutGui( relationalGroup.getFooter() ) == false ) { rootBandComponents.add( new RootBandRenderer( relationalGroup.getFooter(), renderContext ) ); } } } if ( ModelUtility.isHideInLayoutGui( report.getReportFooter() ) == false ) { rootBandComponents.add( new RootBandRenderer( report.getReportFooter(), renderContext ) ); } if ( renderContext.isBandedContext() ) { if ( ModelUtility.isHideInLayoutGui( report.getPageFooter() ) == false ) { rootBandComponents.add( new RootBandRenderer( report.getPageFooter(), renderContext ) ); } if ( ModelUtility.isHideInLayoutGui( report.getWatermark() ) == false ) { rootBandComponents.add( new RootBandRenderer( report.getWatermark(), renderContext ) ); } } if ( isChange( rootBandComponents ) ) { clearRenderers(); this.rootBandComponents.addAll( rootBandComponents ); for ( int i = 0; i < rootBandComponents.size(); i++ ) { final ElementRenderer renderer = rootBandComponents.get( i ); renderer.addChangeListener( rendererChangeHandler ); } fireChangeEvent(); } } private boolean isChange( final ArrayList<ElementRenderer> rootBandComponents ) { if ( rootBandComponents.size() != this.rootBandComponents.size() ) { return true; } for ( int i = 0; i < rootBandComponents.size(); i++ ) { final ElementRenderer newRenderer = rootBandComponents.get( i ); final ElementRenderer oldRenderer = this.rootBandComponents.get( i ); if ( newRenderer.getRepresentationId() != oldRenderer.getRepresentationId() ) { return true; } if ( oldRenderer.isHideInLayout() != newRenderer.isHideInLayout() ) { return true; } } return false; } private Group[] collectGroups() { Group group = report.getRootGroup(); final ArrayList<Group> list = new ArrayList<Group>(); while ( group != null ) { list.add( group ); final Element bodyElement = group.getBody(); if ( bodyElement instanceof SubGroupBody ) { final SubGroupBody body = (SubGroupBody) bodyElement; group = body.getGroup(); continue; } else if ( bodyElement instanceof CrosstabOtherGroupBody ) { final CrosstabOtherGroupBody body = (CrosstabOtherGroupBody) bodyElement; group = body.getGroup(); continue; } group = null; } return list.toArray( new Group[ list.size() ] ); } public void dispose() { clearRenderers(); } private void clearRenderers() { final ElementRenderer[] allRenderers = rootBandComponents.toArray( new ElementRenderer[ rootBandComponents.size() ] ); for ( int i = 0; i < allRenderers.length; i++ ) { final ElementRenderer renderer = allRenderers[ i ]; renderer.removeChangeListener( rendererChangeHandler ); } this.rootBandComponents.clear(); } public PageDefinition getPageDefinition() { return renderContext.getContextRoot().getPageDefinition(); } }