package com.drawbridge.text; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Insets; import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.HashSet; import javax.swing.BorderFactory; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import com.drawbridge.Main; import com.drawbridge.correspondance.RadialSpotlight; import com.drawbridge.correspondance.Spotlight; import com.drawbridge.jsengine.ast.DBParser; import com.drawbridge.jsengine.ast.Evaluator; import com.drawbridge.jsengine.ast.ParserListener; import com.drawbridge.utils.JSUtils; import com.drawbridge.utils.SegmentPanel; import com.drawbridge.utils.TitlePanel; import com.drawbridge.utils.Utils; import com.google.caja.lexer.FilePosition; public class TextPanel extends SegmentPanel implements ParserListener { private static final long serialVersionUID = 1L; private JScrollPane mScrollPane = null; private static TextPanel mInstance = null; private DBDocument mDocument = null; private Insets mInsets = new Insets(0, 30, 0, 50); public static TextPanel getInstance() { if (mInstance != null) { return mInstance; } else { mInstance = new TextPanel(); return mInstance; } } public static void reset() { mInstance = null; } public JScrollPane getScrollBar() { return mScrollPane; } public TextPanel() { // Enable Anti-Aliased Text: System.setProperty("awt.useSystemAAFontSettings", "on"); System.setProperty("swing.aatext", "true"); this.setFont(Main.mainFont); mDocument = new DBDocument("", Main.mainFont, true); setLayout(new BorderLayout()); TitlePanel mTitlePanel = new TitlePanel("Text Panel"); this.add(mTitlePanel, BorderLayout.NORTH); mScrollPane = new JScrollPane(mDocument); mScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); mScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); mScrollPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); mScrollPane.getViewport().addChangeListener(Utils.synchronizedScrollingListener); mScrollPane.setBackground(Color.white); mScrollPane.setOpaque(false); add(mScrollPane, BorderLayout.CENTER); mScrollPane.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent me) { me.setSource(mDocument); mDocument.dispatchEvent(me); } @Override public void mouseReleased(MouseEvent me) { me.setSource(mDocument); mDocument.dispatchEvent(me); } }); mScrollPane.addMouseMotionListener(new MouseAdapter() { @Override public void mouseDragged(MouseEvent me) { me.setSource(mDocument); mDocument.dispatchEvent(me); } }); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { while (TextPanel.this.getWidth() <= 0) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } Dimension preferredSize = new Dimension(mScrollPane.getWidth() - 20, mScrollPane.getHeight() - mInsets.top - mInsets.bottom - 50); mDocument.setPreferredSize(preferredSize); mDocument.setLocation(0, 0); } }); } public JScrollPane getJsArea() { return mScrollPane; } public DBDocument getDocument() { return this.mDocument; } public void setText(Class<?> callerClass, String code) { if (this.getDocument() == null) { throw new RuntimeException("JsPanel Document object was null"); } else { Utils.out.println(this.getClass(), "TextPanel setText from:" + callerClass.getSimpleName()); getDocument().setText(code); } } public static boolean hasInstance() { return (mInstance != null); } @Override public void onParserChange() { Utils.out.println(this.getClass(), "onParserChange TextPanel"); // Do a diff to find areas of change this.getDocument().setText(DBParser.getInstance().getSnapshot()); //Filter out all but integer literals HashSet<Evaluator> rcEvals = DBParser.getInstance().mRecentlyChangedEvaluators; if(rcEvals != null){ HashSet<Spotlight> spotlights = new HashSet<Spotlight>(); for(Evaluator e : rcEvals){ FilePosition fp = e.getFilePosition(); Point pointInParent = getDocument().getDocumentModel().getCoordinatesOfChar(new Point(fp.startCharInLine() - 1, fp.startLineNo() - 1)); if (pointInParent != null) { int x = pointInParent.x; int y = pointInParent.y; Point charStart = getDocument().getDocumentModel().getCharPositionFromStringIndex(fp.startCharInFile() - 1); Point charFinish = getDocument().getDocumentModel().getCharPositionFromStringIndex(fp.endCharInFile() - 1); int width = getDocument().getDocumentModel().getSizeOf(getDocument().getDocumentModel().getRawTextSubstring(charStart, charFinish)); int height = getDocument().getLineHeight(); int radius = Math.max(1, width / 2); spotlights.add(new RadialSpotlight(x + radius, y + (height/2), radius, 30)); } } getDocument().setSpotlights(spotlights); } resetErrors(); } public void resetErrors() { this.mDocument.clearDocumentError(); this.repaint(); } @Override public void onParserException(int lineNumber, String exception) { this.setText(this.getClass(), DBParser.getInstance().getSnapshot()); this.mDocument.setDocumentError(new DocumentError(lineNumber, "Parse Exception", exception)); mDocument.setHighlightElements(JSUtils.getHighlightElements(mDocument.getText())); this.mDocument.repaint(); } // Temporary method to show current code public void moveToBottom() { JScrollBar bar = mScrollPane.getVerticalScrollBar(); bar.setValue(bar.getMaximum()); } public void moveToTop() { JScrollBar bar = mScrollPane.getVerticalScrollBar(); bar.setValue(bar.getMinimum()); } }