Package ketUI.chord

Source Code of ketUI.chord.ChordEventHandler

/*
* 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/>
*/

package ketUI.chord;

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

import ket.*; //?
import ket.display.*;
import ket.display.box.Box;
import ket.treeDiff.TreeDiff;
import ket.treeDiff.Painter;
import ket.math.*;
import ketUI.*;
import ketUI.modes.Modes;
import ketUI.panel.AnimatedDisplay;
import ketUI.panel.KetPanel;
import ketUI.responder.*;


/**
* After a keypress is handled by KeyboardEventHandler, it is assembled into a
* ketUI.chord which is either processed here or delegated to a more specialised
* class.
*/
public class ChordEventHandler {

  private static boolean ANIMATE_SAVED_IMAGES = true;

  final Document document;
  final MathCollection mathCollection;
  final KeyboardEventHandler keyboardEventHandler;
 
  /**
   * Unique log file name to for program profiling.
   */
  String uniqueName;
  String imageName;
  int imageNumber;

  public ChordEventHandler(Document document, KeyboardEventHandler keyboardEventHandler) {
    this.document = document;
    this.mathCollection = getModes().getMathCollection();
    this.keyboardEventHandler = keyboardEventHandler;
    imageName = null;
    imageNumber = 0;
  }

  /**
   * Images can be recorded as the user words, and these are saved to the
   * given filename (a png file).
   */
  public void startSavingImages(String imageName) {
    this.imageName = imageName;
  }

  public boolean imagesAreSaved() {
    return this.imageName != null;
  }

  /**
   * This stops saving images of the equations that are currently being
   * modified.
   */
  public void stopSavingImages() {
    this.imageName = null;
  }

  /**
   * This method processes a given ketUI.chord.  If the ketUI.chord contains an
   * error, or is incomplete, the method returns with the cord in the
   * appropriate state.  However, if the ketUI.chord is correctly executed then
   * it be run 'count' times when a count has been specified (within
   * ketUI.chord).
   */
  public void processChord(Chord chord, Macros macros) {
    int counts = chord.getCounts();
    for (int count=0; count<counts; count++) {
      Responder responder = getModes().getResponder();
      responder.respondToChordEvent(chord, macros, keyboardEventHandler);
      //- Ket.out.println("C: current' = " + mathCollection.getCursor().getCurrent()); // CURRENT -> '' HAPPENS BEFORE HERE
      if (chord.isError()) {
        keyboardEventHandler.error();
        return;
      } else if (!chord.isComplete()){
        // Wait for the rest of the chord to be typed.
        updateForAnimatedDisplay();
        return;
      }
      if (chord.isLoopSkipped()) {
        // Count is handled within responder.
        break;
      }
    }
    chordSuccess(chord, macros);
    mathCollection.updateUndoStack();
    keyboardEventHandler.awaitNewChord();
  }

  private void chordSuccess(Chord chord, Macros macros) {
    logToFile(chord);
    macros.appendIfRecording(chord);
    // TODO: Change explicity boolean to subBranchEquals comparison with undo (this is already done, but not in its own public method).
    // TODO: Add a suppress change flag within chord for undo, 'u'; redo, 'r'; macro record and play, 'q' and '@'.
    // TODO: Remove the return type of all responders etc.
    //- Ket.out.println(" *** up to date undo stack?"+mathCollection.undoStackIsUpToDate()+" *** ");

    // Note: Undo and redo will always result in an up-to-date undo
    // stack and hence will not be recorded here.  Consider this
    // further as recording undos is different to animating or
    // saving undo steps.
    boolean upToDate = mathCollection.undoStackIsUpToDate();
    if (upToDate) {
      keyboardEventHandler.awaitNewChord();
      return;
    }
    updateForAnimatedDisplay(); // TODO: This should also be updated for undos and redos.
    keyboardEventHandler.updateOldChord(); // How does undo affect this?
    mathCollection.setCursorSelection();
    if (imageName==null) {
      return;
    }
    if (ANIMATE_SAVED_IMAGES) { // TODO: This should also be updated for undos and redos.
      // Animate
      // TODO: Split into separate classes: diff algorithm and image daemon.
      Address oldCursor = mathCollection.getUndo().getAddress();
      Ket.out.println("old cursor = " + oldCursor);
      Argument before = mathCollection.getUndo().getLastRoot();
      Argument after = mathCollection.getCursor().getCurrent();
      if (before!=null) {
        Painter painter = new Painter(before, after, imageName, imageNumber);
        imageNumber += Painter.FRAME_NUMBER;
        painter.start();
      }
    } else {
      // Save a single frame.
      Equation currentEquation = mathCollection.getCursor().getEquation();
      saveAsImage(currentEquation);
    }
  }

  private void updateForAnimatedDisplay() {
    KetPanel ketPanel = document.getKetPanel();
    ketPanel.updateForAnimatedDisplay();
  }

  private void saveAsImage(Equation currentEquation) {
    ColourScheme colourScheme = ColourScheme.WHITEBOARD; // TODO: Generalize.
    Box currentBox = currentEquation.toBox(colourScheme);
    BufferedImage image = ImageTools.boxToBufferedImage(currentBox, 800, 600, colourScheme);
    // If image name already ends with ".png", remove it.
    imageName = imageName.replace("\\.png$", "");
    String name = String.format(imageName+"%d.png", imageNumber++);
    Ket.out.println("Writing frame to '" + name + "'");
    try {
      ImageIO.write(image, "png", new File(name));
    } catch (IOException ioe) {
      Ket.out.println(" !!! Can't save current screen !!! ");
      Ket.out.println(ioe);
      Ket.out.println();
      Ket.out.println("[Stopping recording any more images to avoid possible cascading failures]");
      stopSavingImages();
    }
  }

  /**
   * This is a development tool, used to profile relative frequencies of
   * commands by saving chords to a unique file (in the data folder).
   */
  public void logToFile(Chord chord) {
    // Log the ketUI.chord
    if (Ket.KEY_LOGGING_ENABLED) {
      boolean append;
      if (uniqueName==null) {
        String randomString = "" + Math.random();
        uniqueName = "keys" + randomString.substring(2) + ".log";
        Ket.out.printf("unique name = '%s'\n", uniqueName);
        append = false;
      } else {
        append = true;
      }
      if (uniqueName!=null) {
        try {
          FileWriter fileWriter = new FileWriter(uniqueName, append);
          BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
          bufferedWriter.write(chord.getSummary() + "\n");
          bufferedWriter.close();
        } catch (IOException e) {
          Ket.out.println("exception = \n" + e);
          // Do nothing.
        }
      }
    }
  }

  private Modes getModes() {
    return document.getModes();
  }

}
TOP

Related Classes of ketUI.chord.ChordEventHandler

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.