KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > text > information > InformationPresenter


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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 package org.eclipse.jface.text.information;
12
13 import java.util.HashMap JavaDoc;
14 import java.util.Map JavaDoc;
15
16 import org.eclipse.swt.custom.StyledText;
17 import org.eclipse.swt.events.ControlEvent;
18 import org.eclipse.swt.events.ControlListener;
19 import org.eclipse.swt.events.FocusEvent;
20 import org.eclipse.swt.events.FocusListener;
21 import org.eclipse.swt.events.KeyEvent;
22 import org.eclipse.swt.events.KeyListener;
23 import org.eclipse.swt.events.MouseEvent;
24 import org.eclipse.swt.events.MouseListener;
25 import org.eclipse.swt.graphics.Point;
26 import org.eclipse.swt.graphics.Rectangle;
27 import org.eclipse.swt.widgets.Control;
28 import org.eclipse.swt.widgets.Display;
29
30 import org.eclipse.core.runtime.Assert;
31
32 import org.eclipse.jface.text.AbstractInformationControlManager;
33 import org.eclipse.jface.text.BadLocationException;
34 import org.eclipse.jface.text.IDocumentExtension3;
35 import org.eclipse.jface.text.IInformationControl;
36 import org.eclipse.jface.text.IInformationControlCreator;
37 import org.eclipse.jface.text.IRegion;
38 import org.eclipse.jface.text.ITextViewer;
39 import org.eclipse.jface.text.ITextViewerExtension5;
40 import org.eclipse.jface.text.IViewportListener;
41 import org.eclipse.jface.text.IWidgetTokenKeeper;
42 import org.eclipse.jface.text.IWidgetTokenKeeperExtension;
43 import org.eclipse.jface.text.IWidgetTokenOwner;
44 import org.eclipse.jface.text.IWidgetTokenOwnerExtension;
45 import org.eclipse.jface.text.Region;
46 import org.eclipse.jface.text.TextUtilities;
47
48
49 /**
50  * Standard implementation of <code>IInformationPresenter</code>.
51  * This implementation extends <code>AbstractInformationControlManager</code>.
52  * The information control is made visible on request by calling
53  * {@link #showInformationControl(Rectangle)}.
54  * <p>
55  * Usually, clients instantiate this class and configure it before using it. The configuration
56  * must be consistent: This means the used {@link org.eclipse.jface.text.IInformationControlCreator}
57  * must create an information control expecting information in the same format the configured
58  * {@link org.eclipse.jface.text.information.IInformationProvider}s use to encode the information they provide.
59  * </p>
60  *
61  * @since 2.0
62  */

63 public class InformationPresenter extends AbstractInformationControlManager implements IInformationPresenter, IInformationPresenterExtension, IWidgetTokenKeeper, IWidgetTokenKeeperExtension {
64
65
66     /**
67      * Priority of the info controls managed by this information presenter.
68      * Default value: <code>5</code>.
69      *
70      * @since 3.0
71      */

72     /*
73      * 5 as value has been chosen in order to beat the hovers of {@link org.eclipse.jface.text.TextViewerHoverManager}
74      */

75     public static final int WIDGET_PRIORITY= 5;
76
77
78     /**
79      * Internal information control closer. Listens to several events issued by its subject control
80      * and closes the information control when necessary.
81      */

82     class Closer implements IInformationControlCloser, ControlListener, MouseListener, FocusListener, IViewportListener, KeyListener {
83
84         /** The subject control. */
85         private Control fSubjectControl;
86         /** The information control. */
87         private IInformationControl fInformationControlToClose;
88         /** Indicates whether this closer is active. */
89         private boolean fIsActive= false;
90
91         /*
92          * @see IInformationControlCloser#setSubjectControl(Control)
93          */

94         public void setSubjectControl(Control control) {
95             fSubjectControl= control;
96         }
97
98         /*
99          * @see IInformationControlCloser#setInformationControl(IInformationControl)
100          */

101         public void setInformationControl(IInformationControl control) {
102             fInformationControlToClose= control;
103         }
104
105         /*
106          * @see IInformationControlCloser#start(Rectangle)
107          */

108         public void start(Rectangle informationArea) {
109
110             if (fIsActive)
111                 return;
112             fIsActive= true;
113
114             if (fSubjectControl != null && ! fSubjectControl.isDisposed()) {
115                 fSubjectControl.addControlListener(this);
116                 fSubjectControl.addMouseListener(this);
117                 fSubjectControl.addFocusListener(this);
118                 fSubjectControl.addKeyListener(this);
119             }
120
121             if (fInformationControlToClose != null)
122                 fInformationControlToClose.addFocusListener(this);
123
124             fTextViewer.addViewportListener(this);
125         }
126
127         /*
128          * @see IInformationControlCloser#stop()
129          */

130         public void stop() {
131
132             if (!fIsActive)
133                 return;
134             fIsActive= false;
135
136             fTextViewer.removeViewportListener(this);
137
138             if (fInformationControlToClose != null)
139                 fInformationControlToClose.removeFocusListener(this);
140
141             hideInformationControl();
142
143             if (fSubjectControl != null && !fSubjectControl.isDisposed()) {
144                 fSubjectControl.removeControlListener(this);
145                 fSubjectControl.removeMouseListener(this);
146                 fSubjectControl.removeFocusListener(this);
147                 fSubjectControl.removeKeyListener(this);
148             }
149         }
150
151         /*
152          * @see ControlListener#controlResized(ControlEvent)
153          */

154          public void controlResized(ControlEvent e) {
155             stop();
156         }
157
158         /*
159          * @see ControlListener#controlMoved(ControlEvent)
160          */

161          public void controlMoved(ControlEvent e) {
162             stop();
163         }
164
165         /*
166          * @see MouseListener#mouseDown(MouseEvent)
167          */

168          public void mouseDown(MouseEvent e) {
169             stop();
170         }
171
172         /*
173          * @see MouseListener#mouseUp(MouseEvent)
174          */

175         public void mouseUp(MouseEvent e) {
176         }
177
178         /*
179          * @see MouseListener#mouseDoubleClick(MouseEvent)
180          */

181         public void mouseDoubleClick(MouseEvent e) {
182             stop();
183         }
184
185         /*
186          * @see FocusListener#focusGained(FocusEvent)
187          */

188         public void focusGained(FocusEvent e) {
189         }
190
191         /*
192          * @see FocusListener#focusLost(FocusEvent)
193          */

194          public void focusLost(FocusEvent e) {
195             Display d= fSubjectControl.getDisplay();
196             d.asyncExec(new Runnable JavaDoc() {
197                 public void run() {
198                     if (fInformationControlToClose == null || !fInformationControlToClose.isFocusControl())
199                         stop();
200                 }
201             });
202         }
203
204         /*
205          * @see IViewportListenerListener#viewportChanged(int)
206          */

207         public void viewportChanged(int topIndex) {
208             stop();
209         }
210
211         /*
212          * @see KeyListener#keyPressed(KeyEvent)
213          */

214         public void keyPressed(KeyEvent e) {
215             stop();
216         }
217
218         /*
219          * @see KeyListener#keyReleased(KeyEvent)
220          */

221         public void keyReleased(KeyEvent e) {
222         }
223     }
224
225
226     /** The text viewer this information presenter works on */
227     private ITextViewer fTextViewer;
228     /** The map of <code>IInformationProvider</code> objects */
229     private Map JavaDoc fProviders;
230     /** The offset to override selection. */
231     private int fOffset= -1;
232     /**
233      * The document partitioning for this information presenter.
234      * @since 3.0
235      */

236     private String JavaDoc fPartitioning;
237
238     /**
239      * Creates a new information presenter that uses the given information control creator.
240      * The presenter is not installed on any text viewer yet. By default, an information
241      * control closer is set that closes the information control in the event of key strokes,
242      * resizing, moves, focus changes, mouse clicks, and disposal - all of those applied to
243      * the information control's parent control. Also, the setup ensures that the information
244      * control when made visible will request the focus. By default, the default document
245      * partitioning {@link IDocumentExtension3#DEFAULT_PARTITIONING} is used.
246      *
247      * @param creator the information control creator to be used
248      */

249     public InformationPresenter(IInformationControlCreator creator) {
250         super(creator);
251         setCloser(new Closer());
252         takesFocusWhenVisible(true);
253         fPartitioning= IDocumentExtension3.DEFAULT_PARTITIONING;
254     }
255
256     /**
257      * Sets the document partitioning to be used by this information presenter.
258      *
259      * @param partitioning the document partitioning to be used by this information presenter
260      * @since 3.0
261      */

262     public void setDocumentPartitioning(String JavaDoc partitioning) {
263         Assert.isNotNull(partitioning);
264         fPartitioning= partitioning;
265     }
266
267     /*
268      * @see org.eclipse.jface.text.information.IInformationPresenterExtension#getDocumentPartitioning()
269      * @since 3.0
270      */

271     public String JavaDoc getDocumentPartitioning() {
272         return fPartitioning;
273     }
274
275     /**
276      * Registers a given information provider for a particular content type.
277      * If there is already a provider registered for this type, the new provider
278      * is registered instead of the old one.
279      *
280      * @param provider the information provider to register, or <code>null</code> to remove an existing one
281      * @param contentType the content type under which to register
282      */

283      public void setInformationProvider(IInformationProvider provider, String JavaDoc contentType) {
284
285         Assert.isNotNull(contentType);
286
287         if (fProviders == null)
288             fProviders= new HashMap JavaDoc();
289
290         if (provider == null)
291             fProviders.remove(contentType);
292         else
293             fProviders.put(contentType, provider);
294     }
295
296     /*
297      * @see IInformationPresenter#getInformationProvider(String)
298      */

299     public IInformationProvider getInformationProvider(String JavaDoc contentType) {
300         if (fProviders == null)
301             return null;
302
303         return (IInformationProvider) fProviders.get(contentType);
304     }
305
306     /**
307      * Sets a offset to override the selection. Setting the value to <code>-1</code> will disable
308      * overriding.
309      *
310      * @param offset the offset to override selection or <code>-1</code>
311      */

312     public void setOffset(int offset) {
313         fOffset= offset;
314     }
315
316     /*
317      * @see AbstractInformationControlManager#computeInformation()
318      */

319     protected void computeInformation() {
320
321         int offset= fOffset < 0 ? fTextViewer.getSelectedRange().x : fOffset;
322         if (offset == -1)
323             return;
324
325         fOffset= -1;
326
327         IInformationProvider provider= null;
328         try {
329             String JavaDoc contentType= TextUtilities.getContentType(fTextViewer.getDocument(), getDocumentPartitioning(), offset, true);
330             provider= getInformationProvider(contentType);
331         } catch (BadLocationException x) {
332         }
333         if (provider == null)
334             return;
335
336         IRegion subject= provider.getSubject(fTextViewer, offset);
337         if (subject == null)
338             return;
339
340         if (provider instanceof IInformationProviderExtension2)
341             setCustomInformationControlCreator(((IInformationProviderExtension2) provider).getInformationPresenterControlCreator());
342         else
343             setCustomInformationControlCreator(null);
344
345         if (provider instanceof IInformationProviderExtension) {
346             IInformationProviderExtension extension= (IInformationProviderExtension) provider;
347             setInformation(extension.getInformation2(fTextViewer, subject), computeArea(subject));
348         } else {
349             // backward compatibility code
350
setInformation(provider.getInformation(fTextViewer, subject), computeArea(subject));
351         }
352     }
353
354     /**
355      * Determines the graphical area covered by the given text region.
356      *
357      * @param region the region whose graphical extend must be computed
358      * @return the graphical extend of the given region
359      */

360     private Rectangle computeArea(IRegion region) {
361
362         int start= 0;
363         int end= 0;
364
365         IRegion widgetRegion= modelRange2WidgetRange(region);
366         if (widgetRegion != null) {
367             start= widgetRegion.getOffset();
368             end= widgetRegion.getOffset() + widgetRegion.getLength();
369         }
370         
371         StyledText styledText= fTextViewer.getTextWidget();
372         Rectangle bounds;
373         if (end > 0 && start < end)
374             bounds= styledText.getTextBounds(start, end - 1);
375         else {
376             Point loc= styledText.getLocationAtOffset(start);
377             bounds= new Rectangle(loc.x, loc.y, 0, styledText.getLineHeight(start));
378         }
379         
380         return bounds;
381     }
382
383     /**
384      * Translated the given range in the viewer's document into the corresponding
385      * range of the viewer's widget.
386      *
387      * @param region the range in the viewer's document
388      * @return the corresponding widget range
389      * @since 2.1
390      */

391     private IRegion modelRange2WidgetRange(IRegion region) {
392         if (fTextViewer instanceof ITextViewerExtension5) {
393             ITextViewerExtension5 extension= (ITextViewerExtension5) fTextViewer;
394             return extension.modelRange2WidgetRange(region);
395         }
396
397         IRegion visibleRegion= fTextViewer.getVisibleRegion();
398         int start= region.getOffset() - visibleRegion.getOffset();
399         int end= start + region.getLength();
400         if (end > visibleRegion.getLength())
401             end= visibleRegion.getLength();
402
403         return new Region(start, end - start);
404     }
405
406     /*
407      * @see IInformationPresenter#install(ITextViewer)
408      */

409     public void install(ITextViewer textViewer) {
410         fTextViewer= textViewer;
411         install(fTextViewer.getTextWidget());
412     }
413
414     /*
415      * @see IInformationPresenter#uninstall()
416      */

417     public void uninstall() {
418         dispose();
419     }
420
421     /*
422      * @see AbstractInformationControlManager#showInformationControl(Rectangle)
423      */

424     protected void showInformationControl(Rectangle subjectArea) {
425         if (fTextViewer instanceof IWidgetTokenOwnerExtension) {
426             IWidgetTokenOwnerExtension extension= (IWidgetTokenOwnerExtension) fTextViewer;
427             if (extension.requestWidgetToken(this, WIDGET_PRIORITY))
428                 super.showInformationControl(subjectArea);
429         } else if (fTextViewer instanceof IWidgetTokenOwner) {
430             IWidgetTokenOwner owner= (IWidgetTokenOwner) fTextViewer;
431             if (owner.requestWidgetToken(this))
432                 super.showInformationControl(subjectArea);
433
434         }
435     }
436
437     /*
438      * @see AbstractInformationControlManager#hideInformationControl()
439      */

440     protected void hideInformationControl() {
441         try {
442             super.hideInformationControl();
443         } finally {
444             if (fTextViewer instanceof IWidgetTokenOwner) {
445                 IWidgetTokenOwner owner= (IWidgetTokenOwner) fTextViewer;
446                 owner.releaseWidgetToken(this);
447             }
448         }
449     }
450
451     /*
452      * @see AbstractInformationControlManager#handleInformationControlDisposed()
453      */

454     protected void handleInformationControlDisposed() {
455         try {
456             super.handleInformationControlDisposed();
457         } finally {
458             if (fTextViewer instanceof IWidgetTokenOwner) {
459                 IWidgetTokenOwner owner= (IWidgetTokenOwner) fTextViewer;
460                 owner.releaseWidgetToken(this);
461             }
462         }
463     }
464
465     /*
466      * @see org.eclipse.jface.text.IWidgetTokenKeeper#requestWidgetToken(IWidgetTokenOwner)
467      */

468     public boolean requestWidgetToken(IWidgetTokenOwner owner) {
469         return false;
470     }
471
472     /*
473      * @see org.eclipse.jface.text.IWidgetTokenKeeperExtension#requestWidgetToken(org.eclipse.jface.text.IWidgetTokenOwner, int)
474      * @since 3.0
475      */

476     public boolean requestWidgetToken(IWidgetTokenOwner owner, int priority) {
477         return false;
478     }
479
480     /*
481      * @see org.eclipse.jface.text.IWidgetTokenKeeperExtension#setFocus(org.eclipse.jface.text.IWidgetTokenOwner)
482      * @since 3.0
483      */

484     public boolean setFocus(IWidgetTokenOwner owner) {
485         return false;
486     }
487 }
488
489
Popular Tags