CommonTransitions.java
上传用户:haobig99
上传日期:2022-06-15
资源大小:369k
文件大小:21k
源码类别:

J2ME

开发平台:

Java

  1. /*
  2.  * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
  3.  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4.  *
  5.  * This code is free software; you can redistribute it and/or modify it
  6.  * under the terms of the GNU General Public License version 2 only, as
  7.  * published by the Free Software Foundation.  Sun designates this
  8.  * particular file as subject to the "Classpath" exception as provided
  9.  * by Sun in the LICENSE file that accompanied this code.
  10.  *
  11.  * This code is distributed in the hope that it will be useful, but WITHOUT
  12.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14.  * version 2 for more details (a copy is included in the LICENSE file that
  15.  * accompanied this code).
  16.  *
  17.  * You should have received a copy of the GNU General Public License version
  18.  * 2 along with this work; if not, write to the Free Software Foundation,
  19.  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20.  *
  21.  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22.  * CA 95054 USA or visit www.sun.com if you need additional information or
  23.  * have any questions.
  24.  */
  25. package com.sun.lwuit.animations;
  26. import com.sun.lwuit.Button;
  27. import com.sun.lwuit.Component;
  28. import com.sun.lwuit.Container;
  29. import com.sun.lwuit.Dialog;
  30. import com.sun.lwuit.Graphics;
  31. import com.sun.lwuit.Image;
  32. import com.sun.lwuit.Painter;
  33. import com.sun.lwuit.RGBImage;
  34. import com.sun.lwuit.plaf.UIManager;
  35. /**
  36.  * Contains common transition animations including the following:
  37.  * <ol>
  38.  * <li>Slide - the exiting form slides out of the screen while the new form slides in. 
  39.  * <li>Fade - components fade into/out of the screen
  40.  * </ol>
  41.  * <p>Instances of this class are created using factory methods.
  42.  * 
  43.  * @author Shai Almog, Chen Fishbein
  44.  */
  45. public final class CommonTransitions extends Transition {
  46.     private Motion motion;
  47.     private static final int TYPE_EMPTY = 0;
  48.     private static final int TYPE_SLIDE = 1;
  49.     private static final int TYPE_FADE = 2;
  50.     
  51.     /**
  52.      * Slide the transition horizontally
  53.      * @see #createSlide
  54.      */
  55.     public static final int SLIDE_HORIZONTAL = 0;
  56.     /**
  57.      * Slide the transition vertically
  58.      * @see #createSlide
  59.      */
  60.     public static final int SLIDE_VERTICAL = 1;
  61.     
  62.     private int slideType;
  63.     private int speed;
  64.     private int position;
  65.     private int transitionType;
  66.     private Image buffer;
  67.     private Image secondaryBuffer;
  68.     private static boolean defaultLinearMotion = false;
  69.     private boolean linearMotion = defaultLinearMotion;
  70.     
  71.     /**
  72.      * The transition is a special case where we "keep" an allocated buffer
  73.      */
  74.     private RGBImage rgbBuffer;
  75.     private boolean forward;
  76.     private boolean drawDialogMenu;
  77.     private boolean firstFinished;
  78.     
  79.     private CommonTransitions(int type) {
  80.         transitionType = type;
  81.     }
  82.     /**
  83.      * Creates an empty transition that does nothing. This has the same effect as
  84.      * setting a transition to null.
  85.      * 
  86.      * @return empty transition
  87.      */
  88.     public static CommonTransitions createEmpty() {
  89.         CommonTransitions t = new CommonTransitions(TYPE_EMPTY);
  90.         return t;
  91.     }
  92.     /**
  93.      * Creates a slide transition with the given duration and direction
  94.      * 
  95.      * @param type type can be either vertically or horizontally, which means 
  96.      * the movement direction of the transition
  97.      * @param forward forward is a boolean value, represent the directions of 
  98.      * switching forms, for example for a horizontally type, true means 
  99.      * horizontally movement to right.
  100.      * @param duration represent the time the transition should take in millisecond
  101.      * @return a transition object
  102.      */
  103.     public static CommonTransitions createSlide(int type, boolean forward, int duration) {
  104.         return createSlide(type, forward, duration, false);
  105.     }
  106.     /**
  107.      * Creates a slide transition with the given duration and direction
  108.      * 
  109.      * @param type type can be either vertically or horizontally, which means 
  110.      * the movement direction of the transition
  111.      * @param forward forward is a boolean value, represent the directions of 
  112.      * switching forms, for example for a horizontally type, true means 
  113.      * horizontally movement to right.
  114.      * @param duration represent the time the transition should take in millisecond
  115.      * @param drawDialogMenu indicates that the menu (softkey area) of the dialog 
  116.      * should be kept during a slide transition. This is only relevant for 
  117.      * dialog in/out transitions.
  118.      * @return a transition object
  119.      */
  120.     public static CommonTransitions createSlide(int type, boolean forward, int duration, boolean drawDialogMenu) {
  121.         CommonTransitions t = new CommonTransitions(TYPE_SLIDE);
  122.         t.slideType = type;
  123.         t.forward = forward;
  124.         if ((type==SLIDE_HORIZONTAL) && (UIManager.getInstance().getLookAndFeel().isRTL())) {
  125.          t.forward=!t.forward;
  126.         }
  127.         t.speed = duration;
  128.         t.position = 0;
  129.         t.drawDialogMenu = drawDialogMenu;
  130.         return t;
  131.     }
  132.     /**
  133.      * Creates a transition for fading a form in while fading out the original form
  134.      * 
  135.      * @param duration represent the time the transition should take in millisecond
  136.      * @return a transition object
  137.      */
  138.     public static CommonTransitions createFade(int duration) {
  139.         CommonTransitions t = new CommonTransitions(TYPE_FADE);
  140.         t.speed = duration;
  141.         return t;
  142.     }
  143.     /**
  144.      * @inheritDoc
  145.      */
  146.     public void initTransition() {
  147.         firstFinished = false;
  148.         if(transitionType == TYPE_EMPTY) {
  149.             return;
  150.         }
  151.         
  152.         Component source = getSource();
  153.         Component destination = getDestination();
  154.         position = 0;
  155.         int w = source.getWidth();
  156.         int h = source.getHeight();
  157.         
  158.         // a transition might occur with illegal source or destination values (common with 
  159.         // improper replace() calls, this may still be valid and shouldn't fail
  160.         if(w <= 0 || h <= 0) {
  161.             return;
  162.         }
  163.         if (buffer == null) {
  164.             buffer = Image.createImage(w, h);
  165.         } else {
  166.             // this might happen when screen orientation changes or a MIDlet moves
  167.             // to an external screen
  168.             if(buffer.getWidth() != w || buffer.getHeight() != h) {
  169.                 buffer = Image.createImage(w, h);
  170.                 rgbBuffer = null;
  171.                 
  172.                 // slide motion might need resetting since screen size is different
  173.                 motion = null;
  174.             }
  175.         }
  176.         if(transitionType == TYPE_FADE) {
  177.             if(linearMotion) {
  178.                 motion = Motion.createLinearMotion(0, 256, speed);
  179.             } else {
  180.                 motion = Motion.createSplineMotion(0, 256, speed);
  181.             }
  182.             motion.start();
  183.             
  184.             Graphics g = buffer.getGraphics();
  185.             g.translate(-source.getAbsoluteX(), -source.getAbsoluteY());
  186.             
  187.             if(getSource().getParent() != null){
  188.                 getSource().getComponentForm().paintComponent(g);
  189.             }
  190.             //getSource().paintBackgrounds(g);
  191.             g.setClip(0, 0, buffer.getWidth()+source.getAbsoluteX(), buffer.getHeight()+source.getAbsoluteY());
  192.             paint(g, getDestination(), 0, 0);
  193.             if(g.isAlphaSupported()) {
  194.                 secondaryBuffer = buffer;
  195.                 buffer = Image.createImage(w, h);
  196.             } else {
  197.                 rgbBuffer = new RGBImage(buffer.getRGBCached(), buffer.getWidth(), buffer.getHeight());
  198.             }
  199.             
  200.             paint(g, getSource(), 0, 0);
  201.             g.translate(source.getAbsoluteX(), source.getAbsoluteY());
  202.             
  203.         } else {
  204.             if (transitionType == TYPE_SLIDE) {
  205.                 int dest;
  206.                 int startOffset = 0;
  207.                 if (slideType == SLIDE_HORIZONTAL) {
  208.                     dest = w;
  209.                     if(destination instanceof Dialog) {
  210.                         startOffset = w - ((Dialog)destination).getContentPane().getWidth();
  211.                         if(forward) {
  212.                             startOffset -= ((Dialog)destination).getContentPane().getStyle().getMargin(destination.isRTL(), Component.LEFT);
  213.                         } else {
  214.                             startOffset -= ((Dialog)destination).getContentPane().getStyle().getMargin(destination.isRTL(), Component.RIGHT);
  215.                         }
  216.                     } else {
  217.                         if(source instanceof Dialog) {
  218.                             dest = ((Dialog)source).getContentPane().getWidth();
  219.                             if(forward) {
  220.                                 dest += ((Dialog)source).getContentPane().getStyle().getMargin(source.isRTL(), Component.LEFT);
  221.                             } else {
  222.                                 dest += ((Dialog)source).getContentPane().getStyle().getMargin(source.isRTL(), Component.RIGHT);
  223.                             }
  224.                         } 
  225.                     }
  226.                 } else {
  227.                     dest = h;
  228.                     if(destination instanceof Dialog) {
  229.                         startOffset = h - ((Dialog)destination).getContentPane().getHeight() -
  230.                             ((Dialog)destination).getTitleComponent().getHeight();
  231.                         if(forward) {
  232.                             startOffset -= ((Dialog)destination).getContentPane().getStyle().getMargin(false, Component.BOTTOM);
  233.                         } else {
  234.                             startOffset -= ((Dialog)destination).getContentPane().getStyle().getMargin(false, Component.TOP);
  235.                             startOffset -= ((Dialog)destination).getTitleStyle().getMargin(false, Component.TOP);
  236.                             if(!drawDialogMenu && ((Dialog)destination).getCommandCount() > 0) {
  237.                                 Container p = ((Dialog)destination).getSoftButton(0).getParent();
  238.                                 if(p != null) {
  239.                                     startOffset -= p.getHeight();
  240.                                 }
  241.                             }
  242.                         }
  243.                     } else {
  244.                         if(source instanceof Dialog) {
  245.                             dest = ((Dialog)source).getContentPane().getHeight() +
  246.                                 ((Dialog)source).getTitleComponent().getHeight();
  247.                             if(forward) {
  248.                                 dest += ((Dialog)source).getContentPane().getStyle().getMargin(false, Component.BOTTOM);
  249.                             } else {
  250.                                 dest += ((Dialog)source).getContentPane().getStyle().getMargin(false, Component.TOP);
  251.                                 dest += ((Dialog)source).getTitleStyle().getMargin(false, Component.TOP);
  252.                                 if(((Dialog)source).getCommandCount() > 0) {
  253.                                     Container p = ((Dialog)source).getSoftButton(0).getParent();
  254.                                     if(p != null) {
  255.                                         dest += p.getHeight();
  256.                                     }
  257.                                 }
  258.                             }
  259.                         } 
  260.                     }
  261.                 }
  262.                 
  263.                 if(linearMotion) {
  264.                     motion = Motion.createLinearMotion(startOffset, dest, speed);
  265.                 } else {
  266.                     motion = Motion.createSplineMotion(startOffset, dest, speed);
  267.                 }
  268.                 // make sure the destination is painted fully at least once 
  269.                 // we must use a full buffer otherwise the clipping will take effect
  270.                 Graphics g = buffer.getGraphics();
  271.                 
  272.                 // If this is a dialog render the tinted frame once since 
  273.                 // tinting is expensive
  274.                 if(getSource() instanceof Dialog) {
  275.                     paint(g, getDestination(), 0, 0);
  276.                 } else {
  277.                     if(getDestination() instanceof Dialog) {
  278.                         paint(g, getSource(), 0, 0);
  279.                     } else {
  280.                         paint(g, source, -source.getAbsoluteX(), -source.getAbsoluteY());
  281.                     }
  282.                 }
  283.                 motion.start();
  284.             }
  285.         }
  286.     }
  287.     /**
  288.      * @inheritDoc
  289.      */
  290.     public boolean animate() {
  291.         if(motion == null) {
  292.             return false;
  293.         }
  294.         position = motion.getValue();
  295.         
  296.         // after the motion finished we need to paint one last time otherwise
  297.         // there will be a "bump" in sliding
  298.         if(firstFinished) {
  299.             return false;
  300.         }
  301.         boolean finished = motion.isFinished();
  302.         if(finished) {
  303.             if(!firstFinished) {
  304.                 firstFinished = true;
  305.             }
  306.         }
  307.         return true;
  308.     }
  309.     
  310.     /**
  311.      * @inheritDoc
  312.      */
  313.     public void paint(Graphics g) {
  314.         try {
  315.             switch (transitionType) {
  316.                 case TYPE_SLIDE:
  317.                     // if this is an up or down slide
  318.                     if (slideType == SLIDE_HORIZONTAL) {
  319.                         paintSlideAtPosition(g, position, 0);
  320.                     } else {
  321.                         paintSlideAtPosition(g, 0, position);
  322.                     }
  323.                     return;
  324.                 case TYPE_FADE:
  325.                     paintAlpha(g);
  326.                     return;
  327.             }
  328.         } catch(Throwable t) {
  329.             System.out.println("An exception occurred during transition paint this might be valid in case of a resize in the middle of a transition");
  330.             t.printStackTrace();
  331.         }
  332.     }
  333.     private void paintAlpha(Graphics graphics) {
  334.         // this will always be invoked on the EDT so there is no race condition risk
  335.         if(rgbBuffer != null || secondaryBuffer != null) {
  336.             Component src = getSource();
  337.             int w = src.getWidth();
  338.             int h = src.getHeight();
  339.             int position = this.position;
  340.             if (position > 255) {
  341.                 position = 255;
  342.             } else {
  343.                 if (position < 0) {
  344.                     position = 0;
  345.                 }
  346.             }
  347.             if(secondaryBuffer != null) {
  348.                 Component dest = getDestination();                
  349.                 int x = dest.getAbsoluteX();
  350.                 int y = dest.getAbsoluteY();
  351.                 graphics.drawImage(buffer, x, y);
  352.                 graphics.setAlpha(position);
  353.                 graphics.drawImage(secondaryBuffer, x, y);
  354.                 graphics.setAlpha(0xff);
  355.             } else {
  356.                 int alpha = position << 24;
  357.                 int size = w * h;
  358.                 int[] bufferArray = rgbBuffer.getRGB();
  359.                 for (int iter = 0 ; iter < size ; iter++) {
  360.                     bufferArray[iter] = ((bufferArray[iter] & 0xFFFFFF) | alpha);
  361.                 }
  362.                 Component dest = getDestination();                
  363.                 int x = dest.getAbsoluteX();
  364.                 int y = dest.getAbsoluteY();
  365.                 graphics.drawImage(buffer, x, y);
  366.                 graphics.drawImage(rgbBuffer, x, y);
  367.             }
  368.         } 
  369.     }
  370.     /**
  371.      * @inheritDoc
  372.      */
  373.     public void cleanup() {
  374.         super.cleanup();
  375.         buffer = null;
  376.         rgbBuffer = null;
  377.         secondaryBuffer = null;
  378.     }
  379.     private void paintSlideAtPosition(Graphics g, int slideX, int slideY) {
  380.         Component source = getSource();
  381.         
  382.         // if this is the first form we can't do a slide transition since we have no source form
  383.         if (source == null) { 
  384.             return;           
  385.         }
  386.         
  387.         Component dest = getDestination();                
  388.         int w = source.getWidth();
  389.         int h = source.getHeight();
  390.                     
  391.         if (slideType == SLIDE_HORIZONTAL) {
  392.             h = 0;
  393.         } else {
  394.             w = 0;
  395.         }
  396.         if(forward) {
  397.             w = -w;
  398.             h = -h;
  399.         } else {
  400.             slideX = -slideX;
  401.             slideY = -slideY;
  402.         }
  403.         g.setClip(source.getAbsoluteX()+source.getScrollX(), source.getAbsoluteY()+source.getScrollY(), source.getWidth(), source.getHeight());
  404.             
  405.         // dialog animation is slightly different... 
  406.         if(source instanceof Dialog) {
  407.             g.drawImage(buffer, 0, 0);
  408.             paint(g, source, -slideX, -slideY);
  409.             return;
  410.         } 
  411.         
  412.         if(dest instanceof Dialog) {
  413.             g.drawImage(buffer, 0, 0);
  414.             paint(g, dest, -slideX - w, -slideY - h);
  415.             return;
  416.         } 
  417.         
  418.         //g.setClip(source.getAbsoluteX(), source.getAbsoluteY(), source.getWidth(), source.getHeight());
  419.        
  420.         //g.clipRect(dest.getAbsoluteX(), dest.getAbsoluteY(), source.getWidth(), source.getHeight());
  421.         if(source.getParent() != null){
  422.             source.paintBackgrounds(g);
  423.             paint(g, source, slideX , slideY );
  424.         }else{
  425.             g.drawImage(buffer, slideX, slideY);        
  426.         }
  427.         paint(g, dest, slideX + w, slideY + h);
  428.         
  429.     }
  430.     private void paint(Graphics g, Component cmp, int x, int y) {
  431.         int cx = g.getClipX();
  432.         int cy = g.getClipY();
  433.         int cw = g.getClipWidth();
  434.         int ch = g.getClipHeight();
  435.         if(cmp instanceof Dialog) {
  436.             if(transitionType != TYPE_FADE) {
  437.                 if(!(getSource() instanceof Dialog && getDestination() instanceof Dialog && 
  438.                         cmp == getDestination())) {
  439.                     Painter p = cmp.getStyle().getBgPainter();
  440.                     cmp.getStyle().setBgPainter(null);
  441.                     g.translate(x, y);
  442.                     Dialog dlg = (Dialog)cmp;
  443.                     g.setClip(0, 0, cmp.getWidth(), cmp.getHeight());
  444.                     dlg.getTitleComponent().paintComponent(g, false);
  445.                     g.setClip(0, 0, cmp.getWidth(), cmp.getHeight());
  446.                     dlg.getContentPane().paintComponent(g, false);
  447.                     g.translate(-x, -y);
  448.                     if(drawDialogMenu && dlg.getCommandCount() > 0) {
  449.                         Component menuBar = dlg.getSoftButton(0).getParent();
  450.                         if(menuBar != null) {
  451.                             g.setClip(0, 0, cmp.getWidth(), cmp.getHeight());
  452.                             menuBar.paintComponent(g, false);
  453.                         }
  454.                     }
  455.                     g.setClip(cx, cy, cw, ch);
  456.                     cmp.getStyle().setBgPainter(p);
  457.                     return;
  458.                 }
  459.             } 
  460.             cmp.paintComponent(g, false);
  461.             return;
  462.         }
  463.         //g.clipRect(cmp.getAbsoluteX(), cmp.getAbsoluteY(), cmp.getWidth(), cmp.getHeight());
  464.          g.translate(x, y);
  465.         //g.clipRect(cmp.getAbsoluteX(), cmp.getAbsoluteY(), cmp.getWidth(), cmp.getHeight());
  466.         cmp.paintComponent(g, false);
  467.          g.translate(-x, -y);
  468.         
  469.         g.setClip(cx, cy, cw, ch);
  470.     }
  471.     
  472.     /**
  473.      * Motion represents the physical movement within a transition, it can
  474.      * be replaced by the user to provide a more appropriate physical feel
  475.      * 
  476.      * @return the instanceo of the motion class used by this transition
  477.      */
  478.     public Motion getMotion() {
  479.         return motion;
  480.     }
  481.     /**
  482.      * Motion represents the physical movement within a transition, it can
  483.      * be replaced by the user to provide a more appropriate physical feel
  484.      * 
  485.      * @param motion new instance of the motion class that will be used by the transition
  486.      */
  487.     public void setMotion(Motion motion) {
  488.         this.motion = motion;
  489.     }
  490.     
  491.     
  492.     /**
  493.      * @inheritDoc
  494.      */
  495.     public Transition copy(boolean reverse){
  496.         CommonTransitions retVal = null;
  497.         if(transitionType == TYPE_FADE){
  498.             retVal = CommonTransitions.createFade(speed);
  499.         }else if(transitionType == TYPE_SLIDE){
  500.          boolean fwd=forward;
  501.             // prevent double reversing of forward due to bidi when copying a transition
  502.          if ((slideType==SLIDE_HORIZONTAL) && (UIManager.getInstance().getLookAndFeel().isRTL())) {
  503.              fwd=!fwd;
  504.             }
  505.             if(reverse) {
  506.                 retVal = CommonTransitions.createSlide(slideType, !fwd, speed, drawDialogMenu);
  507.             } else {
  508.                 retVal = CommonTransitions.createSlide(slideType, fwd, speed, drawDialogMenu);
  509.             }
  510.         }else if(transitionType == TYPE_EMPTY){
  511.             retVal = CommonTransitions.createEmpty();
  512.         }
  513.         retVal.linearMotion = linearMotion;
  514.         return retVal;
  515.     }
  516.     /**
  517.      * Indicates whether the motion associated with this transition is linear or spline motion
  518.      *
  519.      * @return the linearMotion
  520.      */
  521.     public boolean isLinearMotion() {
  522.         return linearMotion;
  523.     }
  524.     /**
  525.      * Indicates whether the motion associated with this transition is linear or spline motion
  526.      *
  527.      * @param linearMotion the linearMotion to set
  528.      */
  529.     public void setLinearMotion(boolean linearMotion) {
  530.         this.linearMotion = linearMotion;
  531.     }
  532.     /**
  533.      * Indicates whether the motion associated with these transitions by default is linear or spline motion
  534.      *
  535.      * @return the defaultLinearMotion
  536.      */
  537.     public static boolean isDefaultLinearMotion() {
  538.         return defaultLinearMotion;
  539.     }
  540.     /**
  541.      * Indicates whether the motion associated with these transitions by default is linear or spline motion
  542.      *
  543.      * @param aDefaultLinearMotion the defaultLinearMotion to set
  544.      */
  545.     public static void setDefaultLinearMotion(boolean aDefaultLinearMotion) {
  546.         defaultLinearMotion = aDefaultLinearMotion;
  547.     }
  548. }