summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/ui/GLView.java
diff options
context:
space:
mode:
authorOwen Lin <owenlin@google.com>2010-01-28 16:10:19 -0800
committerOwen Lin <owenlin@google.com>2010-02-26 20:26:48 +0800
commit4de149ceb47f2c251f646419907424bfb67d2b64 (patch)
tree6f48682fe065902039bad89d1f3ca90720eca819 /src/com/android/camera/ui/GLView.java
parent02627adfa3d240d817e34af69be8d07e9c66c136 (diff)
downloadLegacyCamera-4de149ceb47f2c251f646419907424bfb67d2b64.zip
LegacyCamera-4de149ceb47f2c251f646419907424bfb67d2b64.tar.gz
LegacyCamera-4de149ceb47f2c251f646419907424bfb67d2b64.tar.bz2
The first runnable version of the new UI.
Implement the new UI with OpenGL (GLSurfaceView). Known issues: * Texture are never freed from GL * Do not consider the density of screen. Currently, the dimensions in mdpi devices are wrong. * It won't work on Sapphire, bug fired: Bug: 2473605 * The action UP event may pass a wrong target. (It should pass to the same target who recive the DOWN action. * Animation is not smooth enough. * Should not allocate objects into heap during rendering path. * The scrollbar in GLListView doesn't match the design * We should calculate our own orientation instead of using the system one. * Regression: "restore to default settings" is removed Change-Id: I93fa45831aa87787dd5ee9e43e270a9d786c5a2a
Diffstat (limited to 'src/com/android/camera/ui/GLView.java')
-rw-r--r--src/com/android/camera/ui/GLView.java312
1 files changed, 312 insertions, 0 deletions
diff --git a/src/com/android/camera/ui/GLView.java b/src/com/android/camera/ui/GLView.java
new file mode 100644
index 0000000..1df1f9e
--- /dev/null
+++ b/src/com/android/camera/ui/GLView.java
@@ -0,0 +1,312 @@
+package com.android.camera.ui;
+
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.view.MotionEvent;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Transformation;
+
+import java.util.ArrayList;
+
+import javax.microedition.khronos.opengles.GL11;
+
+public class GLView {
+ GLRootView mRootView;
+
+ public static final int STATE_EMPTY = 0;
+ public static final int STATE_PRESSED = 1;
+
+ public static final int VISIBLE = 0;
+ public static final int INVISIBLE = 1;
+
+ public static final int FLAG_INVISIBLE = 1;
+ public static final int FLAG_SET_MEASURED_SIZE = 2;
+ public static final int FLAG_LAYOUT_REQUESTED = 4;
+
+ private static final String TAG = "GLView";
+
+ protected final Rect mBounds = new Rect();
+ protected final Rect mPaddings = new Rect();
+
+ private GLView mParent;
+ private ArrayList<GLView> mComponents;
+
+ private OnTouchListener mOnTouchListener;
+ private Animation mAnimation;
+
+ protected int mViewState = STATE_EMPTY;
+ protected int mViewFlags = 0;
+
+ protected int mMeasuredWidth = 0;
+ protected int mMeasuredHeight = 0;
+
+ private int mLastWidthSpec = -1;
+ private int mLastHeightSpec = -1;
+
+ protected int mScrollY = 0;
+ protected int mScrollX = 0;
+ protected int mScrollHeight = 0;
+ protected int mScrollWidth = 0;
+
+ protected void onStateChanged(int oldState, int newState) {
+ }
+
+ protected void addStates(int states) {
+ int newState = (mViewState | states);
+ if (newState != mViewState) {
+ onStateChanged(mViewState, newState);
+ mViewState = newState;
+ }
+ }
+
+ protected void removeStates(int states) {
+ int newState = (mViewState & ~states);
+ if (newState != mViewState) {
+ onStateChanged(mViewState, newState);
+ mViewState = newState;
+ }
+ }
+
+ public void startAnimation(Animation animation) {
+ mAnimation = animation;
+ animation.initialize(getWidth(),
+ getHeight(), mParent.getWidth(), mParent.getHeight());
+ mAnimation.start();
+ invalidate();
+ }
+
+ public void setVisibility(int visibility) {
+ if (visibility == getVisibility()) return;
+ if (visibility == VISIBLE) {
+ mViewFlags &= ~FLAG_INVISIBLE;
+ } else {
+ mViewFlags |= FLAG_INVISIBLE;
+ }
+ invalidate();
+ }
+
+ public int getVisibility() {
+ return (mViewFlags & FLAG_INVISIBLE) == 0 ? VISIBLE : INVISIBLE;
+ }
+
+ public static interface OnTouchListener {
+ public boolean onTouch(GLView view, MotionEvent event);
+ }
+
+ public boolean setBounds(int left, int top, int right, int bottom) {
+ boolean sizeChanged = (right - left) != (mBounds.right - mBounds.left)
+ || (bottom - top) != (mBounds.bottom - mBounds.top);
+ mBounds.set(left, top, right, bottom);
+ return sizeChanged;
+ }
+
+ protected void onAddToParent(GLView parent) {
+ mParent = parent;
+ }
+
+ public void clearComponents() {
+ if (mComponents != null) mComponents.clear();
+ }
+
+ public int getComponentCount() {
+ return mComponents == null ? 0 : mComponents.size();
+ }
+
+ public GLView getComponent(int index) {
+ if (mComponents == null) {
+ throw new ArrayIndexOutOfBoundsException(index);
+ }
+ return mComponents.get(index);
+ }
+
+ public void addComponent(GLView component) {
+ if (mComponents == null) {
+ mComponents = new ArrayList<GLView>();
+ }
+ mComponents.add(component);
+ component.onAddToParent(this);
+ }
+
+ public Rect bounds() {
+ return mBounds;
+ }
+
+ public int getWidth() {
+ return mBounds.right - mBounds.left;
+ }
+
+ public int getHeight() {
+ return mBounds.bottom - mBounds.top;
+ }
+
+ public GLRootView getGLRootView() {
+ if (mRootView == null && mParent != null) {
+ mRootView = mParent.getGLRootView();
+ }
+ return mRootView;
+ }
+
+ public void setOnTouchListener(OnTouchListener listener) {
+ mOnTouchListener = listener;
+ }
+
+ public void invalidate() {
+ GLRootView root = getGLRootView();
+ if (root != null) root.requestRender();
+ }
+
+ public void requestLayout() {
+ mViewFlags |= FLAG_LAYOUT_REQUESTED;
+ if (mParent != null) {
+ mParent.requestLayout();
+ } else {
+ // Is this a content pane ?
+ GLRootView root = getGLRootView();
+ if (root != null) root.requestLayoutContentPane();
+ }
+ }
+
+ protected void render(GLRootView view, GL11 gl) {
+ renderBackground(view, gl);
+ int n = getComponentCount();
+ if (n == 0) return;
+ for (int i = 0; i < n; ++i) {
+ GLView component = getComponent(i);
+ if (component.getVisibility() != GLView.VISIBLE
+ && component.mAnimation == null) continue;
+ renderChild(view, gl, component);
+ }
+ }
+
+ protected void renderBackground(GLRootView view, GL11 gl) {
+ }
+
+ protected void renderChild(GLRootView root, GL11 gl, GLView component) {
+ Animation anim = component.mAnimation;
+ int xoffset = component.mBounds.left - mScrollX;
+ int yoffset = component.mBounds.top - mScrollY;
+
+ Transformation transform = root.getTransformation();
+ Matrix matrix = transform.getMatrix();
+ matrix.preTranslate(xoffset, yoffset);
+ if (anim != null) {
+ long now = AnimationUtils.currentAnimationTimeMillis();
+ Transformation temp = root.obtainTransformation();
+ temp.clear();
+ if (!anim.getTransformation(now, temp)) {
+ component.mAnimation = null;
+ }
+ invalidate();
+ root.pushTransform();
+ transform.compose(temp);
+ root.freeTransformation(temp);
+ }
+ component.render(root, gl);
+ if (anim != null) root.popTransform();
+ matrix.preTranslate(-xoffset, -yoffset);
+ }
+
+ protected boolean onTouch(MotionEvent event) {
+ if (mOnTouchListener != null) {
+ return mOnTouchListener.onTouch(this, event);
+ }
+ return false;
+ }
+
+ protected boolean dispatchTouchEvent(MotionEvent event) {
+ if (mComponents != null) {
+ int eventX = (int) event.getX();
+ int eventY = (int) event.getY();
+ for (int i = 0, n = getComponentCount(); i < n; ++i) {
+ GLView component = getComponent(i);
+ if (component.getVisibility() != GLView.VISIBLE) continue;
+ Rect rect = new Rect(component.mBounds);
+ if (rect.contains(eventX, eventY)) {
+ event.offsetLocation(-rect.left, -rect.top);
+ if (component.dispatchTouchEvent(event)) return true;
+ event.offsetLocation(rect.left, rect.top);
+ }
+ }
+ }
+ return onTouch(event);
+ }
+
+ public Rect getPaddings() {
+ return mPaddings;
+ }
+
+ public void setPaddings(Rect paddings) {
+ mPaddings.set(paddings);
+ }
+
+ public void setPaddings(int left, int top, int right, int bottom) {
+ mPaddings.set(left, top, right, bottom);
+ }
+
+ public void layout(int left, int top, int right, int bottom) {
+ boolean sizeChanged = setBounds(left, top, right, bottom);
+ if (sizeChanged) {
+ mViewFlags &= ~FLAG_LAYOUT_REQUESTED;
+ onLayout(true, left, top, right, bottom);
+ } else if ((mViewFlags & FLAG_LAYOUT_REQUESTED)!= 0) {
+ mViewFlags &= ~FLAG_LAYOUT_REQUESTED;
+ onLayout(false, left, top, right, bottom);
+ }
+ }
+
+ public void measure(int widthSpec, int heightSpec) {
+ if (widthSpec == mLastWidthSpec && heightSpec == mLastHeightSpec
+ && (mViewFlags & FLAG_LAYOUT_REQUESTED) == 0) {
+ return;
+ }
+
+ mLastWidthSpec = widthSpec;
+ mLastHeightSpec = heightSpec;
+
+ mViewFlags &= ~FLAG_SET_MEASURED_SIZE;
+ onMeasure(widthSpec, heightSpec);
+ if ((mViewFlags & FLAG_SET_MEASURED_SIZE) == 0) {
+ throw new IllegalStateException(getClass().getName()
+ + " should call setMeasuredSize() in onMeasure()");
+ }
+ }
+
+ protected void onMeasure(int widthSpec, int heightSpec) {
+ }
+
+ protected void setMeasuredSize(int width, int height) {
+ mViewFlags |= FLAG_SET_MEASURED_SIZE;
+ mMeasuredWidth = width;
+ mMeasuredHeight = height;
+ }
+
+ public int getMeasuredWidth() {
+ return mMeasuredWidth;
+ }
+
+ public int getMeasuredHeight() {
+ return mMeasuredHeight;
+ }
+
+ protected void onLayout(
+ boolean changeSize, int left, int top, int right, int bottom) {
+ }
+
+ public boolean getBoundsOf(GLView child, Rect out) {
+ int xoffset = 0;
+ int yoffset = 0;
+ GLView view = child;
+ while (view != this) {
+ if (view == null) return false;
+ Rect bounds = view.mBounds;
+ xoffset += bounds.left;
+ yoffset += bounds.top;
+ view = view.mParent;
+ }
+ out.set(xoffset, yoffset,
+ xoffset + child.getWidth(), yoffset + child.getHeight());
+ return true;
+ }
+
+}