Implement auto-completion support for wxTextEntry in wxOSX/Cocoa.
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
This commit is contained in:
		@@ -525,6 +525,7 @@ MSW:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
OSX:
 | 
					OSX:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Implement auto-completion support in wxTextEntry.
 | 
				
			||||||
- Implement switching to default video mode in wxDisplay (soren).
 | 
					- Implement switching to default video mode in wxDisplay (soren).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,12 +32,8 @@ class WXDLLIMPEXP_CORE wxTextEntry: public wxTextEntryBase
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    wxTextEntry()
 | 
					    wxTextEntry();
 | 
				
			||||||
        : m_editable(true),
 | 
					    virtual ~wxTextEntry();
 | 
				
			||||||
          m_maxLength(0)
 | 
					 | 
				
			||||||
    { }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    virtual ~wxTextEntry() {};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    virtual bool IsEditable() const;
 | 
					    virtual bool IsEditable() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -88,10 +84,18 @@ public:
 | 
				
			|||||||
    // --------------
 | 
					    // --------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    virtual wxTextWidgetImpl * GetTextPeer() const;
 | 
					    virtual wxTextWidgetImpl * GetTextPeer() const;
 | 
				
			||||||
 | 
					    wxTextCompleter *OSXGetCompleter() const { return m_completer; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    virtual wxString DoGetValue() const;
 | 
					    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;
 | 
					    bool  m_editable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // need to make this public because of the current implementation via callbacks
 | 
					  // need to make this public because of the current implementation via callbacks
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,8 +46,8 @@ public:
 | 
				
			|||||||
        Call this function to enable auto-completion of the text typed in a
 | 
					        Call this function to enable auto-completion of the text typed in a
 | 
				
			||||||
        single-line text control using the given @a choices.
 | 
					        single-line text control using the given @a choices.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Notice that currently this function is only implemented in wxGTK2 and
 | 
					        Notice that currently this function is only implemented in wxGTK2,
 | 
				
			||||||
        wxMSW ports and does nothing under the other platforms.
 | 
					        wxMSW and wxOSX/Cocoa ports and does nothing under the other platforms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @since 2.9.0
 | 
					        @since 2.9.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -75,7 +75,7 @@ public:
 | 
				
			|||||||
        Notice that you need to include @c wx/textcompleter.h in order to
 | 
					        Notice that you need to include @c wx/textcompleter.h in order to
 | 
				
			||||||
        define your class inheriting from wxTextCompleter.
 | 
					        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
 | 
					        @since 2.9.2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,6 +45,7 @@
 | 
				
			|||||||
#include "wx/filefn.h"
 | 
					#include "wx/filefn.h"
 | 
				
			||||||
#include "wx/sysopt.h"
 | 
					#include "wx/sysopt.h"
 | 
				
			||||||
#include "wx/thread.h"
 | 
					#include "wx/thread.h"
 | 
				
			||||||
 | 
					#include "wx/textcompleter.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "wx/osx/private.h"
 | 
					#include "wx/osx/private.h"
 | 
				
			||||||
#include "wx/osx/cocoa/private/textimpl.h"
 | 
					#include "wx/osx/cocoa/private/textimpl.h"
 | 
				
			||||||
@@ -293,21 +294,49 @@ protected :
 | 
				
			|||||||
 forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(int*)index
 | 
					 forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(int*)index
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    NSMutableArray* matches = NULL;
 | 
					    NSMutableArray* matches = NULL;
 | 
				
			||||||
    NSString*       partialString;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    partialString = [[textView string] substringWithRange:charRange];
 | 
					    wxTextWidgetImpl* impl = (wxNSTextFieldControl * ) wxWidgetImpl::FindFromWXWidget( self );
 | 
				
			||||||
    matches       = [NSMutableArray array];
 | 
					    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]
 | 
				
			||||||
 | 
					                            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    wxTextWidgetImpl* impl = (wxTextWidgetImpl* ) wxWidgetImpl::FindFromWXWidget( self );
 | 
					            matches = [NSMutableArray array];
 | 
				
			||||||
    wxArrayString completions;
 | 
					            for ( ;; )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                const wxString s = completer->GetNext();
 | 
				
			||||||
 | 
					                if ( s.empty() )
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // adapt to whatever strategy we have for getting the strings
 | 
					                // Normally the completer should return only the strings
 | 
				
			||||||
    // impl->GetTextEntry()->GetCompletions(wxCFStringRef::AsString(partialString), completions);
 | 
					                // starting with the prefix, but there could be exceptions
 | 
				
			||||||
    
 | 
					                // and, for compatibility with MSW which simply ignores all
 | 
				
			||||||
    for (size_t i = 0; i < completions.GetCount(); ++i )
 | 
					                // entries that don't match the current text control contents,
 | 
				
			||||||
        [matches addObject: wxCFStringRef(completions[i]).AsNSString()];
 | 
					                // we ignore them as well. Besides, our own wxTextCompleterFixed
 | 
				
			||||||
 | 
					                // doesn't respect this rule and, moreover, we need to extract
 | 
				
			||||||
    // [matches sortUsingSelector:@selector(compare:)];
 | 
					                // 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;
 | 
					    return matches;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,9 +45,22 @@
 | 
				
			|||||||
#include "wx/filefn.h"
 | 
					#include "wx/filefn.h"
 | 
				
			||||||
#include "wx/sysopt.h"
 | 
					#include "wx/sysopt.h"
 | 
				
			||||||
#include "wx/thread.h"
 | 
					#include "wx/thread.h"
 | 
				
			||||||
 | 
					#include "wx/textcompleter.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "wx/osx/private.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
 | 
					wxString wxTextEntry::DoGetValue() const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return GetTextPeer()->GetStringValue() ;
 | 
					    return GetTextPeer()->GetStringValue() ;
 | 
				
			||||||
@@ -224,4 +237,23 @@ wxTextWidgetImpl * wxTextEntry::GetTextPeer() const
 | 
				
			|||||||
    return win ? dynamic_cast<wxTextWidgetImpl *>(win->GetPeer()) : NULL;
 | 
					    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
 | 
					#endif // wxUSE_TEXTCTRL
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user