]> git.saurik.com Git - wxWidgets.git/commitdiff
Implement auto-completion support for wxTextEntry in wxOSX/Cocoa.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 17 Apr 2011 23:14:15 +0000 (23:14 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 17 Apr 2011 23:14:15 +0000 (23:14 +0000)
Both completing a set of fixed strings and dynamic completion using a custom
completer are supported, although completing the file names remains MSW-only
for now.

Note that, unlike under MSW, auto-completion under Mac is not automatic and
has to be triggered manually by calling complete: method. This is done by
pressing F5 key by default. In the future we should call it automatically on a
timer event to make it more obviously discoverable.

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

docs/changes.txt
include/wx/osx/textentry.h
interface/wx/textentry.h
src/osx/cocoa/textctrl.mm
src/osx/textentry_osx.cpp

index 7fb9a2360988c1173701605d0ec8ae0a92f9eea2..e742a7880741a8bcbdb3133bd334413afb9d1108 100644 (file)
@@ -525,6 +525,7 @@ MSW:
 
 OSX:
 
+- Implement auto-completion support in wxTextEntry.
 - Implement switching to default video mode in wxDisplay (soren).
 
 
index bf4d6fbd3e5da43f7e6d536671e7e9a3f443cf7b..b51e97bbd560da781b6172b4ddb793b140719a11 100644 (file)
@@ -32,12 +32,8 @@ class WXDLLIMPEXP_CORE wxTextEntry: public wxTextEntryBase
 {
 
 public:
-    wxTextEntry()
-        : m_editable(true),
-          m_maxLength(0)
-    { }
-
-    virtual ~wxTextEntry() {};
+    wxTextEntry();
+    virtual ~wxTextEntry();
 
     virtual bool IsEditable() const;
 
@@ -88,10 +84,18 @@ public:
     // --------------
 
     virtual wxTextWidgetImpl * GetTextPeer() const;
+    wxTextCompleter *OSXGetCompleter() const { return m_completer; }
+
 protected:
 
     virtual wxString DoGetValue() const;
 
+    virtual bool DoAutoCompleteStrings(const wxArrayString& choices);
+    virtual bool DoAutoCompleteCustom(wxTextCompleter *completer);
+
+    // The object providing auto-completions or NULL if none.
+    wxTextCompleter *m_completer;
+
     bool  m_editable;
 
   // need to make this public because of the current implementation via callbacks
index 565bbaf5971e4f925b36df677d27b56802a86a1e..a5894931ba07edfd9824c92c165ab9a678efa45d 100644 (file)
@@ -46,8 +46,8 @@ public:
         Call this function to enable auto-completion of the text typed in a
         single-line text control using the given @a choices.
 
-        Notice that currently this function is only implemented in wxGTK2 and
-        wxMSW ports and does nothing under the other platforms.
+        Notice that currently this function is only implemented in wxGTK2,
+        wxMSW and wxOSX/Cocoa ports and does nothing under the other platforms.
 
         @since 2.9.0
 
@@ -75,7 +75,7 @@ public:
         Notice that you need to include @c wx/textcompleter.h in order to
         define your class inheriting from wxTextCompleter.
 
-        Currently this method is only implemented in wxMSW port.
+        Currently this method is only implemented in wxMSW and wxOSX/Cocoa.
 
         @since 2.9.2
 
index 364c3993b2040ea7e1c45e98a4c986fa7a1f84be..f8e4f22bf26c827f277fff4099ce4f323bbb35e9 100644 (file)
@@ -45,6 +45,7 @@
 #include "wx/filefn.h"
 #include "wx/sysopt.h"
 #include "wx/thread.h"
+#include "wx/textcompleter.h"
 
 #include "wx/osx/private.h"
 #include "wx/osx/cocoa/private/textimpl.h"
@@ -293,22 +294,50 @@ protected :
  forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(int*)index
 {
     NSMutableArray* matches = NULL;
-    NSString*       partialString;
-    
-    partialString = [[textView string] substringWithRange:charRange];
-    matches       = [NSMutableArray array];
-    
-    wxTextWidgetImpl* impl = (wxTextWidgetImpl* ) wxWidgetImpl::FindFromWXWidget( self );
-    wxArrayString completions;
-    
-    // adapt to whatever strategy we have for getting the strings
-    // impl->GetTextEntry()->GetCompletions(wxCFStringRef::AsString(partialString), completions);
-    
-    for (size_t i = 0; i < completions.GetCount(); ++i )
-        [matches addObject: wxCFStringRef(completions[i]).AsNSString()];
 
-    // [matches sortUsingSelector:@selector(compare:)];
-    
+    wxTextWidgetImpl* impl = (wxNSTextFieldControl * ) wxWidgetImpl::FindFromWXWidget( self );
+    wxTextEntry * const entry = impl->GetTextEntry();
+    wxTextCompleter * const completer = entry->OSXGetCompleter();
+    if ( completer )
+    {
+        const wxString prefix = entry->GetValue();
+        if ( completer->Start(prefix) )
+        {
+            const wxString
+                wordStart = wxCFStringRef::AsString(
+                              [[textView string] substringWithRange:charRange]
+                            );
+
+            matches = [NSMutableArray array];
+            for ( ;; )
+            {
+                const wxString s = completer->GetNext();
+                if ( s.empty() )
+                    break;
+
+                // Normally the completer should return only the strings
+                // starting with the prefix, but there could be exceptions
+                // and, for compatibility with MSW which simply ignores all
+                // entries that don't match the current text control contents,
+                // we ignore them as well. Besides, our own wxTextCompleterFixed
+                // doesn't respect this rule and, moreover, we need to extract
+                // just the rest of the string anyhow.
+                wxString completion;
+                if ( s.StartsWith(prefix, &completion) )
+                {
+                    // We discarded the entire prefix above but actually we
+                    // should include the part of it that consists of the
+                    // beginning of the current word, otherwise it would be
+                    // lost when completion is accepted as OS X supposes that
+                    // our matches do start with the "partial word range"
+                    // passed to us.
+                    const wxCFStringRef fullWord(wordStart + completion);
+                    [matches addObject: fullWord.AsNSString()];
+                }
+            }
+        }
+    }
+
     return matches;
 }
 
index 5f51fca1b7bb9524088b0e9e0c3917430bd237d6..8061d068e40f22e28d446f0cb5939f8e8a5d9679 100644 (file)
 #include "wx/filefn.h"
 #include "wx/sysopt.h"
 #include "wx/thread.h"
+#include "wx/textcompleter.h"
 
 #include "wx/osx/private.h"
 
+wxTextEntry::wxTextEntry()
+{
+    m_completer = NULL;
+    m_editable = true;
+    m_maxLength = 0;
+}
+
+wxTextEntry::~wxTextEntry()
+{
+    delete m_completer;
+}
+
 wxString wxTextEntry::DoGetValue() const
 {
     return GetTextPeer()->GetStringValue() ;
@@ -224,4 +237,23 @@ wxTextWidgetImpl * wxTextEntry::GetTextPeer() const
     return win ? dynamic_cast<wxTextWidgetImpl *>(win->GetPeer()) : NULL;
 }
 
+// ----------------------------------------------------------------------------
+// Auto-completion
+// ----------------------------------------------------------------------------
+
+bool wxTextEntry::DoAutoCompleteStrings(const wxArrayString& choices)
+{
+    wxTextCompleterFixed * const completer = new wxTextCompleterFixed;
+    completer->SetCompletions(choices);
+
+    return DoAutoCompleteCustom(completer);
+}
+
+bool wxTextEntry::DoAutoCompleteCustom(wxTextCompleter *completer)
+{
+    m_completer = completer;
+
+    return true;
+}
+
 #endif // wxUSE_TEXTCTRL