1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/generic/srchctlg.cpp 
   3 // Purpose:     implements wxSearchCtrl as a composite control 
   4 // Author:      Vince Harron 
   7 // Copyright:   Vince Harron 
   8 // License:     wxWindows licence 
   9 /////////////////////////////////////////////////////////////////////////////// 
  11 // For compilers that support precompilation, includes "wx.h". 
  12 #include "wx/wxprec.h" 
  20 #include "wx/srchctrl.h" 
  23     #include "wx/button.h" 
  24     #include "wx/dcclient.h" 
  26     #include "wx/dcmemory.h" 
  29 #if !wxUSE_NATIVE_SEARCH_CONTROL 
  33 #define WXMAX(a,b) ((a)>(b)?(a):(b)) 
  35 // ---------------------------------------------------------------------------- 
  37 // ---------------------------------------------------------------------------- 
  39 // the margin between the text control and the search/cancel buttons 
  40 static const wxCoord MARGIN 
= 2; 
  42 // border around all controls to compensate for wxSIMPLE_BORDER 
  43 #if defined(__WXMSW__) 
  44 static const wxCoord BORDER 
= 0; 
  45 static const wxCoord ICON_MARGIN 
= 2; 
  46 static const wxCoord ICON_OFFSET 
= 2; 
  48 static const wxCoord BORDER 
= 2; 
  49 static const wxCoord ICON_MARGIN 
= 0; 
  50 static const wxCoord ICON_OFFSET 
= 0; 
  53 // ---------------------------------------------------------------------------- 
  54 // TODO: These functions or something like them should probably be made 
  55 // public.  There are similar functions in src/aui/dockart.cpp... 
  57 static double wxBlendColour(double fg
, double bg
, double alpha
) 
  59     double result 
= bg 
+ (alpha 
* (fg 
- bg
)); 
  67 static wxColor 
wxStepColour(const wxColor
& c
, int ialpha
) 
  72     double r 
= c
.Red(), g 
= c
.Green(), b 
= c
.Blue(); 
  75     // ialpha is 0..200 where 0 is completely black 
  76     // and 200 is completely white and 100 is the same 
  77     // convert that to normal alpha 0.0 - 1.0 
  78     ialpha 
= wxMin(ialpha
, 200); 
  79     ialpha 
= wxMax(ialpha
, 0); 
  80     double alpha 
= ((double)(ialpha 
- 100.0))/100.0; 
  86         alpha 
= 1.0 - alpha
;  // 0 = transparent fg; 1 = opaque fg 
  92         alpha 
= 1.0 + alpha
;  // 0 = transparent fg; 1 = opaque fg 
  95     r 
= wxBlendColour(r
, bg
, alpha
); 
  96     g 
= wxBlendColour(g
, bg
, alpha
); 
  97     b 
= wxBlendColour(b
, bg
, alpha
); 
  99     return wxColour((unsigned char)r
, (unsigned char)g
, (unsigned char)b
); 
 102 #define LIGHT_STEP 160 
 104 // ---------------------------------------------------------------------------- 
 105 // wxSearchTextCtrl: text control used by search control 
 106 // ---------------------------------------------------------------------------- 
 108 class wxSearchTextCtrl 
: public wxTextCtrl
 
 111     wxSearchTextCtrl(wxSearchCtrl 
*search
, const wxString
& value
, int style
) 
 112         : wxTextCtrl(search
, wxID_ANY
, value
, wxDefaultPosition
, wxDefaultSize
, 
 116         m_defaultFG 
= GetForegroundColour(); 
 118         // remove the default minsize, the searchctrl will have one instead 
 119         SetSizeHints(wxDefaultCoord
,wxDefaultCoord
); 
 122     void SetDescriptiveText(const wxString
& text
) 
 124         if ( GetValue() == m_descriptiveText 
) 
 126             ChangeValue(wxEmptyString
); 
 129         m_descriptiveText 
= text
; 
 132     wxString 
GetDescriptiveText() const 
 134         return m_descriptiveText
; 
 138     void OnText(wxCommandEvent
& eventText
) 
 140         wxCommandEvent 
event(eventText
); 
 141         event
.SetEventObject(m_search
); 
 142         event
.SetId(m_search
->GetId()); 
 144         m_search
->GetEventHandler()->ProcessEvent(event
); 
 147     void OnTextUrl(wxTextUrlEvent
& eventText
) 
 149         // copy constructor is disabled for some reason? 
 150         //wxTextUrlEvent event(eventText); 
 151         wxTextUrlEvent 
event( 
 153             eventText
.GetMouseEvent(), 
 154             eventText
.GetURLStart(), 
 155             eventText
.GetURLEnd() 
 157         event
.SetEventObject(m_search
); 
 159         m_search
->GetEventHandler()->ProcessEvent(event
); 
 162     void OnIdle(wxIdleEvent
& WXUNUSED(event
)) 
 164         if ( IsEmpty() && !(wxWindow::FindFocus() == this) ) 
 166             ChangeValue(m_descriptiveText
); 
 167             SetInsertionPoint(0); 
 168             SetForegroundColour(wxStepColour(m_defaultFG
, LIGHT_STEP
)); 
 172     void OnFocus(wxFocusEvent
& event
) 
 175         if ( GetValue() == m_descriptiveText 
) 
 177             ChangeValue(wxEmptyString
); 
 178             SetForegroundColour(m_defaultFG
); 
 183     wxSearchCtrl
* m_search
; 
 184     wxString      m_descriptiveText
; 
 185     wxColour      m_defaultFG
; 
 187     DECLARE_EVENT_TABLE() 
 190 BEGIN_EVENT_TABLE(wxSearchTextCtrl
, wxTextCtrl
) 
 191     EVT_TEXT(wxID_ANY
, wxSearchTextCtrl::OnText
) 
 192     EVT_TEXT_ENTER(wxID_ANY
, wxSearchTextCtrl::OnText
) 
 193     EVT_TEXT_URL(wxID_ANY
, wxSearchTextCtrl::OnTextUrl
) 
 194     EVT_TEXT_MAXLEN(wxID_ANY
, wxSearchTextCtrl::OnText
) 
 195     EVT_IDLE(wxSearchTextCtrl::OnIdle
) 
 196     EVT_SET_FOCUS(wxSearchTextCtrl::OnFocus
) 
 199 // ---------------------------------------------------------------------------- 
 200 // wxSearchButton: search button used by search control 
 201 // ---------------------------------------------------------------------------- 
 203 class wxSearchButton 
: public wxControl
 
 206     wxSearchButton(wxSearchCtrl 
*search
, int eventType
, const wxBitmap
& bmp
) 
 207         : wxControl(search
, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, wxNO_BORDER
), 
 209           m_eventType(eventType
), 
 213     void SetBitmapLabel(const wxBitmap
& label
) { m_bmp 
= label
; } 
 217     wxSize 
DoGetBestSize() const 
 219         return wxSize(m_bmp
.GetWidth(), m_bmp
.GetHeight()); 
 222     void OnLeftUp(wxMouseEvent
&) 
 224         wxCommandEvent 
event(m_eventType
, m_search
->GetId()); 
 225         event
.SetEventObject(m_search
); 
 227         GetEventHandler()->ProcessEvent(event
); 
 229         m_search
->SetFocus(); 
 232         if ( m_eventType 
== wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN 
) 
 234             // this happens automatically, just like on Mac OS X 
 235             m_search
->PopupSearchMenu(); 
 237 #endif // wxUSE_MENUS 
 240     void OnPaint(wxPaintEvent
&) 
 243         dc
.DrawBitmap(m_bmp
, 0,0, true); 
 248     wxSearchCtrl 
*m_search
; 
 249     wxEventType   m_eventType
; 
 252     DECLARE_EVENT_TABLE() 
 255 BEGIN_EVENT_TABLE(wxSearchButton
, wxControl
) 
 256     EVT_LEFT_UP(wxSearchButton::OnLeftUp
) 
 257     EVT_PAINT(wxSearchButton::OnPaint
) 
 260 BEGIN_EVENT_TABLE(wxSearchCtrl
, wxSearchCtrlBase
) 
 261     EVT_SEARCHCTRL_SEARCH_BTN(wxID_ANY
, wxSearchCtrl::OnSearchButton
) 
 262     EVT_SET_FOCUS(wxSearchCtrl::OnSetFocus
) 
 263     EVT_SIZE(wxSearchCtrl::OnSize
) 
 266 IMPLEMENT_DYNAMIC_CLASS(wxSearchCtrl
, wxSearchCtrlBase
) 
 268 // ============================================================================ 
 270 // ============================================================================ 
 272 // ---------------------------------------------------------------------------- 
 273 // wxSearchCtrl creation 
 274 // ---------------------------------------------------------------------------- 
 279 wxSearchCtrl::wxSearchCtrl() 
 284 wxSearchCtrl::wxSearchCtrl(wxWindow 
*parent
, wxWindowID id
, 
 285            const wxString
& value
, 
 289            const wxValidator
& validator
, 
 290            const wxString
& name
) 
 294     Create(parent
, id
, value
, pos
, size
, style
, validator
, name
); 
 297 void wxSearchCtrl::Init() 
 300     m_searchButton 
= NULL
; 
 301     m_cancelButton 
= NULL
; 
 304 #endif // wxUSE_MENUS 
 306     m_searchButtonVisible 
= true; 
 307     m_cancelButtonVisible 
= false; 
 309     m_searchBitmapUser 
= false; 
 310     m_cancelBitmapUser 
= false; 
 312     m_searchMenuBitmapUser 
= false; 
 313 #endif // wxUSE_MENUS 
 316 bool wxSearchCtrl::Create(wxWindow 
*parent
, wxWindowID id
, 
 317             const wxString
& value
, 
 321             const wxValidator
& validator
, 
 322             const wxString
& name
) 
 324     // force border style for more native appearance 
 325     style 
&= ~wxBORDER_MASK
; 
 327     style 
|= wxBORDER_SUNKEN
; 
 329     style 
|= wxBORDER_SIMPLE
; 
 331     if ( !wxTextCtrlBase::Create(parent
, id
, pos
, size
, style
, validator
, name
) ) 
 336     m_text 
= new wxSearchTextCtrl(this, value
, style 
& ~wxBORDER_MASK
); 
 337     m_text
->SetDescriptiveText(_("Search")); 
 339     wxSize sizeText 
= m_text
->GetBestSize(); 
 341     m_searchButton 
= new wxSearchButton(this, 
 342                                         wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN
, 
 344     m_cancelButton 
= new wxSearchButton(this, 
 345                                         wxEVT_COMMAND_SEARCHCTRL_CANCEL_BTN
, 
 348     SetForegroundColour( m_text
->GetForegroundColour() ); 
 349     m_searchButton
->SetForegroundColour( m_text
->GetForegroundColour() ); 
 350     m_cancelButton
->SetForegroundColour( m_text
->GetForegroundColour() ); 
 352     SetBackgroundColour( m_text
->GetBackgroundColour() ); 
 353     m_searchButton
->SetBackgroundColour( m_text
->GetBackgroundColour() ); 
 354     m_cancelButton
->SetBackgroundColour( m_text
->GetBackgroundColour() ); 
 358     SetInitialSize(size
); 
 363 wxSearchCtrl::~wxSearchCtrl() 
 366     delete m_searchButton
; 
 367     delete m_cancelButton
; 
 370 #endif // wxUSE_MENUS 
 374 // search control specific interfaces 
 377 void wxSearchCtrl::SetMenu( wxMenu
* menu 
) 
 379     if ( menu 
== m_menu 
) 
 384     bool hadMenu 
= (m_menu 
!= NULL
); 
 388     if ( m_menu 
&& !hadMenu 
) 
 390         m_searchButton
->SetBitmapLabel(m_searchMenuBitmap
); 
 391         m_searchButton
->Refresh(); 
 393     else if ( !m_menu 
&& hadMenu 
) 
 395         m_searchButton
->SetBitmapLabel(m_searchBitmap
); 
 396         if ( m_searchButtonVisible 
) 
 398             m_searchButton
->Refresh(); 
 401     wxRect rect 
= GetRect(); 
 402     LayoutControls(0, 0, rect
.GetWidth(), rect
.GetHeight()); 
 405 wxMenu
* wxSearchCtrl::GetMenu() 
 410 #endif // wxUSE_MENUS 
 412 void wxSearchCtrl::ShowSearchButton( bool show 
) 
 414     if ( m_searchButtonVisible 
== show 
) 
 419     m_searchButtonVisible 
= show
; 
 420     if ( m_searchButtonVisible 
) 
 425     wxRect rect 
= GetRect(); 
 426     LayoutControls(0, 0, rect
.GetWidth(), rect
.GetHeight()); 
 429 bool wxSearchCtrl::IsSearchButtonVisible() const 
 431     return m_searchButtonVisible
; 
 435 void wxSearchCtrl::ShowCancelButton( bool show 
) 
 437     if ( m_cancelButtonVisible 
== show 
) 
 442     m_cancelButtonVisible 
= show
; 
 444     wxRect rect 
= GetRect(); 
 445     LayoutControls(0, 0, rect
.GetWidth(), rect
.GetHeight()); 
 448 bool wxSearchCtrl::IsCancelButtonVisible() const 
 450     return m_cancelButtonVisible
; 
 453 void wxSearchCtrl::SetDescriptiveText(const wxString
& text
) 
 455     m_text
->SetDescriptiveText(text
); 
 458 wxString 
wxSearchCtrl::GetDescriptiveText() const 
 460     return m_text
->GetDescriptiveText(); 
 463 // ---------------------------------------------------------------------------- 
 465 // ---------------------------------------------------------------------------- 
 467 wxSize 
wxSearchCtrl::DoGetBestSize() const 
 469     wxSize sizeText 
= m_text
->GetBestSize(); 
 470     wxSize 
sizeSearch(0,0); 
 471     wxSize 
sizeCancel(0,0); 
 472     int searchMargin 
= 0; 
 473     int cancelMargin 
= 0; 
 474     if ( m_searchButtonVisible 
|| HasMenu() ) 
 476         sizeSearch 
= m_searchButton
->GetBestSize(); 
 477         searchMargin 
= MARGIN
; 
 479     if ( m_cancelButtonVisible 
) 
 481         sizeCancel 
= m_cancelButton
->GetBestSize(); 
 482         cancelMargin 
= MARGIN
; 
 485     int horizontalBorder 
= 1 + ( sizeText
.y 
- sizeText
.y 
* 14 / 21 ) / 2; 
 487     // buttons are square and equal to the height of the text control 
 488     int height 
= sizeText
.y
; 
 489     return wxSize(sizeSearch
.x 
+ searchMargin 
+ sizeText
.x 
+ cancelMargin 
+ sizeCancel
.x 
+ 2*horizontalBorder
, 
 493 void wxSearchCtrl::DoMoveWindow(int x
, int y
, int width
, int height
) 
 495     wxSearchCtrlBase::DoMoveWindow(x
, y
, width
, height
); 
 497     LayoutControls(0, 0, width
, height
); 
 500 void wxSearchCtrl::LayoutControls(int x
, int y
, int width
, int height
) 
 505     wxSize sizeText 
= m_text
->GetBestSize(); 
 506     // make room for the search menu & clear button 
 507     int horizontalBorder 
= ( sizeText
.y 
- sizeText
.y 
* 14 / 21 ) / 2; 
 508     x 
+= horizontalBorder
; 
 510     width 
-= horizontalBorder
*2; 
 513     wxSize 
sizeSearch(0,0); 
 514     wxSize 
sizeCancel(0,0); 
 515     int searchMargin 
= 0; 
 516     int cancelMargin 
= 0; 
 517     if ( m_searchButtonVisible 
|| HasMenu() ) 
 519         sizeSearch 
= m_searchButton
->GetBestSize(); 
 520         searchMargin 
= MARGIN
; 
 522     if ( m_cancelButtonVisible 
) 
 524         sizeCancel 
= m_cancelButton
->GetBestSize(); 
 525         cancelMargin 
= MARGIN
; 
 527     m_searchButton
->Show( m_searchButtonVisible 
|| HasMenu() ); 
 528     m_cancelButton
->Show( m_cancelButtonVisible 
); 
 530     if ( sizeSearch
.x 
+ sizeCancel
.x 
> width 
) 
 532         sizeSearch
.x 
= width
/2; 
 533         sizeCancel
.x 
= width
/2; 
 537     wxCoord textWidth 
= width 
- sizeSearch
.x 
- sizeCancel
.x 
- searchMargin 
- cancelMargin
; 
 539     // position the subcontrols inside the client area 
 541     m_searchButton
->SetSize(x
, y 
+ ICON_OFFSET 
- 1, sizeSearch
.x
, height
); 
 542     m_text
->SetSize( x 
+ sizeSearch
.x 
+ searchMargin
, 
 543                      y 
+ ICON_OFFSET 
- BORDER
, 
 546     m_cancelButton
->SetSize(x 
+ sizeSearch
.x 
+ searchMargin 
+ textWidth 
+ cancelMargin
, 
 547                             y 
+ ICON_OFFSET 
- 1, sizeCancel
.x
, height
); 
 554 wxString 
wxSearchCtrl::GetValue() const 
 556     wxString value 
= m_text
->GetValue(); 
 557     if (value 
== m_text
->GetDescriptiveText()) 
 558         return wxEmptyString
; 
 562 void wxSearchCtrl::SetValue(const wxString
& value
) 
 564     m_text
->SetValue(value
); 
 567 wxString 
wxSearchCtrl::GetRange(long from
, long to
) const 
 569     return m_text
->GetRange(from
, to
); 
 572 int wxSearchCtrl::GetLineLength(long lineNo
) const 
 574     return m_text
->GetLineLength(lineNo
); 
 576 wxString 
wxSearchCtrl::GetLineText(long lineNo
) const 
 578     return m_text
->GetLineText(lineNo
); 
 580 int wxSearchCtrl::GetNumberOfLines() const 
 582     return m_text
->GetNumberOfLines(); 
 585 bool wxSearchCtrl::IsModified() const 
 587     return m_text
->IsModified(); 
 589 bool wxSearchCtrl::IsEditable() const 
 591     return m_text
->IsEditable(); 
 594 // more readable flag testing methods 
 595 bool wxSearchCtrl::IsSingleLine() const 
 597     return m_text
->IsSingleLine(); 
 599 bool wxSearchCtrl::IsMultiLine() const 
 601     return m_text
->IsMultiLine(); 
 604 // If the return values from and to are the same, there is no selection. 
 605 void wxSearchCtrl::GetSelection(long* from
, long* to
) const 
 607     m_text
->GetSelection(from
, to
); 
 610 wxString 
wxSearchCtrl::GetStringSelection() const 
 612     return m_text
->GetStringSelection(); 
 619 void wxSearchCtrl::Clear() 
 623 void wxSearchCtrl::Replace(long from
, long to
, const wxString
& value
) 
 625     m_text
->Replace(from
, to
, value
); 
 627 void wxSearchCtrl::Remove(long from
, long to
) 
 629     m_text
->Remove(from
, to
); 
 632 // load/save the controls contents from/to the file 
 633 bool wxSearchCtrl::LoadFile(const wxString
& file
) 
 635     return m_text
->LoadFile(file
); 
 637 bool wxSearchCtrl::SaveFile(const wxString
& file
) 
 639     return m_text
->SaveFile(file
); 
 642 // sets/clears the dirty flag 
 643 void wxSearchCtrl::MarkDirty() 
 647 void wxSearchCtrl::DiscardEdits() 
 649     m_text
->DiscardEdits(); 
 652 // set the max number of characters which may be entered in a single line 
 654 void wxSearchCtrl::SetMaxLength(unsigned long len
) 
 656     m_text
->SetMaxLength(len
); 
 659 // writing text inserts it at the current position, appending always 
 660 // inserts it at the end 
 661 void wxSearchCtrl::WriteText(const wxString
& text
) 
 663     m_text
->WriteText(text
); 
 665 void wxSearchCtrl::AppendText(const wxString
& text
) 
 667     m_text
->AppendText(text
); 
 670 // insert the character which would have resulted from this key event, 
 671 // return true if anything has been inserted 
 672 bool wxSearchCtrl::EmulateKeyPress(const wxKeyEvent
& event
) 
 674     return m_text
->EmulateKeyPress(event
); 
 677 // text control under some platforms supports the text styles: these 
 678 // methods allow to apply the given text style to the given selection or to 
 679 // set/get the style which will be used for all appended text 
 680 bool wxSearchCtrl::SetStyle(long start
, long end
, const wxTextAttr
& style
) 
 682     return m_text
->SetStyle(start
, end
, style
); 
 684 bool wxSearchCtrl::GetStyle(long position
, wxTextAttr
& style
) 
 686     return m_text
->GetStyle(position
, style
); 
 688 bool wxSearchCtrl::SetDefaultStyle(const wxTextAttr
& style
) 
 690     return m_text
->SetDefaultStyle(style
); 
 692 const wxTextAttr
& wxSearchCtrl::GetDefaultStyle() const 
 694     return m_text
->GetDefaultStyle(); 
 697 // translate between the position (which is just an index in the text ctrl 
 698 // considering all its contents as a single strings) and (x, y) coordinates 
 699 // which represent column and line. 
 700 long wxSearchCtrl::XYToPosition(long x
, long y
) const 
 702     return m_text
->XYToPosition(x
, y
); 
 704 bool wxSearchCtrl::PositionToXY(long pos
, long *x
, long *y
) const 
 706     return m_text
->PositionToXY(pos
, x
, y
); 
 709 void wxSearchCtrl::ShowPosition(long pos
) 
 711     m_text
->ShowPosition(pos
); 
 714 // find the character at position given in pixels 
 716 // NB: pt is in device coords (not adjusted for the client area origin nor 
 718 wxTextCtrlHitTestResult 
wxSearchCtrl::HitTest(const wxPoint
& pt
, long *pos
) const 
 720     return m_text
->HitTest(pt
, pos
); 
 722 wxTextCtrlHitTestResult 
wxSearchCtrl::HitTest(const wxPoint
& pt
, 
 724                                         wxTextCoord 
*row
) const 
 726     return m_text
->HitTest(pt
, col
, row
); 
 729 // Clipboard operations 
 730 void wxSearchCtrl::Copy() 
 734 void wxSearchCtrl::Cut() 
 738 void wxSearchCtrl::Paste() 
 743 bool wxSearchCtrl::CanCopy() const 
 745     return m_text
->CanCopy(); 
 747 bool wxSearchCtrl::CanCut() const 
 749     return m_text
->CanCut(); 
 751 bool wxSearchCtrl::CanPaste() const 
 753     return m_text
->CanPaste(); 
 757 void wxSearchCtrl::Undo() 
 761 void wxSearchCtrl::Redo() 
 766 bool wxSearchCtrl::CanUndo() const 
 768     return m_text
->CanUndo(); 
 770 bool wxSearchCtrl::CanRedo() const 
 772     return m_text
->CanRedo(); 
 776 void wxSearchCtrl::SetInsertionPoint(long pos
) 
 778     m_text
->SetInsertionPoint(pos
); 
 780 void wxSearchCtrl::SetInsertionPointEnd() 
 782     m_text
->SetInsertionPointEnd(); 
 784 long wxSearchCtrl::GetInsertionPoint() const 
 786     return m_text
->GetInsertionPoint(); 
 788 wxTextPos 
wxSearchCtrl::GetLastPosition() const 
 790     return m_text
->GetLastPosition(); 
 793 void wxSearchCtrl::SetSelection(long from
, long to
) 
 795     m_text
->SetSelection(from
, to
); 
 797 void wxSearchCtrl::SelectAll() 
 802 void wxSearchCtrl::SetEditable(bool editable
) 
 804     m_text
->SetEditable(editable
); 
 807 bool wxSearchCtrl::SetFont(const wxFont
& font
) 
 809     bool result 
= wxSearchCtrlBase::SetFont(font
); 
 810     if ( result 
&& m_text 
) 
 812         result 
= m_text
->SetFont(font
); 
 818 // search control generic only 
 819 void wxSearchCtrl::SetSearchBitmap( const wxBitmap
& bitmap 
) 
 821     m_searchBitmap 
= bitmap
; 
 822     m_searchBitmapUser 
= bitmap
.Ok(); 
 823     if ( m_searchBitmapUser 
) 
 825         if ( m_searchButton 
&& !HasMenu() ) 
 827             m_searchButton
->SetBitmapLabel( m_searchBitmap 
); 
 832         // the user bitmap was just cleared, generate one 
 839 void wxSearchCtrl::SetSearchMenuBitmap( const wxBitmap
& bitmap 
) 
 841     m_searchMenuBitmap 
= bitmap
; 
 842     m_searchMenuBitmapUser 
= bitmap
.Ok(); 
 843     if ( m_searchMenuBitmapUser 
) 
 845         if ( m_searchButton 
&& m_menu 
) 
 847             m_searchButton
->SetBitmapLabel( m_searchMenuBitmap 
); 
 852         // the user bitmap was just cleared, generate one 
 857 #endif // wxUSE_MENUS 
 859 void wxSearchCtrl::SetCancelBitmap( const wxBitmap
& bitmap 
) 
 861     m_cancelBitmap 
= bitmap
; 
 862     m_cancelBitmapUser 
= bitmap
.Ok(); 
 863     if ( m_cancelBitmapUser 
) 
 865         if ( m_cancelButton 
) 
 867             m_cancelButton
->SetBitmapLabel( m_cancelBitmap 
); 
 872         // the user bitmap was just cleared, generate one 
 879 // override streambuf method 
 880 #if wxHAS_TEXT_WINDOW_STREAM 
 882 #endif // wxHAS_TEXT_WINDOW_STREAM 
 884 // stream-like insertion operators: these are always available, whether we 
 885 // were, or not, compiled with streambuf support 
 886 wxTextCtrl
& operator<<(const wxString
& s
); 
 887 wxTextCtrl
& operator<<(int i
); 
 888 wxTextCtrl
& operator<<(long i
); 
 889 wxTextCtrl
& operator<<(float f
); 
 890 wxTextCtrl
& operator<<(double d
); 
 891 wxTextCtrl
& operator<<(const wxChar c
); 
 894 void wxSearchCtrl::DoSetValue(const wxString
& value
, int flags
) 
 896     m_text
->ChangeValue( value 
); 
 897     if ( flags 
& SetValue_SendEvent 
) 
 898         SendTextUpdatedEvent(); 
 901 // do the window-specific processing after processing the update event 
 902 void wxSearchCtrl::DoUpdateWindowUI(wxUpdateUIEvent
& event
) 
 904     wxSearchCtrlBase::DoUpdateWindowUI(event
); 
 907 bool wxSearchCtrl::ShouldInheritColours() const 
 912 // icons are rendered at 3-8 times larger than necessary and downscaled for 
 914 static int GetMultiplier() 
 917     // speed up bitmap generation by using a small bitmap 
 920     int depth 
= ::wxDisplayDepth(); 
 930 wxBitmap 
wxSearchCtrl::RenderSearchBitmap( int x
, int y
, bool renderDrop 
) 
 932     wxColour bg 
= GetBackgroundColour(); 
 933     wxColour fg 
= wxStepColour(GetForegroundColour(), LIGHT_STEP
-20); 
 935     //=============================================================================== 
 936     // begin drawing code 
 937     //=============================================================================== 
 940     // force width:height ratio 
 952     // glass 11x11, top left corner 
 953     // handle (9,9)-(13,13) 
 954     // drop (13,16)-(19,6)-(16,9) 
 956     int multiplier 
= GetMultiplier(); 
 957     int penWidth 
= multiplier 
* 2; 
 959     penWidth 
= penWidth 
* x 
/ 20; 
 961     wxBitmap 
bitmap( multiplier
*x
, multiplier
*y 
); 
 963     mem
.SelectObject(bitmap
); 
 966     mem
.SetBrush( wxBrush(bg
) ); 
 967     mem
.SetPen( wxPen(bg
) ); 
 968     mem
.DrawRectangle(0,0,bitmap
.GetWidth(),bitmap
.GetHeight()); 
 971     mem
.SetBrush( wxBrush(fg
) ); 
 972     mem
.SetPen( wxPen(fg
) ); 
 973     int glassBase 
= 5 * x 
/ 20; 
 974     int glassFactor 
= 2*glassBase 
+ 1; 
 975     int radius 
= multiplier
*glassFactor
/2; 
 976     mem
.DrawCircle(radius
,radius
,radius
); 
 977     mem
.SetBrush( wxBrush(bg
) ); 
 978     mem
.SetPen( wxPen(bg
) ); 
 979     mem
.DrawCircle(radius
,radius
,radius
-penWidth
); 
 982     int lineStart 
= radius 
+ (radius
-penWidth
/2) * 707 / 1000; // 707 / 1000 = 0.707 = 1/sqrt(2); 
 984     mem
.SetPen( wxPen(fg
) ); 
 985     mem
.SetBrush( wxBrush(fg
) ); 
 986     int handleCornerShift 
= penWidth 
* 707 / 1000 / 2; // 707 / 1000 = 0.707 = 1/sqrt(2); 
 987     handleCornerShift 
= WXMAX( handleCornerShift
, 1 ); 
 988     int handleBase 
= 4 * x 
/ 20; 
 989     int handleLength 
= 2*handleBase
+1; 
 990     wxPoint handlePolygon
[] = 
 992         wxPoint(-handleCornerShift
,+handleCornerShift
), 
 993         wxPoint(+handleCornerShift
,-handleCornerShift
), 
 994         wxPoint(multiplier
*handleLength
/2+handleCornerShift
,multiplier
*handleLength
/2-handleCornerShift
), 
 995         wxPoint(multiplier
*handleLength
/2-handleCornerShift
,multiplier
*handleLength
/2+handleCornerShift
), 
 997     mem
.DrawPolygon(WXSIZEOF(handlePolygon
),handlePolygon
,lineStart
,lineStart
); 
 999     // draw drop triangle 
1000     int triangleX 
= 13 * x 
/ 20; 
1001     int triangleY 
= 5 * x 
/ 20; 
1002     int triangleBase 
= 3 * x 
/ 20; 
1003     int triangleFactor 
= triangleBase
*2+1; 
1006         wxPoint dropPolygon
[] = 
1008             wxPoint(multiplier
*0,multiplier
*0), // triangle left 
1009             wxPoint(multiplier
*triangleFactor
-1,multiplier
*0), // triangle right 
1010             wxPoint(multiplier
*triangleFactor
/2,multiplier
*triangleFactor
/2), // triangle bottom 
1012         mem
.DrawPolygon(WXSIZEOF(dropPolygon
),dropPolygon
,multiplier
*triangleX
,multiplier
*triangleY
); 
1014     mem
.SelectObject(wxNullBitmap
); 
1016     //=============================================================================== 
1018     //=============================================================================== 
1020     if ( multiplier 
!= 1 ) 
1022         wxImage image 
= bitmap
.ConvertToImage(); 
1024         bitmap 
= wxBitmap( image 
); 
1028         // Trim the edge where the arrow would have gone 
1029         bitmap 
= bitmap
.GetSubBitmap(wxRect(0,0, y
,y
)); 
1035 wxBitmap 
wxSearchCtrl::RenderCancelBitmap( int x
, int y 
) 
1037     wxColour bg 
= GetBackgroundColour(); 
1038     wxColour fg 
= wxStepColour(GetForegroundColour(), LIGHT_STEP
); 
1040     //=============================================================================== 
1041     // begin drawing code 
1042     //=============================================================================== 
1059     // cross line starts (4,4)-(10,10) 
1060     // drop (13,16)-(19,6)-(16,9) 
1062     int multiplier 
= GetMultiplier(); 
1064     int penWidth 
= multiplier 
* x 
/ 14; 
1066     wxBitmap 
bitmap( multiplier
*x
, multiplier
*y 
); 
1068     mem
.SelectObject(bitmap
); 
1071     mem
.SetBrush( wxBrush(bg
) ); 
1072     mem
.SetPen( wxPen(bg
) ); 
1073     mem
.DrawRectangle(0,0,bitmap
.GetWidth(),bitmap
.GetHeight()); 
1076     mem
.SetBrush( wxBrush(fg
) ); 
1077     mem
.SetPen( wxPen(fg
) ); 
1078     int radius 
= multiplier
*x
/2; 
1079     mem
.DrawCircle(radius
,radius
,radius
); 
1082     int lineStartBase 
= 4 * x 
/ 14; 
1083     int lineLength 
= x 
- 2*lineStartBase
; 
1085     mem
.SetPen( wxPen(bg
) ); 
1086     mem
.SetBrush( wxBrush(bg
) ); 
1087     int handleCornerShift 
= penWidth
/2; 
1088     handleCornerShift 
= WXMAX( handleCornerShift
, 1 ); 
1089     wxPoint handlePolygon
[] = 
1091         wxPoint(-handleCornerShift
,+handleCornerShift
), 
1092         wxPoint(+handleCornerShift
,-handleCornerShift
), 
1093         wxPoint(multiplier
*lineLength
+handleCornerShift
,multiplier
*lineLength
-handleCornerShift
), 
1094         wxPoint(multiplier
*lineLength
-handleCornerShift
,multiplier
*lineLength
+handleCornerShift
), 
1096     mem
.DrawPolygon(WXSIZEOF(handlePolygon
),handlePolygon
,multiplier
*lineStartBase
,multiplier
*lineStartBase
); 
1097     wxPoint handlePolygon2
[] = 
1099         wxPoint(+handleCornerShift
,+handleCornerShift
), 
1100         wxPoint(-handleCornerShift
,-handleCornerShift
), 
1101         wxPoint(multiplier
*lineLength
-handleCornerShift
,-multiplier
*lineLength
-handleCornerShift
), 
1102         wxPoint(multiplier
*lineLength
+handleCornerShift
,-multiplier
*lineLength
+handleCornerShift
), 
1104     mem
.DrawPolygon(WXSIZEOF(handlePolygon2
),handlePolygon2
,multiplier
*lineStartBase
,multiplier
*(x
-lineStartBase
)); 
1106     //=============================================================================== 
1108     //=============================================================================== 
1110     if ( multiplier 
!= 1 ) 
1112         wxImage image 
= bitmap
.ConvertToImage(); 
1114         bitmap 
= wxBitmap( image 
); 
1120 void wxSearchCtrl::RecalcBitmaps() 
1126     wxSize sizeText 
= m_text
->GetBestSize(); 
1128     int bitmapHeight 
= sizeText
.y 
- 2 * ICON_MARGIN
; 
1129     int bitmapWidth  
= sizeText
.y 
* 20 / 14; 
1131     if ( !m_searchBitmapUser 
) 
1134             !m_searchBitmap
.Ok() || 
1135             m_searchBitmap
.GetHeight() != bitmapHeight 
|| 
1136             m_searchBitmap
.GetWidth() != bitmapWidth
 
1139             m_searchBitmap 
= RenderSearchBitmap(bitmapWidth
,bitmapHeight
,false); 
1142                 m_searchButton
->SetBitmapLabel(m_searchBitmap
); 
1145         // else this bitmap was set by user, don't alter 
1149     if ( !m_searchMenuBitmapUser 
) 
1152             !m_searchMenuBitmap
.Ok() || 
1153             m_searchMenuBitmap
.GetHeight() != bitmapHeight 
|| 
1154             m_searchMenuBitmap
.GetWidth() != bitmapWidth
 
1157             m_searchMenuBitmap 
= RenderSearchBitmap(bitmapWidth
,bitmapHeight
,true); 
1160                 m_searchButton
->SetBitmapLabel(m_searchMenuBitmap
); 
1163         // else this bitmap was set by user, don't alter 
1165 #endif // wxUSE_MENUS 
1167     if ( !m_cancelBitmapUser 
) 
1170             !m_cancelBitmap
.Ok() || 
1171             m_cancelBitmap
.GetHeight() != bitmapHeight 
|| 
1172             m_cancelBitmap
.GetWidth() != bitmapHeight
 
1175             m_cancelBitmap 
= RenderCancelBitmap(bitmapHeight
-BORDER
,bitmapHeight
-BORDER
); // square 
1176             m_cancelButton
->SetBitmapLabel(m_cancelBitmap
); 
1178         // else this bitmap was set by user, don't alter 
1182 void wxSearchCtrl::OnSearchButton( wxCommandEvent
& event 
) 
1187 void wxSearchCtrl::OnSetFocus( wxFocusEvent
& /*event*/ ) 
1195 void wxSearchCtrl::OnSize( wxSizeEvent
& WXUNUSED(event
) ) 
1198     GetSize(&width
, &height
); 
1199     LayoutControls(0, 0, width
, height
); 
1204 void wxSearchCtrl::PopupSearchMenu() 
1208         wxSize size 
= GetSize(); 
1209         PopupMenu( m_menu
, 0, size
.y 
); 
1213 #endif // wxUSE_MENUS 
1215 #endif // !wxUSE_NATIVE_SEARCH_CONTROL 
1217 #endif // wxUSE_SEARCHCTRL