From 3e6d8c311868c2bce749c4d4922e2efb8e3f019a Mon Sep 17 00:00:00 2001 From: Jaakko Salli Date: Tue, 22 Dec 2009 16:12:02 +0000 Subject: [PATCH] Added wxPropertyGrid::SetUnspecifiedValueAppearance(); Added wxPGEditor::SetControlAppearance() for applying wxPGCell attributes on a property editor. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@62973 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/propgrid/editors.h | 32 ++++- include/wx/propgrid/property.h | 5 + include/wx/propgrid/propgrid.h | 43 +++++++ interface/wx/propgrid/propgrid.h | 20 +++ samples/propgrid/propgrid.cpp | 7 + src/propgrid/editors.cpp | 211 ++++++++++++++++++++++++------- src/propgrid/property.cpp | 24 +++- src/propgrid/propgrid.cpp | 37 +++++- 8 files changed, 320 insertions(+), 59 deletions(-) diff --git a/include/wx/propgrid/editors.h b/include/wx/propgrid/editors.h index 37c22eb99e..d35105a365 100644 --- a/include/wx/propgrid/editors.h +++ b/include/wx/propgrid/editors.h @@ -163,9 +163,35 @@ public: wxWindow* ctrl ) const; #endif - /** Sets value in control to unspecified. */ + /** + Sets new appearance for the control. Default implementation + sets foreground colour, background colour, font, plus text + for wxTextCtrl and wxComboCtrl. + + @param appearance + New appearance to be applied. + + @param oldAppearance + Previously applied appearance. Used to detect which + control attributes need to be changed (e.g. so we only + change background colour if really needed). + + @param unspecified + @true if the new appearance represents an unspecified + property value. + */ + virtual void SetControlAppearance( wxPropertyGrid* pg, + wxPGProperty* property, + wxWindow* ctrl, + const wxPGCell& appearance, + const wxPGCell& oldAppearance, + bool unspecified ) const; + + /** + Sets value in control to unspecified. + */ virtual void SetValueToUnspecified( wxPGProperty* property, - wxWindow* ctrl ) const = 0; + wxWindow* ctrl ) const; /** Sets control's value specifically from string. */ virtual void SetControlStringValue( wxPGProperty* property, @@ -239,8 +265,6 @@ public: virtual bool GetValueFromControl( wxVariant& variant, wxPGProperty* property, wxWindow* ctrl ) const; - virtual void SetValueToUnspecified( wxPGProperty* property, - wxWindow* ctrl ) const; virtual wxString GetName() const; diff --git a/include/wx/propgrid/property.h b/include/wx/propgrid/property.h index 9ec2776a80..e8521d6944 100644 --- a/include/wx/propgrid/property.h +++ b/include/wx/propgrid/property.h @@ -254,6 +254,11 @@ public: return (m_refData && GetData()->m_hasValidText); } + /** + Sets empty but valid data to this cell object. + */ + void SetEmptyData(); + /** Merges valid data from srcCell into this. */ diff --git a/include/wx/propgrid/propgrid.h b/include/wx/propgrid/propgrid.h index 494423697d..c6ac6ece21 100644 --- a/include/wx/propgrid/propgrid.h +++ b/include/wx/propgrid/propgrid.h @@ -1239,6 +1239,33 @@ public: return m_sortFunction; } + /** + Sets appearance of value cells representing an unspecified property + value. Default appearance is blank. + + @remarks If you set the unspecified value to have any + textual representation, then that will override + "InlineHelp" attribute. + + @see wxPGProperty::SetValueToUnspecified(), + wxPGProperty::IsValueUnspecified() + */ + void SetUnspecifiedValueAppearance( const wxPGCell& cell ) + { + m_unspecifiedAppearance = m_propertyDefaultCell; + m_unspecifiedAppearance.MergeFrom(cell); + } + + /** + Returns current appearance of unspecified value cells. + + @see SetUnspecifiedValueAppearance() + */ + const wxPGCell& GetUnspecifiedValueAppearance() const + { + return m_unspecifiedAppearance; + } + /** Returns (visual) text representation of the unspecified property value. @@ -1764,6 +1791,12 @@ protected: /** Actions and keys that trigger them. */ wxPGHashMapI2I m_actionTriggers; + /** Appearance of currently active editor. */ + wxPGCell m_editorAppearance; + + /** Appearance of a unspecified value cell. */ + wxPGCell m_unspecifiedAppearance; + // // Temporary values // @@ -2062,6 +2095,16 @@ protected: */ void RecalculateVirtualSize( int forceXPos = -1 ); + void SetEditorAppearance( const wxPGCell& cell, + bool unspecified = false ); + + void ResetEditorAppearance() + { + wxPGCell cell; + cell.SetEmptyData(); + SetEditorAppearance(cell, false); + } + void PrepareAfterItemsAdded(); /** diff --git a/interface/wx/propgrid/propgrid.h b/interface/wx/propgrid/propgrid.h index c9bc3dfc0a..6a75c9b045 100644 --- a/interface/wx/propgrid/propgrid.h +++ b/interface/wx/propgrid/propgrid.h @@ -740,6 +740,13 @@ public: */ wxTextCtrl* GetEditorTextCtrl() const; + /** + Returns current appearance of unspecified value cells. + + @see SetUnspecifiedValueAppearance() + */ + const wxPGCell& GetUnspecifiedValueAppearance() const; + /** Returns (visual) text representation of the unspecified property value. @@ -981,6 +988,19 @@ public: */ void SetSplitterLeft( bool privateChildrenToo = false ); + /** + Sets appearance of value cells representing an unspecified property + value. Default appearance is blank. + + @remarks If you set the unspecified value to have any + textual representation, then that will override + "InlineHelp" attribute. + + @see wxPGProperty::SetValueToUnspecified(), + wxPGProperty::IsValueUnspecified() + */ + void SetUnspecifiedValueAppearance( const wxPGCell& cell ); + /** Sets vertical spacing. Can be 1, 2, or 3 - a value relative to font height. Value of 2 should be default on most platforms. diff --git a/samples/propgrid/propgrid.cpp b/samples/propgrid/propgrid.cpp index 410ec6936a..04c3db2f2d 100644 --- a/samples/propgrid/propgrid.cpp +++ b/samples/propgrid/propgrid.cpp @@ -2156,6 +2156,13 @@ void FormMain::CreateGrid( int style, int extraStyle ) m_pPropGridManager->GetGrid()->SetVerticalSpacing( 2 ); + // + // Set somewhat different unspecified value appearance + wxPGCell cell; + cell.SetText("Unspecified"); + cell.SetFgCol(*wxLIGHT_GREY); + m_propGrid->SetUnspecifiedValueAppearance(cell); + PopulateGrid(); // Change some attributes in all properties diff --git a/src/propgrid/editors.cpp b/src/propgrid/editors.cpp index fa487428a4..21262e302d 100644 --- a/src/propgrid/editors.cpp +++ b/src/propgrid/editors.cpp @@ -169,13 +169,11 @@ wxString wxPGEditor::GetName() const return GetClassInfo()->GetClassName(); } -void wxPGEditor::DrawValue( wxDC& dc, const wxRect& rect, wxPGProperty* property, const wxString& text ) const +void wxPGEditor::DrawValue( wxDC& dc, const wxRect& rect, + wxPGProperty* WXUNUSED(property), + const wxString& text ) const { - if ( !property->IsValueUnspecified() ) - dc.DrawText( text, rect.x+wxPG_XBEFORETEXT, rect.y ); - else - dc.DrawText( property->GetGrid()->GetUnspecifiedValueText(), - rect.x+wxPG_XBEFORETEXT, rect.y ); + dc.DrawText( text, rect.x+wxPG_XBEFORETEXT, rect.y ); } bool wxPGEditor::GetValueFromControl( wxVariant&, wxPGProperty*, wxWindow* ) const @@ -209,6 +207,104 @@ void wxPGEditor::OnFocus( wxPGProperty*, wxWindow* ) const { } +void wxPGEditor::SetControlAppearance( wxPropertyGrid* pg, + wxPGProperty* property, + wxWindow* ctrl, + const wxPGCell& cell, + const wxPGCell& oCell, + bool WXUNUSED(unspecified) ) const +{ + // Get old editor appearance + wxTextCtrl* tc = NULL; + wxComboCtrl* cb = NULL; + if ( ctrl->IsKindOf(CLASSINFO(wxTextCtrl)) ) + { + tc = (wxTextCtrl*) ctrl; + } + else + { + if ( ctrl->IsKindOf(CLASSINFO(wxComboCtrl)) ) + { + cb = (wxComboCtrl*) ctrl; + tc = cb->GetTextCtrl(); + } + } + + if ( tc || cb ) + { + wxString tcText; + bool changeText = false; + + if ( cell.HasText() && !pg->IsEditorFocused() ) + { + tcText = cell.GetText(); + changeText = true; + } + else if ( oCell.HasText() ) + { + tcText = property->GetValueAsString( + property->HasFlag(wxPG_PROP_READONLY)?0:wxPG_EDITABLE_VALUE); + changeText = true; + } + + if ( changeText ) + { + // This prevents value from being modified + if ( tc ) + { + pg->SetupTextCtrlValue(tcText); + tc->SetValue(tcText); + } + else + { + cb->SetText(tcText); + } + } + } + + wxVisualAttributes vattrs = ctrl->GetDefaultAttributes(); + + // Foreground colour + const wxColour& fgCol = cell.GetFgCol(); + if ( fgCol.IsOk() ) + { + ctrl->SetForegroundColour(fgCol); + } + else if ( oCell.GetFgCol().IsOk() ) + { + ctrl->SetForegroundColour(vattrs.colFg); + } + + // Background colour + const wxColour& bgCol = cell.GetBgCol(); + if ( bgCol.IsOk() ) + { + ctrl->SetBackgroundColour(bgCol); + } + else if ( oCell.GetBgCol().IsOk() ) + { + ctrl->SetBackgroundColour(vattrs.colBg); + } + + // Font + const wxFont& font = cell.GetFont(); + if ( font.IsOk() ) + { + ctrl->SetFont(font); + } + else if ( oCell.GetFont().IsOk() ) + { + ctrl->SetFont(vattrs.font); + } + + // Also call the old SetValueToUnspecified() + SetValueToUnspecified(property, ctrl); +} + +void wxPGEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property), + wxWindow* WXUNUSED(ctrl) ) const +{ +} bool wxPGEditor::CanContainCustomImage() const { @@ -235,8 +331,10 @@ wxPGWindowList wxPGTextCtrlEditor::CreateControls( wxPropertyGrid* propGrid, property->GetChildCount() ) return NULL; - int argFlags = property->HasFlag(wxPG_PROP_READONLY) ? - 0 : wxPG_EDITABLE_VALUE; + int argFlags = 0; + if ( !property->HasFlag(wxPG_PROP_READONLY) && + !property->IsValueUnspecified() ) + argFlags |= wxPG_EDITABLE_VALUE; text = property->GetValueAsString(argFlags); int flags = 0; @@ -366,7 +464,7 @@ bool wxPGTextCtrlEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* } -void wxPGTextCtrlEditor::SetValueToUnspecified( wxPGProperty* property, wxWindow* ctrl ) const +void wxPGTextCtrlEditor::SetControlStringValue( wxPGProperty* property, wxWindow* ctrl, const wxString& txt ) const { wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl); @@ -374,35 +472,37 @@ void wxPGTextCtrlEditor::SetValueToUnspecified( wxPGProperty* property, wxWindow wxASSERT(pg); // Really, property grid should exist if editor does if ( pg ) { - wxString unspecValueText = pg->GetUnspecifiedValueText(); - pg->SetupTextCtrlValue(unspecValueText); - tc->SetValue(unspecValueText); + pg->SetupTextCtrlValue(txt); + tc->SetValue(txt); } } -void wxPGTextCtrlEditor::SetControlStringValue( wxPGProperty* property, wxWindow* ctrl, const wxString& txt ) const +void wxPGTextCtrlEditor_OnFocus( wxPGProperty* property, + wxTextCtrl* tc ) { - wxTextCtrl* tc = wxStaticCast(ctrl, wxTextCtrl); + // Make sure there is correct text (instead of unspecified value + // indicator or inline help) + int flags = property->HasFlag(wxPG_PROP_READONLY) ? + 0 : wxPG_EDITABLE_VALUE; + wxString correctText = property->GetValueAsString(flags); - wxPropertyGrid* pg = property->GetGrid(); - wxASSERT(pg); // Really, property grid should exist if editor does - if ( pg ) + if ( tc->GetValue() != correctText ) { - pg->SetupTextCtrlValue(txt); - tc->SetValue(txt); + property->GetGrid()->SetupTextCtrlValue(correctText); + tc->SetValue(correctText); } -} - -void wxPGTextCtrlEditor::OnFocus( wxPGProperty*, wxWindow* wnd ) const + tc->SetSelection(-1,-1); +} + +void wxPGTextCtrlEditor::OnFocus( wxPGProperty* property, + wxWindow* wnd ) const { wxTextCtrl* tc = wxStaticCast(wnd, wxTextCtrl); - - tc->SetSelection(-1,-1); + wxPGTextCtrlEditor_OnFocus(property, tc); } - wxPGTextCtrlEditor::~wxPGTextCtrlEditor() { } @@ -810,6 +910,13 @@ bool wxPGChoiceEditor_SetCustomPaintWidth( wxPropertyGrid* propGrid, wxPGComboBo wxSize imageSize; bool res; + // TODO: Do this always when cell has custom text. + if ( property->IsValueUnspecified() ) + { + cb->SetCustomPaintWidth( 0 ); + return true; + } + if ( cmnVal >= 0 ) { // Yes, a common value is being selected @@ -842,10 +949,11 @@ wxWindow* wxPGChoiceEditor::CreateControlsBase( wxPropertyGrid* propGrid, wxString defString; int index = property->GetChoiceSelection(); - bool isUnspecified = property->IsValueUnspecified(); - - if ( !isUnspecified ) - defString = property->GetDisplayedString(); + int argFlags = 0; + if ( !property->HasFlag(wxPG_PROP_READONLY) && + !property->IsValueUnspecified() ) + argFlags |= wxPG_EDITABLE_VALUE; + defString = property->GetValueAsString(argFlags); wxArrayString labels = choices.GetLabels(); @@ -871,7 +979,7 @@ wxWindow* wxPGChoiceEditor::CreateControlsBase( wxPropertyGrid* propGrid, unsigned int cmnVals = property->GetDisplayedCommonValueCount(); if ( cmnVals ) { - if ( !isUnspecified ) + if ( !property->IsValueUnspecified() ) { int cmnVal = property->GetCommonValue(); if ( cmnVal >= 0 ) @@ -1040,25 +1148,13 @@ void wxPGChoiceEditor::SetControlIntValue( wxPGProperty* WXUNUSED(property), wxW } -void wxPGChoiceEditor::SetValueToUnspecified( wxPGProperty* property, +void wxPGChoiceEditor::SetValueToUnspecified( wxPGProperty* WXUNUSED(property), wxWindow* ctrl ) const { wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl; - if ( !cb->HasFlag(wxCB_READONLY) ) - { - wxPropertyGrid* pg = property->GetGrid(); - if ( pg ) - { - wxString tcText = pg->GetUnspecifiedValueText(); - pg->SetupTextCtrlValue(tcText); - cb->SetValue(tcText); - } - } - else - { + if ( cb->HasFlag(wxCB_READONLY) ) cb->SetSelection(-1); - } } @@ -1144,10 +1240,11 @@ bool wxPGComboBoxEditor::GetValueFromControl( wxVariant& variant, wxPGProperty* } -void wxPGComboBoxEditor::OnFocus( wxPGProperty*, wxWindow* ctrl ) const +void wxPGComboBoxEditor::OnFocus( wxPGProperty* property, + wxWindow* ctrl ) const { wxOwnerDrawnComboBox* cb = (wxOwnerDrawnComboBox*)ctrl; - cb->GetTextCtrl()->SetSelection(-1,-1); + wxPGTextCtrlEditor_OnFocus(property, cb->GetTextCtrl()); } @@ -1871,6 +1968,28 @@ wxWindow* wxPropertyGrid::GenerateEditorTextCtrlAndButton( const wxPoint& pos, // ----------------------------------------------------------------------- +void wxPropertyGrid::SetEditorAppearance( const wxPGCell& cell, + bool unspecified ) +{ + wxPGProperty* property = GetSelection(); + if ( !property ) + return; + wxWindow* ctrl = GetEditorControl(); + if ( !ctrl ) + return; + + property->GetEditorClass()->SetControlAppearance( this, + property, + ctrl, + cell, + m_editorAppearance, + unspecified ); + + m_editorAppearance = cell; +} + +// ----------------------------------------------------------------------- + wxTextCtrl* wxPropertyGrid::GetEditorTextCtrl() const { wxWindow* wnd = GetEditorControl(); diff --git a/src/propgrid/property.cpp b/src/propgrid/property.cpp index 1e9f6100bd..ca3543a2ff 100644 --- a/src/propgrid/property.cpp +++ b/src/propgrid/property.cpp @@ -135,8 +135,9 @@ int wxPGCellRenderer::PreDrawCell( wxDC& dc, const wxRect& rect, const wxPGCell& // If possible, use cell colours if ( !(flags & DontUseCellBgCol) ) { - dc.SetPen(cell.GetBgCol()); - dc.SetBrush(cell.GetBgCol()); + const wxColour& bgCol = cell.GetBgCol(); + dc.SetPen(bgCol); + dc.SetBrush(bgCol); } if ( !(flags & DontUseCellFgCol) ) @@ -417,6 +418,12 @@ void wxPGCell::MergeFrom( const wxPGCell& srcCell ) data->SetBitmap(srcCell.GetBitmap()); } +void wxPGCell::SetEmptyData() +{ + AllocExclusive(); +} + + // ----------------------------------------------------------------------- // wxPGProperty // ----------------------------------------------------------------------- @@ -706,8 +713,17 @@ void wxPGProperty::GetDisplayInfo( unsigned int column, if ( !(flags & wxPGCellRenderer::ChoicePopup) ) { - // Not painting listi of choice popups, so get text from property - cell = &GetCell(column); + // Not painting list of choice popups, so get text from property + if ( column != 1 || !IsValueUnspecified() || IsCategory() ) + { + cell = &GetCell(column); + } + else + { + // Use special unspecified value cell + cell = &GetGrid()->GetUnspecifiedValueAppearance(); + } + if ( cell->HasText() ) { *pString = cell->GetText(); diff --git a/src/propgrid/propgrid.cpp b/src/propgrid/propgrid.cpp index b35676b458..96198a3af8 100644 --- a/src/propgrid/propgrid.cpp +++ b/src/propgrid/propgrid.cpp @@ -345,6 +345,9 @@ void wxPropertyGrid::Init1() m_mouseSide = 16; m_editorFocused = 0; + // Must set empty but valid data + m_unspecifiedAppearance.SetEmptyData(); + // Set default keys AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_RIGHT ); AddActionTrigger( wxPG_ACTION_NEXT_PROPERTY, WXK_DOWN ); @@ -441,9 +444,9 @@ void wxPropertyGrid::Init2() CalculateFontAndBitmapStuff( wxPG_DEFAULT_VSPACING ); - // Allocate cell datas indirectly by calling setter - m_propertyDefaultCell.SetBgCol(*wxBLACK); - m_categoryDefaultCell.SetBgCol(*wxBLACK); + // Allocate cell datas + m_propertyDefaultCell.SetEmptyData(); + m_categoryDefaultCell.SetEmptyData(); RegainColours(); @@ -1384,6 +1387,8 @@ void wxPropertyGrid::RegainColours() wxColour bgCol = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ); m_colPropBack = bgCol; m_propertyDefaultCell.GetData()->SetBgCol(bgCol); + if ( !m_unspecifiedAppearance.GetBgCol().IsOk() ) + m_unspecifiedAppearance.SetBgCol(bgCol); } if ( !(m_coloursCustomized & 0x0010) ) @@ -1391,6 +1396,8 @@ void wxPropertyGrid::RegainColours() wxColour fgCol = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ); m_colPropFore = fgCol; m_propertyDefaultCell.GetData()->SetFgCol(fgCol); + if ( !m_unspecifiedAppearance.GetFgCol().IsOk() ) + m_unspecifiedAppearance.SetFgCol(fgCol); } if ( !(m_coloursCustomized & 0x0020) ) @@ -1462,6 +1469,7 @@ void wxPropertyGrid::SetCellBackgroundColour( const wxColour& col ) m_coloursCustomized |= 0x08; m_propertyDefaultCell.GetData()->SetBgCol(col); + m_unspecifiedAppearance.SetBgCol(col); Refresh(); } @@ -1474,6 +1482,7 @@ void wxPropertyGrid::SetCellTextColour( const wxColour& col ) m_coloursCustomized |= 0x10; m_propertyDefaultCell.GetData()->SetFgCol(col); + m_unspecifiedAppearance.SetFgCol(col); Refresh(); } @@ -3629,9 +3638,18 @@ void wxPropertyGrid::CustomSetCursor( int type, bool override ) m_curcursor = type; } +// ----------------------------------------------------------------------- + wxString -wxPropertyGrid::GetUnspecifiedValueText( int WXUNUSED(argFlags) ) const +wxPropertyGrid::GetUnspecifiedValueText( int argFlags ) const { + const wxPGCell& ua = GetUnspecifiedValueAppearance(); + + if ( ua.HasText() && + !(argFlags & wxPG_FULL_VALUE) && + !(argFlags & wxPG_EDITABLE_VALUE) ) + return ua.GetText(); + return wxEmptyString; } @@ -3916,6 +3934,9 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags ) wxRect grect = GetEditorWidgetRect(p, m_selColumn); wxPoint goodPos = grect.GetPosition(); + // Editor appearance can now be considered clear + m_editorAppearance.SetEmptyData(); + const wxPGEditor* editor = p->GetEditorClass(); wxCHECK_MSG(editor, false, wxT("NULL editor class not allowed")); @@ -3985,6 +4006,12 @@ bool wxPropertyGrid::DoSelectProperty( wxPGProperty* p, unsigned int flags ) p->GetEditorClass()->OnFocus(p, primaryCtrl); } + else + { + if ( p->IsValueUnspecified() ) + SetEditorAppearance(m_unspecifiedAppearance, + true); + } } if ( m_wndEditor2 ) @@ -4151,7 +4178,7 @@ void wxPropertyGrid::RefreshEditor() editorClass->UpdateControl(p, wnd); if ( p->IsValueUnspecified() ) - editorClass ->SetValueToUnspecified(p, wnd); + SetEditorAppearance(m_unspecifiedAppearance, true); } // ----------------------------------------------------------------------- -- 2.45.2