blob: f2971cdf4fdc3d29a6aa7a0aea0b9220cacc7333 [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.camera.ui;
import com.android.camera.R;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
/**
* A view that contains camera zoom control which could adjust the zoom in/out
* if the camera supports zooming.
*/
public abstract class ZoomControl extends RelativeLayout implements Rotatable {
// The states of zoom button.
public static final int ZOOM_IN = 0;
public static final int ZOOM_OUT = 1;
public static final int ZOOM_STOP = 2;
private static final String TAG = "ZoomControl";
private static final int ZOOMING_INTERVAL = 1000; // milliseconds
protected ImageView mZoomIn;
protected ImageView mZoomOut;
protected ImageView mZoomSlider;
protected int mSliderPosition = 0;
protected int mOrientation;
private Handler mHandler;
public interface OnZoomChangedListener {
void onZoomValueChanged(int index); // only for immediate zoom
void onZoomStateChanged(int state); // only for smooth zoom
}
// The interface OnZoomIndexChangedListener is used to inform the
// ZoomIndexBar about the zoom index change. The index position is between
// 0 (the index is zero) and 1.0 (the index is mZoomMax).
public interface OnZoomIndexChangedListener {
void onZoomIndexChanged(double indexPosition);
}
protected int mZoomMax, mZoomIndex;
private boolean mSmoothZoomSupported;
private OnZoomChangedListener mListener;
private OnZoomIndexChangedListener mIndexListener;
protected OnIndicatorEventListener mOnIndicatorEventListener;
private int mState;
private int mStep;
protected final Runnable mRunnable = new Runnable() {
public void run() {
performZoom(mState, false);
}
};
public ZoomControl(Context context, AttributeSet attrs) {
super(context, attrs);
mZoomIn = addImageView(context, R.drawable.ic_zoom_in);
mZoomSlider = addImageView(context, R.drawable.ic_zoom_slider);
mZoomOut = addImageView(context, R.drawable.ic_zoom_out);
mHandler = new Handler();
}
public void startZoomControl() {
mZoomSlider.setPressed(true);
setZoomIndex(mZoomIndex); // Update the zoom index bar.
}
protected ImageView addImageView(Context context, int iconResourceId) {
ImageView image = new RotateImageView(context);
image.setImageResource(iconResourceId);
if (iconResourceId == R.drawable.ic_zoom_slider) {
image.setContentDescription(getResources().getString(
R.string.accessibility_zoom_control));
} else {
image.setContentDescription(getResources().getString(
R.string.empty));
}
addView(image);
return image;
}
public void closeZoomControl() {
mZoomSlider.setPressed(false);
stopZooming();
if (!mSmoothZoomSupported) mHandler.removeCallbacks(mRunnable);
if (mOnIndicatorEventListener != null) {
mOnIndicatorEventListener.onIndicatorEvent(
OnIndicatorEventListener.EVENT_LEAVE_ZOOM_CONTROL);
}
}
public void setZoomMax(int zoomMax) {
mZoomMax = zoomMax;
// Layout should be requested as the maximum zoom level is the key to
// show the correct zoom slider position.
requestLayout();
}
public void setOnZoomChangeListener(OnZoomChangedListener listener) {
mListener = listener;
}
public void setOnIndicatorEventListener(OnIndicatorEventListener listener) {
mOnIndicatorEventListener = listener;
}
public void setZoomIndex(int index) {
if (index < 0 || index > mZoomMax) {
throw new IllegalArgumentException("Invalid zoom value:" + index);
}
mZoomIndex = index;
invalidate();
}
public void setSmoothZoomSupported(boolean smoothZoomSupported) {
mSmoothZoomSupported = smoothZoomSupported;
}
private boolean zoomIn() {
return (mZoomIndex == mZoomMax) ? false : changeZoomIndex(mZoomIndex + mStep);
}
private boolean zoomOut() {
return (mZoomIndex == 0) ? false : changeZoomIndex(mZoomIndex - mStep);
}
protected void setZoomStep(int step) {
mStep = step;
}
private void stopZooming() {
if (mSmoothZoomSupported) {
if (mListener != null) mListener.onZoomStateChanged(ZOOM_STOP);
}
}
// Called from ZoomControlWheel to change the zoom level.
// TODO: merge the zoom control for both platforms.
protected void performZoom(int state) {
performZoom(state, true);
}
private void performZoom(int state, boolean fromUser) {
if ((mState == state) && fromUser) return;
if (fromUser) mHandler.removeCallbacks(mRunnable);
mState = state;
switch (state) {
case ZOOM_IN:
zoomIn();
break;
case ZOOM_OUT:
zoomOut();
break;
case ZOOM_STOP:
stopZooming();
break;
}
if (!mSmoothZoomSupported) {
// Repeat the zoom action on tablet as the user is still holding
// the zoom slider.
mHandler.postDelayed(mRunnable, ZOOMING_INTERVAL / mZoomMax);
}
}
// Called from ZoomControlBar to change the zoom level.
protected void performZoom(double zoomPercentage) {
int index = (int) (mZoomMax * zoomPercentage);
if (mZoomIndex == index) return;
changeZoomIndex(index);
}
private boolean changeZoomIndex(int index) {
if (mListener != null) {
if (mSmoothZoomSupported) {
int zoomType = (index < mZoomIndex) ? ZOOM_OUT : ZOOM_IN;
if (((zoomType == ZOOM_IN) && (mZoomIndex != mZoomMax)) ||
((zoomType == ZOOM_OUT) && (mZoomIndex != 0))) {
mListener.onZoomStateChanged(zoomType);
}
} else {
if (index > mZoomMax) index = mZoomMax;
if (index < 0) index = 0;
mListener.onZoomValueChanged(index);
mZoomIndex = index;
}
}
return true;
}
public void setOrientation(int orientation) {
mOrientation = orientation;
int count = getChildCount();
for (int i = 0 ; i < count ; ++i) {
View view = getChildAt(i);
if (view instanceof RotateImageView) {
((RotateImageView) view).setOrientation(orientation);
}
}
}
@Override
public void setActivated(boolean activated) {
super.setActivated(activated);
mZoomIn.setActivated(activated);
mZoomOut.setActivated(activated);
}
}