1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/srchctlg.cpp
3 // Purpose: implements wxSearchCtrl as a composite control
4 // Author: Vince Harron
6 // Copyright: Vince Harron
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
19 #include "wx/srchctrl.h"
22 #include "wx/button.h"
23 #include "wx/dcclient.h"
25 #include "wx/dcmemory.h"
28 #if !wxUSE_NATIVE_SEARCH_CONTROL
32 #define WXMAX(a,b) ((a)>(b)?(a):(b))
34 // ----------------------------------------------------------------------------
36 // ----------------------------------------------------------------------------
38 // the margin between the text control and the search/cancel buttons
39 static const wxCoord MARGIN
= 2;
41 // border around all controls to compensate for wxSIMPLE_BORDER
42 #if defined(__WXMSW__)
43 static const wxCoord BORDER
= 0;
44 static const wxCoord ICON_MARGIN
= 2;
45 static const wxCoord ICON_OFFSET
= 2;
47 static const wxCoord BORDER
= 2;
48 static const wxCoord ICON_MARGIN
= 0;
49 static const wxCoord ICON_OFFSET
= 0;
52 #define LIGHT_STEP 160
54 // ----------------------------------------------------------------------------
55 // wxSearchTextCtrl: text control used by search control
56 // ----------------------------------------------------------------------------
58 class wxSearchTextCtrl
: public wxTextCtrl
61 wxSearchTextCtrl(wxSearchCtrl
*search
, const wxString
& value
, int style
)
62 : wxTextCtrl(search
, wxID_ANY
, value
, wxDefaultPosition
, wxDefaultSize
,
63 (style
& ~wxBORDER_MASK
) | wxNO_BORDER
)
69 // Ensure that our best size is recomputed using our overridden
74 virtual wxWindow
* GetMainWindowOfCompositeControl()
79 // provide access to the base class protected methods to wxSearchCtrl which
80 // needs to forward to them
81 void DoSetValue(const wxString
& value
, int flags
)
83 wxTextCtrl::DoSetValue(value
, flags
);
86 bool DoLoadFile(const wxString
& file
, int fileType
)
88 return wxTextCtrl::DoLoadFile(file
, fileType
);
91 bool DoSaveFile(const wxString
& file
, int fileType
)
93 return wxTextCtrl::DoSaveFile(file
, fileType
);
97 void OnText(wxCommandEvent
& eventText
)
99 wxCommandEvent
event(eventText
);
100 event
.SetEventObject(m_search
);
101 event
.SetId(m_search
->GetId());
103 m_search
->GetEventHandler()->ProcessEvent(event
);
106 void OnTextUrl(wxTextUrlEvent
& eventText
)
108 // copy constructor is disabled for some reason?
109 //wxTextUrlEvent event(eventText);
110 wxTextUrlEvent
event(
112 eventText
.GetMouseEvent(),
113 eventText
.GetURLStart(),
114 eventText
.GetURLEnd()
116 event
.SetEventObject(m_search
);
118 m_search
->GetEventHandler()->ProcessEvent(event
);
122 // We increase the text control height to be the same as for the controls
123 // with border as this is what we actually need here because even though
124 // this control itself is borderless, it's inside wxSearchCtrl which does
125 // have the border and so should have the same height as the normal text
126 // entries with border.
128 // This is a bit ugly and it would arguably be better to use whatever size
129 // the base class version returns and just centre the text vertically in
130 // the search control but I failed to modify the code in LayoutControls()
131 // to do this easily and as there is much in that code I don't understand
132 // (notably what is the logic for buttons sizing?) I prefer to not touch it
134 virtual wxSize
DoGetBestSize() const
136 const long flags
= GetWindowStyleFlag();
137 wxSearchTextCtrl
* const self
= const_cast<wxSearchTextCtrl
*>(this);
139 self
->SetWindowStyleFlag((flags
& ~wxBORDER_MASK
) | wxBORDER_DEFAULT
);
140 const wxSize size
= wxTextCtrl::DoGetBestSize();
141 self
->SetWindowStyleFlag(flags
);
148 wxSearchCtrl
* m_search
;
150 DECLARE_EVENT_TABLE()
153 BEGIN_EVENT_TABLE(wxSearchTextCtrl
, wxTextCtrl
)
154 EVT_TEXT(wxID_ANY
, wxSearchTextCtrl::OnText
)
155 EVT_TEXT_ENTER(wxID_ANY
, wxSearchTextCtrl::OnText
)
156 EVT_TEXT_URL(wxID_ANY
, wxSearchTextCtrl::OnTextUrl
)
157 EVT_TEXT_MAXLEN(wxID_ANY
, wxSearchTextCtrl::OnText
)
160 // ----------------------------------------------------------------------------
161 // wxSearchButton: search button used by search control
162 // ----------------------------------------------------------------------------
164 class wxSearchButton
: public wxControl
167 wxSearchButton(wxSearchCtrl
*search
, int eventType
, const wxBitmap
& bmp
)
168 : wxControl(search
, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, wxNO_BORDER
),
170 m_eventType(eventType
),
174 void SetBitmapLabel(const wxBitmap
& label
)
177 InvalidateBestSize();
180 // The buttons in wxSearchCtrl shouldn't accept focus from keyboard because
181 // this would interfere with the usual TAB processing: the user expects
182 // that pressing TAB in the search control should switch focus to the next
183 // control and not give it to the button inside the same control. Besides,
184 // the search button can be already activated by pressing "Enter" so there
185 // is really no reason for it to be able to get focus from keyboard.
186 virtual bool AcceptsFocusFromKeyboard() const { return false; }
188 virtual wxWindow
* GetMainWindowOfCompositeControl()
194 wxSize
DoGetBestSize() const
196 return wxSize(m_bmp
.GetWidth(), m_bmp
.GetHeight());
199 void OnLeftUp(wxMouseEvent
&)
201 wxCommandEvent
event(m_eventType
, m_search
->GetId());
202 event
.SetEventObject(m_search
);
204 if ( m_eventType
== wxEVT_SEARCHCTRL_SEARCH_BTN
)
206 // it's convenient to have the string to search for directly in the
207 // event instead of having to retrieve it from the control in the
208 // event handler code later, so provide it here
209 event
.SetString(m_search
->GetValue());
212 GetEventHandler()->ProcessEvent(event
);
214 m_search
->SetFocus();
217 if ( m_eventType
== wxEVT_SEARCHCTRL_SEARCH_BTN
)
219 // this happens automatically, just like on Mac OS X
220 m_search
->PopupSearchMenu();
222 #endif // wxUSE_MENUS
225 void OnPaint(wxPaintEvent
&)
228 dc
.DrawBitmap(m_bmp
, 0,0, true);
233 wxSearchCtrl
*m_search
;
234 wxEventType m_eventType
;
237 DECLARE_EVENT_TABLE()
240 BEGIN_EVENT_TABLE(wxSearchButton
, wxControl
)
241 EVT_LEFT_UP(wxSearchButton::OnLeftUp
)
242 EVT_PAINT(wxSearchButton::OnPaint
)
245 BEGIN_EVENT_TABLE(wxSearchCtrl
, wxSearchCtrlBase
)
246 EVT_SEARCHCTRL_CANCEL_BTN(wxID_ANY
, wxSearchCtrl::OnCancelButton
)
247 EVT_SET_FOCUS(wxSearchCtrl::OnSetFocus
)
248 EVT_SIZE(wxSearchCtrl::OnSize
)
251 IMPLEMENT_DYNAMIC_CLASS(wxSearchCtrl
, wxSearchCtrlBase
)
253 // ============================================================================
255 // ============================================================================
257 // ----------------------------------------------------------------------------
258 // wxSearchCtrl creation
259 // ----------------------------------------------------------------------------
264 wxSearchCtrl::wxSearchCtrl()
269 wxSearchCtrl::wxSearchCtrl(wxWindow
*parent
, wxWindowID id
,
270 const wxString
& value
,
274 const wxValidator
& validator
,
275 const wxString
& name
)
279 Create(parent
, id
, value
, pos
, size
, style
, validator
, name
);
282 void wxSearchCtrl::Init()
285 m_searchButton
= NULL
;
286 m_cancelButton
= NULL
;
289 #endif // wxUSE_MENUS
291 m_searchButtonVisible
= true;
292 m_cancelButtonVisible
= false;
294 m_searchBitmapUser
= false;
295 m_cancelBitmapUser
= false;
297 m_searchMenuBitmapUser
= false;
298 #endif // wxUSE_MENUS
301 bool wxSearchCtrl::Create(wxWindow
*parent
, wxWindowID id
,
302 const wxString
& value
,
306 const wxValidator
& validator
,
307 const wxString
& name
)
309 // force border style for more native appearance
310 style
&= ~wxBORDER_MASK
;
312 style
|= wxBORDER_SUNKEN
;
313 #elif defined(__WXMSW__)
314 // Don't set the style explicitly, let GetDefaultBorder() work it out, unless
315 // we will get a sunken border (e.g. on Windows 200) in which case we must
316 // override with a simple border.
317 if (GetDefaultBorder() == wxBORDER_SUNKEN
)
318 style
|= wxBORDER_SIMPLE
;
320 style
|= wxBORDER_SIMPLE
;
322 if ( !wxSearchCtrlBaseBaseClass::Create(parent
, id
, pos
, size
,
323 style
, validator
, name
) )
328 m_text
= new wxSearchTextCtrl(this, value
, style
);
330 m_searchButton
= new wxSearchButton(this,
331 wxEVT_SEARCHCTRL_SEARCH_BTN
,
333 m_cancelButton
= new wxSearchButton(this,
334 wxEVT_SEARCHCTRL_CANCEL_BTN
,
337 SetBackgroundColour( m_text
->GetBackgroundColour() );
341 SetInitialSize(size
);
346 wxSearchCtrl::~wxSearchCtrl()
349 delete m_searchButton
;
350 delete m_cancelButton
;
353 #endif // wxUSE_MENUS
357 // search control specific interfaces
360 void wxSearchCtrl::SetMenu( wxMenu
* menu
)
362 if ( menu
== m_menu
)
367 bool hadMenu
= (m_menu
!= NULL
);
371 if ( m_menu
&& !hadMenu
)
373 m_searchButton
->SetBitmapLabel(m_searchMenuBitmap
);
374 m_searchButton
->Refresh();
376 else if ( !m_menu
&& hadMenu
)
378 m_searchButton
->SetBitmapLabel(m_searchBitmap
);
379 if ( m_searchButtonVisible
)
381 m_searchButton
->Refresh();
384 wxRect rect
= GetRect();
385 LayoutControls(0, 0, rect
.GetWidth(), rect
.GetHeight());
388 wxMenu
* wxSearchCtrl::GetMenu()
393 #endif // wxUSE_MENUS
395 void wxSearchCtrl::ShowSearchButton( bool show
)
397 if ( m_searchButtonVisible
== show
)
402 m_searchButtonVisible
= show
;
403 if ( m_searchButtonVisible
)
408 wxRect rect
= GetRect();
409 LayoutControls(0, 0, rect
.GetWidth(), rect
.GetHeight());
412 bool wxSearchCtrl::IsSearchButtonVisible() const
414 return m_searchButtonVisible
;
418 void wxSearchCtrl::ShowCancelButton( bool show
)
420 if ( m_cancelButtonVisible
== show
)
425 m_cancelButtonVisible
= show
;
427 wxRect rect
= GetRect();
428 LayoutControls(0, 0, rect
.GetWidth(), rect
.GetHeight());
431 bool wxSearchCtrl::IsCancelButtonVisible() const
433 return m_cancelButtonVisible
;
436 void wxSearchCtrl::SetDescriptiveText(const wxString
& text
)
438 m_text
->SetHint(text
);
441 wxString
wxSearchCtrl::GetDescriptiveText() const
443 return m_text
->GetHint();
446 // ----------------------------------------------------------------------------
448 // ----------------------------------------------------------------------------
450 wxSize
wxSearchCtrl::DoGetBestSize() const
452 wxSize sizeText
= m_text
->GetBestSize();
453 wxSize
sizeSearch(0,0);
454 wxSize
sizeCancel(0,0);
455 int searchMargin
= 0;
456 int cancelMargin
= 0;
457 if ( m_searchButtonVisible
|| HasMenu() )
459 sizeSearch
= m_searchButton
->GetBestSize();
460 searchMargin
= MARGIN
;
462 if ( m_cancelButtonVisible
)
464 sizeCancel
= m_cancelButton
->GetBestSize();
465 cancelMargin
= MARGIN
;
468 int horizontalBorder
= 1 + ( sizeText
.y
- sizeText
.y
* 14 / 21 ) / 2;
470 // buttons are square and equal to the height of the text control
471 int height
= sizeText
.y
;
472 return wxSize(sizeSearch
.x
+ searchMargin
+ sizeText
.x
+ cancelMargin
+ sizeCancel
.x
+ 2*horizontalBorder
,
476 void wxSearchCtrl::DoMoveWindow(int x
, int y
, int width
, int height
)
478 wxSearchCtrlBase::DoMoveWindow(x
, y
, width
, height
);
480 LayoutControls(0, 0, width
, height
);
483 void wxSearchCtrl::LayoutControls(int x
, int y
, int width
, int height
)
488 wxSize sizeText
= m_text
->GetBestSize();
489 // make room for the search menu & clear button
490 int horizontalBorder
= ( sizeText
.y
- sizeText
.y
* 14 / 21 ) / 2;
491 x
+= horizontalBorder
;
493 width
-= horizontalBorder
*2;
495 if (width
< 0) width
= 0;
496 if (height
< 0) height
= 0;
498 wxSize
sizeSearch(0,0);
499 wxSize
sizeCancel(0,0);
500 int searchMargin
= 0;
501 int cancelMargin
= 0;
502 if ( m_searchButtonVisible
|| HasMenu() )
504 sizeSearch
= m_searchButton
->GetBestSize();
505 searchMargin
= MARGIN
;
507 if ( m_cancelButtonVisible
)
509 sizeCancel
= m_cancelButton
->GetBestSize();
510 cancelMargin
= MARGIN
;
512 m_searchButton
->Show( m_searchButtonVisible
|| HasMenu() );
513 m_cancelButton
->Show( m_cancelButtonVisible
);
515 if ( sizeSearch
.x
+ sizeCancel
.x
> width
)
517 sizeSearch
.x
= width
/2;
518 sizeCancel
.x
= width
/2;
522 wxCoord textWidth
= width
- sizeSearch
.x
- sizeCancel
.x
- searchMargin
- cancelMargin
- 1;
523 if (textWidth
< 0) textWidth
= 0;
525 // position the subcontrols inside the client area
527 m_searchButton
->SetSize(x
, y
+ ICON_OFFSET
- 1, sizeSearch
.x
, height
);
528 m_text
->SetSize( x
+ sizeSearch
.x
+ searchMargin
,
529 y
+ ICON_OFFSET
- BORDER
,
532 m_cancelButton
->SetSize(x
+ sizeSearch
.x
+ searchMargin
+ textWidth
+ cancelMargin
,
533 y
+ ICON_OFFSET
- 1, sizeCancel
.x
, height
);
536 wxWindowList
wxSearchCtrl::GetCompositeWindowParts() const
539 parts
.push_back(m_text
);
540 parts
.push_back(m_searchButton
);
541 parts
.push_back(m_cancelButton
);
548 wxString
wxSearchCtrl::DoGetValue() const
550 return m_text
->GetValue();
552 wxString
wxSearchCtrl::GetRange(long from
, long to
) const
554 return m_text
->GetRange(from
, to
);
557 int wxSearchCtrl::GetLineLength(long lineNo
) const
559 return m_text
->GetLineLength(lineNo
);
561 wxString
wxSearchCtrl::GetLineText(long lineNo
) const
563 return m_text
->GetLineText(lineNo
);
565 int wxSearchCtrl::GetNumberOfLines() const
567 return m_text
->GetNumberOfLines();
570 bool wxSearchCtrl::IsModified() const
572 return m_text
->IsModified();
574 bool wxSearchCtrl::IsEditable() const
576 return m_text
->IsEditable();
579 // more readable flag testing methods
580 bool wxSearchCtrl::IsSingleLine() const
582 return m_text
->IsSingleLine();
584 bool wxSearchCtrl::IsMultiLine() const
586 return m_text
->IsMultiLine();
589 // If the return values from and to are the same, there is no selection.
590 void wxSearchCtrl::GetSelection(long* from
, long* to
) const
592 m_text
->GetSelection(from
, to
);
595 wxString
wxSearchCtrl::GetStringSelection() const
597 return m_text
->GetStringSelection();
604 void wxSearchCtrl::Clear()
608 void wxSearchCtrl::Replace(long from
, long to
, const wxString
& value
)
610 m_text
->Replace(from
, to
, value
);
612 void wxSearchCtrl::Remove(long from
, long to
)
614 m_text
->Remove(from
, to
);
617 // load/save the controls contents from/to the file
618 bool wxSearchCtrl::LoadFile(const wxString
& file
)
620 return m_text
->LoadFile(file
);
622 bool wxSearchCtrl::SaveFile(const wxString
& file
)
624 return m_text
->SaveFile(file
);
627 // sets/clears the dirty flag
628 void wxSearchCtrl::MarkDirty()
632 void wxSearchCtrl::DiscardEdits()
634 m_text
->DiscardEdits();
637 // set the max number of characters which may be entered in a single line
639 void wxSearchCtrl::SetMaxLength(unsigned long len
)
641 m_text
->SetMaxLength(len
);
644 // writing text inserts it at the current position, appending always
645 // inserts it at the end
646 void wxSearchCtrl::WriteText(const wxString
& text
)
648 m_text
->WriteText(text
);
650 void wxSearchCtrl::AppendText(const wxString
& text
)
652 m_text
->AppendText(text
);
655 // insert the character which would have resulted from this key event,
656 // return true if anything has been inserted
657 bool wxSearchCtrl::EmulateKeyPress(const wxKeyEvent
& event
)
659 return m_text
->EmulateKeyPress(event
);
662 // text control under some platforms supports the text styles: these
663 // methods allow to apply the given text style to the given selection or to
664 // set/get the style which will be used for all appended text
665 bool wxSearchCtrl::SetStyle(long start
, long end
, const wxTextAttr
& style
)
667 return m_text
->SetStyle(start
, end
, style
);
669 bool wxSearchCtrl::GetStyle(long position
, wxTextAttr
& style
)
671 return m_text
->GetStyle(position
, style
);
673 bool wxSearchCtrl::SetDefaultStyle(const wxTextAttr
& style
)
675 return m_text
->SetDefaultStyle(style
);
677 const wxTextAttr
& wxSearchCtrl::GetDefaultStyle() const
679 return m_text
->GetDefaultStyle();
682 // translate between the position (which is just an index in the text ctrl
683 // considering all its contents as a single strings) and (x, y) coordinates
684 // which represent column and line.
685 long wxSearchCtrl::XYToPosition(long x
, long y
) const
687 return m_text
->XYToPosition(x
, y
);
689 bool wxSearchCtrl::PositionToXY(long pos
, long *x
, long *y
) const
691 return m_text
->PositionToXY(pos
, x
, y
);
694 void wxSearchCtrl::ShowPosition(long pos
)
696 m_text
->ShowPosition(pos
);
699 // find the character at position given in pixels
701 // NB: pt is in device coords (not adjusted for the client area origin nor
703 wxTextCtrlHitTestResult
wxSearchCtrl::HitTest(const wxPoint
& pt
, long *pos
) const
705 return m_text
->HitTest(pt
, pos
);
707 wxTextCtrlHitTestResult
wxSearchCtrl::HitTest(const wxPoint
& pt
,
709 wxTextCoord
*row
) const
711 return m_text
->HitTest(pt
, col
, row
);
714 // Clipboard operations
715 void wxSearchCtrl::Copy()
719 void wxSearchCtrl::Cut()
723 void wxSearchCtrl::Paste()
728 bool wxSearchCtrl::CanCopy() const
730 return m_text
->CanCopy();
732 bool wxSearchCtrl::CanCut() const
734 return m_text
->CanCut();
736 bool wxSearchCtrl::CanPaste() const
738 return m_text
->CanPaste();
742 void wxSearchCtrl::Undo()
746 void wxSearchCtrl::Redo()
751 bool wxSearchCtrl::CanUndo() const
753 return m_text
->CanUndo();
755 bool wxSearchCtrl::CanRedo() const
757 return m_text
->CanRedo();
761 void wxSearchCtrl::SetInsertionPoint(long pos
)
763 m_text
->SetInsertionPoint(pos
);
765 void wxSearchCtrl::SetInsertionPointEnd()
767 m_text
->SetInsertionPointEnd();
769 long wxSearchCtrl::GetInsertionPoint() const
771 return m_text
->GetInsertionPoint();
773 long wxSearchCtrl::GetLastPosition() const
775 return m_text
->GetLastPosition();
778 void wxSearchCtrl::SetSelection(long from
, long to
)
780 m_text
->SetSelection(from
, to
);
782 void wxSearchCtrl::SelectAll()
787 void wxSearchCtrl::SetEditable(bool editable
)
789 m_text
->SetEditable(editable
);
792 bool wxSearchCtrl::SetFont(const wxFont
& font
)
794 if ( !wxSearchCtrlBase::SetFont(font
) )
797 // Recreate the bitmaps as their size may have changed.
803 bool wxSearchCtrl::SetBackgroundColour(const wxColour
& colour
)
805 if ( !wxSearchCtrlBase::SetBackgroundColour(colour
) )
808 // When the background changes, re-render the bitmaps so that the correct
809 // colour shows in their "transparent" area.
815 // search control generic only
816 void wxSearchCtrl::SetSearchBitmap( const wxBitmap
& bitmap
)
818 m_searchBitmap
= bitmap
;
819 m_searchBitmapUser
= bitmap
.IsOk();
820 if ( m_searchBitmapUser
)
822 if ( m_searchButton
&& !HasMenu() )
824 m_searchButton
->SetBitmapLabel( m_searchBitmap
);
829 // the user bitmap was just cleared, generate one
836 void wxSearchCtrl::SetSearchMenuBitmap( const wxBitmap
& bitmap
)
838 m_searchMenuBitmap
= bitmap
;
839 m_searchMenuBitmapUser
= bitmap
.IsOk();
840 if ( m_searchMenuBitmapUser
)
842 if ( m_searchButton
&& m_menu
)
844 m_searchButton
->SetBitmapLabel( m_searchMenuBitmap
);
849 // the user bitmap was just cleared, generate one
854 #endif // wxUSE_MENUS
856 void wxSearchCtrl::SetCancelBitmap( const wxBitmap
& bitmap
)
858 m_cancelBitmap
= bitmap
;
859 m_cancelBitmapUser
= bitmap
.IsOk();
860 if ( m_cancelBitmapUser
)
862 if ( m_cancelButton
)
864 m_cancelButton
->SetBitmapLabel( m_cancelBitmap
);
869 // the user bitmap was just cleared, generate one
876 // override streambuf method
877 #if wxHAS_TEXT_WINDOW_STREAM
879 #endif // wxHAS_TEXT_WINDOW_STREAM
881 // stream-like insertion operators: these are always available, whether we
882 // were, or not, compiled with streambuf support
883 wxTextCtrl
& operator<<(const wxString
& s
);
884 wxTextCtrl
& operator<<(int i
);
885 wxTextCtrl
& operator<<(long i
);
886 wxTextCtrl
& operator<<(float f
);
887 wxTextCtrl
& operator<<(double d
);
888 wxTextCtrl
& operator<<(const wxChar c
);
891 void wxSearchCtrl::DoSetValue(const wxString
& value
, int flags
)
893 m_text
->DoSetValue(value
, flags
);
896 bool wxSearchCtrl::DoLoadFile(const wxString
& file
, int fileType
)
898 return m_text
->DoLoadFile(file
, fileType
);
901 bool wxSearchCtrl::DoSaveFile(const wxString
& file
, int fileType
)
903 return m_text
->DoSaveFile(file
, fileType
);
906 // do the window-specific processing after processing the update event
907 void wxSearchCtrl::DoUpdateWindowUI(wxUpdateUIEvent
& event
)
909 wxSearchCtrlBase::DoUpdateWindowUI(event
);
912 bool wxSearchCtrl::ShouldInheritColours() const
917 // icons are rendered at 3-8 times larger than necessary and downscaled for
919 static int GetMultiplier()
922 // speed up bitmap generation by using a small bitmap
925 int depth
= ::wxDisplayDepth();
935 wxBitmap
wxSearchCtrl::RenderSearchBitmap( int x
, int y
, bool renderDrop
)
937 wxColour bg
= GetBackgroundColour();
938 wxColour fg
= GetForegroundColour().ChangeLightness(LIGHT_STEP
-20);
940 //===============================================================================
941 // begin drawing code
942 //===============================================================================
945 // force width:height ratio
957 // glass 11x11, top left corner
958 // handle (9,9)-(13,13)
959 // drop (13,16)-(19,6)-(16,9)
961 int multiplier
= GetMultiplier();
962 int penWidth
= multiplier
* 2;
964 penWidth
= penWidth
* x
/ 20;
966 wxBitmap
bitmap( multiplier
*x
, multiplier
*y
);
968 mem
.SelectObject(bitmap
);
971 mem
.SetBrush( wxBrush(bg
) );
972 mem
.SetPen( wxPen(bg
) );
973 mem
.DrawRectangle(0,0,bitmap
.GetWidth(),bitmap
.GetHeight());
976 mem
.SetBrush( wxBrush(fg
) );
977 mem
.SetPen( wxPen(fg
) );
978 int glassBase
= 5 * x
/ 20;
979 int glassFactor
= 2*glassBase
+ 1;
980 int radius
= multiplier
*glassFactor
/2;
981 mem
.DrawCircle(radius
,radius
,radius
);
982 mem
.SetBrush( wxBrush(bg
) );
983 mem
.SetPen( wxPen(bg
) );
984 mem
.DrawCircle(radius
,radius
,radius
-penWidth
);
987 int lineStart
= radius
+ (radius
-penWidth
/2) * 707 / 1000; // 707 / 1000 = 0.707 = 1/sqrt(2);
989 mem
.SetPen( wxPen(fg
) );
990 mem
.SetBrush( wxBrush(fg
) );
991 int handleCornerShift
= penWidth
* 707 / 1000 / 2; // 707 / 1000 = 0.707 = 1/sqrt(2);
992 handleCornerShift
= WXMAX( handleCornerShift
, 1 );
993 int handleBase
= 4 * x
/ 20;
994 int handleLength
= 2*handleBase
+1;
995 wxPoint handlePolygon
[] =
997 wxPoint(-handleCornerShift
,+handleCornerShift
),
998 wxPoint(+handleCornerShift
,-handleCornerShift
),
999 wxPoint(multiplier
*handleLength
/2+handleCornerShift
,multiplier
*handleLength
/2-handleCornerShift
),
1000 wxPoint(multiplier
*handleLength
/2-handleCornerShift
,multiplier
*handleLength
/2+handleCornerShift
),
1002 mem
.DrawPolygon(WXSIZEOF(handlePolygon
),handlePolygon
,lineStart
,lineStart
);
1004 // draw drop triangle
1005 int triangleX
= 13 * x
/ 20;
1006 int triangleY
= 5 * x
/ 20;
1007 int triangleBase
= 3 * x
/ 20;
1008 int triangleFactor
= triangleBase
*2+1;
1011 wxPoint dropPolygon
[] =
1013 wxPoint(multiplier
*0,multiplier
*0), // triangle left
1014 wxPoint(multiplier
*triangleFactor
-1,multiplier
*0), // triangle right
1015 wxPoint(multiplier
*triangleFactor
/2,multiplier
*triangleFactor
/2), // triangle bottom
1017 mem
.DrawPolygon(WXSIZEOF(dropPolygon
),dropPolygon
,multiplier
*triangleX
,multiplier
*triangleY
);
1019 mem
.SelectObject(wxNullBitmap
);
1021 //===============================================================================
1023 //===============================================================================
1025 if ( multiplier
!= 1 )
1027 wxImage image
= bitmap
.ConvertToImage();
1029 bitmap
= wxBitmap( image
);
1033 // Trim the edge where the arrow would have gone
1034 bitmap
= bitmap
.GetSubBitmap(wxRect(0,0, y
,y
));
1040 wxBitmap
wxSearchCtrl::RenderCancelBitmap( int x
, int y
)
1042 wxColour bg
= GetBackgroundColour();
1043 wxColour fg
= GetForegroundColour().ChangeLightness(LIGHT_STEP
);
1045 //===============================================================================
1046 // begin drawing code
1047 //===============================================================================
1064 // cross line starts (4,4)-(10,10)
1065 // drop (13,16)-(19,6)-(16,9)
1067 int multiplier
= GetMultiplier();
1069 int penWidth
= multiplier
* x
/ 14;
1071 wxBitmap
bitmap( multiplier
*x
, multiplier
*y
);
1073 mem
.SelectObject(bitmap
);
1076 mem
.SetBrush( wxBrush(bg
) );
1077 mem
.SetPen( wxPen(bg
) );
1078 mem
.DrawRectangle(0,0,bitmap
.GetWidth(),bitmap
.GetHeight());
1081 mem
.SetBrush( wxBrush(fg
) );
1082 mem
.SetPen( wxPen(fg
) );
1083 int radius
= multiplier
*x
/2;
1084 mem
.DrawCircle(radius
,radius
,radius
);
1087 int lineStartBase
= 4 * x
/ 14;
1088 int lineLength
= x
- 2*lineStartBase
;
1090 mem
.SetPen( wxPen(bg
) );
1091 mem
.SetBrush( wxBrush(bg
) );
1092 int handleCornerShift
= penWidth
/2;
1093 handleCornerShift
= WXMAX( handleCornerShift
, 1 );
1094 wxPoint handlePolygon
[] =
1096 wxPoint(-handleCornerShift
,+handleCornerShift
),
1097 wxPoint(+handleCornerShift
,-handleCornerShift
),
1098 wxPoint(multiplier
*lineLength
+handleCornerShift
,multiplier
*lineLength
-handleCornerShift
),
1099 wxPoint(multiplier
*lineLength
-handleCornerShift
,multiplier
*lineLength
+handleCornerShift
),
1101 mem
.DrawPolygon(WXSIZEOF(handlePolygon
),handlePolygon
,multiplier
*lineStartBase
,multiplier
*lineStartBase
);
1102 wxPoint handlePolygon2
[] =
1104 wxPoint(+handleCornerShift
,+handleCornerShift
),
1105 wxPoint(-handleCornerShift
,-handleCornerShift
),
1106 wxPoint(multiplier
*lineLength
-handleCornerShift
,-multiplier
*lineLength
-handleCornerShift
),
1107 wxPoint(multiplier
*lineLength
+handleCornerShift
,-multiplier
*lineLength
+handleCornerShift
),
1109 mem
.DrawPolygon(WXSIZEOF(handlePolygon2
),handlePolygon2
,multiplier
*lineStartBase
,multiplier
*(x
-lineStartBase
));
1111 //===============================================================================
1113 //===============================================================================
1115 if ( multiplier
!= 1 )
1117 wxImage image
= bitmap
.ConvertToImage();
1119 bitmap
= wxBitmap( image
);
1125 void wxSearchCtrl::RecalcBitmaps()
1131 wxSize sizeText
= m_text
->GetBestSize();
1133 int bitmapHeight
= sizeText
.y
- 2 * ICON_MARGIN
;
1134 int bitmapWidth
= sizeText
.y
* 20 / 14;
1136 if ( !m_searchBitmapUser
)
1139 !m_searchBitmap
.IsOk() ||
1140 m_searchBitmap
.GetHeight() != bitmapHeight
||
1141 m_searchBitmap
.GetWidth() != bitmapWidth
1144 m_searchBitmap
= RenderSearchBitmap(bitmapWidth
,bitmapHeight
,false);
1147 m_searchButton
->SetBitmapLabel(m_searchBitmap
);
1150 // else this bitmap was set by user, don't alter
1154 if ( !m_searchMenuBitmapUser
)
1157 !m_searchMenuBitmap
.IsOk() ||
1158 m_searchMenuBitmap
.GetHeight() != bitmapHeight
||
1159 m_searchMenuBitmap
.GetWidth() != bitmapWidth
1162 m_searchMenuBitmap
= RenderSearchBitmap(bitmapWidth
,bitmapHeight
,true);
1165 m_searchButton
->SetBitmapLabel(m_searchMenuBitmap
);
1168 // else this bitmap was set by user, don't alter
1170 #endif // wxUSE_MENUS
1172 if ( !m_cancelBitmapUser
)
1175 !m_cancelBitmap
.IsOk() ||
1176 m_cancelBitmap
.GetHeight() != bitmapHeight
||
1177 m_cancelBitmap
.GetWidth() != bitmapHeight
1180 m_cancelBitmap
= RenderCancelBitmap(bitmapHeight
-BORDER
-1,bitmapHeight
-BORDER
-1); // square
1181 m_cancelButton
->SetBitmapLabel(m_cancelBitmap
);
1183 // else this bitmap was set by user, don't alter
1187 void wxSearchCtrl::OnCancelButton( wxCommandEvent
& event
)
1193 void wxSearchCtrl::OnSetFocus( wxFocusEvent
& /*event*/ )
1201 void wxSearchCtrl::OnSize( wxSizeEvent
& WXUNUSED(event
) )
1204 GetSize(&width
, &height
);
1205 LayoutControls(0, 0, width
, height
);
1210 void wxSearchCtrl::PopupSearchMenu()
1214 wxSize size
= GetSize();
1215 PopupMenu( m_menu
, 0, size
.y
);
1219 #endif // wxUSE_MENUS
1221 #endif // !wxUSE_NATIVE_SEARCH_CONTROL
1223 #endif // wxUSE_SEARCHCTRL