/* The contents of this file are subject to the Mozilla Public License Version 1.1 (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.mozilla.org/MPL/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is collection of files collectively known as Open Camera. The Initial Developer of the Original Code is Almalence Inc. Portions created by Initial Developer are Copyright (C) 2013 by Almalence Inc. All Rights Reserved. */ package com.almalence.plugins.vf.zoom; import java.util.ArrayList; import java.util.List; import android.content.SharedPreferences; import android.graphics.PointF; import android.os.Handler; import android.os.Message; import android.preference.PreferenceManager; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.View; import android.view.ScaleGestureDetector.OnScaleGestureListener; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.LinearInterpolator; import android.view.animation.TranslateAnimation; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import com.almalence.sony.cameraremote.ZoomCallbackSonyRemote; import com.almalence.ui.VerticalSeekBar; /* <!-- +++ import com.almalence.opencam_plus.ApplicationInterface; import com.almalence.opencam_plus.ApplicationScreen; import com.almalence.opencam_plus.MainScreen; import com.almalence.opencam_plus.PluginViewfinder; import com.almalence.opencam_plus.cameracontroller.CameraController; import com.almalence.opencam_plus.R; +++ --> */ // <!-- -+- import com.almalence.opencam.ApplicationInterface; import com.almalence.opencam.ApplicationScreen; import com.almalence.opencam.MainScreen; import com.almalence.opencam.PluginViewfinder; import com.almalence.opencam.cameracontroller.CameraController; import com.almalence.opencam.R; //-+- --> /*** * Implements zoom functionality - slider, pinch, sound buttons ***/ public class ZoomVFPlugin extends PluginViewfinder { private VerticalSeekBar zoomBar = null; private ImageButton mButtonZoomIn = null; private ImageButton mButtonZoomOut = null; private float zoomCurrent = 0; private View zoomPanelView = null; private LinearLayout zoomPanel = null; private int mainLayoutHeight = 0; private int zoomPanelWidth = 0; private boolean panelOpened = false; private boolean panelToBeOpen = false; private boolean panelOpening = false; private boolean panelClosing = false; private boolean mZoomDisabled = false; private boolean isEnabled = true; private Handler zoomHandler; private boolean zoomStopping = false; private static final int CLOSE_ZOOM_PANEL = 0; private static final int CLOSE_ZOOM_PANEL_DELAY = 1500; private class ZoomHandler extends Handler { @Override public void handleMessage(Message msg) { if (msg.what == CLOSE_ZOOM_PANEL) closeZoomPanel(); } } private ScaleGestureDetector scaleGestureDetector; public ZoomVFPlugin() { super("com.almalence.plugins.zoomvf", R.xml.preferences_vf_zoom, 0, 0, null); zoomHandler = new ZoomHandler(); } @Override public void onCreate() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainScreen.getMainContext()); isEnabled = prefs.getBoolean("enabledPrefZoom", true); panelOpened = false; LayoutInflater inflator = MainScreen.getInstance().getLayoutInflater(); zoomPanelView = inflator.inflate(R.layout.plugin_vf_zoom_layout, null, false); zoomPanel = (LinearLayout) zoomPanelView.findViewById(R.id.zoomLayout); zoomPanel.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return false; } }); mButtonZoomIn = (ImageButton) zoomPanel.findViewById(R.id.button_zoom_in); mButtonZoomOut = (ImageButton) zoomPanel.findViewById(R.id.button_zoom_out); initZoomButtons(); ZoomCallbackSonyRemote zoomCallbackSonyRemote = new ZoomCallbackSonyRemote() { @Override public void onZoomPositionChanged(final int zoomPosition) { MainScreen.getInstance().runOnUiThread(new Runnable() { @Override public void run() { if (zoomPosition == 0) { mButtonZoomIn.setEnabled(true); mButtonZoomOut.setEnabled(false); } else if (zoomPosition == 100) { mButtonZoomIn.setEnabled(false); mButtonZoomOut.setEnabled(true); } else { mButtonZoomIn.setEnabled(true); mButtonZoomOut.setEnabled(true); } } }); } @Override public void onZoomAvailabelChanged(final boolean isZoomAvailable) { MainScreen.getInstance().runOnUiThread(new Runnable() { @Override public void run() { prepareActZoomButtons(isZoomAvailable); } }); } }; CameraController.setZoomCallbackSonyRemote(zoomCallbackSonyRemote); this.zoomBar = (VerticalSeekBar) zoomPanelView.findViewById(R.id.zoomSeekBar); this.zoomBar.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (mZoomDisabled) { if (panelOpened) zoomHandler.sendEmptyMessageDelayed(CLOSE_ZOOM_PANEL, CLOSE_ZOOM_PANEL_DELAY); return true; } switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { if (!panelOpened) { openZoomPanel(); zoomHandler.removeMessages(CLOSE_ZOOM_PANEL); return true; } if (panelClosing) { panelToBeOpen = true; return true; } } break; case MotionEvent.ACTION_UP: { if (panelOpened || panelOpening) zoomHandler.sendEmptyMessageDelayed(CLOSE_ZOOM_PANEL, CLOSE_ZOOM_PANEL_DELAY); } break; case MotionEvent.ACTION_MOVE: return false; default: break; } return false; } }); this.zoomBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { zoomHandler.removeMessages(CLOSE_ZOOM_PANEL); } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (fromUser) { zoomHandler.removeMessages(CLOSE_ZOOM_PANEL); zoomCurrent = progress; if (CameraController.isUseCamera2()) { // Calculate scaleFactor from seekBar progress. zoomCurrent = (float)progress / 10.f + 1.f; Log.e("!!!!!!!", "zoom current caculated = " + zoomCurrent); } if (zoomCurrent > CameraController.getMaxZoom()) { zoomCurrent = CameraController.getMaxZoom(); } //workaround for S7 issue with zooming. if (CameraController.isGalaxyS7 && zoomCurrent>1.2) { zoomCurrent+=0.001f; } CameraController.setZoom(zoomCurrent); } } }); } private void prepareActZoomButtons(boolean flag) { if (flag) { zoomPanel.setVisibility(View.VISIBLE); mButtonZoomOut.setVisibility(View.VISIBLE); mButtonZoomIn.setVisibility(View.VISIBLE); } else { zoomPanel.setVisibility(View.GONE); mButtonZoomOut.setVisibility(View.GONE); mButtonZoomIn.setVisibility(View.GONE); } } private void initZoomButtons() { mButtonZoomIn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { CameraController.actZoomSonyRemote("in", "1shot"); } }); mButtonZoomOut.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { CameraController.actZoomSonyRemote("out", "1shot"); } }); mButtonZoomIn.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View arg0) { CameraController.actZoomSonyRemote("in", "start"); return true; } }); mButtonZoomOut.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View arg0) { CameraController.actZoomSonyRemote("out", "start"); return true; } }); mButtonZoomIn.setOnTouchListener(new View.OnTouchListener() { private long downTime = -1; @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { if (System.currentTimeMillis() - downTime > 500) { CameraController.actZoomSonyRemote("in", "stop"); } } if (event.getAction() == MotionEvent.ACTION_DOWN) { downTime = System.currentTimeMillis(); } return false; } }); mButtonZoomOut.setOnTouchListener(new View.OnTouchListener() { private long downTime = -1; @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { if (System.currentTimeMillis() - downTime > 500) { CameraController.actZoomSonyRemote("out", "stop"); } } if (event.getAction() == MotionEvent.ACTION_DOWN) { downTime = System.currentTimeMillis(); } return false; } }); } @Override public void onStart() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainScreen.getMainContext()); isEnabled = prefs.getBoolean("enabledPrefZoom", true); zoomStopping = false; } @Override public void onStop() { zoomStopping = true; MainScreen.getGUIManager().removeViews(zoomPanel, R.id.specialPluginsLayout); } @Override public void onGUICreate() { MainScreen.getGUIManager().removeViews(zoomPanel, R.id.specialPluginsLayout); RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) MainScreen.getInstance() .findViewById(R.id.specialPluginsLayout).getLayoutParams(); mainLayoutHeight = lp.height; RelativeLayout.LayoutParams params; if (!CameraController.isRemoteCamera()) { params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); zoomPanelWidth = MainScreen.getAppResources().getDrawable(R.drawable.scrubber_control_pressed_holo) .getMinimumWidth(); params.setMargins(-zoomPanelWidth / 2, 0, 0, 0); params.height = (int) (mainLayoutHeight / 2.2); } else { params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params.setMargins(10, 0, 0, 0); } params.addRule(RelativeLayout.CENTER_VERTICAL); params.addRule(RelativeLayout.ALIGN_PARENT_LEFT); ((RelativeLayout) MainScreen.getInstance().findViewById(R.id.specialPluginsLayout)).addView(this.zoomPanel, params); this.zoomPanel.setLayoutParams(params); showZoomControls(); scaleGestureDetector = new ScaleGestureDetector(ApplicationScreen.instance, new OnScaleGestureListener() { @Override public boolean onScale(final ScaleGestureDetector scaleGestureDetector) { if (CameraController.isRemoteCamera()) { return false; } if (!CameraController.isUseCamera2()) { // Division by zero required for smooth zooming. zoomModify((scaleGestureDetector.getCurrentSpan() - scaleGestureDetector .getPreviousSpan()) / 10); } else { zoomModify(zoomCurrent * scaleGestureDetector.getScaleFactor() - zoomCurrent); } return true; } @Override public boolean onScaleBegin(final ScaleGestureDetector scaleGestureDetector) { if (CameraController.isRemoteCamera()) { return false; } return true; } @Override public void onScaleEnd(final ScaleGestureDetector scaleGestureDetector) { } }); onCameraParametersSetup(); } @Override public void onResume() { zoomStopping = false; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainScreen.getMainContext()); isEnabled = prefs.getBoolean("enabledPrefZoom", true); showZoomControls(); } public void showZoomControls() { if (!CameraController.isRemoteCamera()) { zoomPanel.findViewById(R.id.zoom_buttons_container).setVisibility(View.GONE); if (!isEnabled) zoomBar.setVisibility(View.GONE); else zoomBar.setVisibility(View.VISIBLE); } else { zoomBar.setVisibility(View.GONE); if (!isEnabled) zoomPanel.findViewById(R.id.zoom_buttons_container).setVisibility(View.GONE); else zoomPanel.findViewById(R.id.zoom_buttons_container).setVisibility(View.VISIBLE); } } @Override public void onCameraParametersSetup() { if (!CameraController.isUseCamera2()) { zoomCurrent = 0; } else { zoomCurrent = 1.f; } if (CameraController.isZoomSupported()) { // If isCamera2 mode, then decrease value by 1 and multiple maxZoom 10x, because it represent by scale factor (from 1.0 to maxZoom). // Else just set the exact value, given by CameraController (from 0 to maxZoom). zoomBar.setMax(CameraController.isUseCamera2() ? (int)(CameraController.getMaxZoom() * 10 - 10) : (int)CameraController.getMaxZoom()); zoomBar.setProgressAndThumb(0); zoomPanel.setVisibility(View.VISIBLE); CameraController.setZoom(zoomCurrent); } else zoomPanel.setVisibility(View.GONE); } private void zoomModify(float delta) { if (CameraController.isZoomSupported()) { try { zoomCurrent += delta; if (!CameraController.isUseCamera2()) { if (zoomCurrent < 0) zoomCurrent = 0; } else { if (zoomCurrent < 1) zoomCurrent = 1; } if (zoomCurrent > CameraController.getMaxZoom()) { zoomCurrent = CameraController.getMaxZoom(); } //workaround for S7 issue with zooming. if (CameraController.isGalaxyS7 && zoomCurrent>1.2) { zoomCurrent+=0.001f; } CameraController.setZoom(zoomCurrent); zoomBar.setProgressAndThumb((int) (CameraController.isUseCamera2() ? zoomCurrent * 10.f - 10 : zoomCurrent)); } catch (Exception e) { e.printStackTrace(); } } } public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_ZOOM_OUT) { this.zoomModify(CameraController.isUseCamera2() ? -0.1f : -1); return true; } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_ZOOM_IN) { this.zoomModify(CameraController.isUseCamera2() ? 0.1f : 1); return true; } return false; } PointF mid = new PointF(); static final int NONE = 0; static final int DRAG = 1; static final int ZOOM = 2; int mode = NONE; public void closeZoomPanel() { panelClosing = true; this.zoomPanel.clearAnimation(); Animation animation = new TranslateAnimation(0, -zoomPanelWidth / 2, 0, 0); animation.setDuration(300); animation.setRepeatCount(0); animation.setInterpolator(new LinearInterpolator()); animation.setFillAfter(true); this.zoomPanel.setAnimation(animation); animation.setAnimationListener(new AnimationListener() { @Override public void onAnimationEnd(Animation animation) { if (zoomStopping) { List<View> specialView = new ArrayList<View>(); RelativeLayout specialLayout = (RelativeLayout) MainScreen.getInstance().findViewById( R.id.specialPluginsLayout); for (int i = 0; i < specialLayout.getChildCount(); i++) specialView.add(specialLayout.getChildAt(i)); for (int j = 0; j < specialView.size(); j++) { final View view = specialView.get(j); int view_id = view.getId(); int zoom_id = zoomPanel.getId(); if (view_id == zoom_id) { final ViewGroup parentView = (ViewGroup) view.getParent(); if (parentView != null) { parentView.post(new Runnable() { public void run() { // it works without the runOnUiThread, // but all UI updates must // be done on the UI thread MainScreen.getInstance().runOnUiThread(new Runnable() { public void run() { parentView.removeView(view); } }); } }); } } } return; } RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) zoomPanel.getLayoutParams(); if (params == null) { zoomPanel.clearAnimation(); return; } params.setMargins(-zoomPanelWidth / 2, 0, 0, 0); zoomPanel.setLayoutParams(params); zoomPanel.clearAnimation(); panelOpened = false; panelClosing = false; if (panelToBeOpen) { panelToBeOpen = false; openZoomPanel(); } } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationStart(Animation animation) { } }); } public void openZoomPanel() { panelOpening = true; this.zoomPanel.clearAnimation(); Animation animation = new TranslateAnimation(0, zoomPanelWidth / 2, 0, 0); animation.setDuration(500); animation.setRepeatCount(0); animation.setInterpolator(new LinearInterpolator()); animation.setFillAfter(true); this.zoomPanel.setAnimation(animation); animation.setAnimationListener(new AnimationListener() { @Override public void onAnimationEnd(Animation animation) { RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) zoomPanel.getLayoutParams(); if (params == null) { zoomPanel.clearAnimation(); return; } params.setMargins(0, 0, 0, 0); zoomPanel.setLayoutParams(params); zoomPanel.clearAnimation(); zoomPanel.requestLayout(); panelOpened = true; panelOpening = false; } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationStart(Animation animation) { } }); } @Override public boolean onBroadcast(int arg1, int arg2) { if (!isEnabled) return false; if (arg1 == ApplicationInterface.MSG_CONTROL_LOCKED) mZoomDisabled = true; else if (arg1 == ApplicationInterface.MSG_CONTROL_UNLOCKED) mZoomDisabled = false; return false; } @Override public boolean onMultiTouch(View view, MotionEvent e) { return scaleGestureDetector.onTouchEvent(e); } }