From 415a0ff16d5d50015e3d43c1c6f32f48f995cbab Mon Sep 17 00:00:00 2001 From: =?utf8?q?W=C5=82odzimierz=20Skiba?= Date: Thu, 18 Nov 2004 13:16:41 +0000 Subject: [PATCH 1/1] 3rd state in checkboxes for wxUniv [closes bug#1040585]. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@30603 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + include/wx/renderer.h | 1 + include/wx/univ/checkbox.h | 7 ++- src/univ/checkbox.cpp | 89 ++++++++++++++++++++++++++++++-------- src/univ/themes/gtk.cpp | 56 +++++++++++++++++++++--- src/univ/themes/win32.cpp | 73 ++++++++++++++++++++++++++----- 6 files changed, 190 insertions(+), 37 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 7473446f25..48796171e1 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -263,6 +263,7 @@ wxUniv: - wxBU_... button align flags support - vertical notebook orientation support +- 3rd state support for checkboxes 2.5.3 diff --git a/include/wx/renderer.h b/include/wx/renderer.h index 1a14e5fb4b..271f19dcad 100644 --- a/include/wx/renderer.h +++ b/include/wx/renderer.h @@ -54,6 +54,7 @@ enum wxCONTROL_SELECTED = 0x00000020, // selected item in e.g. listbox wxCONTROL_CHECKED = 0x00000040, // (check/radio button) is checked wxCONTROL_CHECKABLE = 0x00000080, // (menu) item can be checked + wxCONTROL_UNDETERMINED = wxCONTROL_CHECKABLE, // (check) undetermined state wxCONTROL_FLAGS_MASK = 0x000000ff, diff --git a/include/wx/univ/checkbox.h b/include/wx/univ/checkbox.h index c7aa666d15..9c6108fac9 100644 --- a/include/wx/univ/checkbox.h +++ b/include/wx/univ/checkbox.h @@ -54,7 +54,7 @@ public: { Status_Checked, Status_Unchecked, - Status_Unknown, + Status_3rdState, Status_Max }; @@ -102,8 +102,11 @@ public: virtual bool IsPressed() const { return m_isPressed; } virtual bool HasTransparentBackground() { return true; } - + protected: + virtual void DoSet3StateValue(wxCheckBoxState WXUNUSED(state)); + virtual wxCheckBoxState DoGet3StateValue() const; + virtual bool PerformAction(const wxControlAction& action, long numArg = -1, const wxString& strArg = wxEmptyString); diff --git a/src/univ/checkbox.cpp b/src/univ/checkbox.cpp index 450d303dc1..fa84b05a95 100644 --- a/src/univ/checkbox.cpp +++ b/src/univ/checkbox.cpp @@ -84,24 +84,12 @@ bool wxCheckBox::Create(wxWindow *parent, bool wxCheckBox::GetValue() const { - return m_status == Status_Checked; + return (Get3StateValue() != wxCHK_UNCHECKED); } void wxCheckBox::SetValue(bool value) { - Status status = value ? Status_Checked : Status_Unchecked; - if ( status != m_status ) - { - m_status = status; - - if ( m_status == Status_Checked ) - { - // invoke the hook - OnCheck(); - } - - Refresh(); - } + Set3StateValue( value ? wxCHK_CHECKED : wxCHK_UNCHECKED ); } void wxCheckBox::OnCheck() @@ -151,8 +139,11 @@ void wxCheckBox::DoDraw(wxControlRenderer *renderer) dc.SetFont(GetFont()); dc.SetTextForeground(GetForegroundColour()); - if ( m_status == Status_Checked ) - flags |= wxCONTROL_CHECKED; + switch ( Get3StateValue() ) + { + case wxCHK_CHECKED: flags |= wxCONTROL_CHECKED; + case wxCHK_UNDETERMINED: flags |= wxCONTROL_UNDETERMINED; + } wxBitmap bitmap(GetBitmap(GetState(flags), m_status)); @@ -203,6 +194,40 @@ wxSize wxCheckBox::DoGetBestClientSize() const // checkbox actions // ---------------------------------------------------------------------------- +void wxCheckBox::DoSet3StateValue(wxCheckBoxState state) +{ + Status status; + switch ( state ) + { + case wxCHK_UNCHECKED: status = Status_Unchecked; break; + case wxCHK_CHECKED: status = Status_Checked; break; + default: wxFAIL_MSG(_T("Unknown checkbox state")); + case wxCHK_UNDETERMINED: status = Status_3rdState; break; + } + if ( status != m_status ) + { + m_status = status; + + if ( m_status == Status_Checked ) + { + // invoke the hook + OnCheck(); + } + + Refresh(); + } +} + +wxCheckBoxState wxCheckBox::DoGet3StateValue() const +{ + switch ( m_status ) + { + case Status_Checked: return wxCHK_CHECKED; + case Status_Unchecked: return wxCHK_UNCHECKED; + } + return wxCHK_UNDETERMINED; +} + void wxCheckBox::Press() { if ( !m_isPressed ) @@ -227,7 +252,25 @@ void wxCheckBox::Toggle() { m_isPressed = false; - ChangeValue(!GetValue()); + Status status = m_status; + + switch ( Get3StateValue() ) + { + case wxCHK_CHECKED: + Set3StateValue(Is3rdStateAllowedForUser() ? wxCHK_UNDETERMINED : wxCHK_UNCHECKED); + break; + + case wxCHK_UNCHECKED: + Set3StateValue(wxCHK_CHECKED); + break; + + case wxCHK_UNDETERMINED: + Set3StateValue(wxCHK_UNCHECKED); + break; + } + + if( status != m_status ) + SendEvent(); } void wxCheckBox::ChangeValue(bool value) @@ -241,7 +284,17 @@ void wxCheckBox::SendEvent() { wxCommandEvent event(wxEVT_COMMAND_CHECKBOX_CLICKED, GetId()); InitCommandEvent(event); - event.SetInt(IsChecked()); + wxCheckBoxState state = Get3StateValue(); + + // If the style flag to allow the user setting the undetermined state + // is not set, then skip the undetermined state and set it to unchecked. + if ( state == wxCHK_UNDETERMINED && !Is3rdStateAllowedForUser() ) + { + state = wxCHK_UNCHECKED; + Set3StateValue(state); + } + + event.SetInt(state); Command(event); } diff --git a/src/univ/themes/gtk.cpp b/src/univ/themes/gtk.cpp index 7dddfa2cdd..ecfebabec1 100644 --- a/src/univ/themes/gtk.cpp +++ b/src/univ/themes/gtk.cpp @@ -329,6 +329,7 @@ public: // helpers for "wxBitmap wxColourScheme::Get()" void DrawCheckBitmap(wxDC& dc, const wxRect& rect); void DrawUncheckBitmap(wxDC& dc, const wxRect& rect, bool isPressed); + void DrawUndeterminedBitmap(wxDC& dc, const wxRect& rect, bool isPressed); protected: // DrawBackground() helpers @@ -469,9 +470,9 @@ private: m_penHighlight; // the checkbox bitmaps: first row is for the normal, second for the - // pressed state and the columns are for checked and unchecked status - // respectively - wxBitmap m_bitmapsCheckbox[2][2]; + // pressed state and the columns are for checked, unchecked and + // undeterminated respectively + wxBitmap m_bitmapsCheckbox[2][3]; // the line wrap bitmap (drawn at the end of wrapped lines) wxBitmap m_bmpLineWrap; @@ -1346,6 +1347,35 @@ void wxGTKRenderer::DrawCheckItem(wxDC& dc, // check/radion buttons // ---------------------------------------------------------------------------- +void wxGTKRenderer::DrawUndeterminedBitmap(wxDC& dc, + const wxRect& rectTotal, + bool isPressed) +{ + // FIXME: For sure it is not GTK look but it is better than nothing. + // Show me correct look and I will immediatelly make it better (ABX) + wxRect rect = rectTotal; + + wxColour col1, col2; + + if ( isPressed ) + { + col1 = wxSCHEME_COLOUR(m_scheme, SHADOW_DARK); + col2 = wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED); + } + else + { + col1 = wxSCHEME_COLOUR(m_scheme, SHADOW_DARK); + col2 = wxSCHEME_COLOUR(m_scheme, SHADOW_IN); + } + + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(wxBrush(col1, wxSOLID)); + dc.DrawRectangle(rect); + rect.Deflate(1); + dc.SetBrush(wxBrush(col2, wxSOLID)); + dc.DrawRectangle(rect); +} + void wxGTKRenderer::DrawUncheckBitmap(wxDC& dc, const wxRect& rectTotal, bool isPressed) @@ -1471,7 +1501,7 @@ wxBitmap wxGTKRenderer::GetCheckBitmap(int flags) rect.height = size.y; for ( int i = 0; i < 2; i++ ) { - for ( int j = 0; j < 2; j++ ) + for ( int j = 0; j < 3; j++ ) m_bitmapsCheckbox[i][j].Create(rect.width, rect.height); } @@ -1485,16 +1515,30 @@ wxBitmap wxGTKRenderer::GetCheckBitmap(int flags) dc.SelectObject(m_bitmapsCheckbox[0][1]); DrawUncheckBitmap(dc, rect, false); + // normal undeterminated + dc.SelectObject(m_bitmapsCheckbox[0][2]); + DrawUndeterminedBitmap(dc, rect, false); + // pressed checked m_bitmapsCheckbox[1][0] = m_bitmapsCheckbox[0][0]; // pressed unchecked dc.SelectObject(m_bitmapsCheckbox[1][1]); DrawUncheckBitmap(dc, rect, true); + + // pressed undeterminated + dc.SelectObject(m_bitmapsCheckbox[1][2]); + DrawUndeterminedBitmap(dc, rect, true); } - int row = flags & wxCONTROL_PRESSED ? 1 : 0; - int col = flags & wxCONTROL_CHECKED ? 0 : 1; + int row = flags & wxCONTROL_PRESSED + ? 1 + : 0; + int col = flags & wxCONTROL_CHECKED + ? 0 + : ( flags & wxCONTROL_UNDETERMINED + ? 2 + : 1 ); return m_bitmapsCheckbox[row][col]; } diff --git a/src/univ/themes/win32.cpp b/src/univ/themes/win32.cpp index e5760cca77..8ac9609416 100644 --- a/src/univ/themes/win32.cpp +++ b/src/univ/themes/win32.cpp @@ -110,6 +110,7 @@ enum IndicatorStatus { IndicatorStatus_Checked, IndicatorStatus_Unchecked, + IndicatorStatus_Undeterminated, IndicatorStatus_Max }; @@ -1009,6 +1010,54 @@ static const char *unchecked_item_xpm[] = { "wwwwwwwwwwwww" }; +static const char *undetermined_xpm[] = { +/* columns rows colors chars-per-pixel */ +"13 13 5 1", +"A c #030303", +"B c #838383", +"C c #C3C3C3", +"D c #FBFBFB", +"E c #DBDBDB", +/* pixels */ +"BBBBBBBBBBBBD", +"BAAAAAAAAAAED", +"BACDCDCDCDCED", +"BADCDCDCDBDED", +"BACDCDCDBBCED", +"BADBDCEBBBDED", +"BACBBDBBBDCED", +"BADBBBBBDCDED", +"BACDBBBDCDCED", +"BADCDBDCDCDED", +"BACDCDCDCDCED", +"BEEEEEEEEEEED", +"DDDDDDDDDDDDD" +}; + +static const char *pressed_undetermined_xpm[] = { +/* columns rows colors chars-per-pixel */ +"13 13 5 1", +"A c #040404", +"B c #848484", +"C c #C4C4C4", +"D c #FCFCFC", +"E c #DCDCDC", +/* pixels */ +"BBBBBBBBBBBBD", +"BAAAAAAAAAAED", +"BACCCCCCCCCCD", +"BACCCCCCCACED", +"BACCCCCCAACED", +"BACACCCAAACED", +"BACAACAAACCED", +"BACAAAAACCCED", +"BACCAAACCCCCD", +"BACCCACCCCCED", +"BACCCCCCCCCED", +"BEEEEEEEEEEED", +"DDDDDDDDDDDDD" +}; + static const char *checked_radio_xpm[] = { /* columns rows colors chars-per-pixel */ "12 12 6 1", @@ -1135,40 +1184,40 @@ static const char ** // checkboxes first { // normal state - { checked_xpm, unchecked_xpm }, + { checked_xpm, unchecked_xpm, undetermined_xpm }, // pressed state - { pressed_checked_xpm, pressed_unchecked_xpm }, + { pressed_checked_xpm, pressed_unchecked_xpm, pressed_undetermined_xpm }, // disabled state - { pressed_disabled_checked_xpm, pressed_unchecked_xpm }, + { pressed_disabled_checked_xpm, pressed_unchecked_xpm, pressed_disabled_checked_xpm }, }, // radio { // normal state - { checked_radio_xpm, unchecked_radio_xpm }, + { checked_radio_xpm, unchecked_radio_xpm, NULL }, // pressed state - { pressed_checked_radio_xpm, pressed_unchecked_radio_xpm }, + { pressed_checked_radio_xpm, pressed_unchecked_radio_xpm, NULL }, // disabled state - { pressed_disabled_checked_radio_xpm, pressed_unchecked_radio_xpm }, + { pressed_disabled_checked_radio_xpm, pressed_unchecked_radio_xpm, NULL }, }, // menu { // normal state - { checked_menu_xpm, NULL }, + { checked_menu_xpm, NULL, NULL }, // selected state - { selected_checked_menu_xpm, NULL }, + { selected_checked_menu_xpm, NULL, NULL }, // disabled state - { disabled_checked_menu_xpm, NULL }, + { disabled_checked_menu_xpm, NULL, NULL }, // disabled selected state - { selected_disabled_checked_menu_xpm, NULL }, + { selected_disabled_checked_menu_xpm, NULL, NULL }, } }; @@ -2315,7 +2364,9 @@ wxBitmap wxWin32Renderer::GetIndicator(IndicatorType indType, int flags) IndicatorStatus indStatus = flags & wxCONTROL_CHECKED ? IndicatorStatus_Checked - : IndicatorStatus_Unchecked; + : ( flags & wxCONTROL_UNDETERMINED + ? IndicatorStatus_Undeterminated + : IndicatorStatus_Unchecked ); wxBitmap bmp = m_bmpIndicators[indType][indState][indStatus]; if ( !bmp.Ok() ) -- 2.45.2