Package ket.treeDiff

Source Code of ket.treeDiff.Painter

/*
* Copyright (C) 2011  Alasdair C. Hamilton
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>
*/

// TODO: Move this class to KetGUI or similar.
package ket.treeDiff;


import java.io.*;
import java.util.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.Graphics2D;

import ket.math.*;
import geom.Offset;
import geom.Position;
import java.awt.Color;
import ket.display.box.Box;
import ketUI.panel.KetPanel;
import ket.display.HTMLTools;
import ket.display.Transition;
import ket.display.ImageTools;
import ket.display.ColourScheme;
import ket.display.ColourSchemeDecorator;
import ketUI.Ket;


/**
* This paints the animated transition from one argument to another and saves
* each frame to file.  It is run as a separate thread as once created is
* independent of the rest of the Ket GUI's behaviour.
*/
public class Painter extends Thread {

  public static final int START_NUMBER = 5;
  public static final int TRANSITION_NUMBER = 15;
  public static final int END_NUMBER = 5;
  public static final int FRAME_NUMBER = START_NUMBER + TRANSITION_NUMBER + END_NUMBER;
  public static final int PAUSE_TIME = 10; // milliseconds

  static final int WIDTH = 800;
  static final int HEIGHT = 600;
  static final int FONT_SIZE = Box.DEFAULT_BOX_FONT_SIZE;
  static final ColourScheme COLOUR_SCHEME = ColourScheme.WHITEBOARD;


  int initialFrameNumber;
  TreeDiff treeDiff;
  String filename;

  BufferedImage image;
  Graphics2D g2D;


  public Painter(Argument before, Argument after, String filename, int initialFrameNumber) {
    Argument beforeClone = Argument.cloneArgument(before.getRoot());
    Argument afterClone = Argument.cloneArgument(after.getRoot());
    treeDiff = new TreeDiff(beforeClone, afterClone);
    this.filename = filename;
    this.initialFrameNumber = initialFrameNumber;
    image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
    g2D = (Graphics2D) image.getGraphics();
    setDaemon(false); // Don't exit until all animations finish.
  }

  /**
   * Differences between two arguments may be animated and saved to file.
   * To separate this process from the running of the GUI, this can be
   * run as a separate daemon process; it is run effectively as a
   * separate process, terminating once FRAME_NUMBER of frames has been
   * generated to demonstrate the animation.
   */
  @Override
  public void run() {
    try {
      paintAndSaveFrames();
      Ket.out.println("[done animating]");
    } catch (InterruptedException ie) {
      Ket.out.println(" !!! A thread responsible for saving frames was interupted !!! ");
    }
  }

  private Offset getWindowWithoutLabel(Box afterRootBox) {
    double minimumHeight = afterRootBox.getInnerRectangle().height;
    double shapeWidth = WIDTH - KetPanel.BORDER_OFFSET.width;
    return new Offset(shapeWidth, minimumHeight);
  }

  private void paintAndSaveFrames() throws InterruptedException {
    Box afterRootBox = treeDiff.getAfter().toBox(0L, COLOUR_SCHEME);
    afterRootBox.setupInnerRectangle(FONT_SIZE);
    Offset windowWithoutLabel = getWindowWithoutLabel(afterRootBox);
    Box beforeRootBox = getBeforeRootBox(windowWithoutLabel);
    afterRootBox.setupOuterRectangle(windowWithoutLabel);
    afterRootBox.calcRootOffset();
    int animationStart = initialFrameNumber + START_NUMBER;
    int animationEnd = animationStart + TRANSITION_NUMBER;
    Position topLeft = calcTopLeft(afterRootBox);
    Vector<Transition> transitions = treeDiff.getTransitions(beforeRootBox, afterRootBox); // Done once!
    for (int frame=initialFrameNumber; frame<animationEnd+END_NUMBER; frame++) {
      g2D.setColor(COLOUR_SCHEME.getBackgroundColour());
      g2D.fillRect(0, 0, WIDTH, HEIGHT);
      if (frame<animationStart) { // Draw the 'before' box.
        beforeRootBox.paintAt(g2D, topLeft, COLOUR_SCHEME);
      } else if (frame>=animationEnd) { // Draw the 'after' box.
        afterRootBox.paintAt(g2D, topLeft, COLOUR_SCHEME);
      } else { // Animate between 'before' and 'after' boxes.
        double fractionalTime = frame-animationStart;
        fractionalTime /= animationEnd - animationStart - 1.0;
        for (Transition t : transitions) {
          t.animate(g2D, COLOUR_SCHEME, fractionalTime, topLeft);
        }
      }
      ImageTools.saveImage(image, getImageName(frame));
      Thread.sleep(PAUSE_TIME);
    }
  }

  private Box getBeforeRootBox(Offset windowWithoutLabel) {
    Box beforeRootBox = treeDiff.getBefore().toBox(0L, COLOUR_SCHEME);
    beforeRootBox.setupInnerRectangle(FONT_SIZE);
    beforeRootBox.setupOuterRectangle(windowWithoutLabel);
    beforeRootBox.calcRootOffset();
    return beforeRootBox;
  }

  // Move this method and use it in chordEventHandler where you only save one image.
  private String getImageName(int frame) {
    String imageName = filename.replace("\\.png$", "");
    return String.format(imageName+"%05d.png", frame);
  }

  private Position calcTopLeft(Box afterRootBox) {
    double centre = (HEIGHT-KetPanel.BORDER_OFFSET.height) / 2.0;
    double heightAboveCentre = afterRootBox.getOuterRectangle().height / 2.0;
    double boxHeight = centre - heightAboveCentre;
    return new Position(KetPanel.LEFT_BORDER_SIZE, boxHeight);
  }

}
TOP

Related Classes of ket.treeDiff.Painter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.