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 // remove the default minsize, the searchctrl will have one instead
71 SetSizeHints(wxDefaultCoord
,wxDefaultCoord
);
75 // provide access to the base class protected methods to wxSearchCtrl which
76 // needs to forward to them
77 void DoSetValue(const wxString
& value
, int flags
)
79 wxTextCtrl
::DoSetValue(value
, flags
);
82 bool DoLoadFile(const wxString
& file
, int fileType
)
84 return wxTextCtrl
::DoLoadFile(file
, fileType
);
87 bool DoSaveFile(const wxString
& file
, int fileType
)
89 return wxTextCtrl
::DoSaveFile(file
, fileType
);
93 void OnText(wxCommandEvent
& eventText
)
95 wxCommandEvent
event(eventText
);
96 event
.SetEventObject(m_search
);
97 event
.SetId(m_search
->GetId());
99 m_search
->GetEventHandler()->ProcessEvent(event
);
102 void OnTextUrl(wxTextUrlEvent
& eventText
)
104 // copy constructor is disabled for some reason?
105 //wxTextUrlEvent event(eventText);
106 wxTextUrlEvent
event(
108 eventText
.GetMouseEvent(),
109 eventText
.GetURLStart(),
110 eventText
.GetURLEnd()
112 event
.SetEventObject(m_search
);
114 m_search
->GetEventHandler()->ProcessEvent(event
);
118 wxSearchCtrl
* m_search
;
120 DECLARE_EVENT_TABLE()
123 BEGIN_EVENT_TABLE(wxSearchTextCtrl
, wxTextCtrl
)
124 EVT_TEXT(wxID_ANY
, wxSearchTextCtrl
::OnText
)
125 EVT_TEXT_ENTER(wxID_ANY
, wxSearchTextCtrl
::OnText
)
126 EVT_TEXT_URL(wxID_ANY
, wxSearchTextCtrl
::OnTextUrl
)
127 EVT_TEXT_MAXLEN(wxID_ANY
, wxSearchTextCtrl
::OnText
)
130 // ----------------------------------------------------------------------------
131 // wxSearchButton: search button used by search control
132 // ----------------------------------------------------------------------------
134 class wxSearchButton
: public wxControl
137 wxSearchButton(wxSearchCtrl
*search
, int eventType
, const wxBitmap
& bmp
)
138 : wxControl(search
, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, wxNO_BORDER
),
140 m_eventType(eventType
),
144 void SetBitmapLabel(const wxBitmap
& label
) { m_bmp
= label
; }
148 wxSize
DoGetBestSize() const
150 return wxSize(m_bmp
.GetWidth(), m_bmp
.GetHeight());
153 void OnLeftUp(wxMouseEvent
&)
155 wxCommandEvent
event(m_eventType
, m_search
->GetId());
156 event
.SetEventObject(m_search
);
158 if ( m_eventType
== wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN
)
160 // it's convenient to have the string to search for directly in the
161 // event instead of having to retrieve it from the control in the
162 // event handler code later, so provide it here
163 event
.SetString(m_search
->GetValue());
166 GetEventHandler()->ProcessEvent(event
);
168 m_search
->SetFocus();
171 if ( m_eventType
== wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN
)
173 // this happens automatically, just like on Mac OS X
174 m_search
->PopupSearchMenu();
176 #endif // wxUSE_MENUS
179 void OnPaint(wxPaintEvent
&)
182 dc
.DrawBitmap(m_bmp
, 0,0, true);
187 wxSearchCtrl
*m_search
;
188 wxEventType m_eventType
;
191 DECLARE_EVENT_TABLE()
194 BEGIN_EVENT_TABLE(wxSearchButton
, wxControl
)
195 EVT_LEFT_UP(wxSearchButton
::OnLeftUp
)
196 EVT_PAINT(wxSearchButton
::OnPaint
)
199 BEGIN_EVENT_TABLE(wxSearchCtrl
, wxSearchCtrlBase
)
200 EVT_SEARCHCTRL_SEARCH_BTN(wxID_ANY
, wxSearchCtrl
::OnSearchButton
)
201 EVT_SET_FOCUS(wxSearchCtrl
::OnSetFocus
)
202 EVT_SIZE(wxSearchCtrl
::OnSize
)
205 IMPLEMENT_DYNAMIC_CLASS(wxSearchCtrl
, wxSearchCtrlBase
)
207 // ============================================================================
209 // ============================================================================
211 // ----------------------------------------------------------------------------
212 // wxSearchCtrl creation
213 // ----------------------------------------------------------------------------
218 wxSearchCtrl
::wxSearchCtrl()
223 wxSearchCtrl
::wxSearchCtrl(wxWindow
*parent
, wxWindowID id
,
224 const wxString
& value
,
228 const wxValidator
& validator
,
229 const wxString
& name
)
233 Create(parent
, id
, value
, pos
, size
, style
, validator
, name
);
236 void wxSearchCtrl
::Init()
239 m_searchButton
= NULL
;
240 m_cancelButton
= NULL
;
243 #endif // wxUSE_MENUS
245 m_searchButtonVisible
= true;
246 m_cancelButtonVisible
= false;
248 m_searchBitmapUser
= false;
249 m_cancelBitmapUser
= false;
251 m_searchMenuBitmapUser
= false;
252 #endif // wxUSE_MENUS
255 bool wxSearchCtrl
::Create(wxWindow
*parent
, wxWindowID id
,
256 const wxString
& value
,
260 const wxValidator
& validator
,
261 const wxString
& name
)
263 // force border style for more native appearance
264 style
&= ~wxBORDER_MASK
;
266 style
|= wxBORDER_SUNKEN
;
267 #elif defined(__WXMSW__)
268 // Don't set the style explicitly, let GetDefaultBorder() work it out, unless
269 // we will get a sunken border (e.g. on Windows 200) in which case we must
270 // override with a simple border.
271 if (GetDefaultBorder() == wxBORDER_SUNKEN
)
272 style
|= wxBORDER_SIMPLE
;
274 style
|= wxBORDER_SIMPLE
;
276 if ( !wxSearchCtrlBaseBaseClass
::Create(parent
, id
, pos
, size
,
277 style
, validator
, name
) )
282 m_text
= new wxSearchTextCtrl(this, value
, style
);
284 m_searchButton
= new wxSearchButton(this,
285 wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN
,
287 m_cancelButton
= new wxSearchButton(this,
288 wxEVT_COMMAND_SEARCHCTRL_CANCEL_BTN
,
291 SetForegroundColour( m_text
->GetForegroundColour() );
292 m_searchButton
->SetForegroundColour( m_text
->GetForegroundColour() );
293 m_cancelButton
->SetForegroundColour( m_text
->GetForegroundColour() );
295 SetBackgroundColour( m_text
->GetBackgroundColour() );
296 m_searchButton
->SetBackgroundColour( m_text
->GetBackgroundColour() );
297 m_cancelButton
->SetBackgroundColour( m_text
->GetBackgroundColour() );
301 SetInitialSize(size
);
306 wxSearchCtrl
::~wxSearchCtrl()
309 delete m_searchButton
;
310 delete m_cancelButton
;
313 #endif // wxUSE_MENUS
317 // search control specific interfaces
320 void wxSearchCtrl
::SetMenu( wxMenu
* menu
)
322 if ( menu
== m_menu
)
327 bool hadMenu
= (m_menu
!= NULL
);
331 if ( m_menu
&& !hadMenu
)
333 m_searchButton
->SetBitmapLabel(m_searchMenuBitmap
);
334 m_searchButton
->Refresh();
336 else if ( !m_menu
&& hadMenu
)
338 m_searchButton
->SetBitmapLabel(m_searchBitmap
);
339 if ( m_searchButtonVisible
)
341 m_searchButton
->Refresh();
344 wxRect rect
= GetRect();
345 LayoutControls(0, 0, rect
.GetWidth(), rect
.GetHeight());
348 wxMenu
* wxSearchCtrl
::GetMenu()
353 #endif // wxUSE_MENUS
355 void wxSearchCtrl
::ShowSearchButton( bool show
)
357 if ( m_searchButtonVisible
== show
)
362 m_searchButtonVisible
= show
;
363 if ( m_searchButtonVisible
)
368 wxRect rect
= GetRect();
369 LayoutControls(0, 0, rect
.GetWidth(), rect
.GetHeight());
372 bool wxSearchCtrl
::IsSearchButtonVisible() const
374 return m_searchButtonVisible
;
378 void wxSearchCtrl
::ShowCancelButton( bool show
)
380 if ( m_cancelButtonVisible
== show
)
385 m_cancelButtonVisible
= show
;
387 wxRect rect
= GetRect();
388 LayoutControls(0, 0, rect
.GetWidth(), rect
.GetHeight());
391 bool wxSearchCtrl
::IsCancelButtonVisible() const
393 return m_cancelButtonVisible
;
396 void wxSearchCtrl
::SetDescriptiveText(const wxString
& text
)
398 m_text
->SetHint(text
);
401 wxString wxSearchCtrl
::GetDescriptiveText() const
403 return m_text
->GetHint();
406 // ----------------------------------------------------------------------------
408 // ----------------------------------------------------------------------------
410 wxSize wxSearchCtrl
::DoGetBestSize() const
412 wxSize sizeText
= m_text
->GetBestSize();
413 wxSize
sizeSearch(0,0);
414 wxSize
sizeCancel(0,0);
415 int searchMargin
= 0;
416 int cancelMargin
= 0;
417 if ( m_searchButtonVisible
|| HasMenu() )
419 sizeSearch
= m_searchButton
->GetBestSize();
420 searchMargin
= MARGIN
;
422 if ( m_cancelButtonVisible
)
424 sizeCancel
= m_cancelButton
->GetBestSize();
425 cancelMargin
= MARGIN
;
428 int horizontalBorder
= 1 + ( sizeText
.y
- sizeText
.y
* 14 / 21 ) / 2;
430 // buttons are square and equal to the height of the text control
431 int height
= sizeText
.y
;
432 return wxSize(sizeSearch
.x
+ searchMargin
+ sizeText
.x
+ cancelMargin
+ sizeCancel
.x
+ 2*horizontalBorder
,
436 void wxSearchCtrl
::DoMoveWindow(int x
, int y
, int width
, int height
)
438 wxSearchCtrlBase
::DoMoveWindow(x
, y
, width
, height
);
440 LayoutControls(0, 0, width
, height
);
443 void wxSearchCtrl
::LayoutControls(int x
, int y
, int width
, int height
)
448 wxSize sizeText
= m_text
->GetBestSize();
449 // make room for the search menu & clear button
450 int horizontalBorder
= ( sizeText
.y
- sizeText
.y
* 14 / 21 ) / 2;
451 x
+= horizontalBorder
;
453 width
-= horizontalBorder
*2;
455 if (width
< 0) width
= 0;
456 if (height
< 0) height
= 0;
458 wxSize
sizeSearch(0,0);
459 wxSize
sizeCancel(0,0);
460 int searchMargin
= 0;
461 int cancelMargin
= 0;
462 if ( m_searchButtonVisible
|| HasMenu() )
464 sizeSearch
= m_searchButton
->GetBestSize();
465 searchMargin
= MARGIN
;
467 if ( m_cancelButtonVisible
)
469 sizeCancel
= m_cancelButton
->GetBestSize();
470 cancelMargin
= MARGIN
;
472 m_searchButton
->Show( m_searchButtonVisible
|| HasMenu() );
473 m_cancelButton
->Show( m_cancelButtonVisible
);
475 if ( sizeSearch
.x
+ sizeCancel
.x
> width
)
477 sizeSearch
.x
= width
/2;
478 sizeCancel
.x
= width
/2;
482 wxCoord textWidth
= width
- sizeSearch
.x
- sizeCancel
.x
- searchMargin
- cancelMargin
- 1;
483 if (textWidth
< 0) textWidth
= 0;
485 // position the subcontrols inside the client area
487 m_searchButton
->SetSize(x
, y
+ ICON_OFFSET
- 1, sizeSearch
.x
, height
);
488 m_text
->SetSize( x
+ sizeSearch
.x
+ searchMargin
,
489 y
+ ICON_OFFSET
- BORDER
,
492 m_cancelButton
->SetSize(x
+ sizeSearch
.x
+ searchMargin
+ textWidth
+ cancelMargin
,
493 y
+ ICON_OFFSET
- 1, sizeCancel
.x
, height
);
500 wxString wxSearchCtrl
::DoGetValue() const
502 return m_text
->GetValue();
504 wxString wxSearchCtrl
::GetRange(long from
, long to
) const
506 return m_text
->GetRange(from
, to
);
509 int wxSearchCtrl
::GetLineLength(long lineNo
) const
511 return m_text
->GetLineLength(lineNo
);
513 wxString wxSearchCtrl
::GetLineText(long lineNo
) const
515 return m_text
->GetLineText(lineNo
);
517 int wxSearchCtrl
::GetNumberOfLines() const
519 return m_text
->GetNumberOfLines();
522 bool wxSearchCtrl
::IsModified() const
524 return m_text
->IsModified();
526 bool wxSearchCtrl
::IsEditable() const
528 return m_text
->IsEditable();
531 // more readable flag testing methods
532 bool wxSearchCtrl
::IsSingleLine() const
534 return m_text
->IsSingleLine();
536 bool wxSearchCtrl
::IsMultiLine() const
538 return m_text
->IsMultiLine();
541 // If the return values from and to are the same, there is no selection.
542 void wxSearchCtrl
::GetSelection(long* from
, long* to
) const
544 m_text
->GetSelection(from
, to
);
547 wxString wxSearchCtrl
::GetStringSelection() const
549 return m_text
->GetStringSelection();
556 void wxSearchCtrl
::Clear()
560 void wxSearchCtrl
::Replace(long from
, long to
, const wxString
& value
)
562 m_text
->Replace(from
, to
, value
);
564 void wxSearchCtrl
::Remove(long from
, long to
)
566 m_text
->Remove(from
, to
);
569 // load/save the controls contents from/to the file
570 bool wxSearchCtrl
::LoadFile(const wxString
& file
)
572 return m_text
->LoadFile(file
);
574 bool wxSearchCtrl
::SaveFile(const wxString
& file
)
576 return m_text
->SaveFile(file
);
579 // sets/clears the dirty flag
580 void wxSearchCtrl
::MarkDirty()
584 void wxSearchCtrl
::DiscardEdits()
586 m_text
->DiscardEdits();
589 // set the max number of characters which may be entered in a single line
591 void wxSearchCtrl
::SetMaxLength(unsigned long len
)
593 m_text
->SetMaxLength(len
);
596 // writing text inserts it at the current position, appending always
597 // inserts it at the end
598 void wxSearchCtrl
::WriteText(const wxString
& text
)
600 m_text
->WriteText(text
);
602 void wxSearchCtrl
::AppendText(const wxString
& text
)
604 m_text
->AppendText(text
);
607 // insert the character which would have resulted from this key event,
608 // return true if anything has been inserted
609 bool wxSearchCtrl
::EmulateKeyPress(const wxKeyEvent
& event
)
611 return m_text
->EmulateKeyPress(event
);
614 // text control under some platforms supports the text styles: these
615 // methods allow to apply the given text style to the given selection or to
616 // set/get the style which will be used for all appended text
617 bool wxSearchCtrl
::SetStyle(long start
, long end
, const wxTextAttr
& style
)
619 return m_text
->SetStyle(start
, end
, style
);
621 bool wxSearchCtrl
::GetStyle(long position
, wxTextAttr
& style
)
623 return m_text
->GetStyle(position
, style
);
625 bool wxSearchCtrl
::SetDefaultStyle(const wxTextAttr
& style
)
627 return m_text
->SetDefaultStyle(style
);
629 const wxTextAttr
& wxSearchCtrl
::GetDefaultStyle() const
631 return m_text
->GetDefaultStyle();
634 // translate between the position (which is just an index in the text ctrl
635 // considering all its contents as a single strings) and (x, y) coordinates
636 // which represent column and line.
637 long wxSearchCtrl
::XYToPosition(long x
, long y
) const
639 return m_text
->XYToPosition(x
, y
);
641 bool wxSearchCtrl
::PositionToXY(long pos
, long *x
, long *y
) const
643 return m_text
->PositionToXY(pos
, x
, y
);
646 void wxSearchCtrl
::ShowPosition(long pos
)
648 m_text
->ShowPosition(pos
);
651 // find the character at position given in pixels
653 // NB: pt is in device coords (not adjusted for the client area origin nor
655 wxTextCtrlHitTestResult wxSearchCtrl
::HitTest(const wxPoint
& pt
, long *pos
) const
657 return m_text
->HitTest(pt
, pos
);
659 wxTextCtrlHitTestResult wxSearchCtrl
::HitTest(const wxPoint
& pt
,
661 wxTextCoord
*row
) const
663 return m_text
->HitTest(pt
, col
, row
);
666 // Clipboard operations
667 void wxSearchCtrl
::Copy()
671 void wxSearchCtrl
::Cut()
675 void wxSearchCtrl
::Paste()
680 bool wxSearchCtrl
::CanCopy() const
682 return m_text
->CanCopy();
684 bool wxSearchCtrl
::CanCut() const
686 return m_text
->CanCut();
688 bool wxSearchCtrl
::CanPaste() const
690 return m_text
->CanPaste();
694 void wxSearchCtrl
::Undo()
698 void wxSearchCtrl
::Redo()
703 bool wxSearchCtrl
::CanUndo() const
705 return m_text
->CanUndo();
707 bool wxSearchCtrl
::CanRedo() const
709 return m_text
->CanRedo();
713 void wxSearchCtrl
::SetInsertionPoint(long pos
)
715 m_text
->SetInsertionPoint(pos
);
717 void wxSearchCtrl
::SetInsertionPointEnd()
719 m_text
->SetInsertionPointEnd();
721 long wxSearchCtrl
::GetInsertionPoint() const
723 return m_text
->GetInsertionPoint();
725 long wxSearchCtrl
::GetLastPosition() const
727 return m_text
->GetLastPosition();
730 void wxSearchCtrl
::SetSelection(long from
, long to
)
732 m_text
->SetSelection(from
, to
);
734 void wxSearchCtrl
::SelectAll()
739 void wxSearchCtrl
::SetEditable(bool editable
)
741 m_text
->SetEditable(editable
);
744 bool wxSearchCtrl
::SetFont(const wxFont
& font
)
746 bool result
= wxSearchCtrlBase
::SetFont(font
);
747 if ( result
&& m_text
)
749 result
= m_text
->SetFont(font
);
755 // search control generic only
756 void wxSearchCtrl
::SetSearchBitmap( const wxBitmap
& bitmap
)
758 m_searchBitmap
= bitmap
;
759 m_searchBitmapUser
= bitmap
.IsOk();
760 if ( m_searchBitmapUser
)
762 if ( m_searchButton
&& !HasMenu() )
764 m_searchButton
->SetBitmapLabel( m_searchBitmap
);
769 // the user bitmap was just cleared, generate one
776 void wxSearchCtrl
::SetSearchMenuBitmap( const wxBitmap
& bitmap
)
778 m_searchMenuBitmap
= bitmap
;
779 m_searchMenuBitmapUser
= bitmap
.IsOk();
780 if ( m_searchMenuBitmapUser
)
782 if ( m_searchButton
&& m_menu
)
784 m_searchButton
->SetBitmapLabel( m_searchMenuBitmap
);
789 // the user bitmap was just cleared, generate one
794 #endif // wxUSE_MENUS
796 void wxSearchCtrl
::SetCancelBitmap( const wxBitmap
& bitmap
)
798 m_cancelBitmap
= bitmap
;
799 m_cancelBitmapUser
= bitmap
.IsOk();
800 if ( m_cancelBitmapUser
)
802 if ( m_cancelButton
)
804 m_cancelButton
->SetBitmapLabel( m_cancelBitmap
);
809 // the user bitmap was just cleared, generate one
816 // override streambuf method
817 #if wxHAS_TEXT_WINDOW_STREAM
819 #endif // wxHAS_TEXT_WINDOW_STREAM
821 // stream-like insertion operators: these are always available, whether we
822 // were, or not, compiled with streambuf support
823 wxTextCtrl
& operator<<(const wxString
& s
);
824 wxTextCtrl
& operator<<(int i
);
825 wxTextCtrl
& operator<<(long i
);
826 wxTextCtrl
& operator<<(float f
);
827 wxTextCtrl
& operator<<(double d
);
828 wxTextCtrl
& operator<<(const wxChar c
);
831 void wxSearchCtrl
::DoSetValue(const wxString
& value
, int flags
)
833 m_text
->DoSetValue(value
, flags
);
836 bool wxSearchCtrl
::DoLoadFile(const wxString
& file
, int fileType
)
838 return m_text
->DoLoadFile(file
, fileType
);
841 bool wxSearchCtrl
::DoSaveFile(const wxString
& file
, int fileType
)
843 return m_text
->DoSaveFile(file
, fileType
);
846 // do the window-specific processing after processing the update event
847 void wxSearchCtrl
::DoUpdateWindowUI(wxUpdateUIEvent
& event
)
849 wxSearchCtrlBase
::DoUpdateWindowUI(event
);
852 bool wxSearchCtrl
::ShouldInheritColours() const
857 // icons are rendered at 3-8 times larger than necessary and downscaled for
859 static int GetMultiplier()
862 // speed up bitmap generation by using a small bitmap
865 int depth
= ::wxDisplayDepth();
875 wxBitmap wxSearchCtrl
::RenderSearchBitmap( int x
, int y
, bool renderDrop
)
877 wxColour bg
= GetBackgroundColour();
878 wxColour fg
= GetForegroundColour().ChangeLightness(LIGHT_STEP
-20);
880 //===============================================================================
881 // begin drawing code
882 //===============================================================================
885 // force width:height ratio
897 // glass 11x11, top left corner
898 // handle (9,9)-(13,13)
899 // drop (13,16)-(19,6)-(16,9)
901 int multiplier
= GetMultiplier();
902 int penWidth
= multiplier
* 2;
904 penWidth
= penWidth
* x
/ 20;
906 wxBitmap
bitmap( multiplier
*x
, multiplier
*y
);
908 mem
.SelectObject(bitmap
);
911 mem
.SetBrush( wxBrush(bg
) );
912 mem
.SetPen( wxPen(bg
) );
913 mem
.DrawRectangle(0,0,bitmap
.GetWidth(),bitmap
.GetHeight());
916 mem
.SetBrush( wxBrush(fg
) );
917 mem
.SetPen( wxPen(fg
) );
918 int glassBase
= 5 * x
/ 20;
919 int glassFactor
= 2*glassBase
+ 1;
920 int radius
= multiplier
*glassFactor
/2;
921 mem
.DrawCircle(radius
,radius
,radius
);
922 mem
.SetBrush( wxBrush(bg
) );
923 mem
.SetPen( wxPen(bg
) );
924 mem
.DrawCircle(radius
,radius
,radius
-penWidth
);
927 int lineStart
= radius
+ (radius
-penWidth
/2) * 707 / 1000; // 707 / 1000 = 0.707 = 1/sqrt(2);
929 mem
.SetPen( wxPen(fg
) );
930 mem
.SetBrush( wxBrush(fg
) );
931 int handleCornerShift
= penWidth
* 707 / 1000 / 2; // 707 / 1000 = 0.707 = 1/sqrt(2);
932 handleCornerShift
= WXMAX( handleCornerShift
, 1 );
933 int handleBase
= 4 * x
/ 20;
934 int handleLength
= 2*handleBase
+1;
935 wxPoint handlePolygon
[] =
937 wxPoint(-handleCornerShift
,+handleCornerShift
),
938 wxPoint(+handleCornerShift
,-handleCornerShift
),
939 wxPoint(multiplier
*handleLength
/2+handleCornerShift
,multiplier
*handleLength
/2-handleCornerShift
),
940 wxPoint(multiplier
*handleLength
/2-handleCornerShift
,multiplier
*handleLength
/2+handleCornerShift
),
942 mem
.DrawPolygon(WXSIZEOF(handlePolygon
),handlePolygon
,lineStart
,lineStart
);
944 // draw drop triangle
945 int triangleX
= 13 * x
/ 20;
946 int triangleY
= 5 * x
/ 20;
947 int triangleBase
= 3 * x
/ 20;
948 int triangleFactor
= triangleBase
*2+1;
951 wxPoint dropPolygon
[] =
953 wxPoint(multiplier
*0,multiplier
*0), // triangle left
954 wxPoint(multiplier
*triangleFactor
-1,multiplier
*0), // triangle right
955 wxPoint(multiplier
*triangleFactor
/2,multiplier
*triangleFactor
/2), // triangle bottom
957 mem
.DrawPolygon(WXSIZEOF(dropPolygon
),dropPolygon
,multiplier
*triangleX
,multiplier
*triangleY
);
959 mem
.SelectObject(wxNullBitmap
);
961 //===============================================================================
963 //===============================================================================
965 if ( multiplier
!= 1 )
967 wxImage image
= bitmap
.ConvertToImage();
969 bitmap
= wxBitmap( image
);
973 // Trim the edge where the arrow would have gone
974 bitmap
= bitmap
.GetSubBitmap(wxRect(0,0, y
,y
));
980 wxBitmap wxSearchCtrl
::RenderCancelBitmap( int x
, int y
)
982 wxColour bg
= GetBackgroundColour();
983 wxColour fg
= GetForegroundColour().ChangeLightness(LIGHT_STEP
);
985 //===============================================================================
986 // begin drawing code
987 //===============================================================================
1004 // cross line starts (4,4)-(10,10)
1005 // drop (13,16)-(19,6)-(16,9)
1007 int multiplier
= GetMultiplier();
1009 int penWidth
= multiplier
* x
/ 14;
1011 wxBitmap
bitmap( multiplier
*x
, multiplier
*y
);
1013 mem
.SelectObject(bitmap
);
1016 mem
.SetBrush( wxBrush(bg
) );
1017 mem
.SetPen( wxPen(bg
) );
1018 mem
.DrawRectangle(0,0,bitmap
.GetWidth(),bitmap
.GetHeight());
1021 mem
.SetBrush( wxBrush(fg
) );
1022 mem
.SetPen( wxPen(fg
) );
1023 int radius
= multiplier
*x
/2;
1024 mem
.DrawCircle(radius
,radius
,radius
);
1027 int lineStartBase
= 4 * x
/ 14;
1028 int lineLength
= x
- 2*lineStartBase
;
1030 mem
.SetPen( wxPen(bg
) );
1031 mem
.SetBrush( wxBrush(bg
) );
1032 int handleCornerShift
= penWidth
/2;
1033 handleCornerShift
= WXMAX( handleCornerShift
, 1 );
1034 wxPoint handlePolygon
[] =
1036 wxPoint(-handleCornerShift
,+handleCornerShift
),
1037 wxPoint(+handleCornerShift
,-handleCornerShift
),
1038 wxPoint(multiplier
*lineLength
+handleCornerShift
,multiplier
*lineLength
-handleCornerShift
),
1039 wxPoint(multiplier
*lineLength
-handleCornerShift
,multiplier
*lineLength
+handleCornerShift
),
1041 mem
.DrawPolygon(WXSIZEOF(handlePolygon
),handlePolygon
,multiplier
*lineStartBase
,multiplier
*lineStartBase
);
1042 wxPoint handlePolygon2
[] =
1044 wxPoint(+handleCornerShift
,+handleCornerShift
),
1045 wxPoint(-handleCornerShift
,-handleCornerShift
),
1046 wxPoint(multiplier
*lineLength
-handleCornerShift
,-multiplier
*lineLength
-handleCornerShift
),
1047 wxPoint(multiplier
*lineLength
+handleCornerShift
,-multiplier
*lineLength
+handleCornerShift
),
1049 mem
.DrawPolygon(WXSIZEOF(handlePolygon2
),handlePolygon2
,multiplier
*lineStartBase
,multiplier
*(x
-lineStartBase
));
1051 //===============================================================================
1053 //===============================================================================
1055 if ( multiplier
!= 1 )
1057 wxImage image
= bitmap
.ConvertToImage();
1059 bitmap
= wxBitmap( image
);
1065 void wxSearchCtrl
::RecalcBitmaps()
1071 wxSize sizeText
= m_text
->GetBestSize();
1073 int bitmapHeight
= sizeText
.y
- 2 * ICON_MARGIN
;
1074 int bitmapWidth
= sizeText
.y
* 20 / 14;
1076 if ( !m_searchBitmapUser
)
1079 !m_searchBitmap
.IsOk() ||
1080 m_searchBitmap
.GetHeight() != bitmapHeight
||
1081 m_searchBitmap
.GetWidth() != bitmapWidth
1084 m_searchBitmap
= RenderSearchBitmap(bitmapWidth
,bitmapHeight
,false);
1087 m_searchButton
->SetBitmapLabel(m_searchBitmap
);
1090 // else this bitmap was set by user, don't alter
1094 if ( !m_searchMenuBitmapUser
)
1097 !m_searchMenuBitmap
.IsOk() ||
1098 m_searchMenuBitmap
.GetHeight() != bitmapHeight
||
1099 m_searchMenuBitmap
.GetWidth() != bitmapWidth
1102 m_searchMenuBitmap
= RenderSearchBitmap(bitmapWidth
,bitmapHeight
,true);
1105 m_searchButton
->SetBitmapLabel(m_searchMenuBitmap
);
1108 // else this bitmap was set by user, don't alter
1110 #endif // wxUSE_MENUS
1112 if ( !m_cancelBitmapUser
)
1115 !m_cancelBitmap
.IsOk() ||
1116 m_cancelBitmap
.GetHeight() != bitmapHeight
||
1117 m_cancelBitmap
.GetWidth() != bitmapHeight
1120 m_cancelBitmap
= RenderCancelBitmap(bitmapHeight
-BORDER
-1,bitmapHeight
-BORDER
-1); // square
1121 m_cancelButton
->SetBitmapLabel(m_cancelBitmap
);
1123 // else this bitmap was set by user, don't alter
1127 void wxSearchCtrl
::OnSearchButton( wxCommandEvent
& event
)
1132 void wxSearchCtrl
::OnSetFocus( wxFocusEvent
& /*event*/ )
1140 void wxSearchCtrl
::OnSize( wxSizeEvent
& WXUNUSED(event
) )
1143 GetSize(&width
, &height
);
1144 LayoutControls(0, 0, width
, height
);
1149 void wxSearchCtrl
::PopupSearchMenu()
1153 wxSize size
= GetSize();
1154 PopupMenu( m_menu
, 0, size
.y
);
1158 #endif // wxUSE_MENUS
1160 #endif // !wxUSE_NATIVE_SEARCH_CONTROL
1162 #endif // wxUSE_SEARCHCTRL