package com.drawbridge.text;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.KeyStroke;
import javax.swing.Scrollable;
import javax.swing.SwingUtilities;
import com.drawbridge.Activity;
import com.drawbridge.correspondance.RadialSpotlight;
import com.drawbridge.correspondance.Spotlight;
import com.drawbridge.correspondance.Spotlightable;
import com.drawbridge.dm.DMSimplePanel;
import com.drawbridge.jsengine.JsEngine;
import com.drawbridge.text.DBCaret.Blinker;
import com.drawbridge.utils.GraphicUtils;
import com.drawbridge.utils.HighlightElement;
import com.drawbridge.utils.JSUtils;
import com.drawbridge.utils.Utils;
import com.drawbridge.vl.VLPanel;
public class DBDocument extends JComponent implements MouseListener,
MouseMotionListener, KeyListener, FocusListener,
Scrollable, ComponentListener, ClipboardOwner, Spotlightable
{
public class CopyAction extends AbstractAction
{
private static final long serialVersionUID = 1L;
public CopyAction(String text, ImageIcon icon, String desc, Integer mnemonic)
{
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
public void actionPerformed(ActionEvent e)
{
String string = mDocumentModel.getRawTextSubstring(mCaret.mMarkCharPosition, mCaret.mDotCharPosition);
Utils.out.println("Copy String:" + string);
StringSelection stringSelection = new StringSelection(string);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(stringSelection, DBDocument.this);
}
}
public class CutAction extends AbstractAction
{
private static final long serialVersionUID = 1L;
public CutAction(String text, ImageIcon icon, String desc, Integer mnemonic)
{
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
public void actionPerformed(ActionEvent e)
{
String string = mDocumentModel.getRawTextSubstring(mCaret.mMarkCharPosition, mCaret.mDotCharPosition);
StringSelection stringSelection = new StringSelection(string);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(stringSelection, DBDocument.this);
mDocumentModel.replace(mCaret.mMarkCharPosition, mCaret.mDotCharPosition, "");
boolean useMark = DBDocumentModel.isCharPosLessThan(mCaret.getMarkCharPosition(), mCaret.getDotCharPosition());
if (useMark)
mCaret.setDotCharPosition(mCaret.getMarkCharPosition());
else
mCaret.setMarkCharPosition(mCaret.getDotCharPosition());
updateUIOnChange(true);
updateVLLineSelection();
}
}
public class SelectAllAction extends AbstractAction
{
private static final long serialVersionUID = 1l;
public SelectAllAction(String text, ImageIcon icon, String desc, Integer mnemonic) {
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
public void actionPerformed(ActionEvent e)
{
mCaret.setMarkCharPosition(new Point(0, 0));
int lastPositionIndex = DBDocument.this.mDocumentModel.getRawText().length();
Point dotPoint = DBDocument.this.mDocumentModel.getCharPositionFromStringIndex(lastPositionIndex);
mCaret.setDotCharPosition(dotPoint);
updateUIOnChange(true);
updateVLLineSelection();
}
}
public interface DBDocumentListener
{
public void onDocumentUpdate(String string);
}
public enum InputType
{
INPUT_SELECTION, INPUT_CARET
}
public class PasteAction extends AbstractAction
{
private static final long serialVersionUID = 1L;
public PasteAction(String text, ImageIcon icon, String desc, Integer mnemonic)
{
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
public void actionPerformed(ActionEvent e)
{
String result = "";
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable contents = clipboard.getContents(null);
boolean hasTransferableText = (contents != null) && contents.isDataFlavorSupported(DataFlavor.stringFlavor);
if (hasTransferableText)
{
try
{
result = (String) contents.getTransferData(DataFlavor.stringFlavor);
} catch (UnsupportedFlavorException ex)
{
// highly unlikely since we are using a standard DataFlavor
Utils.out.println(this.getClass(), ex.toString());
ex.printStackTrace();
} catch (IOException ex)
{
Utils.out.println(this.getClass(), ex.toString());
ex.printStackTrace();
}
}
if (result != null)
mDocumentModel.replace(mCaret.getMarkCharPosition(), mCaret.getDotCharPosition(), result);
Point finalDotPosition = mDocumentModel.getCharPositionFromStringIndex(mDocumentModel.getStringIndexFromCharPos(mCaret.getMarkCharPosition()) + result.length());
mCaret.setDotCharPosition(finalDotPosition);
updateUIOnChange(true);
updateVLLineSelection();
}
}
class PopUpDemo extends JPopupMenu
{
/**
*
*/
private static final long serialVersionUID = 1L;
JMenuItem anItem;
public PopUpDemo(InputType selectionType) {
JMenuItem cut = new JMenuItem(new CutAction("Cut", null, "Cut text", 10));
cut.setEnabled((selectionType == InputType.INPUT_SELECTION) ? true : false);
JMenuItem copy = new JMenuItem(new CopyAction("Copy", null, "Copy text", 12));
copy.setEnabled((selectionType == InputType.INPUT_SELECTION) ? true : false);
JMenuItem paste = new JMenuItem(new PasteAction("Paste", null, "Paste text", 14));
paste.setEnabled(true);
JMenuItem selectAll = new JMenuItem(new SelectAllAction("SelectAll", null, "Select All", 14));
paste.setEnabled(true);
add(cut);
add(copy);
add(paste);
add(selectAll);
}
}
private static final long serialVersionUID = 1L;
/** Connected components providing overlay **/
private DBCaret mCaret = null;
private DBSelection mSelection = null;
/** Size constraints **/
private Dimension mPreferredDimension = new Dimension(500, 600);
private Insets mInsets = new Insets(5, 20, 20, 20);
private int mLineHeight = 7;
private int mLineSpacing = 15;
private DBDocumentModel mDocumentModel = null;
private Integer mHoverIndex = null;
private ArrayList<HighlightElement> mHighlightElements = null;
private boolean mDrawCaretPosition = false;
private boolean mLineHoverHighlight = false;
private boolean mCaretLineHighlight = true;
private BufferedImage mErrorImage = null;
public Rectangle mErrorRect = null;
private DocumentError mDocumentError;
private boolean mDimBackground = false;
private HashSet<RadialSpotlight> mSpotlights = null;
public boolean mInitialised = false;
public final Font mDocumentFont;
public final boolean mCaretEnabled;
public DBDocument(final String text, Font defaultFont, boolean caret) {
mDocumentFont = defaultFont;
mCaretEnabled = caret;
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
while (DBDocument.this.getWidth() <= 0 || DBDocument.this.getHeight() <= 0)
{
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
DBDocument.this.setLayout(null);
if (text == null)
{
throw new RuntimeException("Text cannot be null");
}
mDocumentModel = new DBDocumentModel(text, getPaddedWidth(), DBDocument.this);
mLineHeight = DBDocument.this.getFontMetrics(DBDocument.this.getFont()).getHeight();
requestFocus();
if(mCaretEnabled){
addKeyListener(DBDocument.this);
initKeyMappings();
addMouseListener(DBDocument.this);
addMouseMotionListener(DBDocument.this);
addFocusListener(DBDocument.this);
}
setFocusable(true);
setVisible(true);
setEnabled(true);
addComponentListener(DBDocument.this);
if(mCaretEnabled){
mCaret = new DBCaret(DBDocument.this, new Rectangle(mInsets.left, mInsets.top, getPaddedWidth(), getPaddedHeight()));
mSelection = new DBSelection(DBDocument.this, Color.decode("#90C8DA"));
mSelection.setVisible(true);
mCaret.setDotPositionFromClick(mInsets.left, mInsets.top);
mCaret.setMarkPositionFromClick(mInsets.left, mInsets.top);
}
mErrorImage = GraphicUtils.loadImageFromResource("/Assets/red-dot.png");
mInitialised = true;
setOpaque(false);
setBackground(Color.white);
}
});
}
public Point charPosToPixelPos(int charX, int charY)
{
if (charY >= 0 && charY < mDocumentModel.getNumberOfLines())
{
String subStr = mDocumentModel.getLines().get(charY).substring(0, Math.min(mDocumentModel.getLines().get(charY).length(), charX));
int width = this.getFontMetrics(mDocumentFont).stringWidth(subStr);
int y = charY * (this.mLineHeight + this.mLineSpacing);
return new Point(width, y);
} else
{
Utils.err.println(getClass(), "No such char position :" + charX + ", " + charY + ", " + mDocumentModel.getNumberOfLines());
return null;
}
}
@Override
public void componentHidden(ComponentEvent arg0)
{
}
@Override
public void componentMoved(ComponentEvent arg0)
{
}
@Override
public void componentResized(ComponentEvent arg0)
{
if(mCaretEnabled){
// Get current caretPosition
int markIndex = this.mDocumentModel.getStringIndexFromCharPos(mCaret.getMarkCharPosition());
int dotIndex = this.mDocumentModel.getStringIndexFromCharPos(mCaret.getDotCharPosition());
// Update line width
this.mDocumentModel.setLineWidth(this.getPaddedWidth());
// Set current caretPosition
Point markCharPos = this.mDocumentModel.getCharPositionFromStringIndex(markIndex);
Point dotCharPos = this.mDocumentModel.getCharPositionFromStringIndex(dotIndex);
mCaret.setMarkCharPosition(markCharPos);
mCaret.setDotCharPosition(dotCharPos);
}
}
@Override
public void componentShown(ComponentEvent arg0)
{
}
@Override
public void focusGained(FocusEvent arg0)
{
}
@Override
public void focusLost(FocusEvent arg0)
{
if(mCaretEnabled){
mCaret.setVisible(false);
Blinker b = mCaret.getBlinker();
b.cancelled = true;
}
getParent().repaint();
}
public DBCaret getCaret()
{
return mCaret;
}
public HighlightElement getCharHighlightElement(int index)
{
int latestElement = -1;
if (mHighlightElements != null)
{
for (int i = 0; i < mHighlightElements.size(); i++)
{
int start = mHighlightElements.get(i).mStartPos;
int end = mHighlightElements.get(i).mEndPos;
if (start <= index && index <= end)
{
latestElement = i;
}
}
}
if (latestElement != -1)
return mHighlightElements.get(latestElement);
return null;
}
public DBDocumentModel getDocumentModel()
{
return mDocumentModel;
}
public Insets getInsets()
{
return mInsets;
}
public int getLineHeight()
{
return this.mLineHeight;
}
/**
* Accurately gives you the line position for a given mouse position
*
* @param x
* @param y
* @return
*/
public int getLinePosition(int y)
{
y = y - mInsets.top;
int selectedLine = y / (this.getLineHeight() + this.getLineSpacing());
// get nearest valid line
int closestYLine = 0;
if (selectedLine < 0)
{
closestYLine = 0;
} else if (selectedLine > (mDocumentModel.getNumberOfLines() - 1))
{
closestYLine = mDocumentModel.getNumberOfLines() - 1;
} else
{
closestYLine = selectedLine;
}
return closestYLine;
}
public int getLineSpacing()
{
return this.mLineSpacing;
}
@Override
public Dimension getMaximumSize()
{
return mPreferredDimension;
}
@Override
public Dimension getMinimumSize()
{
return mPreferredDimension;
}
public int getPaddedHeight()
{
return this.getSize().height - (mInsets.top + mInsets.bottom);
}
public int getPaddedWidth()
{
return this.getSize().width - (mInsets.left + mInsets.right);
}
@Override
public Dimension getPreferredScrollableViewportSize()
{
return this.getSize();
}
@Override
public Dimension getPreferredSize()
{
return mPreferredDimension;
}
@Override
public int getScrollableBlockIncrement(Rectangle arg0, int arg1, int arg2)
{
return 0;
}
@Override
public boolean getScrollableTracksViewportHeight()
{
return false;
}
@Override
public boolean getScrollableTracksViewportWidth()
{
return false;
}
@Override
public int getScrollableUnitIncrement(Rectangle arg0, int arg1, int arg2)
{
return 0;
}
public String getText()
{
if (mDocumentModel != null)
return mDocumentModel.getRawText();
else
return null;
}
public int getTextWidth()
{
int width = this.getSize().width;
width -= (mInsets.left + mInsets.right);
return width;
}
private void initKeyMappings()
{
ActionMap actionMap = DBDocument.this.getActionMap();
int condition = JComponent.WHEN_FOCUSED;
InputMap inputMap = DBDocument.this.getInputMap(condition);
String tab = "tab", copy = "copy", paste = "paste", selectAll = "selectall", cut = "cut", enter = "enter",
delete = "delete", backspace = "backspace", left = "left", right = "right", leftstart = "leftstart", rightend = "rightend", up = "up", down = "down";
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), tab);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), cut);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), copy);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), paste);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), selectAll);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), delete);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), enter);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), backspace);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), left);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), right);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), leftstart);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), rightend);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), up);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), down);
DBDocument.this.setFocusTraversalKeysEnabled(false);
actionMap.put(tab, new AbstractAction()
{
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent ap)
{
if (mDocumentModel != null)
{
mDocumentModel.replace(mCaret.mMarkCharPosition, mCaret.mDotCharPosition, " ");
Point posRight = mDocumentModel.getCharPositionRight(mCaret.getMarkCharPosition());
posRight = mDocumentModel.getCharPositionRight(posRight);
posRight = mDocumentModel.getCharPositionRight(posRight);
posRight = mDocumentModel.getCharPositionRight(posRight);
mCaret.setMarkCharPosition(posRight);
mCaret.setDotCharPosition(posRight);
updateUIOnChange(false);
updateVLLineSelection();
}
}
});
actionMap.put(cut, new CutAction("Cut", null, "Cut text", 12));
actionMap.put(copy, new CopyAction("Copy", null, "Cut text", 12));
actionMap.put(paste, new PasteAction("Paste", null, "Cut text", 12));
actionMap.put(selectAll, new SelectAllAction("SelectAll", null, "Select All", 12));
actionMap.put(enter, new AbstractAction()
{
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent ap)
{
if (mDocumentModel != null)
{
mDocumentModel.remove(mCaret.getMarkCharPosition(), mCaret.getDotCharPosition());
mDocumentModel.insertCharAt(DBDocumentModel.NEWLINE, mCaret.getMarkCharPosition());
Utils.err.println("DBDocumentModel.NEWLINE:" + DBDocumentModel.NEWLINE);
mCaret.setDotCharPosition(new Point(0, mCaret.getMarkCharPosition().y + 1));
mCaret.setMarkCharPosition(new Point(0, mCaret.getMarkCharPosition().y + 1));
updateUIOnChange(true);
updateVLLineSelection();
}
}
});
actionMap.put(delete, new AbstractAction()
{
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent ap)
{
if (mDocumentModel != null)
{
if (mCaret.getMarkCharPosition().equals(mCaret.getDotCharPosition())) {
mDocumentModel.delete(mCaret.getMarkCharPosition());
mCaret.setDotCharPosition(mCaret.getMarkCharPosition());
}
else {
boolean markFirst = DBDocumentModel.isCharPosLessThan(mCaret.getMarkCharPosition(), mCaret.getDotCharPosition());
if (markFirst) {
mDocumentModel.replace(mCaret.getMarkCharPosition(), mCaret.getDotCharPosition(), "");
mCaret.setDotCharPosition(mCaret.getMarkCharPosition());
}
else {
mDocumentModel.replace(mCaret.getDotCharPosition(), mCaret.getMarkCharPosition(), "");
mCaret.setMarkCharPosition(mCaret.getDotCharPosition());
}
}
updateUIOnChange(true);
updateVLLineSelection();
}
}
});
actionMap.put(backspace, new AbstractAction()
{
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent ap)
{
if (mDocumentModel != null)
{
Point backspacePoint;
if (!mCaret.getMarkCharPosition().equals(mCaret.getDotCharPosition()))
{
mDocumentModel.remove(mCaret.getMarkCharPosition(), mCaret.getDotCharPosition());
backspacePoint = (DBDocumentModel.isCharPosLessThan(mCaret.getMarkCharPosition(), mCaret.getDotCharPosition())) ? mCaret.getMarkCharPosition() : mCaret.getDotCharPosition();
}
else
{
backspacePoint = mDocumentModel.backspace(mCaret.mMarkCharPosition);
}
mCaret.setDotCharPosition(backspacePoint);
mCaret.setMarkCharPosition(backspacePoint);
updateUIOnChange(true);
updateVLLineSelection();
}
}
});
actionMap.put(left, new AbstractAction()
{
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent ap)
{
if (mDocumentModel != null)
{
Point posLeft = mDocumentModel.getCharPositionLeft(mCaret.mDotCharPosition);
Utils.out.println(this.getClass(), "Left: " + posLeft.x + ", " + posLeft.y);
mCaret.setDotCharPosition(posLeft);
mCaret.setMarkCharPosition(posLeft);
}
}
});
actionMap.put(leftstart, new AbstractAction()
{
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent ap)
{
if (mDocumentModel != null)
{
Point currentPoint = mCaret.mDotCharPosition;
currentPoint.x = 0;
mCaret.setDotCharPosition(currentPoint);
mCaret.setMarkCharPosition(currentPoint);
}
}
});
actionMap.put(right, new AbstractAction()
{
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent ap)
{
if (mDocumentModel != null)
{
Point posRight = mDocumentModel.getCharPositionRight(mCaret.mDotCharPosition);
Utils.out.println(this.getClass(), "Right: " + posRight.x + ", " + posRight.y);
mCaret.setDotCharPosition(posRight);
mCaret.setMarkCharPosition(posRight);
}
}
});
actionMap.put(rightend, new AbstractAction()
{
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent ap)
{
if (mDocumentModel != null)
{
Point currentPoint = mCaret.mDotCharPosition;
currentPoint.x = mDocumentModel.getLines().get(currentPoint.y).length() - 1;
mCaret.setDotCharPosition(currentPoint);
mCaret.setMarkCharPosition(currentPoint);
}
}
});
actionMap.put(up, new AbstractAction()
{
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent ap)
{
if (mDocumentModel != null)
{
Point posUp = mDocumentModel.getCharPositionUp(mCaret.mDotCharPosition);
Utils.out.println(this.getClass(), "Up: " + posUp.x + ", " + posUp.y);
mCaret.setDotCharPosition(posUp);
mCaret.setMarkCharPosition(posUp);
updateVLLineSelection();
}
}
});
actionMap.put(down, new AbstractAction()
{
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent ap)
{
if (mDocumentModel != null)
{
Point posDown = mDocumentModel.getCharPositionDown(mCaret.mDotCharPosition.x, mCaret.mDotCharPosition.y);
Utils.out.println(this.getClass(), "Down: " + posDown.x + ", " + posDown.y);
mCaret.setDotCharPosition(posDown);
mCaret.setMarkCharPosition(posDown);
updateVLLineSelection();
}
}
});
}
@Override
public void keyPressed(KeyEvent ke)
{
}
@Override
public void keyReleased(KeyEvent me)
{
}
@Override
public void keyTyped(KeyEvent ke)
{
if ((ke.getModifiersEx() == 0 || ke.getModifiersEx() == KeyEvent.SHIFT_DOWN_MASK) &&
ke.getKeyChar() != KeyEvent.VK_BACK_SPACE &&
ke.getKeyChar() != KeyEvent.VK_DELETE &&
ke.getKeyChar() != KeyEvent.VK_ENTER) {
Utils.err.println("KEY EVENT");
mDocumentModel.remove(mCaret.getMarkCharPosition(), mCaret.getDotCharPosition());
char keyChar = ke.getKeyChar();
mDocumentModel.insertCharAt(keyChar + "", mCaret.getMarkCharPosition());
Point posRight = mDocumentModel.getCharPositionRight(mCaret.getMarkCharPosition());
mCaret.setDotCharPosition(posRight);
mCaret.setMarkCharPosition(posRight);
updateUIOnChange(true);
}
}
@Override
public void lostOwnership(Clipboard c, Transferable t)
{
}
@Override
public void mouseClicked(MouseEvent me)
{
}
@Override
public void mouseDragged(MouseEvent me)
{
mCaret.setDotPositionFromClick(me.getX(), me.getY());
}
@Override
public void mouseEntered(MouseEvent me)
{
}
@Override
public void mouseExited(MouseEvent me)
{
mHoverIndex = null;
this.repaint();
}
@Override
public void mouseMoved(MouseEvent me)
{
mHoverIndex = new Integer(this.getLinePosition(me.getY()));
this.repaint();
// If user hovers over error circle
if (mErrorRect != null)
{
if (mErrorRect.contains(me.getPoint()))
{
Point activityPoint = SwingUtilities.convertPoint(DBDocument.this, mErrorRect.x + mErrorRect.width + 5, mErrorRect.y - this.mLineSpacing, Activity.getInstance());
Activity.getInstance().showErrorPopup(mDocumentError.errorTitle, mDocumentError.errorDescription, activityPoint);
}
else
{
Activity.getInstance().hideTipWindow();
}
}
}
@Override
public void mousePressed(MouseEvent me)
{
if (me.getButton() == MouseEvent.BUTTON1)
{
if (me.getClickCount() == 1)
{
// Select the caret position
mCaret.setMarkPositionFromClick(me.getX(), me.getY());
mCaret.setDotPositionFromClick(me.getX(), me.getY());
updateVLLineSelection();
DBDocument.this.requestFocusInWindow();
mCaret.setVisible(false);
this.repaint();
mCaret.restartDotAnimation();
} else if (me.getClickCount() == 2)
{
// Select the word
Point nearestCharPos = mDocumentModel.getCharPosFromMouseClick(me.getX() - this.mInsets.left, getLinePosition(me.getY()));
Point[] startAndFinishChar = mDocumentModel.getWordBoundaries(nearestCharPos);
if (startAndFinishChar != null)
{
mCaret.setMarkPosition(this.charPosToPixelPos(startAndFinishChar[0].x, startAndFinishChar[0].y), startAndFinishChar[0]);
mCaret.setDotPosition(this.charPosToPixelPos(startAndFinishChar[1].x, startAndFinishChar[1].y), startAndFinishChar[1]);
}
else
{
mCaret.setMarkCharPosition(nearestCharPos);
mCaret.setDotCharPosition(nearestCharPos);
}
this.repaint();
} else if (me.getClickCount() == 3)
{
// Select the row
Point nearestCharPos = mDocumentModel.getCharPosFromMouseClick(me.getX() - this.mInsets.left, getLinePosition(me.getY()));
mCaret.setMarkPosition(this.charPosToPixelPos(0, nearestCharPos.y), nearestCharPos);
mCaret.setDotPosition(this.charPosToPixelPos(0, nearestCharPos.y + 1), new Point(0, nearestCharPos.y + 1));
}
}
else if (me.getButton() == MouseEvent.BUTTON3)
{
PopUpDemo menu;
if (mCaret.getDotCharPosition().equals(mCaret.getMarkCharPosition()))
{
menu = new PopUpDemo(InputType.INPUT_CARET);
}
else
{
menu = new PopUpDemo(InputType.INPUT_SELECTION);
}
menu.show(me.getComponent(), me.getX(), me.getY());
}
}
public void updateVLLineSelection(){
// Highlight corresponding line in VLJPanel
if (VLPanel.hasInstance())
{
int mCaretPos = mCaret.getDotCharPosition().y;
VLPanel.getInstance().mCanvas.mCaretLine = mCaretPos;
VLPanel.getInstance().mCanvas.repaint();
}
}
@Override
public void mouseReleased(MouseEvent me)
{
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
if(!getParent().getParent().getParent().getBackground().equals(getBackground())){
//TextPanel background
getParent().getParent().getParent().setBackground(getBackground());
}
else if(!getParent().getParent().getBackground().equals(getBackground())){
//ScrollPane background
getParent().getParent().setBackground(getBackground());
// else if(getBackground().getRed() == 220 && getBackground().getBlue() == 220 && getBackground().getGreen() == 220){
}
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(getForeground());
if (mInitialised)
{
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setFont(mDocumentFont);
// Do spotlighting if we need to
if (mSpotlights != null)
{
for (RadialSpotlight ds : mSpotlights)
{
ds.paintRadialSpotlight(g2);
}
}
g2.setColor(Color.black);
// Paint Selected Line
if (mHoverIndex != null && mLineHoverHighlight)
{
g2.setColor(new Color(50, 85, 120, 40));
g2.fillRect(mInsets.left, mInsets.top + ((mHoverIndex) * (this.mLineHeight + this.mLineSpacing)), this.getPaddedWidth(), this.mLineHeight + this.mLineSpacing);
}
if (mCaretLineHighlight && !mDimBackground && mCaretEnabled)
{
g2.setColor(Color.decode("#E8F2FF"));
g2.fillRect(mInsets.left, mInsets.top + ((mCaret.mMarkCharPosition.y) * (this.mLineHeight + this.mLineSpacing)), this.getPaddedWidth(), this.mLineHeight + this.mLineSpacing);
}
// Selection
if(mCaretEnabled)
mSelection.Paint(g);
// Draw Text
g2.setClip(mInsets.left, mInsets.top, getPaddedWidth(), getPaddedHeight());
CopyOnWriteArrayList<String> textLines = mDocumentModel.getLines();
if (textLines != null)
{
for (int i = 0; i < textLines.size(); i++)
{
g2.setColor(Color.black);
String text = textLines.get(i);
int startIndex = mDocumentModel.getStringIndexFromCharPos(new Point(0, i));
printLine(text, g2, i, startIndex);
}
}
g2.setClip(0, 0, this.getWidth(), this.getHeight());
// Paint caretPosition on topRight
if (mDrawCaretPosition)
{
Point position = this.mCaret.mDotCharPosition;
if (position != null)
g2.drawString("(" + position.x + " " + position.y + ")", this.getWidth() - 65, 13);
}
if (mErrorImage != null && mDocumentError != null)
{
int totalLineHeight = mLineHeight + mLineSpacing;
int y = mInsets.top + (mDocumentError.lineNumber * totalLineHeight) + ((totalLineHeight - mErrorImage.getHeight()) / 2);
g2.drawImage(mErrorImage, 3, y + (mLineSpacing / 2) - 2, mErrorImage.getWidth(), mErrorImage.getHeight(), null);
mErrorRect = new Rectangle(3, y + (mLineSpacing / 2) - 2, mErrorImage.getWidth(), mErrorImage.getHeight());
}
else
{
mErrorRect = null;
}
// Caret
if(mCaretEnabled)
mCaret.Paint(g);
}
};
public void setDocumentError(DocumentError error)
{
mDocumentError = error;
int totalLineHeight = mLineHeight + mLineSpacing;
int y = mInsets.top + (mDocumentError.lineNumber * totalLineHeight) + ((totalLineHeight - mErrorImage.getHeight()) / 2);
mErrorRect = new Rectangle(3, y + (mLineSpacing / 2) - 2, mErrorImage.getWidth(), mErrorImage.getHeight());
}
public void printLine(String text, Graphics2D g2, int lineNumber, int startIndex)
{
FontMetrics fontmetrics = g2.getFontMetrics();
int currentWidth = 0;
for (int i = 0; i < text.length(); i++)
{
char c = text.charAt(i);
HighlightElement element = getCharHighlightElement(startIndex + i);
g2.setColor(Color.black);
if (element != null)
{
Color color = element.mColor;
if (color != null)
g2.setColor(color);
}
g2.drawString(c + "", this.mInsets.left + currentWidth, mInsets.top + ((mLineHeight + mLineSpacing) * lineNumber) + mLineHeight + (mLineHeight / 2));
currentWidth += fontmetrics.charWidth(c);
}
}
public void setCaretPositionVisibile(boolean b)
{
mDrawCaretPosition = b;
}
@Override
public void setDimBackground(boolean b)
{
mDimBackground = b;
if (b) {
Color bgc = new Color(220, 220, 220);
setBackground(bgc);
getParent().setBackground(bgc);
}
else {
setBackground(Color.white);
getParent().setBackground(Color.white);
}
getParent().repaint();
}
public void setHighlightElements(ArrayList<HighlightElement> highlightElements)
{
mHighlightElements = highlightElements;
this.repaint();
}
public void setInsets(Insets insets)
{
mInsets = insets;
}
public void setPreferredSize(Dimension dimension)
{
mPreferredDimension = dimension;
}
@SuppressWarnings("unchecked")
@Override
public void setSpotlights(HashSet<? extends Spotlight> spotlights)
{
mSpotlights = (HashSet<RadialSpotlight>) spotlights;
getParent().repaint();
}
String textCache = "";
public void setText(final String text)
{
if (text == null)
{
throw new RuntimeException("Text cannot be null!");
}
// DBSelection sel = getCacheDifference(text, textCache);
new Thread(new Runnable()
{
@Override
public void run()
{
int waitIterations = 0;
while (mDocumentModel == null && waitIterations < 20)
{
try
{
Thread.sleep(100);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
mDocumentModel.setText(text);
updateUIOnChange(false);
}
}).start();
}
public void updateUIOnChange(boolean parseUpdate)
{
if (this.mDocumentModel != null)
{
if (parseUpdate)
{
TextPanel.getInstance().resetErrors();
if(DMSimplePanel.hasInstance() && !DMSimplePanel.getInstance().isPlaying() && DMSimplePanel.getInstance().isStoppedAndEmpty())
JsEngine.getInstance().executeCode(TextPanel.getInstance(), TextPanel.getInstance().getDocument().getText(), true);
else
JsEngine.getInstance().executeCode(TextPanel.getInstance(), TextPanel.getInstance().getDocument().getText(), false);
}
int width = this.getWidth();
int height = this.mInsets.top + (this.mDocumentModel.getNumberOfLines() * (this.mLineHeight + this.mLineSpacing)) + this.mInsets.bottom;
this.mPreferredDimension = new Dimension(width, height);
this.setSize(mPreferredDimension);
setHighlightElements(JSUtils.getHighlightElements(this.getText()));
getParent().repaint();
}
}
public void clearDocumentError()
{
mDocumentError = null;
mErrorRect = null;
}
public void setCaretPosition(int x, int y)
{
this.mCaret.setMarkCharPosition(new Point(x, y));
this.mCaret.setDotCharPosition(new Point(x, y));
}
public void setLineHeight(int newLineHeight)
{
mLineHeight = newLineHeight;
}
}