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