X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e4e55c061f2cf3261bdf7928a180f1d973725699..728799ae114463b67bccc753877af851ab1666fd:/src/propgrid/property.cpp diff --git a/src/propgrid/property.cpp b/src/propgrid/property.cpp index 893eb3f0a6..bafa791fc4 100644 --- a/src/propgrid/property.cpp +++ b/src/propgrid/property.cpp @@ -4,9 +4,8 @@ // Author: Jaakko Salli // Modified by: // Created: 2008-08-23 -// RCS-ID: $Id$ // Copyright: (c) Jaakko Salli -// Licence: wxWindows license +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx/wx.h". @@ -24,6 +23,7 @@ #include "wx/hash.h" #include "wx/string.h" #include "wx/log.h" + #include "wx/math.h" #include "wx/event.h" #include "wx/window.h" #include "wx/panel.h" @@ -35,6 +35,8 @@ #include "wx/intl.h" #endif +#include "wx/image.h" + #include "wx/propgrid/propgrid.h" @@ -45,7 +47,7 @@ #if wxPG_COMPATIBILITY_1_4 -// Used to establish backwards compatiblity +// Used to establish backwards compatibility const char* g_invalidStringContent = "@__TOTALLY_INVALID_STRING__@"; #endif @@ -156,7 +158,7 @@ int wxPGCellRenderer::PreDrawCell( wxDC& dc, const wxRect& rect, const wxPGCell& dc.SetFont(font); const wxBitmap& bmp = cell.GetBitmap(); - if ( bmp.Ok() && + if ( bmp.IsOk() && // Do not draw oversized bitmap outside choice popup ((flags & ChoicePopup) || bmp.GetHeight() < rect.height ) ) @@ -206,7 +208,7 @@ bool wxPGDefaultRenderer::Render( wxDC& dc, const wxRect& rect, { text = propertyGrid->GetCommonValueLabel(cmnVal); DrawText( dc, rect, 0, text ); - if ( text.length() ) + if ( !text.empty() ) return true; } return false; @@ -258,15 +260,15 @@ bool wxPGDefaultRenderer::Render( wxDC& dc, const wxRect& rect, if ( propertyGrid->GetColumnCount() <= 2 ) { wxString unitsString = property->GetAttribute(wxPGGlobalVars->m_strUnits, wxEmptyString); - if ( unitsString.length() ) + if ( !unitsString.empty() ) text = wxString::Format(wxS("%s %s"), text.c_str(), unitsString.c_str() ); } } - if ( text.length() == 0 ) + if ( text.empty() ) { text = property->GetHintText(); - if ( text.length() > 0 ) + if ( !text.empty() ) { res = true; @@ -274,7 +276,7 @@ bool wxPGDefaultRenderer::Render( wxDC& dc, const wxRect& rect, propertyGrid->GetCellDisabledTextColour(); dc.SetTextForeground(hCol); - // Must make the editor NULL to override it's own rendering + // Must make the editor NULL to override its own rendering // code. editor = NULL; } @@ -325,7 +327,7 @@ wxSize wxPGDefaultRenderer::GetImageSize( const wxPGProperty* property, { wxBitmap* bmp = property->GetValueImage(); - if ( bmp && bmp->Ok() ) + if ( bmp && bmp->IsOk() ) return wxSize(bmp->GetWidth(),bmp->GetHeight()); } } @@ -497,7 +499,24 @@ void wxPGProperty::InitAfterAdded( wxPropertyGridPageState* pageState, // (so propgrid can be NULL, too). wxPGProperty* parent = m_parent; - bool parentIsRoot = parent->IsKindOf(CLASSINFO(wxPGRootProperty)); + bool parentIsRoot = parent->IsKindOf(wxCLASSINFO(wxPGRootProperty)); + + // + // Convert invalid cells to default ones in this grid + for ( unsigned int i=0; iGetPropertyDefaultCell(); + const wxPGCell& catDefCell = propgrid->GetCategoryDefaultCell(); + + if ( !HasFlag(wxPG_PROP_CATEGORY) ) + cell = propDefCell; + else + cell = catDefCell; + } + } m_parentState = pageState; @@ -621,6 +640,27 @@ void wxPGProperty::InitAfterAdded( wxPropertyGridPageState* pageState, } } +void wxPGProperty::OnDetached(wxPropertyGridPageState* WXUNUSED(state), + wxPropertyGrid* propgrid) +{ + if ( propgrid ) + { + const wxPGCell& propDefCell = propgrid->GetPropertyDefaultCell(); + const wxPGCell& catDefCell = propgrid->GetCategoryDefaultCell(); + + // Make default cells invalid + for ( unsigned int i=0; iIsCategory() || parent->IsRoot() ) + if ( m_name.empty() || !parent || parent->IsCategory() || parent->IsRoot() ) return m_name; return m_parent->GetName() + wxS(".") + m_name; @@ -692,12 +732,7 @@ wxPropertyGrid* wxPGProperty::GetGrid() const int wxPGProperty::Index( const wxPGProperty* p ) const { - for ( unsigned int i = 0; iGetName()] = s; bool skip = false; - if ( (argFlags & wxPG_UNEDITABLE_COMPOSITE_FRAGMENT) && !s.length() ) + if ( (argFlags & wxPG_UNEDITABLE_COMPOSITE_FRAGMENT) && s.empty() ) skip = true; if ( !curChild->GetChildCount() || skip ) @@ -999,7 +1034,7 @@ bool wxPGProperty::IntToValue( wxVariant& variant, int number, int WXUNUSED(argF } // Convert semicolon delimited tokens into child values. -bool wxPGProperty::StringToValue( wxVariant& variant, const wxString& text, int argFlags ) const +bool wxPGProperty::StringToValue( wxVariant& v, const wxString& text, int argFlags ) const { if ( !GetChildCount() ) return false; @@ -1067,7 +1102,8 @@ bool wxPGProperty::StringToValue( wxVariant& variant, const wxString& text, int // Add only if editable or setting programmatically if ( (argFlags & wxPG_PROGRAMMATIC_VALUE) || - !child->HasFlag(wxPG_PROP_DISABLED|wxPG_PROP_READONLY) ) + (!child->HasFlag(wxPG_PROP_DISABLED) && + !child->HasFlag(wxPG_PROP_READONLY)) ) { if ( len > 0 ) { @@ -1138,7 +1174,7 @@ bool wxPGProperty::StringToValue( wxVariant& variant, const wxString& text, int token = text.substr(startPos,pos-startPos-1); - if ( !token.length() ) + if ( token.empty() ) break; const wxPGProperty* child = Item(curChild); @@ -1147,7 +1183,8 @@ bool wxPGProperty::StringToValue( wxVariant& variant, const wxString& text, int wxVariant variant(oldChildValue); if ( (argFlags & wxPG_PROGRAMMATIC_VALUE) || - !child->HasFlag(wxPG_PROP_DISABLED|wxPG_PROP_READONLY) ) + (!child->HasFlag(wxPG_PROP_DISABLED) && + !child->HasFlag(wxPG_PROP_READONLY)) ) { wxString childName = child->GetBaseName(); @@ -1202,7 +1239,7 @@ bool wxPGProperty::StringToValue( wxVariant& variant, const wxString& text, int } if ( changed ) - variant = list; + v = list; return changed; } @@ -1260,7 +1297,7 @@ void wxPGProperty::OnCustomPaint( wxDC& dc, { wxBitmap* bmp = m_valueBitmap; - wxCHECK_RET( bmp && bmp->Ok(), wxT("invalid bitmap") ); + wxCHECK_RET( bmp && bmp->IsOk(), wxT("invalid bitmap") ); wxCHECK_RET( rect.x >= 0, wxT("unexpected measure call") ); @@ -1362,6 +1399,12 @@ void wxPGProperty::SetValue( wxVariant value, wxVariant* pList, int flags ) } i++; } + + // Always call OnSetValue() for a parent property (do not call it + // here if the value is non-null because it will then be called + // below) + if ( value.IsNull() ) + OnSetValue(); } if ( !value.IsNull() ) @@ -1427,7 +1470,7 @@ void wxPGProperty::SetValueInEvent( wxVariant value ) const GetGrid()->ValueChangeInEvent(value); } -void wxPGProperty::SetFlagRecursively( FlagType flag, bool set ) +void wxPGProperty::SetFlagRecursively( wxPGPropertyFlags flag, bool set ) { ChangeFlag(flag, set); @@ -1489,6 +1532,31 @@ wxVariant wxPGProperty::GetDefaultValue() const return wxVariant(); } +void wxPGProperty::Enable( bool enable ) +{ + wxPropertyGrid* pg = GetGrid(); + + // Preferably call the version in the owning wxPropertyGrid, + // since it handles the editor de-activation. + if ( pg ) + pg->EnableProperty(this, enable); + else + DoEnable(enable); +} + +void wxPGProperty::DoEnable( bool enable ) +{ + if ( enable ) + ClearFlag(wxPG_PROP_DISABLED); + else + SetFlag(wxPG_PROP_DISABLED); + + // Apply same to sub-properties as well + unsigned int i; + for ( i = 0; i < GetChildCount(); i++ ) + Item(i)->DoEnable( enable ); +} + void wxPGProperty::EnsureCells( unsigned int column ) { if ( column >= m_cells.size() ) @@ -1497,14 +1565,17 @@ void wxPGProperty::EnsureCells( unsigned int column ) wxPropertyGrid* pg = GetGrid(); wxPGCell defaultCell; - // Work around possible VC6 bug by using intermediate variables - const wxPGCell& propDefCell = pg->GetPropertyDefaultCell(); - const wxPGCell& catDefCell = pg->GetCategoryDefaultCell(); + if ( pg ) + { + // Work around possible VC6 bug by using intermediate variables + const wxPGCell& propDefCell = pg->GetPropertyDefaultCell(); + const wxPGCell& catDefCell = pg->GetCategoryDefaultCell(); - if ( !HasFlag(wxPG_PROP_CATEGORY) ) - defaultCell = propDefCell; - else - defaultCell = catDefCell; + if ( !HasFlag(wxPG_PROP_CATEGORY) ) + defaultCell = propDefCell; + else + defaultCell = catDefCell; + } // TODO: Replace with resize() call unsigned int cellCountMax = column+1; @@ -1779,7 +1850,7 @@ wxString wxPGProperty::GetFlagsAsString( FlagType flagsMask ) const { const wxChar* fs = gs_propFlagToString[i]; wxASSERT(fs); - if ( s.length() ) + if ( !s.empty() ) s << wxS("|"); s << fs; } @@ -1909,7 +1980,7 @@ void wxPGProperty::SetChoiceSelection( int newValue ) } } -bool wxPGProperty::SetChoices( wxPGChoices& choices ) +bool wxPGProperty::SetChoices( const wxPGChoices& choices ) { // Property must be de-selected first (otherwise choices in // the control would be de-synced with true choices) @@ -1949,17 +2020,43 @@ const wxPGEditor* wxPGProperty::GetEditorClass() const if ( GetDisplayedCommonValueCount() ) { // TextCtrlAndButton -> ComboBoxAndButton - if ( editor->IsKindOf(CLASSINFO(wxPGTextCtrlAndButtonEditor)) ) + if ( wxDynamicCast(editor, wxPGTextCtrlAndButtonEditor) ) editor = wxPGEditor_ChoiceAndButton; // TextCtrl -> ComboBox - else if ( editor->IsKindOf(CLASSINFO(wxPGTextCtrlEditor)) ) + else if ( wxDynamicCast(editor, wxPGTextCtrlEditor) ) editor = wxPGEditor_ComboBox; } return editor; } +bool wxPGProperty::Hide( bool hide, int flags ) +{ + wxPropertyGrid* pg = GetGrid(); + if ( pg ) + return pg->HideProperty(this, hide, flags); + + return DoHide( hide, flags ); +} + +bool wxPGProperty::DoHide( bool hide, int flags ) +{ + if ( !hide ) + ClearFlag( wxPG_PROP_HIDDEN ); + else + SetFlag( wxPG_PROP_HIDDEN ); + + if ( flags & wxPG_RECURSE ) + { + unsigned int i; + for ( i = 0; i < GetChildCount(); i++ ) + Item(i)->DoHide(hide, flags | wxPG_RECURSE_STARTS); + } + + return true; +} + bool wxPGProperty::HasVisibleChildren() const { unsigned int i; @@ -1994,7 +2091,7 @@ void wxPGProperty::SetValueImage( wxBitmap& bmp ) { delete m_valueBitmap; - if ( &bmp && bmp.Ok() ) + if ( &bmp && bmp.IsOk() ) { // Resize the image wxSize maxSz = GetGrid()->GetImageSize(); @@ -2002,19 +2099,23 @@ void wxPGProperty::SetValueImage( wxBitmap& bmp ) if ( imSz.y != maxSz.y ) { - // Create a memory DC + #if wxUSE_IMAGE + // Here we use high-quality wxImage scaling functions available + wxImage img = bmp.ConvertToImage(); + double scaleY = (double)maxSz.y / (double)imSz.y; + img.Rescale(wxRound(bmp.GetWidth()*scaleY), + wxRound(bmp.GetHeight()*scaleY), + wxIMAGE_QUALITY_HIGH); + wxBitmap* bmpNew = new wxBitmap(img, 32); + #else + // This is the old, deprecated method of scaling the image wxBitmap* bmpNew = new wxBitmap(maxSz.x,maxSz.y,bmp.GetDepth()); - wxMemoryDC dc; dc.SelectObject(*bmpNew); - - // Scale - // FIXME: This is ugly - use image or wait for scaling patch. double scaleY = (double)maxSz.y / (double)imSz.y; - dc.SetUserScale(scaleY, scaleY); - dc.DrawBitmap(bmp, 0, 0); + #endif m_valueBitmap = bmpNew; } @@ -2097,7 +2198,7 @@ int wxPGProperty::GetY2( int lh ) const for ( parent = GetParent(); parent != NULL; parent = child->GetParent() ) { if ( !parent->IsExpanded() ) - return -1; + return parent->GetY2(lh); y += parent->GetChildrenHeight(lh, child->GetIndexInParent()); y += lh; child = parent; @@ -2231,9 +2332,9 @@ void wxPGProperty::AdaptListToValue( wxVariant& list, wxVariant* value ) const else allChildrenSpecified = true; - wxVariant childValue = list[0]; unsigned int i; unsigned int n = 0; + wxVariant childValue = list[n]; //wxLogDebug(wxT(">> %s.AdaptListToValue()"),GetBaseName().c_str()); @@ -2468,6 +2569,25 @@ void wxPGProperty::DeleteChildren() } } +bool wxPGProperty::IsChildSelected( bool recursive ) const +{ + size_t i; + for ( i = 0; i < GetChildCount(); i++ ) + { + wxPGProperty* child = Item(i); + + // Test child + if ( m_parentState->DoIsPropertySelected( child ) ) + return true; + + // Test sub-childs + if ( recursive && child->IsChildSelected( recursive ) ) + return true; + } + + return false; +} + wxVariant wxPGProperty::ChildChanged( wxVariant& WXUNUSED(thisValue), int WXUNUSED(childIndex), wxVariant& WXUNUSED(childValue) ) const