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 {\tt true} if it is checked, {\tt false} otherwise.
+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 \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