package ui;
import java.awt.Adjustable;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ToolTipManager;
import javax.swing.text.Element;
import javax.swing.text.JTextComponent;
import javax.swing.text.StyledEditorKit;
import languages.LanguageScannerException;
public class CompoundEditorPane extends JPanel {
private class Mark {
public int position;
public String message;
public int start;
public int end;
public Mark (int position, String message, int start, int end) {
this.position = position;
this.message = message;
this.start = start;
this.end = end;
}
};
private class SideBar extends JComponent {
private JScrollPane scrollPane;
private int fontHeight;
private int adjust;
private int inset;
private Mark[] marks = null;
private JTextComponent textComponent = null;
public SideBar (JScrollPane scrollPane, Font font, int inset) {
super ();
adjust = 0;
this.inset = inset;
scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
Adjustable adjustable = e.getAdjustable();
adjust = adjustable.getValue();
repaint ();
}
});
this.scrollPane = scrollPane;
FontMetrics fm = getFontMetrics (font);
this.fontHeight = fm.getHeight();
this.addMouseListener(new MouseAdapter() {
public void mousePressed (MouseEvent event) {
if (marks != null) {
for (Mark m : marks) {
int y = m.position * fontHeight;
Rectangle r = new Rectangle (0, y - fontHeight / 2, 16, fontHeight);
if (r.contains(event.getX(), event.getY())) {
textComponent.setSelectionStart (m.start);
textComponent.setSelectionEnd(m.end);
return;
}
}
}
}
});
}
public void setTextComponent (JTextComponent textComponent) {
this.textComponent = textComponent;
}
public void setMarks (Mark[] marks) {
this.marks = marks;
}
public void paintMark (Graphics gr, int y) {
y -= adjust + inset;
gr.drawImage(errorIcon.getImage(), 0, y - 8, getBackground(), this);
}
public void paintComponent (Graphics gr) {
gr.setColor(getBackground ());
gr.fillRect(0, 0, getWidth(), getHeight ());
if (marks != null) {
for (Mark mark : marks) {
paintMark (gr, mark.position * fontHeight);
}
}
}
@Override
public String getToolTipText(MouseEvent event) {
if (marks != null) {
for (Mark m : marks) {
int y = m.position * fontHeight;
Rectangle r = new Rectangle (0, y - fontHeight / 2, 16, fontHeight);
if (r.contains(event.getX(), event.getY())) {
return m.message;
}
}
}
return super.getToolTipText(event);
}
}
private SideBar sideBar;
private JEditorPane editorPane;
private JScrollPane scrollPane;
private MLStyledDocument document;
public static ImageIcon errorIcon= null;
public CompoundEditorPane() {
super ();
setLayout (new BorderLayout());
if (CompoundEditorPane.errorIcon == null) {
try {
URL url = CompoundEditorPane.class.getResource("icons/error.gif");
errorIcon = new ImageIcon (url);
}
catch (Exception e) {
e.printStackTrace();
}
}
this.scrollPane = new JScrollPane ();
this.editorPane = new MLStyledEditor();
this.editorPane.setEditorKit(new StyledEditorKit());
document = new MLStyledDocument ();
this.editorPane.setDocument(document);
this.editorPane.setAutoscrolls(false);
int inset = this.scrollPane.getInsets().top +
this.scrollPane.getViewport().getInsets().top +
this.editorPane.getInsets().top;
this.sideBar = new SideBar (this.scrollPane, this.editorPane.getFont(), inset);
this.sideBar.setTextComponent(editorPane);
this.sideBar.setPreferredSize(new Dimension(16, scrollPane.getHeight()));
ToolTipManager.sharedInstance().registerComponent(this.sideBar);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setViewportView (editorPane);
add (sideBar, BorderLayout.WEST);
add (scrollPane, BorderLayout.CENTER);
document.addPropertyChangeListener("exceptions", new PropertyChangeListener() {
public void propertyChange (PropertyChangeEvent event) {
buildMarks ();
}
});
buildMarks ();
}
private void buildMarks () {
LanguageScannerException[] excs = document.getExceptions();
int i = -1;
int count = 0;
Element root = document.getDefaultRootElement();
for (LanguageScannerException e : excs) {
int line = root.getElementIndex(e.getLeft());
if (i == line) continue;
++count;
i = line;
}
Mark[] marks = new Mark[count];
i = -1;
count = 0;
for (LanguageScannerException e : excs) {
int line = root.getElementIndex(e.getLeft ());
if (i == line) continue;
marks [count++] = new Mark (line + 1, e.getMessage(), e.getLeft(), e.getRight ());
}
sideBar.setMarks(marks);
sideBar.repaint();
}
public JEditorPane getEditorPane () {
return this.editorPane;
}
}