Source Code Cross Referenced for ConsoleKeyListener.java in  » Scripting » oscript-2.10.4 » ti » swing » console » 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 » Scripting » oscript 2.10.4 » ti.swing.console 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*=============================================================================
002:         *     Copyright Texas Instruments 2002. All Rights Reserved.
003:         * 
004:         *  This program is free software; you can redistribute it and/or modify
005:         *  it under the terms of the GNU General Public License as published by
006:         *  the Free Software Foundation; either version 2 of the License, or
007:         *  (at your option) any later version.
008:         * 
009:         *  This program is distributed in the hope that it will be useful,
010:         *  but WITHOUT ANY WARRANTY; without even the implied warranty of
011:         *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012:         *  GNU General Public License for more details.
013:         * 
014:         *  You should have received a copy of the GNU General Public License
015:         *  along with this program; if not, write to the Free Software
016:         *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
017:         */
018:
019:        package ti.swing.console;
020:
021:        import ti.exceptions.ProgrammingErrorException;
022:
023:        import java.awt.*;
024:        import java.awt.event.*;
025:        import java.io.*;
026:        import java.util.Vector;
027:
028:        import javax.swing.Timer;
029:
030:        /**
031:         * Handle keyboard input, and provide a reader interface.... this really 
032:         * should be thought of as an inner-class of ConsoleTextArea, but was moved 
033:         * here to preserve sane file sizes...
034:         * 
035:         * @author Rob Clark
036:         * @version 0.1
037:         */
038:        public class ConsoleKeyListener extends KeyAdapter implements 
039:                Serializable {
040:            private final static int RUNNING = 0;
041:            private final static int KILLED = 1;
042:            private int state = RUNNING;
043:
044:            private static final int VK_CONTROL = (System
045:                    .getProperty("mrj.version") == null) ? KeyEvent.VK_CONTROL
046:                    : KeyEvent.VK_META;
047:
048:            /**
049:             * Modifiers....
050:             */
051:            private boolean overwrite = false;
052:            private boolean control = false;
053:
054:            private static final int BUFSIZE = 40;
055:
056:            /**
057:             * The console we are a member of...  we really should be an inner class
058:             * of ConsoleTextArea, but that would be too much for one src file.  Instead
059:             * we manually implement inner-classes by keeping a reference back to our
060:             * creator.
061:             */
062:            private Console console;
063:
064:            private static final char[] EMPTY_BUF = new char[0];
065:
066:            /**
067:             * The buffer of characters typed since last LF
068:             */
069:            private char buf[] = EMPTY_BUF;
070:            private int bufLength = 0;
071:
072:            /**
073:             * The cursor into the buf.
074:             */
075:            private int cursor = 0;
076:
077:            /**
078:             * The "queue" of characters that have been committed (ie. user pressed 
079:             * <ENTER>), but not yet consumed by reader.
080:             */
081:            private char cqueue[] = EMPTY_BUF;
082:
083:            /**
084:             * Since cqueue is overwritten, but we still need to synchronize access
085:             * to it, this object is used:
086:             */
087:            private final Object cqueueLock = new String("cqueueLock");
088:
089:            /**
090:             * The history buffer.
091:             */
092:            private History history = new History();
093:
094:            /**
095:             * The tab completion engine, if one is configured.  Tab completion is 
096:             * disabled if this is <code>null</code>.
097:             */
098:            private ConsoleTabCompleter tabCompleter;
099:
100:            /**
101:             * Class Constructor.
102:             * 
103:             * @param console      the console we belong to
104:             */
105:            public ConsoleKeyListener(Console console) {
106:                this .console = console;
107:            }
108:
109:            /**
110:             * Set the history.  The history object must be an object that was previously
111:             * returned by {@link #getHistory}, but may be serialized/deserialized.
112:             * 
113:             * @param history   a history object, as returned by {@link #getHistory}
114:             * @see #getHistory
115:             */
116:            public void setHistory(Object history) {
117:                if (history instanceof  History)
118:                    this .history = (History) history;
119:            }
120:
121:            /**
122:             * Get the history.  The history is externally treated as opaque, but the
123:             * get/set methods allow the creator of the {@link Console} to make history
124:             * persistant.  The history object is {@link java.io.Serializable}
125:             * 
126:             * @return a opaque history object, which is serializable
127:             * @see #setHistory
128:             */
129:            public Object getHistory() {
130:                return history;
131:            }
132:
133:            /**
134:             * Set the {@link ConsoleTabCompleter}
135:             */
136:            public void setTabCompleter(ConsoleTabCompleter tabCompleter) {
137:                this .tabCompleter = tabCompleter;
138:            }
139:
140:            /**
141:             * Get the Reader for the console.  By using this reader, an application 
142:             * can use this console for input.
143:             *
144:             * @return a reader that can be used to read from the console
145:             */
146:            public Reader getReader() {
147:                return new Reader() {
148:
149:                    /**
150:                     * Tell whether this stream is ready to be read.
151:                     *
152:                     * @return True if the next read() is guaranteed not to block for input,
153:                     * false otherwise.  Note that returning false does not guarantee that the
154:                     * next read will block.
155:                     *
156:                     * @exception  IOException  If an I/O error occurs
157:                     */
158:                    public boolean ready() throws IOException {
159:                        return (state != KILLED) && (cqueue.length > 0);
160:                    }
161:
162:                    /**
163:                     * Read into a portion of an array of characters.  This method will block
164:                     * until some input is available, an I/O error occurs, or the end of the
165:                     * stream is reached, e.g. the outerclass is finalized.
166:                     *
167:                     * @param cbuf        Array of characters to read into
168:                     * @param off         Offset from which to start writing characters 
169:                     * @param len         Number of characters to write
170:                     * @return the number of characters read, or -1 if the end of the stream
171:                     *         has been reached
172:                     * @exception IOException If an I/O error occurs
173:                     */
174:                    public int read(char[] cbuf, int off, int len)
175:                            throws IOException {
176:                        while (true) {
177:                            // wait for data to be available:
178:                            synchronized (cqueueLock) {
179:                                while ((state != KILLED) && !ready()) {
180:                                    try {
181:                                        cqueueLock.wait();
182:                                    } catch (InterruptedException e) {
183:                                    }
184:                                }
185:                            }
186:
187:                            if (state == KILLED)
188:                                return -1;
189:
190:                            synchronized (cqueueLock) {
191:                                if (cqueue.length != 0) {
192:                                    int i = off; // i < off + len
193:                                    int j = 0; // j < cqueue.length
194:
195:                                    while ((i < off + len)
196:                                            && (j < cqueue.length))
197:                                        cbuf[i++] = cqueue[j++];
198:
199:                                    // if there are remaining chars, copy them to the new cqueue:
200:                                    if (j < cqueue.length) {
201:                                        char tmp[] = new char[cqueue.length - j];
202:                                        for (i = 0; i < (cqueue.length - j); i++)
203:                                            tmp[i] = cqueue[j + i];
204:                                        cqueue = tmp;
205:                                    } else {
206:                                        cqueue = new char[0];
207:                                    }
208:
209:                                    // return the number of chars read:
210:                                    return j;
211:                                }
212:                            }
213:                        }
214:                    }
215:
216:                    /**
217:                     * Don't do anything, since you can't close this!
218:                     *
219:                     * @exception IOException - If an I/O error occurs
220:                     */
221:                    public void close() throws IOException {
222:                    }
223:                };
224:            }
225:
226:            /**
227:             * This should called when getting rid of this text-area... this will
228:             * cause any blocking readers to return.
229:             */
230:            public void dispose() {
231:                state = KILLED;
232:
233:                // in case we have someone waiting on cqueue:
234:                synchronized (cqueueLock) {
235:                    cqueueLock.notifyAll();
236:                }
237:            }
238:
239:            /**
240:             * Append char to current active buffer.
241:             */
242:            public void insertChar(char c) {
243:                InputHandler ih = console.getInputHandler();
244:
245:                if (c == Console.LF) {
246:                    synchronized (cqueueLock) {
247:                        // append chars in buf to cqueue:
248:                        char[] tmp = new char[cqueue.length + bufLength + 1];
249:                        System.arraycopy(cqueue, 0, tmp, 0, cqueue.length);
250:                        System.arraycopy(buf, 0, tmp, cqueue.length, bufLength);
251:                        tmp[tmp.length - 1] = Console.LF;
252:
253:                        // update history buffer:
254:                        history.append(buf, 0, bufLength);
255:
256:                        // reset buffer:
257:                        buf = EMPTY_BUF;
258:                        cursor = bufLength = 0;
259:
260:                        // append an EOL:
261:                        ih.append(tmp, tmp.length - 1, 1);
262:
263:                        cqueue = tmp;
264:
265:                        cqueueLock.notifyAll();
266:                    }
267:                } else {
268:                    // check if we need to grow buf:
269:                    ensureCapacity(1);
270:
271:                    if (!overwrite) {
272:                        // delete everything back to cursor:
273:                        ih.zap(bufLength - cursor);
274:
275:                        // copy buf array elements, shifting up by one:
276:                        System.arraycopy(buf, cursor, buf, cursor + 1,
277:                                bufLength - cursor);
278:
279:                        // update buf, length and cursor:
280:                        buf[cursor] = c;
281:                        bufLength++;
282:                        cursor++;
283:
284:                        // write remainging chars back out:
285:                        ih.append(buf, cursor - 1, bufLength - cursor + 1);
286:                    } else {
287:                        // this is basically the same, leaving out the shifting...
288:                        throw new ProgrammingErrorException("unimplemented");
289:                    }
290:                }
291:            }
292:
293:            /**
294:             * Invoked when a key is typed.
295:             */
296:            public synchronized void keyTyped(KeyEvent evt) {
297:                if (!console.isEnabled())
298:                    return;
299:
300:                if (console.getInputMap().get(
301:                        javax.swing.KeyStroke.getKeyStroke(evt.getKeyCode(),
302:                                evt.getModifiers())) != null)
303:                    return;
304:
305:                InputHandler ih = console.getInputHandler();
306:
307:                ih.lock();
308:
309:                char c = evt.getKeyChar();
310:                int keyCode = (int) c;
311:
312:                if (c == Console.CR)
313:                    c = Console.LF;
314:
315:                switch (keyCode) {
316:                case KeyEvent.VK_BACK_SPACE:
317:                    if (cursor > 0) {
318:                        // delete everything back to before cursor:
319:                        ih.zap(bufLength - cursor + 1);
320:
321:                        // copy buf array elements, shifting down one:
322:                        System.arraycopy(buf, cursor, buf, cursor - 1,
323:                                bufLength - cursor);
324:
325:                        // update length and cursor:
326:                        bufLength--;
327:                        cursor--;
328:
329:                        // write remaining chars back out:
330:                        ih.append(buf, cursor, bufLength - cursor);
331:                    }
332:                    break;
333:
334:                case KeyEvent.VK_DELETE:
335:                    if (cursor < bufLength) {
336:                        // delete everything back to cursor:
337:                        ih.zap(bufLength - cursor);
338:
339:                        // copy buf array elements, shifting down one:
340:                        System.arraycopy(buf, cursor + 1, buf, cursor,
341:                                bufLength - cursor - 1);
342:
343:                        // update length and cursor:
344:                        bufLength--;
345:
346:                        // write remaining chars back out:
347:                        ih.append(buf, cursor, bufLength - cursor);
348:                    }
349:                    break;
350:
351:                case KeyEvent.VK_TAB:
352:                    if (tabCompleter != null) {
353:                        String pre = new String(buf, 0, cursor);
354:                        String post = new String(buf, cursor, bufLength
355:                                - cursor);
356:                        replaceLine(pre + tabCompleter.complete(pre) + post);
357:                        break;
358:                    }
359:                    // fall thru
360:                default:
361:                    if (!control)
362:                        insertChar(c);
363:
364:                }
365:
366:                ih.unlock();
367:            }
368:
369:            /**
370:             * Keep track of modifiers.
371:             */
372:            public void keyPressed(KeyEvent evt) {
373:                if (!console.isEnabled())
374:                    return;
375:
376:                int keyCode = evt.getKeyCode();
377:
378:                /* on some platforms we treat other keys as KeyEvent.VK_CONTROL:
379:                 */
380:                if (keyCode == VK_CONTROL)
381:                    keyCode = KeyEvent.VK_CONTROL;
382:
383:                /* handle LEFT/RIGHT here so they repeat if the key is held down!
384:                 */
385:                switch (keyCode) {
386:                case KeyEvent.VK_CONTROL:
387:                    control = true;
388:                    break;
389:
390:                case KeyEvent.VK_LEFT:
391:                    while (cursor > 0) {
392:                        cursor--;
393:
394:                        if (!control || isSeparator(buf[cursor]))
395:                            break;
396:                    }
397:                    console.repaint();
398:                    break;
399:
400:                case KeyEvent.VK_RIGHT:
401:                    while (++cursor < bufLength)
402:                        if (!control || isSeparator(buf[cursor]))
403:                            break;
404:                    if (cursor > bufLength)
405:                        cursor = bufLength;
406:                    console.repaint();
407:                    break;
408:                }
409:            }
410:
411:            /**
412:             * Certain keys don't generate keyTyped events, so we have to do this.
413:             */
414:            public void keyReleased(KeyEvent evt) {
415:                if (!console.isEnabled())
416:                    return;
417:
418:                int keyCode = evt.getKeyCode();
419:
420:                /* on some platforms we treat other keys as KeyEvent.VK_CONTROL:
421:                 */
422:                if (keyCode == VK_CONTROL)
423:                    keyCode = KeyEvent.VK_CONTROL;
424:
425:                int oldCursor = cursor;
426:                switch (keyCode) {
427:                case KeyEvent.VK_CONTROL:
428:                    control = false;
429:                    break;
430:
431:                case KeyEvent.VK_UP:
432:                    replaceLine(history.getPrev(new String(buf, 0, cursor)));
433:                    cursor = Math.min(oldCursor, cursor);
434:                    break;
435:
436:                case KeyEvent.VK_DOWN:
437:                    replaceLine(history.getNext(new String(buf, 0, cursor)));
438:                    cursor = Math.min(oldCursor, cursor);
439:                    break;
440:
441:                case KeyEvent.VK_HOME:
442:                    cursor = 0;
443:                    console.repaint();
444:                    break;
445:
446:                case KeyEvent.VK_END:
447:                    cursor = bufLength;
448:                    console.repaint();
449:                    break;
450:
451:                case KeyEvent.VK_ESCAPE:
452:                    if (control)
453:                        replaceLine("");
454:                    break;
455:                }
456:            }
457:
458:            private static final String SEPARATOR_CHARS = " .()[]{}-+*/_";
459:
460:            private final boolean isSeparator(char c) {
461:                for (int i = 0; i < SEPARATOR_CHARS.length(); i++)
462:                    if (c == SEPARATOR_CHARS.charAt(i))
463:                        return true;
464:                return false;
465:            }
466:
467:            private final void replaceLine(String str) {
468:                if (str != null) {
469:                    char[] buf = str.toCharArray();
470:
471:                    InputHandler ih = console.getInputHandler();
472:                    ih.lock();
473:
474:                    // remove old line:
475:                    ih.zap(bufLength);
476:
477:                    // replace line:
478:                    this .buf = buf;
479:                    bufLength = cursor = buf.length;
480:
481:                    // append new line to console:
482:                    ih.append(buf, 0, bufLength);
483:
484:                    ih.unlock();
485:                }
486:            }
487:
488:            private final void ensureCapacity(int cnt) {
489:                if ((bufLength + cnt) >= buf.length) {
490:                    char[] newBuf = new char[buf.length + BUFSIZE + cnt];
491:                    System.arraycopy(buf, 0, newBuf, 0, buf.length);
492:                    buf = newBuf;
493:                }
494:            }
495:
496:            /**
497:             * Draw the cursor over the graphics.
498:             */
499:            public void paintCursor(Graphics g) {
500:                InputHandler ih = console.getInputHandler();
501:
502:                if (!console.locked()) {
503:                    int off = ih.getOffset() - (bufLength - cursor);
504:                    Point p = console.toPoint(off);
505:
506:                    // we don't want to disturb the state of the current graphics:
507:                    g = g.create();
508:                    g.setColor(Color.white);
509:                    g.setXORMode(Color.blue);
510:
511:                    g.fillRect(p.x, p.y, console.getColumnWidth(), console
512:                            .getRowHeight());
513:                }
514:            }
515:
516:            /**
517:             * Class to implement history buffer.
518:             */
519:            private static class History implements  Serializable {
520:                private Vector history = new Vector();
521:                private int idx = 0;
522:
523:                /**
524:                 * Get the prev entry in the history that begins with <code>current</code>
525:                 * (which is the characters in the current buffer up to the cursor)
526:                 */
527:                String getPrev(String current) {
528:                    int idx = this .idx;
529:                    char[] tmp;
530:                    while ((idx > 0)
531:                            && ((tmp = (char[]) (history.get(--idx))).length >= current
532:                                    .length()))
533:                        if (current
534:                                .equals(new String(tmp, 0, current.length())))
535:                            return new String((char[]) (history
536:                                    .get(this .idx = idx)));
537:                    return null;
538:                }
539:
540:                /**
541:                 * Get the next entry in the history that begins with <code>current</code>
542:                 * (which is the characters in the current buffer up to the cursor)
543:                 */
544:                String getNext(String current) {
545:                    int idx = this .idx;
546:                    while (idx < (history.size() - 1)) {
547:                        char[] tmp = (char[]) (history.get(++idx));
548:                        if (current.equals(new String(tmp, 0, Math.min(
549:                                tmp.length, current.length())))) {
550:                            this .idx = idx;
551:                            return new String(tmp);
552:                        }
553:                    }
554:                    if (idx < history.size())
555:                        return "";
556:                    return null;
557:                }
558:
559:                void append(char[] buf, int off, int len) {
560:                    // always reset idx, even if we don't append:
561:                    idx = history.size();
562:
563:                    // ignore zero length lines:
564:                    if (len <= 0)
565:                        return;
566:
567:                    char[] line = new char[len];
568:                    System.arraycopy(buf, off, line, 0, len);
569:
570:                    // ignore lines same as prev line:
571:                    if ((history.size() > 0)
572:                            && equals(line, (char[]) (history.get(history
573:                                    .size() - 1))))
574:                        return;
575:
576:                    history.add(line);
577:                    idx = history.size();
578:                }
579:
580:                private static boolean equals(char[] a1, char[] a2) {
581:                    if (a1.length != a2.length)
582:                        return false;
583:
584:                    for (int i = 0; i < a1.length; i++)
585:                        if (a1[i] != a2[i])
586:                            return false;
587:
588:                    return true;
589:                }
590:
591:                public String toString() {
592:                    StringBuffer sb = new StringBuffer();
593:                    sb.append('{'); // }
594:
595:                    int i = 0;
596:                    for (; i < history.size(); i++)
597:                        sb.append("\"" + new String((char[]) (history.get(i)))
598:                                + "\",");
599:
600:                    if (i > 0)
601:                        sb.setCharAt(sb.length() - 1, '}');
602:                    else
603:                        sb.append('}');
604:
605:                    return sb.toString();
606:                }
607:            }
608:            /*  
609:             private final static char[] duplicate( char[] buf )
610:             {
611:             char[] newBuf = null;
612:            
613:             if( buf != null )
614:             {
615:             newBuf = new char[buf.length];
616:             System.arraycopy( buf, 0, newBuf, 0, buf.length );
617:             }
618:            
619:             return newBuf;
620:             }
621:             */
622:        }
623:
624:        /*
625:         *   Local Variables:
626:         *   tab-width: 2
627:         *   indent-tabs-mode: nil
628:         *   mode: java
629:         *   c-indentation-style: java
630:         *   c-basic-offset: 2
631:         *   eval: (c-set-offset 'substatement-open '0)
632:         *   eval: (c-set-offset 'case-label '+)
633:         *   eval: (c-set-offset 'inclass '+)
634:         *   eval: (c-set-offset 'inline-open '0)
635:         *   End:
636:         */
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.