X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b5dc8fdbfd0c5cb785ae3ce27526be564c3c0d9d..da6f998486f1070e205f2e0a54f22a1b67cb32a4:/src/generic/srchctlg.cpp diff --git a/src/generic/srchctlg.cpp b/src/generic/srchctlg.cpp index b111b0de8f..ccf7ccbcfc 100644 --- a/src/generic/srchctlg.cpp +++ b/src/generic/srchctlg.cpp @@ -3,9 +3,8 @@ // Purpose: implements wxSearchCtrl as a composite control // Author: Vince Harron // Created: 2006-02-19 -// RCS-ID: $Id$ // Copyright: Vince Harron -// License: wxWindows licence +// Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx.h". @@ -50,55 +49,6 @@ static const wxCoord ICON_MARGIN = 0; static const wxCoord ICON_OFFSET = 0; #endif -// ---------------------------------------------------------------------------- -// TODO: These functions or something like them should probably be made -// public. There are similar functions in src/aui/dockart.cpp... - -static double wxBlendColour(double fg, double bg, double alpha) -{ - double result = bg + (alpha * (fg - bg)); - if (result < 0.0) - result = 0.0; - if (result > 255) - result = 255; - return result; -} - -static wxColor wxStepColour(const wxColor& c, int ialpha) -{ - if (ialpha == 100) - return c; - - double r = c.Red(), g = c.Green(), b = c.Blue(); - double bg; - - // ialpha is 0..200 where 0 is completely black - // and 200 is completely white and 100 is the same - // convert that to normal alpha 0.0 - 1.0 - ialpha = wxMin(ialpha, 200); - ialpha = wxMax(ialpha, 0); - double alpha = ((double)(ialpha - 100.0))/100.0; - - if (ialpha > 100) - { - // blend with white - bg = 255.0; - alpha = 1.0 - alpha; // 0 = transparent fg; 1 = opaque fg - } - else - { - // blend with black - bg = 0.0; - alpha = 1.0 + alpha; // 0 = transparent fg; 1 = opaque fg - } - - r = wxBlendColour(r, bg, alpha); - g = wxBlendColour(g, bg, alpha); - b = wxBlendColour(b, bg, alpha); - - return wxColour((unsigned char)r, (unsigned char)g, (unsigned char)b); -} - #define LIGHT_STEP 160 // ---------------------------------------------------------------------------- @@ -110,30 +60,39 @@ class wxSearchTextCtrl : public wxTextCtrl public: wxSearchTextCtrl(wxSearchCtrl *search, const wxString& value, int style) : wxTextCtrl(search, wxID_ANY, value, wxDefaultPosition, wxDefaultSize, - style | wxNO_BORDER) + (style & ~wxBORDER_MASK) | wxNO_BORDER) { m_search = search; - m_defaultFG = GetForegroundColour(); - - // remove the default minsize, the searchctrl will have one instead - SetSizeHints(wxDefaultCoord,wxDefaultCoord); + + SetHint(_("Search")); + + // Ensure that our best size is recomputed using our overridden + // DoGetBestSize(). + InvalidateBestSize(); } - void SetDescriptiveText(const wxString& text) + virtual wxWindow* GetMainWindowOfCompositeControl() { - if ( GetValue() == m_descriptiveText ) - { - ChangeValue(wxEmptyString); - } - - m_descriptiveText = text; + return m_search; } - - wxString GetDescriptiveText() const + + // provide access to the base class protected methods to wxSearchCtrl which + // needs to forward to them + void DoSetValue(const wxString& value, int flags) + { + wxTextCtrl::DoSetValue(value, flags); + } + + bool DoLoadFile(const wxString& file, int fileType) { - return m_descriptiveText; + return wxTextCtrl::DoLoadFile(file, fileType); } - + + bool DoSaveFile(const wxString& file, int fileType) + { + return wxTextCtrl::DoSaveFile(file, fileType); + } + protected: void OnText(wxCommandEvent& eventText) { @@ -159,31 +118,35 @@ protected: m_search->GetEventHandler()->ProcessEvent(event); } - void OnIdle(wxIdleEvent& WXUNUSED(event)) +#ifdef __WXMSW__ + // We increase the text control height to be the same as for the controls + // with border as this is what we actually need here because even though + // this control itself is borderless, it's inside wxSearchCtrl which does + // have the border and so should have the same height as the normal text + // entries with border. + // + // This is a bit ugly and it would arguably be better to use whatever size + // the base class version returns and just centre the text vertically in + // the search control but I failed to modify the code in LayoutControls() + // to do this easily and as there is much in that code I don't understand + // (notably what is the logic for buttons sizing?) I prefer to not touch it + // at all. + virtual wxSize DoGetBestSize() const { - if ( IsEmpty() && !(wxWindow::FindFocus() == this) ) - { - ChangeValue(m_descriptiveText); - SetInsertionPoint(0); - SetForegroundColour(wxStepColour(m_defaultFG, LIGHT_STEP)); - } - } + const long flags = GetWindowStyleFlag(); + wxSearchTextCtrl* const self = const_cast(this); - void OnFocus(wxFocusEvent& event) - { - event.Skip(); - if ( GetValue() == m_descriptiveText ) - { - ChangeValue(wxEmptyString); - SetForegroundColour(m_defaultFG); - } + self->SetWindowStyleFlag((flags & ~wxBORDER_MASK) | wxBORDER_DEFAULT); + const wxSize size = wxTextCtrl::DoGetBestSize(); + self->SetWindowStyleFlag(flags); + + return size; } - +#endif // __WXMSW__ + private: wxSearchCtrl* m_search; - wxString m_descriptiveText; - wxColour m_defaultFG; - + DECLARE_EVENT_TABLE() }; @@ -192,8 +155,6 @@ BEGIN_EVENT_TABLE(wxSearchTextCtrl, wxTextCtrl) EVT_TEXT_ENTER(wxID_ANY, wxSearchTextCtrl::OnText) EVT_TEXT_URL(wxID_ANY, wxSearchTextCtrl::OnTextUrl) EVT_TEXT_MAXLEN(wxID_ANY, wxSearchTextCtrl::OnText) - EVT_IDLE(wxSearchTextCtrl::OnIdle) - EVT_SET_FOCUS(wxSearchTextCtrl::OnFocus) END_EVENT_TABLE() // ---------------------------------------------------------------------------- @@ -210,8 +171,24 @@ public: m_bmp(bmp) { } - void SetBitmapLabel(const wxBitmap& label) { m_bmp = label; } + void SetBitmapLabel(const wxBitmap& label) + { + m_bmp = label; + InvalidateBestSize(); + } + // The buttons in wxSearchCtrl shouldn't accept focus from keyboard because + // this would interfere with the usual TAB processing: the user expects + // that pressing TAB in the search control should switch focus to the next + // control and not give it to the button inside the same control. Besides, + // the search button can be already activated by pressing "Enter" so there + // is really no reason for it to be able to get focus from keyboard. + virtual bool AcceptsFocusFromKeyboard() const { return false; } + + virtual wxWindow* GetMainWindowOfCompositeControl() + { + return m_search; + } protected: wxSize DoGetBestSize() const @@ -224,15 +201,25 @@ protected: wxCommandEvent event(m_eventType, m_search->GetId()); event.SetEventObject(m_search); + if ( m_eventType == wxEVT_SEARCHCTRL_SEARCH_BTN ) + { + // it's convenient to have the string to search for directly in the + // event instead of having to retrieve it from the control in the + // event handler code later, so provide it here + event.SetString(m_search->GetValue()); + } + GetEventHandler()->ProcessEvent(event); m_search->SetFocus(); - if ( m_eventType == wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN ) +#if wxUSE_MENUS + if ( m_eventType == wxEVT_SEARCHCTRL_SEARCH_BTN ) { // this happens automatically, just like on Mac OS X m_search->PopupSearchMenu(); } +#endif // wxUSE_MENUS } void OnPaint(wxPaintEvent&) @@ -256,7 +243,7 @@ BEGIN_EVENT_TABLE(wxSearchButton, wxControl) END_EVENT_TABLE() BEGIN_EVENT_TABLE(wxSearchCtrl, wxSearchCtrlBase) - EVT_SEARCHCTRL_SEARCH_BTN(wxID_ANY, wxSearchCtrl::OnSearchButton) + EVT_SEARCHCTRL_CANCEL_BTN(wxID_ANY, wxSearchCtrl::OnCancelButton) EVT_SET_FOCUS(wxSearchCtrl::OnSetFocus) EVT_SIZE(wxSearchCtrl::OnSize) END_EVENT_TABLE() @@ -294,17 +281,21 @@ wxSearchCtrl::wxSearchCtrl(wxWindow *parent, wxWindowID id, void wxSearchCtrl::Init() { - m_text = 0; - m_searchButton = 0; - m_cancelButton = 0; - m_menu = 0; + m_text = NULL; + m_searchButton = NULL; + m_cancelButton = NULL; +#if wxUSE_MENUS + m_menu = NULL; +#endif // wxUSE_MENUS m_searchButtonVisible = true; m_cancelButtonVisible = false; - m_searchMenuBitmapUser = false; m_searchBitmapUser = false; m_cancelBitmapUser = false; +#if wxUSE_MENUS + m_searchMenuBitmapUser = false; +#endif // wxUSE_MENUS } bool wxSearchCtrl::Create(wxWindow *parent, wxWindowID id, @@ -315,30 +306,35 @@ bool wxSearchCtrl::Create(wxWindow *parent, wxWindowID id, const wxValidator& validator, const wxString& name) { + // force border style for more native appearance + style &= ~wxBORDER_MASK; #ifdef __WXGTK__ - if ( !wxTextCtrlBase::Create(parent, id, pos, size, wxSUNKEN_BORDER | style, validator, name) ) + style |= wxBORDER_SUNKEN; +#elif defined(__WXMSW__) + // Don't set the style explicitly, let GetDefaultBorder() work it out, unless + // we will get a sunken border (e.g. on Windows 200) in which case we must + // override with a simple border. + if (GetDefaultBorder() == wxBORDER_SUNKEN) + style |= wxBORDER_SIMPLE; #else - if ( !wxTextCtrlBase::Create(parent, id, pos, size, wxSIMPLE_BORDER | style, validator, name) ) + style |= wxBORDER_SIMPLE; #endif + if ( !wxSearchCtrlBaseBaseClass::Create(parent, id, pos, size, + style, validator, name) ) { return false; } - m_text = new wxSearchTextCtrl(this, value, style & ~wxBORDER_MASK); - m_text->SetDescriptiveText(_("Search")); - - wxSize sizeText = m_text->GetBestSize(); - - m_searchButton = new wxSearchButton(this,wxEVT_COMMAND_SEARCHCTRL_SEARCH_BTN,m_searchBitmap); - m_cancelButton = new wxSearchButton(this,wxEVT_COMMAND_SEARCHCTRL_CANCEL_BTN,m_cancelBitmap); + m_text = new wxSearchTextCtrl(this, value, style); - SetForegroundColour( m_text->GetForegroundColour() ); - m_searchButton->SetForegroundColour( m_text->GetForegroundColour() ); - m_cancelButton->SetForegroundColour( m_text->GetForegroundColour() ); + m_searchButton = new wxSearchButton(this, + wxEVT_SEARCHCTRL_SEARCH_BTN, + m_searchBitmap); + m_cancelButton = new wxSearchButton(this, + wxEVT_SEARCHCTRL_CANCEL_BTN, + m_cancelBitmap); SetBackgroundColour( m_text->GetBackgroundColour() ); - m_searchButton->SetBackgroundColour( m_text->GetBackgroundColour() ); - m_cancelButton->SetBackgroundColour( m_text->GetBackgroundColour() ); RecalcBitmaps(); @@ -352,11 +348,15 @@ wxSearchCtrl::~wxSearchCtrl() delete m_text; delete m_searchButton; delete m_cancelButton; +#if wxUSE_MENUS delete m_menu; +#endif // wxUSE_MENUS } // search control specific interfaces +#if wxUSE_MENUS + void wxSearchCtrl::SetMenu( wxMenu* menu ) { if ( menu == m_menu ) @@ -382,7 +382,7 @@ void wxSearchCtrl::SetMenu( wxMenu* menu ) } } wxRect rect = GetRect(); - LayoutControls(0, 0, rect.GetWidth(), rect.GetHeight()); + LayoutControls(0, 0, rect.GetWidth(), rect.GetHeight()); } wxMenu* wxSearchCtrl::GetMenu() @@ -390,6 +390,8 @@ wxMenu* wxSearchCtrl::GetMenu() return m_menu; } +#endif // wxUSE_MENUS + void wxSearchCtrl::ShowSearchButton( bool show ) { if ( m_searchButtonVisible == show ) @@ -433,12 +435,12 @@ bool wxSearchCtrl::IsCancelButtonVisible() const void wxSearchCtrl::SetDescriptiveText(const wxString& text) { - m_text->SetDescriptiveText(text); + m_text->SetHint(text); } wxString wxSearchCtrl::GetDescriptiveText() const { - return m_text->GetDescriptiveText(); + return m_text->GetHint(); } // ---------------------------------------------------------------------------- @@ -452,7 +454,7 @@ wxSize wxSearchCtrl::DoGetBestSize() const wxSize sizeCancel(0,0); int searchMargin = 0; int cancelMargin = 0; - if ( m_searchButtonVisible || m_menu ) + if ( m_searchButtonVisible || HasMenu() ) { sizeSearch = m_searchButton->GetBestSize(); searchMargin = MARGIN; @@ -482,7 +484,7 @@ void wxSearchCtrl::LayoutControls(int x, int y, int width, int height) { if ( !m_text ) return; - + wxSize sizeText = m_text->GetBestSize(); // make room for the search menu & clear button int horizontalBorder = ( sizeText.y - sizeText.y * 14 / 21 ) / 2; @@ -490,12 +492,14 @@ void wxSearchCtrl::LayoutControls(int x, int y, int width, int height) y += BORDER; width -= horizontalBorder*2; height -= BORDER*2; + if (width < 0) width = 0; + if (height < 0) height = 0; wxSize sizeSearch(0,0); wxSize sizeCancel(0,0); int searchMargin = 0; int cancelMargin = 0; - if ( m_searchButtonVisible || m_menu ) + if ( m_searchButtonVisible || HasMenu() ) { sizeSearch = m_searchButton->GetBestSize(); searchMargin = MARGIN; @@ -505,7 +509,7 @@ void wxSearchCtrl::LayoutControls(int x, int y, int width, int height) sizeCancel = m_cancelButton->GetBestSize(); cancelMargin = MARGIN; } - m_searchButton->Show( m_searchButtonVisible || m_menu ); + m_searchButton->Show( m_searchButtonVisible || HasMenu() ); m_cancelButton->Show( m_cancelButtonVisible ); if ( sizeSearch.x + sizeCancel.x > width ) @@ -515,36 +519,36 @@ void wxSearchCtrl::LayoutControls(int x, int y, int width, int height) searchMargin = 0; cancelMargin = 0; } - wxCoord textWidth = width - sizeSearch.x - sizeCancel.x - searchMargin - cancelMargin; + wxCoord textWidth = width - sizeSearch.x - sizeCancel.x - searchMargin - cancelMargin - 1; + if (textWidth < 0) textWidth = 0; // position the subcontrols inside the client area m_searchButton->SetSize(x, y + ICON_OFFSET - 1, sizeSearch.x, height); - m_text->SetSize( x + sizeSearch.x + searchMargin, + m_text->SetSize( x + sizeSearch.x + searchMargin, y + ICON_OFFSET - BORDER, - textWidth, + textWidth, height); m_cancelButton->SetSize(x + sizeSearch.x + searchMargin + textWidth + cancelMargin, y + ICON_OFFSET - 1, sizeCancel.x, height); } +wxWindowList wxSearchCtrl::GetCompositeWindowParts() const +{ + wxWindowList parts; + parts.push_back(m_text); + parts.push_back(m_searchButton); + parts.push_back(m_cancelButton); + return parts; +} // accessors // --------- -wxString wxSearchCtrl::GetValue() const +wxString wxSearchCtrl::DoGetValue() const { - wxString value = m_text->GetValue(); - if (value == m_text->GetDescriptiveText()) - return wxEmptyString; - else - return value; + return m_text->GetValue(); } -void wxSearchCtrl::SetValue(const wxString& value) -{ - m_text->SetValue(value); -} - wxString wxSearchCtrl::GetRange(long from, long to) const { return m_text->GetRange(from, to); @@ -766,7 +770,7 @@ long wxSearchCtrl::GetInsertionPoint() const { return m_text->GetInsertionPoint(); } -wxTextPos wxSearchCtrl::GetLastPosition() const +long wxSearchCtrl::GetLastPosition() const { return m_text->GetLastPosition(); } @@ -787,23 +791,35 @@ void wxSearchCtrl::SetEditable(bool editable) bool wxSearchCtrl::SetFont(const wxFont& font) { - bool result = wxSearchCtrlBase::SetFont(font); - if ( result && m_text ) - { - result = m_text->SetFont(font); - } + if ( !wxSearchCtrlBase::SetFont(font) ) + return false; + + // Recreate the bitmaps as their size may have changed. + RecalcBitmaps(); + + return true; +} + +bool wxSearchCtrl::SetBackgroundColour(const wxColour& colour) +{ + if ( !wxSearchCtrlBase::SetBackgroundColour(colour) ) + return false; + + // When the background changes, re-render the bitmaps so that the correct + // colour shows in their "transparent" area. RecalcBitmaps(); - return result; + + return true; } // search control generic only void wxSearchCtrl::SetSearchBitmap( const wxBitmap& bitmap ) { m_searchBitmap = bitmap; - m_searchBitmapUser = bitmap.Ok(); + m_searchBitmapUser = bitmap.IsOk(); if ( m_searchBitmapUser ) { - if ( m_searchButton && !m_menu ) + if ( m_searchButton && !HasMenu() ) { m_searchButton->SetBitmapLabel( m_searchBitmap ); } @@ -815,10 +831,12 @@ void wxSearchCtrl::SetSearchBitmap( const wxBitmap& bitmap ) } } +#if wxUSE_MENUS + void wxSearchCtrl::SetSearchMenuBitmap( const wxBitmap& bitmap ) { m_searchMenuBitmap = bitmap; - m_searchMenuBitmapUser = bitmap.Ok(); + m_searchMenuBitmapUser = bitmap.IsOk(); if ( m_searchMenuBitmapUser ) { if ( m_searchButton && m_menu ) @@ -833,10 +851,12 @@ void wxSearchCtrl::SetSearchMenuBitmap( const wxBitmap& bitmap ) } } +#endif // wxUSE_MENUS + void wxSearchCtrl::SetCancelBitmap( const wxBitmap& bitmap ) { m_cancelBitmap = bitmap; - m_cancelBitmapUser = bitmap.Ok(); + m_cancelBitmapUser = bitmap.IsOk(); if ( m_cancelBitmapUser ) { if ( m_cancelButton ) @@ -870,9 +890,17 @@ wxTextCtrl& operator<<(const wxChar c); void wxSearchCtrl::DoSetValue(const wxString& value, int flags) { - m_text->ChangeValue( value ); - if ( flags & SetValue_SendEvent ) - SendTextUpdatedEvent(); + m_text->DoSetValue(value, flags); +} + +bool wxSearchCtrl::DoLoadFile(const wxString& file, int fileType) +{ + return m_text->DoLoadFile(file, fileType); +} + +bool wxSearchCtrl::DoSaveFile(const wxString& file, int fileType) +{ + return m_text->DoSaveFile(file, fileType); } // do the window-specific processing after processing the update event @@ -907,7 +935,7 @@ static int GetMultiplier() wxBitmap wxSearchCtrl::RenderSearchBitmap( int x, int y, bool renderDrop ) { wxColour bg = GetBackgroundColour(); - wxColour fg = wxStepColour(GetForegroundColour(), LIGHT_STEP-20); + wxColour fg = GetForegroundColour().ChangeLightness(LIGHT_STEP-20); //=============================================================================== // begin drawing code @@ -989,7 +1017,7 @@ wxBitmap wxSearchCtrl::RenderSearchBitmap( int x, int y, bool renderDrop ) mem.DrawPolygon(WXSIZEOF(dropPolygon),dropPolygon,multiplier*triangleX,multiplier*triangleY); } mem.SelectObject(wxNullBitmap); - + //=============================================================================== // end drawing code //=============================================================================== @@ -1012,7 +1040,7 @@ wxBitmap wxSearchCtrl::RenderSearchBitmap( int x, int y, bool renderDrop ) wxBitmap wxSearchCtrl::RenderCancelBitmap( int x, int y ) { wxColour bg = GetBackgroundColour(); - wxColour fg = wxStepColour(GetForegroundColour(), LIGHT_STEP); + wxColour fg = GetForegroundColour().ChangeLightness(LIGHT_STEP); //=============================================================================== // begin drawing code @@ -1108,13 +1136,13 @@ void wxSearchCtrl::RecalcBitmaps() if ( !m_searchBitmapUser ) { if ( - !m_searchBitmap.Ok() || + !m_searchBitmap.IsOk() || m_searchBitmap.GetHeight() != bitmapHeight || m_searchBitmap.GetWidth() != bitmapWidth ) { m_searchBitmap = RenderSearchBitmap(bitmapWidth,bitmapHeight,false); - if ( !m_menu ) + if ( !HasMenu() ) { m_searchButton->SetBitmapLabel(m_searchBitmap); } @@ -1122,10 +1150,11 @@ void wxSearchCtrl::RecalcBitmaps() // else this bitmap was set by user, don't alter } +#if wxUSE_MENUS if ( !m_searchMenuBitmapUser ) { if ( - !m_searchMenuBitmap.Ok() || + !m_searchMenuBitmap.IsOk() || m_searchMenuBitmap.GetHeight() != bitmapHeight || m_searchMenuBitmap.GetWidth() != bitmapWidth ) @@ -1138,24 +1167,26 @@ void wxSearchCtrl::RecalcBitmaps() } // else this bitmap was set by user, don't alter } +#endif // wxUSE_MENUS if ( !m_cancelBitmapUser ) { if ( - !m_cancelBitmap.Ok() || + !m_cancelBitmap.IsOk() || m_cancelBitmap.GetHeight() != bitmapHeight || m_cancelBitmap.GetWidth() != bitmapHeight ) { - m_cancelBitmap = RenderCancelBitmap(bitmapHeight-BORDER,bitmapHeight-BORDER); // square + m_cancelBitmap = RenderCancelBitmap(bitmapHeight-BORDER-1,bitmapHeight-BORDER-1); // square m_cancelButton->SetBitmapLabel(m_cancelBitmap); } // else this bitmap was set by user, don't alter } } -void wxSearchCtrl::OnSearchButton( wxCommandEvent& event ) +void wxSearchCtrl::OnCancelButton( wxCommandEvent& event ) { + m_text->Clear(); event.Skip(); } @@ -1174,6 +1205,8 @@ void wxSearchCtrl::OnSize( wxSizeEvent& WXUNUSED(event) ) LayoutControls(0, 0, width, height); } +#if wxUSE_MENUS + void wxSearchCtrl::PopupSearchMenu() { if ( m_menu ) @@ -1183,6 +1216,8 @@ void wxSearchCtrl::PopupSearchMenu() } } +#endif // wxUSE_MENUS + #endif // !wxUSE_NATIVE_SEARCH_CONTROL #endif // wxUSE_SEARCHCTRL