/** * Copyright (c) 2014 Marc Fiume <mfiume@cs.toronto.edu> * Unauthorized use of this file is strictly prohibited. * * All rights reserved. No warranty, explicit or implicit, provided. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ package mfiume.component.transition; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLayeredPane; import javax.swing.JPanel; import javax.swing.SwingUtilities; /** * * @author mfiume */ public class JTransitionPanel extends JPanel { private static final float DEFAULT_SLIDE_DURATION = 50.0f; // holds all the layers, including the animation panel private final JLayeredPane layers; // the panel currently on display private JPanel currentPanel; private final JPanel placeHolderOne; // holds the incoming panel, for layout purposes private final JPanel placeHolderTwo; // holds the current panel //private final JPanel blankOutCanvas; // blank out the previous panels, while animating private final JPanel animationCanvas; // where animation happens private void addPanelAndFill(JComponent child, JComponent parent) { parent.removeAll(); parent.setLayout(new BorderLayout()); parent.add(child,BorderLayout.CENTER); parent.updateUI(); } public enum TransitionType { PUSH_LEFT, PUSH_RIGHT, PUSH_UP, PUSH_DOWN, ZOOM_IN, ZOOM_OUT, SLIDE_LEFT, SLIDE_RIGHT, SLIDE_UP, SLIDE_DOWN, FADE_IN, FADE_OUT, NONE } @Override public void setBackground(Color c) { //if (blankOutCanvas != null) { blankOutCanvas.setBackground(c); } super.setBackground(c); } public JTransitionPanel() { currentPanel = null; this.setDoubleBuffered(true); layers = new JLayeredPane(); addPanelAndFill(layers,this); placeHolderOne = new JPanel(); placeHolderTwo = new JPanel(); //blankOutCanvas = new JPanel(); animationCanvas = new JPanel() { @Override public void paintComponent(Graphics g) { // do nothing System.out.println("Flash"); } }; animationCanvas.setOpaque(false); //blankOutCanvas.setVisible(true); layers.add(placeHolderOne,0,0); layers.add(placeHolderTwo,1,0); //layers.add(blankOutCanvas,2,0); layers.add(animationCanvas,2,0); this.addComponentListener(new ComponentListener() { public void componentResized(ComponentEvent e) { rebound(); } public void componentMoved(ComponentEvent e) { } public void componentShown(ComponentEvent e) { } public void componentHidden(ComponentEvent e) { } }); } private void rebound() { for (Component c : layers.getComponents()) { c.setBounds(layers.getBounds()); } this.updateUI(); } /** * Replace the existing panel with a new one, animating the transition as * specified. * * @param newPanel The new panel to show * @param type The type of transition to use to show it * @param doneListener The action to take when the transition is complete */ public void push(final JPanel newPanel, TransitionType type, final ActionListener doneListener) { // TODO: layout the new panel before it is rendered //blankOutCanvas.setVisible(true); //addPanelAndFill(newPanel,placeHolderOne); ActionListener uberListener = new ActionListener() { public void actionPerformed(ActionEvent e) { final JTransitionPanel instance = JTransitionPanel.this; SwingUtilities.invokeLater(new Runnable() { public void run() { placeHolderOne.removeAll(); addPanelAndFill(newPanel,placeHolderTwo); //blankOutCanvas.setVisible(false); animationCanvas.setVisible(false); instance.setBackground(placeHolderTwo.getBackground()); instance.updateUI(); } }); if (doneListener != null) { doneListener.actionPerformed(e); } } }; Point origin = new Point(0, 0); switch (type) { case SLIDE_LEFT: Animator.animateSlide( animationCanvas, currentPanel, newPanel, DEFAULT_SLIDE_DURATION, uberListener, new Point(this.getWidth(), 0), origin); break; case SLIDE_RIGHT: Animator.animateSlide( animationCanvas, currentPanel, newPanel, DEFAULT_SLIDE_DURATION, uberListener, new Point(-this.getWidth(), 0), origin); break; case SLIDE_UP: Animator.animateSlide( this, currentPanel, newPanel, DEFAULT_SLIDE_DURATION, uberListener, new Point(0, this.getHeight()), origin); break; case SLIDE_DOWN: Animator.animateSlide( animationCanvas, currentPanel, newPanel, DEFAULT_SLIDE_DURATION, uberListener, new Point(0, -this.getHeight()), origin); break; case PUSH_LEFT: Animator.animatePush( animationCanvas, currentPanel, newPanel, DEFAULT_SLIDE_DURATION, uberListener, new Point(this.getWidth(), 0), origin); break; case PUSH_RIGHT: Animator.animatePush( animationCanvas, currentPanel, newPanel, DEFAULT_SLIDE_DURATION, uberListener, new Point(-this.getWidth(), 0), origin); break; case PUSH_UP: Animator.animatePush( animationCanvas, currentPanel, newPanel, DEFAULT_SLIDE_DURATION, uberListener, new Point(0, this.getHeight()), origin); break; case PUSH_DOWN: Animator.animatePush( animationCanvas, currentPanel, newPanel, DEFAULT_SLIDE_DURATION, uberListener, new Point(0, -this.getHeight()), origin); break; case FADE_IN: Animator.animateAlpha( animationCanvas, currentPanel, newPanel, DEFAULT_SLIDE_DURATION, uberListener, 0f, 1.0f); break; case FADE_OUT: Animator.animateAlpha( animationCanvas, newPanel,currentPanel, DEFAULT_SLIDE_DURATION, uberListener, 1.0f, 0f); break; case NONE: uberListener.actionPerformed(null); break; default: throw new UnsupportedOperationException("Transition " + type + " not supported yet"); } currentPanel = newPanel; } public static void main(String[] v) { final JTransitionPanel p = new JTransitionPanel(); final JPanel red = new JPanel(); red.setBackground(new Color(60, 60, 60)); final JPanel yellow = new JPanel(); yellow.setBackground(new Color(100, 100, 100)); p.push(red, TransitionType.NONE, null); JButton doIt = new JButton("Do it"); red.add(doIt); doIt.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { p.push(yellow, TransitionType.PUSH_RIGHT, null); } }); for (int i = 0; i < 30; i++) { JButton doIt2 = new JButton("Do it " + i); yellow.add(doIt2); doIt2.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { p.push(red, TransitionType.PUSH_LEFT, null); } }); } JFrame f = new JFrame(); f.add(p); f.pack(); f.setVisible(true); } }