Package ketUI

Source Code of ketUI.FrameManager

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



import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.FileDialog;
import java.awt.Graphics;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.TransferHandler;
import javax.swing.filechooser.FileNameExtensionFilter;


import ket.*;
import ket.display.HTMLTools;
import ket.display.ColourScheme;
import ket.display.ColourSchemeDecorator;
import ket.display.LatexTools;
import ket.display.box.Box;
import ket.math.*;
import ket.math.convert.ArgumentParser;
import ketUI.Clipboard;
import ketUI.chord.Chord;
import ketUI.chord.ChordEventHandler;
import ketUI.chord.KeyboardEventHandler;
import ketUI.modes.*;
import ketUI.panel.AnimatedDisplay;
import ketUI.panel.FocusRequestDaemon;
import ketUI.panel.FullScreenFocusListener;
import ketUI.panel.KetPanel;
import ketUI.panel.KetPanelFocusListener;
import ketUI.panel.KetFrame;

/**
* The top-level model of a collection of equations including associated
* graphical user interface components, methods to load and save documents as
* well as to initialize such documents.
*/
public class FrameManager implements Runnable {

  public static final int SCREEN_WIDTH = 600;
  public static final int SCREEN_HEIGHT = 600;

  final DocumentManager documentManager;
  final Document document;
  final JFrame frame;

  FullScreenFocusListener fullScreen;
  FullScreenFrame fullScreenFrame;
  boolean readOnly;

  String latexFilename;
  String clojureFilename;
  String htmlFilename;
  String filename;


  /**
   * There are three types of document sources: blank documents,
   * templates that are stored within the Ket.jar file and regular input
   * files that are stored elsewhere.  To distinguish blank documents,
   * pass in a null filename and to indicate a template, use *.template
   * while regular documents are *.txt.
   */
  public FrameManager(DocumentManager documentManager, Document document, JFrame existingFrame) {
    this.documentManager = documentManager;
    this.document = document;
    this.frame = existingFrame==null ? new KetFrame(documentManager, document) : existingFrame;
    fullScreenFrame = null;
    latexFilename = null;
    clojureFilename = null;
    htmlFilename = null;
  }

  public void invokeLater() {
    if (isStandAlone()) {
      SwingUtilities.invokeLater(this);
    }
  }

  public void run() {
    boolean hasFocus = getKetPanel().requestFocusInWindow();
    if (!hasFocus) {
      FocusRequestDaemon focusRequestDeamon = new FocusRequestDaemon(getKetPanel());
      focusRequestDeamon.start();
      getKetPanel().addFocusListener(new KetPanelFocusListener(focusRequestDeamon));
    }
    frame.setVisible(true);
    MenuEventHandler menuEventHandler = getMenuEventHandler();
    if (menuEventHandler!=null) {
      menuEventHandler.updateMultipleEquations();
    }
    getKetPanel().updateAndRepaint();
  }

  /*-
  public Document(DocumentManager documentManager, JFrame existingFrame, String filename, String label) {
    this(documentManager, existingFrame, filename);
    getCursor().selectEquation(label);
    int index = getCursor().getEquation().getEquationIndex();
    getKetPanel().fromMiddle(index);
  }

  public Document(DocumentManager documentManager, JFrame existingFrame, String filename, int equationIndex) {
    this(documentManager, existingFrame, filename);
    getCursor().selectEquation(equationIndex);
    int index = getCursor().getEquation().getEquationIndex();
    getKetPanel().fromMiddle(index);
  }
  */

  public boolean isStandAlone() {
    return frame instanceof KetFrame;
  }

  public KetFrame getKetFrame() {
    return isStandAlone() ? (KetFrame) frame : null ;
  }

  public void toggleSavingImages() {
    ChordEventHandler chordEventHandler = getKeyboardEventHandler().getChordEventHandler();
    if (chordEventHandler.imagesAreSaved()) {
      chordEventHandler.stopSavingImages();
    } else {
      startSavingImages();
    }
    MenuEventHandler menuEventHandler = getMenuEventHandler();
    if (menuEventHandler!=null) {
      menuEventHandler.saveImages(chordEventHandler.imagesAreSaved());
    }
  }

  public void startSavingImages() {
    // TODO: Also update the menuitem if not already done so. (Toggle save/stop).
    JFileChooser fileChooser = new JFileChooser(System.getProperty("user.home")); // TODO: If filename is non-null then use its path.
    fileChooser.setDialogTitle("Save future edits as images...");
    FileNameExtensionFilter filter = new FileNameExtensionFilter("Image files (*.png)", "png");
    fileChooser.setFileFilter(filter);
    int returnVal = fileChooser.showSaveDialog(frame);
    if(returnVal!=JFileChooser.APPROVE_OPTION) return;
    File file = fileChooser.getSelectedFile();
    if (file==null) return;
    String filename = file.getPath();
    ChordEventHandler chordEventHandler = getKeyboardEventHandler().getChordEventHandler();
    chordEventHandler.startSavingImages(filename);
    //!> chordEventHandler.stopSavingImages();
  }

  private void loadIfPossible(String filename) {
    boolean loadFile = filename!=null;
    if (loadFile) {
      loadFile = initialFileSetup(filename);
    }
    if ( ! loadFile ) {
      // Default to a blank document.
      blankDocumentSetup();
    }
  }

  /**
   * Load a specified filename.
   */
  private boolean initialFileSetup(String filename) {
    readOnly = false;
    // Load a file, returning if true and defaulting to a blank
    // document (below) if an error is encountered.
    boolean readSuccess = false;
    if (filename.matches(".+\\.template")) {
      // A template (i.e. within Ket.jar).
      readSuccess = getMathCollection().readJar(filename);
      if (readSuccess) {
        // Don't overwrite template files.
        readOnly = true;
      }
    } else {
      // A regular file (i.e. outside Ket.jar).
      File file = new File(filename);
      if (file.exists()) {
        readSuccess = getMathCollection().read(filename);
      }
    }
    if (readSuccess) {
      // View from the top of the equation.
      Argument visibleRoot = getEquationList().getFirstEquation().getVisibleRoot();
      getSelection().setOnly(visibleRoot);
      getKetPanel().fromTop(0);

      getKeyboardEventHandler().setToInitialState();
      getKetPanel().updateAndRepaint();
      setFilename(filename);
      return true;
    } else {
      return false;
    }
  }

  private void blankDocumentSetup() {
    Equation blankEquation = new Equation();
    Selection selection = getMathCollection().getSelection();
    EquationList el = selection.getEquationList();
    el.addLast(blankEquation);
    selection.setCurrent(blankEquation.getRoot());
    getMathCollection().getUndo().initHistory(el);
    getKeyboardEventHandler().setToInitialState();
    getKetPanel().updateAndRepaint();
    setFilename(null);
  }

  /**
   * Return the JFrame in which the document is displayed.
   */
  public JFrame getFrame() {
    return frame;
  }

  public ToolBarEventHandler getToolBarEventHandler() {
    return isStandAlone() ? getKetFrame().getToolBarEventHandler() : null;
  }

  public void setFilename(String filename) {
    this.filename = filename;
    updateFilename();
  }
 
  public void updateFilename() {
    if (!isStandAlone()) {
      return;
    }
    String title;
    if (filename==null) {
      title = "Unknown";
    } else {
      title = filename;
      if (containsUnsavedChanges()) {
        title += "*";
      }
    }
    if (readOnly) {
      title += " [read only]";
    }
    if (title.length()!=0) {
      title += " - ";
    }
    title += "Ket";
    frame.setTitle(title);
  }

  public boolean save(boolean saveAs) {
    if (saveAs || filename==null || filename.matches(".+\\.template")) {
      String text = saveAs ? "Save As" : "Save";
      JFileChooser fileChooser = new JFileChooser(System.getProperty("user.home"));
      fileChooser.setDialogTitle(text);
      FileNameExtensionFilter filter = new FileNameExtensionFilter("Plain text files (*.txt, *.ket)", "txt", "ket");
      fileChooser.setFileFilter(filter);
      int returnVal = fileChooser.showSaveDialog(frame); //! showSaveDialog | showOpenDialog
      if(returnVal!=JFileChooser.APPROVE_OPTION) return false;
      File file = fileChooser.getSelectedFile();
      if (file==null) return false;
      String path = file.getPath();
      setFilename(path);
    }
    if (filename==null) {
      Ket.out.println(" !!! No filename !!! ");
      return false;
    }
    boolean ok = getMathCollection().writeText(filename);
    updateFilename();
    if (ok) {
      return true;
    } else {
      Ket.out.println(" !!! Failed to save the file !!! ");
      return false;
    }
  }

  /**
   * Handle mouse wheel scroll events.
   */
  public void scrollDown() {
    if (getKetPanel().isListDisplayMode()) {
      getKetPanel().moveViewHalfPageDown();
    } else if (getKetPanel().isGridDisplayMode()) {
      getKetPanel().moveViewDown();
    } else {
      getCursor().selectDown();
    }
    getKetPanel().updateAndRepaint();
  }

  /**
   * Handle mouse wheel scroll events.
   */
  public void scrollUp() {
    if (getKetPanel().isListDisplayMode()) {
      getKetPanel().moveViewHalfPageUp();
    } else if (getKetPanel().isGridDisplayMode()) {
      getKetPanel().moveViewUp();
    } else {
      getCursor().selectUp();
    }
    getKetPanel().updateAndRepaint();
  }

  private GraphicsDevice getScreenDevice() {
    return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
  }

  public boolean isFullScreen() {
    return fullScreenFrame!=null;
  }

  class FullScreenFrame extends JFrame implements Runnable {
    FullScreenFocusListener listener;
    public FullScreenFrame(KetPanel ketPanel) {
      super();
      listener = new FullScreenFocusListener(FrameManager.this);
      addWindowListener(listener);
      addFocusListener(listener);
      setUndecorated(true);
      add(ketPanel);
      setResizable(false);
    }
    public void run() {
      getScreenDevice().setFullScreenWindow(fullScreenFrame);
      this.setVisible(true)
    }
  }

  public void enterFullScreen() {
    if (!isStandAlone()) {
      return;
    }
    fullScreenFrame = new FullScreenFrame(getKetPanel());
    frame.setVisible(false);
    SwingUtilities.invokeLater(fullScreenFrame);
  }

  public void exitFullScreen() {
    if (fullScreenFrame==null) return;
    //! Window window = getScreenDevice().getFullScreenWindow();
    //! where window==fullScreenFrame
    frame.setResizable(true);
    //- frame.setJMenuBar(getMenuBar());
    getKetFrame().refreshMenuBar();
    frame.add(getKetPanel());
    getScreenDevice().setFullScreenWindow(null);
    SwingUtilities.invokeLater(this);
    fullScreenFrame.dispose();
    int index = getCursor().getEquationIndex();
    getKetPanel().fromMiddle(index);
    fullScreenFrame = null;
    SwingUtilities.invokeLater(this);
  }

  public void toggleFullScreen() {
    if (isFullScreen()) {
      exitFullScreen();
    } else {
      enterFullScreen();
    }
  }

  /**
   * Check if the user wants to save the current equations before
   * proceeding.  True is returned if the user wants to proceed and false
   * if save failed or they selected cancel.
   */
  private boolean confirmDocumentCanBeChanged() {
    if (containsUnsavedChanges()) {
      String name = getFilename();

      int response = JOptionPane.showConfirmDialog(
          frame,
          "Save changes to '"+name+"'",
          "Unsaved changes",
          JOptionPane.YES_NO_CANCEL_OPTION,
          JOptionPane.QUESTION_MESSAGE);

      switch (response) {
        case JOptionPane.YES_OPTION:
          boolean ok = this.save(false);
          return ok;

        case JOptionPane.NO_OPTION:
          return true;

        case JOptionPane.CLOSED_OPTION:
        case JOptionPane.CANCEL_OPTION:
        default:
          return false;
      }
    } else {
      return true;
    }
  }

  /**
   * If required, display a dialog checking if the user wants to save
   * before closing then close this window and if no other windows exist
   * then close all of them.
   */
  public void confirmDispose() {
    if (confirmDocumentCanBeChanged() ) {
      this.dispose();
    }
  }

  /**
   * Clear the current equation list and replace it with a single,
   * unknown equation.
   */
  public void clear() {
    if ( isStandAlone() && confirmDocumentCanBeChanged() ) {
      getSelection().deleteAllEquations();
      readOnly = false;
      frame.setTitle(null);
      setFilename(null); //?
      getKetPanel().fromTop(0);
      getKeyboardEventHandler().setToInitialState();
      getModes().setDocumentState(DocumentState.UPDATE_REPLACE);
      getKetPanel().updateAndRepaint();
      updateFilename();
    }
  }

  public void setTitle(String title) { // This may be useful elsewhere.
    if (isStandAlone()) {
      frame.setTitle(title);
    }
  }

  /**
   * Dispose of this window and if there are no other windows then exit
   * the program.
   */
  public void dispose() {
    if (documentManager==null) return;
    int numberOfWindows = documentManager.getNumberOfWindows() - 1;
    documentManager.removeDocument(document);
    if (numberOfWindows>0) {
      frame.dispose();
    } else {
      System.exit(0);
    }
  }

  /**
   * Return either the filename of the current list or null otherwise.
   */
  public String getFilename() {
    return filename!=null ? filename : "Unknown";
  }

  /**
   * Return the filename if defined or null otherwise.
   */
  public String getRawFilename() {
    return filename;
  }

  /**
   * Check for any unsaved changes.
   */
  public boolean containsUnsavedChanges() {
    return getMathCollection().containsUnsavedChanges();
  }

  /**
   * If this equation list is changed then open in a new window and if
   * not then open here.
   */
  public void open() {
    String filename = openFileDialog();
    if (filename==null) {
      return;
    } else if (documentManager!=null && containsUnsavedChanges()) {
      Document additionalDocument = new Document(documentManager, null, filename);
      documentManager.addDocument(additionalDocument);
      updateFilename();
    } else {
      // Note: this block doesn't require a new document and hence a new document manager:
      int oldSize = getEquationList().size();
      boolean ok = getMathCollection().read(filename);
      if (!ok) {
        Ket.out.println(" !!! Reading failed !!! ");
        return;
      }
      int newSize = getEquationList().size();
      if (oldSize<newSize) {
        for (int i=0; i<oldSize; i++) {
          getEquationList().deleteEquation(0);
        }
      }
      getKeyboardEventHandler().setToInitialState();
      Argument root = getEquationList().getFirstEquation().getVisibleRoot();
      getSelection().setOnly(root);
      getKetPanel().fromTop(0);
      getKetPanel().updateAndRepaint();
      updateFilename();
    }
  }

  public KeyboardEventHandler getKeyboardEventHandler() {
    return document.getKeyboardEventHandler();
  }

  /**
   * Display the open-file dialog and return the filename or null if
   * cancelled.
   */
  public String openFileDialog() {
    JFileChooser fileChooser = new JFileChooser(System.getProperty("user.home"));
    fileChooser.setDialogTitle("Open");
    FileNameExtensionFilter filter = new FileNameExtensionFilter("Plain text files (*.txt, *.ket)", "txt", "ket");
    fileChooser.setFileFilter(filter);
    int returnVal = fileChooser.showOpenDialog(frame);
    if(returnVal!=JFileChooser.APPROVE_OPTION) return null;
    File file = fileChooser.getSelectedFile();
    if (file==null) return null;
    if (!file.exists()) return null;
    return file.getPath();
  }

  public void exportToHTML() {
    /*-
    FileDialog fileDialog = new FileDialog(frame, "Export to HTML (*.html)", FileDialog.SAVE);
    if (htmlFilename!=null) {
      fileDialog.setFile(htmlFilename);
    }
    fileDialog.setVisible(true);
    String filename = fileDialog.getDirectory() + fileDialog.getFile();
    if (fileDialog.getFile()==null) {
      return;
    }
    */
    JFileChooser fileChooser = new JFileChooser(htmlFilename!=null?htmlFilename:System.getProperty("user.home"));
    fileChooser.setDialogTitle("Export to HTML (*.html)");
    FileNameExtensionFilter filter = new FileNameExtensionFilter("Web pages (*.html, *.htm)", "html", "htm");
    fileChooser.setFileFilter(filter);
    int returnVal = fileChooser.showSaveDialog(frame);
    if(returnVal!=JFileChooser.APPROVE_OPTION) return;
    File file = fileChooser.getSelectedFile();
    if (file==null) return;
    htmlFilename = file.getPath();
    boolean ok = getMathCollection().writeHTML(htmlFilename);
    if (!ok) return;
    HTMLTools.openURI(htmlFilename);
  }

  public void exportToLatex() {
    JFileChooser fileChooser = new JFileChooser(latexFilename!=null?latexFilename:System.getProperty("user.home"));
    fileChooser.setDialogTitle("Export to LaTeX (*.tex)");
    FileNameExtensionFilter filter = new FileNameExtensionFilter("Export to Latex (*.tex)", "tex");
    fileChooser.setFileFilter(filter);
    int returnVal = fileChooser.showSaveDialog(frame);
    if(returnVal!=JFileChooser.APPROVE_OPTION) return;
    File file = fileChooser.getSelectedFile();
    if (file==null) return;
    latexFilename = file.getPath();
    LatexTools.convertToPDF(latexFilename, getModes());
  }

  public void exportToClojure() {
    JFileChooser fileChooser = new JFileChooser(clojureFilename!=null?clojureFilename:System.getProperty("user.home"));
    fileChooser.setDialogTitle("Export to Clojure (*.clj)");
    FileNameExtensionFilter filter = new FileNameExtensionFilter("Clojure program source file (*.clj)", "clj");
    fileChooser.setFileFilter(filter);
    int returnVal = fileChooser.showSaveDialog(frame);
    if(returnVal!=JFileChooser.APPROVE_OPTION) return;
    File file = fileChooser.getSelectedFile();
    if (file==null) return;
    clojureFilename = file.getPath();
    getMathCollection().writeClojure(clojureFilename);
  }

  public void displayAboutMessage() {
    String text = "<H1><FONT color=\"RED\">KET</FONT></H1><BR>";
    text += "<FONT color=\"BLUE\">";
    text += "version "+Ket.VERSION+"<BR>";
    text += "by Alasdair C. Hamilton<BR>";
    text += "Ket is open source and freely distributable";
    text += "</FONT>";
    String html = "<HTML> <BODY> <CENTER> "+text+" <CENTER> </BODY> </HTML>";
    JOptionPane.showMessageDialog(frame, html, "About", JOptionPane.PLAIN_MESSAGE);
    getKeyboardEventHandler().setToInitialState();
  }


  ////////////////////
  // HELPER METHODS //
  ////////////////////

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

  public Cursor getCursor() {
    return getSelection().getCursor();
  }

  public EquationList getEquationList() {
    return getSelection().getEquationList();
  }

  public Selection getSelection() {
    return getMathCollection().getSelection();
  }

  public MathCollection getMathCollection() {
    return document.getMathCollection();
  }

  public KetPanel getKetPanel() {
    return document.getKetPanel();
  }

  public DocumentManager getDocumentManager() {
    return documentManager;
 

  public String toString() { // Not used.
    String string = "<Document filename='"+filename+"'>\n";
    string += getMathCollection().toString();
    string += "</Document>\n";
    return string;
  }

  public MenuEventHandler getMenuEventHandler() {
    return isStandAlone() ? getKetFrame().getMenuEventHandler() : null;
  }

  public static int WINDOW_SIZE = 10;
  public void resize(int dx, int dy) {
    int x = frame.getWidth() + WINDOW_SIZE*dx;
    int y = frame.getHeight() + WINDOW_SIZE*dy;
    Point p = frame.getLocation();
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    x = bound(x, 0, screenSize.width-p.x);
    y = bound(y, 0, screenSize.height-p.y);
    frame.setSize(x, y);
  }
  public void shift(int dx, int dy) {
    Point p = frame.getLocation();
    int x = p.x + WINDOW_SIZE*dx;
    int y = p.y + WINDOW_SIZE*dy;
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    x = bound(x, 0, screenSize.width - frame.getWidth());
    y = bound(y, 0, screenSize.height - frame.getHeight());
    frame.setLocation(x, y);
  }
  private int bound(int x, int xMin, int xMax) {
    if (x<xMin) return xMin;
    if (x>xMax) return xMax;
    return x;
  }
}
TOP

Related Classes of ketUI.FrameManager

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.