1 11 package org.eclipse.jface.internal.text.link.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 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 74 public class ContentAssistant2 implements IContentAssistant, IContentAssistantExtension, IWidgetTokenKeeper, IWidgetTokenKeeperExtension { 75 76 82 class Closer implements ControlListener, MouseListener, FocusListener, DisposeListener, IViewportListener { 83 84 85 private Shell fShell; 86 87 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 104 w.addDisposeListener(this); 105 } 106 107 fViewer.addViewportListener(this); 108 } 109 110 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 128 w.removeDisposeListener(this); 129 } 130 131 fViewer.removeViewportListener(this); 132 } 133 134 137 public void controlResized(ControlEvent e) { 138 hide(); 139 } 140 141 144 public void controlMoved(ControlEvent e) { 145 hide(); 146 } 147 148 151 public void mouseDown(MouseEvent e) { 152 hide(); 153 } 154 155 158 public void mouseUp(MouseEvent e) { 159 } 160 161 164 public void mouseDoubleClick(MouseEvent e) { 165 hide(); 166 } 167 168 171 public void focusGained(FocusEvent e) { 172 } 173 174 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 () { 184 public void run() { 185 if (!hasFocus()) 186 hide(); 187 } 188 }); 189 } 190 } 191 } 192 } 193 194 197 public void widgetDisposed(DisposeEvent e) { 198 201 hide(); 202 } 203 204 207 public void viewportChanged(int topIndex) { 208 hide(); 209 } 210 } 211 212 221 class AutoAssistListener implements VerifyKeyListener, Runnable { 222 223 private Thread fThread; 224 private boolean fIsReset= false; 225 private Object fMutex= new Object (); 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 (this, ContentAssistMessages.getString("ContentAssistant.assist_delay_timer_name")); 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 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 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 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 () { 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 338 class LayoutManager implements Listener { 339 340 342 public final static int LAYOUT_PROPOSAL_SELECTOR= 0; 343 344 public final static int LAYOUT_CONTEXT_SELECTOR= 1; 345 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 [] fPopups= new Object [3]; 351 352 protected void add(Object 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 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 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 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 Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR]; 449 shell.setLocation(getBelowLocation(shell, offset)); 450 } else { 451 switch (fProposalPopupOrientation) { 452 case PROPOSAL_REMOVE: { 453 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 Shell shell= fShells[LAYOUT_PROPOSAL_SELECTOR]; 463 shell.setLocation(getBelowLocation(shell, offset)); 464 break; 465 } 466 case PROPOSAL_STACKED: { 467 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 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 fShells[LAYOUT_PROPOSAL_SELECTOR].dispose(); 487 break; 488 489 case PROPOSAL_OVERLAY: 490 break; 492 493 case PROPOSAL_STACKED: { 494 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 Shell shell= fShells[LAYOUT_CONTEXT_INFO_POPUP]; 509 shell.setLocation(getAboveLocation(shell, offset)); 510 break; 511 } 512 case CONTEXT_INFO_BELOW: { 513 Shell parent= fShells[LAYOUT_CONTEXT_INFO_POPUP]; 515 parent.setLocation(getBelowLocation(parent, offset)); 516 if (Helper2.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR])) { 517 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 removeContentAssistListener((IContentAssistListener2) fPopups[LAYOUT_CONTEXT_SELECTOR], CONTEXT_SELECTOR); 598 break; 599 case LAYOUT_CONTEXT_SELECTOR: 600 if (Helper2.okToUse(fShells[LAYOUT_PROPOSAL_SELECTOR])) 601 removeContentAssistListener((IContentAssistListener2) fPopups[LAYOUT_PROPOSAL_SELECTOR], PROPOSAL_SELECTOR); 603 break; 604 case LAYOUT_CONTEXT_INFO_POPUP: 605 break; 606 } 607 } 608 } 609 610 613 class InternalListener implements VerifyKeyListener, IEventConsumer { 614 615 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 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 final static int CONTEXT_SELECTOR= 0; 654 final static int PROPOSAL_SELECTOR= 1; 655 final static int CONTEXT_INFO_POPUP= 2; 656 657 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 fProcessors; 675 private String 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 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 [] fProposalStrings; 698 private ICompletionProposal[] fProposals; 699 private final List fProposalListeners= new ArrayList (); 700 701 708 public ContentAssistant2() { 709 setContextInformationPopupOrientation(CONTEXT_INFO_ABOVE); 710 setInformationControlCreator(getInformationControlCreator()); 711 712 } 723 724 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 742 public void setDocumentPartitioning(String partitioning) { 743 Assert.isNotNull(partitioning); 744 fPartitioning= partitioning; 745 } 746 747 751 public String getDocumentPartitioning() { 752 return fPartitioning; 753 } 754 755 763 public void setContentAssistProcessor(IContentAssistProcessor processor, String contentType) { 764 765 Assert.isNotNull(contentType); 766 767 if (fProcessors == null) 768 fProcessors= new HashMap (); 769 770 if (processor == null) 771 fProcessors.remove(contentType); 772 else 773 fProcessors.put(contentType, processor); 774 } 775 776 779 public IContentAssistProcessor getContentAssistProcessor(String contentType) { 780 if (fProcessors == null) 781 return null; 782 783 return (IContentAssistProcessor) fProcessors.get(contentType); 784 } 785 786 791 public void enableAutoActivation(boolean enabled) { 792 fIsAutoActivated= enabled; 793 manageAutoActivation(fIsAutoActivated); 794 } 795 796 805 public void enableAutoInsert(boolean enabled) { 806 fIsAutoInserting= enabled; 807 } 808 809 816 boolean isAutoInserting() { 817 return fIsAutoInserting; 818 } 819 820 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 862 public void setAutoActivationDelay(int delay) { 863 fAutoActivationDelay= delay; 864 } 865 866 884 public void setProposalPopupOrientation(int orientation) { 885 fProposalPopupOrientation= orientation; 886 } 887 888 904 public void setContextInformationPopupOrientation(int orientation) { 905 fContextInfoPopupOrientation= orientation; 906 } 907 908 913 public void setContextInformationPopupBackground(Color background) { 914 fContextInfoPopupBackground= background; 915 } 916 917 923 Color getContextInformationPopupBackground() { 924 return fContextInfoPopupBackground; 925 } 926 927 933 public void setContextInformationPopupForeground(Color foreground) { 934 fContextInfoPopupForeground= foreground; 935 } 936 937 943 Color getContextInformationPopupForeground() { 944 return fContextInfoPopupForeground; 945 } 946 947 953 public void setProposalSelectorBackground(Color background) { 954 fProposalSelectorBackground= background; 955 } 956 957 963 Color getProposalSelectorBackground() { 964 return fProposalSelectorBackground; 965 } 966 967 973 public void setProposalSelectorForeground(Color foreground) { 974 fProposalSelectorForeground= foreground; 975 } 976 977 983 Color getProposalSelectorForeground() { 984 return fProposalSelectorForeground; 985 } 986 987 993 public void setContextSelectorBackground(Color background) { 994 fContextSelectorBackground= background; 995 } 996 997 1003 Color getContextSelectorBackground() { 1004 return fContextSelectorBackground; 1005 } 1006 1007 1013 public void setContextSelectorForeground(Color foreground) { 1014 fContextSelectorForeground= foreground; 1015 } 1016 1017 1023 Color getContextSelectorForeground() { 1024 return fContextSelectorForeground; 1025 } 1026 1027 1033 public void setInformationControlCreator(IInformationControlCreator creator) { 1034 fInformationControlCreator= creator; 1035 } 1036 1037 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 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 1093 void addToLayout(Object popup, Shell shell, int type, int visibleOffset) { 1094 fLayoutManager.add(popup, shell, type, visibleOffset); 1095 } 1096 1097 1106 void layout(int type, int visibleOffset) { 1107 fLayoutManager.layout(type, visibleOffset); 1108 } 1109 1110 1115 void popupFocusLost(FocusEvent e) { 1116 fCloser.focusLost(e); 1117 } 1118 1119 1125 int getSelectionOffset() { 1126 StyledText text= fViewer.getTextWidget(); 1127 return text.getSelectionRange().x; 1128 } 1129 1130 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 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 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 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 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 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 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 1298 public String showPossibleCompletions() { 1299 return fProposalPopup.showProposals(false); 1300 } 1301 1302 1305 public void hidePossibleCompletions() { 1306 if (fProposalPopup != null) 1307 fProposalPopup.hide(); 1308 } 1309 1310 1313 protected void hide() { 1314 if (fProposalPopup != null) 1315 fProposalPopup.hide(); 1316 if (fContextInfoPopup != null) 1317 fContextInfoPopup.hide(); 1318 } 1319 1320 1324 protected void possibleCompletionsClosed() { 1325 } 1326 1327 1330 public String showContextInformation() { 1331 return fContextInfoPopup.showContextProposals(false); 1332 } 1333 1334 1335 1339 protected void contextInformationClosed() { 1340 } 1341 1342 1349 void showContextInformation(IContextInformation contextInformation, int position) { 1350 fContextInfoPopup.showContextInformation(contextInformation, position); 1351 } 1352 1353 1358 String getErrorMessage() { 1359 return fLastErrorMessage; 1360 } 1361 1362 1370 private IContentAssistProcessor getProcessor(ITextViewer viewer, int offset) { 1371 try { 1372 String type= TextUtilities.getContentType(viewer.getDocument(), getDocumentPartitioning(), offset, true); 1373 return getContentAssistProcessor(type); 1374 } catch (BadLocationException x) { 1375 } 1376 return null; 1377 } 1378 1379 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 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 1439 IContextInformationValidator getContextInformationValidator(ITextViewer textViewer, int offset) { 1440 IContentAssistProcessor p= getProcessor(textViewer, offset); 1441 return p != null ? p.getContextInformationValidator() : null; 1442 } 1443 1444 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 1472 private char[] getCompletionProposalAutoActivationCharacters(ITextViewer textViewer, int offset) { 1473 IContentAssistProcessor p= getProcessor(textViewer, offset); 1474 return p != null ? p.getCompletionProposalAutoActivationCharacters() : null; 1475 } 1476 1477 1488 private char[] getContextInformationAutoActivationCharacters(ITextViewer textViewer, int offset) { 1489 IContentAssistProcessor p= getProcessor(textViewer, offset); 1490 return p != null ? p.getContextInformationAutoActivationCharacters() : null; 1491 } 1492 1493 1497 public boolean requestWidgetToken(IWidgetTokenOwner owner) { 1498 hidePossibleCompletions(); 1499 return true; 1500 } 1501 1502 1505 public void setCompletionPosition(int completionPosition) { 1506 fCompletionPosition= completionPosition; 1507 } 1508 1509 1512 public int getCompletionPosition() { 1513 return fCompletionPosition; 1514 } 1515 1516 1519 public void setCompletions(String [] proposals) { 1520 fProposalStrings= proposals; 1521 } 1522 1523 1526 public void setCompletions(ICompletionProposal[] proposals) { 1527 fProposals= proposals; 1528 } 1529 1530 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 1546 public boolean setFocus(IWidgetTokenOwner owner) { 1547 if (fProposalPopup != null) { 1548 fProposalPopup.setFocus(); 1549 return fProposalPopup.hasFocus(); 1550 } 1551 return false; 1552 } 1553 1554 1559 public boolean hasFocus() { 1560 return (fProposalPopup != null && fProposalPopup.hasFocus()) 1561 || (fContextInfoPopup != null && fContextInfoPopup.hasFocus()); 1562 } 1563 1564 1567 public String completePrefix() { 1568 return null; 1569 } 1570 1571 1574 public void fireProposalChosen(ICompletionProposal proposal) { 1575 List list= new ArrayList (fProposalListeners); 1576 for (Iterator it= list.iterator(); it.hasNext();) { 1577 IProposalListener listener= (IProposalListener) it.next(); 1578 listener.proposalChosen(proposal); 1579 } 1580 1581 } 1582 1583 1586 public void removeProposalListener(IProposalListener listener) { 1587 fProposalListeners.remove(listener); 1588 } 1589 1590 1593 public void addProposalListener(IProposalListener listener) { 1594 fProposalListeners.add(listener); 1595 } 1596} 1597 1598 | Popular Tags |