--- /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.model.Point;\r
+import org.achartengine.model.SeriesSelection;\r
+import org.achartengine.renderer.DefaultRenderer;\r
+import org.achartengine.renderer.XYMultipleSeriesRenderer;\r
+import org.achartengine.tools.FitZoom;\r
+import org.achartengine.tools.PanListener;\r
+import org.achartengine.tools.Zoom;\r
+import org.achartengine.tools.ZoomListener;\r
+\r
+import android.content.Context;\r
+import android.graphics.Bitmap;\r
+import android.graphics.BitmapFactory;\r
+import android.graphics.Canvas;\r
+import android.graphics.Color;\r
+import android.graphics.Paint;\r
+import android.graphics.Rect;\r
+import android.graphics.RectF;\r
+import android.os.Build;\r
+import android.os.Handler;\r
+import android.view.MotionEvent;\r
+import android.view.View;\r
+\r
+/**\r
+ * The view that encapsulates the graphical chart.\r
+ */\r
+public class GraphicalView extends View {\r
+ /** The chart to be drawn. */\r
+ private AbstractChart mChart;\r
+ /** The chart renderer. */\r
+ private DefaultRenderer mRenderer;\r
+ /** The view bounds. */\r
+ private Rect mRect = new Rect();\r
+ /** The user interface thread handler. */\r
+ private Handler mHandler;\r
+ /** The zoom buttons rectangle. */\r
+ private RectF mZoomR = new RectF();\r
+ /** The zoom in icon. */\r
+ private Bitmap zoomInImage;\r
+ /** The zoom out icon. */\r
+ private Bitmap zoomOutImage;\r
+ /** The fit zoom icon. */\r
+ private Bitmap fitZoomImage;\r
+ /** The zoom area size. */\r
+ private int zoomSize = 50;\r
+ /** The zoom buttons background color. */\r
+ private static final int ZOOM_BUTTONS_COLOR = Color.argb(175, 150, 150, 150);\r
+ /** The zoom in tool. */\r
+ private Zoom mZoomIn;\r
+ /** The zoom out tool. */\r
+ private Zoom mZoomOut;\r
+ /** The fit zoom tool. */\r
+ private FitZoom mFitZoom;\r
+ /** The paint to be used when drawing the chart. */\r
+ private Paint mPaint = new Paint();\r
+ /** The touch handler. */\r
+ private ITouchHandler mTouchHandler;\r
+ /** The old x coordinate. */\r
+ private float oldX;\r
+ /** The old y coordinate. */\r
+ private float oldY;\r
+\r
+ /**\r
+ * Creates a new graphical view.\r
+ * \r
+ * @param context the context\r
+ * @param chart the chart to be drawn\r
+ */\r
+ public GraphicalView(Context context, AbstractChart chart) {\r
+ super(context);\r
+ mChart = chart;\r
+ mHandler = new Handler();\r
+ if (mChart instanceof XYChart) {\r
+ mRenderer = ((XYChart) mChart).getRenderer();\r
+ } else {\r
+ mRenderer = ((RoundChart) mChart).getRenderer();\r
+ }\r
+ if (mRenderer.isZoomButtonsVisible()) {\r
+ zoomInImage = BitmapFactory.decodeStream(GraphicalView.class\r
+ .getResourceAsStream("image/zoom_in.png"));\r
+ zoomOutImage = BitmapFactory.decodeStream(GraphicalView.class\r
+ .getResourceAsStream("image/zoom_out.png"));\r
+ fitZoomImage = BitmapFactory.decodeStream(GraphicalView.class\r
+ .getResourceAsStream("image/zoom-1.png"));\r
+ }\r
+\r
+ if (mRenderer instanceof XYMultipleSeriesRenderer\r
+ && ((XYMultipleSeriesRenderer) mRenderer).getMarginsColor() == XYMultipleSeriesRenderer.NO_COLOR) {\r
+ ((XYMultipleSeriesRenderer) mRenderer).setMarginsColor(mPaint.getColor());\r
+ }\r
+ if (mRenderer.isZoomEnabled() && mRenderer.isZoomButtonsVisible()\r
+ || mRenderer.isExternalZoomEnabled()) {\r
+ mZoomIn = new Zoom(mChart, true, mRenderer.getZoomRate());\r
+ mZoomOut = new Zoom(mChart, false, mRenderer.getZoomRate());\r
+ mFitZoom = new FitZoom(mChart);\r
+ }\r
+ int version = 7;\r
+ try {\r
+ version = Integer.valueOf(Build.VERSION.SDK);\r
+ } catch (Exception e) {\r
+ // do nothing\r
+ }\r
+ if (version < 7) {\r
+ mTouchHandler = new TouchHandlerOld(this, mChart);\r
+ } else {\r
+ mTouchHandler = new TouchHandler(this, mChart);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Returns the current series selection object.\r
+ * \r
+ * @return the series selection\r
+ */\r
+ public SeriesSelection getCurrentSeriesAndPoint() {\r
+ return mChart.getSeriesAndPointForScreenCoordinate(new Point(oldX, oldY));\r
+ }\r
+\r
+ /**\r
+ * Transforms the currently selected screen point to a real point.\r
+ * \r
+ * @param scale the scale\r
+ * @return the currently selected real point\r
+ */\r
+ public double[] toRealPoint(int scale) {\r
+ if (mChart instanceof XYChart) {\r
+ XYChart chart = (XYChart) mChart;\r
+ return chart.toRealPoint(oldX, oldY, scale);\r
+ }\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ protected void onDraw(Canvas canvas) {\r
+ super.onDraw(canvas);\r
+ canvas.getClipBounds(mRect);\r
+ int top = mRect.top;\r
+ int left = mRect.left;\r
+ int width = mRect.width();\r
+ int height = mRect.height();\r
+ if (mRenderer.isInScroll()) {\r
+ top = 0;\r
+ left = 0;\r
+ width = getMeasuredWidth();\r
+ height = getMeasuredHeight();\r
+ }\r
+ mChart.draw(canvas, left, top, width, height, mPaint);\r
+ if (mRenderer != null && mRenderer.isZoomEnabled() && mRenderer.isZoomButtonsVisible()) {\r
+ mPaint.setColor(ZOOM_BUTTONS_COLOR);\r
+ zoomSize = Math.max(zoomSize, Math.min(width, height) / 7);\r
+ mZoomR.set(left + width - zoomSize * 3, top + height - zoomSize * 0.775f, left + width, top\r
+ + height);\r
+ canvas.drawRoundRect(mZoomR, zoomSize / 3, zoomSize / 3, mPaint);\r
+ float buttonY = top + height - zoomSize * 0.625f;\r
+ canvas.drawBitmap(zoomInImage, left + width - zoomSize * 2.75f, buttonY, null);\r
+ canvas.drawBitmap(zoomOutImage, left + width - zoomSize * 1.75f, buttonY, null);\r
+ canvas.drawBitmap(fitZoomImage, left + width - zoomSize * 0.75f, buttonY, null);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Sets the zoom rate.\r
+ * \r
+ * @param rate the zoom rate\r
+ */\r
+ public void setZoomRate(float rate) {\r
+ if (mZoomIn != null && mZoomOut != null) {\r
+ mZoomIn.setZoomRate(rate);\r
+ mZoomOut.setZoomRate(rate);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Do a chart zoom in.\r
+ */\r
+ public void zoomIn() {\r
+ if (mZoomIn != null) {\r
+ mZoomIn.apply(Zoom.ZOOM_AXIS_XY);\r
+ repaint();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Do a chart zoom out.\r
+ */\r
+ public void zoomOut() {\r
+ if (mZoomOut != null) {\r
+ mZoomOut.apply(Zoom.ZOOM_AXIS_XY);\r
+ repaint();\r
+ }\r
+ }\r
+ \r
+\r
+\r
+ /**\r
+ * Do a chart zoom reset / fit zoom.\r
+ */\r
+ public void zoomReset() {\r
+ if (mFitZoom != null) {\r
+ mFitZoom.apply();\r
+ mZoomIn.notifyZoomResetListeners();\r
+ repaint();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Adds a new zoom listener.\r
+ * \r
+ * @param listener zoom listener\r
+ */\r
+ public void addZoomListener(ZoomListener listener, boolean onButtons, boolean onPinch) {\r
+ if (onButtons) {\r
+ if (mZoomIn != null) {\r
+ mZoomIn.addZoomListener(listener);\r
+ mZoomOut.addZoomListener(listener);\r
+ }\r
+ if (onPinch) {\r
+ mTouchHandler.addZoomListener(listener);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Removes a zoom listener.\r
+ * \r
+ * @param listener zoom listener\r
+ */\r
+ public synchronized void removeZoomListener(ZoomListener listener) {\r
+ if (mZoomIn != null) {\r
+ mZoomIn.removeZoomListener(listener);\r
+ mZoomOut.removeZoomListener(listener);\r
+ }\r
+ mTouchHandler.removeZoomListener(listener);\r
+ }\r
+\r
+ /**\r
+ * Adds a new pan listener.\r
+ * \r
+ * @param listener pan listener\r
+ */\r
+ public void addPanListener(PanListener listener) {\r
+ mTouchHandler.addPanListener(listener);\r
+ }\r
+\r
+ /**\r
+ * Removes a pan listener.\r
+ * \r
+ * @param listener pan listener\r
+ */\r
+ public void removePanListener(PanListener listener) {\r
+ mTouchHandler.removePanListener(listener);\r
+ }\r
+\r
+ protected RectF getZoomRectangle() {\r
+ return mZoomR;\r
+ }\r
+\r
+ @Override\r
+ public boolean onTouchEvent(MotionEvent event) {\r
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {\r
+ // save the x and y so they can be used in the click and long press\r
+ // listeners\r
+ oldX = event.getX();\r
+ oldY = event.getY();\r
+ }\r
+ if (mRenderer != null && (mRenderer.isPanEnabled() || mRenderer.isZoomEnabled())) {\r
+ if (mTouchHandler.handleTouch(event)) {\r
+ return true;\r
+ }\r
+ }\r
+ return super.onTouchEvent(event);\r
+ }\r
+\r
+ /**\r
+ * Schedule a view content repaint.\r
+ */\r
+ public void repaint() {\r
+ mHandler.post(new Runnable() {\r
+ public void run() {\r
+ invalidate();\r
+ }\r
+ });\r
+ }\r
+\r
+ /**\r
+ * Schedule a view content repaint, in the specified rectangle area.\r
+ * \r
+ * @param left the left position of the area to be repainted\r
+ * @param top the top position of the area to be repainted\r
+ * @param right the right position of the area to be repainted\r
+ * @param bottom the bottom position of the area to be repainted\r
+ */\r
+ public void repaint(final int left, final int top, final int right, final int bottom) {\r
+ mHandler.post(new Runnable() {\r
+ public void run() {\r
+ invalidate(left, top, right, bottom);\r
+ }\r
+ });\r
+ }\r
+\r
+ /**\r
+ * Saves the content of the graphical view to a bitmap.\r
+ * \r
+ * @return the bitmap\r
+ */\r
+ public Bitmap toBitmap() {\r
+ setDrawingCacheEnabled(false);\r
+ if (!isDrawingCacheEnabled()) {\r
+ setDrawingCacheEnabled(true);\r
+ }\r
+ if (mRenderer.isApplyBackgroundColor()) {\r
+ setDrawingCacheBackgroundColor(mRenderer.getBackgroundColor());\r
+ }\r
+ setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);\r
+ return getDrawingCache(true);\r
+ }\r
+\r
+}
\ No newline at end of file