Advertisement
Guest User

Untitled

a guest
May 4th, 2015
225
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 35.04 KB | None | 0 0
  1. /* ===========================================================
  2. * AFreeChart : a free chart library for Android(tm) platform.
  3. * (based on JFreeChart and JCommon)
  4. * ===========================================================
  5. *
  6. * (C) Copyright 2010, by ICOMSYSTECH Co.,Ltd.
  7. * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors.
  8. *
  9. * Project Info:
  10. * AFreeChart: http://code.google.com/p/afreechart/
  11. * JFreeChart: http://www.jfree.org/jfreechart/index.html
  12. * JCommon : http://www.jfree.org/jcommon/index.html
  13. *
  14. * This program is free software: you can redistribute it and/or modify
  15. * it under the terms of the GNU Lesser General Public License as published by
  16. * the Free Software Foundation, either version 3 of the License, or
  17. * (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU Lesser General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU Lesser General Public License
  25. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  26. *
  27. * [Android is a trademark of Google Inc.]
  28. *
  29. * -----------------
  30. * ChartView.java
  31. * -----------------
  32. * (C) Copyright 2010, by ICOMSYSTECH Co.,Ltd.
  33. *
  34. * Original Author: Niwano Masayoshi (for ICOMSYSTECH Co.,Ltd);
  35. * Contributor(s): -;
  36. *
  37. * Changes
  38. * -------
  39. * 19-Nov-2010 : Version 0.0.1 (NM);
  40. * 14-Jan-2011 : renamed method name
  41. * 14-Jan-2011 : Updated API docs
  42. */
  43.  
  44. package org.afree.chart.demo;
  45.  
  46. import org.afree.ui.RectangleInsets;
  47. import org.afree.chart.ChartTouchEvent;
  48. import org.afree.chart.ChartTouchListener;
  49. import org.afree.chart.ChartRenderingInfo;
  50. import org.afree.chart.AFreeChart;
  51. import org.afree.chart.entity.ChartEntity;
  52. import org.afree.chart.entity.EntityCollection;
  53. import org.afree.chart.event.ChartChangeEvent;
  54. import org.afree.chart.event.ChartChangeListener;
  55. import org.afree.chart.event.ChartProgressEvent;
  56. import org.afree.chart.event.ChartProgressListener;
  57. import org.afree.chart.plot.Movable;
  58. import org.afree.chart.plot.Plot;
  59. import org.afree.chart.plot.PlotOrientation;
  60. import org.afree.chart.plot.PlotRenderingInfo;
  61. import org.afree.chart.plot.Zoomable;
  62. import org.afree.graphics.geom.Dimension;
  63. import org.afree.graphics.geom.RectShape;
  64. import org.afree.graphics.SolidColor;
  65.  
  66. import java.util.EventListener;
  67. import java.util.concurrent.CopyOnWriteArrayList;
  68.  
  69. import android.content.Context;
  70. import android.graphics.Canvas;
  71. import android.graphics.Color;
  72. import android.graphics.PointF;
  73. import android.os.Handler;
  74. import android.util.AttributeSet;
  75. import android.util.Log;
  76. import android.view.MotionEvent;
  77. import android.view.View;
  78.  
  79.  
  80. public class DemoView extends View
  81. implements ChartChangeListener, ChartProgressListener{
  82.  
  83. /** The user interface thread handler. */
  84. private Handler mHandler;
  85.  
  86. public DemoView(Context context) {
  87. super(context);
  88. mHandler = new Handler();
  89. this.initialize();
  90. }
  91.  
  92. public DemoView(Context context, AttributeSet attrs) {
  93. super(context, attrs);
  94. mHandler = new Handler();
  95. this.initialize();
  96. }
  97.  
  98. /**
  99. * initialize parameters
  100. */
  101. private void initialize() {
  102. this.chartMotionListeners = new CopyOnWriteArrayList<ChartTouchListener>();
  103. this.info = new ChartRenderingInfo();
  104. this.minimumDrawWidth = DEFAULT_MINIMUM_DRAW_WIDTH;
  105. this.minimumDrawHeight = DEFAULT_MINIMUM_DRAW_HEIGHT;
  106. this.maximumDrawWidth = DEFAULT_MAXIMUM_DRAW_WIDTH;
  107. this.maximumDrawHeight = DEFAULT_MAXIMUM_DRAW_HEIGHT;
  108. this.moveTriggerDistance = DEFAULT_MOVE_TRIGGER_DISTANCE;
  109. new SolidColor(Color.BLUE);
  110. new SolidColor(Color.argb(0, 0, 255, 63));
  111. new java.util.ArrayList();
  112. }
  113.  
  114. /**
  115. * Default setting for buffer usage. The default has been changed to
  116. * <code>true</code> from version 1.0.13 onwards, because of a severe
  117. * performance problem with drawing the zoom RectShape using XOR (which
  118. * now happens only when the buffer is NOT used).
  119. */
  120. public static final boolean DEFAULT_BUFFER_USED = true;
  121.  
  122. /** The default panel width. */
  123. public static final int DEFAULT_WIDTH = 680;
  124.  
  125. /** The default panel height. */
  126. public static final int DEFAULT_HEIGHT = 420;
  127.  
  128. /** The default limit below which chart scaling kicks in. */
  129. public static final int DEFAULT_MINIMUM_DRAW_WIDTH = 10;
  130.  
  131. /** The default limit below which chart scaling kicks in. */
  132. public static final int DEFAULT_MINIMUM_DRAW_HEIGHT = 10;
  133.  
  134. /** The default limit above which chart scaling kicks in. */
  135. public static final int DEFAULT_MAXIMUM_DRAW_WIDTH = 1024;
  136.  
  137. /** The default limit above which chart scaling kicks in. */
  138. public static final int DEFAULT_MAXIMUM_DRAW_HEIGHT = 1000;
  139.  
  140. /** The minimum size required to perform a zoom on a RectShape */
  141. public static final int DEFAULT_ZOOM_TRIGGER_DISTANCE = 10;
  142.  
  143. /** The minimum size required to perform a move on a RectShape */
  144. public static final int DEFAULT_MOVE_TRIGGER_DISTANCE = 10;
  145.  
  146. /** The chart that is displayed in the panel. */
  147. private AFreeChart chart;
  148.  
  149. /** Storage for registered (chart) touch listeners. */
  150. private transient CopyOnWriteArrayList<ChartTouchListener> chartMotionListeners;
  151.  
  152. /** The drawing info collected the last time the chart was drawn. */
  153. private ChartRenderingInfo info;
  154.  
  155. /** The scale factor used to draw the chart. */
  156. private double scaleX;
  157.  
  158. /** The scale factor used to draw the chart. */
  159. private double scaleY;
  160.  
  161. /** The plot orientation. */
  162. private PlotOrientation orientation = PlotOrientation.VERTICAL;
  163.  
  164. /**
  165. * The zoom RectShape starting point (selected by the user with touch).
  166. * This is a point on the screen, not the chart (which may have
  167. * been scaled up or down to fit the panel).
  168. */
  169. private PointF zoomPoint = null;
  170.  
  171. /** Controls if the zoom RectShape is drawn as an outline or filled. */
  172. // private boolean fillZoomRectShape = true;
  173.  
  174. private int moveTriggerDistance;
  175.  
  176. /** The last touch position during panning. */
  177. // private Point panLast;
  178.  
  179. private RectangleInsets insets = null;
  180.  
  181.  
  182. /**
  183. * The minimum width for drawing a chart (uses scaling for smaller widths).
  184. */
  185. private int minimumDrawWidth;
  186.  
  187. /**
  188. * The minimum height for drawing a chart (uses scaling for smaller
  189. * heights).
  190. */
  191. private int minimumDrawHeight;
  192.  
  193. /**
  194. * The maximum width for drawing a chart (uses scaling for bigger
  195. * widths).
  196. */
  197. private int maximumDrawWidth;
  198.  
  199. /**
  200. * The maximum height for drawing a chart (uses scaling for bigger
  201. * heights).
  202. */
  203. private int maximumDrawHeight;
  204.  
  205. private Dimension size = null;
  206.  
  207. /** The chart anchor point. */
  208. private PointF anchor;
  209.  
  210. /** A flag that controls whether or not domain moving is enabled. */
  211. private boolean domainMovable = false;
  212.  
  213. /** A flag that controls whether or not range moving is enabled. */
  214. private boolean rangeMovable = false;
  215.  
  216. private double accelX, accelY;
  217. private double friction = 0.8;
  218. private boolean inertialMovedFlag = false;
  219. private PointF lastTouch;
  220.  
  221. private float mScale = 1.0f;
  222.  
  223. private long mPrevTimeMillis = 0;
  224. private long mNowTimeMillis = System.currentTimeMillis();
  225.  
  226. /**
  227. * touch event
  228. */
  229. public boolean onTouchEvent(MotionEvent ev) {
  230.  
  231. super.onTouchEvent(ev);
  232. int action = ev.getAction();
  233. int count = ev.getPointerCount();
  234.  
  235. this.anchor = new PointF(ev.getX(), ev.getY());
  236.  
  237. if (this.info != null) {
  238. EntityCollection entities = this.info.getEntityCollection();
  239. if (entities != null) {
  240. }
  241. }
  242.  
  243. switch (action & MotionEvent.ACTION_MASK) {
  244. case MotionEvent.ACTION_DOWN:
  245. case MotionEvent.ACTION_POINTER_DOWN:
  246. Log.i("TouchEvent", "ACTION_DOWN");
  247. if(count == 2 && this.multiTouchStartInfo == null) {
  248. setMultiTouchStartInfo(ev);
  249. } else if (count == 1 && this.singleTouchStartInfo == null) {
  250. setSingleTouchStartInfo(ev);
  251. }
  252.  
  253. touched(ev);
  254.  
  255. break;
  256. case MotionEvent.ACTION_MOVE:
  257. Log.i("TouchEvent", "ACTION_MOVE");
  258. if(count == 1 && this.singleTouchStartInfo != null) {
  259. moveAdjustment(ev);
  260. } else if (count == 2 && this.multiTouchStartInfo != null) {
  261. //scaleAdjustment(ev);
  262. zoomAdjustment(ev);
  263. }
  264.  
  265. inertialMovedFlag = false;
  266.  
  267. break;
  268. case MotionEvent.ACTION_UP:
  269. case MotionEvent.ACTION_POINTER_UP:
  270. Log.i("TouchEvent", "ACTION_UP");
  271. if(count <= 2) {
  272. this.multiTouchStartInfo = null;
  273. this.singleTouchStartInfo = null;
  274. }
  275. if (count <= 1) {
  276. this.singleTouchStartInfo = null;
  277. }
  278.  
  279. // double click check
  280. if (count == 1) {
  281. mNowTimeMillis = System.currentTimeMillis();
  282. if(mNowTimeMillis - mPrevTimeMillis < 400) {
  283. if(chart.getPlot() instanceof Movable) {
  284. restoreAutoBounds();
  285. mScale = 1.0f;
  286. inertialMovedFlag = false;
  287. }
  288. } else {
  289. inertialMovedFlag = true;
  290. }
  291. mPrevTimeMillis = mNowTimeMillis;
  292. }
  293. break;
  294. default:
  295. break;
  296. }
  297.  
  298. return true;
  299. }
  300.  
  301. /**
  302. * MultiTouchStartInfo setting
  303. * @param ev
  304. */
  305. private void setMultiTouchStartInfo(MotionEvent ev) {
  306.  
  307. if(this.multiTouchStartInfo == null) {
  308. this.multiTouchStartInfo = new MultiTouchStartInfo();
  309. }
  310.  
  311. // distance
  312. double distance = Math.sqrt(Math.pow(ev.getX(0) - ev.getX(1),2) + Math.pow(ev.getY(0) - ev.getY(1),2));
  313. this.multiTouchStartInfo.setDistance(distance);
  314. }
  315.  
  316. /**
  317. * SingleTouchStartInfo setting
  318. * @param ev
  319. */
  320. private void setSingleTouchStartInfo(MotionEvent ev) {
  321.  
  322. if(this.singleTouchStartInfo == null) {
  323. this.singleTouchStartInfo = new SingleTouchStartInfo();
  324. }
  325.  
  326. // start point
  327. this.singleTouchStartInfo.setX(ev.getX(0));
  328. this.singleTouchStartInfo.setY(ev.getY(0));
  329. }
  330.  
  331.  
  332.  
  333. /**
  334. * Translate MotionEvent as TouchEvent
  335. * @param ev
  336. */
  337. private void moveAdjustment(MotionEvent ev) {
  338.  
  339. boolean hMove = false;
  340. boolean vMove = false;
  341. if (this.orientation == PlotOrientation.HORIZONTAL) {
  342. hMove = this.rangeMovable;
  343. vMove = this.domainMovable;
  344. }
  345. else {
  346. hMove = this.domainMovable;
  347. vMove = this.rangeMovable;
  348. }
  349.  
  350. boolean moveTrigger1 = hMove && Math.abs(ev.getX(0) - this.singleTouchStartInfo.getX() ) >= this.moveTriggerDistance;
  351. boolean moveTrigger2 = vMove && Math.abs(ev.getY(0) - this.singleTouchStartInfo.getY()) >= this.moveTriggerDistance;
  352. if (moveTrigger1 || moveTrigger2) {
  353.  
  354. RectShape dataArea = this.info.getPlotInfo().getDataArea();
  355.  
  356. double moveBoundX;
  357. double moveBoundY;
  358. double dataAreaWidth = dataArea.getWidth();
  359. double dataAreaHeight = dataArea.getHeight();
  360.  
  361. // for touchReleased event, (horizontalZoom || verticalZoom)
  362. // will be true, so we can just test for either being false;
  363. // otherwise both are true
  364.  
  365. if (!vMove) {
  366. moveBoundX = this.singleTouchStartInfo.getX() - ev.getX(0);
  367. moveBoundY = 0;
  368. }
  369. else if (!hMove) {
  370. moveBoundX = 0;
  371. moveBoundY = this.singleTouchStartInfo.getY() - ev.getY(0);
  372. }
  373. else {
  374. moveBoundX = this.singleTouchStartInfo.getX() - ev.getX(0);
  375. moveBoundY = this.singleTouchStartInfo.getY() - ev.getY(0);
  376. }
  377. accelX = moveBoundX;
  378. accelY = moveBoundY;
  379.  
  380. lastTouch = new PointF(ev.getX(0), ev.getY(0));
  381. move(lastTouch, moveBoundX,moveBoundY,dataAreaWidth,dataAreaHeight);
  382.  
  383. }
  384.  
  385. setSingleTouchStartInfo(ev);
  386. }
  387.  
  388. /**
  389. *
  390. * @param moveBoundX
  391. * @param moveBoundY
  392. * @param dataAreaWidth
  393. * @param dataAreaHeight
  394. */
  395. private void move(PointF source, double moveBoundX, double moveBoundY,
  396. double dataAreaWidth, double dataAreaHeight) {
  397.  
  398. if (source == null) {
  399. throw new IllegalArgumentException("Null 'source' argument");
  400. }
  401.  
  402. double hMovePercent = moveBoundX / dataAreaWidth;
  403. double vMovePercent = - moveBoundY / dataAreaHeight;
  404.  
  405. Plot p = this.chart.getPlot();
  406. if (p instanceof Movable) {
  407. PlotRenderingInfo info = this.info.getPlotInfo();
  408. // here we tweak the notify flag on the plot so that only
  409. // one notification happens even though we update multiple
  410. // axes...
  411. //boolean savedNotify = p.isNotify();
  412. //p.setNotify(false);
  413. Movable z = (Movable) p;
  414. if (z.getOrientation() == PlotOrientation.HORIZONTAL) {
  415. z.moveDomainAxes(vMovePercent, info, source);
  416. z.moveRangeAxes(hMovePercent, info, source);
  417. }
  418. else {
  419. z.moveDomainAxes(hMovePercent, info, source);
  420. z.moveRangeAxes(vMovePercent, info, source);
  421. }
  422. //p.setNotify(savedNotify);
  423.  
  424. //repaint
  425. invalidate();
  426. }
  427.  
  428. }
  429.  
  430.  
  431. /**
  432. * Restores the auto-range calculation on both axes.
  433. */
  434. public void restoreAutoBounds() {
  435. Plot plot = this.chart.getPlot();
  436. if (plot == null) {
  437. return;
  438. }
  439. // here we tweak the notify flag on the plot so that only
  440. // one notification happens even though we update multiple
  441. // axes...
  442. //boolean savedNotify = plot.isNotify();
  443. //plot.setNotify(false);
  444. restoreAutoDomainBounds();
  445. restoreAutoRangeBounds();
  446. //plot.setNotify(savedNotify);
  447. }
  448.  
  449. /**
  450. * Restores the auto-range calculation on the domain axis.
  451. */
  452. public void restoreAutoDomainBounds() {
  453. Plot plot = this.chart.getPlot();
  454. if (plot instanceof Zoomable) {
  455. Zoomable z = (Zoomable) plot;
  456. // here we tweak the notify flag on the plot so that only
  457. // one notification happens even though we update multiple
  458. // axes...
  459. //boolean savedNotify = plot.isNotify();
  460. //plot.setNotify(false);
  461. // we need to guard against this.zoomPoint being null
  462. PointF zp = (this.zoomPoint != null
  463. ? this.zoomPoint : new PointF());
  464. z.zoomDomainAxes(0.0, this.info.getPlotInfo(), zp);
  465. //plot.setNotify(savedNotify);
  466. }
  467. }
  468.  
  469. /**
  470. * Restores the auto-range calculation on the range axis.
  471. */
  472. public void restoreAutoRangeBounds() {
  473. Plot plot = this.chart.getPlot();
  474. if (plot instanceof Zoomable) {
  475. Zoomable z = (Zoomable) plot;
  476. // here we tweak the notify flag on the plot so that only
  477. // one notification happens even though we update multiple
  478. // axes...
  479. //boolean savedNotify = plot.isNotify();
  480. //plot.setNotify(false);
  481. // we need to guard against this.zoomPoint being null
  482. PointF zp = (this.zoomPoint != null
  483. ? this.zoomPoint : new PointF());
  484. z.zoomRangeAxes(0.0, this.info.getPlotInfo(), zp);
  485. //plot.setNotify(savedNotify);
  486. }
  487. }
  488.  
  489. protected void onSizeChanged(int w, int h, int oldw, int oldh){
  490. this.insets = new RectangleInsets(0,0,0,0);
  491. this.size = new Dimension(w, h);
  492. }
  493.  
  494. private RectangleInsets getInsets() {
  495. return this.insets;
  496. }
  497.  
  498. /**
  499. * Returns the X scale factor for the chart. This will be 1.0 if no
  500. * scaling has been used.
  501. *
  502. * @return The scale factor.
  503. */
  504. public double getScaleX() {
  505. return this.scaleX;
  506. }
  507.  
  508. /**
  509. * Returns the Y scale factory for the chart. This will be 1.0 if no
  510. * scaling has been used.
  511. *
  512. * @return The scale factor.
  513. */
  514. public double getScaleY() {
  515. return this.scaleY;
  516. }
  517.  
  518. /**
  519. * Sets the chart that is displayed in the panel.
  520. *
  521. * @param chart the chart (<code>null</code> permitted).
  522. */
  523. public void setChart(AFreeChart chart) {
  524.  
  525. // stop listening for changes to the existing chart
  526. if (this.chart != null) {
  527. this.chart.removeChangeListener(this);
  528. this.chart.removeProgressListener(this);
  529. }
  530.  
  531. // add the new chart
  532. this.chart = chart;
  533. if (chart != null) {
  534. this.chart.addChangeListener(this);
  535. this.chart.addProgressListener(this);
  536. Plot plot = chart.getPlot();
  537. if (plot instanceof Zoomable) {
  538. Zoomable z = (Zoomable) plot;
  539. z.isRangeZoomable();
  540. this.orientation = z.getOrientation();
  541. }
  542.  
  543. this.domainMovable = false;
  544. this.rangeMovable = false;
  545. if (plot instanceof Movable) {
  546. Movable z = (Movable) plot;
  547. this.domainMovable = z.isDomainMovable();
  548. this.rangeMovable = z.isRangeMovable();
  549. this.orientation = z.getOrientation();
  550. }
  551. }
  552. else {
  553. this.domainMovable = false;
  554. this.rangeMovable = false;
  555. }
  556. // if (this.useBuffer) {
  557. // this.refreshBuffer = true;
  558. // }
  559. repaint();
  560.  
  561. }
  562.  
  563. /**
  564. * Returns the minimum drawing width for charts.
  565. * <P>
  566. * If the width available on the panel is less than this, then the chart is
  567. * drawn at the minimum width then scaled down to fit.
  568. *
  569. * @return The minimum drawing width.
  570. */
  571. public int getMinimumDrawWidth() {
  572. return this.minimumDrawWidth;
  573. }
  574.  
  575. /**
  576. * Sets the minimum drawing width for the chart on this panel.
  577. * <P>
  578. * At the time the chart is drawn on the panel, if the available width is
  579. * less than this amount, the chart will be drawn using the minimum width
  580. * then scaled down to fit the available space.
  581. *
  582. * @param width The width.
  583. */
  584. public void setMinimumDrawWidth(int width) {
  585. this.minimumDrawWidth = width;
  586. }
  587.  
  588. /**
  589. * Returns the maximum drawing width for charts.
  590. * <P>
  591. * If the width available on the panel is greater than this, then the chart
  592. * is drawn at the maximum width then scaled up to fit.
  593. *
  594. * @return The maximum drawing width.
  595. */
  596. public int getMaximumDrawWidth() {
  597. return this.maximumDrawWidth;
  598. }
  599.  
  600. /**
  601. * Sets the maximum drawing width for the chart on this panel.
  602. * <P>
  603. * At the time the chart is drawn on the panel, if the available width is
  604. * greater than this amount, the chart will be drawn using the maximum
  605. * width then scaled up to fit the available space.
  606. *
  607. * @param width The width.
  608. */
  609. public void setMaximumDrawWidth(int width) {
  610. this.maximumDrawWidth = width;
  611. }
  612.  
  613. /**
  614. * Returns the minimum drawing height for charts.
  615. * <P>
  616. * If the height available on the panel is less than this, then the chart
  617. * is drawn at the minimum height then scaled down to fit.
  618. *
  619. * @return The minimum drawing height.
  620. */
  621. public int getMinimumDrawHeight() {
  622. return this.minimumDrawHeight;
  623. }
  624.  
  625. /**
  626. * Sets the minimum drawing height for the chart on this panel.
  627. * <P>
  628. * At the time the chart is drawn on the panel, if the available height is
  629. * less than this amount, the chart will be drawn using the minimum height
  630. * then scaled down to fit the available space.
  631. *
  632. * @param height The height.
  633. */
  634. public void setMinimumDrawHeight(int height) {
  635. this.minimumDrawHeight = height;
  636. }
  637.  
  638. /**
  639. * Returns the maximum drawing height for charts.
  640. * <P>
  641. * If the height available on the panel is greater than this, then the
  642. * chart is drawn at the maximum height then scaled up to fit.
  643. *
  644. * @return The maximum drawing height.
  645. */
  646. public int getMaximumDrawHeight() {
  647. return this.maximumDrawHeight;
  648. }
  649.  
  650. /**
  651. * Sets the maximum drawing height for the chart on this panel.
  652. * <P>
  653. * At the time the chart is drawn on the panel, if the available height is
  654. * greater than this amount, the chart will be drawn using the maximum
  655. * height then scaled up to fit the available space.
  656. *
  657. * @param height The height.
  658. */
  659. public void setMaximumDrawHeight(int height) {
  660. this.maximumDrawHeight = height;
  661. }
  662.  
  663. /**
  664. * Returns the chart rendering info from the most recent chart redraw.
  665. *
  666. * @return The chart rendering info.
  667. */
  668. public ChartRenderingInfo getChartRenderingInfo() {
  669. return this.info;
  670. }
  671.  
  672. protected void onDraw(Canvas canvas) {
  673. super.onDraw(canvas);
  674.  
  675. inertialMove();
  676.  
  677. paintComponent(canvas);
  678. }
  679.  
  680. @Override
  681. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
  682. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  683. }
  684.  
  685.  
  686. /**
  687. * Paints the component by drawing the chart to fill the entire component,
  688. * but allowing for the insets (which will be non-zero if a border has been
  689. * set for this component). To increase performance (at the expense of
  690. * memory), an off-screen buffer image can be used.
  691. *
  692. * @param canvas the graphics device for drawing on.
  693. */
  694. public void paintComponent(Canvas canvas) {
  695.  
  696. // first determine the size of the chart rendering area...
  697. Dimension size = getSize();
  698. RectangleInsets insets = getInsets();
  699. RectShape available = new RectShape(insets.getLeft(), insets.getTop(),
  700. size.getWidth() - insets.getLeft() - insets.getRight(),
  701. size.getHeight() - insets.getTop() - insets.getBottom());
  702.  
  703. double drawWidth = available.getWidth();
  704. double drawHeight = available.getHeight();
  705. this.scaleX = 1.0;
  706. this.scaleY = 1.0;
  707.  
  708. if (drawWidth < this.minimumDrawWidth) {
  709. this.scaleX = drawWidth / this.minimumDrawWidth;
  710. drawWidth = this.minimumDrawWidth;
  711. }
  712. else if (drawWidth > this.maximumDrawWidth) {
  713. this.scaleX = drawWidth / this.maximumDrawWidth;
  714. drawWidth = this.maximumDrawWidth;
  715. }
  716.  
  717. if (drawHeight < this.minimumDrawHeight) {
  718. this.scaleY = drawHeight / this.minimumDrawHeight;
  719. drawHeight = this.minimumDrawHeight;
  720. }
  721. else if (drawHeight > this.maximumDrawHeight) {
  722. this.scaleY = drawHeight / this.maximumDrawHeight;
  723. drawHeight = this.maximumDrawHeight;
  724. }
  725.  
  726. RectShape chartArea = new RectShape(0.0, 0.0, drawWidth,
  727. drawHeight);
  728.  
  729. // are we using the chart buffer?
  730. // if (this.useBuffer) {
  731. //
  732. // // do we need to resize the buffer?
  733. // if ((this.chartBuffer == null)
  734. // || (this.chartBufferWidth != available.getWidth())
  735. // || (this.chartBufferHeight != available.getHeight())) {
  736. // this.chartBufferWidth = (int) available.getWidth();
  737. // this.chartBufferHeight = (int) available.getHeight();
  738. // GraphicsConfiguration gc = canvas.getDeviceConfiguration();
  739. // this.chartBuffer = gc.createCompatibleImage(
  740. // this.chartBufferWidth, this.chartBufferHeight,
  741. // Transparency.TRANSLUCENT);
  742. // this.refreshBuffer = true;
  743. // }
  744. //
  745. // // do we need to redraw the buffer?
  746. // if (this.refreshBuffer) {
  747. //
  748. // this.refreshBuffer = false; // clear the flag
  749. //
  750. // RectShape bufferArea = new RectShape(
  751. // 0, 0, this.chartBufferWidth, this.chartBufferHeight);
  752. //
  753. // Graphics2D bufferG2 = (Graphics2D)
  754. // this.chartBuffer.getGraphics();
  755. // RectShape r = new RectShape(0, 0, this.chartBufferWidth,
  756. // this.chartBufferHeight);
  757. // bufferG2.setPaint(getBackground());
  758. // bufferG2.fill(r);
  759. // if (scale) {
  760. // AffineTransform saved = bufferG2.getTransform();
  761. // AffineTransform st = AffineTransform.getScaleInstance(
  762. // this.scaleX, this.scaleY);
  763. // bufferG2.transform(st);
  764. // this.chart.draw(bufferG2, chartArea, this.anchor,
  765. // this.info);
  766. // bufferG2.setTransform(saved);
  767. // }
  768. // else {
  769. // this.chart.draw(bufferG2, bufferArea, this.anchor,
  770. // this.info);
  771. // }
  772. //
  773. // }
  774. //
  775. // // zap the buffer onto the panel...
  776. // canvas.drawImage(this.chartBuffer, insets.left, insets.top, this);
  777. //
  778. // }
  779.  
  780. // TODO:AffineTransform
  781. // or redrawing the chart every time...
  782. // else {
  783.  
  784. // AffineTransform saved = canvas.getTransform();
  785. // canvas.translate(insets.left, insets.top);
  786. // if (scale) {
  787. // AffineTransform st = AffineTransform.getScaleInstance(
  788. // this.scaleX, this.scaleY);
  789. // canvas.transform(st);
  790. // }
  791. // this.chart.draw(canvas, chartArea, this.anchor, this.info);
  792. // canvas.setTransform(saved);
  793.  
  794. // }
  795. this.chart.draw(canvas, chartArea, this.anchor, this.info);
  796.  
  797.  
  798. // Iterator iterator = this.overlays.iterator();
  799. // while (iterator.hasNext()) {
  800. // Overlay overlay = (Overlay) iterator.next();
  801. // overlay.paintOverlay(canvas, this);
  802. // }
  803.  
  804. // redraw the zoom RectShape (if present) - if useBuffer is false,
  805. // we use XOR so we can XOR the RectShape away again without redrawing
  806. // the chart
  807. //drawZoomRectShape(canvas, !this.useBuffer);
  808.  
  809. //canvas.dispose();
  810.  
  811. this.anchor = null;
  812. // this.verticalTraceLine = null;
  813. // this.horizontalTraceLine = null;
  814.  
  815. }
  816.  
  817.  
  818. public Dimension getSize() {
  819. return this.size;
  820. }
  821.  
  822. /**
  823. * Returns the anchor point.
  824. *
  825. * @return The anchor point (possibly <code>null</code>).
  826. */
  827. public PointF getAnchor() {
  828. return this.anchor;
  829. }
  830.  
  831.  
  832. public ChartRenderingInfo getInfo() {
  833. return info;
  834. }
  835.  
  836. /**
  837. * Sets the anchor point. This method is provided for the use of
  838. * subclasses, not end users.
  839. *
  840. * @param anchor the anchor point (<code>null</code> permitted).
  841. */
  842. protected void setAnchor(PointF anchor) {
  843. this.anchor = anchor;
  844. }
  845.  
  846. /**
  847. * Information for multi touch start
  848. * @author ikeda
  849. *
  850. */
  851. private class MultiTouchStartInfo {
  852. private double distance = 0;
  853.  
  854. public double getDistance() {
  855. return distance;
  856. }
  857. public void setDistance(double distance) {
  858. this.distance = distance;
  859. }
  860. }
  861.  
  862. private MultiTouchStartInfo multiTouchStartInfo = null;
  863.  
  864. /**
  865. * Information for Single touch start
  866. * @author ikeda
  867. *
  868. */
  869. private class SingleTouchStartInfo {
  870. private double x = 0;
  871. private double y = 0;
  872.  
  873. public double getX() {
  874. return x;
  875. }
  876. public void setX(double x) {
  877. this.x = x;
  878. }
  879. public double getY() {
  880. return y;
  881. }
  882. public void setY(double y) {
  883. this.y = y;
  884. }
  885. }
  886.  
  887. private SingleTouchStartInfo singleTouchStartInfo = null;
  888.  
  889. /**
  890. * Zoom
  891. * @param ev
  892. */
  893. private void zoomAdjustment(MotionEvent ev) {
  894. PointF point = new PointF((ev.getX(0) + ev.getX(1)) / 2, (ev.getY(0) + ev.getY(1)) / 2);
  895. //end distance
  896. double endDistance = Math.sqrt(Math.pow(ev.getX(0) - ev.getX(1),2) + Math.pow(ev.getY(0) - ev.getY(1),2));
  897.  
  898. // zoom process
  899. zoom(point, this.multiTouchStartInfo.getDistance(),endDistance);
  900.  
  901. // reset start point
  902. setMultiTouchStartInfo(ev);
  903. }
  904.  
  905. /**
  906. * zoom
  907. * @param startDistance
  908. * @param endDistance
  909. */
  910. private void zoom(PointF source, double startDistance, double endDistance) {
  911.  
  912. Plot plot = this.chart.getPlot();
  913. PlotRenderingInfo info = this.info.getPlotInfo();
  914.  
  915. if(plot instanceof Zoomable) {
  916. float scaleDistance = (float)(startDistance / endDistance);
  917.  
  918. if (this.mScale * scaleDistance < 10.0f &&
  919. this.mScale * scaleDistance > 0.1f) {
  920. this.mScale *= scaleDistance;
  921. Zoomable z = (Zoomable) plot;
  922. z.zoomDomainAxes(scaleDistance, info, source, false);
  923. z.zoomRangeAxes(scaleDistance, info, source, false);
  924. }
  925. }
  926.  
  927. // repaint
  928. invalidate();
  929. }
  930.  
  931. private void inertialMove() {
  932. if(inertialMovedFlag == true) {
  933. RectShape dataArea = this.info.getPlotInfo().getDataArea();
  934.  
  935. accelX *= friction;
  936. accelY *= friction;
  937.  
  938. double dataAreaWidth = dataArea.getWidth();
  939. double dataAreaHeight = dataArea.getHeight();
  940.  
  941. if (lastTouch != null) {
  942. move(lastTouch, accelX, accelY, dataAreaWidth, dataAreaHeight);
  943. }
  944.  
  945. if(accelX < 0.1 && accelX > -0.1) {
  946. accelX = 0;
  947. }
  948.  
  949. if(accelY < 0.1 && accelY > -0.1) {
  950. accelY = 0;
  951. }
  952.  
  953. if(accelX == 0 && accelY == 0) {
  954. inertialMovedFlag = false;
  955. }
  956. }
  957. } /**
  958. * Receives notification of touch on the panel. These are
  959. * translated and passed on to any registered {@link ChartTouchListener}s.
  960. *
  961. * @param event Information about the touch event.
  962. */
  963. public void touched(MotionEvent event) {
  964.  
  965. int x = (int) (event.getX() / this.scaleX);
  966. int y = (int) (event.getY() / this.scaleY);
  967.  
  968. this.anchor = new PointF(x, y);
  969. if (this.chart == null) {
  970. return;
  971. }
  972. this.chart.setNotify(true); // force a redraw
  973.  
  974. chart.handleClick((int)event.getX(), (int)event.getY(), info);
  975. inertialMovedFlag = false;
  976.  
  977. // new entity code...
  978. if (this.chartMotionListeners.size() == 0) {
  979. return;
  980. }
  981.  
  982. ChartEntity entity = null;
  983. if (this.info != null) {
  984. EntityCollection entities = this.info.getEntityCollection();
  985. if (entities != null) {
  986. entity = entities.getEntity(x, y);
  987. }
  988. }
  989. ChartTouchEvent chartEvent = new ChartTouchEvent(getChart(), event,
  990. entity);
  991. for (int i = chartMotionListeners.size() - 1; i >= 0; i--) {
  992. this.chartMotionListeners.get(i).chartTouched(chartEvent);
  993. }
  994.  
  995. }
  996.  
  997. /**
  998. * Returns the chart contained in the panel.
  999. *
  1000. * @return The chart (possibly <code>null</code>).
  1001. */
  1002. public AFreeChart getChart() {
  1003. return this.chart;
  1004. }
  1005.  
  1006. /**
  1007. * Adds a listener to the list of objects listening for chart touch events.
  1008. *
  1009. * @param listener the listener (<code>null</code> not permitted).
  1010. */
  1011. public void addChartTouchListener(ChartTouchListener listener) {
  1012. if (listener == null) {
  1013. throw new IllegalArgumentException("Null 'listener' argument.");
  1014. }
  1015. this.chartMotionListeners.add(listener);
  1016. }
  1017.  
  1018. /**
  1019. * Removes a listener from the list of objects listening for chart touch
  1020. * events.
  1021. *
  1022. * @param listener the listener.
  1023. */
  1024. public void removeChartTouchListener(ChartTouchListener listener) {
  1025. this.chartMotionListeners.remove(listener);
  1026. }
  1027.  
  1028. /**
  1029. * Returns an array of the listeners of the given type registered with the
  1030. * panel.
  1031. *
  1032. * @param listenerType the listener type.
  1033. *
  1034. * @return An array of listeners.
  1035. */
  1036. public EventListener[] getListeners() {
  1037. return this.chartMotionListeners.toArray(new ChartTouchListener[0]);
  1038. }
  1039.  
  1040. /**
  1041. * Schedule a user interface repaint.
  1042. */
  1043. public void repaint() {
  1044. mHandler.post(new Runnable() {
  1045. public void run() {
  1046. invalidate();
  1047. }
  1048. });
  1049. }
  1050.  
  1051. /**
  1052. * Receives notification of changes to the chart, and redraws the chart.
  1053. *
  1054. * @param event details of the chart change event.
  1055. */
  1056. public void chartChanged(ChartChangeEvent event) {
  1057. // this.refreshBuffer = true;
  1058. Plot plot = this.chart.getPlot();
  1059. if (plot instanceof Zoomable) {
  1060. Zoomable z = (Zoomable) plot;
  1061. this.orientation = z.getOrientation();
  1062. }
  1063. repaint();
  1064. }
  1065.  
  1066. /**
  1067. * Receives notification of a chart progress event.
  1068. *
  1069. * @param event the event.
  1070. */
  1071. public void chartProgress(ChartProgressEvent event) {
  1072. // does nothing - override if necessary
  1073. }
  1074. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement