1 11 package org.eclipse.jface.text.contentassist; 12 13 import java.util.ArrayList ; 14 import java.util.HashMap ; 15 import java.util.Iterator ; 16 import java.util.List ; 17 import java.util.Map ; 18 import java.util.Map.Entry; 19 20 import org.eclipse.swt.SWT; 21 import org.eclipse.swt.SWTError; 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.KeyAdapter; 30 import org.eclipse.swt.events.KeyEvent; 31 import org.eclipse.swt.events.KeyListener; 32 import org.eclipse.swt.events.MouseEvent; 33 import org.eclipse.swt.events.MouseListener; 34 import org.eclipse.swt.events.TraverseEvent; 35 import org.eclipse.swt.events.TraverseListener; 36 import org.eclipse.swt.events.VerifyEvent; 37 import org.eclipse.swt.graphics.Color; 38 import org.eclipse.swt.graphics.Point; 39 import org.eclipse.swt.graphics.Rectangle; 40 import org.eclipse.swt.widgets.Control; 41 import org.eclipse.swt.widgets.Display; 42 import org.eclipse.swt.widgets.Event; 43 import org.eclipse.swt.widgets.Listener; 44 import org.eclipse.swt.widgets.Monitor; 45 import org.eclipse.swt.widgets.Shell; 46 import org.eclipse.swt.widgets.Widget; 47 48 import org.eclipse.core.runtime.Assert; 49 50 import org.eclipse.jface.text.BadLocationException; 51 import org.eclipse.jface.text.IDocument; 52 import org.eclipse.jface.text.IDocumentExtension3; 53 import org.eclipse.jface.text.IEventConsumer; 54 import org.eclipse.jface.text.IInformationControlCreator; 55 import org.eclipse.jface.text.ITextViewer; 56 import org.eclipse.jface.text.IViewportListener; 57 import org.eclipse.jface.text.IWidgetTokenKeeper; 58 import org.eclipse.jface.text.IWidgetTokenKeeperExtension; 59 import org.eclipse.jface.text.IWidgetTokenOwner; 60 import org.eclipse.jface.text.IWidgetTokenOwnerExtension; 61 import org.eclipse.jface.text.TextUtilities; 62 63 import org.eclipse.jface.bindings.keys.KeySequence; 64 import org.eclipse.jface.contentassist.IContentAssistSubjectControl; 65 import org.eclipse.jface.contentassist.ISubjectControlContentAssistProcessor; 66 import org.eclipse.jface.dialogs.IDialogSettings; 67 import org.eclipse.jface.util.Geometry; 68 69 73 public class ContentAssistant implements IContentAssistant, IContentAssistantExtension, IContentAssistantExtension2, IContentAssistantExtension3, IWidgetTokenKeeper, IWidgetTokenKeeperExtension { 74 75 79 class Closer implements ControlListener, MouseListener, FocusListener, DisposeListener, IViewportListener { 80 81 82 private Shell fShell; 83 87 private Control fControl; 88 89 92 protected void install() { 93 Control control= fContentAssistSubjectControlAdapter.getControl(); 94 fControl= control; 95 if (Helper.okToUse(control)) { 96 97 Shell shell= control.getShell(); 98 fShell= shell; 99 shell.addControlListener(this); 100 101 control.addMouseListener(this); 102 control.addFocusListener(this); 103 104 108 control.addDisposeListener(this); 109 } 110 if (fViewer != null) 111 fViewer.addViewportListener(this); 112 } 113 114 117 protected void uninstall() { 118 Control shell= fShell; 119 fShell= null; 120 if (Helper.okToUse(shell)) 121 shell.removeControlListener(this); 122 123 Control control= fControl; 124 fControl= null; 125 if (Helper.okToUse(control)) { 126 127 control.removeMouseListener(this); 128 control.removeFocusListener(this); 129 130 134 control.removeDisposeListener(this); 135 } 136 137 if (fViewer != null) 138 fViewer.removeViewportListener(this); 139 } 140 141 144 public void controlResized(ControlEvent e) { 145 hide(); 146 } 147 148 151 public void controlMoved(ControlEvent e) { 152 hide(); 153 } 154 155 158 public void mouseDown(MouseEvent e) { 159 hide(); 160 } 161 162 165 public void mouseUp(MouseEvent e) { 166 } 167 168 171 public void mouseDoubleClick(MouseEvent e) { 172 hide(); 173 } 174 175 178 public void focusGained(FocusEvent e) { 179 } 180 181 184 public void focusLost(FocusEvent e) { 185 Control control= fControl; 186 if (Helper.okToUse(control)) { 187 Display d= control.getDisplay(); 188 if (d != null) { 189 d.asyncExec(new Runnable () { 190 public void run() { 191 if (!fProposalPopup.hasFocus() && (fContextInfoPopup == null || !fContextInfoPopup.hasFocus())) 192 hide(); 193 } 194 }); 195 } 196 } 197 } 198 199 202 public void widgetDisposed(DisposeEvent e) { 203 207 hide(); 208 } 209 210 213 public void viewportChanged(int topIndex) { 214 hide(); 215 } 216 } 217 218 225 class AutoAssistListener extends KeyAdapter implements KeyListener, Runnable , VerifyKeyListener { 226 227 private Thread fThread; 228 private boolean fIsReset= false; 229 private Object fMutex= new Object (); 230 private int fShowStyle; 231 232 private final static int SHOW_PROPOSALS= 1; 233 private final static int SHOW_CONTEXT_INFO= 2; 234 235 protected AutoAssistListener() { 236 } 237 238 protected void start(int showStyle) { 239 fShowStyle= showStyle; 240 fThread= new Thread (this, JFaceTextMessages.getString("ContentAssistant.assist_delay_timer_name")); fThread.start(); 242 } 243 244 public void run() { 245 try { 246 while (true) { 247 synchronized (fMutex) { 248 if (fAutoActivationDelay != 0) 249 fMutex.wait(fAutoActivationDelay); 250 if (fIsReset) { 251 fIsReset= false; 252 continue; 253 } 254 } 255 showAssist(fShowStyle); 256 break; 257 } 258 } catch (InterruptedException e) { 259 } 260 fThread= null; 261 } 262 263 protected void reset(int showStyle) { 264 synchronized (fMutex) { 265 fShowStyle= showStyle; 266 fIsReset= true; 267 fMutex.notifyAll(); 268 } 269 } 270 271 protected void stop() { 272 Thread threadToStop= fThread; 273 if (threadToStop != null && threadToStop.isAlive()) 274 threadToStop.interrupt(); 275 } 276 277 private boolean contains(char[] characters, char character) { 278 if (characters != null) { 279 for (int i= 0; i < characters.length; i++) { 280 if (character == characters[i]) 281 return true; 282 } 283 } 284 return false; 285 } 286 287 public void keyPressed(KeyEvent e) { 288 if (e.character == 0 && (e.keyCode & SWT.KEYCODE_BIT) == 0) 290 return; 291 292 if (e.character != 0 && (e.stateMask == SWT.ALT)) 293 return; 294 295 if (computeAllAutoActivationTriggers().indexOf(e.character) < 0) { 298 stop(); 299 return; 300 } 301 302 int showStyle; 303 int pos= fContentAssistSubjectControlAdapter.getSelectedRange().x; 304 char[] activation; 305 306 activation= fContentAssistSubjectControlAdapter.getCompletionProposalAutoActivationCharacters(ContentAssistant.this, pos); 307 308 if (contains(activation, e.character) && !fProposalPopup.isActive()) 309 showStyle= SHOW_PROPOSALS; 310 else { 311 activation= fContentAssistSubjectControlAdapter.getContextInformationAutoActivationCharacters(ContentAssistant.this, pos); 312 if (contains(activation, e.character) && fContextInfoPopup != null && !fContextInfoPopup.isActive()) 313 showStyle= SHOW_CONTEXT_INFO; 314 else { 315 stop(); 316 return; 317 } 318 } 319 320 if (fThread != null && fThread.isAlive()) 321 reset(showStyle); 322 else 323 start(showStyle); 324 } 325 326 329 public void verifyKey(VerifyEvent event) { 330 keyPressed(event); 331 } 332 333 protected void showAssist(final int showStyle) { 334 final Control control= fContentAssistSubjectControlAdapter.getControl(); 335 if (control == null) 336 return; 337 338 final Display d= control.getDisplay(); 339 if (d == null) 340 return; 341 342 try { 343 d.syncExec(new Runnable () { 344 public void run() { 345 if (fProposalPopup.isActive()) 346 return; 347 348 if (control.isDisposed() || !control.isFocusControl()) 349 return; 350 351 if (showStyle == SHOW_PROPOSALS) { 352 if (!prepareToShowCompletions()) 353 return; 354 fProposalPopup.showProposals(true); 355 fLastAutoActivation= System.currentTimeMillis(); 356 } else if (showStyle == SHOW_CONTEXT_INFO && fContextInfoPopup != null) { 357 promoteKeyListener(); 358 fContextInfoPopup.showContextProposals(true); 359 } 360 } 361 }); 362 } catch (SWTError e) { 363 } 364 } 365 } 366 367 371 class LayoutManager implements Listener { 372 373 375 public final static int LAYOUT_PROPOSAL_SELECTOR= 0; 376 377 public final static int LAYOUT_CONTEXT_SELECTOR= 1; 378 379 public final static int LAYOUT_CONTEXT_INFO_POPUP= 2; 380 381 int fContextType= LAYOUT_CONTEXT_SELECTOR; 382 Shell[] fShells= new Shell[3]; 383 Object [] fPopups= new Object [3]; 384 385 protected void add(Object popup, Shell shell, int type, int offset) { 386 Assert.isNotNull(popup); 387 Assert.isTrue(shell != null && !shell.isDisposed()); 388 checkType(type); 389 390 if (fShells[type] != shell) { 391 if (fShells[type] != null) 392 fShells[type].removeListener(SWT.Dispose, this); 393 shell.addListener(SWT.Dispose, this); 394 fShells[type]= shell; 395 } 396 397 fPopups[type]= popup; 398 if (type == LAYOUT_CONTEXT_SELECTOR || type == LAYOUT_CONTEXT_INFO_POPUP) 399 fContextType= type; 400 401 layout(type, offset); 402 adjustListeners(type); 403 } 404 405 protected void checkType(int type) { 406 Assert.isTrue(type == LAYOUT_PROPOSAL_SELECTOR || 407 type == LAYOUT_CONTEXT_SELECTOR || type == LAYOUT_CONTEXT_INFO_POPUP); 408 } 409 410 public void handleEvent(Event event) { 411 Widget source= event.widget; 412 source.removeListener(SWT.Dispose, this); 413 414 int type= getShellType(source); 415 checkType(type); 416 fShells[type]= null; 417 418 switch (type) { 419 case LAYOUT_PROPOSAL_SELECTOR: 420 if (fContextType == LAYOUT_CONTEXT_SELECTOR && 421 Helper.okToUse(fShells[LAYOUT_CONTEXT_SELECTOR])) { 422 addContentAssistListener((IContentAssistListener) fPopups[LAYOUT_CONTEXT_SELECTOR], CONTEXT_SELECTOR); 424 } 425 break; 426 427 case LAYOUT_CONTEXT_SELECTOR: 428 if (Helper.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR])) { 429 if (fProposalPopupOrientation == PROPOSAL_STACKED) 430 layout(LAYOUT_PROPOSAL_SELECTOR, getSelectionOffset()); 431 addContentAssistListener((IContentAssistListener) fPopups[LAYOUT_PROPOSAL_SELECTOR], PROPOSAL_SELECTOR); 433 } 434 fContextType= LAYOUT_CONTEXT_INFO_POPUP; 435 break; 436 437 case LAYOUT_CONTEXT_INFO_POPUP: 438 if (Helper.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR])) { 439 if (fContextInfoPopupOrientation == CONTEXT_INFO_BELOW) 440 layout(LAYOUT_PROPOSAL_SELECTOR, getSelectionOffset()); 441 } 442 fContextType= LAYOUT_CONTEXT_SELECTOR; 443 break; 444 } 445 } 446 447 protected int getShellType(Widget shell) { 448 for (int i= 0; i < fShells.length; i++) { 449 if (fShells[i] == shell) 450 return i; 451 } 452 return -1; 453 } 454 455 461 protected void layout(int type, int offset) { 462 switch (type) { 463 case LAYOUT_PROPOSAL_SELECTOR: 464 layoutProposalSelector(offset); 465 break; 466 case LAYOUT_CONTEXT_SELECTOR: 467 layoutContextSelector(offset); 468 break; 469 case LAYOUT_CONTEXT_INFO_POPUP: 470 layoutContextInfoPopup(offset); 471 break; 472 } 473 } 474 475 protected void layoutProposalSelector(int offset) { 476 if (fContextType == LAYOUT_CONTEXT_INFO_POPUP && 477 fContextInfoPopupOrientation == CONTEXT_INFO_BELOW && 478 Helper.okToUse(fShells[LAYOUT_CONTEXT_INFO_POPUP])) { 479 Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR]; 481 Shell parent= fShells[LAYOUT_CONTEXT_INFO_POPUP]; 482 shell.setLocation(getStackedLocation(shell, parent)); 483 } else if (fContextType != LAYOUT_CONTEXT_SELECTOR || 484 !Helper.okToUse(fShells[LAYOUT_CONTEXT_SELECTOR])) { 485 Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR]; 488 CompletionProposalPopup popup= (CompletionProposalPopup) fPopups[LAYOUT_PROPOSAL_SELECTOR]; 489 shell.setBounds(computeBoundsBelowAbove(shell, shell.getSize(), offset, popup)); 490 } else { 491 CompletionProposalPopup popup= ((CompletionProposalPopup) fPopups[LAYOUT_PROPOSAL_SELECTOR]); 492 switch (fProposalPopupOrientation) { 493 case PROPOSAL_REMOVE: { 494 fShells[LAYOUT_CONTEXT_SELECTOR].dispose(); 497 Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR]; 498 shell.setBounds(computeBoundsBelowAbove(shell, shell.getSize(), offset, popup)); 499 break; 500 } 501 case PROPOSAL_OVERLAY: { 502 Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR]; 504 shell.setBounds(computeBoundsBelowAbove(shell, shell.getSize(), offset, popup)); 505 break; 506 } 507 case PROPOSAL_STACKED: { 508 Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR]; 510 Shell parent= fShells[LAYOUT_CONTEXT_SELECTOR]; 511 shell.setLocation(getStackedLocation(shell, parent)); 512 break; 513 } 514 } 515 } 516 } 517 518 protected void layoutContextSelector(int offset) { 519 Shell shell= fShells[LAYOUT_CONTEXT_SELECTOR]; 521 shell.setBounds(computeBoundsBelowAbove(shell, shell.getSize(), offset, null)); 522 523 if (Helper.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR])) { 524 switch (fProposalPopupOrientation) { 525 case PROPOSAL_REMOVE: 526 fShells[LAYOUT_PROPOSAL_SELECTOR].dispose(); 528 break; 529 530 case PROPOSAL_OVERLAY: 531 break; 533 534 case PROPOSAL_STACKED: { 535 shell= fShells[LAYOUT_PROPOSAL_SELECTOR]; 537 Shell parent= fShells[LAYOUT_CONTEXT_SELECTOR]; 538 shell.setLocation(getStackedLocation(shell, parent)); 539 break; 540 } 541 } 542 } 543 } 544 545 protected void layoutContextInfoPopup(int offset) { 546 switch (fContextInfoPopupOrientation) { 547 case CONTEXT_INFO_ABOVE: { 548 Shell shell= fShells[LAYOUT_CONTEXT_INFO_POPUP]; 550 shell.setBounds(computeBoundsAboveBelow(shell, shell.getSize(), offset)); 551 break; 552 } 553 case CONTEXT_INFO_BELOW: { 554 Shell parent= fShells[LAYOUT_CONTEXT_INFO_POPUP]; 556 parent.setBounds(computeBoundsBelowAbove(parent, parent.getSize(), offset, null)); 557 if (Helper.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR])) { 558 Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR]; 560 shell.setLocation(getStackedLocation(shell, parent)); 561 } 562 break; 563 } 564 } 565 } 566 567 576 protected void constrainLocation(Point point, Point shellSize, Rectangle bounds) { 577 if (point.x + shellSize.x > bounds.x + bounds.width) 578 point.x= bounds.x + bounds.width - shellSize.x; 579 580 if (point.x < bounds.x) 581 point.x= bounds.x; 582 583 if (point.y + shellSize.y > bounds.y + bounds.height) 584 point.y= bounds.y + bounds.height - shellSize.y; 585 586 if (point.y < bounds.y) 587 point.y= bounds.y; 588 } 589 590 protected Rectangle constrainHorizontally(Rectangle rect, Rectangle bounds) { 591 if (rect.width > bounds.width) 593 rect.width= bounds.width; 594 595 if (rect.x + rect.width > bounds.x + bounds.width) 596 rect.x= bounds.x + bounds.width - rect.width; 597 if (rect.x < bounds.x) 598 rect.x= bounds.x; 599 600 return rect; 601 } 602 603 614 protected Rectangle computeBoundsAboveBelow(Shell shell, Point preferred, int offset) { 615 Control subjectControl= fContentAssistSubjectControlAdapter.getControl(); 616 Display display= subjectControl.getDisplay(); 617 Rectangle caret= getCaretRectangle(offset); 618 Monitor monitor= getClosestMonitor(display, caret); 619 Rectangle bounds= monitor.getClientArea(); 620 Geometry.moveInside(caret, bounds); 621 622 int spaceAbove= caret.y - bounds.y; 623 int caretLowerY= caret.y + caret.height; 624 int spaceBelow= bounds.y + bounds.height - caretLowerY; 625 Rectangle rect; 626 if (spaceAbove >= preferred.y) 627 rect= new Rectangle(caret.x, caret.y - preferred.y, preferred.x, preferred.y); 628 else if (spaceBelow >= preferred.y) 629 rect= new Rectangle(caret.x, caretLowerY, preferred.x, preferred.y); 630 else if (spaceBelow <= spaceAbove) 632 rect= new Rectangle(caret.x, bounds.y, preferred.x, spaceAbove); 633 else 634 rect= new Rectangle(caret.x, caretLowerY, preferred.x, spaceBelow); 635 636 return constrainHorizontally(rect, bounds); 637 } 638 639 651 protected Rectangle computeBoundsBelowAbove(Shell shell, Point preferred, int offset, CompletionProposalPopup popup) { 652 Control subjectControl= fContentAssistSubjectControlAdapter.getControl(); 653 Display display= subjectControl.getDisplay(); 654 Rectangle caret= getCaretRectangle(offset); 655 Monitor monitor= getClosestMonitor(display, caret); 656 Rectangle bounds= monitor.getClientArea(); 657 Geometry.moveInside(caret, bounds); 658 659 int threshold= popup == null ? Integer.MAX_VALUE : popup.getMinimalHeight(); 660 int spaceAbove= caret.y - bounds.y; 661 int spaceBelow= bounds.y + bounds.height - (caret.y + caret.height); 662 Rectangle rect; 663 boolean switched= false; 664 if (spaceBelow >= preferred.y) 665 rect= new Rectangle(caret.x, caret.y + caret.height, preferred.x, preferred.y); 666 else if (spaceBelow >= threshold) 668 rect= new Rectangle(caret.x, caret.y + caret.height, preferred.x, spaceBelow); 669 else if (spaceAbove >= preferred.y) { 670 rect= new Rectangle(caret.x, caret.y - preferred.y, preferred.x, preferred.y); 671 switched= true; 672 } else if (spaceBelow >= spaceAbove) { 673 rect= new Rectangle(caret.x, caret.y + caret.height, preferred.x, spaceBelow); 675 } else { 676 rect= new Rectangle(caret.x, bounds.y, preferred.x, spaceAbove); 677 switched= true; 678 } 679 680 if (popup != null) 681 popup.switchedPositionToAbove(switched); 682 683 return constrainHorizontally(rect, bounds); 684 } 685 686 private Rectangle getCaretRectangle(int offset) { 687 Point location= fContentAssistSubjectControlAdapter.getLocationAtOffset(offset); 688 Control subjectControl= fContentAssistSubjectControlAdapter.getControl(); 689 Point controlSize= subjectControl.getSize(); 690 constrainLocation(location, new Point(0, 0), new Rectangle(0, 0, controlSize.x, controlSize.y)); 691 location= subjectControl.toDisplay(location); 692 Rectangle subjectRectangle= new Rectangle(location.x, location.y, 1, fContentAssistSubjectControlAdapter.getLineHeight()); 693 return subjectRectangle; 694 } 695 696 protected Point getStackedLocation(Shell shell, Shell parent) { 697 Point p= parent.getLocation(); 698 Point size= parent.getSize(); 699 p.x += size.x / 4; 700 p.y += size.y; 701 702 p= parent.toDisplay(p); 703 704 Point shellSize= shell.getSize(); 705 Monitor monitor= getClosestMonitor(parent.getDisplay(), new Rectangle(p.x, p.y, 0, 0)); 706 Rectangle displayBounds= monitor.getClientArea(); 707 constrainLocation(p, shellSize, displayBounds); 708 709 return p; 710 } 711 712 protected void adjustListeners(int type) { 713 switch (type) { 714 case LAYOUT_PROPOSAL_SELECTOR: 715 if (fContextType == LAYOUT_CONTEXT_SELECTOR && 716 Helper.okToUse(fShells[LAYOUT_CONTEXT_SELECTOR])) 717 removeContentAssistListener((IContentAssistListener) fPopups[LAYOUT_CONTEXT_SELECTOR], CONTEXT_SELECTOR); 719 break; 720 case LAYOUT_CONTEXT_SELECTOR: 721 if (Helper.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR])) 722 removeContentAssistListener((IContentAssistListener) fPopups[LAYOUT_PROPOSAL_SELECTOR], PROPOSAL_SELECTOR); 724 break; 725 case LAYOUT_CONTEXT_INFO_POPUP: 726 break; 727 } 728 } 729 730 744 private Monitor getClosestMonitor(Display toSearch, Rectangle rectangle) { 745 int closest = Integer.MAX_VALUE; 746 747 Point toFind= Geometry.centerPoint(rectangle); 748 Monitor[] monitors = toSearch.getMonitors(); 749 Monitor result = monitors[0]; 750 751 for (int idx = 0; idx < monitors.length; idx++) { 752 Monitor current = monitors[idx]; 753 754 Rectangle clientArea = current.getClientArea(); 755 756 if (clientArea.contains(toFind)) { 757 return current; 758 } 759 760 int distance = Geometry.distanceSquared(Geometry.centerPoint(clientArea), toFind); 761 if (distance < closest) { 762 closest = distance; 763 result = current; 764 } 765 } 766 767 return result; 768 } 769 } 770 771 774 class InternalListener implements VerifyKeyListener, IEventConsumer { 775 776 783 public void verifyKey(VerifyEvent e) { 784 IContentAssistListener[] listeners= (IContentAssistListener[]) fListeners.clone(); 785 for (int i= 0; i < listeners.length; i++) { 786 if (listeners[i] != null) { 787 if (!listeners[i].verifyKey(e) || !e.doit) 788 break; 789 } 790 } 791 if (fAutoAssistListener != null) 792 fAutoAssistListener.keyPressed(e); 793 } 794 795 798 public void processEvent(VerifyEvent event) { 799 800 installKeyListener(); 801 802 IContentAssistListener[] listeners= (IContentAssistListener[]) fListeners.clone(); 803 for (int i= 0; i < listeners.length; i++) { 804 if (listeners[i] != null) { 805 listeners[i].processEvent(event); 806 if (!event.doit) 807 return; 808 } 809 } 810 } 811 } 812 813 818 public static final String STORE_SIZE_X= "size.x"; public static final String STORE_SIZE_Y= "size.y"; 821 final static int CONTEXT_SELECTOR= 0; 823 final static int PROPOSAL_SELECTOR= 1; 824 final static int CONTEXT_INFO_POPUP= 2; 825 826 832 public static final int WIDGET_PRIORITY= 20; 833 834 private static final int DEFAULT_AUTO_ACTIVATION_DELAY= 500; 835 836 private IInformationControlCreator fInformationControlCreator; 837 private int fAutoActivationDelay= DEFAULT_AUTO_ACTIVATION_DELAY; 838 private boolean fIsAutoActivated= false; 839 private boolean fIsAutoInserting= false; 840 private int fProposalPopupOrientation= PROPOSAL_OVERLAY; 841 private int fContextInfoPopupOrientation= CONTEXT_INFO_ABOVE; 842 private Map fProcessors; 843 844 849 private String fPartitioning; 850 851 private Color fContextInfoPopupBackground; 852 private Color fContextInfoPopupForeground; 853 private Color fContextSelectorBackground; 854 private Color fContextSelectorForeground; 855 private Color fProposalSelectorBackground; 856 private Color fProposalSelectorForeground; 857 858 private ITextViewer fViewer; 859 private String fLastErrorMessage; 860 861 private Closer fCloser; 862 LayoutManager fLayoutManager; 863 private AutoAssistListener fAutoAssistListener; 864 private InternalListener fInternalListener; 865 private CompletionProposalPopup fProposalPopup; 866 private ContextInformationPopup fContextInfoPopup; 867 868 873 private boolean fVerifyKeyListenerHooked= false; 874 private IContentAssistListener[] fListeners= new IContentAssistListener[4]; 875 880 private IContentAssistSubjectControl fContentAssistSubjectControl; 881 886 private Shell fContentAssistSubjectControlShell; 887 892 private TraverseListener fCASCSTraverseListener; 893 898 private ContentAssistSubjectControlAdapter fContentAssistSubjectControlAdapter; 899 904 private IDialogSettings fDialogSettings; 905 910 private boolean fIsPrefixCompletionEnabled= false; 911 916 private List fCompletionListeners= new ArrayList (); 917 922 private String fMessage= ""; 928 private boolean fIsRepetitionMode= false; 929 934 private boolean fShowEmptyList= false; 935 940 private boolean fIsStatusLineVisible; 941 945 private long fLastAutoActivation= Long.MIN_VALUE; 946 951 private KeySequence fTriggerSequence; 952 953 954 961 public ContentAssistant() { 962 fPartitioning= IDocumentExtension3.DEFAULT_PARTITIONING; 963 } 964 965 971 public void setDocumentPartitioning(String partitioning) { 972 Assert.isNotNull(partitioning); 973 fPartitioning= partitioning; 974 } 975 976 980 public String getDocumentPartitioning() { 981 return fPartitioning; 982 } 983 984 992 public void setContentAssistProcessor(IContentAssistProcessor processor, String contentType) { 993 994 Assert.isNotNull(contentType); 995 996 if (fProcessors == null) 997 fProcessors= new HashMap (); 998 999 if (processor == null) 1000 fProcessors.remove(contentType); 1001 else 1002 fProcessors.put(contentType, processor); 1003 } 1004 1005 1008 public IContentAssistProcessor getContentAssistProcessor(String contentType) { 1009 if (fProcessors == null) 1010 return null; 1011 1012 return (IContentAssistProcessor) fProcessors.get(contentType); 1013 } 1014 1015 1021 private String computeAllAutoActivationTriggers() { 1022 if (fProcessors == null) 1023 return ""; 1025 StringBuffer buf= new StringBuffer (5); 1026 Iterator iter= fProcessors.entrySet().iterator(); 1027 while (iter.hasNext()) { 1028 Entry entry= (Entry) iter.next(); 1029 IContentAssistProcessor processor= (IContentAssistProcessor) entry.getValue(); 1030 char[] triggers= processor.getCompletionProposalAutoActivationCharacters(); 1031 if (triggers != null) 1032 buf.append(triggers); 1033 triggers= processor.getContextInformationAutoActivationCharacters(); 1034 if (triggers != null) 1035 buf.append(triggers); 1036 } 1037 return buf.toString(); 1038 } 1039 1040 1045 public void enableAutoActivation(boolean enabled) { 1046 fIsAutoActivated= enabled; 1047 manageAutoActivation(fIsAutoActivated); 1048 } 1049 1050 1058 public void enableAutoInsert(boolean enabled) { 1059 fIsAutoInserting= enabled; 1060 } 1061 1062 1068 boolean isAutoInserting() { 1069 return fIsAutoInserting; 1070 } 1071 1072 1079 private void manageAutoActivation(boolean start) { 1080 if (start) { 1081 1082 if ((fContentAssistSubjectControlAdapter != null) && fAutoAssistListener == null) { 1083 fAutoAssistListener= new AutoAssistListener(); 1084 if (fContentAssistSubjectControlAdapter.supportsVerifyKeyListener()) 1086 fContentAssistSubjectControlAdapter.appendVerifyKeyListener(fAutoAssistListener); 1087 else 1088 fContentAssistSubjectControlAdapter.addKeyListener(fAutoAssistListener); 1089 } 1090 1091 } else if (fAutoAssistListener != null) { 1092 if (fContentAssistSubjectControlAdapter.supportsVerifyKeyListener()) 1094 fContentAssistSubjectControlAdapter.removeVerifyKeyListener(fAutoAssistListener); 1095 else 1096 fContentAssistSubjectControlAdapter.removeKeyListener(fAutoAssistListener); 1097 fAutoAssistListener= null; 1098 } 1099 } 1100 1101 1107 public void setAutoActivationDelay(int delay) { 1108 fAutoActivationDelay= delay; 1109 } 1110 1111 1128 public void setProposalPopupOrientation(int orientation) { 1129 fProposalPopupOrientation= orientation; 1130 } 1131 1132 1148 public void setContextInformationPopupOrientation(int orientation) { 1149 fContextInfoPopupOrientation= orientation; 1150 } 1151 1152 1157 public void setContextInformationPopupBackground(Color background) { 1158 fContextInfoPopupBackground= background; 1159 } 1160 1161 1167 Color getContextInformationPopupBackground() { 1168 return fContextInfoPopupBackground; 1169 } 1170 1171 1177 public void setContextInformationPopupForeground(Color foreground) { 1178 fContextInfoPopupForeground= foreground; 1179 } 1180 1181 1187 Color getContextInformationPopupForeground() { 1188 return fContextInfoPopupForeground; 1189 } 1190 1191 1197 public void setProposalSelectorBackground(Color background) { 1198 fProposalSelectorBackground= background; 1199 } 1200 1201 1207 Color getProposalSelectorBackground() { 1208 return fProposalSelectorBackground; 1209 } 1210 1211 1217 public void setProposalSelectorForeground(Color foreground) { 1218 fProposalSelectorForeground= foreground; 1219 } 1220 1221 1227 Color getProposalSelectorForeground() { 1228 return fProposalSelectorForeground; 1229 } 1230 1231 1237 public void setContextSelectorBackground(Color background) { 1238 fContextSelectorBackground= background; 1239 } 1240 1241 1247 Color getContextSelectorBackground() { 1248 return fContextSelectorBackground; 1249 } 1250 1251 1257 public void setContextSelectorForeground(Color foreground) { 1258 fContextSelectorForeground= foreground; 1259 } 1260 1261 1267 Color getContextSelectorForeground() { 1268 return fContextSelectorForeground; 1269 } 1270 1271 1277 public void setInformationControlCreator(IInformationControlCreator creator) { 1278 fInformationControlCreator= creator; 1279 } 1280 1281 1285 protected void install(IContentAssistSubjectControl contentAssistSubjectControl) { 1286 fContentAssistSubjectControl= contentAssistSubjectControl; 1287 fContentAssistSubjectControlAdapter= new ContentAssistSubjectControlAdapter(fContentAssistSubjectControl); 1288 install(); 1289 } 1290 1291 1295 public void install(ITextViewer textViewer) { 1296 fViewer= textViewer; 1297 fContentAssistSubjectControlAdapter= new ContentAssistSubjectControlAdapter(fViewer); 1298 install(); 1299 } 1300 1301 protected void install() { 1302 1303 fLayoutManager= new LayoutManager(); 1304 fInternalListener= new InternalListener(); 1305 1306 AdditionalInfoController controller= null; 1307 if (fInformationControlCreator != null) { 1308 int delay= fAutoActivationDelay; 1309 if (delay == 0) 1310 delay= DEFAULT_AUTO_ACTIVATION_DELAY; 1311 delay= Math.round(delay * 1.5f); 1312 controller= new AdditionalInfoController(fInformationControlCreator, delay); 1313 } 1314 1315 fContextInfoPopup= fContentAssistSubjectControlAdapter.createContextInfoPopup(this); 1316 fProposalPopup= fContentAssistSubjectControlAdapter.createCompletionProposalPopup(this, controller); 1317 1318 if (Helper.okToUse(fContentAssistSubjectControlAdapter.getControl())) { 1319 fContentAssistSubjectControlShell= fContentAssistSubjectControlAdapter.getControl().getShell(); 1320 fCASCSTraverseListener= new TraverseListener() { 1321 public void keyTraversed(TraverseEvent e) { 1322 if (e.detail == SWT.TRAVERSE_ESCAPE && fProposalPopup != null && fProposalPopup.isActive()) 1323 e.doit= false; 1324 } 1325 }; 1326 fContentAssistSubjectControlShell.addTraverseListener(fCASCSTraverseListener); 1327 } 1328 1329 manageAutoActivation(fIsAutoActivated); 1330 } 1331 1332 1335 public void uninstall() { 1336 hide(); 1337 manageAutoActivation(false); 1338 1339 if (fCloser != null) { 1340 fCloser.uninstall(); 1341 fCloser= null; 1342 } 1343 1344 if (Helper.okToUse(fContentAssistSubjectControlShell)) 1345 fContentAssistSubjectControlShell.removeTraverseListener(fCASCSTraverseListener); 1346 fCASCSTraverseListener= null; 1347 fContentAssistSubjectControlShell= null; 1348 1349 fViewer= null; 1350 fContentAssistSubjectControl= null; 1351 fContentAssistSubjectControlAdapter= null; 1352 } 1353 1354 1365 void addToLayout(Object popup, Shell shell, int type, int visibleOffset) { 1366 fLayoutManager.add(popup, shell, type, visibleOffset); 1367 } 1368 1369 1379 void layout(int type, int visibleOffset) { 1380 fLayoutManager.layout(type, visibleOffset); 1381 } 1382 1383 1389 LayoutManager getLayoutManager() { 1390 return fLayoutManager; 1391 } 1392 1393 1398 void popupFocusLost(FocusEvent e) { 1399 fCloser.focusLost(e); 1400 } 1401 1402 1408 int getSelectionOffset() { 1409 return fContentAssistSubjectControlAdapter.getWidgetSelectionRange().x; 1410 } 1411 1412 1425 private boolean acquireWidgetToken(int type) { 1426 switch (type) { 1427 case CONTEXT_SELECTOR: 1428 case PROPOSAL_SELECTOR: 1429 if (fContentAssistSubjectControl instanceof IWidgetTokenOwnerExtension) { 1430 IWidgetTokenOwnerExtension extension= (IWidgetTokenOwnerExtension) fContentAssistSubjectControl; 1431 return extension.requestWidgetToken(this, WIDGET_PRIORITY); 1432 } else if (fContentAssistSubjectControl instanceof IWidgetTokenOwner) { 1433 IWidgetTokenOwner owner= (IWidgetTokenOwner) fContentAssistSubjectControl; 1434 return owner.requestWidgetToken(this); 1435 } else if (fViewer instanceof IWidgetTokenOwnerExtension) { 1436 IWidgetTokenOwnerExtension extension= (IWidgetTokenOwnerExtension) fViewer; 1437 return extension.requestWidgetToken(this, WIDGET_PRIORITY); 1438 } else if (fViewer instanceof IWidgetTokenOwner) { 1439 IWidgetTokenOwner owner= (IWidgetTokenOwner) fViewer; 1440 return owner.requestWidgetToken(this); 1441 } 1442 } 1443 return true; 1444 } 1445 1446 1461 boolean addContentAssistListener(IContentAssistListener listener, int type) { 1462 1463 if (acquireWidgetToken(type)) { 1464 1465 fListeners[type]= listener; 1466 1467 if (fCloser == null && getNumberOfListeners() == 1) { 1468 fCloser= new Closer(); 1469 fCloser.install(); 1470 fContentAssistSubjectControlAdapter.setEventConsumer(fInternalListener); 1471 installKeyListener(); 1472 } else 1473 promoteKeyListener(); 1474 return true; 1475 } 1476 1477 return false; 1478 } 1479 1480 1487 private void promoteKeyListener() { 1488 uninstallVerifyKeyListener(); 1489 installKeyListener(); 1490 } 1491 1492 1495 private void installKeyListener() { 1496 if (!fVerifyKeyListenerHooked) { 1497 if (Helper.okToUse(fContentAssistSubjectControlAdapter.getControl())) { 1498 fVerifyKeyListenerHooked= fContentAssistSubjectControlAdapter.prependVerifyKeyListener(fInternalListener); 1499 } 1500 } 1501 } 1502 1503 1516 private void releaseWidgetToken(int type) { 1517 if (fListeners[CONTEXT_SELECTOR] == null && fListeners[PROPOSAL_SELECTOR] == null) { 1518 IWidgetTokenOwner owner= null; 1519 if (fContentAssistSubjectControl instanceof IWidgetTokenOwner) 1520 owner= (IWidgetTokenOwner) fContentAssistSubjectControl; 1521 else if (fViewer instanceof IWidgetTokenOwner) 1522 owner= (IWidgetTokenOwner) fViewer; 1523 if (owner != null) 1524 owner.releaseWidgetToken(this); 1525 } 1526 } 1527 1528 1535 void removeContentAssistListener(IContentAssistListener listener, int type) { 1536 fListeners[type]= null; 1537 1538 if (getNumberOfListeners() == 0) { 1539 1540 if (fCloser != null) { 1541 fCloser.uninstall(); 1542 fCloser= null; 1543 } 1544 1545 uninstallVerifyKeyListener(); 1546 fContentAssistSubjectControlAdapter.setEventConsumer(null); 1547 } 1548 1549 releaseWidgetToken(type); 1550 } 1551 1552 1557 private void uninstallVerifyKeyListener() { 1558 if (fVerifyKeyListenerHooked) { 1559 if (Helper.okToUse(fContentAssistSubjectControlAdapter.getControl())) 1560 fContentAssistSubjectControlAdapter.removeVerifyKeyListener(fInternalListener); 1561 fVerifyKeyListenerHooked= false; 1562 } 1563 } 1564 1565 1571 private int getNumberOfListeners() { 1572 int count= 0; 1573 for (int i= 0; i <= CONTEXT_INFO_POPUP; i++) { 1574 if (fListeners[i] != null) 1575 ++count; 1576 } 1577 return count; 1578 } 1579 1580 1583 public String showPossibleCompletions() { 1584 if (!prepareToShowCompletions()) 1585 return null; 1586 if (fIsPrefixCompletionEnabled) 1587 return fProposalPopup.incrementalComplete(); 1588 return fProposalPopup.showProposals(false); 1589 } 1590 1591 1595 public String completePrefix() { 1596 if (!prepareToShowCompletions()) 1597 return null; 1598 return fProposalPopup.incrementalComplete(); 1599 } 1600 1601 1609 private boolean prepareToShowCompletions() { 1610 long current= System.currentTimeMillis(); 1611 int gracePeriod= Math.max(fAutoActivationDelay, 200); 1612 if (current < fLastAutoActivation + gracePeriod) 1613 return false; 1614 1615 promoteKeyListener(); 1616 fireSessionBeginEvent(); 1617 return true; 1618 } 1619 1620 1626 protected void possibleCompletionsClosed() { 1627 fLastAutoActivation= Long.MIN_VALUE; 1628 storeCompletionProposalPopupSize(); 1629 } 1630 1631 1634 public String showContextInformation() { 1635 promoteKeyListener(); 1636 if (fContextInfoPopup != null) 1637 return fContextInfoPopup.showContextProposals(false); 1638 return null; 1639 } 1640 1641 1647 protected void contextInformationClosed() { 1648 } 1649 1650 1657 void showContextInformation(IContextInformation contextInformation, int offset) { 1658 if (fContextInfoPopup != null) 1659 fContextInfoPopup.showContextInformation(contextInformation, offset); 1660 } 1661 1662 1667 String getErrorMessage() { 1668 return fLastErrorMessage; 1669 } 1670 1671 1679 private IContentAssistProcessor getProcessor(ITextViewer viewer, int offset) { 1680 try { 1681 1682 IDocument document= viewer.getDocument(); 1683 String type= TextUtilities.getContentType(document, getDocumentPartitioning(), offset, true); 1684 1685 return getContentAssistProcessor(type); 1686 1687 } catch (BadLocationException x) { 1688 } 1689 1690 return null; 1691 } 1692 1693 1701 private IContentAssistProcessor getProcessor(IContentAssistSubjectControl contentAssistSubjectControl, int offset) { 1702 try { 1703 1704 IDocument document= contentAssistSubjectControl.getDocument(); 1705 String type; 1706 if (document != null) 1707 type= TextUtilities.getContentType(document, getDocumentPartitioning(), offset, true); 1708 else 1709 type= IDocument.DEFAULT_CONTENT_TYPE; 1710 1711 return getContentAssistProcessor(type); 1712 1713 } catch (BadLocationException x) { 1714 } 1715 1716 return null; 1717 } 1718 1719 1729 ICompletionProposal[] computeCompletionProposals(IContentAssistSubjectControl contentAssistSubjectControl, int offset) { 1730 fLastErrorMessage= null; 1731 1732 ICompletionProposal[] result= null; 1733 1734 IContentAssistProcessor p= getProcessor(contentAssistSubjectControl, offset); 1735 if (p instanceof ISubjectControlContentAssistProcessor) { 1736 result= ((ISubjectControlContentAssistProcessor) p).computeCompletionProposals(contentAssistSubjectControl, offset); 1737 fLastErrorMessage= p.getErrorMessage(); 1738 } 1739 1740 return result; 1741 } 1742 1743 1752 ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { 1753 fLastErrorMessage= null; 1754 1755 ICompletionProposal[] result= null; 1756 1757 IContentAssistProcessor p= getProcessor(viewer, offset); 1758 if (p != null) { 1759 result= p.computeCompletionProposals(viewer, offset); 1760 fLastErrorMessage= p.getErrorMessage(); 1761 } 1762 1763 return result; 1764 } 1765 1766 1776 IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { 1777 fLastErrorMessage= null; 1778 1779 IContextInformation[] result= null; 1780 1781 IContentAssistProcessor p= getProcessor(viewer, offset); 1782 if (p != null) { 1783 result= p.computeContextInformation(viewer, offset); 1784 fLastErrorMessage= p.getErrorMessage(); 1785 } 1786 1787 return result; 1788 } 1789 1790 1801 IContextInformation[] computeContextInformation(IContentAssistSubjectControl contentAssistSubjectControl, int offset) { 1802 fLastErrorMessage= null; 1803 1804 IContextInformation[] result= null; 1805 1806 IContentAssistProcessor p= getProcessor(contentAssistSubjectControl, offset); 1807 if (p instanceof ISubjectControlContentAssistProcessor) { 1808 result= ((ISubjectControlContentAssistProcessor) p).computeContextInformation(contentAssistSubjectControl, offset); 1809 fLastErrorMessage= p.getErrorMessage(); 1810 } 1811 1812 return result; 1813 } 1814 1815 1826 IContextInformationValidator getContextInformationValidator(ITextViewer viewer, int offset) { 1827 IContentAssistProcessor p= getProcessor(viewer, offset); 1828 return p != null ? p.getContextInformationValidator() : null; 1829 } 1830 1831 1842 IContextInformationValidator getContextInformationValidator(IContentAssistSubjectControl contentAssistSubjectControl, int offset) { 1843 IContentAssistProcessor p= getProcessor(contentAssistSubjectControl, offset); 1844 return p != null ? p.getContextInformationValidator() : null; 1845 } 1846 1847 1856 IContextInformationPresenter getContextInformationPresenter(ITextViewer viewer, int offset) { 1857 IContextInformationValidator validator= getContextInformationValidator(viewer, offset); 1858 if (validator instanceof IContextInformationPresenter) 1859 return (IContextInformationPresenter) validator; 1860 return null; 1861 } 1862 1863 1872 IContextInformationPresenter getContextInformationPresenter(IContentAssistSubjectControl contentAssistSubjectControl, int offset) { 1873 IContextInformationValidator validator= getContextInformationValidator(contentAssistSubjectControl, offset); 1874 if (validator instanceof IContextInformationPresenter) 1875 return (IContextInformationPresenter) validator; 1876 return null; 1877 } 1878 1879 1890 char[] getCompletionProposalAutoActivationCharacters(IContentAssistSubjectControl contentAssistSubjectControl, int offset) { 1891 IContentAssistProcessor p= getProcessor(contentAssistSubjectControl, offset); 1892 return p != null ? p.getCompletionProposalAutoActivationCharacters() : null; 1893 } 1894 1895 1905 char[] getCompletionProposalAutoActivationCharacters(ITextViewer viewer, int offset) { 1906 IContentAssistProcessor p= getProcessor(viewer, offset); 1907 return p != null ? p.getCompletionProposalAutoActivationCharacters() : null; 1908 } 1909 1910 1921 char[] getContextInformationAutoActivationCharacters(ITextViewer viewer, int offset) { 1922 IContentAssistProcessor p= getProcessor(viewer, offset); 1923 return p != null ? p.getContextInformationAutoActivationCharacters() : null; 1924 } 1925 1926 1937 char[] getContextInformationAutoActivationCharacters(IContentAssistSubjectControl contentAssistSubjectControl, int offset) { 1938 IContentAssistProcessor p= getProcessor(contentAssistSubjectControl, offset); 1939 return p != null ? p.getContextInformationAutoActivationCharacters() : null; 1940 } 1941 1942 1946 public boolean requestWidgetToken(IWidgetTokenOwner owner) { 1947 return false; 1948 } 1949 1950 1955 public boolean requestWidgetToken(IWidgetTokenOwner owner, int priority) { 1956 if (priority > WIDGET_PRIORITY) { 1957 hide(); 1958 return true; 1959 } 1960 return false; 1961 } 1962 1963 1967 public boolean setFocus(IWidgetTokenOwner owner) { 1968 if (fProposalPopup != null) { 1969 fProposalPopup.setFocus(); 1970 return fProposalPopup.hasFocus(); 1971 } 1972 return false; 1973 } 1974 1975 1980 protected void hide() { 1981 if (fProposalPopup != null) 1982 fProposalPopup.hide(); 1983 1984 if (fContextInfoPopup != null) 1985 fContextInfoPopup.hide(); 1986 } 1987 1988 1990 2010 public void setRestoreCompletionProposalSize(IDialogSettings dialogSettings) { 2011 Assert.isTrue(dialogSettings != null); 2012 fDialogSettings= dialogSettings; 2013 } 2014 2015 2018 protected void storeCompletionProposalPopupSize() { 2019 if (fDialogSettings == null || fProposalPopup == null) 2020 return; 2021 2022 Point size= fProposalPopup.getSize(); 2023 if (size == null) 2024 return; 2025 2026 fDialogSettings.put(STORE_SIZE_X, size.x); 2027 fDialogSettings.put(STORE_SIZE_Y, size.y); 2028 } 2029 2030 2036 protected Point restoreCompletionProposalPopupSize() { 2037 if (fDialogSettings == null) 2038 return null; 2039 2040 Point size= new Point(-1, -1); 2041 2042 try { 2043 size.x= fDialogSettings.getInt(STORE_SIZE_X); 2044 size.y= fDialogSettings.getInt(STORE_SIZE_Y); 2045 } catch (NumberFormatException ex) { 2046 size.x= -1; 2047 size.y= -1; 2048 } 2049 2050 if (size.x == -1 && size.y == -1) 2052 return null; 2053 2054 Rectangle maxBounds= null; 2055 if (fContentAssistSubjectControl != null && Helper.okToUse(fContentAssistSubjectControl.getControl())) 2056 maxBounds= fContentAssistSubjectControl.getControl().getDisplay().getBounds(); 2057 else { 2058 Display display= Display.getCurrent(); 2060 if (display == null) 2061 display= Display.getDefault(); 2062 if (display != null && !display.isDisposed()) 2063 maxBounds= display.getBounds(); 2064 } 2065 2066 if (size.x > -1 && size.y > -1) { 2067 if (maxBounds != null) { 2068 size.x= Math.min(size.x, maxBounds.width); 2069 size.y= Math.min(size.y, maxBounds.height); 2070 } 2071 2072 size.x= Math.max(size.x, 30); 2074 size.y= Math.max(size.y, 30); 2075 } 2076 2077 return size; 2078 } 2079 2080 2087 public void enablePrefixCompletion(boolean enabled) { 2088 fIsPrefixCompletionEnabled= enabled; 2089 } 2090 2091 2097 boolean isPrefixCompletionEnabled() { 2098 return fIsPrefixCompletionEnabled; 2099 } 2100 2101 2107 public boolean hasProposalPopupFocus() { 2108 return fProposalPopup.hasFocus(); 2109 } 2110 2111 2115 public void addCompletionListener(ICompletionListener listener) { 2116 Assert.isLegal(listener != null); 2117 fCompletionListeners.add(listener); 2118 } 2119 2120 2124 public void removeCompletionListener(ICompletionListener listener) { 2125 fCompletionListeners.remove(listener); 2126 } 2127 2128 2133 void fireSessionBeginEvent() { 2134 if (fContentAssistSubjectControlAdapter != null && (fProposalPopup == null || !fProposalPopup.isActive())) { 2135 IContentAssistProcessor processor= getProcessor(fContentAssistSubjectControlAdapter, fContentAssistSubjectControlAdapter.getSelectedRange().x); 2136 ContentAssistEvent event= new ContentAssistEvent(this, processor); 2137 for (Iterator it= new ArrayList (fCompletionListeners).iterator(); it.hasNext();) { 2138 ICompletionListener listener= (ICompletionListener) it.next(); 2139 listener.assistSessionStarted(event); 2140 } 2141 } 2142 } 2143 2144 2149 void fireSessionEndEvent() { 2150 if (fContentAssistSubjectControlAdapter != null) { 2151 IContentAssistProcessor processor= getProcessor(fContentAssistSubjectControlAdapter, fContentAssistSubjectControlAdapter.getSelectedRange().x); 2152 ContentAssistEvent event= new ContentAssistEvent(this, processor); 2153 for (Iterator it= new ArrayList (fCompletionListeners).iterator(); it.hasNext();) { 2154 ICompletionListener listener= (ICompletionListener) it.next(); 2155 listener.assistSessionEnded(event); 2156 } 2157 } 2158 } 2159 2160 2164 public void setRepeatedInvocationMode(boolean cycling) { 2165 fIsRepetitionMode= cycling; 2166 } 2167 2168 2176 boolean isRepeatedInvocationMode() { 2177 return fIsRepetitionMode; 2178 } 2179 2180 2184 public void setShowEmptyList(boolean showEmpty) { 2185 fShowEmptyList= showEmpty; 2186 } 2187 2188 2196 boolean isShowEmptyList() { 2197 return fShowEmptyList; 2198 } 2199 2200 2204 public void setStatusLineVisible(boolean show) { 2205 fIsStatusLineVisible= show; 2206 if (fProposalPopup != null) 2207 fProposalPopup.setStatusLineVisible(show); 2208 } 2209 2210 2218 boolean isStatusLineVisible() { 2219 return fIsStatusLineVisible; 2220 } 2221 2222 2226 public void setStatusMessage(String message) { 2227 Assert.isLegal(message != null); 2228 fMessage= message; 2229 if (fProposalPopup != null) 2230 fProposalPopup.setMessage(message); 2231 } 2232 2233 2239 String getStatusMessage() { 2240 return fMessage; 2241 } 2242 2243 2247 public void setEmptyMessage(String message) { 2248 Assert.isLegal(message != null); 2249 if (fProposalPopup != null) 2250 fProposalPopup.setEmptyMessage(message); 2251 } 2252 2253 2260 void fireSelectionEvent(ICompletionProposal proposal, boolean smartToggle) { 2261 for (Iterator it= new ArrayList (fCompletionListeners).iterator(); it.hasNext();) { 2262 ICompletionListener listener= (ICompletionListener) it.next(); 2263 listener.selectionChanged(proposal, smartToggle); 2264 } 2265 } 2266 2267 2271 public void setRepeatedInvocationTrigger(KeySequence sequence) { 2272 fTriggerSequence= sequence; 2273 } 2274 2275 2281 KeySequence getTriggerSequence() { 2282 return fTriggerSequence; 2283 } 2284} 2285 | Popular Tags |