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());
}
}