KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > debug > internal > ui > views > console > ConsoleViewer


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

11 package org.eclipse.debug.internal.ui.views.console;
12
13
14 import org.eclipse.debug.internal.ui.DebugUIPlugin;
15 import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
16 import org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants;
17 import org.eclipse.debug.ui.console.IConsoleColorProvider;
18 import org.eclipse.debug.ui.console.IConsoleHyperlink;
19 import org.eclipse.jface.resource.JFaceResources;
20 import org.eclipse.jface.text.BadLocationException;
21 import org.eclipse.jface.text.BadPositionCategoryException;
22 import org.eclipse.jface.text.DocumentEvent;
23 import org.eclipse.jface.text.IDocument;
24 import org.eclipse.jface.text.IDocumentListener;
25 import org.eclipse.jface.text.IDocumentPartitioner;
26 import org.eclipse.jface.text.IRegion;
27 import org.eclipse.jface.text.ITypedRegion;
28 import org.eclipse.jface.text.Position;
29 import org.eclipse.jface.text.TextViewer;
30 import org.eclipse.jface.util.IPropertyChangeListener;
31 import org.eclipse.jface.util.PropertyChangeEvent;
32 import org.eclipse.swt.SWT;
33 import org.eclipse.swt.custom.LineStyleEvent;
34 import org.eclipse.swt.custom.LineStyleListener;
35 import org.eclipse.swt.custom.StyleRange;
36 import org.eclipse.swt.custom.StyledText;
37 import org.eclipse.swt.events.MouseEvent;
38 import org.eclipse.swt.events.MouseListener;
39 import org.eclipse.swt.events.MouseMoveListener;
40 import org.eclipse.swt.events.MouseTrackListener;
41 import org.eclipse.swt.events.PaintEvent;
42 import org.eclipse.swt.events.PaintListener;
43 import org.eclipse.swt.events.VerifyEvent;
44 import org.eclipse.swt.graphics.Color;
45 import org.eclipse.swt.graphics.Cursor;
46 import org.eclipse.swt.graphics.FontMetrics;
47 import org.eclipse.swt.graphics.Point;
48 import org.eclipse.swt.widgets.Composite;
49 import org.eclipse.swt.widgets.Control;
50 import org.eclipse.swt.widgets.Event;
51 import org.eclipse.swt.widgets.Listener;
52 import org.eclipse.ui.console.IConsoleConstants;
53
54 public class ConsoleViewer extends TextViewer implements IPropertyChangeListener, MouseTrackListener, MouseMoveListener, MouseListener, PaintListener, LineStyleListener, Listener {
55     
56     /**
57      * Hand cursor
58      */

59     private Cursor fHandCursor;
60     
61     /**
62      * Text cursor
63      */

64     private Cursor fTextCursor;
65     
66     /**
67      * The active hyperlink, or <code>null</code>
68      */

69     private IConsoleHyperlink fHyperLink = null;
70         
71     protected InternalDocumentListener fInternalDocumentListener= new InternalDocumentListener();
72     
73     /**
74      * Whether the console scrolls as output is appended.
75      */

76     private boolean fAutoScroll = true;
77     
78     /**
79      * Internal document listener.
80      */

81     class InternalDocumentListener implements IDocumentListener {
82         /**
83          * @see IDocumentListener#documentAboutToBeChanged(DocumentEvent)
84          */

85         public void documentAboutToBeChanged(DocumentEvent e) {
86         }
87         
88         /**
89          * @see IDocumentListener#documentChanged(DocumentEvent)
90          */

91         public void documentChanged(DocumentEvent e) {
92             ConsoleDocument doc= (ConsoleDocument)getDocument();
93             if (doc == null) {
94                 getTextWidget().setEditable(false);
95                 return;
96             }
97             getTextWidget().setEditable(!doc.isReadOnly());
98             revealEndOfDocument();
99         }
100     }
101     
102     /**
103      * Creates a new console viewer and adds verification checking
104      * to only allow text modification if the text is being modified
105      * in the editable portion of the underlying document.
106      *
107      * @see org.eclipse.swt.events.VerifyListener
108      */

109     public ConsoleViewer(Composite parent) {
110         super(parent, getSWTStyles());
111         
112         getTextWidget().setDoubleClickEnabled(true);
113         
114         DebugUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this);
115         JFaceResources.getFontRegistry().addListener(this);
116
117         getTextWidget().setFont(JFaceResources.getFont(IConsoleConstants.CONSOLE_FONT));
118         getTextWidget().addMouseTrackListener(this);
119         getTextWidget().addPaintListener(this);
120         getTextWidget().addLineStyleListener(this);
121         getTextWidget().addListener(SWT.KeyUp, this);
122         getTextWidget().setTabs(DebugUIPlugin.getDefault().getPluginPreferences().getInt(IDebugPreferenceConstants.CONSOLE_TAB_WIDTH));
123     }
124     
125     /**
126      * Returns the SWT style flags used when instantiating this viewer
127      */

128     private static int getSWTStyles() {
129         int styles= SWT.H_SCROLL | SWT.V_SCROLL;
130         return styles;
131     }
132
133     /**
134      * Reveals (makes visible) the end of the current document
135      */

136     protected void revealEndOfDocument() {
137         if (isAutoScroll()) {
138             IDocument doc = getDocument();
139             int lines = doc.getNumberOfLines();
140             try {
141                 // lines are 0-based
142
int lineStartOffset = doc.getLineOffset(lines - 1);
143                 StyledText widget= getTextWidget();
144                 if (lineStartOffset > 0) {
145                     widget.setCaretOffset(lineStartOffset);
146                     widget.showSelection();
147                 }
148                 int lineEndOffset = lineStartOffset + doc.getLineLength(lines - 1);
149                 if (lineEndOffset > 0) {
150                     widget.setCaretOffset(lineEndOffset);
151                 }
152             } catch (BadLocationException e) {
153             }
154         }
155     }
156
157     /**
158      * @see ITextViewer#setDocument(IDocument)
159      */

160     public void setDocument(IDocument doc) {
161         IDocument oldDoc= getDocument();
162         IDocument document= doc;
163         if (oldDoc == null && document == null) {
164             return;
165         }
166         if (oldDoc != null) {
167             oldDoc.removeDocumentListener(fInternalDocumentListener);
168             if (oldDoc.equals(document)) {
169                 document.addDocumentListener(fInternalDocumentListener);
170                 return;
171             }
172         }
173
174         super.setDocument(document);
175         if (document != null) {
176             revealEndOfDocument();
177             document.addDocumentListener(fInternalDocumentListener);
178         }
179     }
180     
181     /**
182      * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
183      */

184     public void propertyChange(PropertyChangeEvent event) {
185         String JavaDoc propertyName= event.getProperty();
186         if (propertyName.equals(IDebugPreferenceConstants.CONSOLE_SYS_IN_COLOR) ||
187             propertyName.equals(IDebugPreferenceConstants.CONSOLE_SYS_OUT_COLOR) ||
188             propertyName.equals(IDebugPreferenceConstants.CONSOLE_SYS_ERR_COLOR)) {
189                 getTextWidget().redraw();
190         } else if (propertyName.equals(IConsoleConstants.CONSOLE_FONT)) {
191             getTextWidget().setFont(JFaceResources.getFont(IConsoleConstants.CONSOLE_FONT));
192         } else if (propertyName.equals(IDebugPreferenceConstants.CONSOLE_TAB_WIDTH)) {
193             getTextWidget().setTabs(DebugUIPlugin.getDefault().getPluginPreferences().getInt(IDebugPreferenceConstants.CONSOLE_TAB_WIDTH));
194         } else if (propertyName.equals(IInternalDebugUIConstants.PREF_CONSOLE_SCROLL_LOCK)) {
195             setAutoScroll(!DebugUIPlugin.getDefault().getPluginPreferences().getBoolean(IInternalDebugUIConstants.PREF_CONSOLE_SCROLL_LOCK));
196         }
197     }
198     
199     /**
200      * Dispose this viewer and resources
201      */

202     public void dispose() {
203         Control control = getTextWidget();
204         if (control != null) {
205             control.removeMouseTrackListener(this);
206             control.removePaintListener(this);
207         }
208         if (fHandCursor != null) {
209             fHandCursor.dispose();
210         }
211         if (fTextCursor != null) {
212             fTextCursor.dispose();
213         }
214         DebugUIPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this);
215         JFaceResources.getFontRegistry().removeListener(this);
216     }
217     
218     /**
219      * Only allow text to be typed at the end of the document.
220      *
221      * @see org.eclipse.swt.events.VerifyListener#verifyText(org.eclipse.swt.events.VerifyEvent)
222      */

223     protected void handleVerifyEvent(VerifyEvent e) {
224         ConsoleDocument doc= (ConsoleDocument)getDocument();
225         if (doc != null) {
226             if (doc.isReadOnly()) {
227                 e.doit = false;
228                 return;
229             }
230             IDocumentPartitioner partitioner = doc.getDocumentPartitioner();
231             if (partitioner != null) {
232                 int length = doc.getLength();
233                 ITypedRegion[] partitions = partitioner.computePartitioning(length, 0);
234                 if (partitions.length == 0) {
235                 } else {
236                     ITypedRegion partition = partitions[partitions.length - 1];
237                     if (partition.getType().equals(InputPartition.INPUT_PARTITION_TYPE)) {
238                         // > 1 char in the input buffer
239
e.doit = (e.start >= partition.getOffset()) && (e.end <= (partition.getLength() + partition.getOffset()));
240                     } else {
241                         // first character in the input buffer
242
e.doit = length == e.start;
243                     }
244                 }
245             }
246         }
247     }
248     
249     /**
250      * @see org.eclipse.swt.events.MouseTrackListener#mouseEnter(org.eclipse.swt.events.MouseEvent)
251      */

252     public void mouseEnter(MouseEvent e) {
253         getTextWidget().addMouseMoveListener(this);
254     }
255
256     /**
257      * @see org.eclipse.swt.events.MouseTrackListener#mouseExit(org.eclipse.swt.events.MouseEvent)
258      */

259     public void mouseExit(MouseEvent e) {
260         getTextWidget().removeMouseMoveListener(this);
261         if (fHyperLink != null) {
262             linkExited(fHyperLink);
263         }
264     }
265
266     /**
267      * @see org.eclipse.swt.events.MouseTrackListener#mouseHover(org.eclipse.swt.events.MouseEvent)
268      */

269     public void mouseHover(MouseEvent e) {
270     }
271
272     /**
273      * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
274      */

275     public void mouseMove(MouseEvent e) {
276         int offset = -1;
277         try {
278             Point p = new Point(e.x, e.y);
279             offset = getTextWidget().getOffsetAtLocation(p);
280         } catch (IllegalArgumentException JavaDoc ex) {
281             // out of the document range
282
}
283         updateLinks(offset);
284     }
285
286     public IConsoleHyperlink getHyperlink(int offset) {
287         if (offset >= 0 && getDocument() != null) {
288             Position[] positions = null;
289             try {
290                 positions = getDocument().getPositions(HyperlinkPosition.HYPER_LINK_CATEGORY);
291             } catch (BadPositionCategoryException ex) {
292                 // no links have been added
293
return null;
294             }
295             for (int i = 0; i < positions.length; i++) {
296                 Position position = positions[i];
297                 if (offset >= position.getOffset() && offset <= (position.getOffset() + position.getLength())) {
298                     return ((HyperlinkPosition)position).getHyperLink();
299                 }
300             }
301         }
302         return null;
303     }
304
305     protected void linkEntered(IConsoleHyperlink link) {
306         Control control = getTextWidget();
307         control.setRedraw(false);
308         if (fHyperLink != null) {
309             linkExited(fHyperLink);
310         }
311         fHyperLink = link;
312         fHyperLink.linkEntered();
313         control.setCursor(getHandCursor());
314         control.setRedraw(true);
315         control.redraw();
316         control.addMouseListener(this);
317     }
318     
319     protected void linkExited(IConsoleHyperlink link) {
320         link.linkExited();
321         fHyperLink = null;
322         Control control = getTextWidget();
323         control.setCursor(getTextCursor());
324         control.redraw();
325         control.removeMouseListener(this);
326     }
327     /**
328      * @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent)
329      */

330     public void paintControl(PaintEvent e) {
331         if (fHyperLink != null) {
332             IDocument doc = getDocument();
333             if (doc == null) {
334                 return;
335             }
336             ConsoleDocumentPartitioner partitioner = (ConsoleDocumentPartitioner)doc.getDocumentPartitioner();
337             if (partitioner == null) {
338                 return;
339             }
340             IRegion linkRegion = partitioner.getRegion(fHyperLink);
341             if (linkRegion != null) {
342                 int start = linkRegion.getOffset();
343                 int end = start + linkRegion.getLength();
344                 IConsoleColorProvider colorProvider = partitioner.getColorProvider();
345                 try {
346                     ITypedRegion partition = doc.getPartition(start);
347                     Color fontColor = e.gc.getForeground();
348                     if (partition instanceof StreamPartition) {
349                         StreamPartition streamPartition = (StreamPartition)partition;
350                         fontColor = colorProvider.getColor(streamPartition.getStreamIdentifier());
351                     }
352                     int startLine = doc.getLineOfOffset(start);
353                     int endLine = doc.getLineOfOffset(end);
354                     for (int i = startLine; i <= endLine; i++) {
355                         IRegion lineRegion = doc.getLineInformation(i);
356                         int lineStart = lineRegion.getOffset();
357                         int lineEnd = lineStart + lineRegion.getLength();
358                         Color color = e.gc.getForeground();
359                         e.gc.setForeground(fontColor);
360                         if (lineStart < end) {
361                             lineStart = Math.max(start, lineStart);
362                             lineEnd = Math.min(end, lineEnd);
363                             Point p1 = getTextWidget().getLocationAtOffset(lineStart);
364                             Point p2 = getTextWidget().getLocationAtOffset(lineEnd);
365                             FontMetrics metrics = e.gc.getFontMetrics();
366                             int height = metrics.getHeight();
367                             e.gc.drawLine(p1.x, p1.y + height, p2.x, p2.y + height);
368                         }
369                         e.gc.setForeground(color);
370                     }
371                 } catch (BadLocationException ex) {
372                 }
373             }
374         }
375     }
376     
377     protected Cursor getHandCursor() {
378         if (fHandCursor == null) {
379             fHandCursor = new Cursor(DebugUIPlugin.getStandardDisplay(), SWT.CURSOR_HAND);
380         }
381         return fHandCursor;
382     }
383     
384     protected Cursor getTextCursor() {
385         if (fTextCursor == null) {
386             fTextCursor = new Cursor(DebugUIPlugin.getStandardDisplay(), SWT.CURSOR_IBEAM);
387         }
388         return fTextCursor;
389     }
390
391     /**
392      * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
393      */

394     public void mouseDoubleClick(MouseEvent e) {
395     }
396
397     /**
398      * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
399      */

400     public void mouseDown(MouseEvent e) {
401     }
402
403     /**
404      * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
405      */

406     public void mouseUp(MouseEvent e) {
407         if (fHyperLink != null) {
408             String JavaDoc selection = getTextWidget().getSelectionText();
409             if (selection.length() <= 0) {
410                 if (e.button == 1) {
411                     fHyperLink.linkActivated();
412                 }
413             }
414         }
415     }
416
417     /**
418      * @see org.eclipse.swt.custom.LineStyleListener#lineGetStyle(org.eclipse.swt.custom.LineStyleEvent)
419      */

420     public void lineGetStyle(LineStyleEvent event) {
421         IDocument document = getDocument();
422         if (document != null) {
423             ConsoleDocumentPartitioner partitioner = (ConsoleDocumentPartitioner)document.getDocumentPartitioner();
424             if (partitioner != null) {
425                 IConsoleColorProvider colorProvider = partitioner.getColorProvider();
426                 ITypedRegion[] regions = partitioner.computePartitioning(event.lineOffset, event.lineOffset + event.lineText.length());
427                 StyleRange[] styles = new StyleRange[regions.length];
428                 for (int i = 0; i < regions.length; i++) {
429                     StreamPartition partition = (StreamPartition)regions[i];
430                     Color color = colorProvider.getColor(partition.getStreamIdentifier());
431                     styles[i] = new StyleRange(partition.getOffset(), partition.getLength(), color, null);
432                 }
433                 event.styles = styles;
434             }
435         }
436     }
437     
438     /**
439      * Sets whether this viewer should auto-scroll as output is appended to the
440      * document.
441      *
442      * @param scroll
443      */

444     public void setAutoScroll(boolean scroll) {
445         fAutoScroll = scroll;
446     }
447     
448     /**
449      * Returns whether this viewer should auto-scroll as output is appended to
450      * the document.
451      */

452     public boolean isAutoScroll() {
453         return fAutoScroll;
454     }
455
456     /**
457      * On KeyUp events, see if we need to enter/exit a link.
458      *
459      * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
460      */

461     public void handleEvent(Event event) {
462         int offset = getTextWidget().getCaretOffset();
463         updateLinks(offset);
464     }
465     
466     /**
467      * The cursor has just be moved to the given offset, the mouse has
468      * hovered over the given offset. Update link rendering.
469      *
470      * @param offset
471      */

472     protected void updateLinks(int offset) {
473         if (offset >= 0) {
474             IConsoleHyperlink link = getHyperlink(offset);
475             if (link != null) {
476                 if (link.equals(fHyperLink)) {
477                     return;
478                 } else {
479                     linkEntered(link);
480                     return;
481                 }
482             }
483         }
484         if (fHyperLink != null) {
485             linkExited(fHyperLink);
486         }
487     }
488
489 }
490
491
Popular Tags