Source Code Cross Referenced for DumbTextComponent.java in  » Internationalization-Localization » icu4j » com » ibm » icu » dev » demo » impl » 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 » Internationalization Localization » icu4j » com.ibm.icu.dev.demo.impl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *******************************************************************************
003:         * Copyright (C) 1996-2006, International Business Machines Corporation and    *
004:         * others. All Rights Reserved.                                                *
005:         *******************************************************************************
006:         */
007:        package com.ibm.icu.dev.demo.impl;
008:
009:        import java.awt.*;
010:        import java.awt.event.*;
011:        import java.text.*;
012:        import java.awt.datatransfer.*;
013:
014:        // LIU: Changed from final to non-final
015:        public class DumbTextComponent extends Canvas implements  KeyListener,
016:                MouseListener, MouseMotionListener, FocusListener {
017:            private transient static final String copyright = "Copyright \u00A9 1998, Mark Davis. All Rights Reserved.";
018:            private transient static boolean DEBUG = false;
019:
020:            private String contents = "";
021:            private Selection selection = new Selection();
022:            private int activeStart = -1;
023:            private boolean editable = true;
024:
025:            private transient Selection tempSelection = new Selection();
026:            private transient boolean focus;
027:            private transient BreakIterator lineBreaker = BreakIterator
028:                    .getLineInstance();
029:            private transient BreakIterator wordBreaker = BreakIterator
030:                    .getWordInstance();
031:            private transient BreakIterator charBreaker = BreakIterator
032:                    .getCharacterInstance();
033:            private transient int lineAscent;
034:            private transient int lineHeight;
035:            private transient int lineLeading;
036:            private transient int lastHeight = 10;
037:            private transient int lastWidth = 50;
038:            private static final int MAX_LINES = 200; // LIU: Use symbolic name
039:            private transient int[] lineStarts = new int[MAX_LINES]; // LIU
040:            private transient int lineCount = 1;
041:
042:            private transient boolean valid = false;
043:            private transient FontMetrics fm;
044:            private transient boolean redoLines = true;
045:            private transient boolean doubleClick = false;
046:            private transient TextListener textListener;
047:            private transient ActionListener selectionListener;
048:            private transient Image cacheImage;
049:            private transient Dimension mySize;
050:            private transient int xInset = 5;
051:            private transient int yInset = 5;
052:            private transient Point startPoint = new Point();
053:            private transient Point endPoint = new Point();
054:            private transient Point caretPoint = new Point();
055:            private transient Point activePoint = new Point();
056:
057:            //private transient static String clipBoard;
058:
059:            private static final char CR = '\015'; // LIU
060:
061:            // ============================================
062:
063:            public DumbTextComponent() {
064:                addMouseListener(this );
065:                addMouseMotionListener(this );
066:                addKeyListener(this );
067:                addFocusListener(this );
068:                setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
069:
070:            }
071:
072:            // ================ Events ====================
073:
074:            // public boolean isFocusTraversable() { return true; }
075:
076:            public void addActionListener(ActionListener l) {
077:                selectionListener = AWTEventMulticaster.add(selectionListener,
078:                        l);
079:            }
080:
081:            public void removeActionListener(ActionListener l) {
082:                selectionListener = AWTEventMulticaster.remove(
083:                        selectionListener, l);
084:            }
085:
086:            public void addTextListener(TextListener l) {
087:                textListener = AWTEventMulticaster.add(textListener, l);
088:            }
089:
090:            public void removeTextListener(TextListener l) {
091:                textListener = AWTEventMulticaster.remove(textListener, l);
092:            }
093:
094:            private transient boolean pressed;
095:
096:            public void mousePressed(MouseEvent e) {
097:                if (DEBUG)
098:                    System.out.println("mousePressed");
099:                if (pressed) {
100:                    select(e, false);
101:                } else {
102:                    doubleClick = e.getClickCount() > 1;
103:                    requestFocus();
104:                    select(e, true);
105:                    pressed = true;
106:                }
107:            }
108:
109:            public void mouseDragged(MouseEvent e) {
110:                if (DEBUG)
111:                    System.out.println("mouseDragged");
112:                select(e, false);
113:            }
114:
115:            public void mouseReleased(MouseEvent e) {
116:                if (DEBUG)
117:                    System.out.println("mouseReleased");
118:                pressed = false;
119:            }
120:
121:            public void mouseEntered(MouseEvent e) {
122:                //if (pressed) select(e, false);
123:            }
124:
125:            public void mouseExited(MouseEvent e) {
126:                //if (pressed) select(e, false);
127:            }
128:
129:            public void mouseClicked(MouseEvent e) {
130:            }
131:
132:            public void mouseMoved(MouseEvent e) {
133:            }
134:
135:            public void focusGained(FocusEvent e) {
136:                if (DEBUG)
137:                    System.out.println("focusGained");
138:                focus = true;
139:                valid = false;
140:                repaint(16);
141:            }
142:
143:            public void focusLost(FocusEvent e) {
144:                if (DEBUG)
145:                    System.out.println("focusLost");
146:                focus = false;
147:                valid = false;
148:                repaint(16);
149:            }
150:
151:            public void select(MouseEvent e, boolean first) {
152:                setKeyStart(-1);
153:                point2Offset(e.getPoint(), tempSelection);
154:                if (first) {
155:                    if ((e.getModifiers() & InputEvent.SHIFT_MASK) == 0) {
156:                        tempSelection.anchor = tempSelection.caret;
157:                    }
158:                }
159:                // fix words
160:                if (doubleClick) {
161:                    tempSelection.expand(wordBreaker);
162:                }
163:                select(tempSelection);
164:            }
165:
166:            public void keyPressed(KeyEvent e) {
167:                int code = e.getKeyCode();
168:                if (DEBUG)
169:                    System.out.println("keyPressed " + hex((char) code) + ", "
170:                            + hex((char) e.getModifiers()));
171:                int start = selection.getStart();
172:                int end = selection.getEnd();
173:                boolean shift = (e.getModifiers() & InputEvent.SHIFT_MASK) != 0;
174:                boolean ctrl = (e.getModifiers() & InputEvent.CTRL_MASK) != 0;
175:
176:                switch (code) {
177:                case KeyEvent.VK_Q:
178:                    if (!ctrl || !editable)
179:                        break;
180:                    setKeyStart(-1);
181:                    fixHex();
182:                    break;
183:                case KeyEvent.VK_V:
184:                    if (!ctrl)
185:                        break;
186:                    if (!editable) {
187:                        this .getToolkit().beep();
188:                    } else {
189:                        paste();
190:                    }
191:                    break;
192:                case KeyEvent.VK_C:
193:                    if (!ctrl)
194:                        break;
195:                    copy();
196:                    break;
197:                case KeyEvent.VK_X:
198:                    if (!ctrl)
199:                        break;
200:                    if (!editable) {
201:                        this .getToolkit().beep();
202:                    } else {
203:                        copy();
204:                        insertText("");
205:                    }
206:                    break;
207:                case KeyEvent.VK_A:
208:                    if (!ctrl)
209:                        break;
210:                    setKeyStart(-1);
211:                    select(Integer.MAX_VALUE, 0, false);
212:                    break;
213:                case KeyEvent.VK_RIGHT:
214:                    setKeyStart(-1);
215:                    tempSelection.set(selection);
216:                    tempSelection.nextBound(ctrl ? wordBreaker : charBreaker,
217:                            +1, shift);
218:                    select(tempSelection);
219:                    break;
220:                case KeyEvent.VK_LEFT:
221:                    setKeyStart(-1);
222:                    tempSelection.set(selection);
223:                    tempSelection.nextBound(ctrl ? wordBreaker : charBreaker,
224:                            -1, shift);
225:                    select(tempSelection);
226:                    break;
227:                case KeyEvent.VK_UP: // LIU: Add support for up arrow
228:                    setKeyStart(-1);
229:                    tempSelection.set(selection);
230:                    tempSelection.caret = lineDelta(tempSelection.caret, -1);
231:                    if (!shift) {
232:                        tempSelection.anchor = tempSelection.caret;
233:                    }
234:                    select(tempSelection);
235:                    break;
236:                case KeyEvent.VK_DOWN: // LIU: Add support for down arrow
237:                    setKeyStart(-1);
238:                    tempSelection.set(selection);
239:                    tempSelection.caret = lineDelta(tempSelection.caret, +1);
240:                    if (!shift) {
241:                        tempSelection.anchor = tempSelection.caret;
242:                    }
243:                    select(tempSelection);
244:                    break;
245:                case KeyEvent.VK_DELETE: // LIU: Add delete key support
246:                    if (!editable)
247:                        break;
248:                    setKeyStart(-1);
249:                    if (contents.length() == 0)
250:                        break;
251:                    start = selection.getStart();
252:                    end = selection.getEnd();
253:                    if (start == end) {
254:                        ++end;
255:                        if (end > contents.length()) {
256:                            getToolkit().beep();
257:                            return;
258:                        }
259:                    }
260:                    replaceRange("", start, end);
261:                    break;
262:                }
263:            }
264:
265:            void copy() {
266:                Clipboard cb = this .getToolkit().getSystemClipboard();
267:                StringSelection ss = new StringSelection(contents.substring(
268:                        selection.getStart(), selection.getEnd()));
269:                cb.setContents(ss, ss);
270:            }
271:
272:            void paste() {
273:                Clipboard cb = this .getToolkit().getSystemClipboard();
274:                Transferable t = cb.getContents(this );
275:                if (t == null) {
276:                    this .getToolkit().beep();
277:                    return;
278:                }
279:                try {
280:                    String temp = (String) t
281:                            .getTransferData(DataFlavor.stringFlavor);
282:                    insertText(temp);
283:                } catch (Exception e) {
284:                    this .getToolkit().beep();
285:                }
286:            }
287:
288:            /**
289:             * LIU: Given an offset into contents, moves up or down by lines,
290:             * according to lineStarts[].
291:             * @param off the offset into contents
292:             * @param delta how many lines to move up (< 0) or down (> 0)
293:             * @return the new offset into contents
294:             */
295:            private int lineDelta(int off, int delta) {
296:                int line = findLine(off, false);
297:                int posInLine = off - lineStarts[line];
298:                // System.out.println("off=" + off + " at " + line + ":" + posInLine);
299:                line += delta;
300:                if (line < 0) {
301:                    line = posInLine = 0;
302:                } else if (line >= lineCount) {
303:                    return contents.length();
304:                }
305:                off = lineStarts[line] + posInLine;
306:                if (off >= lineStarts[line + 1]) {
307:                    off = lineStarts[line + 1] - 1;
308:                }
309:                return off;
310:            }
311:
312:            public void keyReleased(KeyEvent e) {
313:                int code = e.getKeyCode();
314:                if (DEBUG)
315:                    System.out.println("keyReleased " + hex((char) code) + ", "
316:                            + hex((char) e.getModifiers()));
317:            }
318:
319:            public void keyTyped(KeyEvent e) {
320:                char ch = e.getKeyChar();
321:                if (DEBUG)
322:                    System.out.println("keyTyped " + hex((char) ch) + ", "
323:                            + hex((char) e.getModifiers()));
324:                if ((e.getModifiers() & InputEvent.CTRL_MASK) != 0)
325:                    return;
326:                int start, end;
327:                switch (ch) {
328:                case KeyEvent.CHAR_UNDEFINED:
329:                    break;
330:                case KeyEvent.VK_BACK_SPACE:
331:                    //setKeyStart(-1);
332:                    if (!editable)
333:                        break;
334:                    if (contents.length() == 0)
335:                        break;
336:                    start = selection.getStart();
337:                    end = selection.getEnd();
338:                    if (start == end) {
339:                        --start;
340:                        if (start < 0) {
341:                            getToolkit().beep(); // LIU: Add audio feedback of NOP
342:                            return;
343:                        }
344:                    }
345:                    replaceRange("", start, end);
346:                    break;
347:                case KeyEvent.VK_DELETE:
348:                    //setKeyStart(-1);
349:                    if (!editable)
350:                        break;
351:                    if (contents.length() == 0)
352:                        break;
353:                    start = selection.getStart();
354:                    end = selection.getEnd();
355:                    if (start == end) {
356:                        ++end;
357:                        if (end > contents.length()) {
358:                            getToolkit().beep(); // LIU: Add audio feedback of NOP
359:                            return;
360:                        }
361:                    }
362:                    replaceRange("", start, end);
363:                    break;
364:                default:
365:                    if (!editable)
366:                        break;
367:                    // LIU: Dispatch to subclass API
368:                    handleKeyTyped(e);
369:                    break;
370:                }
371:            }
372:
373:            // LIU: Subclass API for handling of key typing
374:            protected void handleKeyTyped(KeyEvent e) {
375:                insertText(String.valueOf(e.getKeyChar()));
376:            }
377:
378:            protected void setKeyStart(int keyStart) {
379:                if (activeStart != keyStart) {
380:                    activeStart = keyStart;
381:                    repaint(10);
382:                }
383:            }
384:
385:            protected void validateKeyStart() {
386:                if (activeStart > selection.getStart()) {
387:                    activeStart = selection.getStart();
388:                    repaint(10);
389:                }
390:            }
391:
392:            protected int getKeyStart() {
393:                return activeStart;
394:            }
395:
396:            // ===================== Control ======================
397:
398:            public synchronized void setEditable(boolean b) {
399:                editable = b;
400:            }
401:
402:            public boolean isEditable() {
403:                return editable;
404:            }
405:
406:            public void select(Selection newSelection) {
407:                newSelection.pin(contents);
408:                if (!selection.equals(newSelection)) {
409:                    selection.set(newSelection);
410:                    if (selectionListener != null) {
411:                        selectionListener.actionPerformed(new ActionEvent(this ,
412:                                ActionEvent.ACTION_PERFORMED,
413:                                "Selection Changed", 0));
414:                    }
415:                    repaint(10);
416:                    valid = false;
417:                }
418:            }
419:
420:            public void select(int start, int end) {
421:                select(start, end, false);
422:            }
423:
424:            public void select(int start, int end, boolean clickAfter) {
425:                tempSelection.set(start, end, clickAfter);
426:                select(tempSelection);
427:            }
428:
429:            public int getSelectionStart() {
430:                return selection.getStart();
431:            }
432:
433:            public int getSelectionEnd() {
434:                return selection.getEnd();
435:            }
436:
437:            public void setBounds(int x, int y, int w, int h) {
438:                super .setBounds(x, y, w, h);
439:                redoLines = true;
440:            }
441:
442:            public Dimension getPreferredSize() {
443:                return new Dimension(lastWidth, lastHeight);
444:            }
445:
446:            public Dimension getMaximumSize() {
447:                return new Dimension(lastWidth, lastHeight);
448:            }
449:
450:            public Dimension getMinimumSize() {
451:                return new Dimension(lastHeight, lastHeight);
452:            }
453:
454:            public void setText(String text) {
455:                setText2(text);
456:                select(tempSelection.set(selection).pin(contents));
457:            }
458:
459:            public void setText2(String text) {
460:                contents = text;
461:                charBreaker.setText(text);
462:                wordBreaker.setText(text);
463:                lineBreaker.setText(text);
464:                redoLines = true;
465:                if (textListener != null)
466:                    textListener.textValueChanged(new TextEvent(this ,
467:                            TextEvent.TEXT_VALUE_CHANGED));
468:                repaint(16);
469:            }
470:
471:            public void insertText(String text) {
472:                if (activeStart == -1)
473:                    activeStart = selection.getStart();
474:                replaceRange(text, selection.getStart(), selection.getEnd());
475:            }
476:
477:            public void replaceRange(String s, int start, int end) {
478:                setText2(contents.substring(0, start) + s
479:                        + contents.substring(end));
480:                select(tempSelection.set(selection).fixAfterReplace(start, end,
481:                        s.length()));
482:                validateKeyStart();
483:            }
484:
485:            public String getText() {
486:                return contents;
487:            }
488:
489:            public void setFont(Font font) {
490:                super .setFont(font);
491:                redoLines = true;
492:                repaint(16);
493:            }
494:
495:            // ================== Graphics ======================
496:
497:            public void update(Graphics g) {
498:                if (DEBUG)
499:                    System.out.println("update");
500:                paint(g);
501:            }
502:
503:            public void paint(Graphics g) {
504:                mySize = getSize();
505:                if (cacheImage == null
506:                        || cacheImage.getHeight(this ) != mySize.height
507:                        || cacheImage.getWidth(this ) != mySize.width) {
508:                    cacheImage = createImage(mySize.width, mySize.height);
509:                    valid = false;
510:                }
511:                if (!valid || redoLines) {
512:                    if (DEBUG)
513:                        System.out.println("painting");
514:                    paint2(cacheImage.getGraphics());
515:                    valid = true;
516:                }
517:                //getToolkit().sync();
518:                if (DEBUG)
519:                    System.out.println("copying");
520:                g.drawImage(cacheImage, 0, 0, mySize.width, mySize.height, 0,
521:                        0, mySize.width, mySize.height, this );
522:            }
523:
524:            public void paint2(Graphics g) {
525:                g.clearRect(0, 0, mySize.width, mySize.height);
526:                if (DEBUG)
527:                    System.out.println("print");
528:                if (focus)
529:                    g.setColor(Color.black);
530:                else
531:                    g.setColor(Color.gray);
532:                g.drawRect(0, 0, mySize.width - 1, mySize.height - 1);
533:                g.setClip(1, 1, mySize.width - 2, mySize.height - 2);
534:                g.setColor(Color.black);
535:                g.setFont(getFont());
536:                fm = g.getFontMetrics();
537:                lineAscent = fm.getAscent();
538:                lineLeading = fm.getLeading();
539:                lineHeight = lineAscent + fm.getDescent() + lineLeading;
540:                int y = yInset + lineAscent;
541:                String lastSubstring = "";
542:                if (redoLines)
543:                    fixLineStarts(mySize.width - xInset - xInset);
544:                for (int i = 0; i < lineCount; y += lineHeight, ++i) {
545:                    // LIU: Don't display terminating ^M characters
546:                    int lim = lineStarts[i + 1];
547:                    if (lim > 0 && contents.length() > 0
548:                            && contents.charAt(lim - 1) == CR)
549:                        --lim;
550:                    lastSubstring = contents.substring(lineStarts[i], lim);
551:                    g.drawString(lastSubstring, xInset, y);
552:                }
553:                drawSelection(g, lastSubstring);
554:                lastHeight = y + yInset - lineHeight + yInset;
555:                lastWidth = mySize.width - xInset - xInset;
556:            }
557:
558:            void paintRect(Graphics g, int x, int y, int w, int h) {
559:                if (focus) {
560:                    g.fillRect(x, y, w, h);
561:                } else {
562:                    g.drawRect(x, y, w - 1, h - 1);
563:                }
564:            }
565:
566:            public void drawSelection(Graphics g, String lastSubstring) {
567:                g.setXORMode(Color.black);
568:                if (activeStart != -1) {
569:                    offset2Point(activeStart, false, activePoint);
570:                    g.setColor(Color.magenta);
571:                    int line = activePoint.x - 1;
572:                    g.fillRect(line, activePoint.y, 1, lineHeight);
573:                }
574:                if (selection.isCaret()) {
575:                    offset2Point(selection.caret, selection.clickAfter,
576:                            caretPoint);
577:                } else {
578:                    if (focus)
579:                        g.setColor(Color.blue);
580:                    else
581:                        g.setColor(Color.yellow);
582:                    offset2Point(selection.getStart(), true, startPoint);
583:                    offset2Point(selection.getEnd(), false, endPoint);
584:                    if (selection.getStart() == selection.caret)
585:                        caretPoint.setLocation(startPoint);
586:                    else
587:                        caretPoint.setLocation(endPoint);
588:                    if (startPoint.y == endPoint.y) {
589:                        paintRect(g, startPoint.x, startPoint.y, Math.max(1,
590:                                endPoint.x - startPoint.x), lineHeight);
591:                    } else {
592:                        paintRect(g, startPoint.x, startPoint.y,
593:                                (mySize.width - xInset) - startPoint.x,
594:                                lineHeight);
595:                        if (startPoint.y + lineHeight < endPoint.y)
596:                            paintRect(g, xInset, startPoint.y + lineHeight,
597:                                    (mySize.width - xInset) - xInset,
598:                                    endPoint.y - startPoint.y - lineHeight);
599:                        paintRect(g, xInset, endPoint.y, endPoint.x - xInset,
600:                                lineHeight);
601:                    }
602:                }
603:                if (focus || selection.isCaret()) {
604:                    if (focus)
605:                        g.setColor(Color.green);
606:                    else
607:                        g.setColor(Color.red);
608:                    int line = caretPoint.x - (selection.clickAfter ? 0 : 1);
609:                    g.fillRect(line, caretPoint.y, 1, lineHeight);
610:                    int w = lineHeight / 12 + 1;
611:                    int braces = line - (selection.clickAfter ? -1 : w);
612:                    g.fillRect(braces, caretPoint.y, w, 1);
613:                    g.fillRect(braces, caretPoint.y + lineHeight - 1, w, 1);
614:                }
615:            }
616:
617:            public Point offset2Point(int off, boolean start, Point p) {
618:                int line = findLine(off, start);
619:                int width = 0;
620:                try {
621:                    width = fm.stringWidth(contents.substring(lineStarts[line],
622:                            off));
623:                } catch (Exception e) {
624:                    System.out.println(e);
625:                }
626:                p.x = width + xInset;
627:                if (p.x > mySize.width - xInset)
628:                    p.x = mySize.width - xInset;
629:                p.y = lineHeight * line + yInset;
630:                return p;
631:            }
632:
633:            private int findLine(int off, boolean start) {
634:                // if it is start, then go to the next line!
635:                if (start)
636:                    ++off;
637:                for (int i = 1; i < lineCount; ++i) {
638:                    // LIU: This was <= ; changed to < to make caret after
639:                    // final CR in line appear at START of next line.
640:                    if (off < lineStarts[i])
641:                        return i - 1;
642:                }
643:                // LIU: Check for special case; after CR at end of the last line
644:                if (off == lineStarts[lineCount] && off > 0
645:                        && contents.length() > 0
646:                        && contents.charAt(off - 1) == CR) {
647:                    return lineCount;
648:                }
649:                return lineCount - 1;
650:            }
651:
652:            // offsets on any line will go from start,true to end,false
653:            // excluding start,false and end,true
654:            public Selection point2Offset(Point p, Selection o) {
655:                if (p.y < yInset) {
656:                    o.caret = 0;
657:                    o.clickAfter = true;
658:                    return o;
659:                }
660:                int line = (p.y - yInset) / lineHeight;
661:                if (line >= lineCount) {
662:                    o.caret = contents.length();
663:                    o.clickAfter = false;
664:                    return o;
665:                }
666:                int target = p.x - xInset;
667:                if (target <= 0) {
668:                    o.caret = lineStarts[line];
669:                    o.clickAfter = true;
670:                    return o;
671:                }
672:                int lowGuess = lineStarts[line];
673:                int lowWidth = 0;
674:                int highGuess = lineStarts[line + 1];
675:                int highWidth = fm.stringWidth(contents.substring(
676:                        lineStarts[line], highGuess));
677:                if (target >= highWidth) {
678:                    o.caret = lineStarts[line + 1];
679:                    o.clickAfter = false;
680:                    return o;
681:                }
682:                while (lowGuess < highGuess - 1) {
683:                    int guess = (lowGuess + highGuess) / 2;
684:                    int width = fm.stringWidth(contents.substring(
685:                            lineStarts[line], guess));
686:                    if (width <= target) {
687:                        lowGuess = guess;
688:                        lowWidth = width;
689:                        if (width == target)
690:                            break;
691:                    } else {
692:                        highGuess = guess;
693:                        highWidth = width;
694:                    }
695:                }
696:                // at end, either lowWidth < target < width(low+1), or lowWidth = target
697:                int highBound = charBreaker.following(lowGuess);
698:                int lowBound = charBreaker.previous();
699:                // we are now at character boundaries
700:                if (lowBound != lowGuess)
701:                    lowWidth = fm.stringWidth(contents.substring(
702:                            lineStarts[line], lowBound));
703:                if (highBound != highGuess)
704:                    highWidth = fm.stringWidth(contents.substring(
705:                            lineStarts[line], highBound));
706:                // we now have the right widths
707:                if (target - lowWidth < highWidth - target) {
708:                    o.caret = lowBound;
709:                    o.clickAfter = true;
710:                } else {
711:                    o.caret = highBound;
712:                    o.clickAfter = false;
713:                }
714:                // we now have the closest!
715:                return o;
716:            }
717:
718:            private void fixLineStarts(int width) {
719:                lineCount = 1;
720:                lineStarts[0] = 0;
721:                if (contents.length() == 0) {
722:                    lineStarts[1] = 0;
723:                    return;
724:                }
725:                int end = 0;
726:                // LIU: Add check for MAX_LINES
727:                for (int start = 0; start < contents.length()
728:                        && lineCount < MAX_LINES; start = end) {
729:                    end = nextLine(fm, start, width);
730:                    lineStarts[lineCount++] = end;
731:                    if (end == start) { // LIU: Assertion
732:                        throw new RuntimeException("nextLine broken");
733:                    }
734:                }
735:                --lineCount;
736:                redoLines = false;
737:            }
738:
739:            // LIU: Enhanced to wrap long lines.  Bug with return of start fixed.
740:            public int nextLine(FontMetrics fm, int start, int width) {
741:                int len = contents.length();
742:                for (int i = start; i < len; ++i) {
743:                    // check for line separator
744:                    char ch = (contents.charAt(i));
745:                    if (ch >= 0x000A && ch <= 0x000D || ch == 0x2028
746:                            || ch == 0x2029) {
747:                        len = i + 1;
748:                        if (ch == 0x000D && i + 1 < len
749:                                && contents.charAt(i + 1) == 0x000A) // crlf
750:                            ++len; // grab extra char
751:                        break;
752:                    }
753:                }
754:                String subject = contents.substring(start, len);
755:                if (visibleWidth(fm, subject) <= width)
756:                    return len;
757:
758:                // LIU: Remainder of this method rewritten to accomodate lines
759:                // longer than the component width by first trying to break
760:                // into lines; then words; finally chars.
761:                int n = findFittingBreak(fm, subject, width, lineBreaker);
762:                if (n == 0) {
763:                    n = findFittingBreak(fm, subject, width, wordBreaker);
764:                }
765:                if (n == 0) {
766:                    n = findFittingBreak(fm, subject, width, charBreaker);
767:                }
768:                return n > 0 ? start + n : len;
769:            }
770:
771:            /**
772:             * LIU: Finds the longest substring that fits a given width
773:             * composed of subunits returned by a BreakIterator.  If the smallest
774:             * subunit is too long, returns 0.
775:             * @param fm metrics to use
776:             * @param line the string to be fix into width
777:             * @param width line.substring(0, result) must be <= width
778:             * @param breaker the BreakIterator that will be used to find subunits
779:             * @return maximum characters, at boundaries returned by breaker,
780:             * that fit into width, or zero on failure
781:             */
782:            private int findFittingBreak(FontMetrics fm, String line,
783:                    int width, BreakIterator breaker) {
784:                breaker.setText(line);
785:                int last = breaker.first();
786:                int end = breaker.next();
787:                while (end != BreakIterator.DONE
788:                        && visibleWidth(fm, line.substring(0, end)) <= width) {
789:                    last = end;
790:                    end = breaker.next();
791:                }
792:                return last;
793:            }
794:
795:            public int visibleWidth(FontMetrics fm, String s) {
796:                int i;
797:                for (i = s.length() - 1; i >= 0; --i) {
798:                    char ch = s.charAt(i);
799:                    if (!(ch == ' ' || ch >= 0x000A && ch <= 0x000D
800:                            || ch == 0x2028 || ch == 0x2029))
801:                        return fm.stringWidth(s.substring(0, i + 1));
802:                }
803:                return 0;
804:            }
805:
806:            // =============== Utility ====================
807:
808:            private void fixHex() {
809:                if (selection.getEnd() == 0)
810:                    return;
811:                int store = 0;
812:                int places = 1;
813:                int count = 0;
814:                int min = Math.min(8, selection.getEnd());
815:                for (int i = 0; i < min; ++i) {
816:                    char ch = contents.charAt(selection.getEnd() - 1 - i);
817:                    int value = Character.getNumericValue(ch);
818:                    if (value < 0 || value > 15)
819:                        break;
820:                    store += places * value;
821:                    ++count;
822:                    places *= 16;
823:                }
824:                String add = "";
825:                int bottom = store & 0xFFFF;
826:                if (store >= 0xD8000000 && store < 0xDC000000
827:                        && bottom >= 0xDC00 && bottom < 0xE000) { // surrogates
828:                    add = "" + (char) (store >> 16) + (char) bottom;
829:                } else if (store > 0xFFFF && store <= 0x10FFFF) {
830:                    store -= 0x10000;
831:                    add = "" + (char) (((store >> 10) & 0x3FF) + 0xD800)
832:                            + (char) ((store & 0x3FF) + 0xDC00);
833:
834:                } else if (count >= 4) {
835:                    count = 4;
836:                    add = "" + (char) (store & 0xFFFF);
837:                } else {
838:                    count = 1;
839:                    char ch = contents.charAt(selection.getEnd() - 1);
840:                    add = hex(ch);
841:                    if (ch >= 0xDC00 && ch <= 0xDFFF && selection.getEnd() > 1) {
842:                        ch = contents.charAt(selection.getEnd() - 2);
843:                        if (ch >= 0xD800 && ch <= 0xDBFF) {
844:                            count = 2;
845:                            add = hex(ch) + add;
846:                        }
847:                    }
848:                }
849:                replaceRange(add, selection.getEnd() - count, selection
850:                        .getEnd());
851:            }
852:
853:            public static String hex(char ch) {
854:                String result = Integer.toString(ch, 16).toUpperCase();
855:                result = "0000".substring(result.length(), 4) + result;
856:                return result;
857:            }
858:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.