2 * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL
\r
4 * Licensed under the Apache License, Version 2.0 (the "License");
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://www.apache.org/licenses/LICENSE-2.0
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an "AS IS" BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
16 package org.achartengine;
\r
18 import org.achartengine.chart.AbstractChart;
\r
19 import org.achartengine.chart.RoundChart;
\r
20 import org.achartengine.chart.XYChart;
\r
21 import org.achartengine.model.Point;
\r
22 import org.achartengine.model.SeriesSelection;
\r
23 import org.achartengine.renderer.DefaultRenderer;
\r
24 import org.achartengine.renderer.XYMultipleSeriesRenderer;
\r
25 import org.achartengine.tools.FitZoom;
\r
26 import org.achartengine.tools.PanListener;
\r
27 import org.achartengine.tools.Zoom;
\r
28 import org.achartengine.tools.ZoomListener;
\r
30 import android.content.Context;
\r
31 import android.graphics.Bitmap;
\r
32 import android.graphics.BitmapFactory;
\r
33 import android.graphics.Canvas;
\r
34 import android.graphics.Color;
\r
35 import android.graphics.Paint;
\r
36 import android.graphics.Rect;
\r
37 import android.graphics.RectF;
\r
38 import android.os.Build;
\r
39 import android.os.Handler;
\r
40 import android.view.MotionEvent;
\r
41 import android.view.View;
\r
44 * The view that encapsulates the graphical chart.
\r
46 public class GraphicalView extends View {
\r
47 /** The chart to be drawn. */
\r
48 private AbstractChart mChart;
\r
49 /** The chart renderer. */
\r
50 private DefaultRenderer mRenderer;
\r
51 /** The view bounds. */
\r
52 private Rect mRect = new Rect();
\r
53 /** The user interface thread handler. */
\r
54 private Handler mHandler;
\r
55 /** The zoom buttons rectangle. */
\r
56 private RectF mZoomR = new RectF();
\r
57 /** The zoom in icon. */
\r
58 private Bitmap zoomInImage;
\r
59 /** The zoom out icon. */
\r
60 private Bitmap zoomOutImage;
\r
61 /** The fit zoom icon. */
\r
62 private Bitmap fitZoomImage;
\r
63 /** The zoom area size. */
\r
64 private int zoomSize = 50;
\r
65 /** The zoom buttons background color. */
\r
66 private static final int ZOOM_BUTTONS_COLOR = Color.argb(175, 150, 150, 150);
\r
67 /** The zoom in tool. */
\r
68 private Zoom mZoomIn;
\r
69 /** The zoom out tool. */
\r
70 private Zoom mZoomOut;
\r
71 /** The fit zoom tool. */
\r
72 private FitZoom mFitZoom;
\r
73 /** The paint to be used when drawing the chart. */
\r
74 private Paint mPaint = new Paint();
\r
75 /** The touch handler. */
\r
76 private ITouchHandler mTouchHandler;
\r
77 /** The old x coordinate. */
\r
79 /** The old y coordinate. */
\r
83 * Creates a new graphical view.
\r
85 * @param context the context
\r
86 * @param chart the chart to be drawn
\r
88 public GraphicalView(Context context, AbstractChart chart) {
\r
91 mHandler = new Handler();
\r
92 if (mChart instanceof XYChart) {
\r
93 mRenderer = ((XYChart) mChart).getRenderer();
\r
95 mRenderer = ((RoundChart) mChart).getRenderer();
\r
97 if (mRenderer.isZoomButtonsVisible()) {
\r
98 zoomInImage = BitmapFactory.decodeStream(GraphicalView.class
\r
99 .getResourceAsStream("image/zoom_in.png"));
\r
100 zoomOutImage = BitmapFactory.decodeStream(GraphicalView.class
\r
101 .getResourceAsStream("image/zoom_out.png"));
\r
102 fitZoomImage = BitmapFactory.decodeStream(GraphicalView.class
\r
103 .getResourceAsStream("image/zoom-1.png"));
\r
106 if (mRenderer instanceof XYMultipleSeriesRenderer
\r
107 && ((XYMultipleSeriesRenderer) mRenderer).getMarginsColor() == XYMultipleSeriesRenderer.NO_COLOR) {
\r
108 ((XYMultipleSeriesRenderer) mRenderer).setMarginsColor(mPaint.getColor());
\r
110 if (mRenderer.isZoomEnabled() && mRenderer.isZoomButtonsVisible()
\r
111 || mRenderer.isExternalZoomEnabled()) {
\r
112 mZoomIn = new Zoom(mChart, true, mRenderer.getZoomRate());
\r
113 mZoomOut = new Zoom(mChart, false, mRenderer.getZoomRate());
\r
114 mFitZoom = new FitZoom(mChart);
\r
118 version = Integer.valueOf(Build.VERSION.SDK);
\r
119 } catch (Exception e) {
\r
123 mTouchHandler = new TouchHandlerOld(this, mChart);
\r
125 mTouchHandler = new TouchHandler(this, mChart);
\r
130 * Returns the current series selection object.
\r
132 * @return the series selection
\r
134 public SeriesSelection getCurrentSeriesAndPoint() {
\r
135 return mChart.getSeriesAndPointForScreenCoordinate(new Point(oldX, oldY));
\r
139 * Transforms the currently selected screen point to a real point.
\r
141 * @param scale the scale
\r
142 * @return the currently selected real point
\r
144 public double[] toRealPoint(int scale) {
\r
145 if (mChart instanceof XYChart) {
\r
146 XYChart chart = (XYChart) mChart;
\r
147 return chart.toRealPoint(oldX, oldY, scale);
\r
153 protected void onDraw(Canvas canvas) {
\r
154 super.onDraw(canvas);
\r
155 canvas.getClipBounds(mRect);
\r
156 int top = mRect.top;
\r
157 int left = mRect.left;
\r
158 int width = mRect.width();
\r
159 int height = mRect.height();
\r
160 if (mRenderer.isInScroll()) {
\r
163 width = getMeasuredWidth();
\r
164 height = getMeasuredHeight();
\r
166 mChart.draw(canvas, left, top, width, height, mPaint);
\r
167 if (mRenderer != null && mRenderer.isZoomEnabled() && mRenderer.isZoomButtonsVisible()) {
\r
168 mPaint.setColor(ZOOM_BUTTONS_COLOR);
\r
169 zoomSize = Math.max(zoomSize, Math.min(width, height) / 7);
\r
170 mZoomR.set(left + width - zoomSize * 3, top + height - zoomSize * 0.775f, left + width, top
\r
172 canvas.drawRoundRect(mZoomR, zoomSize / 3, zoomSize / 3, mPaint);
\r
173 float buttonY = top + height - zoomSize * 0.625f;
\r
174 canvas.drawBitmap(zoomInImage, left + width - zoomSize * 2.75f, buttonY, null);
\r
175 canvas.drawBitmap(zoomOutImage, left + width - zoomSize * 1.75f, buttonY, null);
\r
176 canvas.drawBitmap(fitZoomImage, left + width - zoomSize * 0.75f, buttonY, null);
\r
181 * Sets the zoom rate.
\r
183 * @param rate the zoom rate
\r
185 public void setZoomRate(float rate) {
\r
186 if (mZoomIn != null && mZoomOut != null) {
\r
187 mZoomIn.setZoomRate(rate);
\r
188 mZoomOut.setZoomRate(rate);
\r
193 * Do a chart zoom in.
\r
195 public void zoomIn() {
\r
196 if (mZoomIn != null) {
\r
197 mZoomIn.apply(Zoom.ZOOM_AXIS_XY);
\r
203 * Do a chart zoom out.
\r
205 public void zoomOut() {
\r
206 if (mZoomOut != null) {
\r
207 mZoomOut.apply(Zoom.ZOOM_AXIS_XY);
\r
215 * Do a chart zoom reset / fit zoom.
\r
217 public void zoomReset() {
\r
218 if (mFitZoom != null) {
\r
220 mZoomIn.notifyZoomResetListeners();
\r
226 * Adds a new zoom listener.
\r
228 * @param listener zoom listener
\r
230 public void addZoomListener(ZoomListener listener, boolean onButtons, boolean onPinch) {
\r
232 if (mZoomIn != null) {
\r
233 mZoomIn.addZoomListener(listener);
\r
234 mZoomOut.addZoomListener(listener);
\r
237 mTouchHandler.addZoomListener(listener);
\r
243 * Removes a zoom listener.
\r
245 * @param listener zoom listener
\r
247 public synchronized void removeZoomListener(ZoomListener listener) {
\r
248 if (mZoomIn != null) {
\r
249 mZoomIn.removeZoomListener(listener);
\r
250 mZoomOut.removeZoomListener(listener);
\r
252 mTouchHandler.removeZoomListener(listener);
\r
256 * Adds a new pan listener.
\r
258 * @param listener pan listener
\r
260 public void addPanListener(PanListener listener) {
\r
261 mTouchHandler.addPanListener(listener);
\r
265 * Removes a pan listener.
\r
267 * @param listener pan listener
\r
269 public void removePanListener(PanListener listener) {
\r
270 mTouchHandler.removePanListener(listener);
\r
273 protected RectF getZoomRectangle() {
\r
278 public boolean onTouchEvent(MotionEvent event) {
\r
279 if (event.getAction() == MotionEvent.ACTION_DOWN) {
\r
280 // save the x and y so they can be used in the click and long press
\r
282 oldX = event.getX();
\r
283 oldY = event.getY();
\r
285 if (mRenderer != null && (mRenderer.isPanEnabled() || mRenderer.isZoomEnabled())) {
\r
286 if (mTouchHandler.handleTouch(event)) {
\r
290 return super.onTouchEvent(event);
\r
294 * Schedule a view content repaint.
\r
296 public void repaint() {
\r
297 mHandler.post(new Runnable() {
\r
298 public void run() {
\r
305 * Schedule a view content repaint, in the specified rectangle area.
\r
307 * @param left the left position of the area to be repainted
\r
308 * @param top the top position of the area to be repainted
\r
309 * @param right the right position of the area to be repainted
\r
310 * @param bottom the bottom position of the area to be repainted
\r
312 public void repaint(final int left, final int top, final int right, final int bottom) {
\r
313 mHandler.post(new Runnable() {
\r
314 public void run() {
\r
315 invalidate(left, top, right, bottom);
\r
321 * Saves the content of the graphical view to a bitmap.
\r
323 * @return the bitmap
\r
325 public Bitmap toBitmap() {
\r
326 setDrawingCacheEnabled(false);
\r
327 if (!isDrawingCacheEnabled()) {
\r
328 setDrawingCacheEnabled(true);
\r
330 if (mRenderer.isApplyBackgroundColor()) {
\r
331 setDrawingCacheBackgroundColor(mRenderer.getBackgroundColor());
\r
333 setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
\r
334 return getDrawingCache(true);
\r