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
This commit is contained in:
@@ -263,6 +263,7 @@ wxUniv:
|
|||||||
|
|
||||||
- wxBU_... button align flags support
|
- wxBU_... button align flags support
|
||||||
- vertical notebook orientation support
|
- vertical notebook orientation support
|
||||||
|
- 3rd state support for checkboxes
|
||||||
|
|
||||||
|
|
||||||
2.5.3
|
2.5.3
|
||||||
|
@@ -54,6 +54,7 @@ enum
|
|||||||
wxCONTROL_SELECTED = 0x00000020, // selected item in e.g. listbox
|
wxCONTROL_SELECTED = 0x00000020, // selected item in e.g. listbox
|
||||||
wxCONTROL_CHECKED = 0x00000040, // (check/radio button) is checked
|
wxCONTROL_CHECKED = 0x00000040, // (check/radio button) is checked
|
||||||
wxCONTROL_CHECKABLE = 0x00000080, // (menu) item can be checked
|
wxCONTROL_CHECKABLE = 0x00000080, // (menu) item can be checked
|
||||||
|
wxCONTROL_UNDETERMINED = wxCONTROL_CHECKABLE, // (check) undetermined state
|
||||||
|
|
||||||
wxCONTROL_FLAGS_MASK = 0x000000ff,
|
wxCONTROL_FLAGS_MASK = 0x000000ff,
|
||||||
|
|
||||||
|
@@ -54,7 +54,7 @@ public:
|
|||||||
{
|
{
|
||||||
Status_Checked,
|
Status_Checked,
|
||||||
Status_Unchecked,
|
Status_Unchecked,
|
||||||
Status_Unknown,
|
Status_3rdState,
|
||||||
Status_Max
|
Status_Max
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -102,8 +102,11 @@ public:
|
|||||||
virtual bool IsPressed() const { return m_isPressed; }
|
virtual bool IsPressed() const { return m_isPressed; }
|
||||||
|
|
||||||
virtual bool HasTransparentBackground() { return true; }
|
virtual bool HasTransparentBackground() { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual void DoSet3StateValue(wxCheckBoxState WXUNUSED(state));
|
||||||
|
virtual wxCheckBoxState DoGet3StateValue() const;
|
||||||
|
|
||||||
virtual bool PerformAction(const wxControlAction& action,
|
virtual bool PerformAction(const wxControlAction& action,
|
||||||
long numArg = -1,
|
long numArg = -1,
|
||||||
const wxString& strArg = wxEmptyString);
|
const wxString& strArg = wxEmptyString);
|
||||||
|
@@ -84,24 +84,12 @@ bool wxCheckBox::Create(wxWindow *parent,
|
|||||||
|
|
||||||
bool wxCheckBox::GetValue() const
|
bool wxCheckBox::GetValue() const
|
||||||
{
|
{
|
||||||
return m_status == Status_Checked;
|
return (Get3StateValue() != wxCHK_UNCHECKED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxCheckBox::SetValue(bool value)
|
void wxCheckBox::SetValue(bool value)
|
||||||
{
|
{
|
||||||
Status status = value ? Status_Checked : Status_Unchecked;
|
Set3StateValue( value ? wxCHK_CHECKED : wxCHK_UNCHECKED );
|
||||||
if ( status != m_status )
|
|
||||||
{
|
|
||||||
m_status = status;
|
|
||||||
|
|
||||||
if ( m_status == Status_Checked )
|
|
||||||
{
|
|
||||||
// invoke the hook
|
|
||||||
OnCheck();
|
|
||||||
}
|
|
||||||
|
|
||||||
Refresh();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxCheckBox::OnCheck()
|
void wxCheckBox::OnCheck()
|
||||||
@@ -151,8 +139,11 @@ void wxCheckBox::DoDraw(wxControlRenderer *renderer)
|
|||||||
dc.SetFont(GetFont());
|
dc.SetFont(GetFont());
|
||||||
dc.SetTextForeground(GetForegroundColour());
|
dc.SetTextForeground(GetForegroundColour());
|
||||||
|
|
||||||
if ( m_status == Status_Checked )
|
switch ( Get3StateValue() )
|
||||||
flags |= wxCONTROL_CHECKED;
|
{
|
||||||
|
case wxCHK_CHECKED: flags |= wxCONTROL_CHECKED;
|
||||||
|
case wxCHK_UNDETERMINED: flags |= wxCONTROL_UNDETERMINED;
|
||||||
|
}
|
||||||
|
|
||||||
wxBitmap bitmap(GetBitmap(GetState(flags), m_status));
|
wxBitmap bitmap(GetBitmap(GetState(flags), m_status));
|
||||||
|
|
||||||
@@ -203,6 +194,40 @@ wxSize wxCheckBox::DoGetBestClientSize() const
|
|||||||
// checkbox actions
|
// 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()
|
void wxCheckBox::Press()
|
||||||
{
|
{
|
||||||
if ( !m_isPressed )
|
if ( !m_isPressed )
|
||||||
@@ -227,7 +252,25 @@ void wxCheckBox::Toggle()
|
|||||||
{
|
{
|
||||||
m_isPressed = false;
|
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)
|
void wxCheckBox::ChangeValue(bool value)
|
||||||
@@ -241,7 +284,17 @@ void wxCheckBox::SendEvent()
|
|||||||
{
|
{
|
||||||
wxCommandEvent event(wxEVT_COMMAND_CHECKBOX_CLICKED, GetId());
|
wxCommandEvent event(wxEVT_COMMAND_CHECKBOX_CLICKED, GetId());
|
||||||
InitCommandEvent(event);
|
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);
|
Command(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -329,6 +329,7 @@ public:
|
|||||||
// helpers for "wxBitmap wxColourScheme::Get()"
|
// helpers for "wxBitmap wxColourScheme::Get()"
|
||||||
void DrawCheckBitmap(wxDC& dc, const wxRect& rect);
|
void DrawCheckBitmap(wxDC& dc, const wxRect& rect);
|
||||||
void DrawUncheckBitmap(wxDC& dc, const wxRect& rect, bool isPressed);
|
void DrawUncheckBitmap(wxDC& dc, const wxRect& rect, bool isPressed);
|
||||||
|
void DrawUndeterminedBitmap(wxDC& dc, const wxRect& rect, bool isPressed);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// DrawBackground() helpers
|
// DrawBackground() helpers
|
||||||
@@ -469,9 +470,9 @@ private:
|
|||||||
m_penHighlight;
|
m_penHighlight;
|
||||||
|
|
||||||
// the checkbox bitmaps: first row is for the normal, second for the
|
// the checkbox bitmaps: first row is for the normal, second for the
|
||||||
// pressed state and the columns are for checked and unchecked status
|
// pressed state and the columns are for checked, unchecked and
|
||||||
// respectively
|
// undeterminated respectively
|
||||||
wxBitmap m_bitmapsCheckbox[2][2];
|
wxBitmap m_bitmapsCheckbox[2][3];
|
||||||
|
|
||||||
// the line wrap bitmap (drawn at the end of wrapped lines)
|
// the line wrap bitmap (drawn at the end of wrapped lines)
|
||||||
wxBitmap m_bmpLineWrap;
|
wxBitmap m_bmpLineWrap;
|
||||||
@@ -1346,6 +1347,35 @@ void wxGTKRenderer::DrawCheckItem(wxDC& dc,
|
|||||||
// check/radion buttons
|
// 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,
|
void wxGTKRenderer::DrawUncheckBitmap(wxDC& dc,
|
||||||
const wxRect& rectTotal,
|
const wxRect& rectTotal,
|
||||||
bool isPressed)
|
bool isPressed)
|
||||||
@@ -1471,7 +1501,7 @@ wxBitmap wxGTKRenderer::GetCheckBitmap(int flags)
|
|||||||
rect.height = size.y;
|
rect.height = size.y;
|
||||||
for ( int i = 0; i < 2; i++ )
|
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);
|
m_bitmapsCheckbox[i][j].Create(rect.width, rect.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1485,16 +1515,30 @@ wxBitmap wxGTKRenderer::GetCheckBitmap(int flags)
|
|||||||
dc.SelectObject(m_bitmapsCheckbox[0][1]);
|
dc.SelectObject(m_bitmapsCheckbox[0][1]);
|
||||||
DrawUncheckBitmap(dc, rect, false);
|
DrawUncheckBitmap(dc, rect, false);
|
||||||
|
|
||||||
|
// normal undeterminated
|
||||||
|
dc.SelectObject(m_bitmapsCheckbox[0][2]);
|
||||||
|
DrawUndeterminedBitmap(dc, rect, false);
|
||||||
|
|
||||||
// pressed checked
|
// pressed checked
|
||||||
m_bitmapsCheckbox[1][0] = m_bitmapsCheckbox[0][0];
|
m_bitmapsCheckbox[1][0] = m_bitmapsCheckbox[0][0];
|
||||||
|
|
||||||
// pressed unchecked
|
// pressed unchecked
|
||||||
dc.SelectObject(m_bitmapsCheckbox[1][1]);
|
dc.SelectObject(m_bitmapsCheckbox[1][1]);
|
||||||
DrawUncheckBitmap(dc, rect, true);
|
DrawUncheckBitmap(dc, rect, true);
|
||||||
|
|
||||||
|
// pressed undeterminated
|
||||||
|
dc.SelectObject(m_bitmapsCheckbox[1][2]);
|
||||||
|
DrawUndeterminedBitmap(dc, rect, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int row = flags & wxCONTROL_PRESSED ? 1 : 0;
|
int row = flags & wxCONTROL_PRESSED
|
||||||
int col = flags & wxCONTROL_CHECKED ? 0 : 1;
|
? 1
|
||||||
|
: 0;
|
||||||
|
int col = flags & wxCONTROL_CHECKED
|
||||||
|
? 0
|
||||||
|
: ( flags & wxCONTROL_UNDETERMINED
|
||||||
|
? 2
|
||||||
|
: 1 );
|
||||||
|
|
||||||
return m_bitmapsCheckbox[row][col];
|
return m_bitmapsCheckbox[row][col];
|
||||||
}
|
}
|
||||||
|
@@ -110,6 +110,7 @@ enum IndicatorStatus
|
|||||||
{
|
{
|
||||||
IndicatorStatus_Checked,
|
IndicatorStatus_Checked,
|
||||||
IndicatorStatus_Unchecked,
|
IndicatorStatus_Unchecked,
|
||||||
|
IndicatorStatus_Undeterminated,
|
||||||
IndicatorStatus_Max
|
IndicatorStatus_Max
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1009,6 +1010,54 @@ static const char *unchecked_item_xpm[] = {
|
|||||||
"wwwwwwwwwwwww"
|
"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[] = {
|
static const char *checked_radio_xpm[] = {
|
||||||
/* columns rows colors chars-per-pixel */
|
/* columns rows colors chars-per-pixel */
|
||||||
"12 12 6 1",
|
"12 12 6 1",
|
||||||
@@ -1135,40 +1184,40 @@ static const char **
|
|||||||
// checkboxes first
|
// checkboxes first
|
||||||
{
|
{
|
||||||
// normal state
|
// normal state
|
||||||
{ checked_xpm, unchecked_xpm },
|
{ checked_xpm, unchecked_xpm, undetermined_xpm },
|
||||||
|
|
||||||
// pressed state
|
// pressed state
|
||||||
{ pressed_checked_xpm, pressed_unchecked_xpm },
|
{ pressed_checked_xpm, pressed_unchecked_xpm, pressed_undetermined_xpm },
|
||||||
|
|
||||||
// disabled state
|
// disabled state
|
||||||
{ pressed_disabled_checked_xpm, pressed_unchecked_xpm },
|
{ pressed_disabled_checked_xpm, pressed_unchecked_xpm, pressed_disabled_checked_xpm },
|
||||||
},
|
},
|
||||||
|
|
||||||
// radio
|
// radio
|
||||||
{
|
{
|
||||||
// normal state
|
// normal state
|
||||||
{ checked_radio_xpm, unchecked_radio_xpm },
|
{ checked_radio_xpm, unchecked_radio_xpm, NULL },
|
||||||
|
|
||||||
// pressed state
|
// pressed state
|
||||||
{ pressed_checked_radio_xpm, pressed_unchecked_radio_xpm },
|
{ pressed_checked_radio_xpm, pressed_unchecked_radio_xpm, NULL },
|
||||||
|
|
||||||
// disabled state
|
// disabled state
|
||||||
{ pressed_disabled_checked_radio_xpm, pressed_unchecked_radio_xpm },
|
{ pressed_disabled_checked_radio_xpm, pressed_unchecked_radio_xpm, NULL },
|
||||||
},
|
},
|
||||||
|
|
||||||
// menu
|
// menu
|
||||||
{
|
{
|
||||||
// normal state
|
// normal state
|
||||||
{ checked_menu_xpm, NULL },
|
{ checked_menu_xpm, NULL, NULL },
|
||||||
|
|
||||||
// selected state
|
// selected state
|
||||||
{ selected_checked_menu_xpm, NULL },
|
{ selected_checked_menu_xpm, NULL, NULL },
|
||||||
|
|
||||||
// disabled state
|
// disabled state
|
||||||
{ disabled_checked_menu_xpm, NULL },
|
{ disabled_checked_menu_xpm, NULL, NULL },
|
||||||
|
|
||||||
// disabled selected state
|
// 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 indStatus = flags & wxCONTROL_CHECKED
|
||||||
? IndicatorStatus_Checked
|
? IndicatorStatus_Checked
|
||||||
: IndicatorStatus_Unchecked;
|
: ( flags & wxCONTROL_UNDETERMINED
|
||||||
|
? IndicatorStatus_Undeterminated
|
||||||
|
: IndicatorStatus_Unchecked );
|
||||||
|
|
||||||
wxBitmap bmp = m_bmpIndicators[indType][indState][indStatus];
|
wxBitmap bmp = m_bmpIndicators[indType][indState][indStatus];
|
||||||
if ( !bmp.Ok() )
|
if ( !bmp.Ok() )
|
||||||
|
Reference in New Issue
Block a user