KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > internal > text > link > contentassist > ContentAssistant2


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 package org.eclipse.jface.internal.text.link.contentassist;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.HashMap JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.List JavaDoc;
17 import java.util.Map JavaDoc;
18
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.SWTError;
21 import org.eclipse.swt.custom.StyledText;
22 import org.eclipse.swt.custom.VerifyKeyListener;
23 import org.eclipse.swt.events.ControlEvent;
24 import org.eclipse.swt.events.ControlListener;
25 import org.eclipse.swt.events.DisposeEvent;
26 import org.eclipse.swt.events.DisposeListener;
27 import org.eclipse.swt.events.FocusEvent;
28 import org.eclipse.swt.events.FocusListener;
29 import org.eclipse.swt.events.MouseEvent;
30 import org.eclipse.swt.events.MouseListener;
31 import org.eclipse.swt.events.VerifyEvent;
32 import org.eclipse.swt.graphics.Color;
33 import org.eclipse.swt.graphics.Point;
34 import org.eclipse.swt.graphics.Rectangle;
35 import org.eclipse.swt.widgets.Control;
36 import org.eclipse.swt.widgets.Display;
37 import org.eclipse.swt.widgets.Event;
38 import org.eclipse.swt.widgets.Listener;
39 import org.eclipse.swt.widgets.Shell;
40 import org.eclipse.swt.widgets.Widget;
41
42 import org.eclipse.core.runtime.Assert;
43
44 import org.eclipse.jface.internal.text.html.HTMLTextPresenter;
45
46 import org.eclipse.jface.text.BadLocationException;
47 import org.eclipse.jface.text.DefaultInformationControl;
48 import org.eclipse.jface.text.IEventConsumer;
49 import org.eclipse.jface.text.IInformationControl;
50 import org.eclipse.jface.text.IInformationControlCreator;
51 import org.eclipse.jface.text.ITextViewer;
52 import org.eclipse.jface.text.ITextViewerExtension;
53 import org.eclipse.jface.text.IViewportListener;
54 import org.eclipse.jface.text.IWidgetTokenKeeper;
55 import org.eclipse.jface.text.IWidgetTokenKeeperExtension;
56 import org.eclipse.jface.text.IWidgetTokenOwner;
57 import org.eclipse.jface.text.IWidgetTokenOwnerExtension;
58 import org.eclipse.jface.text.TextUtilities;
59 import org.eclipse.jface.text.contentassist.CompletionProposal;
60 import org.eclipse.jface.text.contentassist.ICompletionProposal;
61 import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
62 import org.eclipse.jface.text.contentassist.IContentAssistant;
63 import org.eclipse.jface.text.contentassist.IContentAssistantExtension;
64 import org.eclipse.jface.text.contentassist.IContextInformation;
65 import org.eclipse.jface.text.contentassist.IContextInformationPresenter;
66 import org.eclipse.jface.text.contentassist.IContextInformationValidator;
67
68
69 /**
70  * A custom implementation of the <code>IContentAssistant</code> interface.
71  * This implementation is used by the linked mode UI. This is internal and subject
72  * to change without notice.
73  */

74 public class ContentAssistant2 implements IContentAssistant, IContentAssistantExtension, IWidgetTokenKeeper, IWidgetTokenKeeperExtension {
75
76     /**
77      * A generic closer class used to monitor various
78      * interface events in order to determine whether
79      * content-assist should be terminated and all
80      * associated windows closed.
81      */

82     class Closer implements ControlListener, MouseListener, FocusListener, DisposeListener, IViewportListener {
83
84         /** The shell on which we add listeners. */
85         private Shell fShell;
86
87         /**
88          * Installs this closer on it's viewer's text widget.
89          */

90         protected void install() {
91             Control w= fViewer.getTextWidget();
92             if (Helper2.okToUse(w)) {
93
94                 Shell shell= w.getShell();
95                 fShell= shell;
96                 shell.addControlListener(this);
97
98                 w.addMouseListener(this);
99                 w.addFocusListener(this);
100
101                 /*
102                  * 1GGYYWK: ITPJUI:ALL - Dismissing editor with code assist up causes lots of Internal Errors
103                  */

104                 w.addDisposeListener(this);
105             }
106
107             fViewer.addViewportListener(this);
108         }
109
110         /**
111          * Uninstalls this closer from the viewer's text widget.
112          */

113         protected void uninstall() {
114             Shell shell= fShell;
115             fShell= null;
116             if (Helper2.okToUse(shell))
117                 shell.removeControlListener(this);
118
119             Control w= fViewer.getTextWidget();
120             if (Helper2.okToUse(w)) {
121
122                 w.removeMouseListener(this);
123                 w.removeFocusListener(this);
124
125                 /*
126                  * 1GGYYWK: ITPJUI:ALL - Dismissing editor with code assist up causes lots of Internal Errors
127                  */

128                 w.removeDisposeListener(this);
129             }
130
131             fViewer.removeViewportListener(this);
132         }
133
134         /*
135          * @see ControlListener#controlResized(ControlEvent)
136          */

137         public void controlResized(ControlEvent e) {
138             hide();
139         }
140
141         /*
142          * @see ControlListener#controlMoved(ControlEvent)
143          */

144         public void controlMoved(ControlEvent e) {
145             hide();
146         }
147
148         /*
149          * @see MouseListener#mouseDown(MouseEvent)
150          */

151         public void mouseDown(MouseEvent e) {
152             hide();
153         }
154
155         /*
156          * @see MouseListener#mouseUp(MouseEvent)
157          */

158         public void mouseUp(MouseEvent e) {
159         }
160
161         /*
162          * @see MouseListener#mouseDoubleClick(MouseEvent)
163          */

164         public void mouseDoubleClick(MouseEvent e) {
165             hide();
166         }
167
168         /*
169          * @see FocusListener#focusGained(FocusEvent)
170          */

171         public void focusGained(FocusEvent e) {
172         }
173
174         /*
175          * @see FocusListener#focusLost(FocusEvent)
176          */

177         public void focusLost(FocusEvent e) {
178             if (fViewer != null) {
179                 Control control= fViewer.getTextWidget();
180                 if (control != null) {
181                     Display d= control.getDisplay();
182                     if (d != null) {
183                         d.asyncExec(new Runnable JavaDoc() {
184                             public void run() {
185                                 if (!hasFocus())
186                                     hide();
187                             }
188                         });
189                     }
190                 }
191             }
192         }
193
194         /*
195          * @seeDisposeListener#widgetDisposed(DisposeEvent)
196          */

197         public void widgetDisposed(DisposeEvent e) {
198             /*
199              * 1GGYYWK: ITPJUI:ALL - Dismissing editor with code assist up causes lots of Internal Errors
200              */

201             hide();
202         }
203
204         /*
205          * @see IViewportListener#viewportChanged(int)
206          */

207         public void viewportChanged(int topIndex) {
208             hide();
209         }
210     }
211
212     /**
213      * An implementation of <code>IContentAssistListener</code>, this class is
214      * used to monitor key events in support of automatic activation
215      * of the content assistant. If enabled, the implementation utilizes a
216      * thread to watch for input characters matching the activation
217      * characters specified by the content assist processor, and if
218      * detected, will wait the indicated delay interval before
219      * activating the content assistant.
220      */

221     class AutoAssistListener implements VerifyKeyListener, Runnable JavaDoc {
222
223         private Thread JavaDoc fThread;
224         private boolean fIsReset= false;
225         private Object JavaDoc fMutex= new Object JavaDoc();
226         private int fShowStyle;
227
228         private final static int SHOW_PROPOSALS= 1;
229         private final static int SHOW_CONTEXT_INFO= 2;
230
231         protected AutoAssistListener() {
232         }
233
234         protected void start(int showStyle) {
235             fShowStyle= showStyle;
236             fThread= new Thread JavaDoc(this, ContentAssistMessages.getString("ContentAssistant.assist_delay_timer_name")); //$NON-NLS-1$
237
fThread.start();
238         }
239
240         public void run() {
241             try {
242                 while (true) {
243                     synchronized (fMutex) {
244                         if (fAutoActivationDelay != 0)
245                             fMutex.wait(fAutoActivationDelay);
246                         if (fIsReset) {
247                             fIsReset= false;
248                             continue;
249                         }
250                     }
251                     showAssist(fShowStyle);
252                     break;
253                 }
254             } catch (InterruptedException JavaDoc e) {
255             }
256             fThread= null;
257         }
258
259         protected void reset(int showStyle) {
260             synchronized (fMutex) {
261                 fShowStyle= showStyle;
262                 fIsReset= true;
263                 fMutex.notifyAll();
264             }
265         }
266
267         protected void stop() {
268             Thread JavaDoc threadToStop= fThread;
269             if (threadToStop != null)
270                 threadToStop.interrupt();
271         }
272
273         private boolean contains(char[] characters, char character) {
274             if (characters != null) {
275                 for (int i= 0; i < characters.length; i++) {
276                     if (character == characters[i])
277                         return true;
278                 }
279             }
280             return false;
281         }
282
283         public void verifyKey(VerifyEvent e) {
284             // Only act on typed characters and ignore modifier-only events
285
if (e.character == 0 && (e.keyCode & SWT.KEYCODE_BIT) == 0)
286                 return;
287
288             if (e.character != 0 && (e.stateMask == SWT.ALT))
289                 return;
290
291             int showStyle;
292             int pos= fViewer.getSelectedRange().x;
293             char[] activation= getCompletionProposalAutoActivationCharacters(fViewer, pos);
294
295             if (contains(activation, e.character) && !fProposalPopup.isActive())
296                 showStyle= SHOW_PROPOSALS;
297             else {
298                 activation= getContextInformationAutoActivationCharacters(fViewer, pos);
299                 if (contains(activation, e.character) && !fContextInfoPopup.isActive())
300                     showStyle= SHOW_CONTEXT_INFO;
301                 else {
302                     if (fThread != null && fThread.isAlive())
303                         stop();
304                     return;
305                 }
306             }
307
308             if (fThread != null && fThread.isAlive())
309                 reset(showStyle);
310             else
311                 start(showStyle);
312         }
313
314         protected void showAssist(final int showStyle) {
315             Control control= fViewer.getTextWidget();
316             Display d= control.getDisplay();
317             if (d != null) {
318                 try {
319                     d.syncExec(new Runnable JavaDoc() {
320                         public void run() {
321                             if (showStyle == SHOW_PROPOSALS)
322                                 fProposalPopup.showProposals(true);
323                             else if (showStyle == SHOW_CONTEXT_INFO)
324                                 fContextInfoPopup.showContextProposals(true);
325                         }
326                     });
327                 } catch (SWTError e) {
328                 }
329             }
330         }
331     }
332
333     /**
334      * The layout manager layouts the various
335      * windows associated with the content assistant based on the
336      * settings of the content assistant.
337      */

338     class LayoutManager implements Listener {
339
340         // Presentation types.
341
/** proposal selector */
342         public final static int LAYOUT_PROPOSAL_SELECTOR= 0;
343         /** context selector */
344         public final static int LAYOUT_CONTEXT_SELECTOR= 1;
345         /** context info */
346         public final static int LAYOUT_CONTEXT_INFO_POPUP= 2;
347
348         int fContextType= LAYOUT_CONTEXT_SELECTOR;
349         Shell[] fShells= new Shell[3];
350         Object JavaDoc[] fPopups= new Object JavaDoc[3];
351
352         protected void add(Object JavaDoc popup, Shell shell, int type, int offset) {
353             Assert.isNotNull(popup);
354             Assert.isTrue(shell != null && !shell.isDisposed());
355             checkType(type);
356
357             if (fShells[type] != shell) {
358                 if (fShells[type] != null)
359                     fShells[type].removeListener(SWT.Dispose, this);
360                 shell.addListener(SWT.Dispose, this);
361                 fShells[type]= shell;
362             }
363
364             fPopups[type]= popup;
365             if (type == LAYOUT_CONTEXT_SELECTOR || type == LAYOUT_CONTEXT_INFO_POPUP)
366                 fContextType= type;
367
368             layout(type, offset);
369             adjustListeners(type);
370         }
371
372         protected void checkType(int type) {
373             Assert.isTrue(type == LAYOUT_PROPOSAL_SELECTOR ||
374                 type == LAYOUT_CONTEXT_SELECTOR || type == LAYOUT_CONTEXT_INFO_POPUP);
375         }
376
377         public void handleEvent(Event event) {
378             Widget source= event.widget;
379             source.removeListener(SWT.Dispose, this);
380
381             int type= getShellType(source);
382             checkType(type);
383             fShells[type]= null;
384
385             switch (type) {
386                 case LAYOUT_PROPOSAL_SELECTOR:
387                     if (fContextType == LAYOUT_CONTEXT_SELECTOR &&
388                             Helper2.okToUse(fShells[LAYOUT_CONTEXT_SELECTOR])) {
389                         // Restore event notification to the tip popup.
390
addContentAssistListener((IContentAssistListener2) fPopups[LAYOUT_CONTEXT_SELECTOR], CONTEXT_SELECTOR);
391                     }
392                     break;
393
394                 case LAYOUT_CONTEXT_SELECTOR:
395                     if (Helper2.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR])) {
396                         if (fProposalPopupOrientation == PROPOSAL_STACKED)
397                             layout(LAYOUT_PROPOSAL_SELECTOR, getSelectionOffset());
398                         // Restore event notification to the proposal popup.
399
addContentAssistListener((IContentAssistListener2) fPopups[LAYOUT_PROPOSAL_SELECTOR], PROPOSAL_SELECTOR);
400                     }
401                     fContextType= LAYOUT_CONTEXT_INFO_POPUP;
402                     break;
403
404                 case LAYOUT_CONTEXT_INFO_POPUP:
405                     if (Helper2.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR])) {
406                         if (fContextInfoPopupOrientation == CONTEXT_INFO_BELOW)
407                             layout(LAYOUT_PROPOSAL_SELECTOR, getSelectionOffset());
408                     }
409                     fContextType= LAYOUT_CONTEXT_SELECTOR;
410                     break;
411             }
412         }
413
414         protected int getShellType(Widget shell) {
415             for (int i=0; i<fShells.length; i++) {
416                 if (fShells[i] == shell)
417                     return i;
418             }
419             return -1;
420         }
421
422         protected void layout(int type, int offset) {
423             switch (type) {
424                 case LAYOUT_PROPOSAL_SELECTOR:
425                     layoutProposalSelector(offset);
426                     break;
427                 case LAYOUT_CONTEXT_SELECTOR:
428                     layoutContextSelector(offset);
429                     break;
430                 case LAYOUT_CONTEXT_INFO_POPUP:
431                     layoutContextInfoPopup(offset);
432                     break;
433             }
434         }
435
436         protected void layoutProposalSelector(int offset) {
437             if (fContextType == LAYOUT_CONTEXT_INFO_POPUP &&
438                     fContextInfoPopupOrientation == CONTEXT_INFO_BELOW &&
439                     Helper2.okToUse(fShells[LAYOUT_CONTEXT_INFO_POPUP])) {
440                 // Stack proposal selector beneath the tip box.
441
Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
442                 Shell parent= fShells[LAYOUT_CONTEXT_INFO_POPUP];
443                 shell.setLocation(getStackedLocation(shell, parent));
444             } else if (fContextType != LAYOUT_CONTEXT_SELECTOR ||
445                         !Helper2.okToUse(fShells[LAYOUT_CONTEXT_SELECTOR])) {
446                 // There are no other presentations to be concerned with,
447
// so place the proposal selector beneath the cursor line.
448
Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
449                 shell.setLocation(getBelowLocation(shell, offset));
450             } else {
451                 switch (fProposalPopupOrientation) {
452                     case PROPOSAL_REMOVE: {
453                         // Remove the tip selector and place the
454
// proposal selector beneath the cursor line.
455
fShells[LAYOUT_CONTEXT_SELECTOR].dispose();
456                         Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
457                         shell.setLocation(getBelowLocation(shell, offset));
458                         break;
459                     }
460                     case PROPOSAL_OVERLAY: {
461                         // Overlay the tip selector with the proposal selector.
462
Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
463                         shell.setLocation(getBelowLocation(shell, offset));
464                         break;
465                     }
466                     case PROPOSAL_STACKED: {
467                         // Stack the proposal selector beneath the tip selector.
468
Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
469                         Shell parent= fShells[LAYOUT_CONTEXT_SELECTOR];
470                         shell.setLocation(getStackedLocation(shell, parent));
471                         break;
472                     }
473                 }
474             }
475         }
476
477         protected void layoutContextSelector(int offset) {
478             // Always place the context selector beneath the cursor line.
479
Shell shell= fShells[LAYOUT_CONTEXT_SELECTOR];
480             shell.setLocation(getBelowLocation(shell, offset));
481
482             if (Helper2.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR])) {
483                 switch (fProposalPopupOrientation) {
484                     case PROPOSAL_REMOVE:
485                         // Remove the proposal selector.
486
fShells[LAYOUT_PROPOSAL_SELECTOR].dispose();
487                         break;
488
489                     case PROPOSAL_OVERLAY:
490                         // The proposal selector has been overlaid by the tip selector.
491
break;
492
493                     case PROPOSAL_STACKED: {
494                         // Stack the proposal selector beneath the tip selector.
495
shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
496                         Shell parent= fShells[LAYOUT_CONTEXT_SELECTOR];
497                         shell.setLocation(getStackedLocation(shell, parent));
498                         break;
499                     }
500                 }
501             }
502         }
503
504         protected void layoutContextInfoPopup(int offset) {
505             switch (fContextInfoPopupOrientation) {
506                 case CONTEXT_INFO_ABOVE: {
507                     // Place the popup above the cursor line.
508
Shell shell= fShells[LAYOUT_CONTEXT_INFO_POPUP];
509                     shell.setLocation(getAboveLocation(shell, offset));
510                     break;
511                 }
512                 case CONTEXT_INFO_BELOW: {
513                     // Place the popup beneath the cursor line.
514
Shell parent= fShells[LAYOUT_CONTEXT_INFO_POPUP];
515                     parent.setLocation(getBelowLocation(parent, offset));
516                     if (Helper2.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR])) {
517                         // Stack the proposal selector beneath the context info popup.
518
Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR];
519                         shell.setLocation(getStackedLocation(shell, parent));
520                     }
521                     break;
522                 }
523             }
524         }
525
526         protected void shiftHorizontalLocation(Point location, Rectangle shellBounds, Rectangle displayBounds) {
527             if (location.x + shellBounds.width > displayBounds.width)
528                 location.x= displayBounds.width - shellBounds.width;
529
530             if (location.x < displayBounds.x)
531                 location.x= displayBounds.x;
532         }
533
534         protected void shiftVerticalLocation(Point location, Rectangle shellBounds, Rectangle displayBounds) {
535             if (location.y + shellBounds.height > displayBounds.height)
536                 location.y= displayBounds.height - shellBounds.height;
537
538             if (location.y < displayBounds.y)
539                 location.y= displayBounds.y;
540         }
541
542         protected Point getAboveLocation(Shell shell, int offset) {
543             StyledText text= fViewer.getTextWidget();
544             Point location= text.getLocationAtOffset(offset);
545             location= text.toDisplay(location);
546
547             Rectangle shellBounds= shell.getBounds();
548             Rectangle displayBounds= shell.getDisplay().getClientArea();
549
550             location.y=location.y - shellBounds.height;
551
552             shiftHorizontalLocation(location, shellBounds, displayBounds);
553             shiftVerticalLocation(location, shellBounds, displayBounds);
554
555             return location;
556         }
557
558         protected Point getBelowLocation(Shell shell, int offset) {
559             StyledText text= fViewer.getTextWidget();
560             Point location= text.getLocationAtOffset(offset);
561             if (location.x < 0) location.x= 0;
562             if (location.y < 0) location.y= 0;
563             location= text.toDisplay(location);
564
565             Rectangle shellBounds= shell.getBounds();
566             Rectangle displayBounds= shell.getDisplay().getClientArea();
567
568             location.y= location.y + text.getLineHeight(offset);
569             shiftHorizontalLocation(location, shellBounds, displayBounds);
570             shiftVerticalLocation(location, shellBounds, displayBounds);
571
572             return location;
573         }
574
575         protected Point getStackedLocation(Shell shell, Shell parent) {
576             Point p= parent.getLocation();
577             Point size= parent.getSize();
578             p.x += size.x / 4;
579             p.y += size.y;
580
581             p= parent.toDisplay(p);
582
583             Rectangle shellBounds= shell.getBounds();
584             Rectangle displayBounds= shell.getDisplay().getClientArea();
585             shiftHorizontalLocation(p, shellBounds, displayBounds);
586             shiftVerticalLocation(p, shellBounds, displayBounds);
587
588             return p;
589         }
590
591         protected void adjustListeners(int type) {
592             switch (type) {
593                 case LAYOUT_PROPOSAL_SELECTOR:
594                     if (fContextType == LAYOUT_CONTEXT_SELECTOR &&
595                             Helper2.okToUse(fShells[LAYOUT_CONTEXT_SELECTOR]))
596                         // Disable event notification to the tip selector.
597
removeContentAssistListener((IContentAssistListener2) fPopups[LAYOUT_CONTEXT_SELECTOR], CONTEXT_SELECTOR);
598                     break;
599                 case LAYOUT_CONTEXT_SELECTOR:
600                     if (Helper2.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR]))
601                         // Disable event notification to the proposal selector.
602
removeContentAssistListener((IContentAssistListener2) fPopups[LAYOUT_PROPOSAL_SELECTOR], PROPOSAL_SELECTOR);
603                     break;
604                 case LAYOUT_CONTEXT_INFO_POPUP:
605                     break;
606             }
607         }
608     }
609
610     /**
611      * Internal key listener and event consumer.
612      */

613     class InternalListener implements VerifyKeyListener, IEventConsumer {
614
615         /**
616          * Verifies key events by notifying the registered listeners.
617          * Each listener is allowed to indicate that the event has been
618          * handled and should not be further processed.
619          *
620          * @param e the verify event
621          * @see VerifyKeyListener#verifyKey(org.eclipse.swt.events.VerifyEvent)
622          */

623         public void verifyKey(VerifyEvent e) {
624             IContentAssistListener2[] listeners= (IContentAssistListener2[]) fListeners.clone();
625             for (int i= 0; i < listeners.length; i++) {
626                 if (listeners[i] != null) {
627                     if (!listeners[i].verifyKey(e) || !e.doit)
628                         return;
629                 }
630             }
631         }
632
633         /*
634          * @see IEventConsumer#processEvent
635          */

636         public void processEvent(VerifyEvent event) {
637
638             installKeyListener();
639
640             IContentAssistListener2[] listeners= (IContentAssistListener2[])fListeners.clone();
641             for (int i= 0; i < listeners.length; i++) {
642                 if (listeners[i] != null) {
643                     listeners[i].processEvent(event);
644                     if (!event.doit)
645                         return;
646                 }
647             }
648         }
649     }
650
651
652     // Content-Assist Listener types
653
final static int CONTEXT_SELECTOR= 0;
654     final static int PROPOSAL_SELECTOR= 1;
655     final static int CONTEXT_INFO_POPUP= 2;
656
657     /**
658      * The popup priority: &gt; info pop-ups, &lt; standard content assist.
659      * Default value: <code>10</code>.
660      *
661      * @since 3.0
662      */

663     public static final int WIDGET_PRIORITY= 10;
664
665
666     private static final int DEFAULT_AUTO_ACTIVATION_DELAY= 500;
667
668     private IInformationControlCreator fInformationControlCreator;
669     private int fAutoActivationDelay= DEFAULT_AUTO_ACTIVATION_DELAY;
670     private boolean fIsAutoActivated= false;
671     private boolean fIsAutoInserting= false;
672     private int fProposalPopupOrientation= PROPOSAL_OVERLAY;
673     private int fContextInfoPopupOrientation= CONTEXT_INFO_ABOVE;
674     private Map JavaDoc fProcessors;
675     private String JavaDoc fPartitioning;
676
677     private Color fContextInfoPopupBackground;
678     private Color fContextInfoPopupForeground;
679     private Color fContextSelectorBackground;
680     private Color fContextSelectorForeground;
681     private Color fProposalSelectorBackground;
682     private Color fProposalSelectorForeground;
683
684     private ITextViewer fViewer;
685     private String JavaDoc fLastErrorMessage;
686
687     private Closer fCloser;
688     private LayoutManager fLayoutManager;
689     private AutoAssistListener fAutoAssistListener;
690     private InternalListener fInternalListener;
691     private CompletionProposalPopup2 fProposalPopup;
692     private ContextInformationPopup2 fContextInfoPopup;
693
694     private boolean fKeyListenerHooked= false;
695     private IContentAssistListener2[] fListeners= new IContentAssistListener2[4];
696     private int fCompletionPosition;
697     private String JavaDoc[] fProposalStrings;
698     private ICompletionProposal[] fProposals;
699     private final List JavaDoc fProposalListeners= new ArrayList JavaDoc();
700
701     /**
702      * Creates a new content assistant. The content assistant is not automatically activated,
703      * overlays the completion proposals with context information list if necessary, and
704      * shows the context information above the location at which it was activated. If auto
705      * activation will be enabled, without further configuration steps, this content assistant
706      * is activated after a 500 ms delay. It uses the default partitioning.
707      */

708     public ContentAssistant2() {
709         setContextInformationPopupOrientation(CONTEXT_INFO_ABOVE);
710         setInformationControlCreator(getInformationControlCreator());
711
712 // JavaTextTools textTools= JavaPlugin.getDefault().getJavaTextTools();
713
// IColorManager manager= textTools.getColorManager();
714
//
715
// IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore();
716
//
717
// Color c= getColor(store, PreferenceConstants.CODEASSIST_PROPOSALS_FOREGROUND, manager);
718
// setProposalSelectorForeground(c);
719
//
720
// c= getColor(store, PreferenceConstants.CODEASSIST_PROPOSALS_BACKGROUND, manager);
721
// setProposalSelectorBackground(c);
722
}
723
724     /**
725      * Creates an <code>IInformationControlCreator</code> to be used to display context information.
726      *
727      * @return an <code>IInformationControlCreator</code> to be used to display context information
728      */

729     private IInformationControlCreator getInformationControlCreator() {
730         return new IInformationControlCreator() {
731             public IInformationControl createInformationControl(Shell parent) {
732                 return new DefaultInformationControl(parent, new HTMLTextPresenter());
733             }
734         };
735     }
736
737     /**
738      * Sets the document partitioning this content assistant is using.
739      *
740      * @param partitioning the document partitioning for this content assistant
741      */

742     public void setDocumentPartitioning(String JavaDoc partitioning) {
743         Assert.isNotNull(partitioning);
744         fPartitioning= partitioning;
745     }
746
747     /*
748      * @see org.eclipse.jface.text.contentassist.IContentAssistantExtension#getDocumentPartitioning()
749      * @since 3.0
750      */

751     public String JavaDoc getDocumentPartitioning() {
752         return fPartitioning;
753     }
754
755     /**
756      * Registers a given content assist processor for a particular content type.
757      * If there is already a processor registered for this type, the new processor
758      * is registered instead of the old one.
759      *
760      * @param processor the content assist processor to register, or <code>null</code> to remove an existing one
761      * @param contentType the content type under which to register
762      */

763      public void setContentAssistProcessor(IContentAssistProcessor processor, String JavaDoc contentType) {
764
765         Assert.isNotNull(contentType);
766
767         if (fProcessors == null)
768             fProcessors= new HashMap JavaDoc();
769
770         if (processor == null)
771             fProcessors.remove(contentType);
772         else
773             fProcessors.put(contentType, processor);
774     }
775
776     /*
777      * @see IContentAssistant#getContentAssistProcessor
778      */

779     public IContentAssistProcessor getContentAssistProcessor(String JavaDoc contentType) {
780         if (fProcessors == null)
781             return null;
782
783         return (IContentAssistProcessor) fProcessors.get(contentType);
784     }
785
786     /**
787      * Enables the content assistant's auto activation mode.
788      *
789      * @param enabled indicates whether auto activation is enabled or not
790      */

791     public void enableAutoActivation(boolean enabled) {
792         fIsAutoActivated= enabled;
793         manageAutoActivation(fIsAutoActivated);
794     }
795
796     /**
797      * Enables the content assistant's auto insertion mode. If enabled,
798      * the content assistant inserts a proposal automatically if it is
799      * the only proposal. In the case of ambiguities, the user must
800      * make the choice.
801      *
802      * @param enabled indicates whether auto insertion is enabled or not
803      * @since 2.0
804      */

805     public void enableAutoInsert(boolean enabled) {
806         fIsAutoInserting= enabled;
807     }
808
809     /**
810      * Returns whether this content assistant is in the auto insertion
811      * mode or not.
812      *
813      * @return <code>true</code> if in auto insertion mode
814      * @since 2.0
815      */

816     boolean isAutoInserting() {
817         return fIsAutoInserting;
818     }
819
820     /**
821      * Installs and uninstall the listeners needed for auto-activation.
822      * @param start <code>true</code> if listeners must be installed,
823      * <code>false</code> if they must be removed
824      * @since 2.0
825      */

826     private void manageAutoActivation(boolean start) {
827         if (start) {
828
829             if (fViewer != null && fAutoAssistListener == null) {
830                 fAutoAssistListener= new AutoAssistListener();
831                 if (fViewer instanceof ITextViewerExtension) {
832                     ITextViewerExtension extension= (ITextViewerExtension) fViewer;
833                     extension.appendVerifyKeyListener(fAutoAssistListener);
834                 } else {
835                     StyledText textWidget= fViewer.getTextWidget();
836                     if (Helper2.okToUse(textWidget))
837                         textWidget.addVerifyKeyListener(fAutoAssistListener);
838                 }
839             }
840
841         } else if (fAutoAssistListener != null) {
842
843             if (fViewer instanceof ITextViewerExtension) {
844                 ITextViewerExtension extension= (ITextViewerExtension) fViewer;
845                 extension.removeVerifyKeyListener(fAutoAssistListener);
846             } else {
847                 StyledText textWidget= fViewer.getTextWidget();
848                 if (Helper2.okToUse(textWidget))
849                     textWidget.removeVerifyKeyListener(fAutoAssistListener);
850             }
851
852             fAutoAssistListener= null;
853         }
854     }
855
856     /**
857      * Sets the delay after which the content assistant is automatically invoked
858      * if the cursor is behind an auto activation character.
859      *
860      * @param delay the auto activation delay
861      */

862     public void setAutoActivationDelay(int delay) {
863         fAutoActivationDelay= delay;
864     }
865
866     /**
867      * Sets the proposal pop-ups' orientation.
868      * The following values may be used:
869      * <ul>
870      * <li>PROPOSAL_OVERLAY<p>
871      * proposal popup windows should overlay each other
872      * </li>
873      * <li>PROPOSAL_REMOVE<p>
874      * any currently shown proposal popup should be closed
875      * </li>
876      * <li>PROPOSAL_STACKED<p>
877      * proposal popup windows should be vertical stacked, with no overlap,
878      * beneath the line containing the current cursor location
879      * </li>
880      * </ul>
881      *
882      * @param orientation the popup's orientation
883      */

884     public void setProposalPopupOrientation(int orientation) {
885         fProposalPopupOrientation= orientation;
886     }
887
888     /**
889      * Sets the context information popup's orientation.
890      * The following values may be used:
891      * <ul>
892      * <li>CONTEXT_ABOVE<p>
893      * context information popup should always appear above the line containing
894      * the current cursor location
895      * </li>
896      * <li>CONTEXT_BELOW<p>
897      * context information popup should always appear below the line containing
898      * the current cursor location
899      * </li>
900      * </ul>
901      *
902      * @param orientation the popup's orientation
903      */

904     public void setContextInformationPopupOrientation(int orientation) {
905         fContextInfoPopupOrientation= orientation;
906     }
907
908     /**
909      * Sets the context information popup's background color.
910      *
911      * @param background the background color
912      */

913     public void setContextInformationPopupBackground(Color background) {
914         fContextInfoPopupBackground= background;
915     }
916
917     /**
918      * Returns the background of the context information popup.
919      *
920      * @return the background of the context information popup
921      * @since 2.0
922      */

923     Color getContextInformationPopupBackground() {
924         return fContextInfoPopupBackground;
925     }
926
927     /**
928      * Sets the context information popup's foreground color.
929      *
930      * @param foreground the foreground color
931      * @since 2.0
932      */

933     public void setContextInformationPopupForeground(Color foreground) {
934         fContextInfoPopupForeground= foreground;
935     }
936
937     /**
938      * Returns the foreground of the context information popup.
939      *
940      * @return the foreground of the context information popup
941      * @since 2.0
942      */

943     Color getContextInformationPopupForeground() {
944         return fContextInfoPopupForeground;
945     }
946
947     /**
948      * Sets the proposal selector's background color.
949      *
950      * @param background the background color
951      * @since 2.0
952      */

953     public void setProposalSelectorBackground(Color background) {
954         fProposalSelectorBackground= background;
955     }
956
957     /**
958      * Returns the background of the proposal selector.
959      *
960      * @return the background of the proposal selector
961      * @since 2.0
962      */

963     Color getProposalSelectorBackground() {
964         return fProposalSelectorBackground;
965     }
966
967     /**
968      * Sets the proposal's foreground color.
969      *
970      * @param foreground the foreground color
971      * @since 2.0
972      */

973     public void setProposalSelectorForeground(Color foreground) {
974         fProposalSelectorForeground= foreground;
975     }
976
977     /**
978      * Returns the foreground of the proposal selector.
979      *
980      * @return the foreground of the proposal selector
981      * @since 2.0
982      */

983     Color getProposalSelectorForeground() {
984         return fProposalSelectorForeground;
985     }
986
987     /**
988      * Sets the context selector's background color.
989      *
990      * @param background the background color
991      * @since 2.0
992      */

993     public void setContextSelectorBackground(Color background) {
994         fContextSelectorBackground= background;
995     }
996
997     /**
998      * Returns the background of the context selector.
999      *
1000     * @return the background of the context selector
1001     * @since 2.0
1002     */

1003    Color getContextSelectorBackground() {
1004        return fContextSelectorBackground;
1005    }
1006
1007    /**
1008     * Sets the context selector's foreground color.
1009     *
1010     * @param foreground the foreground color
1011     * @since 2.0
1012     */

1013    public void setContextSelectorForeground(Color foreground) {
1014        fContextSelectorForeground= foreground;
1015    }
1016
1017    /**
1018     * Returns the foreground of the context selector.
1019     *
1020     * @return the foreground of the context selector
1021     * @since 2.0
1022     */

1023    Color getContextSelectorForeground() {
1024        return fContextSelectorForeground;
1025    }
1026
1027    /**
1028     * Sets the information control creator for the additional information control.
1029     *
1030     * @param creator the information control creator for the additional information control
1031     * @since 2.0
1032     */

1033    public void setInformationControlCreator(IInformationControlCreator creator) {
1034        fInformationControlCreator= creator;
1035    }
1036
1037    /*
1038     * @see IContentAssist#install
1039     */

1040    public void install(ITextViewer textViewer) {
1041        Assert.isNotNull(textViewer);
1042
1043        fViewer= textViewer;
1044
1045        fLayoutManager= new LayoutManager();
1046        fInternalListener= new InternalListener();
1047
1048        AdditionalInfoController2 controller= null;
1049        if (fInformationControlCreator != null) {
1050            int delay= fAutoActivationDelay;
1051            if (delay == 0)
1052                delay= DEFAULT_AUTO_ACTIVATION_DELAY;
1053            delay= Math.round(delay * 1.5f);
1054            controller= new AdditionalInfoController2(fInformationControlCreator, delay);
1055        }
1056        fContextInfoPopup= new ContextInformationPopup2(this, fViewer);
1057        fProposalPopup= new CompletionProposalPopup2(this, fViewer, controller);
1058
1059        manageAutoActivation(fIsAutoActivated);
1060    }
1061
1062    /*
1063     * @see IContentAssist#uninstall
1064     */

1065    public void uninstall() {
1066
1067        if (fProposalPopup != null)
1068            fProposalPopup.hide();
1069
1070        if (fContextInfoPopup != null)
1071            fContextInfoPopup.hide();
1072
1073        manageAutoActivation(false);
1074
1075        if (fCloser != null) {
1076            fCloser.uninstall();
1077            fCloser= null;
1078        }
1079
1080        fViewer= null;
1081    }
1082
1083    /**
1084     * Adds the given shell of the specified type to the layout.
1085     * Valid types are defined by <code>LayoutManager</code>.
1086     *
1087     * @param popup a content assist popup
1088     * @param shell the shell of the content-assist popup
1089     * @param type the type of popup
1090     * @param visibleOffset the offset at which to layout the popup relative to the offset of the viewer's visible region
1091     * @since 2.0
1092     */

1093    void addToLayout(Object JavaDoc popup, Shell shell, int type, int visibleOffset) {
1094        fLayoutManager.add(popup, shell, type, visibleOffset);
1095    }
1096
1097    /**
1098     * Layouts the registered popup of the given type relative to the
1099     * given offset. The offset is relative to the offset of the viewer's visible region.
1100     * Valid types are defined by <code>LayoutManager</code>.
1101     *
1102     * @param type the type of popup to layout
1103     * @param visibleOffset the offset at which to layout relative to the offset of the viewer's visible region
1104     * @since 2.0
1105     */

1106    void layout(int type, int visibleOffset) {
1107        fLayoutManager.layout(type, visibleOffset);
1108    }
1109
1110    /**
1111     * Notifies the controller that a popup has lost focus.
1112     *
1113     * @param e the focus event
1114     */

1115    void popupFocusLost(FocusEvent e) {
1116        fCloser.focusLost(e);
1117    }
1118
1119    /**
1120     * Returns the offset of the selection relative to the offset of the visible region.
1121     *
1122     * @return the offset of the selection relative to the offset of the visible region
1123     * @since 2.0
1124     */

1125    int getSelectionOffset() {
1126        StyledText text= fViewer.getTextWidget();
1127        return text.getSelectionRange().x;
1128    }
1129
1130    /**
1131     * Returns whether the widget token could be acquired.
1132     * The following are valid listener types:
1133     * <ul>
1134     * <li>AUTO_ASSIST
1135     * <li>CONTEXT_SELECTOR
1136     * <li>PROPOSAL_SELECTOR
1137     * <li>CONTEXT_INFO_POPUP
1138     * <ul>
1139     * @param type the listener type for which to acquire
1140     * @return <code>true</code> if the widget token could be acquired
1141     * @since 2.0
1142     */

1143    private boolean acquireWidgetToken(int type) {
1144        switch (type) {
1145            case CONTEXT_SELECTOR:
1146            case PROPOSAL_SELECTOR:
1147                if (fViewer instanceof IWidgetTokenOwner) {
1148                    IWidgetTokenOwner owner= (IWidgetTokenOwner) fViewer;
1149                    return owner.requestWidgetToken(this);
1150                } else if (fViewer instanceof IWidgetTokenOwnerExtension) {
1151                    IWidgetTokenOwnerExtension extension= (IWidgetTokenOwnerExtension) fViewer;
1152                    return extension.requestWidgetToken(this, WIDGET_PRIORITY);
1153                }
1154        }
1155        return true;
1156    }
1157
1158    /**
1159     * Registers a content assist listener.
1160     * The following are valid listener types:
1161     * <ul>
1162     * <li>AUTO_ASSIST
1163     * <li>CONTEXT_SELECTOR
1164     * <li>PROPOSAL_SELECTOR
1165     * <li>CONTEXT_INFO_POPUP
1166     * <ul>
1167     * Returns whether the listener could be added successfully. A listener
1168     * can not be added if the widget token could not be acquired.
1169     *
1170     * @param listener the listener to register
1171     * @param type the type of listener
1172     * @return <code>true</code> if the listener could be added
1173     */

1174    boolean addContentAssistListener(IContentAssistListener2 listener, int type) {
1175
1176        if (acquireWidgetToken(type)) {
1177
1178            fListeners[type]= listener;
1179
1180            if (getNumberOfListeners() == 1) {
1181                fCloser= new Closer();
1182                fCloser.install();
1183                fViewer.setEventConsumer(fInternalListener);
1184                installKeyListener();
1185            }
1186            return true;
1187        }
1188
1189        return false;
1190    }
1191
1192    /**
1193     * Installs a key listener on the text viewer's widget.
1194     */

1195    private void installKeyListener() {
1196        if (!fKeyListenerHooked) {
1197            StyledText text= fViewer.getTextWidget();
1198            if (Helper2.okToUse(text)) {
1199
1200                if (fViewer instanceof ITextViewerExtension) {
1201                    ITextViewerExtension e= (ITextViewerExtension) fViewer;
1202                    e.prependVerifyKeyListener(fInternalListener);
1203                } else {
1204                    text.addVerifyKeyListener(fInternalListener);
1205                }
1206
1207                fKeyListenerHooked= true;
1208            }
1209        }
1210    }
1211
1212    /**
1213     * Releases the previously acquired widget token if the token
1214     * is no longer necessary.
1215     * The following are valid listener types:
1216     * <ul>
1217     * <li>AUTO_ASSIST
1218     * <li>CONTEXT_SELECTOR
1219     * <li>PROPOSAL_SELECTOR
1220     * <li>CONTEXT_INFO_POPUP
1221     * <ul>
1222     *
1223     * @param type the listener type
1224     * @since 2.0
1225     */

1226    private void releaseWidgetToken(int type) {
1227        if (fListeners[CONTEXT_SELECTOR] == null && fListeners[PROPOSAL_SELECTOR] == null) {
1228            if (fViewer instanceof IWidgetTokenOwner) {
1229                IWidgetTokenOwner owner= (IWidgetTokenOwner) fViewer;
1230                owner.releaseWidgetToken(this);
1231            }
1232        }
1233    }
1234
1235    /**
1236     * Unregisters a content assist listener.
1237     *
1238     * @param listener the listener to unregister
1239     * @param type the type of listener
1240     *
1241     * @see #addContentAssistListener
1242     */

1243    void removeContentAssistListener(IContentAssistListener2 listener, int type) {
1244        fListeners[type]= null;
1245
1246        if (getNumberOfListeners() == 0) {
1247
1248            if (fCloser != null) {
1249                fCloser.uninstall();
1250                fCloser= null;
1251            }
1252
1253            uninstallKeyListener();
1254            fViewer.setEventConsumer(null);
1255        }
1256
1257        releaseWidgetToken(type);
1258    }
1259
1260    /**
1261     * Uninstall the key listener from the text viewer's widget.
1262     */

1263    private void uninstallKeyListener() {
1264        if (fKeyListenerHooked) {
1265            StyledText text= fViewer.getTextWidget();
1266            if (Helper2.okToUse(text)) {
1267
1268                if (fViewer instanceof ITextViewerExtension) {
1269                    ITextViewerExtension e= (ITextViewerExtension) fViewer;
1270                    e.removeVerifyKeyListener(fInternalListener);
1271                } else {
1272                    text.removeVerifyKeyListener(fInternalListener);
1273                }
1274
1275                fKeyListenerHooked= false;
1276            }
1277        }
1278    }
1279
1280    /**
1281     * Returns the number of listeners.
1282     *
1283     * @return the number of listeners
1284     * @since 2.0
1285     */

1286    private int getNumberOfListeners() {
1287        int count= 0;
1288        for (int i= 0; i <= CONTEXT_INFO_POPUP; i++) {
1289            if (fListeners[i] != null)
1290                ++ count;
1291        }
1292        return count;
1293    }
1294
1295    /*
1296     * @see IContentAssist#showPossibleCompletions
1297     */

1298    public String JavaDoc showPossibleCompletions() {
1299        return fProposalPopup.showProposals(false);
1300    }
1301
1302    /**
1303     * Hides the proposal popup.
1304     */

1305    public void hidePossibleCompletions() {
1306        if (fProposalPopup != null)
1307            fProposalPopup.hide();
1308    }
1309
1310    /**
1311     * Hides any open pop-ups.
1312     */

1313    protected void hide() {
1314        if (fProposalPopup != null)
1315            fProposalPopup.hide();
1316        if (fContextInfoPopup != null)
1317            fContextInfoPopup.hide();
1318    }
1319
1320    /**
1321     * Callback to signal this content assistant that the presentation of the possible completions has been stopped.
1322     * @since 2.1
1323     */

1324    protected void possibleCompletionsClosed() {
1325    }
1326
1327    /*
1328     * @see IContentAssist#showContextInformation
1329     */

1330    public String JavaDoc showContextInformation() {
1331        return fContextInfoPopup.showContextProposals(false);
1332    }
1333
1334
1335    /**
1336     * Callback to signal this content assistant that the presentation of the context information has been stopped.
1337     * @since 2.1
1338     */

1339    protected void contextInformationClosed() {
1340    }
1341
1342    /**
1343     * Requests that the specified context information to be shown.
1344     *
1345     * @param contextInformation the context information to be shown
1346     * @param position the position to which the context information refers to
1347     * @since 2.0
1348     */

1349    void showContextInformation(IContextInformation contextInformation, int position) {
1350        fContextInfoPopup.showContextInformation(contextInformation, position);
1351    }
1352
1353    /**
1354     * Returns the current content assist error message.
1355     *
1356     * @return an error message or <code>null</code> if no error has occurred
1357     */

1358    String JavaDoc getErrorMessage() {
1359        return fLastErrorMessage;
1360    }
1361
1362    /**
1363     * Returns the content assist processor for the content
1364     * type of the specified document position.
1365     *
1366     * @param viewer the text viewer
1367     * @param offset a offset within the document
1368     * @return a content-assist processor or <code>null</code> if none exists
1369     */

1370    private IContentAssistProcessor getProcessor(ITextViewer viewer, int offset) {
1371        try {
1372            String JavaDoc type= TextUtilities.getContentType(viewer.getDocument(), getDocumentPartitioning(), offset, true);
1373            return getContentAssistProcessor(type);
1374        } catch (BadLocationException x) {
1375        }
1376        return null;
1377    }
1378
1379    /**
1380     * Returns an array of completion proposals computed based on
1381     * the specified document position. The position is used to
1382     * determine the appropriate content assist processor to invoke.
1383     *
1384     * @param viewer the viewer for which to compute the proposals
1385     * @param position a document position
1386     * @return an array of completion proposals
1387     *
1388     * @see IContentAssistProcessor#computeCompletionProposals
1389     */

1390    ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int position) {
1391        if (fProposals != null) {
1392            return fProposals;
1393        } else if (fProposalStrings != null) {
1394            ICompletionProposal[] result= new ICompletionProposal[fProposalStrings.length];
1395            for (int i= 0; i < fProposalStrings.length; i++) {
1396                result[i]= new CompletionProposal(fProposalStrings[i], position, fProposalStrings[i].length(), fProposalStrings[i].length());
1397            }
1398            return result;
1399        } else return null;
1400    }
1401
1402    /**
1403     * Returns an array of context information objects computed based
1404     * on the specified document position. The position is used to determine
1405     * the appropriate content assist processor to invoke.
1406     *
1407     * @param viewer the viewer for which to compute the context information
1408     * @param position a document position
1409     * @return an array of context information objects
1410     *
1411     * @see IContentAssistProcessor#computeContextInformation
1412     */

1413    IContextInformation[] computeContextInformation(ITextViewer viewer, int position) {
1414        fLastErrorMessage= null;
1415
1416        IContextInformation[] result= null;
1417
1418        IContentAssistProcessor p= getProcessor(viewer, position);
1419        if (p != null) {
1420            result= p.computeContextInformation(viewer, position);
1421            fLastErrorMessage= p.getErrorMessage();
1422        }
1423
1424        return result;
1425    }
1426
1427    /**
1428     * Returns the context information validator that should be used to
1429     * determine when the currently displayed context information should
1430     * be dismissed. The position is used to determine the appropriate
1431     * content assist processor to invoke.
1432     *
1433     * @param textViewer the text viewer
1434     * @param offset a document offset
1435     * @return an validator
1436     *
1437     * @see IContentAssistProcessor#getContextInformationValidator
1438     */

1439    IContextInformationValidator getContextInformationValidator(ITextViewer textViewer, int offset) {
1440        IContentAssistProcessor p= getProcessor(textViewer, offset);
1441        return p != null ? p.getContextInformationValidator() : null;
1442    }
1443
1444    /**
1445     * Returns the context information presenter that should be used to
1446     * display context information. The position is used to determine the appropriate
1447     * content assist processor to invoke.
1448     *
1449     * @param textViewer the text viewer
1450     * @param offset a document offset
1451     * @return a presenter
1452     * @since 2.0
1453     */

1454    IContextInformationPresenter getContextInformationPresenter(ITextViewer textViewer, int offset) {
1455        IContextInformationValidator validator= getContextInformationValidator(textViewer, offset);
1456        if (validator instanceof IContextInformationPresenter)
1457            return (IContextInformationPresenter) validator;
1458        return null;
1459    }
1460
1461    /**
1462     * Returns the characters which when typed by the user should automatically
1463     * initiate proposing completions. The position is used to determine the
1464     * appropriate content assist processor to invoke.
1465     *
1466     * @param textViewer the text viewer
1467     * @param offset a document offset
1468     * @return the auto activation characters
1469     *
1470     * @see IContentAssistProcessor#getCompletionProposalAutoActivationCharacters
1471     */

1472    private char[] getCompletionProposalAutoActivationCharacters(ITextViewer textViewer, int offset) {
1473        IContentAssistProcessor p= getProcessor(textViewer, offset);
1474        return p != null ? p.getCompletionProposalAutoActivationCharacters() : null;
1475    }
1476
1477    /**
1478     * Returns the characters which when typed by the user should automatically
1479     * initiate the presentation of context information. The position is used
1480     * to determine the appropriate content assist processor to invoke.
1481     *
1482     * @param textViewer the text viewer
1483     * @param offset a document offset
1484     * @return the auto activation characters
1485     *
1486     * @see IContentAssistProcessor#getContextInformationAutoActivationCharacters
1487     */

1488    private char[] getContextInformationAutoActivationCharacters(ITextViewer textViewer, int offset) {
1489        IContentAssistProcessor p= getProcessor(textViewer, offset);
1490        return p != null ? p.getContextInformationAutoActivationCharacters() : null;
1491    }
1492
1493    /*
1494     * @see org.eclipse.jface.text.IWidgetTokenKeeper#requestWidgetToken(IWidgetTokenOwner)
1495     * @since 2.0
1496     */

1497    public boolean requestWidgetToken(IWidgetTokenOwner owner) {
1498        hidePossibleCompletions();
1499        return true;
1500    }
1501
1502    /**
1503     * @param completionPosition
1504     */

1505    public void setCompletionPosition(int completionPosition) {
1506        fCompletionPosition= completionPosition;
1507    }
1508
1509    /**
1510     * @return the completion position
1511     */

1512    public int getCompletionPosition() {
1513        return fCompletionPosition;
1514    }
1515
1516    /**
1517     * @param proposals
1518     */

1519    public void setCompletions(String JavaDoc[] proposals) {
1520        fProposalStrings= proposals;
1521    }
1522
1523    /**
1524     * @param proposals
1525     */

1526    public void setCompletions(ICompletionProposal[] proposals) {
1527        fProposals= proposals;
1528    }
1529
1530    /*
1531     * @see org.eclipse.jface.text.IWidgetTokenKeeperExtension#requestWidgetToken(org.eclipse.jface.text.IWidgetTokenOwner, int)
1532     * @since 3.0
1533     */

1534    public boolean requestWidgetToken(IWidgetTokenOwner owner, int priority) {
1535        if (priority > WIDGET_PRIORITY) {
1536            hidePossibleCompletions();
1537            return true;
1538        }
1539        return false;
1540    }
1541
1542    /*
1543     * @see org.eclipse.jface.text.IWidgetTokenKeeperExtension#setFocus(org.eclipse.jface.text.IWidgetTokenOwner)
1544     * @since 3.0
1545     */

1546    public boolean setFocus(IWidgetTokenOwner owner) {
1547        if (fProposalPopup != null) {
1548            fProposalPopup.setFocus();
1549            return fProposalPopup.hasFocus();
1550        }
1551        return false;
1552    }
1553
1554    /**
1555     * Returns whether any popups controlled by the receiver have the input focus.
1556     *
1557     * @return <code>true</code> if any of the managed popups have the focus, <code>false</code> otherwise
1558     */

1559    public boolean hasFocus() {
1560        return (fProposalPopup != null && fProposalPopup.hasFocus())
1561                || (fContextInfoPopup != null && fContextInfoPopup.hasFocus());
1562    }
1563
1564    /*
1565     * @see org.eclipse.jface.text.contentassist.IContentAssistantExtension#completePrefix()
1566     */

1567    public String JavaDoc completePrefix() {
1568        return null;
1569    }
1570
1571    /**
1572     * @param proposal
1573     */

1574    public void fireProposalChosen(ICompletionProposal proposal) {
1575        List JavaDoc list= new ArrayList JavaDoc(fProposalListeners);
1576        for (Iterator JavaDoc it= list.iterator(); it.hasNext();) {
1577            IProposalListener listener= (IProposalListener) it.next();
1578            listener.proposalChosen(proposal);
1579        }
1580
1581    }
1582
1583    /**
1584     * @param listener
1585     */

1586    public void removeProposalListener(IProposalListener listener) {
1587        fProposalListeners.remove(listener);
1588    }
1589
1590    /**
1591     * @param listener
1592     */

1593    public void addProposalListener(IProposalListener listener) {
1594        fProposalListeners.add(listener);
1595    }
1596}
1597
1598
Popular Tags