KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > text > contentassist > ContextInformationPopup


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.contentassist;
12
13 import java.util.Iterator JavaDoc;
14 import java.util.Stack JavaDoc;
15
16 import org.eclipse.swt.SWT;
17 import org.eclipse.swt.custom.BusyIndicator;
18 import org.eclipse.swt.custom.StyledText;
19 import org.eclipse.swt.events.KeyEvent;
20 import org.eclipse.swt.events.SelectionAdapter;
21 import org.eclipse.swt.events.SelectionEvent;
22 import org.eclipse.swt.events.SelectionListener;
23 import org.eclipse.swt.events.VerifyEvent;
24 import org.eclipse.swt.graphics.Color;
25 import org.eclipse.swt.graphics.Point;
26 import org.eclipse.swt.graphics.Rectangle;
27 import org.eclipse.swt.layout.GridData;
28 import org.eclipse.swt.layout.GridLayout;
29 import org.eclipse.swt.widgets.Control;
30 import org.eclipse.swt.widgets.Display;
31 import org.eclipse.swt.widgets.Shell;
32 import org.eclipse.swt.widgets.Table;
33 import org.eclipse.swt.widgets.TableItem;
34
35 import org.eclipse.jface.contentassist.IContentAssistSubjectControl;
36
37 import org.eclipse.jface.text.ITextViewer;
38 import org.eclipse.jface.text.TextPresentation;
39
40
41 /**
42  * This class is used to present context information to the user.
43  * If multiple contexts are valid at the current cursor location,
44  * a list is presented from which the user may choose one context.
45  * Once the user makes their choice, or if there was only a single
46  * possible context, the context information is shown in a tool tip like popup. <p>
47  * If the tool tip is visible and the user wants to see context information of
48  * a context embedded into the one for which context information is displayed,
49  * context information for the embedded context is shown. As soon as the
50  * cursor leaves the embedded context area, the context information for
51  * the embedding context is shown again.
52  *
53  * @see IContextInformation
54  * @see IContextInformationValidator
55  */

56 class ContextInformationPopup implements IContentAssistListener {
57
58
59     /**
60      * Represents the state necessary for embedding contexts.
61      *
62      * @since 2.0
63      */

64     static class ContextFrame {
65
66         final int fBeginOffset;
67         final int fOffset;
68         final int fVisibleOffset;
69         final IContextInformation fInformation;
70         final IContextInformationValidator fValidator;
71         final IContextInformationPresenter fPresenter;
72
73         /*
74          * @since 3.1
75          */

76         public ContextFrame(IContextInformation information, int beginOffset, int offset, int visibleOffset, IContextInformationValidator validator, IContextInformationPresenter presenter) {
77             fInformation = information;
78             fBeginOffset = beginOffset;
79             fOffset = offset;
80             fVisibleOffset = visibleOffset;
81             fValidator = validator;
82             fPresenter = presenter;
83         }
84
85         /*
86          * @see java.lang.Object#equals(java.lang.Object)
87          * @since 3.0
88          */

89         public boolean equals(Object JavaDoc obj) {
90             if (obj instanceof ContextFrame) {
91                 ContextFrame frame= (ContextFrame) obj;
92                 return fInformation.equals(frame.fInformation) && fBeginOffset == frame.fBeginOffset;
93             }
94             return super.equals(obj);
95         }
96
97         /*
98          * @see java.lang.Object#hashCode()
99          * @since 3.1
100          */

101         public int hashCode() {
102             return (fInformation.hashCode() << 16) | fBeginOffset;
103         }
104     }
105
106     private ITextViewer fViewer;
107     private ContentAssistant fContentAssistant;
108
109     private PopupCloser fPopupCloser= new PopupCloser();
110     private Shell fContextSelectorShell;
111     private Table fContextSelectorTable;
112     private IContextInformation[] fContextSelectorInput;
113     private String JavaDoc fLineDelimiter= null;
114
115     private Shell fContextInfoPopup;
116     private StyledText fContextInfoText;
117     private TextPresentation fTextPresentation;
118
119     private Stack JavaDoc fContextFrameStack= new Stack JavaDoc();
120     /**
121      * The content assist subject control.
122      *
123      * @since 3.0
124      */

125     private IContentAssistSubjectControl fContentAssistSubjectControl;
126     /**
127      * The content assist subject control adapter.
128      *
129      * @since 3.0
130      */

131     private ContentAssistSubjectControlAdapter fContentAssistSubjectControlAdapter;
132
133     /**
134      * Selection listener on the text widget which is active
135      * while a context information pop up is shown.
136      *
137      * @since 3.0
138      */

139     private SelectionListener fTextWidgetSelectionListener;
140
141     /**
142      * The last removed context frame is remembered in order to not re-query the
143      * user about which context should be used.
144      *
145      * @since 3.0
146      */

147     private ContextFrame fLastContext= null;
148
149     /**
150      * Creates a new context information popup.
151      *
152      * @param contentAssistant the content assist for computing the context information
153      * @param viewer the viewer on top of which the context information is shown
154      */

155     public ContextInformationPopup(ContentAssistant contentAssistant, ITextViewer viewer) {
156         fContentAssistant= contentAssistant;
157         fViewer= viewer;
158         fContentAssistSubjectControlAdapter= new ContentAssistSubjectControlAdapter(fViewer);
159     }
160
161     /**
162      * Creates a new context information popup.
163      *
164      * @param contentAssistant the content assist for computing the context information
165      * @param contentAssistSubjectControl the content assist subject control on top of which the context information is shown
166      * @since 3.0
167      */

168     public ContextInformationPopup(ContentAssistant contentAssistant, IContentAssistSubjectControl contentAssistSubjectControl) {
169         fContentAssistant= contentAssistant;
170         fContentAssistSubjectControl= contentAssistSubjectControl;
171         fContentAssistSubjectControlAdapter= new ContentAssistSubjectControlAdapter(fContentAssistSubjectControl);
172     }
173
174     /**
175      * Shows all possible contexts for the given cursor position of the viewer.
176      *
177      * @param autoActivated <code>true</code> if auto activated
178      * @return a potential error message or <code>null</code> in case of no error
179      */

180     public String JavaDoc showContextProposals(final boolean autoActivated) {
181         final Control control= fContentAssistSubjectControlAdapter.getControl();
182         BusyIndicator.showWhile(control.getDisplay(), new Runnable JavaDoc() {
183             public void run() {
184
185                 int offset= fContentAssistSubjectControlAdapter.getSelectedRange().x;
186
187                 IContextInformation[] contexts= computeContextInformation(offset);
188                 int count = (contexts == null ? 0 : contexts.length);
189                 if (count == 1) {
190
191                     ContextFrame frame= createContextFrame(contexts[0], offset);
192                     if (isDuplicate(frame))
193                         validateContextInformation();
194                     else
195                         // Show context information directly
196
internalShowContextInfo(frame);
197
198                 } else if (count > 0) {
199
200                     // if any of the proposed context matches any of the contexts on the stack,
201
// assume that one (so, if context info is invoked repeatedly, the current
202
// info is kept)
203
for (int i= 0; i < contexts.length; i++) {
204                         IContextInformation info= contexts[i];
205                         ContextFrame frame= createContextFrame(info, offset);
206
207                         // check top of stack and stored context
208
if (isDuplicate(frame)) {
209                             validateContextInformation();
210                             return;
211                         }
212
213                         if (isLastFrame(frame)) {
214                             internalShowContextInfo(frame);
215                             return;
216                         }
217
218                         // also check all other contexts
219
for (Iterator JavaDoc it= fContextFrameStack.iterator(); it.hasNext(); ) {
220                             ContextFrame stackFrame= (ContextFrame) it.next();
221                             if (stackFrame.equals(frame)) {
222                                 validateContextInformation();
223                                 return;
224                             }
225                         }
226                     }
227
228                     // otherwise:
229
// Precise context must be selected
230

231                     if (fLineDelimiter == null)
232                         fLineDelimiter= fContentAssistSubjectControlAdapter.getLineDelimiter();
233
234                     createContextSelector();
235                     setContexts(contexts);
236                     displayContextSelector();
237                 }
238             }
239         });
240
241         return getErrorMessage();
242     }
243
244     /**
245      * Displays the given context information for the given offset.
246      *
247      * @param info the context information
248      * @param offset the offset
249      * @since 2.0
250      */

251     public void showContextInformation(final IContextInformation info, final int offset) {
252         Control control= fContentAssistSubjectControlAdapter.getControl();
253         BusyIndicator.showWhile(control.getDisplay(), new Runnable JavaDoc() {
254             public void run() {
255                 if (info == null)
256                     validateContextInformation();
257                 else {
258                     ContextFrame frame= createContextFrame(info, offset);
259                     if (isDuplicate(frame))
260                         validateContextInformation();
261                     else
262                         internalShowContextInfo(frame);
263                     hideContextSelector();
264                 }
265             }
266         });
267     }
268
269     /**
270      * Displays the given context information for the given offset.
271      *
272      * @param frame the context frame to display, or <code>null</code>
273      * @since 3.0
274      */

275     private void internalShowContextInfo(ContextFrame frame) {
276         if (frame != null) {
277             fContextFrameStack.push(frame);
278             if (fContextFrameStack.size() == 1)
279                 fLastContext= null;
280             internalShowContextFrame(frame, fContextFrameStack.size() == 1);
281             validateContextInformation();
282         }
283     }
284
285     /**
286      * Creates a context frame for the given offset.
287      *
288      * @param information the context information
289      * @param offset the offset
290      * @return the created context frame
291      * @since 3.0
292      */

293     private ContextFrame createContextFrame(IContextInformation information, int offset) {
294         IContextInformationValidator validator= fContentAssistSubjectControlAdapter.getContextInformationValidator(fContentAssistant, offset);
295
296         if (validator != null) {
297             int beginOffset= (information instanceof IContextInformationExtension) ? ((IContextInformationExtension) information).getContextInformationPosition() : offset;
298             if (beginOffset == -1) beginOffset= offset;
299             int visibleOffset= fContentAssistSubjectControlAdapter.getWidgetSelectionRange().x - (offset - beginOffset);
300             IContextInformationPresenter presenter = fContentAssistSubjectControlAdapter.getContextInformationPresenter(fContentAssistant, offset);
301             return new ContextFrame(information, beginOffset, offset, visibleOffset, validator, presenter);
302         }
303
304         return null;
305     }
306
307     /**
308      * Compares <code>frame</code> with the top of the stack, returns <code>true</code>
309      * if the frames are the same.
310      *
311      * @param frame the frame to check
312      * @return <code>true</code> if <code>frame</code> matches the top of the stack
313      * @since 3.0
314      */

315     private boolean isDuplicate(ContextFrame frame) {
316         if (frame == null)
317             return false;
318         if (fContextFrameStack.isEmpty())
319             return false;
320         // stack not empty
321
ContextFrame top= (ContextFrame) fContextFrameStack.peek();
322         return frame.equals(top);
323     }
324
325     /**
326      * Compares <code>frame</code> with most recently removed context frame, returns <code>true</code>
327      * if the frames are the same.
328      *
329      * @param frame the frame to check
330      * @return <code>true</code> if <code>frame</code> matches the most recently removed
331      * @since 3.0
332      */

333     private boolean isLastFrame(ContextFrame frame) {
334         return frame != null && frame.equals(fLastContext);
335     }
336
337     /**
338      * Shows the given context frame.
339      *
340      * @param frame the frame to display
341      * @param initial <code>true</code> if this is the first frame to be displayed
342      * @since 2.0
343      */

344     private void internalShowContextFrame(ContextFrame frame, boolean initial) {
345
346         fContentAssistSubjectControlAdapter.installValidator(frame);
347
348         if (frame.fPresenter != null) {
349             if (fTextPresentation == null)
350                 fTextPresentation= new TextPresentation();
351             fContentAssistSubjectControlAdapter.installContextInformationPresenter(frame);
352             frame.fPresenter.updatePresentation(frame.fOffset, fTextPresentation);
353         }
354
355         createContextInfoPopup();
356
357         fContextInfoText.setText(frame.fInformation.getInformationDisplayString());
358         if (fTextPresentation != null)
359             TextPresentation.applyTextPresentation(fTextPresentation, fContextInfoText);
360         resize(frame.fVisibleOffset);
361
362         if (initial) {
363             if (fContentAssistant.addContentAssistListener(this, ContentAssistant.CONTEXT_INFO_POPUP)) {
364                 if (fContentAssistSubjectControlAdapter.getControl() != null) {
365                     fTextWidgetSelectionListener= new SelectionAdapter() {
366                         /*
367                          * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
368                          */

369                         public void widgetSelected(SelectionEvent e) {
370                             validateContextInformation();
371                         }};
372                     fContentAssistSubjectControlAdapter.addSelectionListener(fTextWidgetSelectionListener);
373                 }
374                 fContentAssistant.addToLayout(this, fContextInfoPopup, ContentAssistant.LayoutManager.LAYOUT_CONTEXT_INFO_POPUP, frame.fVisibleOffset);
375                 fContextInfoPopup.setVisible(true);
376             }
377         } else {
378             fContentAssistant.layout(ContentAssistant.LayoutManager.LAYOUT_CONTEXT_INFO_POPUP, frame.fVisibleOffset);
379         }
380     }
381
382     /**
383      * Computes all possible context information for the given offset.
384      *
385      * @param offset the offset
386      * @return all possible context information for the given offset
387      * @since 2.0
388      */

389     private IContextInformation[] computeContextInformation(int offset) {
390         return fContentAssistSubjectControlAdapter.computeContextInformation(fContentAssistant, offset);
391     }
392
393     /**
394      *Returns the error message generated while computing context information.
395      *
396      * @return the error message
397      */

398     private String JavaDoc getErrorMessage() {
399         return fContentAssistant.getErrorMessage();
400     }
401
402     /**
403      * Creates the context information popup. This is the tool tip like overlay window.
404      */

405     private void createContextInfoPopup() {
406         if (Helper.okToUse(fContextInfoPopup))
407             return;
408
409         Control control= fContentAssistSubjectControlAdapter.getControl();
410         Display display= control.getDisplay();
411
412         fContextInfoPopup= new Shell(control.getShell(), SWT.NO_TRIM | SWT.ON_TOP);
413         fContextInfoPopup.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
414
415         fContextInfoText= new StyledText(fContextInfoPopup, SWT.MULTI | SWT.READ_ONLY | SWT.WRAP);
416
417         Color c= fContentAssistant.getContextInformationPopupBackground();
418         if (c == null)
419             c= display.getSystemColor(SWT.COLOR_INFO_BACKGROUND);
420         fContextInfoText.setBackground(c);
421
422         c= fContentAssistant.getContextInformationPopupForeground();
423         if (c == null)
424             c= display.getSystemColor(SWT.COLOR_INFO_FOREGROUND);
425         fContextInfoText.setForeground(c);
426     }
427
428     /**
429      * Resizes the context information popup.
430      *
431      * @param offset the caret offset in widget coordinates
432      * @since 2.0
433      */

434     private void resize(int offset) {
435         Point size= fContextInfoText.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
436         final int TEXT_PAD= 0;
437         final int BORDER_PAD= 2;
438         final int PAD= TEXT_PAD + BORDER_PAD;
439         size.x += PAD;
440         Rectangle bounds= fContentAssistant.getLayoutManager().computeBoundsAboveBelow(fContextInfoPopup, size, offset);
441         if (bounds.width < size.x)
442             // we don't fit on the screen - try again and wrap
443
size= fContextInfoText.computeSize(bounds.width - PAD, SWT.DEFAULT, true);
444         
445         size.x += TEXT_PAD;
446         fContextInfoText.setSize(size);
447         fContextInfoText.setLocation(1,1);
448         size.x += BORDER_PAD;
449         size.y += BORDER_PAD;
450         fContextInfoPopup.setSize(size);
451     }
452
453     /**
454      * Hides the context information popup.
455      */

456     private void hideContextInfoPopup() {
457
458         if (Helper.okToUse(fContextInfoPopup)) {
459
460             int size= fContextFrameStack.size();
461             if (size > 0) {
462                 fLastContext= (ContextFrame) fContextFrameStack.pop();
463                 -- size;
464             }
465
466             if (size > 0) {
467                 ContextFrame current= (ContextFrame) fContextFrameStack.peek();
468                 internalShowContextFrame(current, false);
469             } else {
470
471                 fContentAssistant.removeContentAssistListener(this, ContentAssistant.CONTEXT_INFO_POPUP);
472
473                 if (fContentAssistSubjectControlAdapter.getControl() != null)
474                     fContentAssistSubjectControlAdapter.removeSelectionListener(fTextWidgetSelectionListener);
475                 fTextWidgetSelectionListener= null;
476
477                 fContextInfoPopup.setVisible(false);
478                 fContextInfoPopup.dispose();
479                 fContextInfoPopup= null;
480
481                 if (fTextPresentation != null) {
482                     fTextPresentation.clear();
483                     fTextPresentation= null;
484                 }
485             }
486         }
487
488         if (fContextInfoPopup == null)
489             fContentAssistant.contextInformationClosed();
490     }
491
492     /**
493      * Creates the context selector in case the user has the choice between multiple valid contexts
494      * at a given offset.
495      */

496     private void createContextSelector() {
497         if (Helper.okToUse(fContextSelectorShell))
498             return;
499
500         Control control= fContentAssistSubjectControlAdapter.getControl();
501         fContextSelectorShell= new Shell(control.getShell(), SWT.ON_TOP | SWT.RESIZE);
502         GridLayout layout= new GridLayout();
503         layout.marginWidth= 0;
504         layout.marginHeight= 0;
505         fContextSelectorShell.setLayout(layout);
506         fContextSelectorShell.setBackground(control.getDisplay().getSystemColor(SWT.COLOR_BLACK));
507
508
509         fContextSelectorTable= new Table(fContextSelectorShell, SWT.H_SCROLL | SWT.V_SCROLL);
510         fContextSelectorTable.setLocation(1, 1);
511         GridData gd= new GridData(GridData.FILL_BOTH);
512         gd.heightHint= fContextSelectorTable.getItemHeight() * 10;
513         gd.widthHint= 300;
514         fContextSelectorTable.setLayoutData(gd);
515
516         fContextSelectorShell.pack(true);
517
518         Color c= fContentAssistant.getContextSelectorBackground();
519         if (c == null)
520             c= control.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND);
521         fContextSelectorTable.setBackground(c);
522
523         c= fContentAssistant.getContextSelectorForeground();
524         if (c == null)
525             c= control.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND);
526         fContextSelectorTable.setForeground(c);
527
528         fContextSelectorTable.addSelectionListener(new SelectionListener() {
529             public void widgetSelected(SelectionEvent e) {
530             }
531
532             public void widgetDefaultSelected(SelectionEvent e) {
533                 insertSelectedContext();
534                 hideContextSelector();
535             }
536         });
537
538         fPopupCloser.install(fContentAssistant, fContextSelectorTable);
539
540         fContextSelectorTable.setHeaderVisible(false);
541         fContentAssistant.addToLayout(this, fContextSelectorShell, ContentAssistant.LayoutManager.LAYOUT_CONTEXT_SELECTOR, fContentAssistant.getSelectionOffset());
542     }
543
544     /**
545      * Returns the minimal required height for the popup, may return 0 if the popup has not been
546      * created yet.
547      *
548      * @return the minimal height
549      * @since 3.3
550      */

551     int getMinimalHeight() {
552         int height= 0;
553         if (Helper.okToUse(fContextSelectorTable)) {
554             int items= fContextSelectorTable.getItemHeight() * 10;
555             Rectangle trim= fContextSelectorTable.computeTrim(0, 0, SWT.DEFAULT, items);
556             height= trim.height;
557         }
558         return height;
559     }
560
561     /**
562      * Causes the context information of the context selected in the context selector
563      * to be displayed in the context information popup.
564      */

565     private void insertSelectedContext() {
566         int i= fContextSelectorTable.getSelectionIndex();
567
568         if (i < 0 || i >= fContextSelectorInput.length)
569             return;
570
571         int offset= fContentAssistSubjectControlAdapter.getSelectedRange().x;
572         internalShowContextInfo(createContextFrame(fContextSelectorInput[i], offset));
573     }
574
575     /**
576      * Sets the contexts in the context selector to the given set.
577      *
578      * @param contexts the possible contexts
579      */

580     private void setContexts(IContextInformation[] contexts) {
581         if (Helper.okToUse(fContextSelectorTable)) {
582
583             fContextSelectorInput= contexts;
584
585             fContextSelectorTable.setRedraw(false);
586             fContextSelectorTable.removeAll();
587
588             TableItem item;
589             IContextInformation t;
590             for (int i= 0; i < contexts.length; i++) {
591                 t= contexts[i];
592                 item= new TableItem(fContextSelectorTable, SWT.NULL);
593                 if (t.getImage() != null)
594                     item.setImage(t.getImage());
595                 item.setText(t.getContextDisplayString());
596             }
597
598             fContextSelectorTable.select(0);
599             fContextSelectorTable.setRedraw(true);
600         }
601     }
602
603     /**
604      * Displays the context selector.
605      */

606     private void displayContextSelector() {
607         if (fContentAssistant.addContentAssistListener(this, ContentAssistant.CONTEXT_SELECTOR))
608             fContextSelectorShell.setVisible(true);
609     }
610
611     /**
612      * Hides the context selector.
613      */

614     private void hideContextSelector() {
615         if (Helper.okToUse(fContextSelectorShell)) {
616             fContentAssistant.removeContentAssistListener(this, ContentAssistant.CONTEXT_SELECTOR);
617
618             fPopupCloser.uninstall();
619             fContextSelectorShell.setVisible(false);
620             fContextSelectorShell.dispose();
621             fContextSelectorShell= null;
622         }
623
624         if (!Helper.okToUse(fContextInfoPopup))
625             fContentAssistant.contextInformationClosed();
626     }
627
628     /**
629      *Returns whether the context selector has the focus.
630      *
631      * @return <code>true</code> if the context selector has the focus
632      */

633     public boolean hasFocus() {
634         if (Helper.okToUse(fContextSelectorShell))
635             return (fContextSelectorShell.isFocusControl() || fContextSelectorTable.isFocusControl());
636
637         return false;
638     }
639
640     /**
641      * Hides context selector and context information popup.
642      */

643     public void hide() {
644         hideContextSelector();
645         hideContextInfoPopup();
646     }
647
648     /**
649      * Returns whether this context information popup is active. I.e., either
650      * a context selector or context information is displayed.
651      *
652      * @return <code>true</code> if the context selector is active
653      */

654     public boolean isActive() {
655         return (Helper.okToUse(fContextInfoPopup) || Helper.okToUse(fContextSelectorShell));
656     }
657
658     /*
659      * @see IContentAssistListener#verifyKey(VerifyEvent)
660      */

661     public boolean verifyKey(VerifyEvent e) {
662         if (Helper.okToUse(fContextSelectorShell))
663             return contextSelectorKeyPressed(e);
664         if (Helper.okToUse(fContextInfoPopup))
665             return contextInfoPopupKeyPressed(e);
666         return true;
667     }
668
669     /**
670      * Processes a key stroke in the context selector.
671      *
672      * @param e the verify event describing the key stroke
673      * @return <code>true</code> if processing can be stopped
674      */

675     private boolean contextSelectorKeyPressed(VerifyEvent e) {
676
677         char key= e.character;
678         if (key == 0) {
679
680             int change;
681             int visibleRows= (fContextSelectorTable.getSize().y / fContextSelectorTable.getItemHeight()) - 1;
682             int selection= fContextSelectorTable.getSelectionIndex();
683
684             switch (e.keyCode) {
685
686                 case SWT.ARROW_UP:
687                     change= (fContextSelectorTable.getSelectionIndex() > 0 ? -1 : 0);
688                     break;
689
690                 case SWT.ARROW_DOWN:
691                     change= (fContextSelectorTable.getSelectionIndex() < fContextSelectorTable.getItemCount() - 1 ? 1 : 0);
692                     break;
693
694                 case SWT.PAGE_DOWN :
695                     change= visibleRows;
696                     if (selection + change >= fContextSelectorTable.getItemCount())
697                         change= fContextSelectorTable.getItemCount() - selection;
698                     break;
699
700                 case SWT.PAGE_UP :
701                     change= -visibleRows;
702                     if (selection + change < 0)
703                         change= -selection;
704                     break;
705
706                 case SWT.HOME :
707                     change= -selection;
708                     break;
709
710                 case SWT.END :
711                     change= fContextSelectorTable.getItemCount() - selection;
712                     break;
713
714                 default:
715                     if (e.keyCode != SWT.CAPS_LOCK && e.keyCode != SWT.MOD1 && e.keyCode != SWT.MOD2 && e.keyCode != SWT.MOD3 && e.keyCode != SWT.MOD4)
716                         hideContextSelector();
717                     return true;
718             }
719
720             fContextSelectorTable.setSelection(selection + change);
721             fContextSelectorTable.showSelection();
722             e.doit= false;
723             return false;
724
725         } else if ('\t' == key) {
726             // switch focus to selector shell
727
e.doit= false;
728             fContextSelectorShell.setFocus();
729             return false;
730         } else if (key == 0x1B) {
731             // terminate on Esc
732
hideContextSelector();
733         }
734
735         return true;
736     }
737
738     /**
739      * Processes a key stroke while the info popup is up.
740      *
741      * @param e the verify event describing the key stroke
742      * @return <code>true</code> if processing can be stopped
743      */

744     private boolean contextInfoPopupKeyPressed(KeyEvent e) {
745
746         char key= e.character;
747         if (key == 0) {
748
749             switch (e.keyCode) {
750
751                 case SWT.ARROW_LEFT:
752                 case SWT.ARROW_RIGHT:
753                     validateContextInformation();
754                     break;
755                 default:
756                     if (e.keyCode != SWT.CAPS_LOCK && e.keyCode != SWT.MOD1 && e.keyCode != SWT.MOD2 && e.keyCode != SWT.MOD3 && e.keyCode != SWT.MOD4)
757                         hideContextInfoPopup();
758                     break;
759             }
760
761         } else if (key == 0x1B) {
762             // terminate on Esc
763
hideContextInfoPopup();
764         } else {
765             validateContextInformation();
766         }
767         return true;
768     }
769
770     /*
771      * @see IEventConsumer#processEvent(VerifyEvent)
772      */

773     public void processEvent(VerifyEvent event) {
774         if (Helper.okToUse(fContextSelectorShell))
775             contextSelectorProcessEvent(event);
776         if (Helper.okToUse(fContextInfoPopup))
777             contextInfoPopupProcessEvent(event);
778     }
779
780     /**
781      * Processes a key stroke in the context selector.
782      *
783      * @param e the verify event describing the key stroke
784      */

785     private void contextSelectorProcessEvent(VerifyEvent e) {
786
787         if (e.start == e.end && e.text != null && e.text.equals(fLineDelimiter)) {
788             e.doit= false;
789             insertSelectedContext();
790         }
791
792         hideContextSelector();
793     }
794
795     /**
796      * Processes a key stroke while the info popup is up.
797      *
798      * @param e the verify event describing the key stroke
799      */

800     private void contextInfoPopupProcessEvent(VerifyEvent e) {
801         if (e.start != e.end && (e.text == null || e.text.length() == 0))
802             validateContextInformation();
803     }
804
805     /**
806      * Validates the context information for the viewer's actual cursor position.
807      */

808     private void validateContextInformation() {
809         /*
810          * Post the code in the event queue in order to ensure that the
811          * action described by this verify key event has already been executed.
812          * Otherwise, we'd validate the context information based on the
813          * pre-key-stroke state.
814          */

815         if (!Helper.okToUse(fContextInfoPopup))
816             return;
817
818         fContextInfoPopup.getDisplay().asyncExec(new Runnable JavaDoc() {
819
820             private ContextFrame fFrame= (ContextFrame) fContextFrameStack.peek();
821
822             public void run() {
823                 // only do this if no other frames have been added in between
824
if (!fContextFrameStack.isEmpty() && fFrame == fContextFrameStack.peek()) {
825                     int offset= fContentAssistSubjectControlAdapter.getSelectedRange().x;
826
827                     // iterate all contexts on the stack
828
while (Helper.okToUse(fContextInfoPopup) && !fContextFrameStack.isEmpty()) {
829                         ContextFrame top= (ContextFrame) fContextFrameStack.peek();
830                         if (top.fValidator == null || !top.fValidator.isContextInformationValid(offset)) {
831                             hideContextInfoPopup(); // loop variant: reduces the number of contexts on the stack
832
} else if (top.fPresenter != null && top.fPresenter.updatePresentation(offset, fTextPresentation)) {
833                             int widgetOffset= fContentAssistSubjectControlAdapter.getWidgetSelectionRange().x;
834                             TextPresentation.applyTextPresentation(fTextPresentation, fContextInfoText);
835                             resize(widgetOffset);
836                             break;
837                         } else
838                             break;
839                     }
840                 }
841             }
842         });
843     }
844 }
845
Popular Tags