--- /dev/null
+/**\r
+ * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.achartengine;\r
+\r
+import org.achartengine.chart.AbstractChart;\r
+import org.achartengine.chart.RoundChart;\r
+import org.achartengine.chart.XYChart;\r
+import org.achartengine.renderer.DefaultRenderer;\r
+import org.achartengine.tools.Pan;\r
+import org.achartengine.tools.PanListener;\r
+import org.achartengine.tools.Zoom;\r
+import org.achartengine.tools.ZoomListener;\r
+\r
+import android.graphics.RectF;\r
+import android.view.MotionEvent;\r
+\r
+/**\r
+ * The main handler of the touch events.\r
+ */\r
+public class TouchHandler implements ITouchHandler {\r
+ /** The chart renderer. */\r
+ private DefaultRenderer mRenderer;\r
+ /** The old x coordinate. */\r
+ private float oldX;\r
+ /** The old y coordinate. */\r
+ private float oldY;\r
+ /** The old x2 coordinate. */\r
+ private float oldX2;\r
+ /** The old y2 coordinate. */\r
+ private float oldY2;\r
+ /** The zoom buttons rectangle. */\r
+ private RectF zoomR = new RectF();\r
+ /** The pan tool. */\r
+ private Pan mPan;\r
+ /** The zoom for the pinch gesture. */\r
+ private Zoom mPinchZoom;\r
+ /** The graphical view. */\r
+ private GraphicalView graphicalView;\r
+\r
+ /**\r
+ * Creates a new graphical view.\r
+ * \r
+ * @param view the graphical view\r
+ * @param chart the chart to be drawn\r
+ */\r
+ public TouchHandler(GraphicalView view, AbstractChart chart) {\r
+ graphicalView = view;\r
+ zoomR = graphicalView.getZoomRectangle();\r
+ if (chart instanceof XYChart) {\r
+ mRenderer = ((XYChart) chart).getRenderer();\r
+ } else {\r
+ mRenderer = ((RoundChart) chart).getRenderer();\r
+ }\r
+ if (mRenderer.isPanEnabled()) {\r
+ mPan = new Pan(chart);\r
+ }\r
+ if (mRenderer.isZoomEnabled()) {\r
+ mPinchZoom = new Zoom(chart, true, 1);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Handles the touch event.\r
+ * \r
+ * @param event the touch event\r
+ */\r
+ public boolean handleTouch(MotionEvent event) {\r
+ int action = event.getAction();\r
+ if (mRenderer != null && action == MotionEvent.ACTION_MOVE) {\r
+ if (oldX >= 0 || oldY >= 0) {\r
+ float newX = event.getX(0);\r
+ float newY = event.getY(0);\r
+ if (event.getPointerCount() > 1 && (oldX2 >= 0 || oldY2 >= 0) && mRenderer.isZoomEnabled()) {\r
+ float newX2 = event.getX(1);\r
+ float newY2 = event.getY(1);\r
+ float newDeltaX = Math.abs(newX - newX2);\r
+ float newDeltaY = Math.abs(newY - newY2);\r
+ float oldDeltaX = Math.abs(oldX - oldX2);\r
+ float oldDeltaY = Math.abs(oldY - oldY2);\r
+ float zoomRate = 1;\r
+\r
+ float tan1 = Math.abs(newY - oldY) / Math.abs(newX - oldX);\r
+ float tan2 = Math.abs(newY2 - oldY2) / Math.abs(newX2 - oldX2);\r
+ if ( tan1 <= 0.577 && tan2 <= 0.577) {\r
+ // horizontal pinch zoom, |deltaY| / |deltaX| is [0 ~ 0.577], 0.577 is the approximate value of tan(Pi/6)\r
+ zoomRate = newDeltaX / oldDeltaX;\r
+ if (zoomRate > 0.909 && zoomRate < 1.1) {\r
+ mPinchZoom.setZoomRate(zoomRate);\r
+ mPinchZoom.apply(Zoom.ZOOM_AXIS_X);\r
+ }\r
+ } else if ( tan1 >= 1.732 && tan2 >= 1.732 ) {\r
+ // pinch zoom vertically, |deltaY| / |deltaX| is [1.732 ~ infinity], 1.732 is the approximate value of tan(Pi/3)\r
+ zoomRate = newDeltaY / oldDeltaY;\r
+ if (zoomRate > 0.909 && zoomRate < 1.1) {\r
+ mPinchZoom.setZoomRate(zoomRate);\r
+ mPinchZoom.apply(Zoom.ZOOM_AXIS_Y);\r
+ }\r
+ } else if ( (tan1 > 0.577 && tan1 < 1.732) && (tan2 > 0.577 && tan2 < 1.732) ){\r
+ // pinch zoom diagonally\r
+ if (Math.abs(newX - oldX) >= Math.abs(newY - oldY)) {\r
+ zoomRate = newDeltaX / oldDeltaX;\r
+ } else {\r
+ zoomRate = newDeltaY / oldDeltaY;\r
+ }\r
+ if (zoomRate > 0.909 && zoomRate < 1.1) {\r
+ mPinchZoom.setZoomRate(zoomRate);\r
+ mPinchZoom.apply(Zoom.ZOOM_AXIS_XY);\r
+ }\r
+ }\r
+ oldX2 = newX2;\r
+ oldY2 = newY2;\r
+ } else if (mRenderer.isPanEnabled()) {\r
+ mPan.apply(oldX, oldY, newX, newY);\r
+ oldX2 = 0;\r
+ oldY2 = 0;\r
+ }\r
+ oldX = newX;\r
+ oldY = newY;\r
+ graphicalView.repaint();\r
+ return true;\r
+ }\r
+ } else if (action == MotionEvent.ACTION_DOWN) {\r
+ oldX = event.getX(0);\r
+ oldY = event.getY(0);\r
+ if (mRenderer != null && mRenderer.isZoomEnabled() && zoomR.contains(oldX, oldY)) {\r
+ if (oldX < zoomR.left + zoomR.width() / 3) {\r
+ graphicalView.zoomIn();\r
+ } else if (oldX < zoomR.left + zoomR.width() * 2 / 3) {\r
+ graphicalView.zoomOut();\r
+ } else {\r
+ graphicalView.zoomReset();\r
+ }\r
+ return true;\r
+ }\r
+ } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) {\r
+ oldX = 0;\r
+ oldY = 0;\r
+ oldX2 = 0;\r
+ oldY2 = 0;\r
+ if (action == MotionEvent.ACTION_POINTER_UP) {\r
+ oldX = -1;\r
+ oldY = -1;\r
+ }\r
+ }\r
+ return !mRenderer.isClickEnabled();\r
+ }\r
+\r
+ /**\r
+ * Adds a new zoom listener.\r
+ * \r
+ * @param listener zoom listener\r
+ */\r
+ public void addZoomListener(ZoomListener listener) {\r
+ if (mPinchZoom != null) {\r
+ mPinchZoom.addZoomListener(listener);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Removes a zoom listener.\r
+ * \r
+ * @param listener zoom listener\r
+ */\r
+ public void removeZoomListener(ZoomListener listener) {\r
+ if (mPinchZoom != null) {\r
+ mPinchZoom.removeZoomListener(listener);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Adds a new pan listener.\r
+ * \r
+ * @param listener pan listener\r
+ */\r
+ public void addPanListener(PanListener listener) {\r
+ if (mPan != null) {\r
+ mPan.addPanListener(listener);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Removes a pan listener.\r
+ * \r
+ * @param listener pan listener\r
+ */\r
+ public void removePanListener(PanListener listener) {\r
+ if (mPan != null) {\r
+ mPan.removePanListener(listener);\r
+ }\r
+ }\r
+}
\ No newline at end of file