Home | History | Annotate | Download | only in ui
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.camera.ui;
     18 
     19 import android.graphics.Rect;
     20 import android.view.View.MeasureSpec;
     21 import android.view.animation.AlphaAnimation;
     22 import android.view.animation.Animation;
     23 import android.view.animation.AnimationSet;
     24 import android.view.animation.OvershootInterpolator;
     25 import android.view.animation.ScaleAnimation;
     26 
     27 import javax.microedition.khronos.opengles.GL11;
     28 
     29 public class PopupWindow extends GLView {
     30 
     31     protected Texture mAnchor;
     32     protected int mAnchorOffset;
     33 
     34     protected int mAnchorPosition;
     35     private final RotatePane mRotatePane = new RotatePane();
     36     private RawTexture mBackupTexture;
     37 
     38     protected FrameTexture mBackground;
     39 
     40     public PopupWindow() {
     41         super.addComponent(mRotatePane);
     42     }
     43 
     44     public void setBackground(FrameTexture background) {
     45         if (background == mBackground) return;
     46         mBackground = background;
     47         if (background != null) {
     48             setPaddings(mBackground.getPaddings());
     49         } else {
     50             setPaddings(0, 0, 0, 0);
     51         }
     52         invalidate();
     53     }
     54 
     55     public void setAnchor(Texture anchor, int offset) {
     56         mAnchor = anchor;
     57         mAnchorOffset = offset;
     58     }
     59 
     60     @Override
     61     public void addComponent(GLView component) {
     62         throw new UnsupportedOperationException("use setContent(GLView)");
     63     }
     64 
     65     @Override
     66     protected void onMeasure(int widthSpec, int heightSpec) {
     67         int widthMode = MeasureSpec.getMode(widthSpec);
     68         if (widthMode != MeasureSpec.UNSPECIFIED) {
     69             Rect p = mPaddings;
     70             int width = MeasureSpec.getSize(widthSpec);
     71             widthSpec = MeasureSpec.makeMeasureSpec(
     72                     Math.max(0, width - p.left - p.right
     73                     - mAnchor.getWidth() + mAnchorOffset), widthMode);
     74         }
     75 
     76         int heightMode = MeasureSpec.getMode(heightSpec);
     77         if (heightMode != MeasureSpec.UNSPECIFIED) {
     78             int height = MeasureSpec.getSize(widthSpec);
     79             widthSpec = MeasureSpec.makeMeasureSpec(Math.max(
     80                     0, height - mPaddings.top - mPaddings.bottom), heightMode);
     81         }
     82 
     83         Rect p = mPaddings;
     84         GLView child = mRotatePane;
     85         child.measure(widthSpec, heightSpec);
     86         setMeasuredSize(child.getMeasuredWidth()
     87                 + p.left + p.right + mAnchor.getWidth() - mAnchorOffset,
     88                 child.getMeasuredHeight() + p.top + p.bottom);
     89     }
     90 
     91     @Override
     92     protected void onLayout(
     93             boolean change, int left, int top, int right, int bottom) {
     94         Rect p = getPaddings();
     95         GLView view = mRotatePane;
     96         view.layout(p.left, p.top,
     97                 getWidth() - p.right - mAnchor.getWidth() + mAnchorOffset,
     98                 getHeight() - p.bottom);
     99     }
    100 
    101     public void setAnchorPosition(int yoffset) {
    102         mAnchorPosition = yoffset;
    103     }
    104 
    105     @Override
    106     protected void renderBackground(GLRootView root, GL11 gl) {
    107         int width = getWidth();
    108         int height = getHeight();
    109         int aWidth = mAnchor.getWidth();
    110         int aHeight = mAnchor.getHeight();
    111 
    112         Rect p = mPaddings;
    113         int aXoffset = width - aWidth;
    114         int aYoffset = Math.max(p.top, mAnchorPosition - aHeight / 2);
    115         aYoffset = Math.min(aYoffset, height - p.bottom - aHeight);
    116 
    117         if (mAnchor != null) {
    118             mAnchor.draw(root, aXoffset, aYoffset);
    119         }
    120 
    121         if (mBackupTexture == null || mBackupTexture.getBoundGL() != gl) {
    122             mBackupTexture = RawTexture.newInstance(gl);
    123         }
    124 
    125         RawTexture backup = mBackupTexture;
    126         try {
    127             // Copy the current drawing results of the triangle area into
    128             // "backup", so that we can restore the content after it is
    129             // overlaid by the background.
    130             root.copyTexture2D(backup, aXoffset, aYoffset, aWidth, aHeight);
    131         } catch (GLOutOfMemoryException e) {
    132             e.printStackTrace();
    133         }
    134 
    135         if (mBackground != null) {
    136             mBackground.setSize(width - aWidth + mAnchorOffset, height);
    137             mBackground.draw(root, 0, 0);
    138         }
    139 
    140         gl.glBlendFunc(GL11.GL_ONE, GL11.GL_ZERO);
    141         backup.draw(root, aXoffset, aYoffset, aWidth, aHeight, 1);
    142         gl.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
    143     }
    144 
    145     public void setContent(GLView content) {
    146         mRotatePane.setContent(content);
    147     }
    148 
    149     @Override
    150     public void clearComponents() {
    151         throw new UnsupportedOperationException();
    152     }
    153 
    154     public void popup() {
    155         setVisibility(GLView.VISIBLE);
    156 
    157         AnimationSet set = new AnimationSet(false);
    158         Animation scale = new ScaleAnimation(
    159                 0.7f, 1f, 0.7f, 1f, getWidth(), mAnchorPosition);
    160         Animation alpha = new AlphaAnimation(0.5f, 1.0f);
    161 
    162         set.addAnimation(scale);
    163         set.addAnimation(alpha);
    164         scale.setDuration(150);
    165         alpha.setDuration(100);
    166         scale.setInterpolator(new OvershootInterpolator());
    167         startAnimation(set);
    168     }
    169 
    170     public void popoff() {
    171         setVisibility(GLView.INVISIBLE);
    172         Animation alpha = new AlphaAnimation(0.7f, 0.0f);
    173         alpha.setDuration(100);
    174         startAnimation(alpha);
    175     }
    176 
    177     public void setOrientation(int orientation) {
    178         switch (orientation) {
    179             case 90:
    180                 mRotatePane.setOrientation(RotatePane.LEFT);
    181                 break;
    182             case 180:
    183                 mRotatePane.setOrientation(RotatePane.DOWN);
    184                 break;
    185             case 270:
    186                 mRotatePane.setOrientation(RotatePane.RIGHT);
    187                 break;
    188             default:
    189                 mRotatePane.setOrientation(RotatePane.UP);
    190                 break;
    191         }
    192     }
    193 
    194 }
    195