Source Code Cross Referenced for TextAreaPainter.java in  » Database-Client » SQL-Workbench » workbench » gui » editor » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database Client » SQL Workbench » workbench.gui.editor 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * TextAreaPainter.java - Paints the text area
003:         * Copyright (C) 1999 Slava Pestov
004:         *
005:         * You may use and modify this package for any purpose. Redistribution is
006:         * permitted, in both source and binary form, provided that this notice
007:         * remains intact in all source distributions of this package.
008:         */
009:        package workbench.gui.editor;
010:
011:        import java.awt.Color;
012:        import java.awt.Cursor;
013:        import java.awt.Font;
014:        import java.awt.FontMetrics;
015:        import java.awt.Graphics;
016:        import java.awt.Rectangle;
017:        import java.beans.PropertyChangeEvent;
018:        import java.beans.PropertyChangeListener;
019:
020:        import javax.swing.JComponent;
021:        import javax.swing.text.PlainDocument;
022:        import javax.swing.text.Segment;
023:        import javax.swing.text.TabExpander;
024:        import javax.swing.text.Utilities;
025:        import workbench.resource.Settings;
026:        import workbench.util.NumberStringCache;
027:        import workbench.util.StringUtil;
028:
029:        /**
030:         * The text area repaint manager. It performs double buffering and paints
031:         * lines of text.
032:         * @author Slava Pestov
033:         */
034:        public class TextAreaPainter extends JComponent implements  TabExpander,
035:                PropertyChangeListener {
036:            int currentLineIndex;
037:            Token currentLineTokens;
038:            Segment currentLine;
039:
040:            // protected members
041:            protected JEditTextArea textArea;
042:            protected SyntaxStyle[] styles;
043:            protected Color caretColor;
044:            protected Color selectionColor;
045:            protected Color bracketHighlightColor;
046:            protected Color errorColor;
047:            protected Color currentLineColor;
048:
049:            protected boolean bracketHighlight;
050:
051:            protected int tabSize = -1;
052:            protected FontMetrics fm;
053:
054:            protected boolean showLineNumbers = false;
055:            protected int gutterWidth = 0;
056:            protected int gutterCharWidth = 0;
057:
058:            protected static final int GUTTER_MARGIN = 2;
059:            private static final Color GUTTER_BACKGROUND = new Color(238, 240,
060:                    238);
061:            private static final Color GUTTER_COLOR = Color.DARK_GRAY;
062:
063:            public TextAreaPainter(JEditTextArea textArea) {
064:                this .textArea = textArea;
065:
066:                setDoubleBuffered(true);
067:                setOpaque(true);
068:
069:                currentLine = new Segment();
070:                currentLineIndex = -1;
071:
072:                setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
073:
074:                setFont(new Font("Monospaced", Font.PLAIN, 12));
075:                setForeground(Color.BLACK);
076:                setBackground(Color.WHITE);
077:
078:                caretColor = Color.BLACK;
079:                errorColor = Settings.getInstance().getEditorErrorColor();
080:                selectionColor = Settings.getInstance()
081:                        .getEditorSelectionColor();
082:                currentLineColor = Settings.getInstance()
083:                        .getEditorCurrentLineColor();
084:                bracketHighlightColor = Color.BLACK;
085:                bracketHighlight = true;
086:                Settings.getInstance().addPropertyChangeListener(this ,
087:                        Settings.PROPERTY_EDITOR_TAB_WIDTH,
088:                        Settings.PROPERTY_EDITOR_CURRENT_LINE_COLOR);
089:            }
090:
091:            public void dispose() {
092:                Settings.getInstance().removePropertyChangeListener(this );
093:            }
094:
095:            public void propertyChange(PropertyChangeEvent evt) {
096:                if (Settings.PROPERTY_EDITOR_TAB_WIDTH.equals(evt
097:                        .getPropertyName())) {
098:                    this .calculateTabSize();
099:                } else if (Settings.PROPERTY_EDITOR_CURRENT_LINE_COLOR
100:                        .equals(evt.getPropertyName())) {
101:                    this .currentLineColor = Settings.getInstance()
102:                            .getEditorCurrentLineColor();
103:                    invalidate();
104:                }
105:            }
106:
107:            /**
108:             * Switches display of line numbers in the left gutter area.
109:             *
110:             * @param aFlag
111:             */
112:            public final void setShowLineNumbers(boolean aFlag) {
113:                this .showLineNumbers = aFlag;
114:                this .invalidate();
115:            }
116:
117:            public final boolean getShowLineNumbers() {
118:                return this .showLineNumbers;
119:            }
120:
121:            /**
122:             * Returns if this component can be traversed by pressing the
123:             * Tab key. This returns false.
124:             */
125:            @SuppressWarnings("deprecation")
126:            public final boolean isManagingFocus() {
127:                return false;
128:            }
129:
130:            /**
131:             * Returns the syntax styles used to paint colorized text. Entry <i>n</i>
132:             * will be used to paint tokens with id = <i>n</i>.
133:             * @see Token
134:             */
135:            public final SyntaxStyle[] getStyles() {
136:                return styles;
137:            }
138:
139:            /**
140:             * Sets the syntax styles used to paint colorized text. Entry <i>n</i>
141:             * will be used to paint tokens with id = <i>n</i>.
142:             * @param styles The syntax styles
143:             * @see Token
144:             */
145:            public final void setStyles(SyntaxStyle[] styles) {
146:                this .styles = styles;
147:                repaint();
148:            }
149:
150:            /**
151:             * Returns the caret color.
152:             */
153:            public final Color getCaretColor() {
154:                return caretColor;
155:            }
156:
157:            /**
158:             * Sets the caret color.
159:             * @param caretColor The caret color
160:             */
161:            public final void setCaretColor(Color caretColor) {
162:                this .caretColor = caretColor;
163:                invalidateSelectedLines();
164:            }
165:
166:            /**
167:             * Returns the selection color.
168:             */
169:            public final Color getSelectionColor() {
170:                return selectionColor;
171:            }
172:
173:            /**
174:             * Sets the selection color.
175:             * @param selectionColor The selection color
176:             */
177:            public final void setSelectionColor(Color selectionColor) {
178:                this .selectionColor = selectionColor;
179:                invalidateSelectedLines();
180:            }
181:
182:            /**
183:             * Returns the bracket highlight color.
184:             */
185:            public final Color getBracketHighlightColor() {
186:                return bracketHighlightColor;
187:            }
188:
189:            /**
190:             * Sets the bracket highlight color.
191:             * @param bracketHighlightColor The bracket highlight color
192:             */
193:            public final void setBracketHighlightColor(
194:                    Color bracketHighlightColor) {
195:                this .bracketHighlightColor = bracketHighlightColor;
196:                invalidateLine(textArea.getBracketLine());
197:            }
198:
199:            /**
200:             * Returns true if bracket highlighting is enabled, false otherwise.
201:             * When bracket highlighting is enabled, the bracket matching the
202:             * one before the caret (if any) is highlighted.
203:             */
204:            public final boolean isBracketHighlightEnabled() {
205:                return bracketHighlight;
206:            }
207:
208:            /**
209:             * Enables or disables bracket highlighting.
210:             * When bracket highlighting is enabled, the bracket matching the
211:             * one before the caret (if any) is highlighted.
212:             * @param bracketHighlight True if bracket highlighting should be
213:             * enabled, false otherwise
214:             */
215:            public final void setBracketHighlightEnabled(
216:                    boolean bracketHighlight) {
217:                this .bracketHighlight = bracketHighlight;
218:                invalidateLine(textArea.getBracketLine());
219:            }
220:
221:            /**
222:             * Returns the font metrics used by this component.
223:             */
224:            public FontMetrics getFontMetrics() {
225:                if (fm == null) {
226:                    this .fm = getFontMetrics(getFont());
227:                }
228:                return fm;
229:            }
230:
231:            /**
232:             * Sets the font for this component. This is overridden to update the
233:             * cached font metrics and to recalculate which lines are visible.
234:             * @param font The font
235:             */
236:            public void setFont(Font font) {
237:                super .setFont(font);
238:                this .fm = getFontMetrics(font);
239:                calculateTabSize();
240:                calculateGutterWidth();
241:            }
242:
243:            private void calculateGutterWidth() {
244:                FontMetrics cfm = getFontMetrics();
245:                if (cfm == null) {
246:                    this .gutterCharWidth = 18;
247:                } else {
248:                    this .gutterCharWidth = cfm.charWidth('9');
249:                }
250:                if (this .showLineNumbers) {
251:                    int lastLine = textArea.getLineCount();
252:                    int chars = StringUtil.numDigits(lastLine);
253:                    this .gutterWidth = (chars * gutterCharWidth)
254:                            + (GUTTER_MARGIN * 2);
255:                } else {
256:                    this .gutterWidth = 0;
257:                }
258:            }
259:
260:            public void calculateTabSize() {
261:                this .tabSize = -1;
262:                if (this .textArea == null)
263:                    return;
264:                if (this .textArea.getDocument() == null)
265:                    return;
266:                FontMetrics cfm = this .getFontMetrics();
267:                if (cfm == null)
268:                    return;
269:
270:                Object tab = textArea.getDocument().getProperty(
271:                        PlainDocument.tabSizeAttribute);
272:                int t = -1;
273:                if (tab == null) {
274:                    t = Settings.getInstance().getEditorTabWidth();
275:                } else {
276:                    Integer tsize = (Integer) tab;
277:                    t = tsize.intValue();
278:                }
279:                this .tabSize = cfm.charWidth(' ') * t;
280:            }
281:
282:            public void paint(Graphics gfx) {
283:
284:                calculateGutterWidth();
285:
286:                Rectangle clipRect = gfx.getClipBounds();
287:
288:                if (clipRect != null) {
289:                    gfx.setColor(this .getBackground());
290:                    gfx.fillRect(clipRect.x, clipRect.y, clipRect.width,
291:                            clipRect.height);
292:
293:                    if (this .showLineNumbers) {
294:                        gfx.setColor(GUTTER_BACKGROUND);
295:                        gfx.fillRect(clipRect.x, clipRect.y, gutterWidth
296:                                - clipRect.x, clipRect.height);
297:                    }
298:                }
299:
300:                final int lastLine = textArea.getLineCount();
301:                final int visibleCount = textArea.getVisibleLines();
302:                final int firstVisible = textArea.getFirstLine();
303:
304:                int fheight = fm.getHeight();
305:                int firstInvalid = firstVisible + clipRect.y / fheight;
306:                int lastInvalid = firstVisible
307:                        + ((clipRect.y + clipRect.height) / fheight) + 1;
308:                if (lastInvalid > lastLine)
309:                    lastInvalid = lastLine;
310:
311:                try {
312:                    TokenMarker tokenMarker = textArea.getDocument()
313:                            .getTokenMarker();
314:                    int x = textArea.getHorizontalOffset();
315:
316:                    int endLine = firstVisible + visibleCount;
317:                    if (endLine > lastLine)
318:                        endLine = lastLine;
319:
320:                    int cw = this .getWidth() - gutterWidth;
321:                    int ch = getHeight();
322:                    int gutterX = this .gutterWidth - GUTTER_MARGIN;
323:
324:                    final int caretLine = textArea.getCaretLine();
325:
326:                    for (int line = firstVisible; line <= endLine; line++) {
327:                        int y = textArea.lineToY(line);
328:
329:                        if (this .showLineNumbers) {
330:                            // It seems that the Objects created by Integer.toString()
331:                            // that are passed to drawString() are not collected
332:                            // correctly (as seen in the profiler). So each time
333:                            // the editor gets redrawn a small amount of memory is lost
334:                            // To workaround this, I'm caching (some of) the values 
335:                            // that are needed here.
336:
337:                            String s = NumberStringCache.getNumberString(line);
338:                            int w = s.length() * this .gutterCharWidth;
339:                            gfx.setColor(GUTTER_COLOR);
340:                            gfx.drawString(s, gutterX - w, y);
341:                        }
342:
343:                        if (line >= firstInvalid && line < lastInvalid) {
344:                            if (this .showLineNumbers) {
345:                                gfx.setClip(this .gutterWidth, 0, cw, ch);
346:                                gfx.translate(this .gutterWidth, 0);
347:                            }
348:
349:                            if (line == caretLine
350:                                    && this .currentLineColor != null) {
351:                                gfx.setColor(currentLineColor);
352:                                gfx.fillRect(0, y + fm.getLeading()
353:                                        + fm.getMaxDescent(), getWidth(),
354:                                        fheight);
355:                                gfx.setColor(getBackground());
356:                            }
357:
358:                            paintLine(gfx, tokenMarker, line, y, x);
359:
360:                            if (this .showLineNumbers) {
361:                                gfx.translate(-this .gutterWidth, 0);
362:                                gfx.setClip(null);
363:                            }
364:                        }
365:                    }
366:                } catch (Exception e) {
367:                    System.err.println("Error repainting line range {"
368:                            + firstInvalid + "," + lastInvalid + "}:"
369:                            + e.getMessage());
370:                    //e.printStackTrace();
371:                }
372:            }
373:
374:            /**
375:             * Marks a line as needing a repaint.
376:             * @param line The line to invalidate
377:             */
378:            public final void invalidateLine(int line) {
379:                repaint(0, textArea.lineToY(line) + fm.getMaxDescent()
380:                        + fm.getLeading(), getWidth(), fm.getHeight());
381:            }
382:
383:            public int getGutterWidth() {
384:                return this .gutterWidth; // + GUTTER_MARGIN;
385:            }
386:
387:            /**
388:             * Marks a range of lines as needing a repaint.
389:             * @param firstLine The first line to invalidate
390:             * @param lastLine The last line to invalidate
391:             */
392:            public final void invalidateLineRange(int firstLine, int lastLine) {
393:                repaint(0, textArea.lineToY(firstLine) + fm.getMaxDescent()
394:                        + fm.getLeading(), getWidth(),
395:                        (lastLine - firstLine + 1) * fm.getHeight());
396:            }
397:
398:            /**
399:             * Repaints the lines containing the selection.
400:             */
401:            public final void invalidateSelectedLines() {
402:                invalidateLineRange(textArea.getSelectionStartLine(), textArea
403:                        .getSelectionEndLine());
404:            }
405:
406:            /**
407:             * Implementation of TabExpander interface. Returns next tab stop after
408:             * a specified point.
409:             * @param x The x co-ordinate
410:             * @param tabOffset Ignored
411:             * @return The next tab stop after <i>x</i>
412:             */
413:            public float nextTabStop(float x, int tabOffset) {
414:                if (tabSize == -1) {
415:                    this .calculateTabSize();
416:                }
417:                int offset = textArea.getHorizontalOffset();
418:                int ntabs = ((int) x - offset) / tabSize;
419:                return (ntabs + 1) * tabSize + offset;
420:            }
421:
422:            protected void paintLine(Graphics gfx, TokenMarker tokenMarker,
423:                    int line, int y, int x) {
424:                Font defaultFont = getFont();
425:                Color defaultColor = getForeground();
426:
427:                currentLineIndex = line;
428:
429:                if (tokenMarker == null) {
430:                    paintPlainLine(gfx, line, defaultFont, defaultColor, x, y);
431:                } else {
432:                    paintSyntaxLine(gfx, tokenMarker, line, defaultFont,
433:                            defaultColor, x, y);
434:                }
435:            }
436:
437:            protected void paintPlainLine(Graphics gfx, int line,
438:                    Font defaultFont, Color defaultColor, int x, int y) {
439:                textArea.getLineText(line, currentLine);
440:
441:                paintHighlight(gfx, line, y);
442:
443:                gfx.setFont(defaultFont);
444:                gfx.setColor(defaultColor);
445:
446:                y += fm.getHeight();
447:                Utilities.drawTabbedText(currentLine, x, y, gfx, this , 0);
448:            }
449:
450:            protected void paintSyntaxLine(Graphics gfx,
451:                    TokenMarker tokenMarker, int line, Font defaultFont,
452:                    Color defaultColor, int x, int y) {
453:                textArea.getLineText(line, currentLine);
454:
455:                currentLineTokens = tokenMarker.markTokens(currentLine, line);
456:
457:                paintHighlight(gfx, line, y);
458:
459:                gfx.setFont(defaultFont);
460:                gfx.setColor(defaultColor);
461:                y += fm.getHeight();
462:                SyntaxUtilities.paintSyntaxLine(currentLine, currentLineTokens,
463:                        styles, this , gfx, x, y, 0);
464:            }
465:
466:            protected void paintHighlight(Graphics gfx, int line, int y) {
467:                if (line >= textArea.getSelectionStartLine()
468:                        && line <= textArea.getSelectionEndLine()) {
469:                    paintLineHighlight(gfx, line, y);
470:                }
471:
472:                if (bracketHighlight && line == textArea.getBracketLine()) {
473:                    paintBracketHighlight(gfx, line, y);
474:                }
475:
476:                if (line == textArea.getCaretLine()) {
477:                    paintCaret(gfx, line, y);
478:                }
479:            }
480:
481:            protected void paintLineHighlight(Graphics gfx, int line, int y) {
482:                int selectionStart = textArea.getSelectionStart();
483:                int selectionEnd = textArea.getSelectionEnd();
484:
485:                if (selectionStart == selectionEnd)
486:                    return;
487:
488:                int height = fm.getHeight();
489:                y += fm.getLeading() + fm.getMaxDescent();
490:
491:                Color c = this .textArea.getAlternateSelectionColor();
492:                if (c != null) {
493:                    gfx.setColor(c);
494:                } else {
495:                    gfx.setColor(selectionColor);
496:                }
497:
498:                int selectionStartLine = textArea.getSelectionStartLine();
499:                int selectionEndLine = textArea.getSelectionEndLine();
500:                int lineStart = textArea.getLineStartOffset(line);
501:
502:                int x1, x2;
503:                if (textArea.isSelectionRectangular()) {
504:                    int lineLen = textArea.getLineLength(line);
505:                    x1 = textArea
506:                            ._offsetToX(
507:                                    line,
508:                                    Math
509:                                            .min(
510:                                                    lineLen,
511:                                                    selectionStart
512:                                                            - textArea
513:                                                                    .getLineStartOffset(selectionStartLine)));// + this.gutterWidth;
514:                    x2 = textArea
515:                            ._offsetToX(
516:                                    line,
517:                                    Math
518:                                            .min(
519:                                                    lineLen,
520:                                                    selectionEnd
521:                                                            - textArea
522:                                                                    .getLineStartOffset(selectionEndLine)));// + this.gutterWidth;
523:                    if (x1 == x2)
524:                        x2++;
525:                } else if (selectionStartLine == selectionEndLine) {
526:                    x1 = textArea._offsetToX(line, selectionStart - lineStart);
527:                    x2 = textArea._offsetToX(line, selectionEnd - lineStart);
528:                } else if (line == selectionStartLine) {
529:                    x1 = textArea._offsetToX(line, selectionStart - lineStart);
530:                    x2 = getWidth();
531:                } else if (line == selectionEndLine) {
532:                    x1 = 0;
533:                    x2 = textArea._offsetToX(line, selectionEnd - lineStart);
534:                } else {
535:                    x1 = 0; //gutterWidth;
536:                    x2 = getWidth();
537:                }
538:
539:                // "inlined" min/max()
540:                gfx.fillRect(x1 > x2 ? x2 : x1, y, x1 > x2 ? (x1 - x2)
541:                        : (x2 - x1), height);
542:
543:            }
544:
545:            protected void paintBracketHighlight(Graphics gfx, int line, int y) {
546:                int position = textArea.getBracketPosition();
547:                if (position == -1)
548:                    return;
549:
550:                y += fm.getLeading() + fm.getMaxDescent();
551:                int x = textArea._offsetToX(line, position);// + this.gutterWidth;
552:                gfx.setColor(bracketHighlightColor);
553:                // Hack!!! Since there is no fast way to get the character
554:                // from the bracket matching routine, we use ( since all
555:                // brackets probably have the same width anyway
556:                gfx.drawRect(x, y, fm.charWidth('(') - 1, fm.getHeight() - 1);
557:            }
558:
559:            protected void paintCaret(Graphics gfx, int line, int y) {
560:                if (textArea.isCaretVisible()) {
561:                    int offset = textArea.getCaretPosition()
562:                            - textArea.getLineStartOffset(line);
563:                    int caretX = textArea._offsetToX(line, offset);// + this.gutterWidth;
564:                    int caretWidth = (textArea.isOverwriteEnabled() ? fm
565:                            .charWidth('w') : 2);
566:                    y += fm.getLeading() + fm.getMaxDescent();
567:                    int height = fm.getHeight();
568:
569:                    gfx.setColor(caretColor);
570:
571:                    if (textArea.isOverwriteEnabled()) {
572:                        gfx.fillRect(caretX, y + height - 1, caretWidth, 1);
573:                    } else {
574:                        gfx.drawRect(caretX, y, caretWidth - 1, height - 1);
575:                    }
576:                }
577:            }
578:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.