Package lupos.autocomplete.gui

Source Code of lupos.autocomplete.gui.JTextPanePreparer$RoundedBorder

/**
* Copyright (c) 2013, Institute of Information Systems (Sven Groppe and contributors of LUPOSDATE), University of Luebeck
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
*   - Redistributions of source code must retain the above copyright notice, this list of conditions and the following
*     disclaimer.
*   - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
*     following disclaimer in the documentation and/or other materials provided with the distribution.
*   - Neither the name of the University of Luebeck nor the names of its contributors may be used to endorse or promote
*     products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package lupos.autocomplete.gui;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Observable;

import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.border.AbstractBorder;

import lupos.autocomplete.strategies.Strategy;
import lupos.autocomplete.strategies.StrategyManager;
import lupos.autocomplete.strategies.StrategyManager.LANGUAGE;
import lupos.gui.anotherSyntaxHighlighting.LuposDocument;

public class JTextPanePreparer extends Observable implements ActionListener, KeyListener {

  protected final JTextPane textPane;
  protected JPopupMenu popupMenu;
  protected JList jl;
  protected int index;
  protected final LuposDocument document;
  protected final StrategyManager sm;

  public JTextPanePreparer(final JTextPane textPane, final LANGUAGE language, final LuposDocument document) {
    this.textPane = textPane;
    this.document = document;
    this.sm = new StrategyManager(language, document);
    ((JComponent) textPane).registerKeyboardAction(this, "open",
        KeyStroke.getKeyStroke(KeyEvent.VK_SPACE , Event.CTRL_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW);
//    // Binding Alt F4
//    ((JComponent) textPane).registerKeyboardAction(this, "close",
//        alt(KeyEvent.VK_F4), JComponent.WHEN_FOCUSED);
    this.textPane.addKeyListener(this);
  }

  // was passiert wenn tasten gedrueckt werden
  @Override
  public void actionPerformed(final ActionEvent event) {

    final String cmd = event.getActionCommand();
    try {
      if (cmd.equals("open")) {
        this.openPopup();
      } else if (cmd.equals("close")) {
        System.exit(0);
      }
    } catch (final Exception e) {
      e.printStackTrace();
    }
  }


  @Override
  public void keyTyped(final KeyEvent e) {
  }

  @SuppressWarnings("serial")
  @Override
  public void keyReleased(final KeyEvent e) {

    /*
     * Workaround fuer den Bug mit der CaretPosition
     */
//    if (JTextPanePreparer.this.popupMenu != null && !JTextPanePreparer.this.popupMenu.isVisible()){
//      if (JTextPanePreparer.this.textPane.getCaretPosition() == JTextPanePreparer.this.textPane.getText().length()) {
//        JTextPanePreparer.this.textPane.setCaretPosition(JTextPanePreparer.this.textPane.getCaretPosition() - 1);
//        JTextPanePreparer.this.textPane.setCaretPosition(JTextPanePreparer.this.textPane.getCaretPosition() + 1);
//      } else {
//        JTextPanePreparer.this.textPane.setCaretPosition(JTextPanePreparer.this.textPane.getCaretPosition() + 1);
//        JTextPanePreparer.this.textPane.setCaretPosition(JTextPanePreparer.this.textPane.getCaretPosition() - 1);
//      }
//    }

    /*
     * Stellt sicher, dass Keybindings nur aktiviert sind wenn Popup
     * sichtbar
     *
     * ENTER und TAB fuegen aktuelles Listenelement ein, UP und DOWN
     * navigieren in der Liste, RIGHT und LEFT schliessen das Popup
     */
    if ((this.popupMenu != null) && (this.popupMenu.isVisible())) {

      if((e.getKeyCode() != KeyEvent.VK_DOWN) && (e.getKeyCode() != KeyEvent.VK_UP)) {
        this.jl.setModel(this.sm.listToJList(this.textPane.getText().replaceAll("\r\n", "\n"), this.textPane.getCaretPosition()));
        this.jl.setSelectedIndex(0);
      }

      this.textPane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "myEnter");
      this.textPane.getActionMap().put("myEnter", new AbstractAction() {
        @Override
        public void actionPerformed(final ActionEvent e) {
          if(!JTextPanePreparer.this.popupMenu.isVisible()){
            JTextPanePreparer.this.textPane.getInputMap().clear();
            // this is the dirty way to pass "enter" to the JTextPane!
            Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(new KeyEvent(
                JTextPanePreparer.this.textPane,
                                KeyEvent.KEY_PRESSED,
                                System.currentTimeMillis(),
                                0,
                                KeyEvent.VK_ENTER,
                                KeyEvent.CHAR_UNDEFINED));
            return;
          }
          if (JTextPanePreparer.this.jl.getSelectedValue() == null) {
            JTextPanePreparer.this.popupMenu.setVisible(false);
          } else {
            JTextPanePreparer.this.insertSelectedWord();
            JTextPanePreparer.this.popupMenu.setVisible(false);
          }

        }
      });

      this.textPane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), "myTab");
      this.textPane.getActionMap().put("myTab", new AbstractAction() {
        @Override
        public void actionPerformed(final ActionEvent e) {
          JTextPanePreparer.this.insertSelectedWord();
          JTextPanePreparer.this.popupMenu.setVisible(false);
        }
      });

      this.textPane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "myUp");
      this.textPane.getActionMap().put("myUp", new AbstractAction() {
        @Override
        public void actionPerformed(final ActionEvent e) {
          if(!JTextPanePreparer.this.popupMenu.isVisible()){
            JTextPanePreparer.this.textPane.getInputMap().clear();
            // this is the dirty way to pass "up" to the JTextPane!
            Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(new KeyEvent(
                JTextPanePreparer.this.textPane,
                                KeyEvent.KEY_PRESSED,
                                System.currentTimeMillis(),
                                0,
                                KeyEvent.VK_UP,
                                KeyEvent.CHAR_UNDEFINED));
            return;
          }
          JTextPanePreparer.this.previousListItem();
        }
      });

      this.textPane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "myDown");
      this.textPane.getActionMap().put("myDown", new AbstractAction() {
        @Override
        public void actionPerformed(final ActionEvent e) {
          if(!JTextPanePreparer.this.popupMenu.isVisible()){
            JTextPanePreparer.this.textPane.getInputMap().clear();
            // this is the dirty way to pass "down" to the JTextPane!
            Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(new KeyEvent(
                JTextPanePreparer.this.textPane,
                                KeyEvent.KEY_PRESSED,
                                System.currentTimeMillis(),
                                0,
                                KeyEvent.VK_DOWN,
                                KeyEvent.CHAR_UNDEFINED));
            return;
          }
          JTextPanePreparer.this.nextListItem();
        }
      });

      this.textPane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "myRight");
      this.textPane.getActionMap().put("myRight", new AbstractAction() {
        @Override
        public void actionPerformed(final ActionEvent e) {
          JTextPanePreparer.this.popupMenu.setVisible(false);
          JTextPanePreparer.this.textPane.setCaretPosition(JTextPanePreparer.this.textPane.getCaretPosition()+1);
        }
      });

      this.textPane.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "myLeft");
      this.textPane.getActionMap().put("myLeft", new AbstractAction() {
        @Override
        public void actionPerformed(final ActionEvent e) {
          JTextPanePreparer.this.popupMenu.setVisible(false);
          JTextPanePreparer.this.textPane.setCaretPosition(JTextPanePreparer.this.textPane.getCaretPosition()-1);
        }
      });

    } else {
      /*
       * sorgt dafuer, dass die Bindings wieder verschwinden wenn
       * das Popup nicht mehr geöffnet ist
       */
      this.textPane.getInputMap().clear();
    }
  }

  @Override
  public void keyPressed(final KeyEvent e) {
  }


  /*
   * doppelter Mausklick fuegt ausgewähltes Wort ein
   */
  public void handleMouseKlicks() {
    this.jl.addMouseListener(new MouseListener() {
      @Override
      public void mouseReleased(final MouseEvent e) {
        JTextPanePreparer.this.textPane.requestFocusInWindow();
      }

      @Override
      public void mousePressed(final MouseEvent e) {
        JTextPanePreparer.this.textPane.requestFocusInWindow();
      }

      @Override
      public void mouseExited(final MouseEvent e) {
        JTextPanePreparer.this.textPane.requestFocusInWindow();
      }

      @Override
      public void mouseEntered(final MouseEvent e) {
      }

      @Override
      public void mouseClicked(final MouseEvent e) {
        JTextPanePreparer.this.textPane.requestFocusInWindow();
        if (e.getClickCount() == 2 && JTextPanePreparer.this.popupMenu.isVisible()) {
          JTextPanePreparer.this.insertSelectedWord();
          JTextPanePreparer.this.popupMenu.setVisible(false);
        } else {
          JTextPanePreparer.this.textPane.requestFocusInWindow();
        }
      }
    });
  }

  /*
   * fuegt das ausgewaehlte Listenelement an
   * der aktuellen Textcursorposition ein
   */
  public void insertSelectedWord() {
    try {
      final String currentWord = this.getCurrentWord();
      final String text = this.textPane.getText().replaceAll("\r\n", "\n");
      final int caret = this.textPane.getCaretPosition();
      String textBefore;
      String textAfter;
      String newText;
      // immer leerzeichen nach eingefügtem Wort
      final String addWord = this.jl.getSelectedValue().toString() + " ";
      /*
       * Wenn Cursor am Ende, textAfter dementsprechend leer
       */
      if (text.length() == 0) {
        textAfter = "";
        textBefore = "";
        this.textPane.setText(addWord);
      } else if (caret == 0) {
        textBefore = "";
        textAfter = text.substring(caret);
      } else if (text.substring(caret).length() == 0) {
        textBefore = text.substring(0, caret - (currentWord.length()));
        textAfter = "";
        // Ansonsten textAfter = hinterer Text
      } else {
        textBefore = text.substring(0, caret - (currentWord.length()));
        textAfter = text.substring(caret);
      }
      // Falls aktuelles Wort leerzeichen
      if (currentWord.equals(" ")) {
        // neuer Text incl leerzeichen vor hinzuzufuegendem Wort
        newText = textBefore + " " + addWord + textAfter;
        this.textPane.setText(newText);
        // Falls Cursor am Ende->bleibt Cursor am Ende
        if (caret == text.length()) {
          this.textPane.setCaretPosition(newText.length());
          // Ansonsten von Caret die Laenge des akt Wortes abziehen
          // und
          // Laenge vom neuen Wort +1 raufaddieren ->neue
          // Caretposition
        } else {
          this.textPane.setCaretPosition(caret - currentWord.length()
              + (addWord.length()) + 1);
        }
        /*
         * Hier wird reingesprungen falls akt. Wort kein Leerzeichen
         * Eigentlich alles wie oben, bis auf das zusaetzliche
         * leerzeichen und caret +1
         */
      } else {
        newText = textBefore + addWord + textAfter;
//        if (textBefore.length() > 0
//            && textBefore.substring(textBefore.length() - 1)
//                .equals("\n")) {
//          newText = textBefore + addWord + textAfter;
//        }
        this.textPane.setText(newText);
        if (caret == text.length()) {
          this.textPane.setCaretPosition(newText.length());
        } else {
          this.textPane.setCaretPosition(caret - currentWord.length() + (addWord.length()));
        }
      }
    } catch (final Exception e) {
      System.out.println("INSERT FEHLER= " + e);
      e.printStackTrace();
    }
  }

  /*
   * navigiert zum naechsten Listenelement
   */
  public void nextListItem() {
    this.index = this.jl.getSelectedIndex();
    if (this.index == (this.jl.getModel().getSize() - 1)) {
      this.index = 0;
    } else {
      this.index += 1;
    }
    this.jl.setSelectedIndex(this.index);
    this.jl.ensureIndexIsVisible(this.index);
  }

  /*
   * navigiert zum vorigen Listenelement
   */
  public void previousListItem() {
    this.index = this.jl.getSelectedIndex();
    if (this.index > 0) {
      this.index -= 1;
    } else if (this.index == 0) {
      this.index = this.jl.getModel().getSize() - 1;
    }
    this.jl.setSelectedIndex(this.index);
    this.jl.ensureIndexIsVisible(this.index);
  }

  /*
   * oeffnet das Popup
   */
  public void openPopup() {
    /*
     * wenn popupMenu nicht existiert, wird es erstellt
     * und auf unsichtbar gestellt, ansonsten immer bei
     * der aktuellen caret Position mit show() aufgerufen
     */
    if (this.popupMenu == null) {
      this.buildPopup();
      this.popupMenu.setVisible(false);
    }
    this.jl.setModel(this.sm.listToJList(this.textPane.getText().replaceAll("\r\n", "\n"),
        this.textPane.getCaretPosition()));
    this.jl.setSelectedIndex(0);
    if (this.textPane.getCaretPosition() == 0) {
      this.popupMenu.show(this.textPane, 0, 15);
    } else {
      if ((this.textPane.getCaret().getMagicCaretPosition().x == 0)) {
        this.popupMenu.show(this.textPane, 0, 15);

      } else {
        this.jl.setSelectedIndex(0);
        this.popupMenu.show(this.textPane, this.textPane.getCaret()
            .getMagicCaretPosition().x, (this.textPane.getCaret()
                .getMagicCaretPosition().y + 15));
      }
    }
    this.jl.ensureIndexIsVisible(this.jl.getSelectedIndex());
    this.textPane.requestFocusInWindow();
  }

  /*
   * Initialisiert das Popup mit seinen Einstellungen
   */
  public void buildPopup() {
    this.popupMenu = new JPopupMenu();
    final JPanel panel = new JPanel();
    this.jl = new JList();
    this.jl.setModel(this.sm.listToJList(this.textPane.getText().replaceAll("\r\n", "\n"),
        this.textPane.getCaretPosition()));
    this.jl.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    this.jl.setSelectedIndex(0);
    panel.setBorder(new RoundedBorder());
    this.popupMenu.setBorder(new RoundedBorder());
    this.popupMenu.setOpaque(false);
    this.popupMenu.setFocusable(true);
    this.popupMenu.add(panel, Component.LEFT_ALIGNMENT);
    this.popupMenu.show(this.textPane, 0, 0);
    this.popupMenu.setVisible(true);

    final JScrollPane scrollPane = new JScrollPane(this.jl);
    scrollPane.setPreferredSize(new Dimension(300, 300));
    panel.add(scrollPane);

    this.popupMenu.setLocation(this.getPositionX(), this.getPositionY());
    this.jl.ensureIndexIsVisible(this.jl.getSelectedIndex());
    this.textPane.requestFocusInWindow();
    this.handleMouseKlicks();
  }

  /*
   *  returnt die genaue X Koordinate on Screen
   */
  public int getPositionX() {
    if (this.textPane.getCaretPosition() == 0) {
      return (int) this.textPane.getLocationOnScreen().getX();
    }
    return (int) (this.textPane.getLocationOnScreen().getX() + this.textPane
        .getCaret().getMagicCaretPosition().x);
  }

  /*
   *  returnt die genaue Y Koordinate on Screen + 15px damit es eine Spalte
   *  weiter unten ist
   */
  public int getPositionY() {
    if (this.textPane.getCaretPosition() == 0) {
      return (int) this.textPane.getLocationOnScreen().getY() + 16;
    }
    return (int) (this.textPane.getLocationOnScreen().getY()
        + this.textPane.getCaret().getMagicCaretPosition().y + 15);
  }

  // gibt das aktuelle Wort zurueck
  public String getCurrentWord() {
    return Strategy.getCurrentWord(this.textPane.getText().replaceAll("\r\n", "\n"), this.textPane.getCaretPosition());
  }

  @SuppressWarnings("serial")
  public static class RoundedBorder extends AbstractBorder {
    /*
     * runde Ecken fuer PopupMenu
     */
    @Override
    public void paintBorder(final Component c, final Graphics g, final int x, final int y,
        final int width, final int height) {
      final Graphics2D g2 = (Graphics2D) g;
      g2.setColor(Color.darkGray);
      final int arc = 10;
      g2.drawRoundRect(x, y, width - 1, height - 1, arc, arc);
    }
  }
}
TOP

Related Classes of lupos.autocomplete.gui.JTextPanePreparer$RoundedBorder

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.