X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b7bc9d806b57f20e1d3135025ba0e6f603e7450e..beb2638a997914bd12c55e81589adebd90af9ed2:/src/propgrid/property.cpp?ds=sidebyside diff --git a/src/propgrid/property.cpp b/src/propgrid/property.cpp index 10ba288e65..d670542dfa 100644 --- a/src/propgrid/property.cpp +++ b/src/propgrid/property.cpp @@ -94,8 +94,6 @@ wxSize wxPGCellRenderer::GetImageSize( const wxPGProperty* WXUNUSED(property), void wxPGCellRenderer::DrawText( wxDC& dc, const wxRect& rect, int xOffset, const wxString& text ) const { - if ( xOffset ) - xOffset += wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2; dc.DrawText( text, rect.x+xOffset+wxPG_XBEFORETEXT, rect.y+((rect.height-dc.GetCharHeight())/2) ); @@ -106,9 +104,6 @@ void wxPGCellRenderer::DrawEditorValue( wxDC& dc, const wxRect& rect, wxPGProperty* property, const wxPGEditor* editor ) const { - if ( xOffset ) - xOffset += wxCC_CUSTOM_IMAGE_MARGIN1 + wxCC_CUSTOM_IMAGE_MARGIN2; - int yOffset = ((rect.height-dc.GetCharHeight())/2); if ( editor ) @@ -135,7 +130,7 @@ void wxPGCellRenderer::DrawCaptionSelectionRect( wxDC& dc, int x, int y, int w, int wxPGCellRenderer::PreDrawCell( wxDC& dc, const wxRect& rect, const wxPGCell& cell, int flags ) const { - int imageOffset = 0; + int imageWidth = 0; // If possible, use cell colours if ( !(flags & DontUseCellBgCol) ) @@ -149,8 +144,10 @@ int wxPGCellRenderer::PreDrawCell( wxDC& dc, const wxRect& rect, const wxPGCell& dc.SetTextForeground(cell.GetFgCol()); } - // Draw Background - dc.DrawRectangle(rect); + // Draw Background, but only if not rendering in control + // (as control already has rendered correct background). + if ( !(flags & (Control|ChoicePopup)) ) + dc.DrawRectangle(rect); const wxBitmap& bmp = cell.GetBitmap(); if ( bmp.Ok() && @@ -162,10 +159,10 @@ int wxPGCellRenderer::PreDrawCell( wxDC& dc, const wxRect& rect, const wxPGCell& rect.x + wxPG_CONTROL_MARGIN + wxCC_CUSTOM_IMAGE_MARGIN1, rect.y + wxPG_CUSTOM_IMAGE_SPACINGY, true ); - imageOffset = bmp.GetWidth(); + imageWidth = bmp.GetWidth(); } - return imageOffset; + return imageWidth; } // ----------------------------------------------------------------------- @@ -194,12 +191,12 @@ void wxPGDefaultRenderer::Render( wxDC& dc, const wxRect& rect, const wxPGCell* cell = NULL; wxString text; - int imageOffset = 0; + int imageWidth = 0; int preDrawFlags = flags; property->GetDisplayInfo(column, item, flags, &text, &cell); - imageOffset = PreDrawCell( dc, rect, *cell, preDrawFlags ); + imageWidth = PreDrawCell( dc, rect, *cell, preDrawFlags ); if ( column == 1 ) { @@ -229,7 +226,7 @@ void wxPGDefaultRenderer::Render( wxDC& dc, const wxRect& rect, property->OnCustomPaint( dc, imageRect, paintdata ); - imageOffset = paintdata.m_drawnWidth; + imageWidth = paintdata.m_drawnWidth; } text = property->GetValueAsString(); @@ -255,6 +252,8 @@ void wxPGDefaultRenderer::Render( wxDC& dc, const wxRect& rect, } } + int imageOffset = property->GetImageOffset(imageWidth); + DrawEditorValue( dc, rect, imageOffset, text, property, editor ); // active caption gets nice dotted rectangle @@ -262,8 +261,11 @@ void wxPGDefaultRenderer::Render( wxDC& dc, const wxRect& rect, { if ( flags & Selected ) { - if ( imageOffset > 0 ) - imageOffset += wxCC_CUSTOM_IMAGE_MARGIN2 + 4; + if ( imageWidth > 0 ) + { + imageOffset -= DEFAULT_IMAGE_OFFSET_INCREMENT; + imageWidth += wxCC_CUSTOM_IMAGE_MARGIN2 + 4; + } DrawCaptionSelectionRect( dc, rect.x+wxPG_XBEFORETEXT-wxPG_CAPRECTXMARGIN+imageOffset, @@ -400,16 +402,16 @@ void wxPGProperty::Init() m_arrIndex = 0xFFFF; m_parent = NULL; - m_parentState = (wxPropertyGridPageState*) NULL; + m_parentState = NULL; m_clientData = NULL; m_clientObject = NULL; - m_customEditor = (wxPGEditor*) NULL; + m_customEditor = NULL; #if wxUSE_VALIDATORS - m_validator = (wxValidator*) NULL; + m_validator = NULL; #endif - m_valueBitmap = (wxBitmap*) NULL; + m_valueBitmap = NULL; m_maxLen = 0; // infinite maximum length @@ -537,10 +539,12 @@ void wxPGProperty::InitAfterAdded( wxPropertyGridPageState* pageState, if ( GetChildCount() ) { // Check parental flags - wxASSERT_MSG( (m_flags & wxPG_PROP_PARENTAL_FLAGS), - "Call SetFlag(wxPG_PROP_MISC_PARENT) or" - "SetFlag(wxPG_PROP_AGGREGATE) before calling" - "wxPGProperty::AddChild()." ); + wxASSERT_MSG( ((m_flags & wxPG_PROP_PARENTAL_FLAGS) == + wxPG_PROP_AGGREGATE) || + ((m_flags & wxPG_PROP_PARENTAL_FLAGS) == + wxPG_PROP_MISC_PARENT), + "wxPGProperty parental flags set incorrectly at " + "this time" ); if ( HasFlag(wxPG_PROP_AGGREGATE) ) { @@ -637,12 +641,6 @@ int wxPGProperty::Index( const wxPGProperty* p ) const return wxNOT_FOUND; } -void wxPGProperty::UpdateControl( wxWindow* primary ) -{ - if ( primary ) - GetEditorClass()->UpdateControl(this, primary); -} - bool wxPGProperty::ValidateValue( wxVariant& WXUNUSED(value), wxPGValidationInfo& WXUNUSED(validationInfo) ) const { return true; @@ -656,6 +654,10 @@ void wxPGProperty::RefreshChildren () { } +void wxPGProperty::OnValidationFailure( wxVariant& WXUNUSED(pendingValue) ) +{ +} + void wxPGProperty::GetDisplayInfo( unsigned int column, int choiceIndex, int flags, @@ -976,6 +978,11 @@ bool wxPGProperty::StringToValue( wxVariant& variant, const wxString& text, int for ( ;; ) { + // How many units we iterate string forward at the end of loop? + // We need to keep track of this or risk going to negative + // with it-- operation. + unsigned int strPosIncrement = 1; + if ( tokenStart != 0xFFFFFF ) { // Token is running @@ -989,11 +996,12 @@ bool wxPGProperty::StringToValue( wxVariant& variant, const wxString& text, int { const wxPGProperty* child = Item(curChild); wxVariant variant(child->GetValue()); - variant.SetName(child->GetBaseName()); + wxString childName = child->GetBaseName(); #ifdef __WXDEBUG__ if ( debug_print ) - wxLogDebug(wxT("token = '%s', child = %s"),token.c_str(),child->GetLabel().c_str()); + wxLogDebug(wxT("token = '%s', child = %s"), + token.c_str(), childName.c_str()); #endif // Add only if editable or setting programmatically @@ -1002,8 +1010,18 @@ bool wxPGProperty::StringToValue( wxVariant& variant, const wxString& text, int { if ( len > 0 ) { - if ( child->StringToValue(variant, token, propagatedFlags|wxPG_COMPOSITE_FRAGMENT) ) + if ( child->StringToValue(variant, token, + propagatedFlags|wxPG_COMPOSITE_FRAGMENT) ) { + // We really need to set the variant's name + // *after* child->StringToValue() has been + // called, since variant's value may be set by + // assigning another variant into it, which + // then usually causes name to be copied (ie. + // usually cleared) as well. wxBoolProperty + // being case in point with its use of + // wxPGVariant_Bool macro as an optimization. + variant.SetName(childName); list.Append(variant); changed = true; @@ -1013,6 +1031,7 @@ bool wxPGProperty::StringToValue( wxVariant& variant, const wxString& text, int { // Empty, becomes unspecified variant.MakeNull(); + variant.SetName(childName); list.Append(variant); changed = true; } @@ -1069,23 +1088,23 @@ bool wxPGProperty::StringToValue( wxVariant& variant, const wxString& text, int if ( (argFlags & wxPG_PROGRAMMATIC_VALUE) || !child->HasFlag(wxPG_PROP_DISABLED|wxPG_PROP_READONLY) ) { - bool stvRes = child->StringToValue( variant, token, propagatedFlags ); + wxString childName = child->GetBaseName(); + + bool stvRes = child->StringToValue( variant, token, + propagatedFlags ); if ( stvRes || (variant != oldChildValue) ) { - if ( stvRes ) - changed = true; + variant.SetName(childName); + list.Append(variant); + + changed = true; } else { - // Failed, becomes unspecified - variant.MakeNull(); - changed = true; + // No changes... } } - variant.SetName(child->GetBaseName()); - list.Append(variant); - curChild++; if ( curChild >= iMax ) break; @@ -1099,10 +1118,7 @@ bool wxPGProperty::StringToValue( wxVariant& variant, const wxString& text, int tokenStart = pos; if ( a == delimeter ) - { - pos--; - --it; - } + strPosIncrement -= 1; } } } @@ -1110,7 +1126,8 @@ bool wxPGProperty::StringToValue( wxVariant& variant, const wxString& text, int if ( a == 0 ) break; - ++it; + it += strPosIncrement; + if ( it != text.end() ) { a = *it; @@ -1119,7 +1136,8 @@ bool wxPGProperty::StringToValue( wxVariant& variant, const wxString& text, int { a = 0; } - pos++; + + pos += strPosIncrement; } if ( changed ) @@ -1154,6 +1172,22 @@ wxSize wxPGProperty::OnMeasureImage( int WXUNUSED(item) ) const return wxSize(0,0); } +int wxPGProperty::GetImageOffset( int imageWidth ) const +{ + int imageOffset = 0; + + if ( imageWidth ) + { + // Do not increment offset too much for wide images + if ( imageWidth <= (wxPG_CUSTOM_IMAGE_WIDTH+5) ) + imageOffset = imageWidth + DEFAULT_IMAGE_OFFSET_INCREMENT; + else + imageOffset = imageWidth + 1; + } + + return imageOffset; +} + wxPGCellRenderer* wxPGProperty::GetCellRenderer( int WXUNUSED(column) ) const { return wxPGGlobalVars->m_defaultRenderer; @@ -1273,9 +1307,6 @@ void wxPGProperty::SetValue( wxVariant value, wxVariant* pList, int flags ) { m_value = value; OnSetValue(); - - if ( !(flags & wxPG_SETVAL_FROM_PARENT) ) - UpdateParentValues(); } if ( flags & wxPG_SETVAL_BY_USER ) @@ -1305,13 +1336,21 @@ void wxPGProperty::SetValue( wxVariant value, wxVariant* pList, int flags ) } } + if ( !(flags & wxPG_SETVAL_FROM_PARENT) ) + UpdateParentValues(); + // // Update editor control // // We need to check for these, otherwise GetGrid() may fail. if ( flags & wxPG_SETVAL_REFRESH_EDITOR ) + { RefreshEditor(); + wxPropertyGrid* pg = GetGridIfDisplayed(); + if ( pg ) + pg->DrawItemAndValueRelated(this); + } } @@ -1334,18 +1373,13 @@ void wxPGProperty::SetFlagRecursively( FlagType flag, bool set ) void wxPGProperty::RefreshEditor() { - if ( m_parent && GetParentState() ) - { - wxPropertyGrid* pg = GetParentState()->GetGrid(); - if ( pg->GetSelectedProperty() == this ) - { - wxWindow* editor = pg->GetEditorControl(); - if ( editor ) - GetEditorClass()->UpdateControl( this, editor ); - } - } -} + if ( !m_parent ) + return; + wxPropertyGrid* pg = GetGrid(); + if ( pg && pg->GetSelectedProperty() == this ) + pg->RefreshEditor(); +} wxVariant wxPGProperty::GetDefaultValue() const { @@ -1704,7 +1738,7 @@ void wxPGProperty::SetFlagsFromString( const wxString& str ) wxValidator* wxPGProperty::DoGetValidator() const { - return (wxValidator*) NULL; + return NULL; } int wxPGProperty::InsertChoice( const wxString& label, int index, int value ) @@ -1887,7 +1921,7 @@ void wxPGProperty::SetValueImage( wxBitmap& bmp ) wxSize maxSz = GetGrid()->GetImageSize(); wxSize imSz(bmp.GetWidth(),bmp.GetHeight()); - if ( imSz.x != maxSz.x || imSz.y != maxSz.y ) + if ( imSz.y != maxSz.y ) { // Create a memory DC wxBitmap* bmpNew = new wxBitmap(maxSz.x,maxSz.y,bmp.GetDepth()); @@ -1897,12 +1931,11 @@ void wxPGProperty::SetValueImage( wxBitmap& bmp ) // Scale // FIXME: This is ugly - use image or wait for scaling patch. - double scaleX = (double)maxSz.x / (double)imSz.x; double scaleY = (double)maxSz.y / (double)imSz.y; - dc.SetUserScale(scaleX,scaleY); + dc.SetUserScale(scaleY, scaleY); - dc.DrawBitmap( bmp, 0, 0 ); + dc.DrawBitmap(bmp, 0, 0); m_valueBitmap = bmpNew; } @@ -1966,6 +1999,8 @@ bool wxPGProperty::IsVisible() const wxPropertyGrid* wxPGProperty::GetGridIfDisplayed() const { wxPropertyGridPageState* state = GetParentState(); + if ( !state ) + return NULL; wxPropertyGrid* propGrid = state->GetGrid(); if ( state == propGrid->GetState() ) return propGrid; @@ -2001,7 +2036,8 @@ int wxPGProperty::GetY() const } // This is used by Insert etc. -void wxPGProperty::AddChild2( wxPGProperty* prop, int index, bool correct_mode ) +void wxPGProperty::DoAddChild( wxPGProperty* prop, int index, + bool correct_mode ) { if ( index < 0 || (size_t)index >= m_children.size() ) { @@ -2017,14 +2053,15 @@ void wxPGProperty::AddChild2( wxPGProperty* prop, int index, bool correct_mode ) prop->m_parent = this; } -// This is used by properties that have fixed sub-properties -void wxPGProperty::AddChild( wxPGProperty* prop ) +void wxPGProperty::DoPreAddChild( int index, wxPGProperty* prop ) { wxASSERT_MSG( prop->GetBaseName().length(), - "Property's children must have unique, non-empty names within their scope" ); + "Property's children must have unique, non-empty " + "names within their scope" ); - prop->m_arrIndex = m_children.size(); - m_children.push_back( prop ); + prop->m_arrIndex = index; + m_children.insert( m_children.begin()+index, + prop ); int custImgHeight = prop->OnMeasureImage().y; if ( custImgHeight < 0 /*|| custImgHeight > 1*/ ) @@ -2033,6 +2070,52 @@ void wxPGProperty::AddChild( wxPGProperty* prop ) prop->m_parent = this; } +void wxPGProperty::AddPrivateChild( wxPGProperty* prop ) +{ + if ( !(m_flags & wxPG_PROP_PARENTAL_FLAGS) ) + SetParentalType(wxPG_PROP_AGGREGATE); + + wxASSERT_MSG( (m_flags & wxPG_PROP_PARENTAL_FLAGS) == + wxPG_PROP_AGGREGATE, + "Do not mix up AddPrivateChild() calls with other " + "property adders." ); + + DoPreAddChild( m_children.size(), prop ); +} + +#if wxPG_COMPATIBILITY_1_4 +void wxPGProperty::AddChild( wxPGProperty* prop ) +{ + AddPrivateChild(prop); +} +#endif + +wxPGProperty* wxPGProperty::InsertChild( int index, + wxPGProperty* childProperty ) +{ + if ( index < 0 ) + index = m_children.size(); + + if ( m_parentState ) + { + m_parentState->DoInsert(this, index, childProperty); + } + else + { + if ( !(m_flags & wxPG_PROP_PARENTAL_FLAGS) ) + SetParentalType(wxPG_PROP_MISC_PARENT); + + wxASSERT_MSG( (m_flags & wxPG_PROP_PARENTAL_FLAGS) == + wxPG_PROP_MISC_PARENT, + "Do not mix up AddPrivateChild() calls with other " + "property adders." ); + + DoPreAddChild( index, childProperty ); + } + + return childProperty; +} + void wxPGProperty::RemoveChild( wxPGProperty* p ) { wxArrayPGProperty::iterator it; @@ -2124,7 +2207,7 @@ wxPGProperty* wxPGProperty::GetPropertyByName( const wxString& name ) const // Does it have point, then? int pos = name.Find(wxS('.')); if ( pos <= 0 ) - return (wxPGProperty*) NULL; + return NULL; wxPGProperty* p = GetPropertyByName(name. substr(0,pos)); @@ -2274,6 +2357,17 @@ void wxPGProperty::Empty() m_children.clear(); } +void wxPGProperty::DeleteChildren() +{ + wxPropertyGridPageState* state = m_parentState; + + while ( GetChildCount() ) + { + wxPGProperty* child = Item(GetChildCount()-1); + state->DoDelete(child, true); + } +} + void wxPGProperty::ChildChanged( wxVariant& WXUNUSED(thisValue), int WXUNUSED(childIndex), wxVariant& WXUNUSED(childValue) ) const @@ -2382,7 +2476,7 @@ void wxPGProperty::SubPropsChanged( int oldSelInd ) child->InitAfterAdded(state, grid); } - wxPGProperty* sel = (wxPGProperty*) NULL; + wxPGProperty* sel = NULL; if ( oldSelInd >= (int)m_children.size() ) oldSelInd = (int)m_children.size() - 1; @@ -2408,11 +2502,14 @@ WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPGRootProperty,none,TextCtrl) IMPLEMENT_DYNAMIC_CLASS(wxPGRootProperty, wxPGProperty) -wxPGRootProperty::wxPGRootProperty() +wxPGRootProperty::wxPGRootProperty( const wxString& name ) : wxPGProperty() { #ifdef __WXDEBUG__ - m_name = wxS(""); + m_name = name; + m_label = m_name; +#else + wxUnusedVar(name); #endif SetParentalType(0); m_depth = 0; @@ -2480,6 +2577,270 @@ void wxPropertyCategory::CalculateTextExtent( wxWindow* wnd, const wxFont& font m_textExtent = x; } +// ----------------------------------------------------------------------- +// wxPGChoices +// ----------------------------------------------------------------------- + +wxPGChoiceEntry& wxPGChoices::Add( const wxString& label, int value ) +{ + AllocExclusive(); + + wxPGChoiceEntry entry(label, value); + return m_data->Insert( -1, entry ); +} + +// ----------------------------------------------------------------------- + +wxPGChoiceEntry& wxPGChoices::Add( const wxString& label, const wxBitmap& bitmap, int value ) +{ + AllocExclusive(); + + wxPGChoiceEntry entry(label, value); + entry.SetBitmap(bitmap); + return m_data->Insert( -1, entry ); +} + +// ----------------------------------------------------------------------- + +wxPGChoiceEntry& wxPGChoices::Insert( const wxPGChoiceEntry& entry, int index ) +{ + AllocExclusive(); + + return m_data->Insert( index, entry ); +} + +// ----------------------------------------------------------------------- + +wxPGChoiceEntry& wxPGChoices::Insert( const wxString& label, int index, int value ) +{ + AllocExclusive(); + + wxPGChoiceEntry entry(label, value); + return m_data->Insert( index, entry ); +} + +// ----------------------------------------------------------------------- + +wxPGChoiceEntry& wxPGChoices::AddAsSorted( const wxString& label, int value ) +{ + AllocExclusive(); + + size_t index = 0; + + while ( index < GetCount() ) + { + int cmpRes = GetLabel(index).Cmp(label); + if ( cmpRes > 0 ) + break; + index++; + } + + wxPGChoiceEntry entry(label, value); + return m_data->Insert( index, entry ); +} + +// ----------------------------------------------------------------------- + +void wxPGChoices::Add( const wxChar** labels, const ValArrItem* values ) +{ + AllocExclusive(); + + unsigned int itemcount = 0; + const wxChar** p = &labels[0]; + while ( *p ) { p++; itemcount++; } + + unsigned int i; + for ( i = 0; i < itemcount; i++ ) + { + int value = i; + if ( values ) + value = values[i]; + wxPGChoiceEntry entry(labels[i], value); + m_data->Insert( i, entry ); + } +} + +// ----------------------------------------------------------------------- + +void wxPGChoices::Add( const wxArrayString& arr, const wxArrayInt& arrint ) +{ + AllocExclusive(); + + unsigned int i; + unsigned int itemcount = arr.size(); + + for ( i = 0; i < itemcount; i++ ) + { + int value = i; + if ( &arrint && arrint.size() ) + value = arrint[i]; + wxPGChoiceEntry entry(arr[i], value); + m_data->Insert( i, entry ); + } +} + +// ----------------------------------------------------------------------- + +void wxPGChoices::RemoveAt(size_t nIndex, size_t count) +{ + AllocExclusive(); + + wxASSERT( m_data->m_refCount != 0xFFFFFFF ); + m_data->m_items.erase(m_data->m_items.begin()+nIndex, + m_data->m_items.begin()+nIndex+count); +} + +// ----------------------------------------------------------------------- + +void wxPGChoices::Clear() +{ + if ( m_data != wxPGChoicesEmptyData ) + { + AllocExclusive(); + m_data->Clear(); + } +} + +// ----------------------------------------------------------------------- + +int wxPGChoices::Index( const wxString& str ) const +{ + if ( IsOk() ) + { + unsigned int i; + for ( i=0; i< m_data->GetCount(); i++ ) + { + const wxPGChoiceEntry& entry = m_data->Item(i); + if ( entry.HasText() && entry.GetText() == str ) + return i; + } + } + return -1; +} + +// ----------------------------------------------------------------------- + +int wxPGChoices::Index( int val ) const +{ + if ( IsOk() ) + { + unsigned int i; + for ( i=0; i< m_data->GetCount(); i++ ) + { + const wxPGChoiceEntry& entry = m_data->Item(i); + if ( entry.GetValue() == val ) + return i; + } + } + return -1; +} + +// ----------------------------------------------------------------------- + +wxArrayString wxPGChoices::GetLabels() const +{ + wxArrayString arr; + unsigned int i; + + if ( this && IsOk() ) + for ( i=0; i= 0 ) + arr.Add(GetValue(index)); + else + arr.Add(wxPG_INVALID_VALUE); + } + } + + return arr; +} + +// ----------------------------------------------------------------------- + +wxArrayInt wxPGChoices::GetIndicesForStrings( const wxArrayString& strings, + wxArrayString* unmatched ) const +{ + wxArrayInt arr; + + if ( IsOk() ) + { + unsigned int i; + for ( i=0; i< strings.size(); i++ ) + { + const wxString& str = strings[i]; + int index = Index(str); + if ( index >= 0 ) + arr.Add(index); + else if ( unmatched ) + unmatched->Add(str); + } + } + + return arr; +} + +// ----------------------------------------------------------------------- + +void wxPGChoices::AllocExclusive() +{ + EnsureData(); + + if ( m_data->m_refCount != 1 ) + { + wxPGChoicesData* data = new wxPGChoicesData(); + data->CopyDataFrom(m_data); + Free(); + m_data = data; + } +} + +// ----------------------------------------------------------------------- + +void wxPGChoices::AssignData( wxPGChoicesData* data ) +{ + Free(); + + if ( data != wxPGChoicesEmptyData ) + { + m_data = data; + data->m_refCount++; + } +} + +// ----------------------------------------------------------------------- + +void wxPGChoices::Init() +{ + m_data = wxPGChoicesEmptyData; +} + +// ----------------------------------------------------------------------- + +void wxPGChoices::Free() +{ + if ( m_data != wxPGChoicesEmptyData ) + { + m_data->DecRef(); + m_data = wxPGChoicesEmptyData; + } +} + // ----------------------------------------------------------------------- // wxPGAttributeStorage // -----------------------------------------------------------------------