Files
wxWidgets/src/osx/cocoa/srchctrl.mm
Stefan Csomor 5f21280130 Avoid duplicate wxEVT_SEARCHCTRL_CANCEL_BTN event under macOS
see https://github.com/wxWidgets/wxWidgets/pull/698 , along the idea by commit 1776f136f7d673c8e772c9ca6e1607089a071651, implemented a little bit more defensively
2018-01-30 17:17:47 +01:00

242 lines
6.8 KiB
Plaintext

///////////////////////////////////////////////////////////////////////////////
// Name: src/osx/cocoa/srchctrl.mm
// Purpose: implements mac carbon wxSearchCtrl
// Author: Vince Harron
// Created: 2006-02-19
// Copyright: Vince Harron
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#if wxUSE_SEARCHCTRL
#include "wx/srchctrl.h"
#ifndef WX_PRECOMP
#include "wx/menu.h"
#endif //WX_PRECOMP
#if wxUSE_NATIVE_SEARCH_CONTROL
#include "wx/osx/private.h"
#include "wx/osx/cocoa/private/textimpl.h"
@interface wxNSSearchField : NSSearchField
{
BOOL m_withinTextDidChange;
}
@end
@implementation wxNSSearchField
+ (void)initialize
{
static BOOL initialized = NO;
if (!initialized)
{
initialized = YES;
wxOSXCocoaClassAddWXMethods( self );
}
}
- (id)initWithFrame:(NSRect)frame
{
if ( self = [super initWithFrame:frame] )
{
m_withinTextDidChange = NO;
}
return self;
}
- (void)textDidChange:(NSNotification *)aNotification
{
m_withinTextDidChange = YES;
[super textDidChange:aNotification];
m_withinTextDidChange = NO;
}
- (void)controlTextDidChange:(NSNotification *)aNotification
{
wxUnusedVar(aNotification);
wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self );
if ( impl )
impl->controlTextDidChange();
}
- (NSArray *)control:(NSControl *)control textView:(NSTextView *)textView completions:(NSArray *)words
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:)];
return matches;
}
- (BOOL) isWithinTextDidChange
{
return m_withinTextDidChange;
}
@end
// ============================================================================
// wxMacSearchFieldControl
// ============================================================================
class wxNSSearchFieldControl : public wxNSTextFieldControl, public wxSearchWidgetImpl
{
public :
wxNSSearchFieldControl( wxTextCtrl *wxPeer, wxNSSearchField* w ) : wxNSTextFieldControl(wxPeer, w)
{
m_searchFieldCell = [w cell];
m_searchField = w;
}
~wxNSSearchFieldControl();
// search field options
virtual void ShowSearchButton( bool show ) wxOVERRIDE
{
if ( show )
[m_searchFieldCell resetSearchButtonCell];
else
[m_searchFieldCell setSearchButtonCell:nil];
[m_searchField setNeedsDisplay:YES];
}
virtual bool IsSearchButtonVisible() const wxOVERRIDE
{
return [m_searchFieldCell searchButtonCell] != nil;
}
virtual void ShowCancelButton( bool show ) wxOVERRIDE
{
if ( show )
[m_searchFieldCell resetCancelButtonCell];
else
[m_searchFieldCell setCancelButtonCell:nil];
[m_searchField setNeedsDisplay:YES];
}
virtual bool IsCancelButtonVisible() const wxOVERRIDE
{
return [m_searchFieldCell cancelButtonCell] != nil;
}
virtual void SetSearchMenu( wxMenu* menu ) wxOVERRIDE
{
if ( menu )
[m_searchFieldCell setSearchMenuTemplate:menu->GetHMenu()];
else
[m_searchFieldCell setSearchMenuTemplate:nil];
[m_searchField setNeedsDisplay:YES];
}
virtual void SetDescriptiveText(const wxString& text) wxOVERRIDE
{
[m_searchFieldCell setPlaceholderString:
wxCFStringRef( text , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
}
virtual bool SetFocus() wxOVERRIDE
{
return wxNSTextFieldControl::SetFocus();
}
void controlAction( WXWidget WXUNUSED(slf), void *WXUNUSED(_cmd), void *WXUNUSED(sender)) wxOVERRIDE
{
wxSearchCtrl* wxpeer = (wxSearchCtrl*) GetWXPeer();
if ( wxpeer )
{
NSString *searchString = [m_searchField stringValue];
if ( searchString == nil || !searchString.length )
{
if ( ![m_searchField isWithinTextDidChange])
wxpeer->HandleSearchFieldCancelHit();
}
else
{
wxpeer->HandleSearchFieldSearchHit();
}
}
}
virtual void SetCentredLook( bool centre )
{
SEL sel = @selector(setCenteredLook:);
if ( [m_searchFieldCell respondsToSelector: sel] )
{
// all this avoids xcode parsing warnings when using
// [m_searchFieldCell setCenteredLook:NO];
NSMethodSignature* signature =
[NSSearchFieldCell instanceMethodSignatureForSelector:sel];
NSInvocation* invocation =
[NSInvocation invocationWithMethodSignature: signature];
[invocation setTarget: m_searchFieldCell];
[invocation setSelector:sel];
[invocation setArgument:&centre atIndex:2];
[invocation invoke];
}
}
private:
wxNSSearchField* m_searchField;
NSSearchFieldCell* m_searchFieldCell;
} ;
wxNSSearchFieldControl::~wxNSSearchFieldControl()
{
}
wxWidgetImplType* wxWidgetImpl::CreateSearchControl( wxSearchCtrl* wxpeer,
wxWindowMac* WXUNUSED(parent),
wxWindowID WXUNUSED(id),
const wxString& str,
const wxPoint& pos,
const wxSize& size,
long WXUNUSED(style),
long WXUNUSED(extraStyle))
{
NSRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ;
wxNSSearchField* v = [[wxNSSearchField alloc] initWithFrame:r];
// Make it behave consistently with the single line wxTextCtrl
[[v cell] setScrollable:YES];
[[v cell] setSendsWholeSearchString:YES];
// per wx default cancel is not shown
[[v cell] setCancelButtonCell:nil];
wxNSSearchFieldControl* c = new wxNSSearchFieldControl( wxpeer, v );
c->SetNeedsFrame( false );
c->SetCentredLook( false );
c->SetStringValue( str );
return c;
}
#endif // wxUSE_NATIVE_SEARCH_CONTROL
#endif // wxUSE_SEARCHCTRL