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