/*! * 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.model.selection; import org.pentaho.reporting.engine.classic.core.Element; import org.pentaho.reporting.libraries.designtime.swing.WeakEventListenerList; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; public class DefaultReportSelectionModel implements DocumentContextSelectionModel { private WeakEventListenerList listenerList; private LinkedHashMap<Object, Object> backend; private Object[] valuesCached; public DefaultReportSelectionModel() { listenerList = new WeakEventListenerList(); backend = new LinkedHashMap<Object, Object>(); } public void addReportSelectionListener( final ReportSelectionListener listener ) { listenerList.add( ReportSelectionListener.class, listener ); } public void removeReportSelectionListener( final ReportSelectionListener listener ) { listenerList.remove( ReportSelectionListener.class, listener ); } public int getSelectionCount() { return backend.size(); } public Object getSelectedElement( final int index ) { fillCaches(); return valuesCached[ index ]; } public void clearSelection() { final Object[] objects; if ( valuesCached == null ) { objects = backend.values().toArray(); } else { objects = valuesCached; } for ( int i = 0; i < objects.length; i++ ) { remove( objects[ i ] ); } } private boolean contains( final Object[] elements, final Object o ) { for ( int i = 0; i < elements.length; i++ ) { if ( elements[ i ] == o ) { return true; } } return false; } public void setSelectedElements( final Object[] elements ) { // Bulk update. // Step 1: Remove all elements that are not part of the new selection. // Keep all elements that are part of the new selection, so that we do not fire add-events for them later final Iterator iterator = backend.values().iterator(); while ( iterator.hasNext() ) { final Object elementFromOldSelection = iterator.next(); if ( contains( elements, elementFromOldSelection ) == false ) { iterator.remove(); valuesCached = null; fireSelectionRemoved( elementFromOldSelection ); } } // now add all new elements and fire events for the new ones .. for ( int i = 0; i < elements.length; i++ ) { final Object element = elements[ i ]; final Object key = computeKey( element ); if ( backend.containsKey( key ) == false ) { backend.put( key, element ); valuesCached = null; fireSelectionAdded( element ); } } } private Object computeKey( final Object o ) { if ( o instanceof Element ) { final Element e = (Element) o; return e.getObjectID(); } else { return System.identityHashCode( o ); } } protected void fireSelectionAdded( final Object selection ) { final ReportSelectionEvent event = new ReportSelectionEvent( this, selection ); final ReportSelectionListener[] reportSelectionListeners = listenerList.getListeners( ReportSelectionListener.class ); for ( int i = 0; i < reportSelectionListeners.length; i++ ) { final ReportSelectionListener listener = reportSelectionListeners[ i ]; listener.selectionAdded( event ); } fireLeadSelectionChanged( getLeadSelection() ); } protected void fireSelectionRemoved( final Object selection ) { final ReportSelectionEvent event = new ReportSelectionEvent( this, selection ); final ReportSelectionListener[] reportSelectionListeners = listenerList.getListeners( ReportSelectionListener.class ); for ( int i = 0; i < reportSelectionListeners.length; i++ ) { final ReportSelectionListener listener = reportSelectionListeners[ i ]; listener.selectionRemoved( event ); } fireLeadSelectionChanged( getLeadSelection() ); } protected void fireLeadSelectionChanged( final Object selection ) { final ReportSelectionEvent event = new ReportSelectionEvent( this, selection ); final ReportSelectionListener[] reportSelectionListeners = listenerList.getListeners( ReportSelectionListener.class ); for ( int i = 0; i < reportSelectionListeners.length; i++ ) { final ReportSelectionListener listener = reportSelectionListeners[ i ]; listener.leadSelectionChanged( event ); } } public boolean add( final Object element ) { final Object key = computeKey( element ); if ( backend.containsKey( key ) == false ) { backend.put( key, element ); valuesCached = null; fireSelectionAdded( element ); return true; } return false; } public void remove( final Object element ) { final Object key = computeKey( element ); if ( backend.containsKey( key ) ) { backend.remove( key ); valuesCached = null; fireSelectionRemoved( element ); } } public boolean isSelected( final Object o ) { return backend.containsKey( computeKey( o ) ); } public Object[] getSelectedElements() { fillCaches(); return valuesCached.clone(); } public Object getLeadSelection() { if ( backend.isEmpty() ) { return null; } fillCaches(); return valuesCached[ valuesCached.length - 1 ]; } private void fillCaches() { if ( valuesCached == null ) { valuesCached = backend.values().toArray(); } } public <T> List<T> getSelectedElementsOfType( final Class<T> t ) { ArrayList<T> list = new ArrayList<T>(); for ( Object o : backend.values() ) { if ( t.isInstance( o ) ) { //noinspection unchecked list.add( (T) o ); } } return Collections.unmodifiableList( list ); } }