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
,
67 m_defaultFG
= GetForegroundColour();
69 // remove the default minsize, the searchctrl will have one instead
70 SetSizeHints(wxDefaultCoord
,wxDefaultCoord
);
73 void SetDescriptiveText(const wxString
& text
)
75 if ( GetValue() == m_descriptiveText
)
77 ChangeValue(wxEmptyString
);
80 m_descriptiveText
= text
;
83 wxString
GetDescriptiveText() const
85 return m_descriptiveText
;
89 // provide access to the base class protected methods to wxSearchCtrl which
90 // needs to forward to them
91 void DoSetValue(const wxString
& value
, int flags
)
93 wxTextCtrl::DoSetValue(value
, flags
);
96 bool DoLoadFile(const wxString
& file
, int fileType
)
98 return wxTextCtrl::DoLoadFile(file
, fileType
);
101 bool DoSaveFile(const wxString
& file
, int fileType
)
103 return wxTextCtrl::DoSaveFile(file
, fileType
);
107 void OnText(wxCommandEvent
& eventText
)
109 wxCommandEvent
event(eventText
);
110 event
.SetEventObject(m_search
);
111 event
.SetId(m_search
->GetId());
113 m_search
->GetEventHandler()->ProcessEvent(event
);
116 void OnTextUrl(wxTextUrlEvent
& eventText
)
118 // copy constructor is disabled for some reason?
119 //wxTextUrlEvent event(eventText);
120 wxTextUrlEvent
event(
122 eventText
.GetMouseEvent(),
123 eventText
.GetURLStart(),
124 eventText
.GetURLEnd()
126 event
.SetEventObject(m_search
);
128 m_search
->GetEventHandler()->ProcessEvent(event
);
131 void OnIdle(wxIdleEvent
& WXUNUSED(event
))
133 if ( IsEmpty() && !(wxWindow::FindFocus() == this) )
135 ChangeValue(m_descriptiveText
);
136 SetInsertionPoint(0);
137 SetForegroundColour(m_defaultFG
.ChangeLightness (LIGHT_STEP
));
141 void OnFocus(wxFocusEvent
& event
)
144 if ( GetValue() == m_descriptiveText
)
146 ChangeValue(wxEmptyString
);
147 SetForegroundColour(m_defaultFG
);
152 wxSearchCtrl
* m_search
;
153 wxString m_descriptiveText
;
154 wxColour m_defaultFG
;
156 DECLARE_EVENT_TABLE()
159 BEGIN_EVENT_TABLE(wxSearchTextCtrl
, wxTextCtrl
)
160 EVT_TEXT(wxID_ANY
, wxSearchTextCtrl::OnText
)
161 EVT_TEXT_ENTER(wxID_ANY
, wxSearchTextCtrl::OnText
)
162 EVT_TEXT_URL(wxID_ANY
, wxSearchTextCtrl::OnTextUrl
)
163 EVT_TEXT_MAXLEN(wxID_ANY
, wxSearchTextCtrl::OnText
)
164 EVT_IDLE(wxSearchTextCtrl::OnIdle
)
165 EVT_SET_FOCUS(wxSearchTextCtrl::OnFocus
)
168 // ----------------------------------------------------------------------------
169 // wxSearchButton: search button used by search control
170 // ----------------------------------------------------------------------------
172 class wxSearchButton
: public wxControl
175 wxSearchButton(wxSearchCtrl
*search
, int eventType
, const wxBitmap
& bmp
)
176 : wxControl(search
, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, wxNO_BORDER
),
178 m_eventType(eventType
),
182 void SetBitmapLabel(const wxBitmap
& label
) { m_bmp
= label
; }
186 wxSize
DoGetBestSize() const
188 return wxSize(m_bmp
.GetWidth(), m_bmp
.GetHeight());
191 void OnLeftUp(wxMouseEvent
&)
193 wxCommandEvent
event(m_eventType
, m_search
->GetId());
194 event
.SetEventObject(m_search
);
196 if ( m_eventType
== wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN
)
198 // it's convenient to have the string to search for directly in the
199 // event instead of having to retrieve it from the control in the
200 // event handler code later, so provide it here
201 event
.SetString(m_search
->GetValue());
204 GetEventHandler()->ProcessEvent(event
);
206 m_search
->SetFocus();
209 if ( m_eventType
== wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN
)
211 // this happens automatically, just like on Mac OS X
212 m_search
->PopupSearchMenu();
214 #endif // wxUSE_MENUS
217 void OnPaint(wxPaintEvent
&)
220 dc
.DrawBitmap(m_bmp
, 0,0, true);
225 wxSearchCtrl
*m_search
;
226 wxEventType m_eventType
;
229 DECLARE_EVENT_TABLE()
232 BEGIN_EVENT_TABLE(wxSearchButton
, wxControl
)
233 EVT_LEFT_UP(wxSearchButton::OnLeftUp
)
234 EVT_PAINT(wxSearchButton::OnPaint
)
237 BEGIN_EVENT_TABLE(wxSearchCtrl
, wxSearchCtrlBase
)
238 EVT_SEARCHCTRL_SEARCH_BTN(wxID_ANY
, wxSearchCtrl::OnSearchButton
)
239 EVT_SET_FOCUS(wxSearchCtrl::OnSetFocus
)
240 EVT_SIZE(wxSearchCtrl::OnSize
)
243 IMPLEMENT_DYNAMIC_CLASS(wxSearchCtrl
, wxSearchCtrlBase
)
245 // ============================================================================
247 // ============================================================================
249 // ----------------------------------------------------------------------------
250 // wxSearchCtrl creation
251 // ----------------------------------------------------------------------------
256 wxSearchCtrl::wxSearchCtrl()
261 wxSearchCtrl::wxSearchCtrl(wxWindow
*parent
, wxWindowID id
,
262 const wxString
& value
,
266 const wxValidator
& validator
,
267 const wxString
& name
)
271 Create(parent
, id
, value
, pos
, size
, style
, validator
, name
);
274 void wxSearchCtrl::Init()
277 m_searchButton
= NULL
;
278 m_cancelButton
= NULL
;
281 #endif // wxUSE_MENUS
283 m_searchButtonVisible
= true;
284 m_cancelButtonVisible
= false;
286 m_searchBitmapUser
= false;
287 m_cancelBitmapUser
= false;
289 m_searchMenuBitmapUser
= false;
290 #endif // wxUSE_MENUS
293 bool wxSearchCtrl::Create(wxWindow
*parent
, wxWindowID id
,
294 const wxString
& value
,
298 const wxValidator
& validator
,
299 const wxString
& name
)
301 // force border style for more native appearance
302 style
&= ~wxBORDER_MASK
;
304 style
|= wxBORDER_SUNKEN
;
305 #elif defined(__WXMSW__)
306 // Don't set the style explicitly, let GetDefaultBorder() work it out, unless
307 // we will get a sunken border (e.g. on Windows 200) in which case we must
308 // override with a simple border.
309 if (GetDefaultBorder() == wxBORDER_SUNKEN
)
310 style
|= wxBORDER_SIMPLE
;
312 style
|= wxBORDER_SIMPLE
;
314 if ( !wxSearchCtrlBaseBaseClass::Create(parent
, id
, pos
, size
,
315 style
, validator
, name
) )
320 m_text
= new wxSearchTextCtrl(this, value
, style
& ~wxBORDER_MASK
);
321 m_text
->SetDescriptiveText(_("Search"));
323 m_searchButton
= new wxSearchButton(this,
324 wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN
,
326 m_cancelButton
= new wxSearchButton(this,
327 wxEVT_COMMAND_SEARCHCTRL_CANCEL_BTN
,
330 SetForegroundColour( m_text
->GetForegroundColour() );
331 m_searchButton
->SetForegroundColour( m_text
->GetForegroundColour() );
332 m_cancelButton
->SetForegroundColour( m_text
->GetForegroundColour() );
334 SetBackgroundColour( m_text
->GetBackgroundColour() );
335 m_searchButton
->SetBackgroundColour( m_text
->GetBackgroundColour() );
336 m_cancelButton
->SetBackgroundColour( m_text
->GetBackgroundColour() );
340 SetInitialSize(size
);
345 wxSearchCtrl::~wxSearchCtrl()
348 delete m_searchButton
;
349 delete m_cancelButton
;
352 #endif // wxUSE_MENUS
356 // search control specific interfaces
359 void wxSearchCtrl::SetMenu( wxMenu
* menu
)
361 if ( menu
== m_menu
)
366 bool hadMenu
= (m_menu
!= NULL
);
370 if ( m_menu
&& !hadMenu
)
372 m_searchButton
->SetBitmapLabel(m_searchMenuBitmap
);
373 m_searchButton
->Refresh();
375 else if ( !m_menu
&& hadMenu
)
377 m_searchButton
->SetBitmapLabel(m_searchBitmap
);
378 if ( m_searchButtonVisible
)
380 m_searchButton
->Refresh();
383 wxRect rect
= GetRect();
384 LayoutControls(0, 0, rect
.GetWidth(), rect
.GetHeight());
387 wxMenu
* wxSearchCtrl::GetMenu()
392 #endif // wxUSE_MENUS
394 void wxSearchCtrl::ShowSearchButton( bool show
)
396 if ( m_searchButtonVisible
== show
)
401 m_searchButtonVisible
= show
;
402 if ( m_searchButtonVisible
)
407 wxRect rect
= GetRect();
408 LayoutControls(0, 0, rect
.GetWidth(), rect
.GetHeight());
411 bool wxSearchCtrl::IsSearchButtonVisible() const
413 return m_searchButtonVisible
;
417 void wxSearchCtrl::ShowCancelButton( bool show
)
419 if ( m_cancelButtonVisible
== show
)
424 m_cancelButtonVisible
= show
;
426 wxRect rect
= GetRect();
427 LayoutControls(0, 0, rect
.GetWidth(), rect
.GetHeight());
430 bool wxSearchCtrl::IsCancelButtonVisible() const
432 return m_cancelButtonVisible
;
435 void wxSearchCtrl::SetDescriptiveText(const wxString
& text
)
437 m_text
->SetDescriptiveText(text
);
440 wxString
wxSearchCtrl::GetDescriptiveText() const
442 return m_text
->GetDescriptiveText();
445 // ----------------------------------------------------------------------------
447 // ----------------------------------------------------------------------------
449 wxSize
wxSearchCtrl::DoGetBestSize() const
451 wxSize sizeText
= m_text
->GetBestSize();
452 wxSize
sizeSearch(0,0);
453 wxSize
sizeCancel(0,0);
454 int searchMargin
= 0;
455 int cancelMargin
= 0;
456 if ( m_searchButtonVisible
|| HasMenu() )
458 sizeSearch
= m_searchButton
->GetBestSize();
459 searchMargin
= MARGIN
;
461 if ( m_cancelButtonVisible
)
463 sizeCancel
= m_cancelButton
->GetBestSize();
464 cancelMargin
= MARGIN
;
467 int horizontalBorder
= 1 + ( sizeText
.y
- sizeText
.y
* 14 / 21 ) / 2;
469 // buttons are square and equal to the height of the text control
470 int height
= sizeText
.y
;
471 return wxSize(sizeSearch
.x
+ searchMargin
+ sizeText
.x
+ cancelMargin
+ sizeCancel
.x
+ 2*horizontalBorder
,
475 void wxSearchCtrl::DoMoveWindow(int x
, int y
, int width
, int height
)
477 wxSearchCtrlBase::DoMoveWindow(x
, y
, width
, height
);
479 LayoutControls(0, 0, width
, height
);
482 void wxSearchCtrl::LayoutControls(int x
, int y
, int width
, int height
)
487 wxSize sizeText
= m_text
->GetBestSize();
488 // make room for the search menu & clear button
489 int horizontalBorder
= ( sizeText
.y
- sizeText
.y
* 14 / 21 ) / 2;
490 x
+= horizontalBorder
;
492 width
-= horizontalBorder
*2;
494 if (width
< 0) width
= 0;
495 if (height
< 0) height
= 0;
497 wxSize
sizeSearch(0,0);
498 wxSize
sizeCancel(0,0);
499 int searchMargin
= 0;
500 int cancelMargin
= 0;
501 if ( m_searchButtonVisible
|| HasMenu() )
503 sizeSearch
= m_searchButton
->GetBestSize();
504 searchMargin
= MARGIN
;
506 if ( m_cancelButtonVisible
)
508 sizeCancel
= m_cancelButton
->GetBestSize();
509 cancelMargin
= MARGIN
;
511 m_searchButton
->Show( m_searchButtonVisible
|| HasMenu() );
512 m_cancelButton
->Show( m_cancelButtonVisible
);
514 if ( sizeSearch
.x
+ sizeCancel
.x
> width
)
516 sizeSearch
.x
= width
/2;
517 sizeCancel
.x
= width
/2;
521 wxCoord textWidth
= width
- sizeSearch
.x
- sizeCancel
.x
- searchMargin
- cancelMargin
- 1;
522 if (textWidth
< 0) textWidth
= 0;
524 // position the subcontrols inside the client area
526 m_searchButton
->SetSize(x
, y
+ ICON_OFFSET
- 1, sizeSearch
.x
, height
);
527 m_text
->SetSize( x
+ sizeSearch
.x
+ searchMargin
,
528 y
+ ICON_OFFSET
- BORDER
,
531 m_cancelButton
->SetSize(x
+ sizeSearch
.x
+ searchMargin
+ textWidth
+ cancelMargin
,
532 y
+ ICON_OFFSET
- 1, sizeCancel
.x
, height
);
539 wxString
wxSearchCtrl::DoGetValue() const
541 wxString value
= m_text
->GetValue();
542 if (value
== m_text
->GetDescriptiveText())
543 return wxEmptyString
;
547 wxString
wxSearchCtrl::GetRange(long from
, long to
) const
549 return m_text
->GetRange(from
, to
);
552 int wxSearchCtrl::GetLineLength(long lineNo
) const
554 return m_text
->GetLineLength(lineNo
);
556 wxString
wxSearchCtrl::GetLineText(long lineNo
) const
558 return m_text
->GetLineText(lineNo
);
560 int wxSearchCtrl::GetNumberOfLines() const
562 return m_text
->GetNumberOfLines();
565 bool wxSearchCtrl::IsModified() const
567 return m_text
->IsModified();
569 bool wxSearchCtrl::IsEditable() const
571 return m_text
->IsEditable();
574 // more readable flag testing methods
575 bool wxSearchCtrl::IsSingleLine() const
577 return m_text
->IsSingleLine();
579 bool wxSearchCtrl::IsMultiLine() const
581 return m_text
->IsMultiLine();
584 // If the return values from and to are the same, there is no selection.
585 void wxSearchCtrl::GetSelection(long* from
, long* to
) const
587 m_text
->GetSelection(from
, to
);
590 wxString
wxSearchCtrl::GetStringSelection() const
592 return m_text
->GetStringSelection();
599 void wxSearchCtrl::Clear()
603 void wxSearchCtrl::Replace(long from
, long to
, const wxString
& value
)
605 m_text
->Replace(from
, to
, value
);
607 void wxSearchCtrl::Remove(long from
, long to
)
609 m_text
->Remove(from
, to
);
612 // load/save the controls contents from/to the file
613 bool wxSearchCtrl::LoadFile(const wxString
& file
)
615 return m_text
->LoadFile(file
);
617 bool wxSearchCtrl::SaveFile(const wxString
& file
)
619 return m_text
->SaveFile(file
);
622 // sets/clears the dirty flag
623 void wxSearchCtrl::MarkDirty()
627 void wxSearchCtrl::DiscardEdits()
629 m_text
->DiscardEdits();
632 // set the max number of characters which may be entered in a single line
634 void wxSearchCtrl::SetMaxLength(unsigned long len
)
636 m_text
->SetMaxLength(len
);
639 // writing text inserts it at the current position, appending always
640 // inserts it at the end
641 void wxSearchCtrl::WriteText(const wxString
& text
)
643 m_text
->WriteText(text
);
645 void wxSearchCtrl::AppendText(const wxString
& text
)
647 m_text
->AppendText(text
);
650 // insert the character which would have resulted from this key event,
651 // return true if anything has been inserted
652 bool wxSearchCtrl::EmulateKeyPress(const wxKeyEvent
& event
)
654 return m_text
->EmulateKeyPress(event
);
657 // text control under some platforms supports the text styles: these
658 // methods allow to apply the given text style to the given selection or to
659 // set/get the style which will be used for all appended text
660 bool wxSearchCtrl::SetStyle(long start
, long end
, const wxTextAttr
& style
)
662 return m_text
->SetStyle(start
, end
, style
);
664 bool wxSearchCtrl::GetStyle(long position
, wxTextAttr
& style
)
666 return m_text
->GetStyle(position
, style
);
668 bool wxSearchCtrl::SetDefaultStyle(const wxTextAttr
& style
)
670 return m_text
->SetDefaultStyle(style
);
672 const wxTextAttr
& wxSearchCtrl::GetDefaultStyle() const
674 return m_text
->GetDefaultStyle();
677 // translate between the position (which is just an index in the text ctrl
678 // considering all its contents as a single strings) and (x, y) coordinates
679 // which represent column and line.
680 long wxSearchCtrl::XYToPosition(long x
, long y
) const
682 return m_text
->XYToPosition(x
, y
);
684 bool wxSearchCtrl::PositionToXY(long pos
, long *x
, long *y
) const
686 return m_text
->PositionToXY(pos
, x
, y
);
689 void wxSearchCtrl::ShowPosition(long pos
)
691 m_text
->ShowPosition(pos
);
694 // find the character at position given in pixels
696 // NB: pt is in device coords (not adjusted for the client area origin nor
698 wxTextCtrlHitTestResult
wxSearchCtrl::HitTest(const wxPoint
& pt
, long *pos
) const
700 return m_text
->HitTest(pt
, pos
);
702 wxTextCtrlHitTestResult
wxSearchCtrl::HitTest(const wxPoint
& pt
,
704 wxTextCoord
*row
) const
706 return m_text
->HitTest(pt
, col
, row
);
709 // Clipboard operations
710 void wxSearchCtrl::Copy()
714 void wxSearchCtrl::Cut()
718 void wxSearchCtrl::Paste()
723 bool wxSearchCtrl::CanCopy() const
725 return m_text
->CanCopy();
727 bool wxSearchCtrl::CanCut() const
729 return m_text
->CanCut();
731 bool wxSearchCtrl::CanPaste() const
733 return m_text
->CanPaste();
737 void wxSearchCtrl::Undo()
741 void wxSearchCtrl::Redo()
746 bool wxSearchCtrl::CanUndo() const
748 return m_text
->CanUndo();
750 bool wxSearchCtrl::CanRedo() const
752 return m_text
->CanRedo();
756 void wxSearchCtrl::SetInsertionPoint(long pos
)
758 m_text
->SetInsertionPoint(pos
);
760 void wxSearchCtrl::SetInsertionPointEnd()
762 m_text
->SetInsertionPointEnd();
764 long wxSearchCtrl::GetInsertionPoint() const
766 return m_text
->GetInsertionPoint();
768 long wxSearchCtrl::GetLastPosition() const
770 return m_text
->GetLastPosition();
773 void wxSearchCtrl::SetSelection(long from
, long to
)
775 m_text
->SetSelection(from
, to
);
777 void wxSearchCtrl::SelectAll()
782 void wxSearchCtrl::SetEditable(bool editable
)
784 m_text
->SetEditable(editable
);
787 bool wxSearchCtrl::SetFont(const wxFont
& font
)
789 bool result
= wxSearchCtrlBase::SetFont(font
);
790 if ( result
&& m_text
)
792 result
= m_text
->SetFont(font
);
798 // search control generic only
799 void wxSearchCtrl::SetSearchBitmap( const wxBitmap
& bitmap
)
801 m_searchBitmap
= bitmap
;
802 m_searchBitmapUser
= bitmap
.Ok();
803 if ( m_searchBitmapUser
)
805 if ( m_searchButton
&& !HasMenu() )
807 m_searchButton
->SetBitmapLabel( m_searchBitmap
);
812 // the user bitmap was just cleared, generate one
819 void wxSearchCtrl::SetSearchMenuBitmap( const wxBitmap
& bitmap
)
821 m_searchMenuBitmap
= bitmap
;
822 m_searchMenuBitmapUser
= bitmap
.Ok();
823 if ( m_searchMenuBitmapUser
)
825 if ( m_searchButton
&& m_menu
)
827 m_searchButton
->SetBitmapLabel( m_searchMenuBitmap
);
832 // the user bitmap was just cleared, generate one
837 #endif // wxUSE_MENUS
839 void wxSearchCtrl::SetCancelBitmap( const wxBitmap
& bitmap
)
841 m_cancelBitmap
= bitmap
;
842 m_cancelBitmapUser
= bitmap
.Ok();
843 if ( m_cancelBitmapUser
)
845 if ( m_cancelButton
)
847 m_cancelButton
->SetBitmapLabel( m_cancelBitmap
);
852 // the user bitmap was just cleared, generate one
859 // override streambuf method
860 #if wxHAS_TEXT_WINDOW_STREAM
862 #endif // wxHAS_TEXT_WINDOW_STREAM
864 // stream-like insertion operators: these are always available, whether we
865 // were, or not, compiled with streambuf support
866 wxTextCtrl
& operator<<(const wxString
& s
);
867 wxTextCtrl
& operator<<(int i
);
868 wxTextCtrl
& operator<<(long i
);
869 wxTextCtrl
& operator<<(float f
);
870 wxTextCtrl
& operator<<(double d
);
871 wxTextCtrl
& operator<<(const wxChar c
);
874 void wxSearchCtrl::DoSetValue(const wxString
& value
, int flags
)
876 m_text
->DoSetValue(value
, flags
);
879 bool wxSearchCtrl::DoLoadFile(const wxString
& file
, int fileType
)
881 return m_text
->DoLoadFile(file
, fileType
);
884 bool wxSearchCtrl::DoSaveFile(const wxString
& file
, int fileType
)
886 return m_text
->DoSaveFile(file
, fileType
);
889 // do the window-specific processing after processing the update event
890 void wxSearchCtrl::DoUpdateWindowUI(wxUpdateUIEvent
& event
)
892 wxSearchCtrlBase::DoUpdateWindowUI(event
);
895 bool wxSearchCtrl::ShouldInheritColours() const
900 // icons are rendered at 3-8 times larger than necessary and downscaled for
902 static int GetMultiplier()
905 // speed up bitmap generation by using a small bitmap
908 int depth
= ::wxDisplayDepth();
918 wxBitmap
wxSearchCtrl::RenderSearchBitmap( int x
, int y
, bool renderDrop
)
920 wxColour bg
= GetBackgroundColour();
921 wxColour fg
= GetForegroundColour().ChangeLightness(LIGHT_STEP
-20);
923 //===============================================================================
924 // begin drawing code
925 //===============================================================================
928 // force width:height ratio
940 // glass 11x11, top left corner
941 // handle (9,9)-(13,13)
942 // drop (13,16)-(19,6)-(16,9)
944 int multiplier
= GetMultiplier();
945 int penWidth
= multiplier
* 2;
947 penWidth
= penWidth
* x
/ 20;
949 wxBitmap
bitmap( multiplier
*x
, multiplier
*y
);
951 mem
.SelectObject(bitmap
);
954 mem
.SetBrush( wxBrush(bg
) );
955 mem
.SetPen( wxPen(bg
) );
956 mem
.DrawRectangle(0,0,bitmap
.GetWidth(),bitmap
.GetHeight());
959 mem
.SetBrush( wxBrush(fg
) );
960 mem
.SetPen( wxPen(fg
) );
961 int glassBase
= 5 * x
/ 20;
962 int glassFactor
= 2*glassBase
+ 1;
963 int radius
= multiplier
*glassFactor
/2;
964 mem
.DrawCircle(radius
,radius
,radius
);
965 mem
.SetBrush( wxBrush(bg
) );
966 mem
.SetPen( wxPen(bg
) );
967 mem
.DrawCircle(radius
,radius
,radius
-penWidth
);
970 int lineStart
= radius
+ (radius
-penWidth
/2) * 707 / 1000; // 707 / 1000 = 0.707 = 1/sqrt(2);
972 mem
.SetPen( wxPen(fg
) );
973 mem
.SetBrush( wxBrush(fg
) );
974 int handleCornerShift
= penWidth
* 707 / 1000 / 2; // 707 / 1000 = 0.707 = 1/sqrt(2);
975 handleCornerShift
= WXMAX( handleCornerShift
, 1 );
976 int handleBase
= 4 * x
/ 20;
977 int handleLength
= 2*handleBase
+1;
978 wxPoint handlePolygon
[] =
980 wxPoint(-handleCornerShift
,+handleCornerShift
),
981 wxPoint(+handleCornerShift
,-handleCornerShift
),
982 wxPoint(multiplier
*handleLength
/2+handleCornerShift
,multiplier
*handleLength
/2-handleCornerShift
),
983 wxPoint(multiplier
*handleLength
/2-handleCornerShift
,multiplier
*handleLength
/2+handleCornerShift
),
985 mem
.DrawPolygon(WXSIZEOF(handlePolygon
),handlePolygon
,lineStart
,lineStart
);
987 // draw drop triangle
988 int triangleX
= 13 * x
/ 20;
989 int triangleY
= 5 * x
/ 20;
990 int triangleBase
= 3 * x
/ 20;
991 int triangleFactor
= triangleBase
*2+1;
994 wxPoint dropPolygon
[] =
996 wxPoint(multiplier
*0,multiplier
*0), // triangle left
997 wxPoint(multiplier
*triangleFactor
-1,multiplier
*0), // triangle right
998 wxPoint(multiplier
*triangleFactor
/2,multiplier
*triangleFactor
/2), // triangle bottom
1000 mem
.DrawPolygon(WXSIZEOF(dropPolygon
),dropPolygon
,multiplier
*triangleX
,multiplier
*triangleY
);
1002 mem
.SelectObject(wxNullBitmap
);
1004 //===============================================================================
1006 //===============================================================================
1008 if ( multiplier
!= 1 )
1010 wxImage image
= bitmap
.ConvertToImage();
1012 bitmap
= wxBitmap( image
);
1016 // Trim the edge where the arrow would have gone
1017 bitmap
= bitmap
.GetSubBitmap(wxRect(0,0, y
,y
));
1023 wxBitmap
wxSearchCtrl::RenderCancelBitmap( int x
, int y
)
1025 wxColour bg
= GetBackgroundColour();
1026 wxColour fg
= GetForegroundColour().ChangeLightness(LIGHT_STEP
);
1028 //===============================================================================
1029 // begin drawing code
1030 //===============================================================================
1047 // cross line starts (4,4)-(10,10)
1048 // drop (13,16)-(19,6)-(16,9)
1050 int multiplier
= GetMultiplier();
1052 int penWidth
= multiplier
* x
/ 14;
1054 wxBitmap
bitmap( multiplier
*x
, multiplier
*y
);
1056 mem
.SelectObject(bitmap
);
1059 mem
.SetBrush( wxBrush(bg
) );
1060 mem
.SetPen( wxPen(bg
) );
1061 mem
.DrawRectangle(0,0,bitmap
.GetWidth(),bitmap
.GetHeight());
1064 mem
.SetBrush( wxBrush(fg
) );
1065 mem
.SetPen( wxPen(fg
) );
1066 int radius
= multiplier
*x
/2;
1067 mem
.DrawCircle(radius
,radius
,radius
);
1070 int lineStartBase
= 4 * x
/ 14;
1071 int lineLength
= x
- 2*lineStartBase
;
1073 mem
.SetPen( wxPen(bg
) );
1074 mem
.SetBrush( wxBrush(bg
) );
1075 int handleCornerShift
= penWidth
/2;
1076 handleCornerShift
= WXMAX( handleCornerShift
, 1 );
1077 wxPoint handlePolygon
[] =
1079 wxPoint(-handleCornerShift
,+handleCornerShift
),
1080 wxPoint(+handleCornerShift
,-handleCornerShift
),
1081 wxPoint(multiplier
*lineLength
+handleCornerShift
,multiplier
*lineLength
-handleCornerShift
),
1082 wxPoint(multiplier
*lineLength
-handleCornerShift
,multiplier
*lineLength
+handleCornerShift
),
1084 mem
.DrawPolygon(WXSIZEOF(handlePolygon
),handlePolygon
,multiplier
*lineStartBase
,multiplier
*lineStartBase
);
1085 wxPoint handlePolygon2
[] =
1087 wxPoint(+handleCornerShift
,+handleCornerShift
),
1088 wxPoint(-handleCornerShift
,-handleCornerShift
),
1089 wxPoint(multiplier
*lineLength
-handleCornerShift
,-multiplier
*lineLength
-handleCornerShift
),
1090 wxPoint(multiplier
*lineLength
+handleCornerShift
,-multiplier
*lineLength
+handleCornerShift
),
1092 mem
.DrawPolygon(WXSIZEOF(handlePolygon2
),handlePolygon2
,multiplier
*lineStartBase
,multiplier
*(x
-lineStartBase
));
1094 //===============================================================================
1096 //===============================================================================
1098 if ( multiplier
!= 1 )
1100 wxImage image
= bitmap
.ConvertToImage();
1102 bitmap
= wxBitmap( image
);
1108 void wxSearchCtrl::RecalcBitmaps()
1114 wxSize sizeText
= m_text
->GetBestSize();
1116 int bitmapHeight
= sizeText
.y
- 2 * ICON_MARGIN
;
1117 int bitmapWidth
= sizeText
.y
* 20 / 14;
1119 if ( !m_searchBitmapUser
)
1122 !m_searchBitmap
.Ok() ||
1123 m_searchBitmap
.GetHeight() != bitmapHeight
||
1124 m_searchBitmap
.GetWidth() != bitmapWidth
1127 m_searchBitmap
= RenderSearchBitmap(bitmapWidth
,bitmapHeight
,false);
1130 m_searchButton
->SetBitmapLabel(m_searchBitmap
);
1133 // else this bitmap was set by user, don't alter
1137 if ( !m_searchMenuBitmapUser
)
1140 !m_searchMenuBitmap
.Ok() ||
1141 m_searchMenuBitmap
.GetHeight() != bitmapHeight
||
1142 m_searchMenuBitmap
.GetWidth() != bitmapWidth
1145 m_searchMenuBitmap
= RenderSearchBitmap(bitmapWidth
,bitmapHeight
,true);
1148 m_searchButton
->SetBitmapLabel(m_searchMenuBitmap
);
1151 // else this bitmap was set by user, don't alter
1153 #endif // wxUSE_MENUS
1155 if ( !m_cancelBitmapUser
)
1158 !m_cancelBitmap
.Ok() ||
1159 m_cancelBitmap
.GetHeight() != bitmapHeight
||
1160 m_cancelBitmap
.GetWidth() != bitmapHeight
1163 m_cancelBitmap
= RenderCancelBitmap(bitmapHeight
-BORDER
-1,bitmapHeight
-BORDER
-1); // square
1164 m_cancelButton
->SetBitmapLabel(m_cancelBitmap
);
1166 // else this bitmap was set by user, don't alter
1170 void wxSearchCtrl::OnSearchButton( wxCommandEvent
& event
)
1175 void wxSearchCtrl::OnSetFocus( wxFocusEvent
& /*event*/ )
1183 void wxSearchCtrl::OnSize( wxSizeEvent
& WXUNUSED(event
) )
1186 GetSize(&width
, &height
);
1187 LayoutControls(0, 0, width
, height
);
1192 void wxSearchCtrl::PopupSearchMenu()
1196 wxSize size
= GetSize();
1197 PopupMenu( m_menu
, 0, size
.y
);
1201 #endif // wxUSE_MENUS
1203 #endif // !wxUSE_NATIVE_SEARCH_CONTROL
1205 #endif // wxUSE_SEARCHCTRL