+/**\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.tools;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\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
+\r
+/**\r
+ * The zoom tool.\r
+ */\r
+public class Zoom extends AbstractTool {\r
+ /** A flag to be used to know if this is a zoom in or out. */\r
+ private boolean mZoomIn;\r
+ /** The zoom rate. */\r
+ private float mZoomRate;\r
+ /** The zoom listeners. */\r
+ private List<ZoomListener> mZoomListeners = new ArrayList<ZoomListener>();\r
+ /** Zoom limits reached on the X axis. */\r
+ private boolean limitsReachedX = false;\r
+ /** Zoom limits reached on the Y axis. */\r
+ private boolean limitsReachedY = false;\r
+\r
+ /** Zoom on X axis and Y axis */\r
+ public static final int ZOOM_AXIS_XY = 0;\r
+ /** Zoom on X axis independently */\r
+ public static final int ZOOM_AXIS_X = 1;\r
+ /** Zoom on Y axis independently */\r
+ public static final int ZOOM_AXIS_Y = 2;\r
+\r
+\r
+ /**\r
+ * Builds the zoom tool.\r
+ * \r
+ * @param chart the chart\r
+ * @param in zoom in or out\r
+ * @param rate the zoom rate\r
+ */\r
+ public Zoom(AbstractChart chart, boolean in, float rate) {\r
+ super(chart);\r
+ mZoomIn = in;\r
+ setZoomRate(rate);\r
+ }\r
+\r
+ /**\r
+ * Sets the zoom rate.\r
+ * \r
+ * @param rate\r
+ */\r
+ public void setZoomRate(float rate) {\r
+ mZoomRate = rate;\r
+ }\r
+\r
+ /**\r
+ * Apply the zoom.\r
+ */\r
+ public void apply(int zoom_axis) {\r
+ if (mChart instanceof XYChart) {\r
+ int scales = mRenderer.getScalesCount();\r
+ for (int i = 0; i < scales; i++) {\r
+ double[] range = getRange(i);\r
+ checkRange(range, i);\r
+ double[] limits = mRenderer.getZoomLimits();\r
+\r
+ double centerX = (range[0] + range[1]) / 2;\r
+ double centerY = (range[2] + range[3]) / 2;\r
+ double newWidth = range[1] - range[0];\r
+ double newHeight = range[3] - range[2];\r
+ double newXMin = centerX - newWidth / 2;\r
+ double newXMax = centerX + newWidth / 2;\r
+ double newYMin = centerY - newHeight / 2;\r
+ double newYMax = centerY + newHeight / 2;\r
+\r
+ // if already reached last zoom, then it will always set to reached\r
+ if (i == 0) {\r
+ limitsReachedX = limits != null && (newXMin <= limits[0] || newXMax >= limits[1]);\r
+ limitsReachedY = limits != null && (newYMin <= limits[2] || newYMax >= limits[3]);\r
+ }\r
+\r
+ if (mZoomIn) {\r
+ if (mRenderer.isZoomXEnabled() && // zoom in on X axis\r
+ (zoom_axis == ZOOM_AXIS_X || zoom_axis == ZOOM_AXIS_XY)) {\r
+ if (limitsReachedX && mZoomRate < 1) { \r
+ // ignore pinch zoom out once reached X limit\r
+ } else {\r
+ newWidth /= mZoomRate;\r
+ }\r
+ }\r
+\r
+ if (mRenderer.isZoomYEnabled() && // zoom in on Y axis\r
+ (zoom_axis == ZOOM_AXIS_Y || zoom_axis == ZOOM_AXIS_XY)) {\r
+ if (limitsReachedY && mZoomRate < 1) {\r
+ } else {\r
+ newHeight /= mZoomRate;\r
+ }\r
+ }\r
+ } else {\r
+ if (mRenderer.isZoomXEnabled() && !limitsReachedX && // zoom out on X axis\r
+ (zoom_axis == ZOOM_AXIS_X || zoom_axis == ZOOM_AXIS_XY)) {\r
+ newWidth *= mZoomRate;\r
+ }\r
+\r
+ if (mRenderer.isZoomYEnabled() && !limitsReachedY && // zoom out on Y axis\r
+ (zoom_axis == ZOOM_AXIS_Y || zoom_axis == ZOOM_AXIS_XY)) {\r
+ newHeight *= mZoomRate;\r
+ }\r
+ }\r
+\r
+ if (mRenderer.isZoomXEnabled() && \r
+ (zoom_axis == ZOOM_AXIS_X || zoom_axis == ZOOM_AXIS_XY)) {\r
+ newXMin = centerX - newWidth / 2;\r
+ newXMax = centerX + newWidth / 2;\r
+ setXRange(newXMin, newXMax, i);\r
+ }\r
+ if (mRenderer.isZoomYEnabled() &&\r
+ (zoom_axis == ZOOM_AXIS_Y || zoom_axis == ZOOM_AXIS_XY)) {\r
+ newYMin = centerY - newHeight / 2;\r
+ newYMax = centerY + newHeight / 2;\r
+ setYRange(newYMin, newYMax, i);\r
+ }\r
+ }\r
+ } else {\r
+ DefaultRenderer renderer = ((RoundChart) mChart).getRenderer();\r
+ if (mZoomIn) {\r
+ renderer.setScale(renderer.getScale() * mZoomRate);\r
+ } else {\r
+ renderer.setScale(renderer.getScale() / mZoomRate);\r
+ }\r
+ }\r
+ notifyZoomListeners(new ZoomEvent(mZoomIn, mZoomRate));\r
+ }\r
+\r
+\r
+ /**\r
+ * Notify the zoom listeners about a zoom change.\r
+ * \r
+ * @param e the zoom event\r
+ */\r
+ private synchronized void notifyZoomListeners(ZoomEvent e) {\r
+ for (ZoomListener listener : mZoomListeners) {\r
+ listener.zoomApplied(e);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Notify the zoom listeners about a zoom reset.\r
+ */\r
+ public synchronized void notifyZoomResetListeners() {\r
+ for (ZoomListener listener : mZoomListeners) {\r
+ listener.zoomReset();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Adds a new zoom listener.\r
+ * \r
+ * @param listener zoom listener\r
+ */\r
+ public synchronized void addZoomListener(ZoomListener listener) {\r
+ mZoomListeners.add(listener);\r
+ }\r
+\r
+ /**\r
+ * Removes a zoom listener.\r
+ * \r
+ * @param listener zoom listener\r
+ */\r
+ public synchronized void removeZoomListener(ZoomListener listener) {\r
+ mZoomListeners.add(listener);\r
+ }\r
+\r
+}\r