]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/generic/srchctlg.cpp
added wxCSConv::IsOk() (patch 1637944)
[wxWidgets.git] / src / generic / srchctlg.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/generic/srchctlg.cpp
3// Purpose: implements wxSearchCtrl as a composite control
4// Author: Vince Harron
5// Created: 2006-02-19
6// RCS-ID: $Id$
7// Copyright: Vince Harron
8// License: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
18#if wxUSE_SEARCHCTRL
19
20#include "wx/srchctrl.h"
21
22#ifndef WX_PRECOMP
23 #include "wx/button.h"
24 #include "wx/dcclient.h"
25 #include "wx/menu.h"
26 #include "wx/dcmemory.h"
27#endif //WX_PRECOMP
28
29#if !wxUSE_NATIVE_SEARCH_CONTROL
30
31#include "wx/image.h"
32
33#define WXMAX(a,b) ((a)>(b)?(a):(b))
34
35// ----------------------------------------------------------------------------
36// constants
37// ----------------------------------------------------------------------------
38
39// the margin between the text control and the search/cancel buttons
40static const wxCoord MARGIN = 2;
41
42// border around all controls to compensate for wxSIMPLE_BORDER
43#if defined(__WXMSW__)
44static const wxCoord BORDER = 0;
45static const wxCoord ICON_MARGIN = 2;
46static const wxCoord ICON_OFFSET = 2;
47#else
48static const wxCoord BORDER = 2;
49static const wxCoord ICON_MARGIN = 0;
50static const wxCoord ICON_OFFSET = 0;
51#endif
52
53// ----------------------------------------------------------------------------
54// wxSearchTextCtrl: text control used by search control
55// ----------------------------------------------------------------------------
56
57class wxSearchTextCtrl : public wxTextCtrl
58{
59public:
60 wxSearchTextCtrl(wxSearchCtrl *search, const wxString& value, int style)
61 : wxTextCtrl(search, wxID_ANY, value, wxDefaultPosition, wxDefaultSize,
62 style | wxNO_BORDER)
63 {
64 m_search = search;
65
66 // remove the default minsize, the searchctrl will have one instead
67 SetSizeHints(wxDefaultCoord,wxDefaultCoord);
68 }
69
70protected:
71 void OnText(wxCommandEvent& eventText)
72 {
73 wxCommandEvent event(eventText);
74 event.SetEventObject(m_search);
75 event.SetId(m_search->GetId());
76
77 m_search->GetEventHandler()->ProcessEvent(event);
78 }
79
80 void OnTextUrl(wxTextUrlEvent& eventText)
81 {
82 // copy constructor is disabled for some reason?
83 //wxTextUrlEvent event(eventText);
84 wxTextUrlEvent event(
85 m_search->GetId(),
86 eventText.GetMouseEvent(),
87 eventText.GetURLStart(),
88 eventText.GetURLEnd()
89 );
90 event.SetEventObject(m_search);
91
92 m_search->GetEventHandler()->ProcessEvent(event);
93 }
94
95private:
96 wxSearchCtrl* m_search;
97
98 DECLARE_EVENT_TABLE()
99};
100
101BEGIN_EVENT_TABLE(wxSearchTextCtrl, wxTextCtrl)
102 EVT_TEXT(wxID_ANY, wxSearchTextCtrl::OnText)
103 EVT_TEXT_ENTER(wxID_ANY, wxSearchTextCtrl::OnText)
104 EVT_TEXT_URL(wxID_ANY, wxSearchTextCtrl::OnTextUrl)
105 EVT_TEXT_MAXLEN(wxID_ANY, wxSearchTextCtrl::OnText)
106END_EVENT_TABLE()
107
108// ----------------------------------------------------------------------------
109// wxSearchButton: search button used by search control
110// ----------------------------------------------------------------------------
111
112class wxSearchButton : public wxControl
113{
114public:
115 wxSearchButton(wxSearchCtrl *search, int eventType, const wxBitmap& bmp)
116 : wxControl(search, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNO_BORDER),
117 m_search(search),
118 m_eventType(eventType),
119 m_bmp(bmp)
120 { }
121
122 void SetBitmapLabel(const wxBitmap& label) { m_bmp = label; }
123
124
125protected:
126 wxSize DoGetBestSize() const
127 {
128 return wxSize(m_bmp.GetWidth(), m_bmp.GetHeight());
129 }
130
131 void OnLeftUp(wxMouseEvent&)
132 {
133 wxCommandEvent event(m_eventType, m_search->GetId());
134 event.SetEventObject(m_search);
135
136 GetEventHandler()->ProcessEvent(event);
137
138 m_search->SetFocus();
139
140 if ( m_eventType == wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN )
141 {
142 // this happens automatically, just like on Mac OS X
143 m_search->PopupSearchMenu();
144 }
145 }
146
147 void OnPaint(wxPaintEvent&)
148 {
149 wxPaintDC dc(this);
150 dc.DrawBitmap(m_bmp, 0,0, true);
151 }
152
153
154private:
155 wxSearchCtrl *m_search;
156 wxEventType m_eventType;
157 wxBitmap m_bmp;
158
159 DECLARE_EVENT_TABLE()
160};
161
162BEGIN_EVENT_TABLE(wxSearchButton, wxControl)
163 EVT_LEFT_UP(wxSearchButton::OnLeftUp)
164 EVT_PAINT(wxSearchButton::OnPaint)
165END_EVENT_TABLE()
166
167BEGIN_EVENT_TABLE(wxSearchCtrl, wxSearchCtrlBase)
168 EVT_SEARCHCTRL_SEARCH_BTN(wxID_ANY, wxSearchCtrl::OnSearchButton)
169 EVT_SET_FOCUS(wxSearchCtrl::OnSetFocus)
170 EVT_SIZE(wxSearchCtrl::OnSize)
171END_EVENT_TABLE()
172
173IMPLEMENT_DYNAMIC_CLASS(wxSearchCtrl, wxSearchCtrlBase)
174
175// ============================================================================
176// implementation
177// ============================================================================
178
179// ----------------------------------------------------------------------------
180// wxSearchCtrl creation
181// ----------------------------------------------------------------------------
182
183// creation
184// --------
185
186wxSearchCtrl::wxSearchCtrl()
187{
188 Init();
189}
190
191wxSearchCtrl::wxSearchCtrl(wxWindow *parent, wxWindowID id,
192 const wxString& value,
193 const wxPoint& pos,
194 const wxSize& size,
195 long style,
196 const wxValidator& validator,
197 const wxString& name)
198{
199 Init();
200
201 Create(parent, id, value, pos, size, style, validator, name);
202}
203
204void wxSearchCtrl::Init()
205{
206 m_text = 0;
207 m_searchButton = 0;
208 m_cancelButton = 0;
209 m_menu = 0;
210
211 m_searchButtonVisible = true;
212 m_cancelButtonVisible = false;
213
214 m_searchMenuBitmapUser = false;
215 m_searchBitmapUser = false;
216 m_cancelBitmapUser = false;
217}
218
219bool wxSearchCtrl::Create(wxWindow *parent, wxWindowID id,
220 const wxString& value,
221 const wxPoint& pos,
222 const wxSize& size,
223 long style,
224 const wxValidator& validator,
225 const wxString& name)
226{
227#ifdef __WXGTK__
228 if ( !wxTextCtrlBase::Create(parent, id, pos, size, wxSUNKEN_BORDER | style, validator, name) )
229#else
230 if ( !wxTextCtrlBase::Create(parent, id, pos, size, wxSIMPLE_BORDER | style, validator, name) )
231#endif
232 {
233 return false;
234 }
235
236 m_text = new wxSearchTextCtrl(this, value, style & ~wxBORDER_MASK);
237
238 wxSize sizeText = m_text->GetBestSize();
239
240 m_searchButton = new wxSearchButton(this,wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN,m_searchBitmap);
241 m_cancelButton = new wxSearchButton(this,wxEVT_COMMAND_SEARCHCTRL_CANCEL_BTN,m_cancelBitmap);
242
243 SetForegroundColour( m_text->GetForegroundColour() );
244 m_searchButton->SetForegroundColour( m_text->GetForegroundColour() );
245 m_cancelButton->SetForegroundColour( m_text->GetForegroundColour() );
246
247 SetBackgroundColour( m_text->GetBackgroundColour() );
248 m_searchButton->SetBackgroundColour( m_text->GetBackgroundColour() );
249 m_cancelButton->SetBackgroundColour( m_text->GetBackgroundColour() );
250
251 RecalcBitmaps();
252
253 SetInitialSize(size);
254 Move(pos);
255 return true;
256}
257
258wxSearchCtrl::~wxSearchCtrl()
259{
260 delete m_text;
261 delete m_searchButton;
262 delete m_cancelButton;
263 delete m_menu;
264}
265
266
267// search control specific interfaces
268void wxSearchCtrl::SetMenu( wxMenu* menu )
269{
270 if ( menu == m_menu )
271 {
272 // no change
273 return;
274 }
275 bool hadMenu = (m_menu != NULL);
276 delete m_menu;
277 m_menu = menu;
278
279 if ( m_menu && !hadMenu )
280 {
281 m_searchButton->SetBitmapLabel(m_searchMenuBitmap);
282 m_searchButton->Refresh();
283 if ( !m_searchButtonVisible )
284 {
285 // adding the menu will force the search button to be visible
286 wxRect rect = GetRect();
287 LayoutControls(0, 0, rect.GetWidth(), rect.GetHeight());
288 }
289 }
290 else if ( !m_menu && hadMenu )
291 {
292 m_searchButton->SetBitmapLabel(m_searchBitmap);
293 if ( m_searchButtonVisible )
294 {
295 m_searchButton->Refresh();
296 }
297 else
298 {
299 wxRect rect = GetRect();
300 LayoutControls(0, 0, rect.GetWidth(), rect.GetHeight());
301 }
302 }
303}
304
305wxMenu* wxSearchCtrl::GetMenu()
306{
307 return m_menu;
308}
309
310void wxSearchCtrl::ShowSearchButton( bool show )
311{
312 if ( m_searchButtonVisible == show )
313 {
314 // no change
315 return;
316 }
317 m_searchButtonVisible = show;
318 if ( m_searchButtonVisible )
319 {
320 RecalcBitmaps();
321 }
322
323 wxRect rect = GetRect();
324 LayoutControls(0, 0, rect.GetWidth(), rect.GetHeight());
325}
326
327bool wxSearchCtrl::IsSearchButtonVisible() const
328{
329 return m_searchButtonVisible;
330}
331
332
333void wxSearchCtrl::ShowCancelButton( bool show )
334{
335 if ( m_cancelButtonVisible == show )
336 {
337 // no change
338 return;
339 }
340 m_cancelButtonVisible = show;
341
342 wxRect rect = GetRect();
343 LayoutControls(0, 0, rect.GetWidth(), rect.GetHeight());
344}
345
346bool wxSearchCtrl::IsCancelButtonVisible() const
347{
348 return m_cancelButtonVisible;
349}
350
351
352// ----------------------------------------------------------------------------
353// geometry
354// ----------------------------------------------------------------------------
355
356wxSize wxSearchCtrl::DoGetBestSize() const
357{
358 wxSize sizeText = m_text->GetBestSize();
359 wxSize sizeSearch(0,0);
360 wxSize sizeCancel(0,0);
361 int searchMargin = 0;
362 int cancelMargin = 0;
363 if ( m_searchButtonVisible || m_menu )
364 {
365 sizeSearch = m_searchButton->GetBestSize();
366 searchMargin = MARGIN;
367 }
368 if ( m_cancelButtonVisible )
369 {
370 sizeCancel = m_cancelButton->GetBestSize();
371 cancelMargin = MARGIN;
372 }
373
374 int horizontalBorder = 1 + ( sizeText.y - sizeText.y * 14 / 21 ) / 2;
375
376 // buttons are square and equal to the height of the text control
377 int height = sizeText.y;
378 return wxSize(sizeSearch.x + searchMargin + sizeText.x + cancelMargin + sizeCancel.x + 2*horizontalBorder,
379 height + 2*BORDER);
380}
381
382void wxSearchCtrl::DoMoveWindow(int x, int y, int width, int height)
383{
384 wxSearchCtrlBase::DoMoveWindow(x, y, width, height);
385
386 LayoutControls(0, 0, width, height);
387}
388
389void wxSearchCtrl::LayoutControls(int x, int y, int width, int height)
390{
391 if ( !m_text )
392 return;
393
394 wxSize sizeText = m_text->GetBestSize();
395 // make room for the search menu & clear button
396 int horizontalBorder = 1 + ( sizeText.y - sizeText.y * 14 / 21 ) / 2;
397 x += horizontalBorder;
398 y += BORDER;
399 width -= horizontalBorder*2;
400 height -= BORDER*2;
401
402 wxSize sizeSearch(0,0);
403 wxSize sizeCancel(0,0);
404 int searchMargin = 0;
405 int cancelMargin = 0;
406 if ( m_searchButtonVisible || m_menu )
407 {
408 sizeSearch = m_searchButton->GetBestSize();
409 searchMargin = MARGIN;
410 }
411 if ( m_cancelButtonVisible )
412 {
413 sizeCancel = m_cancelButton->GetBestSize();
414 cancelMargin = MARGIN;
415 }
416 m_searchButton->Show( m_searchButtonVisible || m_menu );
417 m_cancelButton->Show( m_cancelButtonVisible );
418
419 if ( sizeSearch.x + sizeCancel.x > width )
420 {
421 sizeSearch.x = width/2;
422 sizeCancel.x = width/2;
423 searchMargin = 0;
424 cancelMargin = 0;
425 }
426 wxCoord textWidth = width - sizeSearch.x - sizeCancel.x - searchMargin - cancelMargin;
427
428 // position the subcontrols inside the client area
429
430 m_searchButton->SetSize(x, y + ICON_OFFSET, sizeSearch.x, height);
431 m_text->SetSize( x + sizeSearch.x + searchMargin,
432 y + ICON_OFFSET - BORDER,
433 textWidth,
434 height);
435 m_cancelButton->SetSize(x + sizeSearch.x + searchMargin + textWidth + cancelMargin,
436 y + ICON_OFFSET, sizeCancel.x, height);
437}
438
439
440// accessors
441// ---------
442
443wxString wxSearchCtrl::GetValue() const
444{
445 return m_text->GetValue();
446}
447void wxSearchCtrl::SetValue(const wxString& value)
448{
449 m_text->SetValue(value);
450}
451
452wxString wxSearchCtrl::GetRange(long from, long to) const
453{
454 return m_text->GetRange(from, to);
455}
456
457int wxSearchCtrl::GetLineLength(long lineNo) const
458{
459 return m_text->GetLineLength(lineNo);
460}
461wxString wxSearchCtrl::GetLineText(long lineNo) const
462{
463 return m_text->GetLineText(lineNo);
464}
465int wxSearchCtrl::GetNumberOfLines() const
466{
467 return m_text->GetNumberOfLines();
468}
469
470bool wxSearchCtrl::IsModified() const
471{
472 return m_text->IsModified();
473}
474bool wxSearchCtrl::IsEditable() const
475{
476 return m_text->IsEditable();
477}
478
479// more readable flag testing methods
480bool wxSearchCtrl::IsSingleLine() const
481{
482 return m_text->IsSingleLine();
483}
484bool wxSearchCtrl::IsMultiLine() const
485{
486 return m_text->IsMultiLine();
487}
488
489// If the return values from and to are the same, there is no selection.
490void wxSearchCtrl::GetSelection(long* from, long* to) const
491{
492 m_text->GetSelection(from, to);
493}
494
495wxString wxSearchCtrl::GetStringSelection() const
496{
497 return m_text->GetStringSelection();
498}
499
500// operations
501// ----------
502
503// editing
504void wxSearchCtrl::Clear()
505{
506 m_text->Clear();
507}
508void wxSearchCtrl::Replace(long from, long to, const wxString& value)
509{
510 m_text->Replace(from, to, value);
511}
512void wxSearchCtrl::Remove(long from, long to)
513{
514 m_text->Remove(from, to);
515}
516
517// load/save the controls contents from/to the file
518bool wxSearchCtrl::LoadFile(const wxString& file)
519{
520 return m_text->LoadFile(file);
521}
522bool wxSearchCtrl::SaveFile(const wxString& file)
523{
524 return m_text->SaveFile(file);
525}
526
527// sets/clears the dirty flag
528void wxSearchCtrl::MarkDirty()
529{
530 m_text->MarkDirty();
531}
532void wxSearchCtrl::DiscardEdits()
533{
534 m_text->DiscardEdits();
535}
536
537// set the max number of characters which may be entered in a single line
538// text control
539void wxSearchCtrl::SetMaxLength(unsigned long len)
540{
541 m_text->SetMaxLength(len);
542}
543
544// writing text inserts it at the current position, appending always
545// inserts it at the end
546void wxSearchCtrl::WriteText(const wxString& text)
547{
548 m_text->WriteText(text);
549}
550void wxSearchCtrl::AppendText(const wxString& text)
551{
552 m_text->AppendText(text);
553}
554
555// insert the character which would have resulted from this key event,
556// return true if anything has been inserted
557bool wxSearchCtrl::EmulateKeyPress(const wxKeyEvent& event)
558{
559 return m_text->EmulateKeyPress(event);
560}
561
562// text control under some platforms supports the text styles: these
563// methods allow to apply the given text style to the given selection or to
564// set/get the style which will be used for all appended text
565bool wxSearchCtrl::SetStyle(long start, long end, const wxTextAttr& style)
566{
567 return m_text->SetStyle(start, end, style);
568}
569bool wxSearchCtrl::GetStyle(long position, wxTextAttr& style)
570{
571 return m_text->GetStyle(position, style);
572}
573bool wxSearchCtrl::SetDefaultStyle(const wxTextAttr& style)
574{
575 return m_text->SetDefaultStyle(style);
576}
577const wxTextAttr& wxSearchCtrl::GetDefaultStyle() const
578{
579 return m_text->GetDefaultStyle();
580}
581
582// translate between the position (which is just an index in the text ctrl
583// considering all its contents as a single strings) and (x, y) coordinates
584// which represent column and line.
585long wxSearchCtrl::XYToPosition(long x, long y) const
586{
587 return m_text->XYToPosition(x, y);
588}
589bool wxSearchCtrl::PositionToXY(long pos, long *x, long *y) const
590{
591 return m_text->PositionToXY(pos, x, y);
592}
593
594void wxSearchCtrl::ShowPosition(long pos)
595{
596 m_text->ShowPosition(pos);
597}
598
599// find the character at position given in pixels
600//
601// NB: pt is in device coords (not adjusted for the client area origin nor
602// scrolling)
603wxTextCtrlHitTestResult wxSearchCtrl::HitTest(const wxPoint& pt, long *pos) const
604{
605 return m_text->HitTest(pt, pos);
606}
607wxTextCtrlHitTestResult wxSearchCtrl::HitTest(const wxPoint& pt,
608 wxTextCoord *col,
609 wxTextCoord *row) const
610{
611 return m_text->HitTest(pt, col, row);
612}
613
614// Clipboard operations
615void wxSearchCtrl::Copy()
616{
617 m_text->Copy();
618}
619void wxSearchCtrl::Cut()
620{
621 m_text->Cut();
622}
623void wxSearchCtrl::Paste()
624{
625 m_text->Paste();
626}
627
628bool wxSearchCtrl::CanCopy() const
629{
630 return m_text->CanCopy();
631}
632bool wxSearchCtrl::CanCut() const
633{
634 return m_text->CanCut();
635}
636bool wxSearchCtrl::CanPaste() const
637{
638 return m_text->CanPaste();
639}
640
641// Undo/redo
642void wxSearchCtrl::Undo()
643{
644 m_text->Undo();
645}
646void wxSearchCtrl::Redo()
647{
648 m_text->Redo();
649}
650
651bool wxSearchCtrl::CanUndo() const
652{
653 return m_text->CanUndo();
654}
655bool wxSearchCtrl::CanRedo() const
656{
657 return m_text->CanRedo();
658}
659
660// Insertion point
661void wxSearchCtrl::SetInsertionPoint(long pos)
662{
663 m_text->SetInsertionPoint(pos);
664}
665void wxSearchCtrl::SetInsertionPointEnd()
666{
667 m_text->SetInsertionPointEnd();
668}
669long wxSearchCtrl::GetInsertionPoint() const
670{
671 return m_text->GetInsertionPoint();
672}
673wxTextPos wxSearchCtrl::GetLastPosition() const
674{
675 return m_text->GetLastPosition();
676}
677
678void wxSearchCtrl::SetSelection(long from, long to)
679{
680 m_text->SetSelection(from, to);
681}
682void wxSearchCtrl::SelectAll()
683{
684 m_text->SelectAll();
685}
686
687void wxSearchCtrl::SetEditable(bool editable)
688{
689 m_text->SetEditable(editable);
690}
691
692bool wxSearchCtrl::SetFont(const wxFont& font)
693{
694 bool result = wxSearchCtrlBase::SetFont(font);
695 if ( result && m_text )
696 {
697 result = m_text->SetFont(font);
698 }
699 RecalcBitmaps();
700 return result;
701}
702
703// search control generic only
704void wxSearchCtrl::SetSearchBitmap( const wxBitmap& bitmap )
705{
706 m_searchBitmap = bitmap;
707 m_searchBitmapUser = bitmap.Ok();
708 if ( m_searchBitmapUser )
709 {
710 if ( m_searchButton && !m_menu )
711 {
712 m_searchButton->SetBitmapLabel( m_searchBitmap );
713 }
714 }
715 else
716 {
717 // the user bitmap was just cleared, generate one
718 RecalcBitmaps();
719 }
720}
721
722void wxSearchCtrl::SetSearchMenuBitmap( const wxBitmap& bitmap )
723{
724 m_searchMenuBitmap = bitmap;
725 m_searchMenuBitmapUser = bitmap.Ok();
726 if ( m_searchMenuBitmapUser )
727 {
728 if ( m_searchButton && m_menu )
729 {
730 m_searchButton->SetBitmapLabel( m_searchMenuBitmap );
731 }
732 }
733 else
734 {
735 // the user bitmap was just cleared, generate one
736 RecalcBitmaps();
737 }
738}
739
740void wxSearchCtrl::SetCancelBitmap( const wxBitmap& bitmap )
741{
742 m_cancelBitmap = bitmap;
743 m_cancelBitmapUser = bitmap.Ok();
744 if ( m_cancelBitmapUser )
745 {
746 if ( m_cancelButton )
747 {
748 m_cancelButton->SetBitmapLabel( m_cancelBitmap );
749 }
750 }
751 else
752 {
753 // the user bitmap was just cleared, generate one
754 RecalcBitmaps();
755 }
756}
757
758#if 0
759
760// override streambuf method
761#if wxHAS_TEXT_WINDOW_STREAM
762int overflow(int i);
763#endif // wxHAS_TEXT_WINDOW_STREAM
764
765// stream-like insertion operators: these are always available, whether we
766// were, or not, compiled with streambuf support
767wxTextCtrl& operator<<(const wxString& s);
768wxTextCtrl& operator<<(int i);
769wxTextCtrl& operator<<(long i);
770wxTextCtrl& operator<<(float f);
771wxTextCtrl& operator<<(double d);
772wxTextCtrl& operator<<(const wxChar c);
773#endif
774
775void wxSearchCtrl::DoSetValue(const wxString& value, int flags)
776{
777 m_text->ChangeValue( value );
778 if ( flags & SetValue_SendEvent )
779 SendTextUpdatedEvent();
780}
781
782// do the window-specific processing after processing the update event
783void wxSearchCtrl::DoUpdateWindowUI(wxUpdateUIEvent& event)
784{
785 wxSearchCtrlBase::DoUpdateWindowUI(event);
786}
787
788bool wxSearchCtrl::ShouldInheritColours() const
789{
790 return true;
791}
792
793// icons are rendered at 3-8 times larger than necessary and downscaled for
794// antialiasing
795static int GetMultiplier()
796{
797#ifdef __WXWINCE__
798 // speed up bitmap generation by using a small bitmap
799 return 3;
800#else
801 int depth = ::wxDisplayDepth();
802
803 if ( depth >= 24 )
804 {
805 return 8;
806 }
807 return 6;
808#endif
809}
810
811wxBitmap wxSearchCtrl::RenderSearchBitmap( int x, int y, bool renderDrop )
812{
813 wxColour bg = GetBackgroundColour();
814 wxColour fg = GetForegroundColour();
815
816 //===============================================================================
817 // begin drawing code
818 //===============================================================================
819 // image stats
820
821 // force width:height ratio
822 if ( 14*x > y*20 )
823 {
824 // x is too big
825 x = y*20/14;
826 }
827 else
828 {
829 // y is too big
830 y = x*14/20;
831 }
832
833 // glass 11x11, top left corner
834 // handle (9,9)-(13,13)
835 // drop (13,16)-(19,6)-(16,9)
836
837 int multiplier = GetMultiplier();
838 int penWidth = multiplier * 2;
839
840 penWidth = penWidth * x / 20;
841
842 wxBitmap bitmap( multiplier*x, multiplier*y );
843 wxMemoryDC mem;
844 mem.SelectObject(bitmap);
845
846 // clear background
847 mem.SetBrush( wxBrush(bg) );
848 mem.SetPen( wxPen(bg) );
849 mem.DrawRectangle(0,0,bitmap.GetWidth(),bitmap.GetHeight());
850
851 // draw drop glass
852 mem.SetBrush( wxBrush(fg) );
853 mem.SetPen( wxPen(fg) );
854 int glassBase = 5 * x / 20;
855 int glassFactor = 2*glassBase + 1;
856 int radius = multiplier*glassFactor/2;
857 mem.DrawCircle(radius,radius,radius);
858 mem.SetBrush( wxBrush(bg) );
859 mem.SetPen( wxPen(bg) );
860 mem.DrawCircle(radius,radius,radius-penWidth);
861
862 // draw handle
863 int lineStart = radius + (radius-penWidth/2) * 707 / 1000; // 707 / 1000 = 0.707 = 1/sqrt(2);
864
865 mem.SetPen( wxPen(fg) );
866 mem.SetBrush( wxBrush(fg) );
867 int handleCornerShift = penWidth * 707 / 1000 / 2; // 707 / 1000 = 0.707 = 1/sqrt(2);
868 handleCornerShift = WXMAX( handleCornerShift, 1 );
869 int handleBase = 4 * x / 20;
870 int handleLength = 2*handleBase+1;
871 wxPoint handlePolygon[] =
872 {
873 wxPoint(-handleCornerShift,+handleCornerShift),
874 wxPoint(+handleCornerShift,-handleCornerShift),
875 wxPoint(multiplier*handleLength/2+handleCornerShift,multiplier*handleLength/2-handleCornerShift),
876 wxPoint(multiplier*handleLength/2-handleCornerShift,multiplier*handleLength/2+handleCornerShift),
877 };
878 mem.DrawPolygon(WXSIZEOF(handlePolygon),handlePolygon,lineStart,lineStart);
879
880 // draw drop triangle
881 int triangleX = 13 * x / 20;
882 int triangleY = 5 * x / 20;
883 int triangleBase = 3 * x / 20;
884 int triangleFactor = triangleBase*2+1;
885 if ( renderDrop )
886 {
887 wxPoint dropPolygon[] =
888 {
889 wxPoint(multiplier*0,multiplier*0), // triangle left
890 wxPoint(multiplier*triangleFactor-1,multiplier*0), // triangle right
891 wxPoint(multiplier*triangleFactor/2,multiplier*triangleFactor/2), // triangle bottom
892 };
893 mem.DrawPolygon(WXSIZEOF(dropPolygon),dropPolygon,multiplier*triangleX,multiplier*triangleY);
894 }
895
896 //===============================================================================
897 // end drawing code
898 //===============================================================================
899
900 if ( multiplier != 1 )
901 {
902 wxImage image = bitmap.ConvertToImage();
903 image.Rescale(x,y);
904 bitmap = wxBitmap( image );
905 }
906
907 return bitmap;
908}
909
910wxBitmap wxSearchCtrl::RenderCancelBitmap( int x, int y )
911{
912 wxColour bg = GetBackgroundColour();
913 wxColour fg = GetForegroundColour();
914
915 //===============================================================================
916 // begin drawing code
917 //===============================================================================
918 // image stats
919
920 // total size 14x14
921 // force 1:1 ratio
922 if ( x > y )
923 {
924 // x is too big
925 x = y;
926 }
927 else
928 {
929 // y is too big
930 y = x;
931 }
932
933 // 14x14 circle
934 // cross line starts (4,4)-(10,10)
935 // drop (13,16)-(19,6)-(16,9)
936
937 int multiplier = GetMultiplier();
938
939 int penWidth = multiplier * x / 14;
940
941 wxBitmap bitmap( multiplier*x, multiplier*y );
942 wxMemoryDC mem;
943 mem.SelectObject(bitmap);
944
945 // clear background
946 mem.SetBrush( wxBrush(bg) );
947 mem.SetPen( wxPen(bg) );
948 mem.DrawRectangle(0,0,bitmap.GetWidth(),bitmap.GetHeight());
949
950 // draw drop glass
951 mem.SetBrush( wxBrush(fg) );
952 mem.SetPen( wxPen(fg) );
953 int radius = multiplier*x/2;
954 mem.DrawCircle(radius,radius,radius);
955
956 // draw cross
957 int lineStartBase = 4 * x / 14;
958 int lineLength = x - 2*lineStartBase;
959
960 mem.SetPen( wxPen(bg) );
961 mem.SetBrush( wxBrush(bg) );
962 int handleCornerShift = penWidth/2;
963 handleCornerShift = WXMAX( handleCornerShift, 1 );
964 wxPoint handlePolygon[] =
965 {
966 wxPoint(-handleCornerShift,+handleCornerShift),
967 wxPoint(+handleCornerShift,-handleCornerShift),
968 wxPoint(multiplier*lineLength+handleCornerShift,multiplier*lineLength-handleCornerShift),
969 wxPoint(multiplier*lineLength-handleCornerShift,multiplier*lineLength+handleCornerShift),
970 };
971 mem.DrawPolygon(WXSIZEOF(handlePolygon),handlePolygon,multiplier*lineStartBase,multiplier*lineStartBase);
972 wxPoint handlePolygon2[] =
973 {
974 wxPoint(+handleCornerShift,+handleCornerShift),
975 wxPoint(-handleCornerShift,-handleCornerShift),
976 wxPoint(multiplier*lineLength-handleCornerShift,-multiplier*lineLength-handleCornerShift),
977 wxPoint(multiplier*lineLength+handleCornerShift,-multiplier*lineLength+handleCornerShift),
978 };
979 mem.DrawPolygon(WXSIZEOF(handlePolygon2),handlePolygon2,multiplier*lineStartBase,multiplier*(x-lineStartBase));
980
981 //===============================================================================
982 // end drawing code
983 //===============================================================================
984
985 if ( multiplier != 1 )
986 {
987 wxImage image = bitmap.ConvertToImage();
988 image.Rescale(x,y);
989 bitmap = wxBitmap( image );
990 }
991
992 return bitmap;
993}
994
995void wxSearchCtrl::RecalcBitmaps()
996{
997 if ( !m_text )
998 {
999 return;
1000 }
1001 wxSize sizeText = m_text->GetBestSize();
1002
1003 int bitmapHeight = sizeText.y - 2 * ICON_MARGIN;
1004 int bitmapWidth = sizeText.y * 20 / 14;
1005
1006 if ( !m_searchBitmapUser )
1007 {
1008 if (
1009 !m_searchBitmap.Ok() ||
1010 m_searchBitmap.GetHeight() != bitmapHeight ||
1011 m_searchBitmap.GetWidth() != bitmapWidth
1012 )
1013 {
1014 m_searchBitmap = RenderSearchBitmap(bitmapWidth,bitmapHeight,false);
1015 if ( !m_menu )
1016 {
1017 m_searchButton->SetBitmapLabel(m_searchBitmap);
1018 }
1019 }
1020 // else this bitmap was set by user, don't alter
1021 }
1022
1023 if ( !m_searchMenuBitmapUser )
1024 {
1025 if (
1026 !m_searchMenuBitmap.Ok() ||
1027 m_searchMenuBitmap.GetHeight() != bitmapHeight ||
1028 m_searchMenuBitmap.GetWidth() != bitmapWidth
1029 )
1030 {
1031 m_searchMenuBitmap = RenderSearchBitmap(bitmapWidth,bitmapHeight,true);
1032 if ( m_menu )
1033 {
1034 m_searchButton->SetBitmapLabel(m_searchMenuBitmap);
1035 }
1036 }
1037 // else this bitmap was set by user, don't alter
1038 }
1039
1040 if ( !m_cancelBitmapUser )
1041 {
1042 if (
1043 !m_cancelBitmap.Ok() ||
1044 m_cancelBitmap.GetHeight() != bitmapHeight ||
1045 m_cancelBitmap.GetWidth() != bitmapHeight
1046 )
1047 {
1048 m_cancelBitmap = RenderCancelBitmap(bitmapHeight-BORDER,bitmapHeight-BORDER); // square
1049 m_cancelButton->SetBitmapLabel(m_cancelBitmap);
1050 }
1051 // else this bitmap was set by user, don't alter
1052 }
1053}
1054
1055void wxSearchCtrl::OnSearchButton( wxCommandEvent& event )
1056{
1057 event.Skip();
1058}
1059
1060void wxSearchCtrl::OnSetFocus( wxFocusEvent& /*event*/ )
1061{
1062 if ( m_text )
1063 {
1064 m_text->SetFocus();
1065 }
1066}
1067
1068void wxSearchCtrl::OnSize( wxSizeEvent& WXUNUSED(event) )
1069{
1070 int width, height;
1071 GetSize(&width, &height);
1072 LayoutControls(0, 0, width, height);
1073}
1074
1075void wxSearchCtrl::PopupSearchMenu()
1076{
1077 if ( m_menu )
1078 {
1079 wxSize size = GetSize();
1080 PopupMenu( m_menu, 0, size.y );
1081 }
1082}
1083
1084#endif // !wxUSE_NATIVE_SEARCH_CONTROL
1085
1086#endif // wxUSE_SEARCHCTRL