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