KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > console > TextConsole


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.ui.console;
13
14 import java.util.HashMap JavaDoc;
15
16 import org.eclipse.core.runtime.jobs.ISchedulingRule;
17 import org.eclipse.jface.resource.ImageDescriptor;
18 import org.eclipse.jface.resource.JFaceResources;
19 import org.eclipse.jface.text.BadLocationException;
20 import org.eclipse.jface.text.BadPositionCategoryException;
21 import org.eclipse.jface.text.IDocument;
22 import org.eclipse.jface.text.IRegion;
23 import org.eclipse.jface.text.Position;
24 import org.eclipse.jface.text.Region;
25 import org.eclipse.swt.graphics.Color;
26 import org.eclipse.swt.graphics.Font;
27 import org.eclipse.ui.internal.console.ConsoleDocument;
28 import org.eclipse.ui.internal.console.ConsoleHyperlinkPosition;
29 import org.eclipse.ui.internal.console.ConsolePatternMatcher;
30 import org.eclipse.ui.part.IPageBookViewPage;
31
32 /**
33  * An abstract text console that supports regular expression matching and
34  * hyperlinks.
35  * <p>
36  * Pattern match listeners can be registered with a console programmatically
37  * or via the <code>org.eclipse.ui.console.consolePatternMatchListeners</code>
38  * extension point.
39  * </p>
40  * <p>
41  * Clients may subclass this class. Subclasses must provide a document partitioner.
42  * </p>
43  * @since 3.1
44  */

45 public abstract class TextConsole extends AbstractConsole {
46
47     /**
48      * The current width of the console. Used for fixed width consoles.
49      * A value of <=0 means does not have a fixed width.
50      */

51     private int fConsoleWidth;
52     /**
53      * The current tab width
54      */

55     private int fTabWidth;
56     /**
57      * The font used by this console
58      */

59     private Font fFont;
60     
61     /**
62      * The background color used by this console or <code>null</code> if default
63      */

64     private Color fBackground;
65     
66     /**
67      * The Console's regular expression pattern matcher
68      */

69     private ConsolePatternMatcher fPatternMatcher;
70     
71     /**
72      * The Console's document
73      */

74     private ConsoleDocument fDocument;
75     
76    /**
77     * indication that the console's partitioner is not expecting more input
78     */

79     private boolean fPartitionerFinished = false;
80     
81     /**
82      * Indication that the console's pattern matcher has finished.
83      * (all matches have been found and all listeners notified)
84      */

85     private boolean fMatcherFinished = false;
86     
87     /**
88      * indication that the console output complete property has been fired
89      */

90     private boolean fCompleteFired = false;
91
92     
93     /**
94      * Map of client defined attributes
95      */

96     private HashMap JavaDoc fAttributes = new HashMap JavaDoc();
97     
98     private IConsoleManager fConsoleManager = ConsolePlugin.getDefault().getConsoleManager();
99     
100    
101     /* (non-Javadoc)
102      * @see org.eclipse.ui.console.AbstractConsole#dispose()
103      */

104     protected void dispose() {
105         super.dispose();
106         fFont = null;
107         synchronized(fAttributes) {
108             fAttributes.clear();
109         }
110     }
111     /**
112      * Constructs a console with the given name, image descriptor, and lifecycle
113      *
114      * @param name name to display for this console
115      * @param consoleType console type identifier or <code>null</code>
116      * @param imageDescriptor image to display for this console or <code>null</code>
117      * @param autoLifecycle whether lifecycle methods should be called automatically
118      * when this console is added/removed from the console manager
119      */

120     public TextConsole(String JavaDoc name, String JavaDoc consoleType, ImageDescriptor imageDescriptor, boolean autoLifecycle) {
121         super(name, consoleType, imageDescriptor, autoLifecycle);
122         fDocument = new ConsoleDocument();
123         fDocument.addPositionCategory(ConsoleHyperlinkPosition.HYPER_LINK_CATEGORY);
124         fPatternMatcher = new ConsolePatternMatcher(this);
125         fDocument.addDocumentListener(fPatternMatcher);
126         fTabWidth = IConsoleConstants.DEFAULT_TAB_SIZE;
127     }
128
129     /* (non-Javadoc)
130      * @see org.eclipse.ui.console.IConsole#createPage(org.eclipse.ui.console.IConsoleView)
131      */

132     public IPageBookViewPage createPage(IConsoleView view) {
133         return new TextConsolePage(this, view);
134     }
135     
136     /**
137      * Returns this console's document.
138      * <p>
139      * Note that a console may or may not support direct manipulation of its document.
140      * For example, an I/O console document and its partitions are produced from the
141      * streams connected to it, and clients are not intended to modify the document's
142      * contents.
143      * </p>
144      *
145      * @return this console's document
146      */

147     public IDocument getDocument() {
148         return fDocument;
149     }
150     
151     /**
152      * Returns the current width of this console. A value of zero of less
153      * indicates this console has no fixed width.
154      *
155      * @return the current width of this console
156      */

157     public int getConsoleWidth() {
158         return fConsoleWidth;
159     }
160     
161     /**
162      * Sets the width of this console in characters. Any value greater than zero
163      * will cause this console to have a fixed width.
164      *
165      * @param width the width to make this console. Values of 0 or less imply
166      * the console does not have any fixed width.
167      */

168     public void setConsoleWidth(int width) {
169         if (fConsoleWidth != width) {
170             int old = fConsoleWidth;
171             fConsoleWidth = width;
172             
173             firePropertyChange(this, IConsoleConstants.P_CONSOLE_WIDTH, new Integer JavaDoc(old), new Integer JavaDoc(fConsoleWidth));
174         }
175     }
176
177     /**
178      * Sets the tab width used in this console.
179      *
180      * @param newTabWidth the tab width
181      */

182     public void setTabWidth(final int newTabWidth) {
183         if (fTabWidth != newTabWidth) {
184             final int oldTabWidth = fTabWidth;
185             fTabWidth = newTabWidth;
186             ConsolePlugin.getStandardDisplay().asyncExec(new Runnable JavaDoc() {
187                 public void run() {
188                     firePropertyChange(TextConsole.this, IConsoleConstants.P_TAB_SIZE, new Integer JavaDoc(oldTabWidth), new Integer JavaDoc(fTabWidth));
189                 }
190             });
191         }
192     }
193     
194     /**
195      * Returns the tab width used in this console.
196      *
197      * @return tab width used in this console
198      */

199     public int getTabWidth() {
200         return fTabWidth;
201     }
202     
203     /**
204      * Returns the font used by this console. Must be called in the UI thread.
205      *
206      * @return font used by this console
207      */

208     public Font getFont() {
209         if (fFont == null) {
210             fFont = getDefaultFont();
211         }
212         return fFont;
213     }
214     
215     /**
216      * Returns the default text font.
217      *
218      * @return the default text font
219      */

220     private Font getDefaultFont() {
221         return JFaceResources.getFont(JFaceResources.TEXT_FONT);
222     }
223     
224     /**
225      * Sets the font used by this console. Specify <code>null</code> to use
226      * the default text font.
227      *
228      * @param newFont font, or <code>null</code> to indicate the default font
229      */

230     public void setFont(Font newFont) {
231         // ensure font is initialized
232
getFont();
233         // translate null to default font
234
if (newFont == null) {
235             newFont = getDefaultFont();
236         }
237         // fire property change if required
238
if (!fFont.equals(newFont)) {
239             Font old = fFont;
240             fFont = newFont;
241             firePropertyChange(this, IConsoleConstants.P_FONT, old, fFont);
242         }
243     }
244     
245     /**
246      * Sets the background color used by this console. Specify <code>null</code> to use
247      * the default background color.
248      *
249      * @param background background color or <code>null</code> for default
250      * @since 3.3
251      * @deprecated use setBackground(Color) instead
252      */

253     public void setBackgrond(Color background) {
254         setBackground(background);
255     }
256     
257     /**
258      * Sets the background color used by this console. Specify <code>null</code> to use
259      * the default background color.
260      *
261      * @param background background color or <code>null</code> for default
262      * @since 3.3
263      */

264     public void setBackground(Color background) {
265         if (fBackground == null) {
266             if (background == null) {
267                 return;
268             }
269         } else if (fBackground.equals(background)){
270             return;
271         }
272         Color old = fBackground;
273         fBackground = background;
274         firePropertyChange(this, IConsoleConstants.P_BACKGROUND_COLOR, old, fBackground);
275     }
276     
277     /**
278      * Returns the background color to use for this console or <code>null</code> for the
279      * default background color.
280      *
281      * @return background color or <code>null</code> for default
282      * @since 3.3
283      */

284     public Color getBackground() {
285         return fBackground;
286     }
287     
288     /**
289      * Clears the console.
290      * <p>
291      * Since a console may or may not support direct manipulation
292      * of its document's contents, this method should be called to clear a text console's
293      * document. The default implementation sets this console's document content
294      * to the empty string directly. Subclasses should override as required.
295      * </p>
296      */

297     public void clearConsole() {
298         IDocument document = getDocument();
299         if (document != null) {
300             document.set(""); //$NON-NLS-1$
301
}
302     }
303
304     /**
305      * Returns the console's document partitioner.
306      * @return The console's document partitioner
307      */

308     protected abstract IConsoleDocumentPartitioner getPartitioner();
309     
310     /**
311      * Returns all hyperlinks in this console.
312      *
313      * @return all hyperlinks in this console
314      */

315     public IHyperlink[] getHyperlinks() {
316         try {
317             Position[] positions = getDocument().getPositions(ConsoleHyperlinkPosition.HYPER_LINK_CATEGORY);
318             IHyperlink[] hyperlinks = new IHyperlink[positions.length];
319             for (int i = 0; i < positions.length; i++) {
320                 ConsoleHyperlinkPosition position = (ConsoleHyperlinkPosition) positions[i];
321                 hyperlinks[i] = position.getHyperLink();
322             }
323             return hyperlinks;
324         } catch (BadPositionCategoryException e) {
325             return new IHyperlink[0];
326         }
327     }
328     
329     /**
330      * Returns the hyperlink at the given offset of <code>null</code> if none.
331      *
332      * @param offset offset for which a hyperlink is requested
333      * @return the hyperlink at the given offset of <code>null</code> if none
334      */

335     public IHyperlink getHyperlink(int offset) {
336         try {
337             IDocument document = getDocument();
338             if (document != null) {
339                 Position[] positions = document.getPositions(ConsoleHyperlinkPosition.HYPER_LINK_CATEGORY);
340                 Position position = findPosition(offset, positions);
341                 if (position instanceof ConsoleHyperlinkPosition) {
342                     return ((ConsoleHyperlinkPosition) position).getHyperLink();
343                 }
344             }
345         } catch (BadPositionCategoryException e) {
346         }
347         return null;
348     }
349
350     /**
351      * Binary search for the position at a given offset.
352      *
353      * @param offset the offset whose position should be found
354      * @return the position containing the offset, or <code>null</code>
355      */

356     private Position findPosition(int offset, Position[] positions) {
357         
358         if (positions.length == 0)
359             return null;
360             
361         int left= 0;
362         int right= positions.length -1;
363         int mid= 0;
364         Position position= null;
365         
366         while (left < right) {
367             
368             mid= (left + right) / 2;
369                 
370             position= positions[mid];
371             if (offset < position.getOffset()) {
372                 if (left == mid)
373                     right= left;
374                 else
375                     right= mid -1;
376             } else if (offset > (position.getOffset() + position.getLength() - 1)) {
377                 if (right == mid)
378                     left= right;
379                 else
380                     left= mid +1;
381             } else {
382                 left= right= mid;
383             }
384         }
385         
386         position= positions[left];
387         if (offset >= position.getOffset() && (offset < (position.getOffset() + position.getLength()))) {
388             return position;
389         }
390         return null;
391     }
392
393     /**
394      * Adds the given pattern match listener to this console. The listener will
395      * be connected and receive match notifications. Has no effect if an identical
396      * listener has already been added.
397      *
398      * @param listener the listener to add
399      */

400     public void addPatternMatchListener(IPatternMatchListener listener) {
401         fPatternMatcher.addPatternMatchListener(listener);
402     }
403     
404     /**
405      * Removes the given pattern match listener from this console. The listener will be
406      * disconnected and will no longer receive match notifications. Has no effect
407      * if the listener was not previously added.
408      *
409      * @param listener the pattern match listener to remove
410      */

411     public void removePatternMatchListener(IPatternMatchListener listener) {
412         fPatternMatcher.removePatternMatchListener(listener);
413     }
414     
415     
416     /**
417      * Job scheduling rule that prevent the job from running if the console's PatternMatcher
418      * is active.
419      */

420     private class MatcherSchedulingRule implements ISchedulingRule {
421         public boolean contains(ISchedulingRule rule) {
422             return rule == this;
423         }
424
425         public boolean isConflicting(ISchedulingRule rule) {
426             if (contains(rule)) {
427                 return true;
428             }
429             if (rule != this && rule instanceof MatcherSchedulingRule) {
430                 return (((MatcherSchedulingRule)rule).getConsole() == TextConsole.this);
431             }
432             return false;
433         }
434         
435         public TextConsole getConsole() {
436             return TextConsole.this;
437         }
438     }
439     
440     /**
441      * Returns a scheduling rule which can be used to prevent jobs from running
442      * while this console's pattern matcher is active.
443      * <p>
444      * Although this scheduling rule prevents jobs from running at the same time as
445      * pattern matching jobs for this console, it does not enforce any ordering of jobs.
446      * Since 3.2, pattern matching jobs belong to the job family identified by the console
447      * object that matching is occurring on. To ensure a job runs after all scheduled pattern
448      * matching is complete, clients must join on this console's job family.
449      * </p>
450      * @return a scheduling rule which can be used to prevent jobs from running
451      * while this console's pattern matcher is active
452      */

453     public ISchedulingRule getSchedulingRule() {
454         return new MatcherSchedulingRule();
455     }
456     
457     /**
458      * This console's partitioner should call this method when it is not expecting any new data
459      * to be appended to the document.
460      */

461     public void partitionerFinished() {
462         fPatternMatcher.forceFinalMatching();
463         fPartitionerFinished = true;
464         checkFinished();
465     }
466     
467     /**
468      * Called by this console's pattern matcher when matching is complete.
469      * <p>
470      * Clients should not call this method.
471      * <p>
472      */

473     public void matcherFinished() {
474         fMatcherFinished = true;
475         fDocument.removeDocumentListener(fPatternMatcher);
476         checkFinished();
477     }
478     
479     /**
480      * Fires the console output complete property change event.
481      */

482     private synchronized void checkFinished() {
483         if (!fCompleteFired && fPartitionerFinished && fMatcherFinished ) {
484             fCompleteFired = true;
485             firePropertyChange(this, IConsoleConstants.P_CONSOLE_OUTPUT_COMPLETE, null, null);
486         }
487     }
488     
489     /**
490      * Adds a hyperlink to this console.
491      *
492      * @param hyperlink the hyperlink to add
493      * @param offset the offset in the console document at which the hyperlink should be added
494      * @param length the length of the text which should be hyperlinked
495      * @throws BadLocationException if the specified location is not valid.
496      */

497     public void addHyperlink(IHyperlink hyperlink, int offset, int length) throws BadLocationException {
498         IDocument document = getDocument();
499         ConsoleHyperlinkPosition hyperlinkPosition = new ConsoleHyperlinkPosition(hyperlink, offset, length);
500         try {
501             document.addPosition(ConsoleHyperlinkPosition.HYPER_LINK_CATEGORY, hyperlinkPosition);
502             fConsoleManager.refresh(this);
503         } catch (BadPositionCategoryException e) {
504             ConsolePlugin.log(e);
505         }
506     }
507     
508     /**
509      * Returns the region associated with the given hyperlink.
510      *
511      * @param link hyperlink
512      * @return the region associated with the hyperlink or null if the hyperlink is not found.
513      */

514     public IRegion getRegion(IHyperlink link) {
515         try {
516             IDocument doc = getDocument();
517             if (doc != null) {
518                 Position[] positions = doc.getPositions(ConsoleHyperlinkPosition.HYPER_LINK_CATEGORY);
519                 for (int i = 0; i < positions.length; i++) {
520                     ConsoleHyperlinkPosition position = (ConsoleHyperlinkPosition)positions[i];
521                     if (position.getHyperLink().equals(link)) {
522                         return new Region(position.getOffset(), position.getLength());
523                     }
524                 }
525             }
526         } catch (BadPositionCategoryException e) {
527         }
528         return null;
529     }
530     
531     /**
532      * Returns the attribute associated with the specified key.
533      *
534      * @param key attribute key
535      * @return the attribute associated with the specified key
536      */

537     public Object JavaDoc getAttribute(String JavaDoc key) {
538         synchronized (fAttributes) {
539             return fAttributes.get(key);
540         }
541     }
542     
543     /**
544      * Sets an attribute value. Intended for client data.
545      *
546      * @param key attribute key
547      * @param value attribute value
548      */

549     public void setAttribute(String JavaDoc key, Object JavaDoc value) {
550         synchronized(fAttributes) {
551             fAttributes.put(key, value);
552         }
553     }
554 }
555
Popular Tags