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