Package view

Source Code of view.SchemeWindow$SchemeEditor$DanglingHighLighter

package view;

//----- JDK Imports ------------------------------------------------------------
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Vector;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JInternalFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;

//----- Phoenix Imports --------------------------------------------------------
import controller.PhoenixController;
import controller.SchemeController;

/**
* Video Phoenix
* Version 0.2.0
* Copyright (c) 2007 Lunderskov, Ian; Pan, Jiabei; Rebelsky, Samuel;
* Whisenhunt, Heather; Young, Ian; Zuleta Benavides, Luis.
* All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* This window provides a scripting-based interaction platform between the user
* and Phoenix.
*
* @author  Lunderskov, Ian; Pan, Jiabei; Rebelsky, Samuel; Whisenhunt, Heather;
*          Young, Ian; Zuleta Benavides, Luis
* @author  Glimmer Labs 2006-2007
* @version 0.2.0
*/

@SuppressWarnings("serial")
public class SchemeWindow extends JInternalFrame implements KeyListener,
  ActionListener, InternalFrameListener
{
  /*--------*-------------------------------------------------------------------
   * Fields *
   *--------*/

  // flags indicating whether the input and output area are maximized
  Boolean upMax = false;
  Boolean downMax = false;

  // SchemeController for this SchemeWindow
  public SchemeController controller;

  // main display window
  public PhoenixWindow view;

  // saved input
  public static String savedInput = "";

  // vector to store calls and an index
  Vector<String> calls;
  int index;

  // current location in calls
  int current;

  // outputArea's styled document object
  public StyledDocument doc;

  // input and output areas - scrollpanes in editor/text panes
  JSplitPane textSplitPane;
  JScrollPane inputAreaPane;
  public SchemeEditor inputArea;
  public JMenuedTextPane outputArea;
  public JScrollPane outputAreaPane;

  // buttons for controlling the window
  JPanel buttons;
  JButton prevButton;
  JButton nextButton;
  JButton helpButton;
  public JButton runButton;
  public JButton killButton;

  // whether Escape is currently depressed
  // for recognizing esc+p "previous" and esc+n "next" in editor pane
  Boolean flagEsc = false;

  // icons
  ImageIcon runIcon =
    new ImageIcon(PhoenixController.getImage("play.gif"));
  ImageIcon nextIcon =
    new ImageIcon(PhoenixController.getImage("next.gif"));
  ImageIcon prevIcon =
    new ImageIcon(PhoenixController.getImage("prev.gif"));


  /*--------------*-------------------------------------------------------------
   * Constructors *
   *--------------*/

  /**
   * Construct a SchemeWindow of default size
   *
   * @param controller  SchemeController for this SchemeWindow
   */
  public SchemeWindow(SchemeController controller)
  {
    // set resizable, closable, maximizable, iconifiable
    super("Interaction Window", true, true, true, true);
    this.controller = controller;
    this.view = controller.phoenix.view;
    setLayout(new BorderLayout());

    // set close operation
    this.setDefaultCloseOperation(JInternalFrame.HIDE_ON_CLOSE);

    // set up fields in a split pane
    this.inputArea = new SchemeEditor();
    this.inputArea.addKeyListener(this);
    this.inputAreaPane = new JScrollPane(this.inputArea);
    this.inputArea.requestFocusInWindow();
    this.inputAreaPane.setHorizontalScrollBarPolicy(
      ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    this.inputAreaPane.setVerticalScrollBarPolicy(
      ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
    this.outputArea = new JMenuedTextPane();
    this.outputArea.setEditable(false);

    // style initializations
    this.doc = this.outputArea.getStyledDocument();
    this.outputPaneStyles(this.doc);

    // set up control buttons
    this.buttons = new JPanel();
    this.buttons.setLayout(new GridBagLayout());
    GridBagConstraints cons = new GridBagConstraints();
    this.runButton = new JButton(runIcon);
    this.runButton.addActionListener(this);
    this.runButton.setToolTipText("Execute Commands");
    this.prevButton = new JButton(prevIcon);
    this.prevButton.addActionListener(this);
    this.prevButton.setToolTipText("Go to Previous Command");
    this.nextButton = new JButton(nextIcon);
    this.nextButton.addActionListener(this);
    this.nextButton.setToolTipText("Go to Next Command");
    this.helpButton = new JButton(new ImageIcon(PhoenixController.getImage(
      "help.gif")));
    this.helpButton.setToolTipText("Help");
    this.helpButton.addActionListener(this);
    this.killButton = new JButton(new ImageIcon(PhoenixController.getImage(
      "kill.gif")));
    this.killButton.setToolTipText("Terminate Current Command");
    this.killButton.addActionListener(this);
    this.killButton.setEnabled(false);
    cons.fill = GridBagConstraints.HORIZONTAL;
    cons.gridheight = 1;
    cons.gridwidth = 8;
    cons.gridx = 0;
    cons.gridy = 0;
    this.buttons.add(this.prevButton, cons);
    cons.gridx = 0;
    cons.gridy = 1;
    this.buttons.add(this.runButton, cons);
    cons.gridx = 0;
    cons.gridy = 2;
    this.buttons.add(this.nextButton, cons);
    cons.gridx = 0;
    cons.gridy = 3;
    this.buttons.add(this.killButton, cons);

    cons.gridx = 0;
    cons.gridy = 8;
    this.buttons.add(this.helpButton, cons);

    this.outputAreaPane = new JScrollPane(this.outputArea);
    this.outputAreaPane.setHorizontalScrollBarPolicy(
      ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    this.outputAreaPane.setVerticalScrollBarPolicy(
      ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);

    JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());
    panel.add(this.inputAreaPane, BorderLayout.CENTER);
    panel.add(this.buttons, BorderLayout.EAST);
    this.add(panel, BorderLayout.SOUTH);

    this.textSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
      this.outputAreaPane, panel);
    this.textSplitPane.setResizeWeight(1);
    this.add(this.textSplitPane, BorderLayout.CENTER);

    // size the window
    this.setBounds(200, 0, 450, 400);
    this.setVisible(true);

    // initialize index to a value indicating no calls
    // and calls to a value indicating no history
    this.index = 0;
    this.current = 0;
    this.calls = new Vector<String>();
    this.calls.setSize(50);

    this.runButton.addKeyListener(this);
    this.prevButton.addKeyListener(this);
    this.nextButton.addKeyListener(this);
    this.killButton.addKeyListener(this);
    this.helpButton.addKeyListener(this);
    this.outputArea.addKeyListener(this);
    this.view.add(this);
  } // SchemeWindow(MainFrame)


  /*---------*------------------------------------------------------------------
   * Methods *
   *---------*/

  /**
   * Get the SchemeController for this SchemeWindow
   *
   * @return controller  SchemeController for this SchemeWindow
   */
  public SchemeController getController()
  {
    return this.controller;
  } // getController()

  /**
   * Set the text of the output area, erasing previous contents
   *
   * @param str  String to be displayed
   */
  public void setOutputText(String str)
  {
    this.outputArea.setText(str);
  } // setOutputText(String)

  /**
   * Get the text of the output area
   *
   * @return output  Text of the output area
   */
  public String getOutputText()
  {
    return this.outputArea.getText();
  } // getOutputText()

  /**
   * Set the text of the input area, erasing previous contents
   *
   * @param str  String to be displayed
   */
  public void setInputText(String str)
  {
    this.inputArea.setText(str);
  } // setInputText(String)

  /**
   * Get the text of the input area
   *
   * @return input  Text of the input area
   */
  public String getInputText()
  {
    return this.inputArea.getText();
  } // getInputText()

  /**
   * Get a style by name
   *
   * @param name    Name of the style
   * @return style  Style associated with name
   */
  public Style getStyle(String name)
  {
    return this.doc.getStyle(name);
  } // getStyle(String)

  /**
   * Set a style
   *
   * @param name   Name of the style
   * @param style  Style
   */
  public void setStyle(String name, Style style)
  {
    this.doc.addStyle(name, style);
  } // setStyle(String, Style)

  /**
   * Available styles for the output pane
   *
   * @param doc  StyledDocument for which styles are available
   */
  public void outputPaneStyles(StyledDocument doc)
  {
    StyleContext sctx = new StyleContext();
    Style def = sctx.getStyle(StyleContext.DEFAULT_STYLE);

    // Our basic style
    Style regular = doc.addStyle("regular", def);
    StyleConstants.setFontFamily(regular, "Arial");
    StyleConstants.setFontSize(regular, 12);

    // Style for input echoed in the window
    doc.addStyle("input", regular);

    // Style for output
    doc.addStyle("output", regular);
    StyleConstants.setBold(doc.getStyle("output"), true);

    // Style for scheme error
    doc.addStyle("scheme_error", regular);
    StyleConstants.setItalic(doc.getStyle("scheme_error"), true);
    StyleConstants.setForeground(doc.getStyle("scheme_error"),
      new java.awt.Color(255, 0, 0));
  } // outputPaneStyles(StyledDocument)

  /**
   * Interpret the Scheme expression in input area
   */
  public void schemeCall()
  {
    // remove the trailing blank space
    String input = this.getInputText().trim();
    if (input.length() == 0)
    {
      return;
    } // if (input.length() == 0)

    // update the Vector of previous Scheme calls
    this.updateCalls(input);

    // This is the line that may throw an exception
    SchemeController.schemeCall(SchemeWindow.savedInput + "\n" + input, true);
    this.controller.printStyledText("\n" + input + "\n", "input");
    this.setInputText("");
    SchemeWindow.savedInput = "";
  } // schemeCall()

  /**
   * Update history
   *
   * @param call  Call to be entered into history
   */
  public void updateCalls(String call)
  {
    this.index++;
    this.current = this.index;
    if (this.index == 50)
    {
      this.index = 0;
    } // if (this.index == 50)
    call = call.substring(0, call.length());
    this.calls.setElementAt(call, this.index);
  } // updateCalls(String)

  /**
   * Handle key presses
   *
   * @param event  Key pressed event
   */
  public void keyPressed(KeyEvent event)
  {
    // if escape key is being pressed
    if (event.getKeyCode() == KeyEvent.VK_ESCAPE)
    {
      // set flag for use with esc+p and esc+n commands
      this.flagEsc = true;

      // prevent keystroke from being processed by other listeners
      event.consume();
    } // if (event.getKeyCode() == KeyEvent.VK_ESCAPE)

    // if keystroke is shift+enter
    else if (event.isShiftDown() && event.getKeyCode() == KeyEvent.VK_ENTER
      && runButton.isEnabled())
    {
      // run - process input from input window
      schemeCall();
    } // else if (event.isShiftDown() && event.getKeyCode() == ...

    // if keystroke is page-up or esc+p
    else if ((event.getKeyCode() == KeyEvent.VK_PAGE_UP)
      || ((event.getKeyCode() == KeyEvent.VK_P) && this.flagEsc))
    {
      // previous - show previous command stored in history
      this.setInputText(this.calls.get(this.current));
      if (this.current == 1)
      {
        this.current = 1;
      } // if (this.current == 1)
      else if (this.current > 1)
      {
        this.current--;
      // else if (this.current > 1)
    } // else if ((event.getKeyCode() == KeyEvent.VK_PAGE_UP) ...

    // if keystroke is page-down or esc+n
    else if ((event.getKeyCode() == KeyEvent.VK_PAGE_DOWN)
      || ((event.getKeyCode() == KeyEvent.VK_N) && this.flagEsc))
    {
      // next - show next command stored in history
      if (this.current < this.index)
      {
        this.current++;
      } // else if (this.current < index)
      this.setInputText(this.calls.get(this.current));     
    } // else if ((event.getKeyCode() == KeyEvent.VK_PAGE_DOWN) ...

    else if (event.isControlDown() && event.getKeyCode() == KeyEvent.VK_D)
    {
      if (this.downMax)
      {
        this.textSplitPane.setDividerLocation(0.64f);
        this.downMax = false;
        this.upMax = false;
      } // if (this.downMax)
      else
      {
        this.textSplitPane.setDividerLocation(0f);
        this.downMax = true;
        this.upMax = false;
      } // else
    } // else if (event.isControlDown() && event.getKeyCode() == ...

    else if (event.isControlDown() && event.getKeyCode() == KeyEvent.VK_E)
    {
      if (this.upMax)
      {
        this.textSplitPane.setDividerLocation(0.64f);
        this.upMax = false;
        this.downMax = false;
      } // if (this.upMax)
      else
      {
        this.textSplitPane.setDividerLocation(1f);
        this.upMax = true;
        this.downMax = false;
      } // else
    } // else if (event.isControlDown() && event.getKeyCode() == ...
  } // keyPressed(KeyEvent)

  /**
   * Handle keys typed
   *
   * @param event  Key type event
   */
  public void keyTyped(KeyEvent event)
  {
    if (this.flagEsc)
    {
      // prevent keystroke from being processed by other listeners
      event.consume();
    } // if (this.flagEsc)
  } // keyTyped(KeyEvent)

  /**
   * Handle key releases
   *
   * @param event  Key release event
   */
  public void keyReleased(KeyEvent event)
  {
    if (this.flagEsc)
    {
      // prevent keystroke from being processed by other listeners
      event.consume();
    } // if (this.flagEsc)

    // if escape key is being released
    if (event.getKeyCode() == KeyEvent.VK_ESCAPE)
    {
      // reset flag to false
      this.flagEsc = false;
    } // if (event.getKeyCode() == KeyEvent.VK_ESCAPE)
  } // keyReleased(KeyEvent)

  /**
   * Handle mouse actions
   *
   * @param event  Action event
   */
  public void actionPerformed(ActionEvent event)
  {
    // if action came from the run button
    if ((JButton) event.getSource() == this.runButton)
    {
      // run
      this.schemeCall();
    } // if ((JButton) event.getSource() == this.runButton)

    // if action came from the previous button
    else if ((JButton) event.getSource() == this.prevButton)
    {

      // display previous command in history
      this.setInputText(this.calls.get(this.current));
      if (this.current > 1)
      {
        this.current--;
      // if (this.current > 1)
    } // else if ((JButton) event.getSource() == this.prevButton)

    // if action came from the next button
    else if ((JButton) event.getSource() == this.nextButton)
    {
      // display next command in history
      if (this.current < this.index)
      {
        this.current++;
      } // else if (this.current < index)
      this.setInputText(this.calls.get(this.current));
    } // else if ((JButton) event.getSource() == this.nextButton)

    // if action came from the help button
    else if ((JButton) event.getSource() == this.helpButton)
    {
      // show help
      PhoenixWindow.getController().showHelp();
    } // else if ((JButton) event.getSource() == this.helpButton)

    // if action came from the kill button
    else if ((JButton) event.getSource() == this.killButton)
    {
      // interrupt the command interpreter's thread
      SchemeController.cmdListener.interrupt();
    } // else if ((JButton) event.getSource() == this.killButton)
  } // mouseClicked(MouseEvent)

  /**
   * Handle internal frame activated
   *
   * @param event  Internal frame activated event
   */
  public void internalFrameActivated(InternalFrameEvent event)
  {
    this.moveToFront();
  } // internalFrameActivated(InternalFrameEvent)

  /**
   * Handle internal frame opened
   *
   * @param event  Internal frame opened event
   */
  public void internalFrameOpened(InternalFrameEvent event)
  {
    this.moveToFront();
  } // internalFrameOpened(InternalFrameEvent)

  /**
   * Handle internal frame closed
   *
   * @param event  Internal frame closed event
   */
  public void internalFrameClosed(InternalFrameEvent event)
  {
    // do nothing when frame is closed
  } // internalFrameClosed(InternalFrameEvent)

  /**
   * Handle internal frame closing
   *
   * @param event  Internal frame closing event
   */
  public void internalFrameClosing(InternalFrameEvent event)
  {
    // do nothing when frame is closing
  } // internalFrameClosing(InternalFrameEvent)

  /**
   * Handle internal frame deactivated
   *
   * @param event  Internal frame deactivated event
   */
  public void internalFrameDeactivated(InternalFrameEvent event)
  {
    // do nothing when frame is deactivated
  } // internalFrameDeactivated(InternalFrameEvent)

  /**
   * Handle internal frame deiconified
   *
   * @param event  Internal frame deiconified event
   */
  public void internalFrameDeiconified(InternalFrameEvent event)
  {
    // do nothing when frame is expanded
  } // internalFrameDeiconified(InternalFrameEvent)

  /**
   * Handle internal frame iconified
   *
   * @param event  Internal frame iconified event
   */
  public void internalFrameIconified(InternalFrameEvent event)
  {
    // do nothing when frame is minimized
  } // internalFrameIconified(InternalFrameEvent)

  // inspired by http://blog.csdn.net/mq612/archive/2006/09/21/1260761.aspx
  public class JMenuedTextPane extends JTextPane implements MouseListener
  {
    private JPopupMenu pop = null;
    private JMenuItem copy = null;
    private JMenuItem selectAll = null;

    /**
     * Create a new JMenuedTextPane
     */
    public JMenuedTextPane()
    {
      super();
      init();
    } // JMenuedTextPane()

    /* initialize */
    private void init()
    {
      this.addMouseListener(this);
      this.setFont(new Font("Monospaced", Font.PLAIN, 12));
      this.pop = new JPopupMenu();
      this.pop.add(this.copy = new JMenuItem("Copy"));
      this.pop.add(this.selectAll = new JMenuItem("Select All"));
      this.copy.setAccelerator(KeyStroke.getKeyStroke('C', InputEvent.CTRL_MASK));
      this.selectAll.setAccelerator(KeyStroke.getKeyStroke('A',
        InputEvent.CTRL_MASK));
      this.copy.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent event)
        {
          action(event);
        } // actionPerformed(ActionEvent)
      });

      this.selectAll.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent event)
        {
          action(event);
        } // actionPerformed(ActionEvent)
      });
      this.add(pop);
    } // init()

    public void action(ActionEvent event)
    {
      String str = event.getActionCommand();
      if (str.equals(this.copy.getText()))
      {
        this.copy();
      } // if (str.equals(this.copy.getText()))
      else if (str.equals(this.selectAll.getText()))
      {
        this.selectAll();
      } // else if (str.equals(this.selectAll.getText()))
    } // action(ActionEvent)

    public boolean isCanCopy()
    {
      return (! (this.getSelectionStart() == this.getSelectionEnd()));
    } // isCanCopy()

    public void mousePressed(MouseEvent event)
    {
      if (event.getButton() == MouseEvent.BUTTON3)
      {
        this.copy.setEnabled(isCanCopy());
        this.pop.show(this, event.getX(), event.getY());
      } // if (event.getButton() == MouseEvent.BUTTON3)
    } // mousePressed(MouseEvent)

    public void mouseClicked(MouseEvent event)
    {
      // do nothing when mouse is clicked
    } // mouseClicked(MouseEvent)

    public void mouseEntered(MouseEvent event)
    {
      // do nothing when mouse enters frame
    } // mouseEntered(MouseEvent)

    public void mouseExited(MouseEvent event)
    {
      // do nothing when mouse exits frame
    } // mouseExited(MouseEvent)

    public void mouseReleased(MouseEvent event)
    {
      // do nothing when mouse is released
    } // mouseReleased(MouseEvent)
  } // class JMenuedTextPane

  // context menu portion inspired by http://blog.csdn.net/mq612/archive/
  //   2006/09/21/1260761.aspx
  // Highlighter for JEditorPane inspired by http://www.exampledepot.
  //   com/egs/javax.swing.text/style_HiliteWords.html
  public class SchemeEditor extends JEditorPane implements MouseListener,
    CaretListener
  {
    private JPopupMenu pop = null;
    private JMenuItem copy = null;
    private JMenuItem paste = null;
    private JMenuItem cut = null;
    private JMenuItem selectAll = null;
    private Highlighter hilite = this.getHighlighter();

    public SchemeEditor()
    {
      super();
      this.addMouseListener(this);
      this.addCaretListener(this);
      this.setFont(new Font("Monospaced", Font.PLAIN, 12));
      this.pop = new JPopupMenu();
      this.pop.add(this.cut = new JMenuItem("Cut"));
      this.pop.add(this.copy = new JMenuItem("Copy"));
      this.pop.add(this.paste = new JMenuItem("Paste"));
      this.pop.add(this.selectAll = new JMenuItem("Select All"));
      this.copy.setAccelerator(KeyStroke.getKeyStroke('C', InputEvent.CTRL_MASK));
      this.paste.setAccelerator(KeyStroke.getKeyStroke('V', InputEvent.CTRL_MASK));
      this.cut.setAccelerator(KeyStroke.getKeyStroke('X', InputEvent.CTRL_MASK));
      this.selectAll.setAccelerator(KeyStroke.getKeyStroke('A', InputEvent.CTRL_MASK));
      this.copy.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent event)
        {
          action(event);
        } // actionPerformed(ActionEvent)
      });

      this.paste.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent event)
        {
          action(event);
        } // actionPerformed(ActionEvent)
      });

      this.cut.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent event)
        {
          action(event);
        } // actionPerformed(ActionEvent)
      });

      this.selectAll.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent event)
        {
          action(event);
        } // actionPerformed(ActionEvent)
      });
    } // JMenuedEditorPane()

    public void action(ActionEvent event)
    {
      String str = event.getActionCommand();
      if (str.equals(this.copy.getText()))
      {
        this.copy();
      } // if (str.equals(copy.getText()))
      else if (str.equals(this.paste.getText()))
      {
        this.paste();
      } // else if (str.equals(paste.getText()))
      else if (str.equals(this.cut.getText()))
      {
        this.cut();
      } // else if (str.equals(cut.getText()))
      else if (str.equals(this.selectAll.getText()))
      {
        this.selectAll();
      } // else if (str.equals(selectAll.getText()))
    } // action(ActionEvent)

    public boolean isClipboardString()
    {
      boolean b = false;
      Clipboard clipboard = this.getToolkit().getSystemClipboard();
      Transferable content = clipboard.getContents(this);
      try
      {
        if (content.getTransferData(DataFlavor.stringFlavor) instanceof String)
        {
          b = true;
        } // if (content.getTransferData(DataFlavor.stringFlavor) instanceof ...
      } // try
      catch (Exception e)
      {
        // do nothing
      } // catch (Exception)
      return b;
    } // isClipboardString()

    public boolean isCanCopy()
    {
      return (! (this.getSelectionStart() == this.getSelectionEnd()));
    } // isCanCopy()

    public void mousePressed(MouseEvent event)
    {
      if (event.getButton() == MouseEvent.BUTTON3)
      {
        this.copy.setEnabled(isCanCopy());
        this.paste.setEnabled(isClipboardString());
        this.cut.setEnabled(isCanCopy());
        this.pop.show(this, event.getX(), event.getY());
      } // if (event.getButton() == MouseEvent.BUTTON3)
    } // mousePressed(MouseEvent)

    public void mouseClicked(MouseEvent event)
    {
      // do nothing when mouse is clicked
    } // mouseClicked(MouseEvent)

    public void mouseEntered(MouseEvent event)
    {
      // do nothing when mouse enters frame
    } // mouseEntered(MouseEvent)

    public void mouseExited(MouseEvent event)
    {
      // do nothing when mouse exits frame
    } // mouseExited(MouseEvent)

    public void mouseReleased(MouseEvent event)
    {
      // do nothing when mouse is released
    } // mouseReleasedd(MouseEvent)

    private int getMatchingCloseParen(int open)
    throws BadLocationException
    {
      int i = 0;
      int length = this.getText().length();
      int danglingParen = 1;
      boolean insideQuotes = false;
      boolean success = false;
      String now = "";
      for (i = open + 1; (i < length) && (!success); i++)
      {
        now = this.getText(i, 1);
        if (!insideQuotes && (now.equals("(")))
        {
          danglingParen++;
        } // if (!insideQuotes && (now.equals("(")))
        else if (!insideQuotes && now.equals(")"))
        {
          danglingParen--;
        } // else if (!insideQuotes && now.equals(")"))
        else if (now.equals("\"") && (!this.getText(i - 1, 1).equals("\\")))
        {
          insideQuotes = !insideQuotes;
        } // else if (now.equals("\"") && (!this.getText(i - 1, 1).equals("\\")))
        if (danglingParen == 0)
        {
          success = true;
        } // if (danglingParen == 0)
      } // for
      if (success)
      {
        return i;
      } // if (success)
      else
      {
        return -1;
      } // else
    } // getMatchingCloseParen(int)

    private int getMatchingOpenParen(int close)
    throws BadLocationException
    {
      int i = 0;
      int danglingParen = 1;
      boolean insideQuotes = false;
      boolean success = false;
      String now = "";
      for (i = close - 1; (i >= 0) && (!success); i--)
      {
        now = this.getText(i, 1);
        if (!insideQuotes && (now.equals(")")))
        {
          danglingParen++;
        } // if (!insideQuotes && (now.equals(")")))
        else if (!insideQuotes && now.equals("("))
        {
          danglingParen--;
        } // else if (!insideQuotes && now.equals("("))
        else if (now.equals("\"") && (!this.getText(i - 1, 1).equals("\\")))
        {
          insideQuotes = !insideQuotes;
        } // else if (now.equals("\"") && (!this.getText(i - 1, 1).equals("\\")))
        if (danglingParen == 0)
        {
          success = true;
        } // if (danglingParen == 0)
      } // for
      if (success)
      {
        return i+1;
      } // if (success)
      else
      {
        return -1;
      } // else
    } // getMatchingCloseParen(int)

    public void caretUpdate(CaretEvent event)
    {
      int dot = event.getDot();
      if (dot != event.getMark())
      {
        removeHighlights();
        return;
      } // if (dot != event.getMark())
      removeHighlights();
      try
      {
        if ((dot != 0) && (this.getText(dot - 1, 1).equals(")")))
        {
          int pos = getMatchingOpenParen(dot - 1);
          if (pos != -1)
          {
            this.hilite.addHighlight(pos, dot, new ParenHighLighter());
          } // if (pos != -1)
          else
          {
            this.hilite.addHighlight(dot - 1, dot, new DanglingHighLighter());
          } // else
        } // if ((dot != 0) && (this.getText(dot - 1, 1).equals(")")))
        else if ((this.getText(dot, 1).equals("(")))
        {
          int pos = getMatchingCloseParen(dot);
          if (pos != -1)
          {
            this.hilite.addHighlight(dot, pos + 1, new ParenHighLighter());
          } // if (pos != -1)
        } // else if ((this.getText(dot, 1).equals("(")))
      } // try
      catch (BadLocationException e)
      {
        // do nothing
      } // catch (BadLocationException)
    } // caretUpdate(CaretEvent)

    class ParenHighLighter extends DefaultHighlighter.DefaultHighlightPainter
    {
      public ParenHighLighter()
      {
        super(Color.LIGHT_GRAY);
      } // public ParentHighLighter()
    } // class ParenHighLighter

    class DanglingHighLighter extends DefaultHighlighter.DefaultHighlightPainter
    {
      public DanglingHighLighter()
      {
        super(Color.PINK);
      } // DanglingHighLighter()
    } // class DanglingHighLighter

    public void removeHighlights()
    {
      Highlighter.Highlight[] hilites = this.hilite.getHighlights();
      for (int i=0; i<hilites.length; i++)
      {
        if ((hilites[i].getPainter() instanceof ParenHighLighter)
            || ((hilites[i].getPainter() instanceof DanglingHighLighter)))
        {
          this.hilite.removeHighlight(hilites[i]);
        } // if ((hilites[i].getPainter() instanceof ParenHighLighter)
      } // for
    } // removeHighlights()
  } // class JMenuedEditorPane
} // class SchemeWindow
TOP

Related Classes of view.SchemeWindow$SchemeEditor$DanglingHighLighter

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.