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