1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/srchctlg.cpp
3 // Purpose: implements wxSearchCtrl as a composite control
4 // Author: Vince Harron
7 // Copyright: Vince Harron
8 // Licence: 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 #define LIGHT_STEP 160
55 // ----------------------------------------------------------------------------
56 // wxSearchTextCtrl: text control used by search control
57 // ----------------------------------------------------------------------------
59 class wxSearchTextCtrl
: public wxTextCtrl
62 wxSearchTextCtrl(wxSearchCtrl
*search
, const wxString
& value
, int style
)
63 : wxTextCtrl(search
, wxID_ANY
, value
, wxDefaultPosition
, wxDefaultSize
,
64 (style
& ~wxBORDER_MASK
) | wxNO_BORDER
)
70 // Ensure that our best size is recomputed using our overridden
76 // provide access to the base class protected methods to wxSearchCtrl which
77 // needs to forward to them
78 void DoSetValue(const wxString
& value
, int flags
)
80 wxTextCtrl::DoSetValue(value
, flags
);
83 bool DoLoadFile(const wxString
& file
, int fileType
)
85 return wxTextCtrl::DoLoadFile(file
, fileType
);
88 bool DoSaveFile(const wxString
& file
, int fileType
)
90 return wxTextCtrl::DoSaveFile(file
, fileType
);
94 void OnText(wxCommandEvent
& eventText
)
96 wxCommandEvent
event(eventText
);
97 event
.SetEventObject(m_search
);
98 event
.SetId(m_search
->GetId());
100 m_search
->GetEventHandler()->ProcessEvent(event
);
103 void OnTextUrl(wxTextUrlEvent
& eventText
)
105 // copy constructor is disabled for some reason?
106 //wxTextUrlEvent event(eventText);
107 wxTextUrlEvent
event(
109 eventText
.GetMouseEvent(),
110 eventText
.GetURLStart(),
111 eventText
.GetURLEnd()
113 event
.SetEventObject(m_search
);
115 m_search
->GetEventHandler()->ProcessEvent(event
);
119 // We increase the text control height to be the same as for the controls
120 // with border as this is what we actually need here because even though
121 // this control itself is borderless, it's inside wxSearchCtrl which does
122 // have the border and so should have the same height as the normal text
123 // entries with border.
125 // This is a bit ugly and it would arguably be better to use whatever size
126 // the base class version returns and just centre the text vertically in
127 // the search control but I failed to modify the code in LayoutControls()
128 // to do this easily and as there is much in that code I don't understand
129 // (notably what is the logic for buttons sizing?) I prefer to not touch it
131 virtual wxSize
DoGetBestSize() const
133 const long flags
= GetWindowStyleFlag();
134 wxSearchTextCtrl
* const self
= const_cast<wxSearchTextCtrl
*>(this);
136 self
->SetWindowStyleFlag((flags
& ~wxBORDER_MASK
) | wxBORDER_DEFAULT
);
137 const wxSize size
= wxTextCtrl::DoGetBestSize();
138 self
->SetWindowStyleFlag(flags
);
145 wxSearchCtrl
* m_search
;
147 DECLARE_EVENT_TABLE()
150 BEGIN_EVENT_TABLE(wxSearchTextCtrl
, wxTextCtrl
)
151 EVT_TEXT(wxID_ANY
, wxSearchTextCtrl::OnText
)
152 EVT_TEXT_ENTER(wxID_ANY
, wxSearchTextCtrl::OnText
)
153 EVT_TEXT_URL(wxID_ANY
, wxSearchTextCtrl::OnTextUrl
)
154 EVT_TEXT_MAXLEN(wxID_ANY
, wxSearchTextCtrl::OnText
)
157 // ----------------------------------------------------------------------------
158 // wxSearchButton: search button used by search control
159 // ----------------------------------------------------------------------------
161 class wxSearchButton
: public wxControl
164 wxSearchButton(wxSearchCtrl
*search
, int eventType
, const wxBitmap
& bmp
)
165 : wxControl(search
, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, wxNO_BORDER
),
167 m_eventType(eventType
),
171 void SetBitmapLabel(const wxBitmap
& label
) { m_bmp
= label
; }
173 // The buttons in wxSearchCtrl shouldn't accept focus from keyboard because
174 // this would interfere with the usual TAB processing: the user expects
175 // that pressing TAB in the search control should switch focus to the next
176 // control and not give it to the button inside the same control. Besides,
177 // the search button can be already activated by pressing "Enter" so there
178 // is really no reason for it to be able to get focus from keyboard.
179 virtual bool AcceptsFocusFromKeyboard() const { return false; }
182 wxSize
DoGetBestSize() const
184 return wxSize(m_bmp
.GetWidth(), m_bmp
.GetHeight());
187 void OnLeftUp(wxMouseEvent
&)
189 wxCommandEvent
event(m_eventType
, m_search
->GetId());
190 event
.SetEventObject(m_search
);
192 if ( m_eventType
== wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN
)
194 // it's convenient to have the string to search for directly in the
195 // event instead of having to retrieve it from the control in the
196 // event handler code later, so provide it here
197 event
.SetString(m_search
->GetValue());
200 GetEventHandler()->ProcessEvent(event
);
202 m_search
->SetFocus();
205 if ( m_eventType
== wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN
)
207 // this happens automatically, just like on Mac OS X
208 m_search
->PopupSearchMenu();
210 #endif // wxUSE_MENUS
213 void OnPaint(wxPaintEvent
&)
216 dc
.DrawBitmap(m_bmp
, 0,0, true);
221 wxSearchCtrl
*m_search
;
222 wxEventType m_eventType
;
225 DECLARE_EVENT_TABLE()
228 BEGIN_EVENT_TABLE(wxSearchButton
, wxControl
)
229 EVT_LEFT_UP(wxSearchButton::OnLeftUp
)
230 EVT_PAINT(wxSearchButton::OnPaint
)
233 BEGIN_EVENT_TABLE(wxSearchCtrl
, wxSearchCtrlBase
)
234 EVT_SEARCHCTRL_SEARCH_BTN(wxID_ANY
, wxSearchCtrl::OnSearchButton
)
235 EVT_SET_FOCUS(wxSearchCtrl::OnSetFocus
)
236 EVT_SIZE(wxSearchCtrl::OnSize
)
239 IMPLEMENT_DYNAMIC_CLASS(wxSearchCtrl
, wxSearchCtrlBase
)
241 // ============================================================================
243 // ============================================================================
245 // ----------------------------------------------------------------------------
246 // wxSearchCtrl creation
247 // ----------------------------------------------------------------------------
252 wxSearchCtrl::wxSearchCtrl()
257 wxSearchCtrl::wxSearchCtrl(wxWindow
*parent
, wxWindowID id
,
258 const wxString
& value
,
262 const wxValidator
& validator
,
263 const wxString
& name
)
267 Create(parent
, id
, value
, pos
, size
, style
, validator
, name
);
270 void wxSearchCtrl::Init()
273 m_searchButton
= NULL
;
274 m_cancelButton
= NULL
;
277 #endif // wxUSE_MENUS
279 m_searchButtonVisible
= true;
280 m_cancelButtonVisible
= false;
282 m_searchBitmapUser
= false;
283 m_cancelBitmapUser
= false;
285 m_searchMenuBitmapUser
= false;
286 #endif // wxUSE_MENUS
289 bool wxSearchCtrl::Create(wxWindow
*parent
, wxWindowID id
,
290 const wxString
& value
,
294 const wxValidator
& validator
,
295 const wxString
& name
)
297 // force border style for more native appearance
298 style
&= ~wxBORDER_MASK
;
300 style
|= wxBORDER_SUNKEN
;
301 #elif defined(__WXMSW__)
302 // Don't set the style explicitly, let GetDefaultBorder() work it out, unless
303 // we will get a sunken border (e.g. on Windows 200) in which case we must
304 // override with a simple border.
305 if (GetDefaultBorder() == wxBORDER_SUNKEN
)
306 style
|= wxBORDER_SIMPLE
;
308 style
|= wxBORDER_SIMPLE
;
310 if ( !wxSearchCtrlBaseBaseClass::Create(parent
, id
, pos
, size
,
311 style
, validator
, name
) )
316 m_text
= new wxSearchTextCtrl(this, value
, style
);
318 m_searchButton
= new wxSearchButton(this,
319 wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN
,
321 m_cancelButton
= new wxSearchButton(this,
322 wxEVT_COMMAND_SEARCHCTRL_CANCEL_BTN
,
325 SetForegroundColour( m_text
->GetForegroundColour() );
326 SetBackgroundColour( m_text
->GetBackgroundColour() );
330 SetInitialSize(size
);
335 wxSearchCtrl::~wxSearchCtrl()
338 delete m_searchButton
;
339 delete m_cancelButton
;
342 #endif // wxUSE_MENUS
346 // search control specific interfaces
349 void wxSearchCtrl::SetMenu( wxMenu
* menu
)
351 if ( menu
== m_menu
)
356 bool hadMenu
= (m_menu
!= NULL
);
360 if ( m_menu
&& !hadMenu
)
362 m_searchButton
->SetBitmapLabel(m_searchMenuBitmap
);
363 m_searchButton
->Refresh();
365 else if ( !m_menu
&& hadMenu
)
367 m_searchButton
->SetBitmapLabel(m_searchBitmap
);
368 if ( m_searchButtonVisible
)
370 m_searchButton
->Refresh();
373 wxRect rect
= GetRect();
374 LayoutControls(0, 0, rect
.GetWidth(), rect
.GetHeight());
377 wxMenu
* wxSearchCtrl::GetMenu()
382 #endif // wxUSE_MENUS
384 void wxSearchCtrl::ShowSearchButton( bool show
)
386 if ( m_searchButtonVisible
== show
)
391 m_searchButtonVisible
= show
;
392 if ( m_searchButtonVisible
)
397 wxRect rect
= GetRect();
398 LayoutControls(0, 0, rect
.GetWidth(), rect
.GetHeight());
401 bool wxSearchCtrl::IsSearchButtonVisible() const
403 return m_searchButtonVisible
;
407 void wxSearchCtrl::ShowCancelButton( bool show
)
409 if ( m_cancelButtonVisible
== show
)
414 m_cancelButtonVisible
= show
;
416 wxRect rect
= GetRect();
417 LayoutControls(0, 0, rect
.GetWidth(), rect
.GetHeight());
420 bool wxSearchCtrl::IsCancelButtonVisible() const
422 return m_cancelButtonVisible
;
425 void wxSearchCtrl::SetDescriptiveText(const wxString
& text
)
427 m_text
->SetHint(text
);
430 wxString
wxSearchCtrl::GetDescriptiveText() const
432 return m_text
->GetHint();
435 // ----------------------------------------------------------------------------
437 // ----------------------------------------------------------------------------
439 wxSize
wxSearchCtrl::DoGetBestSize() const
441 wxSize sizeText
= m_text
->GetBestSize();
442 wxSize
sizeSearch(0,0);
443 wxSize
sizeCancel(0,0);
444 int searchMargin
= 0;
445 int cancelMargin
= 0;
446 if ( m_searchButtonVisible
|| HasMenu() )
448 sizeSearch
= m_searchButton
->GetBestSize();
449 searchMargin
= MARGIN
;
451 if ( m_cancelButtonVisible
)
453 sizeCancel
= m_cancelButton
->GetBestSize();
454 cancelMargin
= MARGIN
;
457 int horizontalBorder
= 1 + ( sizeText
.y
- sizeText
.y
* 14 / 21 ) / 2;
459 // buttons are square and equal to the height of the text control
460 int height
= sizeText
.y
;
461 return wxSize(sizeSearch
.x
+ searchMargin
+ sizeText
.x
+ cancelMargin
+ sizeCancel
.x
+ 2*horizontalBorder
,
465 void wxSearchCtrl::DoMoveWindow(int x
, int y
, int width
, int height
)
467 wxSearchCtrlBase::DoMoveWindow(x
, y
, width
, height
);
469 LayoutControls(0, 0, width
, height
);
472 void wxSearchCtrl::LayoutControls(int x
, int y
, int width
, int height
)
477 wxSize sizeText
= m_text
->GetBestSize();
478 // make room for the search menu & clear button
479 int horizontalBorder
= ( sizeText
.y
- sizeText
.y
* 14 / 21 ) / 2;
480 x
+= horizontalBorder
;
482 width
-= horizontalBorder
*2;
484 if (width
< 0) width
= 0;
485 if (height
< 0) height
= 0;
487 wxSize
sizeSearch(0,0);
488 wxSize
sizeCancel(0,0);
489 int searchMargin
= 0;
490 int cancelMargin
= 0;
491 if ( m_searchButtonVisible
|| HasMenu() )
493 sizeSearch
= m_searchButton
->GetBestSize();
494 searchMargin
= MARGIN
;
496 if ( m_cancelButtonVisible
)
498 sizeCancel
= m_cancelButton
->GetBestSize();
499 cancelMargin
= MARGIN
;
501 m_searchButton
->Show( m_searchButtonVisible
|| HasMenu() );
502 m_cancelButton
->Show( m_cancelButtonVisible
);
504 if ( sizeSearch
.x
+ sizeCancel
.x
> width
)
506 sizeSearch
.x
= width
/2;
507 sizeCancel
.x
= width
/2;
511 wxCoord textWidth
= width
- sizeSearch
.x
- sizeCancel
.x
- searchMargin
- cancelMargin
- 1;
512 if (textWidth
< 0) textWidth
= 0;
514 // position the subcontrols inside the client area
516 m_searchButton
->SetSize(x
, y
+ ICON_OFFSET
- 1, sizeSearch
.x
, height
);
517 m_text
->SetSize( x
+ sizeSearch
.x
+ searchMargin
,
518 y
+ ICON_OFFSET
- BORDER
,
521 m_cancelButton
->SetSize(x
+ sizeSearch
.x
+ searchMargin
+ textWidth
+ cancelMargin
,
522 y
+ ICON_OFFSET
- 1, sizeCancel
.x
, height
);
525 wxWindowList
wxSearchCtrl::GetCompositeWindowParts() const
528 parts
.push_back(m_text
);
529 parts
.push_back(m_searchButton
);
530 parts
.push_back(m_cancelButton
);
537 wxString
wxSearchCtrl::DoGetValue() const
539 return m_text
->GetValue();
541 wxString
wxSearchCtrl::GetRange(long from
, long to
) const
543 return m_text
->GetRange(from
, to
);
546 int wxSearchCtrl::GetLineLength(long lineNo
) const
548 return m_text
->GetLineLength(lineNo
);
550 wxString
wxSearchCtrl::GetLineText(long lineNo
) const
552 return m_text
->GetLineText(lineNo
);
554 int wxSearchCtrl::GetNumberOfLines() const
556 return m_text
->GetNumberOfLines();
559 bool wxSearchCtrl::IsModified() const
561 return m_text
->IsModified();
563 bool wxSearchCtrl::IsEditable() const
565 return m_text
->IsEditable();
568 // more readable flag testing methods
569 bool wxSearchCtrl::IsSingleLine() const
571 return m_text
->IsSingleLine();
573 bool wxSearchCtrl::IsMultiLine() const
575 return m_text
->IsMultiLine();
578 // If the return values from and to are the same, there is no selection.
579 void wxSearchCtrl::GetSelection(long* from
, long* to
) const
581 m_text
->GetSelection(from
, to
);
584 wxString
wxSearchCtrl::GetStringSelection() const
586 return m_text
->GetStringSelection();
593 void wxSearchCtrl::Clear()
597 void wxSearchCtrl::Replace(long from
, long to
, const wxString
& value
)
599 m_text
->Replace(from
, to
, value
);
601 void wxSearchCtrl::Remove(long from
, long to
)
603 m_text
->Remove(from
, to
);
606 // load/save the controls contents from/to the file
607 bool wxSearchCtrl::LoadFile(const wxString
& file
)
609 return m_text
->LoadFile(file
);
611 bool wxSearchCtrl::SaveFile(const wxString
& file
)
613 return m_text
->SaveFile(file
);
616 // sets/clears the dirty flag
617 void wxSearchCtrl::MarkDirty()
621 void wxSearchCtrl::DiscardEdits()
623 m_text
->DiscardEdits();
626 // set the max number of characters which may be entered in a single line
628 void wxSearchCtrl::SetMaxLength(unsigned long len
)
630 m_text
->SetMaxLength(len
);
633 // writing text inserts it at the current position, appending always
634 // inserts it at the end
635 void wxSearchCtrl::WriteText(const wxString
& text
)
637 m_text
->WriteText(text
);
639 void wxSearchCtrl::AppendText(const wxString
& text
)
641 m_text
->AppendText(text
);
644 // insert the character which would have resulted from this key event,
645 // return true if anything has been inserted
646 bool wxSearchCtrl::EmulateKeyPress(const wxKeyEvent
& event
)
648 return m_text
->EmulateKeyPress(event
);
651 // text control under some platforms supports the text styles: these
652 // methods allow to apply the given text style to the given selection or to
653 // set/get the style which will be used for all appended text
654 bool wxSearchCtrl::SetStyle(long start
, long end
, const wxTextAttr
& style
)
656 return m_text
->SetStyle(start
, end
, style
);
658 bool wxSearchCtrl::GetStyle(long position
, wxTextAttr
& style
)
660 return m_text
->GetStyle(position
, style
);
662 bool wxSearchCtrl::SetDefaultStyle(const wxTextAttr
& style
)
664 return m_text
->SetDefaultStyle(style
);
666 const wxTextAttr
& wxSearchCtrl::GetDefaultStyle() const
668 return m_text
->GetDefaultStyle();
671 // translate between the position (which is just an index in the text ctrl
672 // considering all its contents as a single strings) and (x, y) coordinates
673 // which represent column and line.
674 long wxSearchCtrl::XYToPosition(long x
, long y
) const
676 return m_text
->XYToPosition(x
, y
);
678 bool wxSearchCtrl::PositionToXY(long pos
, long *x
, long *y
) const
680 return m_text
->PositionToXY(pos
, x
, y
);
683 void wxSearchCtrl::ShowPosition(long pos
)
685 m_text
->ShowPosition(pos
);
688 // find the character at position given in pixels
690 // NB: pt is in device coords (not adjusted for the client area origin nor
692 wxTextCtrlHitTestResult
wxSearchCtrl::HitTest(const wxPoint
& pt
, long *pos
) const
694 return m_text
->HitTest(pt
, pos
);
696 wxTextCtrlHitTestResult
wxSearchCtrl::HitTest(const wxPoint
& pt
,
698 wxTextCoord
*row
) const
700 return m_text
->HitTest(pt
, col
, row
);
703 // Clipboard operations
704 void wxSearchCtrl::Copy()
708 void wxSearchCtrl::Cut()
712 void wxSearchCtrl::Paste()
717 bool wxSearchCtrl::CanCopy() const
719 return m_text
->CanCopy();
721 bool wxSearchCtrl::CanCut() const
723 return m_text
->CanCut();
725 bool wxSearchCtrl::CanPaste() const
727 return m_text
->CanPaste();
731 void wxSearchCtrl::Undo()
735 void wxSearchCtrl::Redo()
740 bool wxSearchCtrl::CanUndo() const
742 return m_text
->CanUndo();
744 bool wxSearchCtrl::CanRedo() const
746 return m_text
->CanRedo();
750 void wxSearchCtrl::SetInsertionPoint(long pos
)
752 m_text
->SetInsertionPoint(pos
);
754 void wxSearchCtrl::SetInsertionPointEnd()
756 m_text
->SetInsertionPointEnd();
758 long wxSearchCtrl::GetInsertionPoint() const
760 return m_text
->GetInsertionPoint();
762 long wxSearchCtrl::GetLastPosition() const
764 return m_text
->GetLastPosition();
767 void wxSearchCtrl::SetSelection(long from
, long to
)
769 m_text
->SetSelection(from
, to
);
771 void wxSearchCtrl::SelectAll()
776 void wxSearchCtrl::SetEditable(bool editable
)
778 m_text
->SetEditable(editable
);
781 bool wxSearchCtrl::SetFont(const wxFont
& font
)
783 if ( !wxSearchCtrlBase::SetFont(font
) )
786 // Recreate the bitmaps as their size may have changed.
792 bool wxSearchCtrl::SetBackgroundColour(const wxColour
& colour
)
794 if ( !wxSearchCtrlBase::SetBackgroundColour(colour
) )
797 // When the background changes, re-render the bitmaps so that the correct
798 // colour shows in their "transparent" area.
804 // search control generic only
805 void wxSearchCtrl::SetSearchBitmap( const wxBitmap
& bitmap
)
807 m_searchBitmap
= bitmap
;
808 m_searchBitmapUser
= bitmap
.IsOk();
809 if ( m_searchBitmapUser
)
811 if ( m_searchButton
&& !HasMenu() )
813 m_searchButton
->SetBitmapLabel( m_searchBitmap
);
818 // the user bitmap was just cleared, generate one
825 void wxSearchCtrl::SetSearchMenuBitmap( const wxBitmap
& bitmap
)
827 m_searchMenuBitmap
= bitmap
;
828 m_searchMenuBitmapUser
= bitmap
.IsOk();
829 if ( m_searchMenuBitmapUser
)
831 if ( m_searchButton
&& m_menu
)
833 m_searchButton
->SetBitmapLabel( m_searchMenuBitmap
);
838 // the user bitmap was just cleared, generate one
843 #endif // wxUSE_MENUS
845 void wxSearchCtrl::SetCancelBitmap( const wxBitmap
& bitmap
)
847 m_cancelBitmap
= bitmap
;
848 m_cancelBitmapUser
= bitmap
.IsOk();
849 if ( m_cancelBitmapUser
)
851 if ( m_cancelButton
)
853 m_cancelButton
->SetBitmapLabel( m_cancelBitmap
);
858 // the user bitmap was just cleared, generate one
865 // override streambuf method
866 #if wxHAS_TEXT_WINDOW_STREAM
868 #endif // wxHAS_TEXT_WINDOW_STREAM
870 // stream-like insertion operators: these are always available, whether we
871 // were, or not, compiled with streambuf support
872 wxTextCtrl
& operator<<(const wxString
& s
);
873 wxTextCtrl
& operator<<(int i
);
874 wxTextCtrl
& operator<<(long i
);
875 wxTextCtrl
& operator<<(float f
);
876 wxTextCtrl
& operator<<(double d
);
877 wxTextCtrl
& operator<<(const wxChar c
);
880 void wxSearchCtrl::DoSetValue(const wxString
& value
, int flags
)
882 m_text
->DoSetValue(value
, flags
);
885 bool wxSearchCtrl::DoLoadFile(const wxString
& file
, int fileType
)
887 return m_text
->DoLoadFile(file
, fileType
);
890 bool wxSearchCtrl::DoSaveFile(const wxString
& file
, int fileType
)
892 return m_text
->DoSaveFile(file
, fileType
);
895 // do the window-specific processing after processing the update event
896 void wxSearchCtrl::DoUpdateWindowUI(wxUpdateUIEvent
& event
)
898 wxSearchCtrlBase::DoUpdateWindowUI(event
);
901 bool wxSearchCtrl::ShouldInheritColours() const
906 // icons are rendered at 3-8 times larger than necessary and downscaled for
908 static int GetMultiplier()
911 // speed up bitmap generation by using a small bitmap
914 int depth
= ::wxDisplayDepth();
924 wxBitmap
wxSearchCtrl::RenderSearchBitmap( int x
, int y
, bool renderDrop
)
926 wxColour bg
= GetBackgroundColour();
927 wxColour fg
= GetForegroundColour().ChangeLightness(LIGHT_STEP
-20);
929 //===============================================================================
930 // begin drawing code
931 //===============================================================================
934 // force width:height ratio
946 // glass 11x11, top left corner
947 // handle (9,9)-(13,13)
948 // drop (13,16)-(19,6)-(16,9)
950 int multiplier
= GetMultiplier();
951 int penWidth
= multiplier
* 2;
953 penWidth
= penWidth
* x
/ 20;
955 wxBitmap
bitmap( multiplier
*x
, multiplier
*y
);
957 mem
.SelectObject(bitmap
);
960 mem
.SetBrush( wxBrush(bg
) );
961 mem
.SetPen( wxPen(bg
) );
962 mem
.DrawRectangle(0,0,bitmap
.GetWidth(),bitmap
.GetHeight());
965 mem
.SetBrush( wxBrush(fg
) );
966 mem
.SetPen( wxPen(fg
) );
967 int glassBase
= 5 * x
/ 20;
968 int glassFactor
= 2*glassBase
+ 1;
969 int radius
= multiplier
*glassFactor
/2;
970 mem
.DrawCircle(radius
,radius
,radius
);
971 mem
.SetBrush( wxBrush(bg
) );
972 mem
.SetPen( wxPen(bg
) );
973 mem
.DrawCircle(radius
,radius
,radius
-penWidth
);
976 int lineStart
= radius
+ (radius
-penWidth
/2) * 707 / 1000; // 707 / 1000 = 0.707 = 1/sqrt(2);
978 mem
.SetPen( wxPen(fg
) );
979 mem
.SetBrush( wxBrush(fg
) );
980 int handleCornerShift
= penWidth
* 707 / 1000 / 2; // 707 / 1000 = 0.707 = 1/sqrt(2);
981 handleCornerShift
= WXMAX( handleCornerShift
, 1 );
982 int handleBase
= 4 * x
/ 20;
983 int handleLength
= 2*handleBase
+1;
984 wxPoint handlePolygon
[] =
986 wxPoint(-handleCornerShift
,+handleCornerShift
),
987 wxPoint(+handleCornerShift
,-handleCornerShift
),
988 wxPoint(multiplier
*handleLength
/2+handleCornerShift
,multiplier
*handleLength
/2-handleCornerShift
),
989 wxPoint(multiplier
*handleLength
/2-handleCornerShift
,multiplier
*handleLength
/2+handleCornerShift
),
991 mem
.DrawPolygon(WXSIZEOF(handlePolygon
),handlePolygon
,lineStart
,lineStart
);
993 // draw drop triangle
994 int triangleX
= 13 * x
/ 20;
995 int triangleY
= 5 * x
/ 20;
996 int triangleBase
= 3 * x
/ 20;
997 int triangleFactor
= triangleBase
*2+1;
1000 wxPoint dropPolygon
[] =
1002 wxPoint(multiplier
*0,multiplier
*0), // triangle left
1003 wxPoint(multiplier
*triangleFactor
-1,multiplier
*0), // triangle right
1004 wxPoint(multiplier
*triangleFactor
/2,multiplier
*triangleFactor
/2), // triangle bottom
1006 mem
.DrawPolygon(WXSIZEOF(dropPolygon
),dropPolygon
,multiplier
*triangleX
,multiplier
*triangleY
);
1008 mem
.SelectObject(wxNullBitmap
);
1010 //===============================================================================
1012 //===============================================================================
1014 if ( multiplier
!= 1 )
1016 wxImage image
= bitmap
.ConvertToImage();
1018 bitmap
= wxBitmap( image
);
1022 // Trim the edge where the arrow would have gone
1023 bitmap
= bitmap
.GetSubBitmap(wxRect(0,0, y
,y
));
1029 wxBitmap
wxSearchCtrl::RenderCancelBitmap( int x
, int y
)
1031 wxColour bg
= GetBackgroundColour();
1032 wxColour fg
= GetForegroundColour().ChangeLightness(LIGHT_STEP
);
1034 //===============================================================================
1035 // begin drawing code
1036 //===============================================================================
1053 // cross line starts (4,4)-(10,10)
1054 // drop (13,16)-(19,6)-(16,9)
1056 int multiplier
= GetMultiplier();
1058 int penWidth
= multiplier
* x
/ 14;
1060 wxBitmap
bitmap( multiplier
*x
, multiplier
*y
);
1062 mem
.SelectObject(bitmap
);
1065 mem
.SetBrush( wxBrush(bg
) );
1066 mem
.SetPen( wxPen(bg
) );
1067 mem
.DrawRectangle(0,0,bitmap
.GetWidth(),bitmap
.GetHeight());
1070 mem
.SetBrush( wxBrush(fg
) );
1071 mem
.SetPen( wxPen(fg
) );
1072 int radius
= multiplier
*x
/2;
1073 mem
.DrawCircle(radius
,radius
,radius
);
1076 int lineStartBase
= 4 * x
/ 14;
1077 int lineLength
= x
- 2*lineStartBase
;
1079 mem
.SetPen( wxPen(bg
) );
1080 mem
.SetBrush( wxBrush(bg
) );
1081 int handleCornerShift
= penWidth
/2;
1082 handleCornerShift
= WXMAX( handleCornerShift
, 1 );
1083 wxPoint handlePolygon
[] =
1085 wxPoint(-handleCornerShift
,+handleCornerShift
),
1086 wxPoint(+handleCornerShift
,-handleCornerShift
),
1087 wxPoint(multiplier
*lineLength
+handleCornerShift
,multiplier
*lineLength
-handleCornerShift
),
1088 wxPoint(multiplier
*lineLength
-handleCornerShift
,multiplier
*lineLength
+handleCornerShift
),
1090 mem
.DrawPolygon(WXSIZEOF(handlePolygon
),handlePolygon
,multiplier
*lineStartBase
,multiplier
*lineStartBase
);
1091 wxPoint handlePolygon2
[] =
1093 wxPoint(+handleCornerShift
,+handleCornerShift
),
1094 wxPoint(-handleCornerShift
,-handleCornerShift
),
1095 wxPoint(multiplier
*lineLength
-handleCornerShift
,-multiplier
*lineLength
-handleCornerShift
),
1096 wxPoint(multiplier
*lineLength
+handleCornerShift
,-multiplier
*lineLength
+handleCornerShift
),
1098 mem
.DrawPolygon(WXSIZEOF(handlePolygon2
),handlePolygon2
,multiplier
*lineStartBase
,multiplier
*(x
-lineStartBase
));
1100 //===============================================================================
1102 //===============================================================================
1104 if ( multiplier
!= 1 )
1106 wxImage image
= bitmap
.ConvertToImage();
1108 bitmap
= wxBitmap( image
);
1114 void wxSearchCtrl::RecalcBitmaps()
1120 wxSize sizeText
= m_text
->GetBestSize();
1122 int bitmapHeight
= sizeText
.y
- 2 * ICON_MARGIN
;
1123 int bitmapWidth
= sizeText
.y
* 20 / 14;
1125 if ( !m_searchBitmapUser
)
1128 !m_searchBitmap
.IsOk() ||
1129 m_searchBitmap
.GetHeight() != bitmapHeight
||
1130 m_searchBitmap
.GetWidth() != bitmapWidth
1133 m_searchBitmap
= RenderSearchBitmap(bitmapWidth
,bitmapHeight
,false);
1136 m_searchButton
->SetBitmapLabel(m_searchBitmap
);
1139 // else this bitmap was set by user, don't alter
1143 if ( !m_searchMenuBitmapUser
)
1146 !m_searchMenuBitmap
.IsOk() ||
1147 m_searchMenuBitmap
.GetHeight() != bitmapHeight
||
1148 m_searchMenuBitmap
.GetWidth() != bitmapWidth
1151 m_searchMenuBitmap
= RenderSearchBitmap(bitmapWidth
,bitmapHeight
,true);
1154 m_searchButton
->SetBitmapLabel(m_searchMenuBitmap
);
1157 // else this bitmap was set by user, don't alter
1159 #endif // wxUSE_MENUS
1161 if ( !m_cancelBitmapUser
)
1164 !m_cancelBitmap
.IsOk() ||
1165 m_cancelBitmap
.GetHeight() != bitmapHeight
||
1166 m_cancelBitmap
.GetWidth() != bitmapHeight
1169 m_cancelBitmap
= RenderCancelBitmap(bitmapHeight
-BORDER
-1,bitmapHeight
-BORDER
-1); // square
1170 m_cancelButton
->SetBitmapLabel(m_cancelBitmap
);
1172 // else this bitmap was set by user, don't alter
1176 void wxSearchCtrl::OnSearchButton( wxCommandEvent
& event
)
1181 void wxSearchCtrl::OnSetFocus( wxFocusEvent
& /*event*/ )
1189 void wxSearchCtrl::OnSize( wxSizeEvent
& WXUNUSED(event
) )
1192 GetSize(&width
, &height
);
1193 LayoutControls(0, 0, width
, height
);
1198 void wxSearchCtrl::PopupSearchMenu()
1202 wxSize size
= GetSize();
1203 PopupMenu( m_menu
, 0, size
.y
);
1207 #endif // wxUSE_MENUS
1209 #endif // !wxUSE_NATIVE_SEARCH_CONTROL
1211 #endif // wxUSE_SEARCHCTRL