From 8941fa8806ad22825b13367a0b48f889f177fe90 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 28 Sep 2003 00:23:08 +0000 Subject: [PATCH] added 3-state checkboxes (patch 813790) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@23982 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + docs/latex/wx/checkbox.tex | 64 ++++++++++++-- include/wx/checkbox.h | 91 +++++++++++++++++++- include/wx/mac/checkbox.h | 4 + include/wx/msw/checkbox.h | 6 +- samples/widgets/Makefile.in | 4 + samples/widgets/checkbox.cpp | 160 +++++++++++++++++++++++++++++++++++ samples/widgets/makefile.bcc | 4 + samples/widgets/makefile.gcc | 4 + samples/widgets/makefile.vc | 4 + samples/widgets/makefile.wat | 4 + samples/widgets/widgets.bkl | 6 +- samples/widgets/widgets.dsp | 4 + src/mac/carbon/checkbox.cpp | 73 ++++++++++++++-- src/mac/checkbox.cpp | 73 ++++++++++++++-- src/msw/checkbox.cpp | 82 ++++++++++++++++-- 16 files changed, 547 insertions(+), 37 deletions(-) create mode 100644 samples/widgets/checkbox.cpp diff --git a/docs/changes.txt b/docs/changes.txt index c08cfa022a..049981e0af 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -70,6 +70,7 @@ All: All (GUI): +- added 3-state checkboxes for MSW/Mac (Dimitri Schoolwerth) - added some support for C++ exceptions in the library (do read the manual!) - added wxListCtrl::GetViewRect() - added wxTextCtrl::MarkDirty() diff --git a/docs/latex/wx/checkbox.tex b/docs/latex/wx/checkbox.tex index 673cb679fc..a47d108e16 100644 --- a/docs/latex/wx/checkbox.tex +++ b/docs/latex/wx/checkbox.tex @@ -1,7 +1,8 @@ \section{\class{wxCheckBox}}\label{wxcheckbox} -A checkbox is a labelled box which is either on (checkmark is visible) -or off (no checkmark). +A checkbox is a labelled box which by default is either on (checkmark is visible) +or off (no checkmark). Optionally (When the wxCHK_3STATE style flag is set) it can have +a third state, called the mixed or undetermined state. Often this is used as a "Does Not Apply" state. \wxheading{Derived from} @@ -16,8 +17,12 @@ or off (no checkmark). \wxheading{Window styles} -\twocolwidtha{5cm} +\twocolwidtha{7cm} \begin{twocollist}\itemsep=0pt +\twocolitem{\windowstyle{wxCHK\_2STATE}}{Create a 2-state checkbox (This is the default).} +\twocolitem{\windowstyle{wxCHK\_3STATE}}{Create a 3-state checkbox.} +\twocolitem{\windowstyle{wxCHK\_ALLOW\_3RD\_STATE\_FOR\_USER}}{By default a user can't set a 3-state checkbox +to the third state. It can only be done from code. Using this flags allows the user to set the checkbox to the third state by clicking. } \twocolitem{\windowstyle{wxALIGN\_RIGHT}}{Makes the text appear on the left of the checkbox.} \end{twocollist} @@ -92,11 +97,44 @@ for details. \constfunc{bool}{GetValue}{\void} -Gets the state of the checkbox. +Gets the state of a 2-state checkbox. + +\wxheading{Return value} + +Returns \true if it is checked, \false otherwise. + +\membersection{wxCheckBox::Get3StateValue}\label{wxcheckboxgetthreestatevalue} + +\constfunc{wxCheckBoxState}{Get3StateValue}{\void} + +Gets the state of a 3-state checkbox. + +\wxheading{Return value} + +Returns wxCHK\_UNCHECKED when the checkbox is unchecked, wxCHK\_CHECKED + when it is checked and wxCHK\_UNDETERMINED when it's in the undetermined +state. Asserts when the function is used with a 2-state checkbox. + +\membersection{wxCheckBox::Is3rdStateAllowedForUser}\label{wxcheckboxis3rdstateallowedforuser} + +\constfunc{bool}{Is3rdStateAllowedForUser}{\void} + +Returns whether or not the user can set the checkbox to the third state. \wxheading{Return value} -Returns {\tt true} if it is checked, {\tt false} otherwise. +Returns \true if the user can set the third state of this checkbox, \false if it can only be set +programmatically or if it's a 2-state checkbox. + +\membersection{wxCheckBox::Is3State}\label{wxcheckboxis3state} + +\constfunc{bool}{Is3State}{\void} + +Returns whether or not the checkbox is a 3-state checkbox. + +\wxheading{Return value} + +Returns \true if this checkbox is a 3-state checkbox, \false if it's a 2-state checkbox. \membersection{wxCheckBox::IsChecked}\label{wxcheckboxischecked} @@ -104,7 +142,7 @@ Returns {\tt true} if it is checked, {\tt false} otherwise. This is just a maybe more readable synonym for \helpref{GetValue}{wxcheckboxgetvalue}: just as the latter, it returns -{\tt true} if the checkbox is checked and {\tt false} otherwise. +\true if the checkbox is checked and \false otherwise. \membersection{wxCheckBox::SetValue}\label{wxcheckboxsetvalue} @@ -115,5 +153,17 @@ wxEVT\_COMMAND\_CHECKBOX\_CLICKED event to get emitted. \wxheading{Parameters} -\docparam{state}{If {\tt true}, the check is on, otherwise it is off.} +\docparam{state}{If \true, the check is on, otherwise it is off.} + +\membersection{wxCheckBox::Set3StateValue}\label{wxcheckboxset3statevalue} + +\func{void}{Set3StateValue}{\param{const wxCheckBoxState}{ state}} + +Sets the checkbox to the given state. This does not cause a +wxEVT\_COMMAND\_CHECKBOX\_CLICKED event to get emitted. + +\wxheading{Parameters} +\docparam{state}{Can be one of: wxCHK\_UNCHECKED (Check is off), wxCHK\_CHECKED + (Check is on) or wxCHK\_UNDETERMINED (Check is mixed). Asserts when the checkbox + is a 2-state checkbox and setting the state to wxCHK\_UNDETERMINED.} diff --git a/include/wx/checkbox.h b/include/wx/checkbox.h index a011252b43..ac034b8e12 100644 --- a/include/wx/checkbox.h +++ b/include/wx/checkbox.h @@ -18,7 +18,38 @@ #include "wx/control.h" -WXDLLEXPORT_DATA(extern const wxChar*) wxCheckBoxNameStr; + +/* + * wxCheckBox style flags + * (Using wxCHK_* because wxCB_* is used by wxComboBox). + * Determine whether to use a 3-state or 2-state + * checkbox. 3-state enables to differentiate + * between 'unchecked', 'checked' and 'undetermined'. + */ +#define wxCHK_2STATE 0x0000 +#define wxCHK_3STATE 0x1000 + +/* + * If this style is set the user can set the checkbox to the + * undetermined state. If not set the undetermined set can only + * be set programmatically. + * This style can only be used with 3 state checkboxes. + */ +#define wxCHK_ALLOW_3RD_STATE_FOR_USER 0x2000 + +/* + * The possible states of a 3-state checkbox (Compatible + * with the 2-state checkbox). + */ +enum wxCheckBoxState +{ + wxCHK_UNCHECKED, + wxCHK_CHECKED, + wxCHK_UNDETERMINED /* 3-state checkbox only */ +}; + + +WXDLLEXPORT_DATA(extern const wxChar *) wxCheckBoxNameStr; // ---------------------------------------------------------------------------- // wxCheckBox: a control which shows a label and a box which may be checked @@ -30,10 +61,64 @@ public: wxCheckBoxBase() { } // set/get the checked status of the listbox - virtual void SetValue(bool value) = 0; + virtual void SetValue(const bool value) = 0; virtual bool GetValue() const = 0; - bool IsChecked() const { return GetValue(); } + bool IsChecked() const + { + wxASSERT_MSG( !Is3State(), wxT("Calling IsChecked() doesn't make sense for") + wxT(" a three state checkbox, Use Get3StateValue() instead") ); + + return GetValue(); + } + + wxCheckBoxState Get3StateValue() const + { + wxCheckBoxState state = DoGet3StateValue(); + + if ( state == wxCHK_UNDETERMINED && !Is3State() ) + { + // Undetermined state with a 2-state checkbox?? + wxFAIL_MSG( wxT("DoGet3StateValue() says the 2-state checkbox is ") + wxT("in an undetermined/third state") ); + + state = wxCHK_UNCHECKED; + } + + return state; + } + + void Set3StateValue(wxCheckBoxState state) + { + if ( state == wxCHK_UNDETERMINED && !Is3State() ) + { + wxFAIL_MSG(wxT("Setting a 2-state checkbox to undetermined state")); + state = wxCHK_UNCHECKED; + } + + DoSet3StateValue(state); + } + + bool Is3State() const + { + return (m_style & wxCHK_3STATE) != 0; + } + + bool Is3rdStateAllowedForUser() const + { + return (m_style & wxCHK_ALLOW_3RD_STATE_FOR_USER) != 0; + } + +protected: + int m_style; + + virtual void DoSet3StateValue(wxCheckBoxState WXUNUSED(state)) { wxFAIL; } + + virtual wxCheckBoxState DoGet3StateValue() const + { + wxFAIL; + return wxCHK_UNCHECKED; + } private: DECLARE_NO_COPY_CLASS(wxCheckBoxBase) diff --git a/include/wx/mac/checkbox.h b/include/wx/mac/checkbox.h index 4677f5dd66..a426cb734b 100644 --- a/include/wx/mac/checkbox.h +++ b/include/wx/mac/checkbox.h @@ -37,6 +37,10 @@ public: const wxString& name = wxCheckBoxNameStr); virtual void SetValue(bool); virtual bool GetValue() const; + + void DoSet3StateValue(wxCheckBoxState val); + virtual wxCheckBoxState DoGet3StateValue() const; + virtual void MacHandleControlClick( WXWidget control , wxInt16 controlpart , bool mouseStillDown ); virtual void Command(wxCommandEvent& event); diff --git a/include/wx/msw/checkbox.h b/include/wx/msw/checkbox.h index f3504693bc..1d685dfeaf 100644 --- a/include/wx/msw/checkbox.h +++ b/include/wx/msw/checkbox.h @@ -42,7 +42,7 @@ public: const wxValidator& validator = wxDefaultValidator, const wxString& name = wxCheckBoxNameStr); - virtual void SetValue(bool value); + virtual void SetValue(const bool value); virtual bool GetValue() const; virtual void SetLabel(const wxString& label); @@ -53,6 +53,10 @@ public: protected: virtual wxSize DoGetBestSize() const; + virtual void DoSet3StateValue(wxCheckBoxState value); + + virtual wxCheckBoxState DoGet3StateValue() const; + private: DECLARE_DYNAMIC_CLASS_NO_COPY(wxCheckBox) }; diff --git a/samples/widgets/Makefile.in b/samples/widgets/Makefile.in index 1c017b35ed..cb89c27ae3 100644 --- a/samples/widgets/Makefile.in +++ b/samples/widgets/Makefile.in @@ -41,6 +41,7 @@ WIDGETS_CXXFLAGS = $(CPPFLAGS) -D__WX$(TOOLKIT)__ $(__WXUNIV_DEFINE_p) \ -I$(srcdir)/../../samples $(CXXFLAGS) WIDGETS_OBJECTS = \ widgets_button.o \ + widgets_checkbox.o \ widgets_combobox.o \ widgets_gauge.o \ widgets_listbox.o \ @@ -162,6 +163,9 @@ widgets.app/Contents/PkgInfo: widgets$(EXEEXT) $(top_srcdir)/src/mac/Info.plist. widgets_button.o: $(srcdir)/button.cpp $(CXXC) -c -o $@ $(WIDGETS_CXXFLAGS) $< +widgets_checkbox.o: $(srcdir)/checkbox.cpp + $(CXXC) -c -o $@ $(WIDGETS_CXXFLAGS) $< + widgets_combobox.o: $(srcdir)/combobox.cpp $(CXXC) -c -o $@ $(WIDGETS_CXXFLAGS) $< diff --git a/samples/widgets/checkbox.cpp b/samples/widgets/checkbox.cpp new file mode 100644 index 0000000000..8b242623b2 --- /dev/null +++ b/samples/widgets/checkbox.cpp @@ -0,0 +1,160 @@ +///////////////////////////////////////////////////////////////////////////// +// Program: wxWindows Widgets Sample +// Name: checkbox.cpp +// Purpose: Part of the widgets sample showing wxCheckBox +// Author: Dimitri Schoolwerth +// Created: 27 Sep 2003 +// Id: $Id$ +// Copyright: (c) 2003 wxWindows team +// License: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// for compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +// for all others, include the necessary headers +#ifndef WX_PRECOMP + #include "wx/app.h" + #include "wx/log.h" + + #include "wx/button.h" + #include "wx/checkbox.h" + + #include "wx/sizer.h" + +#endif + +#include "widgets.h" + +#include "icons/checkbox.xpm" + +// ---------------------------------------------------------------------------- +// CheckBoxWidgetsPage +// ---------------------------------------------------------------------------- + +class CheckBoxWidgetsPage : public WidgetsPage +{ +public: + CheckBoxWidgetsPage(wxNotebook *notebook, wxImageList *imaglist); + virtual ~CheckBoxWidgetsPage(); + +protected: + // event handlers + void OnCheckBox(wxCommandEvent& event); + + void OnButton(wxCommandEvent& event); + + // the controls + // ------------ + + wxCheckBox *m_chk2States, + *m_chk3States, + *m_chk3StatesAllows3rdStateForUser; + + wxButton *m_button; + +private: + DECLARE_EVENT_TABLE() + DECLARE_WIDGETS_PAGE(CheckBoxWidgetsPage) +}; + +// ---------------------------------------------------------------------------- +// event tables +// ---------------------------------------------------------------------------- + +BEGIN_EVENT_TABLE(CheckBoxWidgetsPage, WidgetsPage) + EVT_CHECKBOX(wxID_ANY, CheckBoxWidgetsPage::OnCheckBox) + EVT_BUTTON(wxID_ANY, CheckBoxWidgetsPage::OnButton) +END_EVENT_TABLE() + +// ============================================================================ +// implementation +// ============================================================================ + +IMPLEMENT_WIDGETS_PAGE(CheckBoxWidgetsPage, wxT("CheckBox")); + +CheckBoxWidgetsPage::CheckBoxWidgetsPage(wxNotebook *notebook, + wxImageList *imaglist) + : WidgetsPage(notebook) +{ + imaglist->Add(wxBitmap(checkbox_xpm)); + + m_chk2States = new wxCheckBox( this, wxID_ANY, + wxT("I'm a standard 2-state checkbox") ); + m_chk3States = new wxCheckBox( this, wxID_ANY, + wxT("I'm a 3-state checkbox that disallows setting the undetermined") + wxT(" state by the user" ), + wxDefaultPosition, wxDefaultSize, wxCHK_3STATE); + m_button = new wxButton( this, wxID_ANY, wxT("&Programmatically set this") + wxT(" checkbox to undetermined state") ); + + m_chk3StatesAllows3rdStateForUser = new wxCheckBox(this, wxID_ANY, + wxT("I'm a 3-state checkbox that allows setting the 3rd state by the user"), + wxDefaultPosition, wxDefaultSize, wxCHK_3STATE + | wxCHK_ALLOW_3RD_STATE_FOR_USER); + + wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL); + + sizerTop->Add(0, 0, 1, wxEXPAND); + sizerTop->Add(m_chk2States, 0, wxEXPAND); + sizerTop->Add(0, 0, 1, wxEXPAND); + wxSizer *sizerCheckBoxAndButton = new wxBoxSizer(wxHORIZONTAL); + { + wxSizer *szr = sizerCheckBoxAndButton; + szr->Add(m_chk3States, 0, wxEXPAND); + szr->Add(0, 0, 1, wxEXPAND); + szr->Add(m_button, 0, wxEXPAND); + + sizerTop->Add(szr, 0, wxEXPAND); + } + + sizerTop->Add(0, 0, 1, wxEXPAND); + sizerTop->Add(m_chk3StatesAllows3rdStateForUser, 0, wxEXPAND); + sizerTop->Add(0, 0, 1, wxEXPAND); + + SetSizer(sizerTop); + + sizerTop->Fit(this); +} + +CheckBoxWidgetsPage::~CheckBoxWidgetsPage() +{ +} + +// ---------------------------------------------------------------------------- +// event handlers +// ---------------------------------------------------------------------------- + +void CheckBoxWidgetsPage::OnCheckBox(wxCommandEvent& event) +{ + static const wxString stateNames[] = + { + wxT("unchecked"), + wxT("checked"), + wxT("undetermined/mixed"), + }; + wxCheckBoxState state = (wxCheckBoxState) event.GetInt(); + + wxCHECK_RET( (state >= 0) && (state < WXSIZEOF(stateNames)), + "event.GetInt() returned an invalid wxCheckBoxState" ); + + wxLogMessage(wxT("Checkbox now set to state: %s"), + stateNames[state].c_str()); +} + +void CheckBoxWidgetsPage::OnButton(wxCommandEvent& WXUNUSED(event)) +{ + m_chk3States->Set3StateValue(wxCHK_UNDETERMINED); +} diff --git a/samples/widgets/makefile.bcc b/samples/widgets/makefile.bcc index aaa9ba15f6..a6cfc74bd9 100644 --- a/samples/widgets/makefile.bcc +++ b/samples/widgets/makefile.bcc @@ -30,6 +30,7 @@ WIDGETS_CXXFLAGS = $(CPPFLAGS) $(__RUNTIME_LIBS_6) -I$(BCCDIR)\include \ -I. $(__DLLFLAG_p) -I.\..\..\samples $(CXXFLAGS) WIDGETS_OBJECTS = \ $(OBJS)\widgets_button.obj \ + $(OBJS)\widgets_checkbox.obj \ $(OBJS)\widgets_combobox.obj \ $(OBJS)\widgets_gauge.obj \ $(OBJS)\widgets_listbox.obj \ @@ -166,6 +167,9 @@ all: $(OBJS)\widgets.exe $(OBJS)\widgets_button.obj: .\button.cpp $(CXX) -q -c -P -o$@ $(WIDGETS_CXXFLAGS) $** +$(OBJS)\widgets_checkbox.obj: .\checkbox.cpp + $(CXX) -q -c -P -o$@ $(WIDGETS_CXXFLAGS) $** + $(OBJS)\widgets_combobox.obj: .\combobox.cpp $(CXX) -q -c -P -o$@ $(WIDGETS_CXXFLAGS) $** diff --git a/samples/widgets/makefile.gcc b/samples/widgets/makefile.gcc index 951606eee6..ee895c66f7 100644 --- a/samples/widgets/makefile.gcc +++ b/samples/widgets/makefile.gcc @@ -23,6 +23,7 @@ WIDGETS_CXXFLAGS = $(CPPFLAGS) $(__DEBUGINFO) $(__OPTIMIZEFLAG_2) $(GCCFLAGS) \ $(__EXCEPTIONSFLAG_5) WIDGETS_OBJECTS = \ $(OBJS)\widgets_button.o \ + $(OBJS)\widgets_checkbox.o \ $(OBJS)\widgets_combobox.o \ $(OBJS)\widgets_gauge.o \ $(OBJS)\widgets_listbox.o \ @@ -173,6 +174,9 @@ all: $(OBJS)\widgets.exe $(OBJS)\widgets_button.o: ./button.cpp $(CXX) -c -o $@ $(WIDGETS_CXXFLAGS) $< +$(OBJS)\widgets_checkbox.o: ./checkbox.cpp + $(CXX) -c -o $@ $(WIDGETS_CXXFLAGS) $< + $(OBJS)\widgets_combobox.o: ./combobox.cpp $(CXX) -c -o $@ $(WIDGETS_CXXFLAGS) $< diff --git a/samples/widgets/makefile.vc b/samples/widgets/makefile.vc index 9bb4a86d97..eeafbc6e04 100644 --- a/samples/widgets/makefile.vc +++ b/samples/widgets/makefile.vc @@ -24,6 +24,7 @@ WIDGETS_CXXFLAGS = $(CPPFLAGS) /M$(__RUNTIME_LIBS_7)$(__DEBUGRUNTIME_3) \ $(__EXCEPTIONSFLAG_8) $(__EXCEPTIONSFLAG_9) WIDGETS_OBJECTS = \ $(OBJS)\widgets_button.obj \ + $(OBJS)\widgets_checkbox.obj \ $(OBJS)\widgets_combobox.obj \ $(OBJS)\widgets_gauge.obj \ $(OBJS)\widgets_listbox.obj \ @@ -254,6 +255,9 @@ all: $(OBJS)\widgets.exe $(OBJS)\widgets_button.obj: .\button.cpp $(CXX) /c /nologo /TP /Fo$@ $(WIDGETS_CXXFLAGS) $** +$(OBJS)\widgets_checkbox.obj: .\checkbox.cpp + $(CXX) /c /nologo /TP /Fo$@ $(WIDGETS_CXXFLAGS) $** + $(OBJS)\widgets_combobox.obj: .\combobox.cpp $(CXX) /c /nologo /TP /Fo$@ $(WIDGETS_CXXFLAGS) $** diff --git a/samples/widgets/makefile.wat b/samples/widgets/makefile.wat index 932e90f19f..e48a34ab71 100644 --- a/samples/widgets/makefile.wat +++ b/samples/widgets/makefile.wat @@ -177,6 +177,7 @@ WIDGETS_CXXFLAGS = $(CPPFLAGS) $(__DEBUGINFO_0) $(__OPTIMIZEFLAG_2) -bm & -i=.\..\..\samples $(CXXFLAGS) $(__EXCEPTIONSFLAG_7) WIDGETS_OBJECTS = & $(OBJS)\widgets_button.obj & + $(OBJS)\widgets_checkbox.obj & $(OBJS)\widgets_combobox.obj & $(OBJS)\widgets_gauge.obj & $(OBJS)\widgets_listbox.obj & @@ -200,6 +201,9 @@ all : .SYMBOLIC $(OBJS)\widgets.exe $(OBJS)\widgets_button.obj : .AUTODEPEND .\button.cpp $(CXX) -zq -fo=$^@ $(WIDGETS_CXXFLAGS) $< +$(OBJS)\widgets_checkbox.obj : .AUTODEPEND .\checkbox.cpp + $(CXX) -zq -fo=$^@ $(WIDGETS_CXXFLAGS) $< + $(OBJS)\widgets_combobox.obj : .AUTODEPEND .\combobox.cpp $(CXX) -zq -fo=$^@ $(WIDGETS_CXXFLAGS) $< diff --git a/samples/widgets/widgets.bkl b/samples/widgets/widgets.bkl index 6fe98b16cc..804049b4bf 100644 --- a/samples/widgets/widgets.bkl +++ b/samples/widgets/widgets.bkl @@ -4,9 +4,9 @@ - button.cpp combobox.cpp gauge.cpp listbox.cpp notebook.cpp - radiobox.cpp slider.cpp spinbtn.cpp static.cpp textctrl.cpp - widgets.cpp + button.cpp checkbox.cpp combobox.cpp gauge.cpp listbox.cpp + notebook.cpp radiobox.cpp slider.cpp spinbtn.cpp static.cpp + textctrl.cpp widgets.cpp core base widgets.rc diff --git a/samples/widgets/widgets.dsp b/samples/widgets/widgets.dsp index bdd43c33bc..df59b2de75 100644 --- a/samples/widgets/widgets.dsp +++ b/samples/widgets/widgets.dsp @@ -472,6 +472,10 @@ SOURCE=.\button.cpp # End Source File # Begin Source File +SOURCE=.\checkbox.cpp +# End Source File +# Begin Source File + SOURCE=.\combobox.cpp # End Source File # Begin Source File diff --git a/src/mac/carbon/checkbox.cpp b/src/mac/carbon/checkbox.cpp index 3df5c00d9e..7d58ccb136 100644 --- a/src/mac/carbon/checkbox.cpp +++ b/src/mac/carbon/checkbox.cpp @@ -34,12 +34,20 @@ bool wxCheckBox::Create(wxWindow *parent, wxWindowID id, const wxString& label, if ( !wxCheckBoxBase::Create(parent, id, pos, size, style, validator, name) ) return false; + m_style = style; + Rect bounds ; Str255 title ; MacPreControlCreate( parent , id , label , pos , size ,style, validator , name , &bounds , title ) ; - m_macControl = ::NewControl( MAC_WXHWND(parent->MacGetRootWindow()) , &bounds , title , false , 0 , 0 , 1, + SInt16 maxValue = 1 /* kControlCheckboxCheckedValue */; + if (style & wxCH_3STATE) + { + maxValue = 2 /* kControlCheckboxMixedValue */; + } + + m_macControl = ::NewControl( MAC_WXHWND(parent->MacGetRootWindow()) , &bounds , title , false , 0 , 0 , maxValue, kControlCheckBoxProc , (long) this ) ; MacPostControlCreate() ; @@ -49,26 +57,75 @@ bool wxCheckBox::Create(wxWindow *parent, wxWindowID id, const wxString& label, void wxCheckBox::SetValue(bool val) { - ::SetControl32BitValue( (ControlHandle) m_macControl , val ) ; - MacRedrawControl() ; + if (val) + { + Set3StateValue(wxCHK_CHECKED); + } + else + { + Set3StateValue(wxCHK_UNCHECKED); + } } bool wxCheckBox::GetValue() const { - return ::GetControl32BitValue( (ControlHandle) m_macControl ) ; + return (DoGet3StateValue() != 0); } void wxCheckBox::Command (wxCommandEvent & event) { - SetValue ((event.GetInt() != 0)); - ProcessCommand (event); + int state = event.GetInt(); + + wxCHECK_RET( (state == wxCHK_UNCHECKED) || (state == wxCHK_CHECKED) + || (state == wxCHK_UNDETERMINED), + wxT("event.GetInt() returned an invalid checkbox state") ); + + Set3StateValue((wxCheckBoxState) state); + + ProcessCommand(event); +} + +wxCheckBoxState wxCheckBox::DoGet3StateValue() const +{ + return (wxCheckBoxState) ::GetControl32BitValue( (ControlHandle) m_macControl ); +} + +void wxCheckBox::DoSet3StateValue(wxCheckBoxState val) +{ + ::SetControl32BitValue( (ControlHandle) m_macControl , (int) val) ; + MacRedrawControl() ; } void wxCheckBox::MacHandleControlClick( WXWidget WXUNUSED(control), wxInt16 WXUNUSED(controlpart) , bool WXUNUSED(mouseStillDown) ) { - SetValue( !GetValue() ) ; wxCommandEvent event(wxEVT_COMMAND_CHECKBOX_CLICKED, m_windowId ); - event.SetInt(GetValue()); + wxCheckBoxState state = Get3StateValue(); + + if (state == wxCHK_UNCHECKED) + { + state = wxCHK_CHECKED; + } + else if (state == wxCHK_CHECKED) + { + // If the style flag to allow the user setting the undetermined state + // is set, then set the state to undetermined. Otherwise set state to + // unchecked. + if ( Is3rdStateAllowedForUser() ) + { + state = wxCHK_UNDETERMINED; + } + else + { + state = wxCHK_UNCHECKED; + } + } + else if (state == wxCHK_UNDETERMINED) + { + state = wxCHK_UNCHECKED; + } + Set3StateValue(state); + + event.SetInt(state); event.SetEventObject(this); ProcessCommand(event); } diff --git a/src/mac/checkbox.cpp b/src/mac/checkbox.cpp index 3df5c00d9e..7d58ccb136 100644 --- a/src/mac/checkbox.cpp +++ b/src/mac/checkbox.cpp @@ -34,12 +34,20 @@ bool wxCheckBox::Create(wxWindow *parent, wxWindowID id, const wxString& label, if ( !wxCheckBoxBase::Create(parent, id, pos, size, style, validator, name) ) return false; + m_style = style; + Rect bounds ; Str255 title ; MacPreControlCreate( parent , id , label , pos , size ,style, validator , name , &bounds , title ) ; - m_macControl = ::NewControl( MAC_WXHWND(parent->MacGetRootWindow()) , &bounds , title , false , 0 , 0 , 1, + SInt16 maxValue = 1 /* kControlCheckboxCheckedValue */; + if (style & wxCH_3STATE) + { + maxValue = 2 /* kControlCheckboxMixedValue */; + } + + m_macControl = ::NewControl( MAC_WXHWND(parent->MacGetRootWindow()) , &bounds , title , false , 0 , 0 , maxValue, kControlCheckBoxProc , (long) this ) ; MacPostControlCreate() ; @@ -49,26 +57,75 @@ bool wxCheckBox::Create(wxWindow *parent, wxWindowID id, const wxString& label, void wxCheckBox::SetValue(bool val) { - ::SetControl32BitValue( (ControlHandle) m_macControl , val ) ; - MacRedrawControl() ; + if (val) + { + Set3StateValue(wxCHK_CHECKED); + } + else + { + Set3StateValue(wxCHK_UNCHECKED); + } } bool wxCheckBox::GetValue() const { - return ::GetControl32BitValue( (ControlHandle) m_macControl ) ; + return (DoGet3StateValue() != 0); } void wxCheckBox::Command (wxCommandEvent & event) { - SetValue ((event.GetInt() != 0)); - ProcessCommand (event); + int state = event.GetInt(); + + wxCHECK_RET( (state == wxCHK_UNCHECKED) || (state == wxCHK_CHECKED) + || (state == wxCHK_UNDETERMINED), + wxT("event.GetInt() returned an invalid checkbox state") ); + + Set3StateValue((wxCheckBoxState) state); + + ProcessCommand(event); +} + +wxCheckBoxState wxCheckBox::DoGet3StateValue() const +{ + return (wxCheckBoxState) ::GetControl32BitValue( (ControlHandle) m_macControl ); +} + +void wxCheckBox::DoSet3StateValue(wxCheckBoxState val) +{ + ::SetControl32BitValue( (ControlHandle) m_macControl , (int) val) ; + MacRedrawControl() ; } void wxCheckBox::MacHandleControlClick( WXWidget WXUNUSED(control), wxInt16 WXUNUSED(controlpart) , bool WXUNUSED(mouseStillDown) ) { - SetValue( !GetValue() ) ; wxCommandEvent event(wxEVT_COMMAND_CHECKBOX_CLICKED, m_windowId ); - event.SetInt(GetValue()); + wxCheckBoxState state = Get3StateValue(); + + if (state == wxCHK_UNCHECKED) + { + state = wxCHK_CHECKED; + } + else if (state == wxCHK_CHECKED) + { + // If the style flag to allow the user setting the undetermined state + // is set, then set the state to undetermined. Otherwise set state to + // unchecked. + if ( Is3rdStateAllowedForUser() ) + { + state = wxCHK_UNDETERMINED; + } + else + { + state = wxCHK_UNCHECKED; + } + } + else if (state == wxCHK_UNDETERMINED) + { + state = wxCHK_UNCHECKED; + } + Set3StateValue(state); + + event.SetInt(state); event.SetEventObject(this); ProcessCommand(event); } diff --git a/src/msw/checkbox.cpp b/src/msw/checkbox.cpp index aff1a13013..e8c6ec263e 100644 --- a/src/msw/checkbox.cpp +++ b/src/msw/checkbox.cpp @@ -39,10 +39,18 @@ #include "wx/msw/private.h" +#ifndef BST_UNCHECKED + #define BST_UNCHECKED 0x0000 +#endif + #ifndef BST_CHECKED #define BST_CHECKED 0x0001 #endif +#ifndef BST_INDETERMINATE + #define BST_INDETERMINATE 0x0002 +#endif + // ============================================================================ // implementation // ============================================================================ @@ -66,14 +74,14 @@ wxBEGIN_FLAGS( wxCheckBoxStyle ) wxFLAGS_MEMBER(wxDOUBLE_BORDER) wxFLAGS_MEMBER(wxRAISED_BORDER) wxFLAGS_MEMBER(wxSTATIC_BORDER) - wxFLAGS_MEMBER(wxBORDER) + wxFLAGS_MEMBER(wxNO_BORDER) // standard window styles wxFLAGS_MEMBER(wxTAB_TRAVERSAL) wxFLAGS_MEMBER(wxCLIP_CHILDREN) wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW) wxFLAGS_MEMBER(wxWANTS_CHARS) - wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE) + wxFLAGS_MEMBER(wxNO_FULL_REPAINT_ON_RESIZE) wxFLAGS_MEMBER(wxALWAYS_SHOW_SB ) wxFLAGS_MEMBER(wxVSCROLL) wxFLAGS_MEMBER(wxHSCROLL) @@ -107,9 +115,20 @@ IMPLEMENT_DYNAMIC_CLASS(wxCheckBox, wxControl) bool wxCheckBox::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id)) { wxCommandEvent event(wxEVT_COMMAND_CHECKBOX_CLICKED, m_windowId); - event.SetInt(GetValue()); + 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); event.SetEventObject(this); ProcessCommand(event); + return TRUE; } @@ -124,9 +143,26 @@ bool wxCheckBox::Create(wxWindow *parent, if ( !CreateControl(parent, id, pos, size, style, validator, name) ) return FALSE; - long msStyle = BS_AUTOCHECKBOX | WS_TABSTOP; + m_style = style; + + long msStyle = WS_TABSTOP; + + if ( style & wxCHK_3STATE ) + { + msStyle |= BS_AUTO3STATE; + } + else + { + wxASSERT_MSG( !Is3rdStateAllowedForUser(), + wxT("Using wxCH_ALLOW_3RD_STATE_FOR_USER") + wxT(" style flag for a 2-state checkbox is useless") ); + msStyle |= BS_AUTOCHECKBOX; + } + if ( style & wxALIGN_RIGHT ) + { msStyle |= BS_LEFTTEXT; + } return MSWCreateControl(wxT("BUTTON"), msStyle, pos, size, label, 0); } @@ -170,18 +206,50 @@ wxSize wxCheckBox::DoGetBestSize() const void wxCheckBox::SetValue(bool val) { - SendMessage(GetHwnd(), BM_SETCHECK, val, 0); + if (val) + { + Set3StateValue(wxCHK_CHECKED); + } + else + { + Set3StateValue(wxCHK_UNCHECKED); + } } bool wxCheckBox::GetValue() const { - return (SendMessage(GetHwnd(), BM_GETCHECK, 0, 0) & BST_CHECKED) != 0; + return (Get3StateValue() != 0); } void wxCheckBox::Command(wxCommandEvent& event) { - SetValue(event.GetInt() != 0); + int state = event.GetInt(); + wxCHECK_RET( (state == wxCHK_UNCHECKED) || (state == wxCHK_CHECKED) + || (state == wxCHK_UNDETERMINED), + wxT("event.GetInt() returned an invalid checkbox state") ); + + Set3StateValue((wxCheckBoxState) state); ProcessCommand(event); } +wxCOMPILE_TIME_ASSERT(wxCHK_UNCHECKED == BST_UNCHECKED + && wxCHK_CHECKED == BST_CHECKED + && wxCHK_UNDETERMINED == BST_INDETERMINATE, EnumValuesIncorrect); + +void wxCheckBox::DoSet3StateValue(wxCheckBoxState state) +{ + ::SendMessage(GetHwnd(), BM_SETCHECK, (WPARAM) state, 0); +} + +wxCheckBoxState wxCheckBox::DoGet3StateValue() const +{ +#ifdef __WIN32__ + return (wxCheckBoxState) ::SendMessage(GetHwnd(), BM_GETCHECK, 0, 0); +#else + return (wxCheckBoxState) ((::SendMessage(GetHwnd(), BM_GETCHECK, 0, 0) + & 0x001) == 0x001); +#endif + +} + #endif // wxUSE_CHECKBOX -- 2.45.2