]> git.saurik.com Git - wxWidgets.git/commitdiff
Use ACO_AUTOAPPEND option for text completion in wxMSW.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 16 Apr 2011 17:27:26 +0000 (17:27 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 16 Apr 2011 17:27:26 +0000 (17:27 +0000)
This option appends the first candidate completion value to the text control
itself making it more user-friendly as it reduces the amount of typing needed
to enter it.

See #11465.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@67513 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/msw/textentry.cpp

index 161035b59ff5131cc0fd40c019be685ad3fb3f20..f2d8eafd5671d00d1a373a5b41511fec6670ce62 100644 (file)
@@ -194,7 +194,7 @@ public:
         m_enumStrings = NULL;
         m_customCompleter = NULL;
 
-        m_connectedTextChangedEvent = false;
+        m_connectedCharEvent = false;
 
         // Create an object exposing IAutoComplete interface which we'll later
         // use to get IAutoComplete2 as the latter can't be created directly,
@@ -255,6 +255,7 @@ public:
         if ( SUCCEEDED(hr) )
         {
             pAutoComplete2->SetOptions(ACO_AUTOSUGGEST |
+                                       ACO_AUTOAPPEND |
                                        ACO_UPDOWNKEYDROPSLIST);
             pAutoComplete2->Release();
         }
@@ -297,13 +298,25 @@ public:
             // We postpone connecting to this event until we really need to do
             // it (however we don't disconnect from it when we don't need it
             // any more because we don't have wxUNBIND_OR_DISCONNECT_HACK...).
-            if ( !m_connectedTextChangedEvent )
+            if ( !m_connectedCharEvent )
             {
-                m_connectedTextChangedEvent = true;
-
-                wxBIND_OR_CONNECT_HACK(m_win, wxEVT_COMMAND_TEXT_UPDATED,
-                                        wxCommandEventHandler,
-                                        wxTextAutoCompleteData::OnTextChanged,
+                m_connectedCharEvent = true;
+
+                // Use the special wxEVT_AFTER_CHAR and not the usual
+                // wxEVT_CHAR here because we need to have the updated value of
+                // the text control in this handler in order to provide
+                // completions for the correct prefix and unfortunately we
+                // don't have any way to let DefWindowProc() run from our
+                // wxEVT_CHAR handler (as we must also let the other handlers
+                // defined at wx level run first).
+                //
+                // Notice that we can't use wxEVT_COMMAND_TEXT_UPDATED here
+                // neither as, due to our use of ACO_AUTOAPPEND, we get
+                // EN_CHANGE notifications from the control every time
+                // IAutoComplete auto-appends something to it.
+                wxBIND_OR_CONNECT_HACK(m_win, wxEVT_AFTER_CHAR,
+                                        wxKeyEventHandler,
+                                        wxTextAutoCompleteData::OnAfterChar,
                                         this);
             }
 
@@ -348,19 +361,32 @@ private:
     // the currently valid choices according to the custom completer.
     void UpdateStringsFromCustomCompleter()
     {
+        // As we use ACO_AUTOAPPEND, the selected part of the text is usually
+        // the one appended by us so don't consider it as part of the
+        // user-entered prefix.
+        long from, to;
+        m_entry->GetSelection(&from, &to);
+
+        if ( to == from )
+            from = m_entry->GetLastPosition(); // Take all if no selection.
+
+        const wxString prefix = m_entry->GetRange(0, from);
+
         // For efficiency we access m_strings directly instead of creating
         // another wxArrayString, normally this should save us an unnecessary
         // memory allocation on the subsequent calls.
         m_enumStrings->m_strings.clear();
-        m_customCompleter->GetCompletions(m_entry->GetValue(),
-                                          m_enumStrings->m_strings);
+        m_customCompleter->GetCompletions(prefix, m_enumStrings->m_strings);
 
         DoRefresh();
     }
 
-    void OnTextChanged(wxCommandEvent& event)
+    void OnAfterChar(wxKeyEvent& event)
     {
-        if ( m_customCompleter )
+        // Notice that we must not refresh the completions when the user
+        // presses Backspace as this would result in adding back the just
+        // erased character(s) because of ACO_AUTOAPPEND option we use.
+        if ( m_customCompleter && event.GetKeyCode() != WXK_BACK )
             UpdateStringsFromCustomCompleter();
 
         event.Skip();
@@ -386,7 +412,7 @@ private:
     wxTextCompleter *m_customCompleter;
 
     // Initially false, set to true after connecting OnTextChanged() handler.
-    bool m_connectedTextChangedEvent;
+    bool m_connectedCharEvent;
 
 
     wxDECLARE_NO_COPY_CLASS(wxTextAutoCompleteData);