Changed wxPropertyCategory to use same cell rendering code as regular properties. This allows labels for category columns other than the first. Rendering code was heavily modified to allow 'merging' of cells when needed.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@63012 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Jaakko Salli
2009-12-29 16:04:40 +00:00
parent 62f6be4448
commit e16bff8e62
5 changed files with 189 additions and 106 deletions

View File

@@ -98,7 +98,11 @@ public:
DontUseCellBgCol DontUseCellBgCol
}; };
virtual void Render( wxDC& dc, /**
Returns @true if rendered something in the foreground (text or
bitmap.
*/
virtual bool Render( wxDC& dc,
const wxRect& rect, const wxRect& rect,
const wxPropertyGrid* propertyGrid, const wxPropertyGrid* propertyGrid,
wxPGProperty* property, wxPGProperty* property,
@@ -171,7 +175,7 @@ public:
class WXDLLIMPEXP_PROPGRID wxPGDefaultRenderer : public wxPGCellRenderer class WXDLLIMPEXP_PROPGRID wxPGDefaultRenderer : public wxPGCellRenderer
{ {
public: public:
virtual void Render( wxDC& dc, virtual bool Render( wxDC& dc,
const wxRect& rect, const wxRect& rect,
const wxPropertyGrid* propertyGrid, const wxPropertyGrid* propertyGrid,
wxPGProperty* property, wxPGProperty* property,
@@ -2484,6 +2488,7 @@ public:
int GetTextExtent( const wxWindow* wnd, const wxFont& font ) const; int GetTextExtent( const wxWindow* wnd, const wxFont& font ) const;
virtual wxString ValueToString( wxVariant& value, int argFlags ) const; virtual wxString ValueToString( wxVariant& value, int argFlags ) const;
virtual wxString GetValueAsString( int argFlags = 0 ) const;
protected: protected:
void SetTextColIndex( unsigned int colInd ) void SetTextColIndex( unsigned int colInd )

View File

@@ -207,7 +207,10 @@
@subsection wxPropertyCategory @subsection wxPropertyCategory
Not an actual property per se, but a header for a group of properties. Not an actual property per se, but a header for a group of properties.
Regardless inherits from wxPGProperty. Regardless inherits from wxPGProperty, and supports displaying 'labels'
for columns other than the first one. Easiest way to set category's
label for second column is to call wxPGProperty::SetValue() with string
argument.
@subsection wxStringProperty @subsection wxStringProperty

View File

@@ -1868,6 +1868,10 @@ void FormMain::PopulateWithLibraryConfig ()
pid = pg->Append( new wxPropertyCategory( wxT("wxWidgets Library Configuration") ) ); pid = pg->Append( new wxPropertyCategory( wxT("wxWidgets Library Configuration") ) );
pg->SetPropertyCell( pid, 0, wxPG_LABEL, bmp ); pg->SetPropertyCell( pid, 0, wxPG_LABEL, bmp );
// Both of following lines would set a label for the second column
pg->SetPropertyCell( pid, 1, "Is Enabled" );
pid->SetValue("Is Enabled");
ADD_WX_LIB_CONF_GROUP(wxT("Global Settings")) ADD_WX_LIB_CONF_GROUP(wxT("Global Settings"))
ADD_WX_LIB_CONF( wxUSE_GUI ) ADD_WX_LIB_CONF( wxUSE_GUI )

View File

@@ -186,10 +186,14 @@ void wxPGCellRenderer::PostDrawCell( wxDC& dc,
// wxPGDefaultRenderer // wxPGDefaultRenderer
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
void wxPGDefaultRenderer::Render( wxDC& dc, const wxRect& rect, bool wxPGDefaultRenderer::Render( wxDC& dc, const wxRect& rect,
const wxPropertyGrid* propertyGrid, wxPGProperty* property, const wxPropertyGrid* propertyGrid, wxPGProperty* property,
int column, int item, int flags ) const int column, int item, int flags ) const
{ {
const wxPGEditor* editor = NULL;
const wxPGCell* cell = NULL;
wxString text;
bool isUnspecified = property->IsValueUnspecified(); bool isUnspecified = property->IsValueUnspecified();
if ( column == 1 && item == -1 ) if ( column == 1 && item == -1 )
@@ -199,17 +203,19 @@ void wxPGDefaultRenderer::Render( wxDC& dc, const wxRect& rect,
{ {
// Common Value // Common Value
if ( !isUnspecified ) if ( !isUnspecified )
DrawText( dc, rect, 0, propertyGrid->GetCommonValueLabel(cmnVal) ); {
return; text = propertyGrid->GetCommonValueLabel(cmnVal);
DrawText( dc, rect, 0, text );
if ( text.length() )
return true;
}
return false;
} }
} }
const wxPGEditor* editor = NULL;
const wxPGCell* cell = NULL;
wxString text;
int imageWidth = 0; int imageWidth = 0;
int preDrawFlags = flags; int preDrawFlags = flags;
bool res = false;
property->GetDisplayInfo(column, item, flags, &text, &cell); property->GetDisplayInfo(column, item, flags, &text, &cell);
@@ -262,6 +268,8 @@ void wxPGDefaultRenderer::Render( wxDC& dc, const wxRect& rect,
text = property->GetHintText(); text = property->GetHintText();
if ( text.length() > 0 ) if ( text.length() > 0 )
{ {
res = true;
const wxColour& hCol = const wxColour& hCol =
propertyGrid->GetCellDisabledTextColour(); propertyGrid->GetCellDisabledTextColour();
dc.SetTextForeground(hCol); dc.SetTextForeground(hCol);
@@ -271,6 +279,10 @@ void wxPGDefaultRenderer::Render( wxDC& dc, const wxRect& rect,
editor = NULL; editor = NULL;
} }
} }
else
{
res = true;
}
} }
int imageOffset = property->GetImageOffset(imageWidth); int imageOffset = property->GetImageOffset(imageWidth);
@@ -278,7 +290,7 @@ void wxPGDefaultRenderer::Render( wxDC& dc, const wxRect& rect,
DrawEditorValue( dc, rect, imageOffset, text, property, editor ); DrawEditorValue( dc, rect, imageOffset, text, property, editor );
// active caption gets nice dotted rectangle // active caption gets nice dotted rectangle
if ( property->IsCategory() /*&& column == 0*/ ) if ( property->IsCategory() && column == 0 )
{ {
if ( flags & Selected ) if ( flags & Selected )
{ {
@@ -299,6 +311,8 @@ void wxPGDefaultRenderer::Render( wxDC& dc, const wxRect& rect,
} }
PostDrawCell(dc, propertyGrid, *cell, preDrawFlags); PostDrawCell(dc, propertyGrid, *cell, preDrawFlags);
return res;
} }
wxSize wxPGDefaultRenderer::GetImageSize( const wxPGProperty* property, wxSize wxPGDefaultRenderer::GetImageSize( const wxPGProperty* property,
@@ -2629,9 +2643,31 @@ wxPropertyCategory::~wxPropertyCategory()
wxString wxPropertyCategory::ValueToString( wxVariant& WXUNUSED(value), wxString wxPropertyCategory::ValueToString( wxVariant& WXUNUSED(value),
int WXUNUSED(argFlags) ) const int WXUNUSED(argFlags) ) const
{ {
if ( m_value.GetType() == wxPG_VARIANT_TYPE_STRING )
return m_value.GetString();
return wxEmptyString; return wxEmptyString;
} }
wxString wxPropertyCategory::GetValueAsString( int argFlags ) const
{
#if wxPG_COMPATIBILITY_1_4
// This is backwards compatibility test
// That is, to make sure this function is not overridden
// (instead, ValueToString() should be).
if ( argFlags == 0xFFFF )
{
// Do not override! (for backwards compliancy)
return g_invalidStringContent;
}
#endif
// Unspecified value is always empty string
if ( IsValueUnspecified() )
return wxEmptyString;
return wxPGProperty::GetValueAsString(argFlags);
}
int wxPropertyCategory::GetTextExtent( const wxWindow* wnd, const wxFont& font ) const int wxPropertyCategory::GetTextExtent( const wxWindow* wnd, const wxFont& font ) const
{ {
if ( m_textExtent > 0 ) if ( m_textExtent > 0 )

View File

@@ -2123,6 +2123,7 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
const wxPGProperty* firstSelected = GetSelection(); const wxPGProperty* firstSelected = GetSelection();
const wxPropertyGridPageState* state = m_pState; const wxPropertyGridPageState* state = m_pState;
const wxArrayInt& colWidths = state->m_colWidths;
#if wxPG_REFRESH_CONTROLS_AFTER_REPAINT #if wxPG_REFRESH_CONTROLS_AFTER_REPAINT
bool wasSelectedPainted = false; bool wasSelectedPainted = false;
@@ -2222,9 +2223,9 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
unsigned int si; unsigned int si;
int sx = x; int sx = x;
for ( si=0; si<state->m_colWidths.size(); si++ ) for ( si=0; si<colWidths.size(); si++ )
{ {
sx += state->m_colWidths[si]; sx += colWidths[si];
dc.DrawLine( sx, y, sx, y2 ); dc.DrawLine( sx, y, sx, y2 );
} }
@@ -2320,12 +2321,16 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
m_marginWidth, m_marginWidth,
lh ); lh );
if ( p->IsCategory() ) // Default cell rect fill the entire row
wxRect cellRect(greyDepthX, y,
gridWidth - greyDepth + 2, rowHeight-1 );
bool isCategory = p->IsCategory();
if ( isCategory )
{ {
// Captions have their cell areas merged as one
dc.SetFont(m_captionFont); dc.SetFont(m_captionFont);
fontChanged = true; fontChanged = true;
wxRect cellRect(greyDepthX, y, gridWidth - greyDepth + 2, rowHeight-1 );
if ( renderFlags & wxPGCellRenderer::DontUseCellBgCol ) if ( renderFlags & wxPGCellRenderer::DontUseCellBgCol )
{ {
@@ -2337,13 +2342,6 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
{ {
dc.SetTextForeground(rowFgCol); dc.SetTextForeground(rowFgCol);
} }
wxPGCellRenderer* renderer = p->GetCellRenderer(0);
renderer->Render( dc, cellRect, this, p, 0, -1, renderFlags );
// Tree Item Button
if ( !HasFlag(wxPG_HIDE_MARGIN) && p->HasVisibleChildren() )
DrawExpanderButton( dc, butRect, p );
} }
else else
{ {
@@ -2351,111 +2349,148 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
if ( butRect.x > 0 ) if ( butRect.x > 0 )
butRect.x += IN_CELL_EXPANDER_BUTTON_X_ADJUST; butRect.x += IN_CELL_EXPANDER_BUTTON_X_ADJUST;
if ( p->m_flags & wxPG_PROP_MODIFIED && (windowStyle & wxPG_BOLD_MODIFIED) ) if ( p->m_flags & wxPG_PROP_MODIFIED &&
(windowStyle & wxPG_BOLD_MODIFIED) )
{ {
dc.SetFont(m_captionFont); dc.SetFont(m_captionFont);
fontChanged = true; fontChanged = true;
} }
unsigned int ci; // Magic fine-tuning for non-category rows
int cellX = x + 1; cellRect.x += 1;
int nextCellWidth = state->m_colWidths[0] - }
(greyDepthX - m_marginWidth);
wxRect cellRect(greyDepthX+1, y, 0, rowHeight-1);
int textXAdd = textMarginHere - greyDepthX;
for ( ci=0; ci<state->m_colWidths.size(); ci++ ) int firstCellWidth = colWidths[0] - (greyDepthX - m_marginWidth);
int firstCellX = cellRect.x;
// Calculate cellRect.x for the last cell
unsigned int ci = 0;
int cellX = x + 1;
for ( ci=0; ci<colWidths.size(); ci++ )
cellX += colWidths[ci];
cellRect.x = cellX;
// Draw cells from back to front so that we can easily tell if the
// cell on the right was empty from text
bool prevFilled = true;
ci = colWidths.size();
do
{
ci--;
int textXAdd = 0;
if ( ci == 0 )
{ {
cellRect.width = nextCellWidth - 1; textXAdd = textMarginHere - greyDepthX;
cellRect.width = firstCellWidth;
cellRect.x = firstCellX;
}
else
{
int colWidth = colWidths[ci];
cellRect.width = colWidth;
cellRect.x -= colWidth;
}
wxWindow* cellEditor = NULL; // Merge with column to the right?
int cellRenderFlags = renderFlags; if ( !prevFilled && isCategory )
{
cellRect.width += colWidths[ci+1];
}
// Tree Item Button (must be drawn before clipping is set up) if ( !isCategory )
if ( ci == 0 && !HasFlag(wxPG_HIDE_MARGIN) && p->HasVisibleChildren() ) cellRect.width -= 1;
DrawExpanderButton( dc, butRect, p );
// Background wxWindow* cellEditor = NULL;
if ( isSelected && (ci == 1 || ci == m_selColumn) ) int cellRenderFlags = renderFlags;
// Tree Item Button (must be drawn before clipping is set up)
if ( ci == 0 && !HasFlag(wxPG_HIDE_MARGIN) && p->HasVisibleChildren() )
DrawExpanderButton( dc, butRect, p );
// Background
if ( isSelected && (ci == 1 || ci == m_selColumn) )
{
if ( p == firstSelected )
{ {
if ( p == firstSelected ) if ( ci == 1 && m_wndEditor )
{ cellEditor = m_wndEditor;
if ( ci == 1 && m_wndEditor ) else if ( ci == m_selColumn && m_labelEditor )
cellEditor = m_wndEditor; cellEditor = m_labelEditor;
else if ( ci == m_selColumn && m_labelEditor ) }
cellEditor = m_labelEditor;
}
if ( cellEditor ) if ( cellEditor )
{ {
wxColour editorBgCol = wxColour editorBgCol =
cellEditor->GetBackgroundColour(); cellEditor->GetBackgroundColour();
dc.SetBrush(editorBgCol); dc.SetBrush(editorBgCol);
dc.SetPen(editorBgCol); dc.SetPen(editorBgCol);
dc.SetTextForeground(m_colPropFore); dc.SetTextForeground(m_colPropFore);
dc.DrawRectangle(cellRect); dc.DrawRectangle(cellRect);
if ( m_dragStatus != 0 || if ( m_dragStatus != 0 ||
(m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE) ) (m_iFlags & wxPG_FL_CUR_USES_CUSTOM_IMAGE) )
cellEditor = NULL; cellEditor = NULL;
}
else
{
dc.SetBrush(m_colPropBack);
dc.SetPen(m_colPropBack);
dc.SetTextForeground(m_colDisPropFore);
if ( p->IsEnabled() )
dc.SetTextForeground(rowFgCol);
else
dc.SetTextForeground(m_colDisPropFore);
}
} }
else else
{ {
if ( renderFlags & wxPGCellRenderer::DontUseCellBgCol ) dc.SetBrush(m_colPropBack);
{ dc.SetPen(m_colPropBack);
dc.SetBrush(rowBgBrush); dc.SetTextForeground(m_colDisPropFore);
dc.SetPen(rowBgCol); if ( p->IsEnabled() )
}
if ( renderFlags & wxPGCellRenderer::DontUseCellFgCol )
{
dc.SetTextForeground(rowFgCol); dc.SetTextForeground(rowFgCol);
}
}
dc.SetClippingRegion(cellRect);
cellRect.x += textXAdd;
cellRect.width -= textXAdd;
// Foreground
if ( !cellEditor )
{
wxPGCellRenderer* renderer;
int cmnVal = p->GetCommonValue();
if ( cmnVal == -1 || ci != 1 )
{
renderer = p->GetCellRenderer(ci);
renderer->Render( dc, cellRect, this, p, ci, -1,
cellRenderFlags );
}
else else
{ dc.SetTextForeground(m_colDisPropFore);
renderer = GetCommonValue(cmnVal)->GetRenderer(); }
renderer->Render( dc, cellRect, this, p, ci, -1, }
cellRenderFlags ); else
} {
if ( renderFlags & wxPGCellRenderer::DontUseCellBgCol )
{
dc.SetBrush(rowBgBrush);
dc.SetPen(rowBgCol);
} }
cellX += state->m_colWidths[ci]; if ( renderFlags & wxPGCellRenderer::DontUseCellFgCol )
if ( ci < (state->m_colWidths.size()-1) ) {
nextCellWidth = state->m_colWidths[ci+1]; dc.SetTextForeground(rowFgCol);
cellRect.x = cellX; }
dc.DestroyClippingRegion(); // Is this really necessary?
textXAdd = 0;
} }
dc.SetClippingRegion(cellRect);
cellRect.x += textXAdd;
cellRect.width -= textXAdd;
// Foreground
if ( !cellEditor )
{
wxPGCellRenderer* renderer;
int cmnVal = p->GetCommonValue();
if ( cmnVal == -1 || ci != 1 )
{
renderer = p->GetCellRenderer(ci);
prevFilled = renderer->Render(dc, cellRect, this,
p, ci, -1,
cellRenderFlags );
}
else
{
renderer = GetCommonValue(cmnVal)->GetRenderer();
prevFilled = renderer->Render(dc, cellRect, this,
p, ci, -1,
cellRenderFlags );
}
}
else
{
prevFilled = true;
}
dc.DestroyClippingRegion(); // Is this really necessary?
} }
while ( ci > 0 );
if ( fontChanged ) if ( fontChanged )
dc.SetFont(normalFont); dc.SetFont(normalFont);