⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jmedesktop.java

📁 java 3d game jme 工程开发源代码
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/*
 * Copyright (c) 2003-2009 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.jmex.awt.swingui;

import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.FocusEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.beans.PropertyVetoException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JViewport;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.basic.BasicInternalFrameUI;

import com.jme.bounding.OrientedBoundingBox;
import com.jme.image.Texture;
import com.jme.image.Texture2D;
import com.jme.input.InputHandler;
import com.jme.input.KeyInput;
import com.jme.input.MouseInput;
import com.jme.input.action.InputAction;
import com.jme.input.action.InputActionEvent;
import com.jme.math.Ray;
import com.jme.math.Vector2f;
import com.jme.math.Vector3f;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.BlendState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jmex.awt.input.AWTKeyInput;
import com.jmex.awt.input.AWTMouseInput;
import com.jmex.awt.swingui.dnd.JMEDragAndDrop;

/**
 * A quad that displays a {@link JDesktopPane} as texture. It also converts jME mouse and keyboard events to Swing
 * events. The latter does work for ortho mode only. There are some issues with using multiple of this desktops.
 * <p>
 * Notes
 * <ul>
 * <li> Only access the Swing UI from the Swing event dispatch thread! See {@link SwingUtilities#invokeLater}
 * and <a href="http://java.sun.com/docs/books/tutorial/uiswing/concurrency/index.html">Swing tutorial</a> for details.</li>
 * <li>If you would like to change the L&F take into account that PropertiesDialog and PropertiesDialog2 change
 * the L&F setting upon invocation (you can e.g. change the L&F after the dialog).</li>
 * </ul>
 *
 * @see ImageGraphics
 */
public class JMEDesktop extends Quad {
    private static final Logger logger = Logger.getLogger(JMEDesktop.class
            .getName());
    
    private static final long serialVersionUID = 1L;
    private ImageGraphics graphics;
    private JDesktopPane desktop;
    private Texture texture;
    private boolean initialized;
    private int width;
    private int height;

    private boolean showingJFrame = false;
    private final Frame awtWindow;
    private int desktopWidth;
    private int desktopHeight;
    private static final int DOUBLE_CLICK_TIME = 300;
    private final InputHandler inputHandler;
    private JMEDesktop.XUpdateAction xUpdateAction;
    private JMEDesktop.YUpdateAction yUpdateAction;
    private WheelUpdateAction wheelUpdateAction;
    private JMEDesktop.ButtonAction allButtonsUpdateAction;
    private InputAction keyUpdateAction;
    private JMEDragAndDrop dragAndDropSupport;

    /**
     * @return JMEDragAndDrop used for this desktop
     */
    public JMEDragAndDrop getDragAndDropSupport() {
        return dragAndDropSupport;
    }

    /**
     * @param dragAndDropSupport JMEDragAndDrop to be used for this desktop
     * @see JMEDragAndDrop#setDesktop(JMEDesktop)
     */
    public void setDragAndDropSupport( JMEDragAndDrop dragAndDropSupport ) {
        this.dragAndDropSupport = dragAndDropSupport;
    }

    /**
     * @see #setShowingJFrame
     * @return true if frame is displayed
     */
    public boolean isShowingJFrame() {
        return showingJFrame;
    }

    /**
     * @param showingJFrame true to display the desktop in a JFrame instead on this quad.
     * @deprecated for debuggin only
     */
    public void setShowingJFrame( boolean showingJFrame ) {
        this.showingJFrame = showingJFrame;
        awtWindow.setVisible( showingJFrame );
        awtWindow.repaint();
    }

    /**
     * Allows to disable input for the whole desktop and to add custom input actions.
     *
     * @return this desktops input hander for input bindings
     * @see #getXUpdateAction()
     * @see #getYUpdateAction()
     * @see #getWheelUpdateAction()
     * @see #getButtonUpdateAction(int)
     * @see #getKeyUpdateAction()
     */
    public InputHandler getInputHandler() {
        return inputHandler;
    }

    /**
     * Create a quad with a Swing-Texture. Creates the quad and the JFrame but do not setup the rest.
     * Call {@link #setup(int, int, boolean, InputHandler)} to finish setup.
     *
     * @param name name of this desktop
     */
    public JMEDesktop( String name ) {
        super( name );

        inputHandler = new InputHandler();

        awtWindow = new Frame() {
            private static final long serialVersionUID = 1L;
            public boolean isShowing() {
                return true;
            }

            public boolean isVisible() {
//                if ( new Throwable().getStackTrace()[1].getMethodName().startsWith( "requestFocus" ) ) {
//                    logger.info( "requestFocus" );
//                }

                if ( awtWindow.isFocusableWindow()
                        && new Throwable().getStackTrace()[1].getMethodName().startsWith( "requestFocus" ) ) {
                    return false;
                }
                return initialized || super.isVisible();
            }

            public Graphics getGraphics() {
                if ( !showingJFrame ) {
                    return graphics == null ? super.getGraphics() : graphics.create();
                }
                
                return super.getGraphics();
            }

            public boolean isFocused() {
                return true;
            }
        };
        awtWindow.setFocusableWindowState( false );
        Container contentPane = awtWindow;
        awtWindow.setUndecorated( true );
        dontDrawBackground( contentPane );
//            ( (JComponent) contentPane ).setOpaque( false );

        desktop = new JDesktopPane() {
            private static final long serialVersionUID = 1L;
            public void paint( Graphics g ) {
                if ( !isShowingJFrame() ) {
                    g.clearRect( 0, 0, getWidth(), getHeight() );
                }
                super.paint( g );
            }

            public boolean isOptimizedDrawingEnabled() {
                return false;
            }
        };

        new ScrollPaneRepaintFixListener().addTo( desktop );


        final Color transparent = new Color( 0, 0, 0, 0 );
        desktop.setBackground( transparent );
        desktop.setFocusable( true );
        desktop.addMouseListener( new MouseAdapter() {
            public void mousePressed( MouseEvent e ) {
                desktop.requestFocusInWindow();
            }
        } );

        // this internal frame is a workaround for key binding problems in JDK1.5
        // todo: this workaround does not seem to work on mac
        if ( System.getProperty( "os.name" ).toLowerCase().indexOf( "mac" ) < 0 ) {
            final JInternalFrame internalFrame = new JInternalFrame();
            internalFrame.setUI( new BasicInternalFrameUI( internalFrame ) {
                protected void installComponents() {
                }
            } );
            internalFrame.setOpaque( false );
            internalFrame.setBackground( null );
            internalFrame.getContentPane().setLayout( new BorderLayout() );
            internalFrame.getContentPane().add( desktop, BorderLayout.CENTER );
            internalFrame.setVisible( true );
            internalFrame.setBorder( null );
            contentPane.add( internalFrame );
        }
        else {
            // this would have suited for JDK1.4:
            contentPane.add( desktop, BorderLayout.CENTER );
        }

        awtWindow.pack();

        RepaintManager.currentManager( null ).setDoubleBufferingEnabled( false );
    }

    /**
     * Create a quad with a Swing-Texture.
     * Note that for the texture a width and height that is a power of 2 is used if the graphics card does
     * not support the specified size for textures. E.g. this results in a 1024x512
     * texture for a 640x480 desktop (consider using a 512x480 desktop in that case).
     *
     * @param name               name of the spatial
     * @param width              desktop width
     * @param height             desktop height
     * @param inputHandlerParent InputHandler where the InputHandler of this desktop should be added as subhandler,
     *                           may be null to provide custom input handling or later adding of InputHandler(s)
     * @see #getInputHandler()
     */
    public JMEDesktop( String name, final int width, final int height, InputHandler inputHandlerParent ) {
        this( name, width, height, false, inputHandlerParent );
    }

    /**
     * Create a quad with a Swing-Texture.
     * Note that for the texture a width and height that is a power of 2 is used if the graphics card does
     * not support the specified size for textures or mipMapping is true. E.g. this results in a 1024x512
     * texture for a 640x480 desktop (consider using a 512x480 desktop in that case).
     *
     * @param name               name of the spatial
     * @param width              desktop width
     * @param height             desktop hieght
     * @param mipMapping         true to compute mipmaps for the desktop (not recommended), false for creating
     *                           a single image texture
     * @param inputHandlerParent InputHandler where the InputHandler of this desktop should be added as subhandler,
     *                           may be null to provide custom input handling or later adding of InputHandler(s)
     * @see #getInputHandler()
     */
    public JMEDesktop( String name, final int width, final int height, boolean mipMapping, InputHandler inputHandlerParent ) {
        this( name );

        setup( width, height, mipMapping, inputHandlerParent );
    }

    /**
     * Set up the desktop quad - may be called only once.
     * Note that for the texture a width and height that is a power of 2 is used if the graphics card does
     * not support the specified size for textures or mipMapping is true. E.g. this results in a 1024x512
     * texture for a 640x480 desktop (consider using a 512x480 desktop in that case).
     *
     * @param width              desktop width
     * @param height             desktop hieght
     * @param mipMapping         true to compute mipmaps for the desktop (not recommended), false for creating
     *                           a single image texture
     * @param inputHandlerParent InputHandler where the InputHandler of this desktop should be added as subhandler,
     *                           may be null to provide custom input handling or later adding of InputHandler(s)
     * @see #getInputHandler()
     */
    public void setup( int width, int height, boolean mipMapping, InputHandler inputHandlerParent ) {
        reconstruct( null, null, null, null );
        if ( inputHandlerParent != null ) {
            inputHandlerParent.addToAttachedHandlers( inputHandler );
        }

        if ( initialized ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -