/*! * 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.actions.global; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.pentaho.reporting.designer.core.ReportDesignerBoot; import org.pentaho.reporting.designer.core.actions.AbstractDesignerContextAction; import org.pentaho.reporting.designer.core.actions.ActionMessages; import org.pentaho.reporting.designer.core.util.exceptions.UncaughtExceptionsModel; import org.pentaho.reporting.libraries.base.util.PngEncoder; import org.pentaho.reporting.libraries.xmlns.common.ParserUtil; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; public class ScreenCaptureAction extends AbstractDesignerContextAction { private static class ScreenShotFilenameFilter implements FilenameFilter { private ScreenShotFilenameFilter() { } public boolean accept( final File dir, final String name ) { if ( name.startsWith( PREFIX ) && name.endsWith( PNG_SUFFIX ) ) { return true; } return false; } } private static class GlobalKeyEventHandler implements KeyEventPostProcessor { public boolean postProcessKeyEvent( final KeyEvent e ) { if ( e.getID() == KeyEvent.KEY_PRESSED ) { final int menuKeyMask = getMenuKeyMask(); if ( e.getKeyCode() == KeyEvent.VK_P && ( e.getModifiers() & menuKeyMask ) == menuKeyMask ) { saveScreenShot( e.getModifiers() ); return true; } } return false; } } private static final Log logger = LogFactory.getLog( ScreenCaptureAction.class ); private static final String PNG_SUFFIX = ".png"; private static final String PREFIX = "prd-screen-capture-"; private static boolean installed; public ScreenCaptureAction() { putValue( Action.NAME, ActionMessages.getString( "ScreenCaptureAction.Text" ) ); putValue( Action.SHORT_DESCRIPTION, ActionMessages.getString( "ScreenCaptureAction.Description" ) ); putValue( Action.MNEMONIC_KEY, ActionMessages.getOptionalMnemonic( "ScreenCaptureAction.Mnemonic" ) ); //putValue(Action.ACCELERATOR_KEY, ActionMessages.getOptionalKeyStroke("ScreenCaptureAction.Accelerator")); installGlobally(); } public void actionPerformed( final ActionEvent e ) { saveScreenShot( e.getModifiers() ); } public static void installGlobally() { if ( !installed ) { installed = true; KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventPostProcessor( new GlobalKeyEventHandler() ); } } private static int getMenuKeyMask() { try { return Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); } catch ( UnsupportedOperationException he ) { // headless exception extends UnsupportedOperation exception, // but the HeadlessException is not defined in older JDKs... return InputEvent.CTRL_MASK; } } public static void saveScreenShot( final int modifiers ) { final Component component = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); final GraphicsConfiguration graphicsConfiguration = component.getGraphicsConfiguration(); final GraphicsDevice graphicsDevice = graphicsConfiguration.getDevice(); try { final Robot robot = new Robot( graphicsDevice ); final BufferedImage image; if ( ( modifiers & ActionEvent.SHIFT_MASK ) == ActionEvent.SHIFT_MASK ) { image = robot.createScreenCapture( graphicsConfiguration.getBounds() ); } else { image = robot.createScreenCapture( component.getBounds() ); } final String homeDirectory = ReportDesignerBoot.getInstance().getGlobalConfig().getConfigProperty( "user.home", "." ); final File homeDir = new File( homeDirectory ); final File f = generateName( homeDir ); if ( f == null ) { return; } final FileOutputStream fout = new FileOutputStream( f ); try { final PngEncoder encoder = new PngEncoder(); encoder.setCompressionLevel( 6 ); encoder.setEncodeAlpha( false ); encoder.setImage( image ); final byte[] bytes = encoder.pngEncode(); fout.write( bytes ); } finally { fout.close(); } } catch ( IOException ioe ) { UncaughtExceptionsModel.getInstance().addException( ioe ); } catch ( AWTException e1 ) { // ignore UncaughtExceptionsModel.getInstance().addException( e1 ); } } private static File generateName( final File directory ) { final File[] files = directory.listFiles( new ScreenShotFilenameFilter() ); int max = 0; for ( int i = 0; i < files.length; i++ ) { try { final File file = files[ i ]; final String name = file.getName().substring( PREFIX.length() ).substring( PNG_SUFFIX.length() ); final int idx = ParserUtil.parseInt( name, -1 ); if ( idx > max ) { max = idx; } } catch ( Exception e ) { // non-fatal, complete ignore logger.debug( e ); } } for ( int i = max + 1; i < 99999; i++ ) { final String nodeName = PREFIX + i + PNG_SUFFIX; final File f = new File( directory, nodeName ); if ( f.exists() == false ) { return f; } } return null; } }