Android Open Source - AnkiStats Advanced Plot Sheet






From Project

Back to project page AnkiStats.

License

The source code is released under:

GNU General Public License

If you think the Android project AnkiStats listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * //from www.  ja  v a  2 s.c  o  m
 */
package com.wildplot.android.rendering;

import java.util.HashMap;
import java.util.Vector;
import java.util.concurrent.locks.ReentrantLock;

import com.wildplot.android.rendering.graphics.wrapper.BufferedImage;
import com.wildplot.android.rendering.graphics.wrapper.Color;
import com.wildplot.android.rendering.graphics.wrapper.FontMetrics;
import com.wildplot.android.rendering.graphics.wrapper.Graphics2D;
import com.wildplot.android.rendering.graphics.wrapper.Rectangle;
import com.wildplot.android.rendering.interfaces.Drawable;


/**
 * This is a sheet that is used to plot mathematical functions including coordinate systems and optional extras like 
 * legends and descriptors. Additionally all conversions from image to plot coordinates are done here
 */
public class AdvancedPlotSheet extends PlotSheet implements Runnable{
  
  private ReentrantLock reentrantLock = new ReentrantLock();
  private boolean pictureIsConstructed = false;
  private BufferedImage plotImage = null;
  private boolean operationIsAborted = false;
  private Rectangle field;

  private boolean hasFirstPixelSkipSet = false;
  private float firstPixelSkip = 20;
  private ReliefDrawer reliefDrawer = null;
  

  /**
   * Create a virtual sheet used for the plot
   * @param xStart the start of the x-range
   * @param xEnd the end of the x-range
   * @param yStart the start of the y-range
   * @param yEnd the end of the y-range
   * @param drawables list of Drawables that shall be drawn onto the sheet
   */
  public AdvancedPlotSheet(double xStart, double xEnd, double yStart, double yEnd, Vector<Drawable> drawables) {
    super(xStart, xEnd, yStart, yEnd, drawables);
    double[] xRange = {xStart, xEnd};
    double[] yRange = {yStart, yEnd};
    screenParts.add(0, new MultiScreenPart(xRange, yRange, drawables));
  }
  
  /**
   * 
   * Create a virtual sheet used for the plot
   * @param xStart the start of the x-range
   * @param xEnd the end of the x-range
   * @param yStart the start of the y-range
   * @param yEnd the end of the y-range
   */
  public AdvancedPlotSheet(double xStart, double xEnd, double yStart, double yEnd, BufferedImage plotImage) {
    super(xStart, xEnd, yStart, yEnd);
    double[] xRange = {xStart, xEnd};
    double[] yRange = {yStart, yEnd};
    screenParts.add(0, new MultiScreenPart(xRange, yRange));
        this.plotImage = plotImage;
    
  }
  
  public void setClip(Rectangle field){
    this.field = field;
  }
  
  @Override
  public void run() {
        prepareRunnables();
    operationIsAborted = false;
    pictureIsConstructed = false;
    HashMap<Thread, DrawableDrawingRunnable> allDrawableDirectory = new HashMap<Thread, DrawableDrawingRunnable>();
    this.currentScreen = 0;
    
    Vector<DrawableDrawingRunnable> offFrameDrawables = new Vector<DrawableDrawingRunnable>();
    Vector<DrawableDrawingRunnable> onFrameDrawables = new Vector<DrawableDrawingRunnable>();
    //System.err.println("APlotSheet: field: " + field.width + " : " + field.height);
    BufferedImage bufferedFrameImage = new BufferedImage(field.width, field.height, BufferedImage.TYPE_INT_ARGB);
    Graphics2D gFrame = bufferedFrameImage.createGraphics();
    gFrame.setClip(field);
    gFrame.setColor(Color.BLACK);
    Thread[] threads = new Thread[this.screenParts.get(currentScreen).getDrawables().size()]; 
    int i = 0;
    
    if(this.screenParts.get(currentScreen).getDrawables() != null && this.screenParts.get(currentScreen).getDrawables().size() != 0) {
      for(Drawable draw : this.screenParts.get(currentScreen).getDrawables()) {
        DrawableDrawingRunnable drawableDrawingRunnable = new DrawableDrawingRunnable(draw, field);
        threads[i] = new Thread( drawableDrawingRunnable);
        allDrawableDirectory.put(threads[i],drawableDrawingRunnable );
        threads[i++].start();
        if(!draw.isOnFrame()) {
          offFrameDrawables.add(drawableDrawingRunnable);
        } else {
          onFrameDrawables.add(drawableDrawingRunnable);
        }
      }
    }
    
    //paint white frame to over paint everything that was drawn over the border 
    Color oldColor = gFrame.getColor();
    if(this.frameThickness>0){
      gFrame.setColor(Color.WHITE);
      //upper frame
      gFrame.fillRect(0, 0, field.width, this.frameThickness);

      //left frame
      gFrame.fillRect(0, this.frameThickness, this.frameThickness, field.height);
      
      //right frame
      gFrame.fillRect(field.width+1-this.frameThickness, this.frameThickness,this.frameThickness+2, field.height-this.frameThickness);
      
      //bottom frame
      gFrame.fillRect(this.frameThickness, field.height-this.frameThickness, field.width-this.frameThickness,this.frameThickness+1);
      
      //make small black border frame
      if(isBordered){
        gFrame.setColor(Color.black);
        //upper border
        gFrame.fillRect(this.frameThickness-borderThickness+1, this.frameThickness-borderThickness+1, field.width-2*this.frameThickness+2*borderThickness-2, borderThickness);
        
        //lower border
        gFrame.fillRect(this.frameThickness-borderThickness+1, field.height-this.frameThickness, field.width-2*this.frameThickness+2*borderThickness-2, borderThickness);
        
        //left border
        gFrame.fillRect(this.frameThickness-borderThickness+1, this.frameThickness-borderThickness+1, borderThickness, field.height-2*this.frameThickness+2*borderThickness-2);
        
        //right border
        gFrame.fillRect(field.width-this.frameThickness, this.frameThickness-borderThickness+1, borderThickness, field.height-2*this.frameThickness+2*borderThickness-2);
        
      }
      
      gFrame.setColor(oldColor);
      
//      Font oldFont = gFrame.getFont();
//      gFrame.setFont(oldFont.deriveFont(20.0f));
      FontMetrics fm = gFrame.getFontMetrics();
            float height = fm.getHeight();

            float width = fm.stringWidth(this.title);
      gFrame.drawString(this.title, field.width/2 -width/2, this.frameThickness - 10 - height);
//      gFrame.setFont(oldFont);
    }
    gFrame.dispose();
    
    boolean finished = true;
    do{
      //TODO give this abort message to all drawingRunnable for them to handle this event
      if(operationIsAborted){
        if(hasFirstPixelSkipSet){
          this.reliefDrawer.setPixelSkip(firstPixelSkip);
          this.reliefDrawer.abortAndReset();
        }
        for(Drawable draw : this.screenParts.get(currentScreen).getDrawables()) {
          draw.abortAndReset();
        }
        for(i=0; i<threads.length; i++ ){
          try {
            threads[i].join();
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }
        return;
      }
      
      finished = true;
      for(i=0; i<threads.length; i++ ){
        DrawableDrawingRunnable currentDrawableRunnable = allDrawableDirectory.get(threads[i]);
        if (currentDrawableRunnable.hasFinished() || currentDrawableRunnable.getIsCritical()) {
          if(!currentDrawableRunnable.hasJoined()){
            Drawable drawable = currentDrawableRunnable.getDrawable();
            if(drawable instanceof ReliefDrawer){
              reliefDrawer = (ReliefDrawer)drawable;
              if(!this.hasFirstPixelSkipSet){
                this.firstPixelSkip = reliefDrawer.getPixelSkip();
                hasFirstPixelSkipSet = true;
              }
              if(reliefDrawer.getPixelSkip() == 1){
                try {
                  threads[i].join();
                } catch (InterruptedException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
                }
                currentDrawableRunnable.hasJoined = true;
              } else {
                reliefDrawer.setPixelSkip(reliefDrawer.getPixelSkip() -1);
                try {
                  threads[i].join();
                } catch (InterruptedException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
                }
                BufferedImage oldReliefImage = currentDrawableRunnable.getBufferedDrawableImage();
                currentDrawableRunnable.setBufferedOldDrawableImage(oldReliefImage);
                threads[i] = new Thread(currentDrawableRunnable);
                threads[i].start();
                allDrawableDirectory.put(threads[i], currentDrawableRunnable);
                finished = false;
              }
              
            }else{
              try {
                threads[i].join();
              } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
              }
              currentDrawableRunnable.hasJoined = true;
            }
          }
          
        } else {
          finished = false;
        }
      }
      BufferedImage buffTempImage = new BufferedImage(field.width, field.height, BufferedImage.TYPE_INT_ARGB);
      Graphics2D g =  buffTempImage.createGraphics();
      g.setClip(field);
      
      for(DrawableDrawingRunnable offFrameDrawable : offFrameDrawables){
        if(offFrameDrawable.hasJoined)
          g.drawImage(offFrameDrawable.getBufferedDrawableImage(), null, 0, 0);
        else if(offFrameDrawable.getBufferedOldDrawableImage() != null)
          g.drawImage(offFrameDrawable.getBufferedOldDrawableImage(), null, 0, 0);
        
          
      }
      g.drawImage(bufferedFrameImage, null, 0, 0);
      for(DrawableDrawingRunnable onFrameDrawable : onFrameDrawables){
        if(onFrameDrawable.hasJoined)
          g.drawImage(onFrameDrawable.getBufferedDrawableImage(), null, 0, 0);
        else if(onFrameDrawable.getBufferedOldDrawableImage() != null)
          g.drawImage(onFrameDrawable.getBufferedOldDrawableImage(), null, 0, 0);
      }
      g.dispose();
      
      reentrantLock.lock();
      this.plotImage = buffTempImage;
      reentrantLock.unlock();
      
    }while(!finished);
    if(hasFirstPixelSkipSet){
      this.reliefDrawer.setPixelSkip(firstPixelSkip);
    }
    pictureIsConstructed = true;
    
  }

    private void prepareRunnables(){
        Vector<Drawable> drawables = this.screenParts.get(0).getDrawables();
        Vector<Drawable> onFrameDrawables = new Vector<Drawable>();
        Vector<Drawable> offFrameDrawables = new Vector<Drawable>();

        DrawableContainer onFrameContainer = new DrawableContainer(true, false);

        DrawableContainer offFrameContainer = new DrawableContainer(false, false);
        for(Drawable drawable : drawables){
            if(drawable.isOnFrame()){
                if(drawable.isClusterable()){
                    if(onFrameContainer.isCritical() == drawable.isCritical()){
                        onFrameContainer.addDrawable(drawable);
                    }else {
                        if(onFrameContainer.getSize() > 0) {
                            onFrameDrawables.add(onFrameContainer);
                        }
                        onFrameContainer = new DrawableContainer(true, drawable.isCritical());
                        onFrameContainer.addDrawable(drawable);
                    }
                }else{
                    if(onFrameContainer.getSize() > 0) {
                        onFrameDrawables.add(onFrameContainer);
                    }
                    onFrameDrawables.add(drawable);
                    onFrameContainer = new DrawableContainer(true, false);

                }
            }else{
                if(drawable.isClusterable()){
                    if(offFrameContainer.isCritical() == drawable.isCritical()){
                        offFrameContainer.addDrawable(drawable);
                    } else {
                        if(offFrameContainer.getSize() > 0){
                            offFrameDrawables.add(offFrameContainer);
                        }
                        offFrameContainer = new DrawableContainer(false, drawable.isCritical());
                        offFrameContainer.addDrawable(drawable);
                    }
                }else{
                    if(offFrameContainer.getSize() > 0){
                        offFrameDrawables.add(offFrameContainer);
                    }
                    offFrameDrawables.add(drawable);
                    offFrameContainer = new DrawableContainer(false, false);
                }
            }
        }
        if(onFrameContainer.getSize() > 0) {
            onFrameDrawables.add(onFrameContainer);
        }

        if(offFrameContainer.getSize() > 0){
            offFrameDrawables.add(offFrameContainer);
        }

        this.screenParts.get(0).getDrawables().removeAllElements();
        this.screenParts.get(0).getDrawables().addAll(offFrameDrawables);
        this.screenParts.get(0).getDrawables().addAll(onFrameDrawables);


    }


  public void abortOperation(){
    this.operationIsAborted = true;
  }
  
  /**
   * update the x-Range of this PlotSheet
   * @param xStart left beginning of plot
   * @param xEnd right end of plot
   */
    @Override
  public void updateX(double xStart, double xEnd) {
      double[] xRange = {xStart, xEnd};
        this.screenParts.get(0).setxRange(xRange);
    }
    
    /**
   * update the y-Range of this PlotSheet
   * @param yStart bottom beginning of plot
   * @param yEnd upper end of plot
   */
    @Override
  public void updateY(double yStart, double yEnd) {
      double[] yRange = {yStart, yEnd};
        this.screenParts.get(0).setyRange(yRange);
    }
  
  /**
   * add another Drawable object that shall be drawn onto the sheet
   * this adds only drawables for the first screen in multimode plots for
   * 
   * @param draw Drawable object which will be addet to plot sheet
   */
  @Override
  public void addDrawable(Drawable draw) {
    this.screenParts.get(0).addDrawable(draw);
  }
  



  


    @Override
    public boolean isClusterable() {
        return false;
    }


  public BufferedImage getPlotImage(){
    reentrantLock.lock();
    try{
      return plotImage;
    } finally {
      reentrantLock.unlock();
    }
  }
  
  public boolean isFinished(){
    return pictureIsConstructed;
  }
  
  private class DrawableDrawingRunnable implements Runnable {
    
    private Drawable drawable;
    private boolean hasFinished = false;
    private boolean hasJoined = false;
    
    private BufferedImage bufferedDrawableImage;
    private BufferedImage bufferedOldDrawableImage = null;
    private Rectangle field;

    public DrawableDrawingRunnable(Drawable drawable, Rectangle field) {
      super();
      this.drawable = drawable;
      this.field = field;
      
    }


    @Override
    public void run() {
        this.hasFinished = false;
      bufferedDrawableImage = new BufferedImage(field.width, field.height, BufferedImage.TYPE_INT_ARGB);
      Graphics2D g = bufferedDrawableImage.createGraphics();
      g.setClip(field);
      g.setColor(Color.BLACK);
      drawable.paint(g);
      g.dispose();
      this.hasFinished = true;
      
    }

    public Drawable getDrawable() {
      return drawable;
    }

    public boolean hasFinished(){
      return hasFinished;
    }
    public boolean hasJoined(){
      return hasJoined;
    }
    public BufferedImage getBufferedDrawableImage() {
      return bufferedDrawableImage;
    }


    public BufferedImage getBufferedOldDrawableImage() {
      return bufferedOldDrawableImage;
    }


    public void setBufferedOldDrawableImage(BufferedImage bufferedOldDrawableImage) {
      this.bufferedOldDrawableImage = bufferedOldDrawableImage;
    }

        public boolean getIsCritical(){
            return drawable.isCritical();
        }
    
    
  }

  
}




Java Source Code List

com.wildplot.android.ankistats.AnkiDb.java
com.wildplot.android.ankistats.AnkiStatsActivity.java
com.wildplot.android.ankistats.AnkiStatsApplication.java
com.wildplot.android.ankistats.AnswerButton.java
com.wildplot.android.ankistats.ApplicationTest.java
com.wildplot.android.ankistats.CardsTypes.java
com.wildplot.android.ankistats.CollectionData.java
com.wildplot.android.ankistats.Forecast.java
com.wildplot.android.ankistats.HourlyBreakdown.java
com.wildplot.android.ankistats.Intervals.java
com.wildplot.android.ankistats.ReviewCount.java
com.wildplot.android.ankistats.Utils.java
com.wildplot.android.ankistats.WeeklyBreakdown.java
com.wildplot.android.parsing.Atom.java
com.wildplot.android.parsing.ExpressionFormatException.java
com.wildplot.android.parsing.Expression.java
com.wildplot.android.parsing.Factor.java
com.wildplot.android.parsing.Pow.java
com.wildplot.android.parsing.Term.java
com.wildplot.android.parsing.TopLevelParser.java
com.wildplot.android.parsing.TreeElement.java
com.wildplot.android.parsing.AtomTypes.FunctionXAtom.java
com.wildplot.android.parsing.AtomTypes.FunctionXYAtom.java
com.wildplot.android.parsing.AtomTypes.MathFunctionAtom.java
com.wildplot.android.parsing.AtomTypes.NumberAtom.java
com.wildplot.android.parsing.AtomTypes.VariableAtom.java
com.wildplot.android.parsing.AtomTypes.XVariableAtom.java
com.wildplot.android.parsing.AtomTypes.YVariableAtom.java
com.wildplot.android.rendering.AdvancedPlotSheet.java
com.wildplot.android.rendering.BarGraph.java
com.wildplot.android.rendering.DrawableContainer.java
com.wildplot.android.rendering.FunctionDrawer.java
com.wildplot.android.rendering.FunctionDrawer_y.java
com.wildplot.android.rendering.Integral.java
com.wildplot.android.rendering.LegendDrawable.java
com.wildplot.android.rendering.LinesPoints.java
com.wildplot.android.rendering.Lines.java
com.wildplot.android.rendering.MultiScreenPart.java
com.wildplot.android.rendering.PieChart.java
com.wildplot.android.rendering.PlotSheet.java
com.wildplot.android.rendering.PointDrawer2D.java
com.wildplot.android.rendering.RelativeColorGradient.java
com.wildplot.android.rendering.ReliefDrawer.java
com.wildplot.android.rendering.XAxisBarGraph.java
com.wildplot.android.rendering.XAxisHistoGram.java
com.wildplot.android.rendering.XAxis.java
com.wildplot.android.rendering.XGrid.java
com.wildplot.android.rendering.YAxisBarGraph.java
com.wildplot.android.rendering.YAxisHistoGram.java
com.wildplot.android.rendering.YAxis.java
com.wildplot.android.rendering.YGrid.java
com.wildplot.android.rendering.graphics.wrapper.BasicStroke.java
com.wildplot.android.rendering.graphics.wrapper.BufferedImage.java
com.wildplot.android.rendering.graphics.wrapper.Color.java
com.wildplot.android.rendering.graphics.wrapper.FontMetrics.java
com.wildplot.android.rendering.graphics.wrapper.Graphics2D.java
com.wildplot.android.rendering.graphics.wrapper.Graphics.java
com.wildplot.android.rendering.graphics.wrapper.Rectangle.java
com.wildplot.android.rendering.graphics.wrapper.Stroke.java
com.wildplot.android.rendering.interfaces.Drawable.java
com.wildplot.android.rendering.interfaces.Function2D.java
com.wildplot.android.rendering.interfaces.Function3D.java
com.wildplot.android.rendering.interfaces.Legendable.java
com.wildplot.android.rendering.interfaces.StepFunction2D.java