001    package nl.cwi.sen1.tide.tool.srcviewer;
002    
003    import java.awt.Color;
004    import java.awt.Dimension;
005    import java.awt.FontMetrics;
006    import java.awt.Graphics;
007    import java.awt.Polygon;
008    import java.awt.Rectangle;
009    import java.util.HashMap;
010    import java.util.Map;
011    
012    import javax.swing.JComponent;
013    import javax.swing.JTextArea;
014    
015    import nl.cwi.sen1.tide.tool.support.Rule;
016    
017    class LineNumberCanvas extends JComponent {
018            private final static int BORDER = 2;
019            JTextArea text;
020            FontMetrics fontMetrics;
021            FontMetrics sourceMetrics;
022    
023            int cpe;
024    
025            Map<Rule, Integer> rulesByRule;
026            Map<Integer, Rule> rulesByLine;
027    
028            Polygon rulePoly;
029    
030            //{{{ public LineNumberCanvas(JTextArea text)
031    
032            public LineNumberCanvas(JTextArea text) {
033                    this.text = text;
034                    rulesByRule = new HashMap<Rule, Integer>();
035                    rulesByLine = new HashMap<Integer, Rule>();
036            }
037    
038            //}}}
039    
040            //{{{ private void checkMetrics()
041    
042            private void checkMetrics() {
043                    if (fontMetrics != getFontMetrics(getFont())
044                            || sourceMetrics != text.getFontMetrics(text.getFont())) {
045                            fontMetrics = getFontMetrics(getFont());
046                            sourceMetrics = text.getFontMetrics(text.getFont());
047    
048                            rulePoly = new Polygon();
049                            rulePoly.addPoint(0, 0);
050                            rulePoly.addPoint(
051                                    fontMetrics.stringWidth("1999"),
052                                    sourceMetrics.getHeight() / 2);
053                            rulePoly.addPoint(0, sourceMetrics.getHeight());
054                    }
055            }
056    
057            //}}}
058    
059            //{{{ public void paint(Graphics g)
060    
061            public void paint(Graphics g) {
062                    Dimension dim = getSize();
063                    Rectangle clip = g.getClipBounds();
064    
065                    checkMetrics();
066    
067                    g.setColor(getBackground());
068                    g.fillRect(clip.x, clip.y, clip.width, clip.height);
069    
070                    int line = clip.y / sourceMetrics.getHeight();
071                    int y = line * sourceMetrics.getHeight();
072                    line++;
073    
074                    while (y < (clip.y + clip.height)) {
075                            if (line == cpe) {
076                                    g.setColor(SourceFileViewer.COLOR_CPE);
077                                    g.fillRect(0, y, clip.width, sourceMetrics.getHeight());
078                            }
079    
080                            Rule rule = rulesByLine.get(new Integer(line));
081                            if (rule != null) {
082                                    g.setColor(getRuleColor(rule));
083                                    Polygon rulePoly = getRulePoly(rule);
084                                    rulePoly.translate(0, y);
085                                    g.fillPolygon(rulePoly);
086                                    rulePoly.translate(0, -y);
087                            }
088    
089                            g.setColor(getForeground());
090                            String label = String.valueOf(line++);
091                            g.drawString(
092                                    label,
093                                    dim.width - fontMetrics.stringWidth(label) - BORDER,
094                                    y + sourceMetrics.getMaxAscent());
095                            y += sourceMetrics.getHeight();
096                    }
097    
098            }
099    
100            //}}}
101            //{{{ public Dimension getPreferredSize()
102    
103            public Dimension getPreferredSize() {
104                    checkMetrics();
105    
106                    return new Dimension(fontMetrics.stringWidth("1999") + BORDER, 0);
107            }
108    
109            //}}}
110            //{{{ public Dimension getMinimumSize()
111    
112            public Dimension getMinimumSize() {
113                    return getPreferredSize();
114            }
115    
116            //}}}
117    
118            //{{{ public void setCpe(int line)
119    
120            public void setCpe(int line) {
121                    cpe = line;
122                    repaint();
123            }
124    
125            //}}}
126            //{{{ public void clearCpe()
127    
128            public void clearCpe() {
129                    cpe = -1;
130                    repaint();
131            }
132    
133            //}}}
134    
135            //{{{ public void addLocationRule(Rule rule, int line)
136    
137            public void addLocationRule(Rule rule, int line) {
138                    rulesByRule.put(rule, new Integer(line));
139                    rulesByLine.put(new Integer(line), rule);
140            }
141    
142            //}}}
143            //{{{ public void removeLocationRule(Rule rule)
144    
145            public void removeLocationRule(Rule rule) {
146                    Integer line = rulesByRule.remove(rule);
147                    if (line != null) {
148                            rulesByLine.remove(line);
149                    }
150            }
151    
152            //}}}
153    
154            //{{{ public Color getRuleColor(Rule rule)
155    
156            public Color getRuleColor(Rule rule) {
157                    if (rule.isBreakpoint()) {
158                            return SourceFileViewer.COLOR_BREAKPOINT;
159                    }
160    
161                    return SourceFileViewer.COLOR_WATCHPOINT;
162            }
163    
164            //}}}
165    
166            //{{{ public Polygon getRulePoly(Rule rule)
167    
168            public Polygon getRulePoly(Rule rule) {
169                    return rulePoly;
170            }
171    
172            //}}}
173    
174    }