Restore Zoom Point (zoom out) overriding ChartPanel patch

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
wzwei28
Posts: 105
Joined: Wed Mar 16, 2005 9:17 am
Location: Malaysia, Earth
Contact:

Restore Zoom Point (zoom out) overriding ChartPanel patch

Post by wzwei28 » Thu Oct 11, 2007 2:22 pm

Override ChartPanel for restore zooming points (Zoom out / Zoom back to previous point/rectangle)
Usage: Can implement in different chart, either horizontal/vertical/both zoom

Sample demo can view Order Manager System(OMS) link at http://vnetcode.org

Event: When user right-click it will restore previous zooming point
Testing senario: User can zoom n times...then everytime it right-click it will restore back to previous zooming point/rectangle/plotArea (no limitation in zooming count cause it is arrayList not object/array)
Algorithm(workaround):
1)firstly store six element(hLower,hUpper,vLower,vUpper,plotInfo,selectOrigin) in ArrayList
2)Based on total size of ArrayList, we knew how many times user had zoom in
3)Hence, every time user right-click, it will firstly return to original bounds
and then start zoom in n-1 times.
4)If we want chart to restore previous zoom Point by right-click,
then we called restoreZoomPoint() in 'mouseReleased'>'else if (e.isPopupTrigger()){' method
5)Delete last index of the zooming data everytime after restore back.

Overriding code in 'org.jfree.chart.ChartPanel' as follow:
(1 global variable,1 new method,1 existing method,1 call event)

global Variable:

Code: Select all

 /**
   * WZW override
   * ArrayList to store zoom data(in percentage) 
   * alLowerX, alUpperX, alLowerY, alUpperY, alPlotInfo, alSelectOrigin
   * X-domainAxis, Y-rangeAxis
   */
  private ArrayList<Double> alLowerX = new ArrayList<Double>();
  private ArrayList<Double> alUpperX = new ArrayList<Double>();
  private ArrayList<Double> alLowerY = new ArrayList<Double>();
  private ArrayList<Double> alUpperY = new ArrayList<Double>();
  private ArrayList<PlotRenderingInfo> alPlotInfo = new ArrayList<PlotRenderingInfo>();
  private ArrayList<Point2D> alSelectOrigin = new ArrayList<Point2D>();


New method:

Code: Select all

/**
   * WZW override
   * Restore zoomPoints based on storing of 6 element
   * called by mouse Right-click
   */
  private void restoreZoomPoint(){
    int iLen = alLowerX.size();
    int iLast = iLen - 1; //minus 1
    //^Restore only if user had zoom before(store data in ArrayList)
    //^Reset to original chart at initial stage before looping zoom
  if(iLen>0){
    restoreAutoBounds();    	  		
      for(int i=0; i<iLast; i++){
        //^Value restoring
        double hLower = alLowerX.get(i);
        double hUpper = alUpperX.get(i);
        double vLower = alLowerY.get(i);
        double vUpper = alUpperY.get(i);
        PlotRenderingInfo plotInfo = alPlotInfo.get(i);
        Point2D selectOrigin = alSelectOrigin.get(i);
        Plot p = this.chart.getPlot();            
        if (p instanceof Zoomable) {
            Zoomable z = (Zoomable) p;
            if (z.getOrientation() == PlotOrientation.HORIZONTAL) {
                z.zoomDomainAxes(vLower, vUpper, plotInfo, selectOrigin);
                z.zoomRangeAxes(hLower, hUpper, plotInfo, selectOrigin);
            }else {
                z.zoomDomainAxes(hLower, hUpper, plotInfo, selectOrigin);
                z.zoomRangeAxes(vLower, vUpper, plotInfo, selectOrigin);
            }
        }
      }
      //^Removing last(most recent) element
      alLowerX.remove(iLast);
      alUpperX.remove(iLast);
      alLowerY.remove(iLast);
      alUpperY.remove(iLast);
      alPlotInfo.remove(iLast);
      alSelectOrigin.remove(iLast);
    }
}
Existing method:
start: //^WZW override start
end: //^WZW override end

Code: Select all

/**
   * WZW override
   * Zooms in on a selected region.
   *
   * @param selection  the selected region.
   */
  public void zoom(Rectangle2D selection) {

      // get the origin of the zoom selection in the Java2D space used for
      // drawing the chart (that is, before any scaling to fit the panel)
      Point2D selectOrigin = translateScreenToJava2D(new Point(
              (int) Math.ceil(selection.getX()), 
              (int) Math.ceil(selection.getY())));
      PlotRenderingInfo plotInfo = this.info.getPlotInfo();
      Rectangle2D scaledDataArea = getScreenDataArea(
              (int) selection.getCenterX(), (int) selection.getCenterY());
      if ((selection.getHeight() > 0) && (selection.getWidth() > 0)) {
        
          double hLower = (selection.getMinX() - scaledDataArea.getMinX()) 
              / scaledDataArea.getWidth();
          double hUpper = (selection.getMaxX() - scaledDataArea.getMinX()) 
              / scaledDataArea.getWidth();
          double vLower = (scaledDataArea.getMaxY() - selection.getMaxY()) 
              / scaledDataArea.getHeight();
          double vUpper = (scaledDataArea.getMaxY() - selection.getMinY()) 
              / scaledDataArea.getHeight();
          //^WZW override start
          alLowerX.add(hLower);
          alUpperX.add(hUpper);
          alLowerY.add(vLower);
          alUpperY.add(vUpper);
          alPlotInfo.add(plotInfo);
          alSelectOrigin.add(selectOrigin);
          //^WZW override end
         
          Plot p = this.chart.getPlot();            
          if (p instanceof Zoomable) {
              Zoomable z = (Zoomable) p;
              if (z.getOrientation() == PlotOrientation.HORIZONTAL) {
                  z.zoomDomainAxes(vLower, vUpper, plotInfo, selectOrigin);
                  z.zoomRangeAxes(hLower, hUpper, plotInfo, selectOrigin);
              }
              else {
                  z.zoomDomainAxes(hLower, hUpper, plotInfo, selectOrigin);
                  z.zoomRangeAxes(vLower, vUpper, plotInfo, selectOrigin);
              }
          }
      }
  }


Right-click to restore(replace popup menu) event...
In public void mouseReleased(MouseEvent e) {: method

Code: Select all

  else if (e.isPopupTrigger()) {
      if (this.popup != null) {
          //#?displayPopupMenu(e.getX(), e.getY());
          restoreZoomPoint();		
      }
  }

Any mistake found, or query, can post here or email me to wzwei28 (->) yahoo.com

Another simple algo for realtime dynamic crosshair(mouse XY) + tooltip
Sample demo URL: http://vnetcode.org (OMS)
Jfreechart post: http://www.jfree.org/phpBB2/viewtopic.php?p=64888
Last edited by wzwei28 on Thu Oct 18, 2007 1:27 pm, edited 4 times in total.

wzwei28
Posts: 105
Joined: Wed Mar 16, 2005 9:17 am
Location: Malaysia, Earth
Contact:

Post by wzwei28 » Thu Oct 11, 2007 2:37 pm

Hope it helps those application that need restore zoom point (zoom back to previous zoomPoint)! Demo at http://vnetcode.org , source code at post above

annac
Posts: 24
Joined: Mon Oct 01, 2007 7:56 pm
Location: Canada

Post by annac » Thu Oct 11, 2007 5:07 pm

just what I was looking for! thank you for sharing your code with us :)

just one question. why did you choose to restore the original bounds and then zoom in n-1 times? did you encounter a problem in simply setting the axes bounds to the previous values?

I have also been looking for a way to capture and display the x and y coordinates of the cursor pretty much exactly the way you are showing in your sample demo. would you mind sharing how you accomplished that?

thank you very much for all your help! much appreciated

wzwei28
Posts: 105
Joined: Wed Mar 16, 2005 9:17 am
Location: Malaysia, Earth
Contact:

Post by wzwei28 » Thu Oct 11, 2007 5:42 pm

U are welcome annac.
David,Taqua,skunk,develop,and others had contribute so many^n, although my knowledge is limited, I hope i oso can contribute little effort on it.
just one question. why did you choose to restore the original bounds and then zoom in n-1 times? did you encounter a problem in simply setting the axes bounds to the previous values?
My thinking: Yes, this is my 2nd simple algo. In jfreechart, the zooming is based on width + height, then come to percentage of the Plot...Perhaps another way is to stored the dX,dY and dXX,dYY (value in the zooming rectangle)...But troublesome, and eventually not suitable for me, cause I want the rescale the bounds to auto-fit highest 'ask' and lowest 'bid' value.
(Truncated unwanted space and auto-scale after horizontal zoom, hence the chart will appear bigger, focus on data not empty space.)
*This auto-scale features is pending to-do.

For the x,y realtime tooltip, I am re-enhance newer version on this. It will show tooltip in top banner as well as tootltip box in corner. If it can fade out after 1 seconds even better. After completed in these few days, I will post the code/patch in jfreechart forum with title 'Realtime XY tooltip (data in banner and box)'. But maybe my code not 100% suit for all chart type...so, those who interested maybe need to customize a bit to fit his chart type.

Simple algo for realtime dynamic crosshair(mouse XY) + tooltip
Sample demo URL: http://vnetcode.org
Jfreechart post: http://www.jfree.org/phpBB2/viewtopic.php?p=64888
Last edited by wzwei28 on Thu Oct 18, 2007 1:23 pm, edited 2 times in total.

annac
Posts: 24
Joined: Mon Oct 01, 2007 7:56 pm
Location: Canada

Post by annac » Fri Oct 12, 2007 7:08 pm

did you make these changes within the actual ChartPanel class or did you subclass ChartPanel to override the methods?...

wzwei28
Posts: 105
Joined: Wed Mar 16, 2005 9:17 am
Location: Malaysia, Earth
Contact:

Post by wzwei28 » Fri Oct 12, 2007 8:06 pm

1st get the source code of org.jfree.chart.ChartPanel.java
Then after u override code in ChartPanel, compile it.
Ur eclipse / jcreator / netbeans / intelliJ IDEA / etc IDE... will automatic replace old org.jfree.chart.ChartPanel(in library) with new org.jfree.chart.ChartPanel class. (Concept:no need manually exclude ChartPanel from library)

(Meaning, u have two ChartPanel now, 1 in import library, 1 in ur jar or WEB-INF/classes , but ur IDE will combine ur new override ChartPanel class with other imported jfreechart library classes)
Even when u use obfuscator + shrinker...the concept is same.

Hope my explanation not so confusing...

annac
Posts: 24
Joined: Mon Oct 01, 2007 7:56 pm
Location: Canada

Post by annac » Fri Oct 12, 2007 10:06 pm

I am using eclipse. so you are saying that if I change the source ChartPanel.java file the jar file will automatically update the ChartPanel.class file? do I need to import the ChartPanel.java file somewhere special in my eclipse project to work on it?

sorry for all the questions. I am new to this open source thing! thank you for the help :)

annac
Posts: 24
Joined: Mon Oct 01, 2007 7:56 pm
Location: Canada

Post by annac » Fri Oct 12, 2007 10:55 pm

I think I figured it out. I specified the location path for the java source attachment of the jar file and now I am able to open up the .class file and edit it. Is this what you meant?

wzwei28
Posts: 105
Joined: Wed Mar 16, 2005 9:17 am
Location: Malaysia, Earth
Contact:

Post by wzwei28 » Fri Oct 12, 2007 11:47 pm

After u get the source(java) of org.jfree.chart.ChartPanel
U create a package named org.jfree.chart in ur project
Next, u copy the 'ChartPanel.java' into org.jfree.chart package
Then, u just override(modify) the ChartPanel class.

Now, ur import libarary of jfreechart-1.0.6 got 1 ChartPanel class, and after u compile u oso have 1 override ChartPanel class...but, eclipse will run the ChartPanel that u compile...to replace the existing in library...

However, override method oso works well... ur new method(few modified) replacing the orginal ChartPanel method... like extend ChartPanel class...

Hope it helps!
Last edited by wzwei28 on Thu Oct 18, 2007 1:35 pm, edited 1 time in total.

laurent b
Posts: 7
Joined: Fri Apr 27, 2007 5:43 am

Post by laurent b » Sat Oct 13, 2007 12:30 am

annac wrote:did you make these changes within the actual ChartPanel class or did you subclass ChartPanel to override the methods?...
Beside the legal problem when you modify a GPL lib (your source becomes GPL then), it's better to override

Locked