simplify native textcontrol creations, adding search control for cocoa

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@55476 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Stefan Csomor
2008-09-05 14:41:11 +00:00
parent 23e00c551b
commit 1e181c7a2c
21 changed files with 734 additions and 972 deletions

View File

@@ -25,368 +25,165 @@
#if wxUSE_NATIVE_SEARCH_CONTROL
#include "wx/osx/uma.h"
#include "wx/osx/carbon/private/mactext.h"
#include "wx/osx/private.h"
#include "wx/osx/cocoa/private/textimpl.h"
BEGIN_EVENT_TABLE(wxSearchCtrl, wxSearchCtrlBase)
END_EVENT_TABLE()
IMPLEMENT_DYNAMIC_CLASS(wxSearchCtrl, wxSearchCtrlBase)
@interface wxNSSearchField : NSSearchField
{
wxWidgetImpl* impl;
}
@end
@implementation wxNSSearchField
- (id)initWithFrame:(NSRect)frame
{
[super initWithFrame:frame];
impl = NULL;
[self setTarget: self];
[self setAction: @selector(searchAction:)];
return self;
}
- (void)setImplementation: (wxWidgetImpl *) theImplementation
{
impl = theImplementation;
}
- (wxWidgetImpl*) implementation
{
return impl;
}
- (BOOL) isFlipped
{
return YES;
}
// use our common calls
- (void) setTitle:(NSString *) title
{
[self setStringValue: title];
}
- (void) searchAction: (id) sender
{
if ( impl )
{
wxSearchCtrl* wxpeer = dynamic_cast<wxSearchCtrl*>( impl->GetWXPeer() );
if ( wxpeer )
{
NSString *searchString = [self stringValue];
if ( searchString == nil )
{
wxpeer->HandleSearchFieldCancelHit();
}
else
{
wxpeer->HandleSearchFieldSearchHit();
}
}
}
}
@end
// ============================================================================
// wxMacSearchFieldControl
// ============================================================================
static const EventTypeSpec eventList[] =
{
{ kEventClassSearchField, kEventSearchFieldCancelClicked } ,
{ kEventClassSearchField, kEventSearchFieldSearchClicked } ,
};
class wxMacSearchFieldControl : public wxMacUnicodeTextControl
class wxNSSearchFieldControl : public wxNSTextFieldControl, public wxSearchWidgetImpl
{
public :
wxMacSearchFieldControl( wxTextCtrl *wxPeer,
const wxString& str,
const wxPoint& pos,
const wxSize& size, long style ) : wxMacUnicodeTextControl( wxPeer )
wxNSSearchFieldControl( wxTextCtrl *wxPeer, wxNSSearchField* w ) : wxNSTextFieldControl(wxPeer, w)
{
Create( wxPeer, str, pos, size, style );
m_searchFieldCell = [w cell];
m_searchField = w;
}
~wxNSSearchFieldControl();
// search field options
virtual void ShowSearchButton( bool show );
virtual bool IsSearchButtonVisible() const;
virtual void ShowCancelButton( bool show );
virtual bool IsCancelButtonVisible() const;
virtual void SetSearchMenu( wxMenu* menu );
virtual wxMenu* GetSearchMenu() const;
virtual void SetDescriptiveText(const wxString& text);
virtual wxString GetDescriptiveText() const;
virtual void ShowSearchButton( bool show )
{
if ( show )
[m_searchFieldCell resetSearchButtonCell];
else
[m_searchFieldCell setSearchButtonCell:nil];
[m_searchField setNeedsDisplay:YES];
}
virtual bool SetFocus();
virtual bool IsSearchButtonVisible() const
{
return [m_searchFieldCell searchButtonCell] != nil;
}
protected :
virtual void CreateControl( wxTextCtrl* peer, const Rect* bounds, CFStringRef crf );
virtual void ShowCancelButton( bool show )
{
if ( show )
[m_searchFieldCell resetCancelButtonCell];
else
[m_searchFieldCell setCancelButtonCell:nil];
[m_searchField setNeedsDisplay:YES];
}
virtual bool IsCancelButtonVisible() const
{
return [m_searchFieldCell cancelButtonCell] != nil;
}
virtual void SetSearchMenu( wxMenu* menu )
{
if ( menu )
[m_searchFieldCell setSearchMenuTemplate:menu->GetHMenu()];
else
[m_searchFieldCell setSearchMenuTemplate:nil];
[m_searchField setNeedsDisplay:YES];
}
virtual void SetDescriptiveText(const wxString& text)
{
[m_searchFieldCell setPlaceholderString:
wxCFStringRef( text , m_wxPeer->GetFont().GetEncoding() ).AsNSString()];
}
virtual bool SetFocus()
{
return wxNSTextFieldControl::SetFocus();
}
private:
wxMenu* m_menu;
wxNSSearchField* m_searchField;
NSSearchFieldCell* m_searchFieldCell;
} ;
void wxMacSearchFieldControl::CreateControl(wxTextCtrl* WXUNUSED(peer),
const Rect* bounds,
CFStringRef WXUNUSED(crf))
wxNSSearchFieldControl::~wxNSSearchFieldControl()
{
OptionBits attributes = kHISearchFieldAttributesSearchIcon;
HIRect hibounds = { { bounds->left, bounds->top }, { bounds->right-bounds->left, bounds->bottom-bounds->top } };
verify_noerr( HISearchFieldCreate(
&hibounds,
attributes,
0, // MenuRef
CFSTR("Search"),
&m_controlRef
) );
HIViewSetVisible (m_controlRef, true);
}
// search field options
void wxMacSearchFieldControl::ShowSearchButton( bool show )
wxWidgetImplType* wxWidgetImpl::CreateSearchControl( wxTextCtrl* wxpeer,
wxWindowMac* parent,
wxWindowID id,
const wxString& str,
const wxPoint& pos,
const wxSize& size,
long style,
long extraStyle)
{
OptionBits set = 0;
OptionBits clear = 0;
if ( show )
{
set |= kHISearchFieldAttributesSearchIcon;
}
else
{
clear |= kHISearchFieldAttributesSearchIcon;
}
HISearchFieldChangeAttributes( m_controlRef, set, clear );
}
NSView* sv = (wxpeer->GetParent()->GetHandle() );
NSRect r = wxOSXGetFrameForControl( wxpeer, pos , size ) ;
wxNSSearchField* v = [[wxNSSearchField alloc] initWithFrame:r];
[sv addSubview:v];
[[v cell] setSendsWholeSearchString:YES];
// per wx default cancel is not shown
[[v cell] setCancelButtonCell:nil];
bool wxMacSearchFieldControl::IsSearchButtonVisible() const
{
OptionBits attributes = 0;
verify_noerr( HISearchFieldGetAttributes( m_controlRef, &attributes ) );
return ( attributes & kHISearchFieldAttributesSearchIcon ) != 0;
}
void wxMacSearchFieldControl::ShowCancelButton( bool show )
{
OptionBits set = 0;
OptionBits clear = 0;
if ( show )
{
set |= kHISearchFieldAttributesCancel;
}
else
{
clear |= kHISearchFieldAttributesCancel;
}
HISearchFieldChangeAttributes( m_controlRef, set, clear );
}
bool wxMacSearchFieldControl::IsCancelButtonVisible() const
{
OptionBits attributes = 0;
verify_noerr( HISearchFieldGetAttributes( m_controlRef, &attributes ) );
return ( attributes & kHISearchFieldAttributesCancel ) != 0;
}
void wxMacSearchFieldControl::SetSearchMenu( wxMenu* menu )
{
m_menu = menu;
if ( m_menu )
{
verify_noerr( HISearchFieldSetSearchMenu( m_controlRef, MAC_WXHMENU(m_menu->GetHMenu()) ) );
}
else
{
verify_noerr( HISearchFieldSetSearchMenu( m_controlRef, 0 ) );
}
}
wxMenu* wxMacSearchFieldControl::GetSearchMenu() const
{
return m_menu;
}
void wxMacSearchFieldControl::SetDescriptiveText(const wxString& text)
{
verify_noerr( HISearchFieldSetDescriptiveText(
m_controlRef,
wxCFStringRef( text, wxFont::GetDefaultEncoding() )));
}
wxString wxMacSearchFieldControl::GetDescriptiveText() const
{
CFStringRef cfStr;
verify_noerr( HISearchFieldCopyDescriptiveText( m_controlRef, &cfStr ));
if ( cfStr )
{
return wxCFStringRef(cfStr).AsString();
}
else
{
return wxEmptyString;
}
}
bool wxMacSearchFieldControl::SetFocus()
{
// NB: We have to implement SetFocus a little differently because kControlFocusNextPart
// leads to setting the focus on the search icon rather than the text area.
// We get around this by explicitly telling the control to set focus to the
// text area.
OSStatus err = SetKeyboardFocus( GetControlOwner( m_controlRef ), m_controlRef, kControlEditTextPart );
if ( err == errCouldntSetFocus )
return false ;
SetUserFocusWindow(GetControlOwner( m_controlRef ) );
return true;
}
// ============================================================================
// implementation
// ============================================================================
static pascal OSStatus wxMacSearchControlEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
{
OSStatus result = eventNotHandledErr ;
wxMacCarbonEvent cEvent( event ) ;
ControlRef controlRef ;
wxSearchCtrl* thisWindow = (wxSearchCtrl*) data ;
cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ;
switch( GetEventKind( event ) )
{
case kEventSearchFieldCancelClicked :
thisWindow->MacSearchFieldCancelHit( handler , event ) ;
break ;
case kEventSearchFieldSearchClicked :
thisWindow->MacSearchFieldSearchHit( handler , event ) ;
break ;
}
return result ;
}
DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacSearchControlEventHandler )
// ----------------------------------------------------------------------------
// wxSearchCtrl creation
// ----------------------------------------------------------------------------
// creation
// --------
wxSearchCtrl::wxSearchCtrl()
{
Init();
}
wxSearchCtrl::wxSearchCtrl(wxWindow *parent, wxWindowID id,
const wxString& value,
const wxPoint& pos,
const wxSize& size,
long style,
const wxValidator& validator,
const wxString& name)
{
Init();
Create(parent, id, value, pos, size, style, validator, name);
}
void wxSearchCtrl::Init()
{
m_menu = 0;
}
bool wxSearchCtrl::Create(wxWindow *parent, wxWindowID id,
const wxString& value,
const wxPoint& pos,
const wxSize& size,
long style,
const wxValidator& validator,
const wxString& name)
{
if ( !wxTextCtrl::Create(parent, id, wxEmptyString, pos, size, wxBORDER_NONE | style, validator, name) )
{
return false;
}
EventHandlerRef searchEventHandler;
InstallControlEventHandler( m_peer->GetControlRef(), GetwxMacSearchControlEventHandlerUPP(),
GetEventTypeCount(eventList), eventList, this,
(EventHandlerRef *)&searchEventHandler);
SetValue(value);
return true;
}
wxSearchCtrl::~wxSearchCtrl()
{
delete m_menu;
}
wxSize wxSearchCtrl::DoGetBestSize() const
{
wxSize size = wxWindow::DoGetBestSize();
// it seems to return a default width of about 16, which is way too small here.
if (size.GetWidth() < 100)
size.SetWidth(100);
return size;
}
// search control specific interfaces
// wxSearchCtrl owns menu after this call
void wxSearchCtrl::SetMenu( wxMenu* menu )
{
if ( menu == m_menu )
{
// no change
return;
}
if ( m_menu )
{
m_menu->SetInvokingWindow( 0 );
}
delete m_menu;
m_menu = menu;
if ( m_menu )
{
m_menu->SetInvokingWindow( this );
}
GetPeer()->SetSearchMenu( m_menu );
}
wxMenu* wxSearchCtrl::GetMenu()
{
return m_menu;
}
void wxSearchCtrl::ShowSearchButton( bool show )
{
if ( IsSearchButtonVisible() == show )
{
// no change
return;
}
GetPeer()->ShowSearchButton( show );
}
bool wxSearchCtrl::IsSearchButtonVisible() const
{
return GetPeer()->IsSearchButtonVisible();
}
void wxSearchCtrl::ShowCancelButton( bool show )
{
if ( IsCancelButtonVisible() == show )
{
// no change
return;
}
GetPeer()->ShowCancelButton( show );
}
bool wxSearchCtrl::IsCancelButtonVisible() const
{
return GetPeer()->IsCancelButtonVisible();
}
void wxSearchCtrl::SetDescriptiveText(const wxString& text)
{
GetPeer()->SetDescriptiveText(text);
}
wxString wxSearchCtrl::GetDescriptiveText() const
{
return GetPeer()->GetDescriptiveText();
}
wxInt32 wxSearchCtrl::MacSearchFieldSearchHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
{
wxCommandEvent event(wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN, m_windowId );
event.SetEventObject(this);
ProcessCommand(event);
return eventNotHandledErr ;
}
wxInt32 wxSearchCtrl::MacSearchFieldCancelHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
{
wxCommandEvent event(wxEVT_COMMAND_SEARCHCTRL_CANCEL_BTN, m_windowId );
event.SetEventObject(this);
ProcessCommand(event);
return eventNotHandledErr ;
}
void wxSearchCtrl::CreatePeer(
const wxString& str,
const wxPoint& pos,
const wxSize& size, long style )
{
m_peer = new wxMacSearchFieldControl( this , str , pos , size , style );
wxNSSearchFieldControl* c = new wxNSSearchFieldControl( wxpeer, v );
c->SetStringValue( str );
[v setImplementation:c];
return c;
}
#endif // wxUSE_NATIVE_SEARCH_CONTROL