Package ketUI.responder

Source Code of ketUI.responder.StringResponder

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

import java.util.*;

import ketUI.CommandListener;
import geom.Position;
import ket.MathCollection;
import ket.Message;
import ket.Selection;
import ket.display.box.Box;
import ket.display.box.BoxList;
import ket.display.box.BoxWord;
import ket.math.convert.ArgumentParser;
import ket.math.convert.Interpretation;
import ket.math.purpose.Text;
import ketUI.Clipboard;
import ketUI.Document;
import ketUI.DocumentManager;
import ketUI.Ket;
import ketUI.MouseButton;
import ketUI.MouseEventHandler;
import ketUI.chord.Chord;
import ketUI.chord.KeyboardEventHandler;
import ketUI.chord.Macros;
import ketUI.modes.DocumentState;
import ketUI.modes.Modes;
import ketUI.modes.Search;
import ketUI.panel.KetPanel;

import ket.math.*;

public class StringResponder extends Responder {

  final Modes modes;
  final MathCollection mathCollection;
 
  public StringResponder(Modes modes) {
    this.modes = modes;
    this.mathCollection = modes.getMathCollection();
  }

  private void mapInsert(String string, Clipboard clipboard, KnownArguments knownArguments) {
    Argument input = ArgumentParser.parseArgument(string, knownArguments, clipboard, mathCollection);
    Function function = knownArguments.toFunction(input.getPurpose());
    mapInsert(input, function, getCurrent().asBranch());
  }

  private void map2Insert(String string, Clipboard clipboard, KnownArguments knownArguments) {
    Argument input = ArgumentParser.parseArgument(string, knownArguments, clipboard, mathCollection);
    Function function = knownArguments.toFunction(input.getPurpose());
    Vector<Argument> children = getCurrent().asBranch().getChildren();
    for (Argument child : children) {
      //- setCurrent(child);
      if (child instanceof Branch) {
        mapInsert(input, function, child.asBranch());
      }
    }
  }

  private void mapInsert(Argument input, Function function, Branch target) {
    boolean append = modes.getDocumentState()==DocumentState.MAP_APPEND;
    boolean inputHasKids = input instanceof Branch && input.asBranch().size()>0;
    for (Argument child : target.getChildren()) {
      Branch intermediate = child.addIntermediaryParent(function);
      if (inputHasKids) {
        Branch clone = input.asBranch().cloneBranch();
        if (append) {
          intermediate.appendAll(clone.getChildren());
        } else {
          intermediate.prependAll(clone.getChildren());
        }
      }
    }
  }
 
  private String processNextReplaceChordIterationString(String string, Chord chord) {
    if (string.matches("\\s*")) {
      modes.error(" !!! Replace responder: cannot replace with a blank string !!! ");
      return null;
    }
    Clipboard clipboard = modes.getClipboard();
    KnownArguments knownArguments = mathCollection.getKnownArguments();
    switch(modes.getDocumentState()) {
      case WRITE_FUNCTION: // &sin
        {
        Argument next = ArgumentParser.parseArgument(string, knownArguments, clipboard, mathCollection);
        if (next==null) break//     <---
        Function function = knownArguments.toFunction(next.getPurpose());
        if (getCurrent().isBranch()) {
          getCurrent().asBranch().setFunction(function);
        } else {
          getSelection().replace(new Branch(function));
        }
        modes.getNormalMode().selectNextUnknown(false);
        chord.setComplete(false);
        modes.setDocumentState(DocumentState.WRITE_MODE);
        return null;
        }

      case WRITE_SYMBOL: // \alpha or ln
        {
        Argument next = ArgumentParser.parseArgument("\\"+string, knownArguments, clipboard, mathCollection);
        if (getCurrent().isBranch()) {
          Function function = knownArguments.toFunction(next.getPurpose());
          getCurrent().asBranch().setFunction(function);
        } else {
          getSelection().replace(next);
        }
        //+ Reverse direction of search/skip/all/done ....
        boolean found = modes.getNormalMode().selectNextUnknown(false);
        //< if (found) {
          System.out.println("[Found]");
          chord.setComplete(false);
          modes.setDocumentState(DocumentState.WRITE_MODE);
          return null;
          /*
        } else {
          System.out.println("[done]");
          chord.setComplete(true);
          modes.setDocumentState(DocumentState.NORMAL);
        }
        break;*/
        }

      case MAP2_PREPEND:
      case MAP2_APPEND:
        map2Insert(string, clipboard, knownArguments);
        break;

      case MAP_PREPEND:
      case MAP_APPEND:
        mapInsert(string, clipboard, knownArguments);
        break;

      // Replace current with a new purpose and if it is a branch then also add new siblings when given.
      case PREPEND_PURPOSE:
      case APPEND_PURPOSE:
        if (chord!=null) {
          chord.setComplete(true);
        }
        Argument input = ArgumentParser.parseArgument(string, knownArguments, clipboard, mathCollection);
        if (getCurrent() instanceof Token) {
          State state = knownArguments.toState(input.getPurpose());
          getCurrent().asToken().setState(state);
          break;
        }
        Function function = knownArguments.toFunction(input.getPurpose());
        Branch currentBranch = (Branch) getCurrent();
        currentBranch.setFunction(function);
        boolean append = modes.getDocumentState()==DocumentState.APPEND_PURPOSE;
        Branch inputBranch = input.asBranch();
        if (inputBranch==null || inputBranch.size()==0) {
          // Do nothing.
        } else if (append) {
          currentBranch.appendAll(inputBranch.getChildren());
        } else {
          currentBranch.prependAll(inputBranch.getChildren());
        }
        break;

      case UPDATE_PREFIX:
        Argument prefix = ArgumentParser.parsePrefix(string, knownArguments, clipboard, mathCollection);
        getSelection().replace(prefix);
        break;

      case UPDATE_REPLACE:
        Argument replacement = ArgumentParser.parseArgument(string, knownArguments, clipboard, mathCollection);
        if (replacement!=null) {
          getSelection().replace(replacement);
        }
        break;

      case CLJ_REPLACE:
        System.out.println(" --- stringResponder::CLJ_REPLACE --- ");
        Argument cljCode = ArgumentParser.parseClj(string, clipboard, mathCollection); // How is mathCollection used?
        if (cljCode!=null) {
          System.out.println("[code=" + cljCode);
          getSelection().replace(cljCode);
        }
        break;

      case UPDATE_SUBSTITUTE:
        Argument substitution = ArgumentParser.parseArgument(string, knownArguments, clipboard, mathCollection);
        if (substitution!=null) {
          getSelection().substitute(substitution);
        }
        break;
    }
    return string;
  }
 
  private String processNextChordIterationString(String string, Chord chord) {
    Document document = modes.getDocument();
    switch (modes.getDocumentState()) {
      case GET_LABEL_STRING:
        if (string.matches("\\s*")) {
          // An empty string removes the label.
          getCurrent().getEquation().setLabel(null);
          string = "";
          // A blank string means clear; a null string would imply failure.
        } else {
          getCurrent().getEquation().setLabel(string);
        }
        return string;

      case SIFT:
        if (string.matches("\\s*")) {
          modes.error(" !!! Cannot search for whitespace !!! ");
          return null;
        }
        modes.getSearch().search(string, Search.FORWARDS);
        // Restrict the view to those lines that matched the search.
        Vector<Equation> eqtns = modes.getSearch().getEquationMatches();
        if (eqtns!=null) {
          document.getKetPanel().setVisibleEquations(eqtns);
        }
        return string;

      case SEARCH_FORWARDS:
        if (string.matches("\\s*")) {
          modes.error(" !!! Cannot search for whitespace !!! ");
          return null;
        }
        modes.getSearch().search(string, Search.FORWARDS);
        return string;

      case SEARCH_BACKWARDS:
        if (string.matches("\\s*")) {
          modes.error(" !!! Cannot search for whitespace !!! ");
          return null;
        }
        modes.getSearch().search(string, Search.BACKWARDS);
        return string;

      case COMMAND:
        /*-
        // TODO: If on processing the command, the responder
        // changed, don't return to normal responder.
        modes.getCommandMode().processCommand(string, chord);
        // TODO: Only return the string if command responder worked as expected.
        return string;
        */
        //- Ket.out.println(" --- TEST: Normal command --- ");
        //- document.getKeyboardEventHandler().normal(string);
        CommandListener cl = document.getCommandListener();
        if (cl!=null) {
          cl.ketCommand(string);
        } else {
          Ket.out.println("[no command listener: '"+string+"']");
        }
        return string;

      case UPDATE_SUBSTITUTE:
      case UPDATE_REPLACE:
      case CLJ_REPLACE:
      case UPDATE_PREFIX:
      case PREPEND_PURPOSE:
      case APPEND_PURPOSE:
      case MAP_PREPEND:
      case MAP_APPEND:
      case MAP2_PREPEND:
      case MAP2_APPEND:
      case WRITE_SYMBOL:
      case WRITE_FUNCTION:
        return processNextReplaceChordIterationString(string, chord);

      default:
        throw new RuntimeException("Unreachable code.");
    }
  }

  private Argument getCurrent() {
    return getSelection().getCurrent();
  }

  private Selection getSelection() {
    // TODO: Store and call mathCollection directly?
    return modes.getSelection();
  }

  private void setCurrent(Argument argument) {
    modes.getSelection().setCurrent(argument);
  }
 
  private Message getMessage() {
    return modes.getMessage();
 
 
  @Override 
  public void prepareToRespond() {
    modes.getMessage().ensureEditingStarted();
  }

  @Override 
  public void cleanAfterRespond() {
    getMessage().cancelAndClear();
  }

  /**
   * Append the last ketUI.chord's key press to the current message and respond
   * appropriately to complete messages.
   */
  @Override 
  public void respondToChordEvent(Chord chord, Macros macros, KeyboardEventHandler keyboardEventHandler) {
    // TODO: Merge methods:
    Message message = getMessage();
    assert modes.getDocumentState()!=DocumentState.UPDATE_TEXT;
    chord.appendLastKeypressToMessage(message, false);
    if (message.isComplete()) {
      String messageString = message.getLine();
      String processedMessageString = processNextChordIterationString(messageString, chord);
      if (processedMessageString!=null) {
        chord.appendMessage(processedMessageString);
        //- System.out.println("#1" + chord.isComplete());
        //- System.out.println("#1" + modes.getDocumentState());
      } else if (modes.getDocumentState()==DocumentState.WRITE_MODE) { // Part of an editing loop [BUG: Strings are discarded].
        // Do nothing.
      } else {
        Ket.out.println(" !!! Null message string !!! ");
        chord.setError(true);
      }
    } else { // Message is in append mode.
      // Still in append mode: continue appending characters.
      chord.setComplete(false);
    }
  }

  private boolean messageBoxClick(boolean singleClick, Position p) {
    Document document = modes.getDocument();
    Message message = modes.getMessage();
    KetPanel ketPanel = document.getKetPanel();
    // box list: (BoxWord) start, (BoxWord) "|", (BoxWord) end
    BoxList messageBox = ketPanel.getMessageBoxList();
    if (messageBox==null) return false;
    Box clickedOn = messageBox.findDeepestBox(p);
    boolean messageBoxClick = clickedOn!=null;
    if (!messageBoxClick) return false;
    Vector<Box> children = messageBox.getChildren();
    if (children.size()!=3) return false;
    BoxWord startBoxWord = (BoxWord) children.get(0);
    BoxWord endBoxWord = (BoxWord) children.get(2);
    int index = -1;
    if (startBoxWord==clickedOn) {
      index = startBoxWord.getIndex(p)-1;
    } else if (endBoxWord==clickedOn) {
      // Including cursor index.
      int indent = message.getStart().length();
      index = indent + endBoxWord.getIndex(p) + 1;
    } else {
      return false;
    }
    if (index==-1) return false;
    message.setIndex(index);
    return true;
  }
 
  @Override 
  public void respondToMouseClick(MouseButton mouseButton, boolean singleClick, Position p) {
    boolean done = messageBoxClick(singleClick, p);
    if (done)
      return;

    switch (mouseButton) {
      case LEFT:
        if (singleClick) {
          // TODO: Refactor this as soon as possible.
          // TODO: Accept any text changes.
          // Think about this pivot carefully:
          Message message = modes.getMessage();
          String messageString = message.getLine();
          processNextChordIterationString(messageString, null);
          modes.setDocumentState(DocumentState.NORMAL);
        } else {
          //- mouseEventHandler.edit();
          modes.getNormalMode().editCurrentArgument();
        }
        return;
 
      case MIDDLE:
        return;
     
      case RIGHT:
        return;
       
      default:
        return;
    }
  }
 
  @Override
  public void respondToMouseDrag(MouseButton mouseButton, Position initial, Position release) {
    // Do nothing.
 
}
TOP

Related Classes of ketUI.responder.StringResponder

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.