/*
* 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) 2001 - 2013 Object Refinery Ltd, Pentaho Corporation and Contributors.. All rights reserved.
*/
package org.pentaho.reporting.engine.classic.core.modules.gui.base.internal;
import java.awt.FlowLayout;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import org.pentaho.reporting.engine.classic.core.modules.gui.base.PreviewPane;
import org.pentaho.reporting.engine.classic.core.modules.gui.base.actions.ControlAction;
import org.pentaho.reporting.engine.classic.core.modules.gui.base.actions.ControlActionPlugin;
import org.pentaho.reporting.engine.classic.core.modules.gui.base.actions.ExportAction;
import org.pentaho.reporting.engine.classic.core.modules.gui.base.actions.ZoomAction;
import org.pentaho.reporting.engine.classic.core.modules.gui.base.actions.ZoomListActionPlugin;
import org.pentaho.reporting.engine.classic.core.modules.gui.common.DefaultIconTheme;
import org.pentaho.reporting.engine.classic.core.modules.gui.common.IconTheme;
import org.pentaho.reporting.engine.classic.core.modules.gui.commonswing.ActionFactory;
import org.pentaho.reporting.engine.classic.core.modules.gui.commonswing.ActionPlugin;
import org.pentaho.reporting.engine.classic.core.modules.gui.commonswing.ActionPluginMenuComparator;
import org.pentaho.reporting.engine.classic.core.modules.gui.commonswing.DefaultActionFactory;
import org.pentaho.reporting.engine.classic.core.modules.gui.commonswing.ExportActionPlugin;
import org.pentaho.reporting.engine.classic.core.modules.gui.commonswing.SwingCommonModule;
import org.pentaho.reporting.engine.classic.core.modules.gui.commonswing.SwingGuiContext;
import org.pentaho.reporting.libraries.base.config.Configuration;
import org.pentaho.reporting.libraries.base.util.ObjectUtilities;
import org.pentaho.reporting.libraries.xmlns.common.ParserUtil;
/**
* Creation-Date: 17.11.2006, 15:06:51
*
* @author Thomas Morgner
*/
public class PreviewPaneUtilities {
private static final String ICON_THEME_CONFIG_KEY =
"org.pentaho.reporting.engine.classic.core.modules.gui.common.IconTheme"; //$NON-NLS-1$
private static final String ACTION_FACTORY_CONFIG_KEY =
"org.pentaho.reporting.engine.classic.core.modules.gui.base.ActionFactory"; //$NON-NLS-1$
private static final String CATEGORY_PREFIX = "org.pentaho.reporting.engine.classic.core.modules.gui.swing.category.";
//$NON-NLS-1$
private static final ZoomAction[] EMPTY_ZOOM_ACTION = new ZoomAction[0];
private PreviewPaneUtilities() {
}
public static JMenu createMenu( final ActionCategory cat ) {
final JMenu menu = new JMenu();
menu.setText( cat.getDisplayName() );
final Integer mnemonicKey = cat.getMnemonicKey();
if ( mnemonicKey != null ) {
menu.setMnemonic( mnemonicKey.intValue() );
}
final String toolTip = cat.getShortDescription();
if ( toolTip != null && toolTip.length() > 0 ) {
menu.setToolTipText( toolTip );
}
return menu;
}
public static ZoomAction[] buildMenu( final JMenu menu, final ActionPlugin[] actions, final PreviewPane pane ) {
if ( actions.length == 0 ) {
return EMPTY_ZOOM_ACTION;
}
ZoomAction[] retval = EMPTY_ZOOM_ACTION;
Arrays.sort( actions, new ActionPluginMenuComparator() );
boolean separatorPending = false;
int count = 0;
for ( int i = 0; i < actions.length; i++ ) {
final ActionPlugin actionPlugin = actions[i];
if ( actionPlugin.isAddToMenu() == false ) {
continue;
}
if ( count > 0 && separatorPending ) {
menu.addSeparator();
separatorPending = false;
}
if ( actionPlugin instanceof ExportActionPlugin ) {
final ExportActionPlugin exportPlugin = (ExportActionPlugin) actionPlugin;
final ExportAction action = new ExportAction( exportPlugin, pane );
menu.add( new JMenuItem( action ) );
count += 1;
} else if ( actionPlugin instanceof ControlActionPlugin ) {
final ControlActionPlugin controlPlugin = (ControlActionPlugin) actionPlugin;
final ControlAction action = new ControlAction( controlPlugin, pane );
menu.add( new JMenuItem( action ) );
count += 1;
} else if ( actionPlugin instanceof ZoomListActionPlugin ) {
retval = buildViewMenu( menu, pane );
}
if ( actionPlugin.isSeparated() ) {
separatorPending = true;
}
}
return retval;
}
private static ZoomAction[] buildViewMenu( final JMenu zoom, final PreviewPane pane ) {
final double[] zoomFactors = pane.getZoomFactors();
final ZoomAction[] zoomActions = new ZoomAction[zoomFactors.length];
for ( int i = 0; i < zoomFactors.length; i++ ) {
final double factor = zoomFactors[i];
zoomActions[i] = new ZoomAction( factor, pane );
zoom.add( new JMenuItem( zoomActions[i] ) );
}
return zoomActions;
}
public static void addActionsToToolBar( final JToolBar toolBar, final ActionPlugin[] reportActions,
final JComboBox zoomSelector, final PreviewPane pane ) {
if ( reportActions == null ) {
return;
}
boolean separatorPending = false;
int count = 0;
for ( int i = 0; i < reportActions.length; i++ ) {
final ActionPlugin actionPlugin = reportActions[i];
if ( actionPlugin.isAddToToolbar() == false ) {
continue;
}
if ( count > 0 && separatorPending ) {
toolBar.addSeparator();
separatorPending = false;
}
if ( actionPlugin instanceof ExportActionPlugin ) {
final ExportActionPlugin exportPlugin = (ExportActionPlugin) actionPlugin;
final ExportAction action = new ExportAction( exportPlugin, pane );
toolBar.add( createButton( action, pane.getSwingGuiContext() ) );
count += 1;
} else if ( actionPlugin instanceof ControlActionPlugin ) {
final ControlActionPlugin controlPlugin = (ControlActionPlugin) actionPlugin;
final ControlAction action = new ControlAction( controlPlugin, pane );
toolBar.add( createButton( action, pane.getSwingGuiContext() ) );
count += 1;
} else if ( actionPlugin instanceof ZoomListActionPlugin ) {
final ZoomListActionPlugin zoomListActionPlugin = (ZoomListActionPlugin) actionPlugin;
zoomListActionPlugin.setComponent( zoomSelector );
final JPanel zoomPane = new JPanel();
zoomPane.setLayout( new FlowLayout( FlowLayout.LEFT ) );
zoomPane.add( zoomSelector );
toolBar.add( zoomPane );
count += 1;
}
if ( actionPlugin.isSeparated() ) {
separatorPending = true;
}
}
}
/**
* Creates a button using the given action properties for the button's initialisation.
*
* @param action
* the action used to set up the button.
* @return a button based on the supplied action.
*/
private static JButton createButton( final Action action, final SwingGuiContext swingGuiContext ) {
final JButton button = new JButton( action );
boolean needText = true;
if ( isLargeButtonsEnabled( swingGuiContext ) ) {
final Icon icon = (Icon) action.getValue( SwingCommonModule.LARGE_ICON_PROPERTY );
if ( icon != null && ( icon.getIconHeight() > 1 && icon.getIconHeight() > 1 ) ) {
button.setIcon( icon );
needText = false;
}
} else {
final Icon icon = (Icon) action.getValue( Action.SMALL_ICON );
if ( icon != null && ( icon.getIconHeight() > 1 && icon.getIconHeight() > 1 ) ) {
button.setIcon( icon );
needText = false;
}
}
if ( needText ) {
final Object value = action.getValue( Action.NAME );
if ( value != null ) {
button.setText( String.valueOf( value ) );
}
} else {
button.setText( null );
}
final Object value = button.getAction().getValue( Action.ACCELERATOR_KEY );
if ( value instanceof KeyStroke ) {
button.unregisterKeyboardAction( (KeyStroke) value );
}
return button;
}
private static boolean isLargeButtonsEnabled( final SwingGuiContext swingGuiContext ) {
final Configuration configuration = swingGuiContext.getConfiguration();
if ( "true".equals( configuration.getConfigProperty( //$NON-NLS-1$
"org.pentaho.reporting.engine.classic.core.modules.gui.base.LargeIcons" ) ) ) { //$NON-NLS-1$
return true;
}
return false;
}
public static double getNextZoomOut( final double zoom, final double[] zoomFactors ) {
if ( zoom <= zoomFactors[0] ) {
return ( zoom * 2.0 ) / 3.0;
}
final double largestZoom = zoomFactors[zoomFactors.length - 1];
if ( zoom > largestZoom ) {
final double linear = ( zoom * 2.0 ) / 3.0;
if ( linear < largestZoom ) {
return largestZoom;
}
return linear;
}
for ( int i = zoomFactors.length - 1; i >= 0; i-- ) {
final double factor = zoomFactors[i];
if ( factor < zoom ) {
return factor;
}
}
return ( zoom * 2.0 ) / 3.0;
}
public static double getNextZoomIn( final double zoom, final double[] zoomFactors ) {
final double largestZoom = zoomFactors[zoomFactors.length - 1];
if ( zoom >= largestZoom ) {
return ( zoom * 1.5 );
}
final double smallestZoom = zoomFactors[0];
if ( zoom < smallestZoom ) {
final double linear = ( zoom * 1.5 );
if ( linear > smallestZoom ) {
return smallestZoom;
}
return linear;
}
for ( int i = 0; i < zoomFactors.length; i++ ) {
final double factor = zoomFactors[i];
if ( factor > zoom ) {
return factor;
}
}
return ( zoom * 1.5 );
}
public static IconTheme createIconTheme( final Configuration config ) {
final String themeClass = config.getConfigProperty( ICON_THEME_CONFIG_KEY );
final Object maybeTheme = ObjectUtilities.loadAndInstantiate( themeClass, PreviewPane.class, IconTheme.class );
final IconTheme iconTheme;
if ( maybeTheme != null ) {
iconTheme = (IconTheme) maybeTheme;
} else {
iconTheme = new DefaultIconTheme();
}
iconTheme.initialize( config );
return iconTheme;
}
public static ActionFactory createActionFactory( final Configuration config ) {
final String factoryClass = config.getConfigProperty( ACTION_FACTORY_CONFIG_KEY );
final Object maybeFactory =
ObjectUtilities.loadAndInstantiate( factoryClass, PreviewPane.class, ActionFactory.class );
final ActionFactory actionFactory;
if ( maybeFactory != null ) {
actionFactory = (ActionFactory) maybeFactory;
} else {
actionFactory = new DefaultActionFactory();
}
return actionFactory;
}
public static CategoryTreeItem[] buildMenuTree( final ActionCategory[] categories ) {
final CategoryTreeItem[] tree = new CategoryTreeItem[categories.length];
for ( int i = 0; i < categories.length; i++ ) {
final ActionCategory category = categories[i];
tree[i] = new CategoryTreeItem( category );
}
for ( int j = 0; j < tree.length; j++ ) {
final CategoryTreeItem item = tree[j];
final String itemName = item.getName();
int parentWeight = 0;
CategoryTreeItem parent = null;
// now for each item, find the best parent item.
for ( int k = 0; k < tree.length; k++ ) {
if ( k == j ) {
// never add yourself ..
continue;
}
final CategoryTreeItem treeItem = tree[k];
final String parentName = treeItem.getName();
if ( itemName.startsWith( parentName ) == false ) {
continue;
}
if ( parentName.length() > parentWeight ) {
parent = treeItem;
parentWeight = parentName.length();
}
}
item.setParent( parent );
}
for ( int j = 0; j < tree.length; j++ ) {
final CategoryTreeItem item = tree[j];
final CategoryTreeItem parent = item.getParent();
if ( parent != null ) {
parent.add( item );
}
}
return tree;
}
public static Map<ActionCategory, ActionPlugin[]> loadActions( final SwingGuiContext swingGuiContext ) {
final HashMap<ActionCategory, ActionPlugin[]> actions = new HashMap<ActionCategory, ActionPlugin[]>();
final Configuration configuration = swingGuiContext.getConfiguration();
final ActionCategory[] categories = loadCategories( swingGuiContext );
final ActionFactory factory = PreviewPaneUtilities.createActionFactory( configuration );
for ( int i = 0; i < categories.length; i++ ) {
final ActionCategory category = categories[i];
actions.put( category, factory.getActions( swingGuiContext, category.getName() ) );
}
return actions;
}
public static ActionCategory[] loadCategories( final SwingGuiContext swingGuiContext ) {
final ArrayList categories = new ArrayList();
final Configuration configuration = swingGuiContext.getConfiguration();
final Iterator keys = configuration.findPropertyKeys( CATEGORY_PREFIX );
while ( keys.hasNext() ) {
final String enableKey = (String) keys.next();
if ( enableKey.endsWith( ".enabled" ) == false ) { //$NON-NLS-1$
continue;
}
if ( "true".equals( configuration.getConfigProperty( enableKey ) ) == false ) { //$NON-NLS-1$
continue;
}
final String base = enableKey.substring( 0, enableKey.length() - ".enabled".length() ); //$NON-NLS-1$
if ( base.length() == 0 ) {
continue;
}
final String categoryKey = base.substring( CATEGORY_PREFIX.length() );
final String className = configuration.getConfigProperty( base + ".class" ); //$NON-NLS-1$
ActionCategory actionCategory;
if ( className == null ) {
actionCategory = new ActionCategory();
} else {
actionCategory =
(ActionCategory) ObjectUtilities.loadAndInstantiate( className, PreviewPane.class, ActionCategory.class );
if ( actionCategory == null ) {
actionCategory = new ActionCategory();
}
}
final String positionText = configuration.getConfigProperty( base + ".position" ); //$NON-NLS-1$
actionCategory.setPosition( ParserUtil.parseInt( positionText, 0 ) );
actionCategory.setName( categoryKey );
actionCategory.setResourceBase( configuration.getConfigProperty( base + ".resource-base" ) ); //$NON-NLS-1$
actionCategory.setResourcePrefix( configuration.getConfigProperty( base + ".resource-prefix" ) ); //$NON-NLS-1$
actionCategory.initialize( swingGuiContext );
categories.add( actionCategory );
}
return (ActionCategory[]) categories.toArray( new ActionCategory[categories.size()] );
}
}