--- /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.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
+\r
+/**\r
+ * The pan tool.\r
+ */\r
+public class Pan extends AbstractTool {\r
+ /** The pan listeners. */\r
+ private List<PanListener> mPanListeners = new ArrayList<PanListener>();\r
+ /** Pan limits reached on the X axis. */\r
+ private boolean limitsReachedX = false;\r
+ /** Pan limits reached on the X axis. */\r
+ private boolean limitsReachedY = false;\r
+\r
+ /**\r
+ * Builds and instance of the pan tool.\r
+ * \r
+ * @param chart the XY chart\r
+ */\r
+ public Pan(AbstractChart chart) {\r
+ super(chart);\r
+ }\r
+\r
+ /**\r
+ * Apply the tool.\r
+ * \r
+ * @param oldX the previous location on X axis\r
+ * @param oldY the previous location on Y axis\r
+ * @param newX the current location on X axis\r
+ * @param newY the current location on the Y axis\r
+ */\r
+ public void apply(float oldX, float oldY, float newX, float newY) {\r
+ boolean notLimitedUp = true;\r
+ boolean notLimitedBottom = true;\r
+ boolean notLimitedLeft = true;\r
+ boolean notLimitedRight = true;\r
+ if (mChart instanceof XYChart) {\r
+ int scales = mRenderer.getScalesCount();\r
+ double[] limits = mRenderer.getPanLimits();\r
+ boolean limited = limits != null && limits.length == 4;\r
+ XYChart chart = (XYChart) mChart;\r
+ for (int i = 0; i < scales; i++) {\r
+ double[] range = getRange(i);\r
+ double[] calcRange = chart.getCalcRange(i);\r
+ if (limitsReachedX\r
+ && limitsReachedY\r
+ && (range[0] == range[1] && calcRange[0] == calcRange[1] || range[2] == range[3]\r
+ && calcRange[2] == calcRange[3])) {\r
+ return;\r
+ }\r
+ checkRange(range, i);\r
+\r
+ double[] realPoint = chart.toRealPoint(oldX, oldY, i);\r
+ double[] realPoint2 = chart.toRealPoint(newX, newY, i);\r
+ double deltaX = realPoint[0] - realPoint2[0];\r
+ double deltaY = realPoint[1] - realPoint2[1];\r
+ double ratio = getAxisRatio(range);\r
+ if (chart.isVertical(mRenderer)) {\r
+ double newDeltaX = -deltaY * ratio;\r
+ double newDeltaY = deltaX / ratio;\r
+ deltaX = newDeltaX;\r
+ deltaY = newDeltaY;\r
+ }\r
+ if (mRenderer.isPanXEnabled()) {\r
+ if (limits != null) {\r
+ if (notLimitedLeft) {\r
+ notLimitedLeft = limits[0] <= range[0] + deltaX;\r
+ }\r
+ if (notLimitedRight) {\r
+ notLimitedRight = limits[1] >= range[1] + deltaX;\r
+ }\r
+ }\r
+ if (!limited || (notLimitedLeft && notLimitedRight)) {\r
+ setXRange(range[0] + deltaX, range[1] + deltaX, i);\r
+ limitsReachedX = false;\r
+ } else {\r
+ limitsReachedX = true;\r
+ }\r
+ }\r
+ if (mRenderer.isPanYEnabled()) {\r
+ if (limits != null) {\r
+ if (notLimitedBottom) {\r
+ notLimitedBottom = limits[2] <= range[2] + deltaY;\r
+ }\r
+ if (notLimitedUp) {\r
+ notLimitedUp = limits[3] >= range[3] + deltaY;\r
+ }\r
+ }\r
+ if (!limited || (notLimitedBottom && notLimitedUp)) {\r
+ setYRange(range[2] + deltaY, range[3] + deltaY, i);\r
+ limitsReachedY = false;\r
+ } else {\r
+ limitsReachedY = true;\r
+ }\r
+ }\r
+ }\r
+ } else {\r
+ RoundChart chart = (RoundChart) mChart;\r
+ chart.setCenterX(chart.getCenterX() + (int) (newX - oldX));\r
+ chart.setCenterY(chart.getCenterY() + (int) (newY - oldY));\r
+ }\r
+ notifyPanListeners();\r
+ }\r
+\r
+ /**\r
+ * Return the X / Y axis range ratio.\r
+ * \r
+ * @param range the axis range\r
+ * @return the ratio\r
+ */\r
+ private double getAxisRatio(double[] range) {\r
+ return Math.abs(range[1] - range[0]) / Math.abs(range[3] - range[2]);\r
+ }\r
+\r
+ /**\r
+ * Notify the pan listeners about a pan.\r
+ */\r
+ private synchronized void notifyPanListeners() {\r
+ for (PanListener listener : mPanListeners) {\r
+ listener.panApplied();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Adds a new pan listener.\r
+ * \r
+ * @param listener pan listener\r
+ */\r
+ public synchronized void addPanListener(PanListener listener) {\r
+ mPanListeners.add(listener);\r
+ }\r
+\r
+ /**\r
+ * Removes a pan listener.\r
+ * \r
+ * @param listener pan listener\r
+ */\r
+ public synchronized void removePanListener(PanListener listener) {\r
+ mPanListeners.add(listener);\r
+ }\r
+\r
+}\r