comparison dwtx/jface/text/contentassist/ContentAssistant.d @ 158:25f1f92fa3df

...
author Frank Benoit <benoit@tionex.de>
date Tue, 26 Aug 2008 02:46:34 +0200
parents f70d9508c95c
children 1a5b8f8129df
comparison
equal deleted inserted replaced
157:7f75eaa8103a 158:25f1f92fa3df
44 import dwtx.jface.text.contentassist.IContextInformation; // packageimport 44 import dwtx.jface.text.contentassist.IContextInformation; // packageimport
45 import dwtx.jface.text.contentassist.IContentAssistantExtension3; // packageimport 45 import dwtx.jface.text.contentassist.IContentAssistantExtension3; // packageimport
46 import dwtx.jface.text.contentassist.IContentAssistantExtension; // packageimport 46 import dwtx.jface.text.contentassist.IContentAssistantExtension; // packageimport
47 import dwtx.jface.text.contentassist.JFaceTextMessages; // packageimport 47 import dwtx.jface.text.contentassist.JFaceTextMessages; // packageimport
48 48
49
50 import dwt.dwthelper.utils; 49 import dwt.dwthelper.utils;
51
52 import dwtx.dwtxhelper.Collection; 50 import dwtx.dwtxhelper.Collection;
53 51 import tango.core.Thread;
54
55
56 52
57 import dwt.DWT; 53 import dwt.DWT;
58 import dwt.DWTError; 54 import dwt.DWTError;
59 import dwt.custom.VerifyKeyListener; 55 import dwt.custom.VerifyKeyListener;
60 import dwt.events.ControlEvent; 56 import dwt.events.ControlEvent;
107 /** 103 /**
108 * The standard implementation of the <code>IContentAssistant</code> interface. Usually, clients 104 * The standard implementation of the <code>IContentAssistant</code> interface. Usually, clients
109 * instantiate this class and configure it before using it. 105 * instantiate this class and configure it before using it.
110 */ 106 */
111 public class ContentAssistant : IContentAssistant, IContentAssistantExtension, IContentAssistantExtension2, IContentAssistantExtension3, IContentAssistantExtension4, IWidgetTokenKeeper, IWidgetTokenKeeperExtension { 107 public class ContentAssistant : IContentAssistant, IContentAssistantExtension, IContentAssistantExtension2, IContentAssistantExtension3, IContentAssistantExtension4, IWidgetTokenKeeper, IWidgetTokenKeeperExtension {
112 108
113 109
114 110
115 /** 111 /**
116 * Content assist command identifier for 'select next proposal'. 112 * Content assist command identifier for 'select next proposal'.
117 * 113 *
118 * @since 3.4 114 * @since 3.4
119 */ 115 */
120 public static const String SELECT_NEXT_PROPOSAL_COMMAND_ID= "dwtx.ui.edit.text.contentAssist.selectNextProposal"; //$NON-NLS-1$ 116 public static const String SELECT_NEXT_PROPOSAL_COMMAND_ID= "dwtx.ui.edit.text.contentAssist.selectNextProposal"; //$NON-NLS-1$
121 /** 117 /**
122 * Content assist command identifier for 'select previous proposal'. 118 * Content assist command identifier for 'select previous proposal'.
123 * 119 *
124 * @since 3.4 120 * @since 3.4
125 */ 121 */
126 public static const String SELECT_PREVIOUS_PROPOSAL_COMMAND_ID= "dwtx.ui.edit.text.contentAssist.selectPreviousProposal"; //$NON-NLS-1$ 122 public static const String SELECT_PREVIOUS_PROPOSAL_COMMAND_ID= "dwtx.ui.edit.text.contentAssist.selectPreviousProposal"; //$NON-NLS-1$
127 123
128 124
129 /** 125 /**
130 * A generic closer class used to monitor various interface events in order to determine whether 126 * A generic closer class used to monitor various interface events in order to determine whether
131 * content-assist should be terminated and all associated windows closed. 127 * content-assist should be terminated and all associated windows closed.
132 */ 128 */
273 * An implementation of <code>IContentAssistListener</code>, this class is used to monitor 269 * An implementation of <code>IContentAssistListener</code>, this class is used to monitor
274 * key events in support of automatic activation of the content assistant. If enabled, the 270 * key events in support of automatic activation of the content assistant. If enabled, the
275 * implementation utilizes a thread to watch for input characters matching the activation 271 * implementation utilizes a thread to watch for input characters matching the activation
276 * characters specified by the content assist processor, and if detected, will wait the 272 * characters specified by the content assist processor, and if detected, will wait the
277 * indicated delay interval before activating the content assistant. 273 * indicated delay interval before activating the content assistant.
278 * 274 *
279 * @since 3.4 protected, was added in 2.1 as private class 275 * @since 3.4 protected, was added in 2.1 as private class
280 */ 276 */
281 protected class AutoAssistListener : KeyAdapter , KeyListener, Runnable, VerifyKeyListener { 277 protected class AutoAssistListener : KeyAdapter , KeyListener, Runnable, VerifyKeyListener {
282 278
283 private Thread fThread; 279 private Thread fThread;
291 protected this() { 287 protected this() {
292 } 288 }
293 289
294 protected void start(int showStyle) { 290 protected void start(int showStyle) {
295 fShowStyle= showStyle; 291 fShowStyle= showStyle;
296 fThread= new Thread(this, JFaceTextMessages.getString("ContentAssistant.assist_delay_timer_name")); //$NON-NLS-1$ 292 fThread= new Thread(&run);
293 fThread.name = JFaceTextMessages.getString("ContentAssistant.assist_delay_timer_name"); //$NON-NLS-1$
297 fThread.start(); 294 fThread.start();
298 } 295 }
299 296
300 public void run() { 297 public void run() {
301 try { 298 try {
342 339
343 public void keyPressed(KeyEvent e) { 340 public void keyPressed(KeyEvent e) {
344 // Only act on typed characters and ignore modifier-only events 341 // Only act on typed characters and ignore modifier-only events
345 if (e.character is 0 && (e.keyCode & DWT.KEYCODE_BIT) is 0) 342 if (e.character is 0 && (e.keyCode & DWT.KEYCODE_BIT) is 0)
346 return; 343 return;
347 344
348 if (e.character !is 0 && (e.stateMask is DWT.ALT)) 345 if (e.character !is 0 && (e.stateMask is DWT.ALT))
349 return; 346 return;
350 347
351 // Only act on characters that are trigger candidates. This 348 // Only act on characters that are trigger candidates. This
352 // avoids computing the model selection on every keystroke 349 // avoids computing the model selection on every keystroke
353 if (computeAllAutoActivationTriggers().indexOf(e.character) < 0) { 350 if (computeAllAutoActivationTriggers().indexOf(e.character) < 0) {
354 stop(); 351 stop();
355 return; 352 return;
384 */ 381 */
385 public void verifyKey(VerifyEvent event) { 382 public void verifyKey(VerifyEvent event) {
386 keyPressed(event); 383 keyPressed(event);
387 } 384 }
388 385
389 protected void showAssist(final int showStyle) { 386 protected void showAssist(int showStyle) {
390 final Control control= fContentAssistSubjectControlAdapter.getControl(); 387 final Control control= fContentAssistSubjectControlAdapter.getControl();
391 if (control is null) 388 if (control is null)
392 return; 389 return;
393 390
394 final Display d= control.getDisplay(); 391 final Display d= control.getDisplay();
395 if (d is null) 392 if (d is null)
396 return; 393 return;
397 394
398 try { 395 try {
399 d.syncExec(new class() Runnable { 396 d.syncExec(new class() Runnable {
400 public void run() { 397 public void run() {
401 if (isProposalPopupActive()) 398 if (isProposalPopupActive())
402 return; 399 return;
403 400
404 if (control.isDisposed() || !control.isFocusControl()) 401 if (control.isDisposed() || !control.isFocusControl())
405 return; 402 return;
406 403
407 if (showStyle is SHOW_PROPOSALS) { 404 if (showStyle is SHOW_PROPOSALS) {
408 if (!prepareToShowCompletions(true)) 405 if (!prepareToShowCompletions(true))
409 return; 406 return;
410 fProposalPopup.showProposals(true); 407 fProposalPopup.showProposals(true);
411 fLastAutoActivation= System.currentTimeMillis(); 408 fLastAutoActivation= System.currentTimeMillis();
508 return -1; 505 return -1;
509 } 506 }
510 507
511 /** 508 /**
512 * Layouts the popup defined by <code>type</code> at the given widget offset. 509 * Layouts the popup defined by <code>type</code> at the given widget offset.
513 * 510 *
514 * @param type the kind of popup to layout 511 * @param type the kind of popup to layout
515 * @param offset the widget offset 512 * @param offset the widget offset
516 */ 513 */
517 protected void layout(int type, int offset) { 514 protected void layout(int type, int offset) {
518 switch (type) { 515 switch (type) {
621 } 618 }
622 619
623 /** 620 /**
624 * Moves <code>point</code> such that <code>rectangle</code> does not bleed outside of 621 * Moves <code>point</code> such that <code>rectangle</code> does not bleed outside of
625 * <code>bounds</code>. All coordinates must have the same reference. 622 * <code>bounds</code>. All coordinates must have the same reference.
626 * 623 *
627 * @param point the point to move if needed 624 * @param point the point to move if needed
628 * @param shellSize the size of the shell that may be moved 625 * @param shellSize the size of the shell that may be moved
629 * @param bounds the bounds 626 * @param bounds the bounds
630 * @since 3.3 627 * @since 3.3
631 */ 628 */
633 if (point.x + shellSize.x > bounds.x + bounds.width) 630 if (point.x + shellSize.x > bounds.x + bounds.width)
634 point.x= bounds.x + bounds.width - shellSize.x; 631 point.x= bounds.x + bounds.width - shellSize.x;
635 632
636 if (point.x < bounds.x) 633 if (point.x < bounds.x)
637 point.x= bounds.x; 634 point.x= bounds.x;
638 635
639 if (point.y + shellSize.y > bounds.y + bounds.height) 636 if (point.y + shellSize.y > bounds.y + bounds.height)
640 point.y= bounds.y + bounds.height - shellSize.y; 637 point.y= bounds.y + bounds.height - shellSize.y;
641 638
642 if (point.y < bounds.y) 639 if (point.y < bounds.y)
643 point.y= bounds.y; 640 point.y= bounds.y;
644 } 641 }
645 642
646 protected Rectangle constrainHorizontally(Rectangle rect, Rectangle bounds) { 643 protected Rectangle constrainHorizontally(Rectangle rect, Rectangle bounds) {
647 // clip width 644 // clip width
648 if (rect.width > bounds.width) 645 if (rect.width > bounds.width)
649 rect.width= bounds.width; 646 rect.width= bounds.width;
650 647
651 if (rect.x + rect.width > bounds.x + bounds.width) 648 if (rect.x + rect.width > bounds.x + bounds.width)
652 rect.x= bounds.x + bounds.width - rect.width; 649 rect.x= bounds.x + bounds.width - rect.width;
653 if (rect.x < bounds.x) 650 if (rect.x < bounds.x)
654 rect.x= bounds.x; 651 rect.x= bounds.x;
655 652
656 return rect; 653 return rect;
657 } 654 }
658 655
659 /** 656 /**
660 * Returns the display bounds for <code>shell</code> such that it appears right above 657 * Returns the display bounds for <code>shell</code> such that it appears right above
661 * <code>offset</code>, or below it if above is not suitable. The returned bounds lie 658 * <code>offset</code>, or below it if above is not suitable. The returned bounds lie
662 * within the monitor at the caret location and never overlap with the caret line. 659 * within the monitor at the caret location and never overlap with the caret line.
663 * 660 *
664 * @param shell the shell to compute the placement for 661 * @param shell the shell to compute the placement for
665 * @param preferred the preferred size for <code>shell</code> 662 * @param preferred the preferred size for <code>shell</code>
666 * @param offset the caret offset in the subject control 663 * @param offset the caret offset in the subject control
667 * @return the point right above <code>offset</code> in display coordinates 664 * @return the point right above <code>offset</code> in display coordinates
668 * @since 3.3 665 * @since 3.3
672 Display display= subjectControl.getDisplay(); 669 Display display= subjectControl.getDisplay();
673 Rectangle caret= getCaretRectangle(offset); 670 Rectangle caret= getCaretRectangle(offset);
674 Monitor monitor= getClosestMonitor(display, caret); 671 Monitor monitor= getClosestMonitor(display, caret);
675 Rectangle bounds= monitor.getClientArea(); 672 Rectangle bounds= monitor.getClientArea();
676 Geometry.moveInside(caret, bounds); 673 Geometry.moveInside(caret, bounds);
677 674
678 int spaceAbove= caret.y - bounds.y; 675 int spaceAbove= caret.y - bounds.y;
679 int caretLowerY= caret.y + caret.height; 676 int caretLowerY= caret.y + caret.height;
680 int spaceBelow= bounds.y + bounds.height - caretLowerY; 677 int spaceBelow= bounds.y + bounds.height - caretLowerY;
681 Rectangle rect; 678 Rectangle rect;
682 if (spaceAbove >= preferred.y) 679 if (spaceAbove >= preferred.y)
686 // we can't fit in the preferred size - squeeze into larger area 683 // we can't fit in the preferred size - squeeze into larger area
687 else if (spaceBelow <= spaceAbove) 684 else if (spaceBelow <= spaceAbove)
688 rect= new Rectangle(caret.x, bounds.y, preferred.x, spaceAbove); 685 rect= new Rectangle(caret.x, bounds.y, preferred.x, spaceAbove);
689 else 686 else
690 rect= new Rectangle(caret.x, caretLowerY, preferred.x, spaceBelow); 687 rect= new Rectangle(caret.x, caretLowerY, preferred.x, spaceBelow);
691 688
692 return constrainHorizontally(rect, bounds); 689 return constrainHorizontally(rect, bounds);
693 } 690 }
694 691
695 /** 692 /**
696 * Returns the display bounds for <code>shell</code> such that it appears right below 693 * Returns the display bounds for <code>shell</code> such that it appears right below
697 * <code>offset</code>, or above it if below is not suitable. The returned bounds lie 694 * <code>offset</code>, or above it if below is not suitable. The returned bounds lie
698 * within the monitor at the caret location and never overlap with the caret line. 695 * within the monitor at the caret location and never overlap with the caret line.
699 * 696 *
700 * @param shell the shell to compute the placement for 697 * @param shell the shell to compute the placement for
701 * @param preferred the preferred size for <code>shell</code> 698 * @param preferred the preferred size for <code>shell</code>
702 * @param offset the caret offset in the subject control 699 * @param offset the caret offset in the subject control
703 * @param popup a popup to inform if the location was switched to above, <code>null</code> to do nothing 700 * @param popup a popup to inform if the location was switched to above, <code>null</code> to do nothing
704 * @return the point right below <code>offset</code> in display coordinates 701 * @return the point right below <code>offset</code> in display coordinates
730 rect= new Rectangle(caret.x, caret.y + caret.height, preferred.x, spaceBelow); 727 rect= new Rectangle(caret.x, caret.y + caret.height, preferred.x, spaceBelow);
731 } else { 728 } else {
732 rect= new Rectangle(caret.x, bounds.y, preferred.x, spaceAbove); 729 rect= new Rectangle(caret.x, bounds.y, preferred.x, spaceAbove);
733 switched= true; 730 switched= true;
734 } 731 }
735 732
736 if (popup !is null) 733 if (popup !is null)
737 popup.switchedPositionToAbove(switched); 734 popup.switchedPositionToAbove(switched);
738 735
739 return constrainHorizontally(rect, bounds); 736 return constrainHorizontally(rect, bounds);
740 } 737 }
741 738
742 private Rectangle getCaretRectangle(int offset) { 739 private Rectangle getCaretRectangle(int offset) {
743 Point location= fContentAssistSubjectControlAdapter.getLocationAtOffset(offset); 740 Point location= fContentAssistSubjectControlAdapter.getLocationAtOffset(offset);
746 constrainLocation(location, new Point(0, 0), new Rectangle(0, 0, controlSize.x, controlSize.y)); 743 constrainLocation(location, new Point(0, 0), new Rectangle(0, 0, controlSize.x, controlSize.y));
747 location= subjectControl.toDisplay(location); 744 location= subjectControl.toDisplay(location);
748 Rectangle subjectRectangle= new Rectangle(location.x, location.y, 1, fContentAssistSubjectControlAdapter.getLineHeight()); 745 Rectangle subjectRectangle= new Rectangle(location.x, location.y, 1, fContentAssistSubjectControlAdapter.getLineHeight());
749 return subjectRectangle; 746 return subjectRectangle;
750 } 747 }
751 748
752 protected Point getStackedLocation(Shell shell, Shell parent) { 749 protected Point getStackedLocation(Shell shell, Shell parent) {
753 Point p= parent.getLocation(); 750 Point p= parent.getLocation();
754 Point size= parent.getSize(); 751 Point size= parent.getSize();
755 p.x += size.x / 4; 752 p.x += size.x / 4;
756 p.y += size.y; 753 p.y += size.y;
780 break; 777 break;
781 case LAYOUT_CONTEXT_INFO_POPUP: 778 case LAYOUT_CONTEXT_INFO_POPUP:
782 break; 779 break;
783 } 780 }
784 } 781 }
785 782
786 /** 783 /**
787 * Copied from dwtx.jface.window.Window. 784 * Copied from dwtx.jface.window.Window.
788 * Returns the monitor whose client area contains the given point. If no 785 * Returns the monitor whose client area contains the given point. If no
789 * monitor contains the point, returns the monitor that is closest to the 786 * monitor contains the point, returns the monitor that is closest to the
790 * point. If this is ever made public, it should be moved into a separate 787 * point. If this is ever made public, it should be moved into a separate
791 * utility class. 788 * utility class.
792 * 789 *
793 * @param toSearch 790 * @param toSearch
794 * point to find (display coordinates) 791 * point to find (display coordinates)
795 * @param rectangle 792 * @param rectangle
796 * rectangle to find (display coordinates) 793 * rectangle to find (display coordinates)
797 * @return the monitor closest to the given point 794 * @return the monitor closest to the given point
835 * 832 *
836 * @param e the verify event 833 * @param e the verify event
837 * @see VerifyKeyListener#verifyKey(dwt.events.VerifyEvent) 834 * @see VerifyKeyListener#verifyKey(dwt.events.VerifyEvent)
838 */ 835 */
839 public void verifyKey(VerifyEvent e) { 836 public void verifyKey(VerifyEvent e) {
840 IContentAssistListener[] listeners= (IContentAssistListener[]) fListeners.clone(); 837 IContentAssistListener[] listeners= arraycast!(IContentAssistListener)( fListeners.clone() );
841 for (int i= 0; i < listeners.length; i++) { 838 for (int i= 0; i < listeners.length; i++) {
842 if (listeners[i] !is null) { 839 if (listeners[i] !is null) {
843 if (!listeners[i].verifyKey(e) || !e.doit) 840 if (!listeners[i].verifyKey(e) || !e.doit)
844 break; 841 break;
845 } 842 }
853 */ 850 */
854 public void processEvent(VerifyEvent event) { 851 public void processEvent(VerifyEvent event) {
855 852
856 installKeyListener(); 853 installKeyListener();
857 854
858 IContentAssistListener[] listeners= (IContentAssistListener[]) fListeners.clone(); 855 IContentAssistListener[] listeners= arraycast!(IContentAssistListener)( fListeners.clone() );
859 for (int i= 0; i < listeners.length; i++) { 856 for (int i= 0; i < listeners.length; i++) {
860 if (listeners[i] !is null) { 857 if (listeners[i] !is null) {
861 listeners[i].processEvent(event); 858 listeners[i].processEvent(event);
862 if (!event.doit) 859 if (!event.doit)
863 return; 860 return;
994 * @since 3.2 991 * @since 3.2
995 */ 992 */
996 private bool fIsStatusLineVisible; 993 private bool fIsStatusLineVisible;
997 /** 994 /**
998 * The last system time when auto activation performed. 995 * The last system time when auto activation performed.
999 * 996 *
1000 * @since 3.2 997 * @since 3.2
1001 */ 998 */
1002 private long fLastAutoActivation= Long.MIN_VALUE; 999 private long fLastAutoActivation= Long.MIN_VALUE;
1003 /** 1000 /**
1004 * The iteration key sequence to listen for, or <code>null</code>. 1001 * The iteration key sequence to listen for, or <code>null</code>.
1005 * 1002 *
1006 * @since 3.2 1003 * @since 3.2
1007 */ 1004 */
1008 private KeySequence fRepeatedInvocationKeySequence; 1005 private KeySequence fRepeatedInvocationKeySequence;
1009 1006
1010 /** 1007 /**
1011 * Maps handler to command identifiers. 1008 * Maps handler to command identifiers.
1012 * 1009 *
1013 * @since 3.4 1010 * @since 3.4
1014 */ 1011 */
1015 private Map fHandlers; 1012 private Map fHandlers;
1016 1013
1017 /** 1014 /**
1018 * Tells whether colored labels support is enabled. 1015 * Tells whether colored labels support is enabled.
1019 * 1016 *
1020 * @since 3.4 1017 * @since 3.4
1021 */ 1018 */
1022 private bool fIsColoredLabelsSupportEnabled= false; 1019 private bool fIsColoredLabelsSupportEnabled= false;
1023 1020
1024 1021
1169 } 1166 }
1170 } 1167 }
1171 1168
1172 /** 1169 /**
1173 * This method allows subclasses to provide their own {@link AutoAssistListener}. 1170 * This method allows subclasses to provide their own {@link AutoAssistListener}.
1174 * 1171 *
1175 * @return a new auto assist listener 1172 * @return a new auto assist listener
1176 * @since 3.4 1173 * @since 3.4
1177 */ 1174 */
1178 protected AutoAssistListener createAutoAssistListener() { 1175 protected AutoAssistListener createAutoAssistListener() {
1179 return new AutoAssistListener(); 1176 return new AutoAssistListener();
1190 } 1187 }
1191 1188
1192 /** 1189 /**
1193 * Gets the delay after which the content assistant is automatically invoked if the cursor is 1190 * Gets the delay after which the content assistant is automatically invoked if the cursor is
1194 * behind an auto activation character. 1191 * behind an auto activation character.
1195 * 1192 *
1196 * @return the auto activation delay 1193 * @return the auto activation delay
1197 * @since 3.4 1194 * @since 3.4
1198 */ 1195 */
1199 public int getAutoActivationDelay() { 1196 public int getAutoActivationDelay() {
1200 return fAutoActivationDelay; 1197 return fAutoActivationDelay;
1270 fContextInfoPopupForeground= foreground; 1267 fContextInfoPopupForeground= foreground;
1271 } 1268 }
1272 1269
1273 /** 1270 /**
1274 * Returns the foreground of the context information popup. 1271 * Returns the foreground of the context information popup.
1275 * 1272 *
1276 * 1273 *
1277 * @return the foreground of the context information popup 1274 * @return the foreground of the context information popup
1278 * @since 2.0 1275 * @since 2.0
1279 */ 1276 */
1280 Color getContextInformationPopupForeground() { 1277 Color getContextInformationPopupForeground() {
1437 * @see IContentAssist#uninstall 1434 * @see IContentAssist#uninstall
1438 */ 1435 */
1439 public void uninstall() { 1436 public void uninstall() {
1440 hide(); 1437 hide();
1441 manageAutoActivation(false); 1438 manageAutoActivation(false);
1442 1439
1443 if (fHandlers !is null) { 1440 if (fHandlers !is null) {
1444 fHandlers.clear(); 1441 fHandlers.clear();
1445 fHandlers= null; 1442 fHandlers= null;
1446 } 1443 }
1447 1444
1486 * @since 2.0 1483 * @since 2.0
1487 */ 1484 */
1488 void layout(int type, int visibleOffset) { 1485 void layout(int type, int visibleOffset) {
1489 fLayoutManager.layout(type, visibleOffset); 1486 fLayoutManager.layout(type, visibleOffset);
1490 } 1487 }
1491 1488
1492 /** 1489 /**
1493 * Returns the layout manager. 1490 * Returns the layout manager.
1494 * 1491 *
1495 * @return the layout manager 1492 * @return the layout manager
1496 * @since 3.3 1493 * @since 3.3
1497 */ 1494 */
1498 LayoutManager getLayoutManager() { 1495 LayoutManager getLayoutManager() {
1499 return fLayoutManager; 1496 return fLayoutManager;
1708 } 1705 }
1709 1706
1710 /** 1707 /**
1711 * Prepares to show content assist proposals. It returns false if auto activation has kicked in 1708 * Prepares to show content assist proposals. It returns false if auto activation has kicked in
1712 * recently. 1709 * recently.
1713 * 1710 *
1714 * @param isAutoActivated whether completion was triggered by auto activation 1711 * @param isAutoActivated whether completion was triggered by auto activation
1715 * @return <code>true</code> if the caller should continue and show the proposals, 1712 * @return <code>true</code> if the caller should continue and show the proposals,
1716 * <code>false</code> otherwise. 1713 * <code>false</code> otherwise.
1717 * @since 3.2 1714 * @since 3.2
1718 */ 1715 */
1719 private bool prepareToShowCompletions(bool isAutoActivated) { 1716 private bool prepareToShowCompletions(bool isAutoActivated) {
1720 long current= System.currentTimeMillis(); 1717 long current= System.currentTimeMillis();
1721 int gracePeriod= Math.max(fAutoActivationDelay, 200); 1718 int gracePeriod= Math.max(fAutoActivationDelay, 200);
1722 if (current < fLastAutoActivation + gracePeriod) 1719 if (current < fLastAutoActivation + gracePeriod)
1723 return false; 1720 return false;
1724 1721
1725 promoteKeyListener(); 1722 promoteKeyListener();
1726 fireSessionBeginEvent(isAutoActivated); 1723 fireSessionBeginEvent(isAutoActivated);
1727 return true; 1724 return true;
1728 } 1725 }
1729 1726
2195 * disable 2192 * disable
2196 */ 2193 */
2197 public void enablePrefixCompletion(bool enabled) { 2194 public void enablePrefixCompletion(bool enabled) {
2198 fIsPrefixCompletionEnabled= enabled; 2195 fIsPrefixCompletionEnabled= enabled;
2199 } 2196 }
2200 2197
2201 /** 2198 /**
2202 * Returns the prefix completion state. 2199 * Returns the prefix completion state.
2203 * 2200 *
2204 * @return <code>true</code> if prefix completion is enabled, <code>false</code> otherwise 2201 * @return <code>true</code> if prefix completion is enabled, <code>false</code> otherwise
2205 * @since 3.2 2202 * @since 3.2
2206 */ 2203 */
2207 bool isPrefixCompletionEnabled() { 2204 bool isPrefixCompletionEnabled() {
2208 return fIsPrefixCompletionEnabled; 2205 return fIsPrefixCompletionEnabled;
2235 fCompletionListeners.remove(listener); 2232 fCompletionListeners.remove(listener);
2236 } 2233 }
2237 2234
2238 /** 2235 /**
2239 * Fires a session begin event to all registered {@link ICompletionListener}s. 2236 * Fires a session begin event to all registered {@link ICompletionListener}s.
2240 * 2237 *
2241 * @param isAutoActivated <code>true</code> if this session was triggered by auto activation 2238 * @param isAutoActivated <code>true</code> if this session was triggered by auto activation
2242 * @since 3.2 2239 * @since 3.2
2243 */ 2240 */
2244 void fireSessionBeginEvent(bool isAutoActivated) { 2241 void fireSessionBeginEvent(bool isAutoActivated) {
2245 if (fContentAssistSubjectControlAdapter !is null && !isProposalPopupActive()) { 2242 if (fContentAssistSubjectControlAdapter !is null && !isProposalPopupActive()) {
2250 ICompletionListener listener= cast(ICompletionListener)listeners[i]; 2247 ICompletionListener listener= cast(ICompletionListener)listeners[i];
2251 listener.assistSessionStarted(event); 2248 listener.assistSessionStarted(event);
2252 } 2249 }
2253 } 2250 }
2254 } 2251 }
2255 2252
2256 /** 2253 /**
2257 * Fires a session restart event to all registered {@link ICompletionListener}s. 2254 * Fires a session restart event to all registered {@link ICompletionListener}s.
2258 * 2255 *
2259 * @since 3.4 2256 * @since 3.4
2260 */ 2257 */
2404 fRepeatedInvocationKeySequence= sequence; 2401 fRepeatedInvocationKeySequence= sequence;
2405 } 2402 }
2406 2403
2407 /** 2404 /**
2408 * Returns the repeated invocation key sequence. 2405 * Returns the repeated invocation key sequence.
2409 * 2406 *
2410 * @return the repeated invocation key sequence or <code>null</code>, if none 2407 * @return the repeated invocation key sequence or <code>null</code>, if none
2411 * @since 3.2 2408 * @since 3.2
2412 */ 2409 */
2413 KeySequence getRepeatedInvocationKeySequence() { 2410 KeySequence getRepeatedInvocationKeySequence() {
2414 return fRepeatedInvocationKeySequence; 2411 return fRepeatedInvocationKeySequence;
2415 } 2412 }
2416 2413
2417 /** 2414 /**
2418 * Returns whether proposal popup is active. 2415 * Returns whether proposal popup is active.
2419 * 2416 *
2420 * @return <code>true</code> if the proposal popup is active, <code>false</code> otherwise 2417 * @return <code>true</code> if the proposal popup is active, <code>false</code> otherwise
2421 * @since 3.4 2418 * @since 3.4
2422 */ 2419 */
2423 protected bool isProposalPopupActive(){ 2420 protected bool isProposalPopupActive(){
2424 return fProposalPopup !is null && fProposalPopup.isActive(); 2421 return fProposalPopup !is null && fProposalPopup.isActive();
2425 } 2422 }
2426 2423
2427 /** 2424 /**
2428 * Returns whether the context information popup is active. 2425 * Returns whether the context information popup is active.
2429 * 2426 *
2430 * @return <code>true</code> if the context information popup is active, <code>false</code> otherwise 2427 * @return <code>true</code> if the context information popup is active, <code>false</code> otherwise
2431 * @since 3.4 2428 * @since 3.4
2432 */ 2429 */
2433 protected bool isContextInfoPopupActive(){ 2430 protected bool isContextInfoPopupActive(){
2434 return fContextInfoPopup !is null && fContextInfoPopup.isActive(); 2431 return fContextInfoPopup !is null && fContextInfoPopup.isActive();
2435 } 2432 }
2436 2433
2437 /** 2434 /**
2438 * {@inheritDoc} 2435 * {@inheritDoc}
2439 * 2436 *
2440 * @since 3.4 2437 * @since 3.4
2441 */ 2438 */
2442 public final IHandler getHandler(String commandId) { 2439 public final IHandler getHandler(String commandId) {
2443 if (fHandlers is null) 2440 if (fHandlers is null)
2444 throw new IllegalStateException(); 2441 throw new IllegalStateException();
2445 2442
2446 IHandler handler= cast(IHandler)fHandlers.get(commandId); 2443 IHandler handler= cast(IHandler)fHandlers.get(commandId);
2447 if (handler !is null) 2444 if (handler !is null)
2448 return handler; 2445 return handler;
2449 2446
2450 Assert.isLegal(false); 2447 Assert.isLegal(false);
2451 return null; 2448 return null;
2452 } 2449 }
2453 2450
2454 /** 2451 /**
2455 * Registers the given handler under the given command identifier. 2452 * Registers the given handler under the given command identifier.
2456 * 2453 *
2457 * @param commandId the command identifier 2454 * @param commandId the command identifier
2458 * @param handler the handler 2455 * @param handler the handler
2459 * @since 3.4 2456 * @since 3.4
2460 */ 2457 */
2461 protected final void registerHandler(String commandId, IHandler handler) { 2458 protected final void registerHandler(String commandId, IHandler handler) {
2464 fHandlers.put(commandId, handler); 2461 fHandlers.put(commandId, handler);
2465 } 2462 }
2466 2463
2467 /** 2464 /**
2468 * Tells whether the support for colored labels is enabled. 2465 * Tells whether the support for colored labels is enabled.
2469 * 2466 *
2470 * @return <code>true</code> if the support for colored labels is enabled, <code>false</code> otherwise 2467 * @return <code>true</code> if the support for colored labels is enabled, <code>false</code> otherwise
2471 * @since 3.4 2468 * @since 3.4
2472 */ 2469 */
2473 bool isColoredLabelsSupportEnabled() { 2470 bool isColoredLabelsSupportEnabled() {
2474 return fIsColoredLabelsSupportEnabled; 2471 return fIsColoredLabelsSupportEnabled;
2476 2473
2477 /** 2474 /**
2478 * Enables the support for colored labels in the proposal popup. 2475 * Enables the support for colored labels in the proposal popup.
2479 * <p>Completion proposals can implement {@link ICompletionProposalExtension6} 2476 * <p>Completion proposals can implement {@link ICompletionProposalExtension6}
2480 * to provide colored proposal labels.</p> 2477 * to provide colored proposal labels.</p>
2481 * 2478 *
2482 * @param isEnabled if <code>true</code> the support for colored labels is enabled in the proposal popup 2479 * @param isEnabled if <code>true</code> the support for colored labels is enabled in the proposal popup
2483 * @since 3.4 2480 * @since 3.4
2484 */ 2481 */
2485 public void enableColoredLabels(bool isEnabled) { 2482 public void enableColoredLabels(bool isEnabled) {
2486 fIsColoredLabelsSupportEnabled= isEnabled; 2483 fIsColoredLabelsSupportEnabled= isEnabled;