1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/propgrid/property.cpp
3 // Purpose: wxPGProperty and related support classes
4 // Author: Jaakko Salli
8 // Copyright: (c) Jaakko Salli
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
23 #include "wx/object.h"
25 #include "wx/string.h"
28 #include "wx/window.h"
31 #include "wx/dcmemory.h"
32 #include "wx/button.h"
35 #include "wx/cursor.h"
36 #include "wx/dialog.h"
37 #include "wx/settings.h"
38 #include "wx/msgdlg.h"
39 #include "wx/choice.h"
40 #include "wx/stattext.h"
41 #include "wx/scrolwin.h"
42 #include "wx/dirdlg.h"
43 #include "wx/layout.h"
45 #include "wx/textdlg.h"
46 #include "wx/filedlg.h"
47 #include "wx/statusbr.h"
52 #include <wx/propgrid/propgrid.h>
55 #define PWC_CHILD_SUMMARY_LIMIT 16 // Maximum number of children summarized in a parent property's
58 #define PWC_CHILD_SUMMARY_CHAR_LIMIT 64 // Character limit of summary field when not editing
61 // -----------------------------------------------------------------------
63 static void wxPGDrawFocusRect( wxDC
& dc
, const wxRect
& rect
)
65 #if defined(__WXMSW__) && !defined(__WXWINCE__)
66 // FIXME: Use DrawFocusRect code above (currently it draws solid line
67 // for caption focus but works ok for other stuff).
68 // Also, it seems that this code may not work in future wx versions.
69 dc
.SetLogicalFunction(wxINVERT
);
71 wxPen
pen(*wxBLACK
,1,wxDOT
);
72 pen
.SetCap(wxCAP_BUTT
);
74 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
76 dc
.DrawRectangle(rect
);
78 dc
.SetLogicalFunction(wxCOPY
);
80 dc
.SetLogicalFunction(wxINVERT
);
82 dc
.SetPen(wxPen(*wxBLACK
,1,wxDOT
));
83 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
85 dc
.DrawRectangle(rect
);
87 dc
.SetLogicalFunction(wxCOPY
);
91 // -----------------------------------------------------------------------
93 // -----------------------------------------------------------------------
95 wxSize wxPGCellRenderer
::GetImageSize( const wxPGProperty
* WXUNUSED(property
),
97 int WXUNUSED(item
) ) const
102 void wxPGCellRenderer
::DrawText( wxDC
& dc
, const wxRect
& rect
,
103 int xOffset
, const wxString
& text
) const
106 xOffset
+= wxCC_CUSTOM_IMAGE_MARGIN1
+ wxCC_CUSTOM_IMAGE_MARGIN2
;
108 rect
.x
+xOffset
+wxPG_XBEFORETEXT
,
109 rect
.y
+((rect
.height
-dc
.GetCharHeight())/2) );
112 void wxPGCellRenderer
::DrawEditorValue( wxDC
& dc
, const wxRect
& rect
,
113 int xOffset
, const wxString
& text
,
114 wxPGProperty
* property
,
115 const wxPGEditor
* editor
) const
118 xOffset
+= wxCC_CUSTOM_IMAGE_MARGIN1
+ wxCC_CUSTOM_IMAGE_MARGIN2
;
120 int yOffset
= ((rect
.height
-dc
.GetCharHeight())/2);
127 rect2
.height
-= yOffset
;
128 editor
->DrawValue( dc
, rect2
, property
, text
);
133 rect
.x
+xOffset
+wxPG_XBEFORETEXT
,
138 void wxPGCellRenderer
::DrawCaptionSelectionRect( wxDC
& dc
, int x
, int y
, int w
, int h
) const
140 wxRect
focusRect(x
,y
+((h
-dc
.GetCharHeight())/2),w
,h
);
141 wxPGDrawFocusRect(dc
,focusRect
);
144 int wxPGCellRenderer
::PreDrawCell( wxDC
& dc
, const wxRect
& rect
, const wxPGCell
& cell
, int flags
) const
148 if ( !(flags
& Selected
) )
150 // Draw using wxPGCell information, if available
151 wxColour fgCol
= cell
.GetFgCol();
153 dc
.SetTextForeground(fgCol
);
155 wxColour bgCol
= cell
.GetBgCol();
160 dc
.DrawRectangle(rect
);
164 const wxBitmap
& bmp
= cell
.GetBitmap();
166 // In control, do not draw oversized bitmap
167 (!(flags
& Control
) || bmp
.GetHeight() < rect
.height
)
171 rect
.x
+ wxPG_CONTROL_MARGIN
+ wxCC_CUSTOM_IMAGE_MARGIN1
,
172 rect
.y
+ wxPG_CUSTOM_IMAGE_SPACINGY
,
174 imageOffset
= bmp
.GetWidth();
180 // -----------------------------------------------------------------------
181 // wxPGDefaultRenderer
182 // -----------------------------------------------------------------------
184 void wxPGDefaultRenderer
::Render( wxDC
& dc
, const wxRect
& rect
,
185 const wxPropertyGrid
* propertyGrid
, wxPGProperty
* property
,
186 int column
, int item
, int flags
) const
188 bool isUnspecified
= property
->IsValueUnspecified();
190 if ( column
== 1 && item
== -1 )
192 int cmnVal
= property
->GetCommonValue();
196 if ( !isUnspecified
)
197 DrawText( dc
, rect
, 0, propertyGrid
->GetCommonValueLabel(cmnVal
) );
202 const wxPGEditor
* editor
= NULL
;
203 const wxPGCell
* cell
= property
->GetCell(column
);
209 if ( column
== 1 && (flags
& Control
) )
211 int selectedIndex
= property
->GetChoiceSelection();
212 if ( selectedIndex
!= wxNOT_FOUND
)
214 const wxPGChoices
& choices
= property
->GetChoices();
215 const wxPGCell
* ccell
= &choices
[selectedIndex
];
217 ( ccell
->GetBitmap().IsOk() || ccell
->GetFgCol().IsOk() || ccell
->GetBgCol().IsOk() )
225 int preDrawFlags
= flags
;
227 if ( propertyGrid
->GetInternalFlags() & wxPG_FL_CELL_OVERRIDES_SEL
)
228 preDrawFlags
= preDrawFlags
& ~(Selected
);
230 imageOffset
= PreDrawCell( dc
, rect
, *cell
, preDrawFlags
);
231 text
= cell
->GetText();
232 if ( text
== wxS("@!") )
235 text
= property
->GetLabel();
236 else if ( column
== 1 )
237 text
= property
->GetValueString();
239 text
= wxEmptyString
;
242 else if ( column
== 0 )
245 DrawText( dc
, rect
, 0, property
->GetLabel() );
247 else if ( column
== 1 )
249 if ( !isUnspecified
)
251 editor
= property
->GetColumnEditor(column
);
253 // Regular property value
255 wxSize imageSize
= propertyGrid
->GetImageSize(property
, item
);
257 wxPGPaintData paintdata
;
258 paintdata
.m_parent
= propertyGrid
;
259 paintdata
.m_choiceItem
= item
;
261 if ( imageSize
.x
> 0 )
263 wxRect
imageRect(rect
.x
+ wxPG_CONTROL_MARGIN
+ wxCC_CUSTOM_IMAGE_MARGIN1
,
264 rect
.y
+wxPG_CUSTOM_IMAGE_SPACINGY
,
265 wxPG_CUSTOM_IMAGE_WIDTH
,
266 rect
.height
-(wxPG_CUSTOM_IMAGE_SPACINGY
*2));
268 /*if ( imageSize.x == wxPG_FULL_CUSTOM_PAINT_WIDTH )
270 imageRect.width = m_width - imageRect.x;
273 dc
.SetPen( wxPen(propertyGrid
->GetCellTextColour(), 1, wxSOLID
) );
275 paintdata
.m_drawnWidth
= imageSize
.x
;
276 paintdata
.m_drawnHeight
= imageSize
.y
;
278 if ( !isUnspecified
)
280 property
->OnCustomPaint( dc
, imageRect
, paintdata
);
284 dc
.SetBrush(*wxWHITE_BRUSH
);
285 dc
.DrawRectangle(imageRect
);
288 imageOffset
= paintdata
.m_drawnWidth
;
291 text
= property
->GetValueString();
294 if ( propertyGrid
->GetColumnCount() <= 2 )
296 wxString unitsString
= property
->GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
297 if ( unitsString
.length() )
298 text
= wxString
::Format(wxS("%s %s"), text
.c_str(), unitsString
.c_str() );
302 if ( text
.length() == 0 )
304 // Try to show inline help if no text
305 wxVariant vInlineHelp
= property
->GetAttribute(wxPGGlobalVars
->m_strInlineHelp
);
306 if ( !vInlineHelp
.IsNull() )
308 text
= vInlineHelp
.GetString();
309 dc
.SetTextForeground(propertyGrid
->GetCellDisabledTextColour());
313 else if ( column
== 2 )
316 if ( !text
.length() )
317 text
= property
->GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
320 DrawEditorValue( dc
, rect
, imageOffset
, text
, property
, editor
);
322 // active caption gets nice dotted rectangle
323 if ( property
->IsCategory() /*&& column == 0*/ )
325 if ( flags
& Selected
)
327 if ( imageOffset
> 0 )
328 imageOffset
+= wxCC_CUSTOM_IMAGE_MARGIN2
+ 4;
330 DrawCaptionSelectionRect( dc
,
331 rect
.x
+wxPG_XBEFORETEXT
-wxPG_CAPRECTXMARGIN
+imageOffset
,
332 rect
.y
-wxPG_CAPRECTYMARGIN
+1,
333 ((wxPropertyCategory
*)property
)->GetTextExtent(propertyGrid
,
334 propertyGrid
->GetCaptionFont())
335 +(wxPG_CAPRECTXMARGIN
*2),
336 propertyGrid
->GetFontHeight()+(wxPG_CAPRECTYMARGIN
*2) );
341 wxSize wxPGDefaultRenderer
::GetImageSize( const wxPGProperty
* property
,
345 if ( property
&& column
== 1 )
349 wxBitmap
* bmp
= property
->GetValueImage();
351 if ( bmp
&& bmp
->Ok() )
352 return wxSize(bmp
->GetWidth(),bmp
->GetHeight());
358 // -----------------------------------------------------------------------
360 // -----------------------------------------------------------------------
366 wxPGCell
::wxPGCell( const wxString
& text
,
367 const wxBitmap
& bitmap
,
368 const wxColour
& fgCol
,
369 const wxColour
& bgCol
)
370 : m_bitmap(bitmap
), m_fgCol(fgCol
), m_bgCol(bgCol
)
375 // -----------------------------------------------------------------------
377 // -----------------------------------------------------------------------
379 IMPLEMENT_ABSTRACT_CLASS(wxPGProperty
, wxObject
)
381 wxString
* wxPGProperty
::sm_wxPG_LABEL
= NULL
;
383 void wxPGProperty
::Init()
389 m_parentState
= (wxPropertyGridPageState
*) NULL
;
392 m_clientObject
= NULL
;
394 m_customEditor
= (wxPGEditor
*) NULL
;
396 m_validator
= (wxValidator
*) NULL
;
398 m_valueBitmap
= (wxBitmap
*) NULL
;
400 m_maxLen
= 0; // infinite maximum length
402 m_flags
= wxPG_PROP_PROPERTY
;
412 void wxPGProperty
::Init( const wxString
& label
, const wxString
& name
)
414 // We really need to check if &label and &name are NULL pointers
415 // (this can if we are called before property grid has been initalized)
417 if ( (&label
) != NULL
&& label
!= wxPG_LABEL
)
420 if ( (&name
) != NULL
&& name
!= wxPG_LABEL
)
423 DoSetName( m_label
);
428 wxPGProperty
::wxPGProperty()
435 wxPGProperty
::wxPGProperty( const wxString
& label
, const wxString
& name
)
442 wxPGProperty
::~wxPGProperty()
444 delete m_clientObject
;
446 Empty(); // this deletes items
448 delete m_valueBitmap
;
455 for ( i
=0; i
<m_cells
.size(); i
++ )
456 delete (wxPGCell
*) m_cells
[i
];
458 // This makes it easier for us to detect dangling pointers
463 bool wxPGProperty
::IsSomeParent( wxPGProperty
* candidate
) const
465 wxPGProperty
* parent
= m_parent
;
468 if ( parent
== candidate
)
470 parent
= parent
->m_parent
;
476 wxString wxPGProperty
::GetName() const
478 wxPGProperty
* parent
= GetParent();
480 if ( !m_name
.length() || !parent
|| parent
->IsCategory() || parent
->IsRoot() )
483 return m_parent
->GetName() + wxS(".") + m_name
;
486 wxPropertyGrid
* wxPGProperty
::GetGrid() const
488 if ( !m_parentState
)
490 return m_parentState
->GetGrid();
494 void wxPGProperty
::UpdateControl( wxWindow
* primary
)
497 GetEditorClass()->UpdateControl(this, primary
);
500 bool wxPGProperty
::ValidateValue( wxVariant
& WXUNUSED(value
), wxPGValidationInfo
& WXUNUSED(validationInfo
) ) const
505 void wxPGProperty
::OnSetValue()
509 void wxPGProperty
::RefreshChildren ()
513 wxString wxPGProperty
::GetColumnText( unsigned int col
) const
515 wxPGCell
* cell
= GetCell(col
);
518 return cell
->GetText();
525 return GetDisplayedString();
527 return GetAttribute(wxPGGlobalVars
->m_strUnits
, wxEmptyString
);
530 return wxEmptyString
;
533 void wxPGProperty
::GenerateComposedValue( wxString
& text
, int argFlags
) const
536 int iMax
= m_children
.GetCount();
542 if ( iMax
> PWC_CHILD_SUMMARY_LIMIT
&&
543 !(argFlags
& wxPG_FULL_VALUE
) )
544 iMax
= PWC_CHILD_SUMMARY_LIMIT
;
546 int iMaxMinusOne
= iMax
-1;
548 if ( !IsTextEditable() )
549 argFlags
|= wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
;
551 wxPGProperty
* curChild
= (wxPGProperty
*) m_children
.Item(0);
553 for ( i
= 0; i
< iMax
; i
++ )
556 if ( !curChild
->IsValueUnspecified() )
557 s
= curChild
->GetValueString(argFlags
|wxPG_COMPOSITE_FRAGMENT
);
560 if ( (argFlags
& wxPG_UNEDITABLE_COMPOSITE_FRAGMENT
) && !s
.length() )
563 if ( !curChild
->GetChildCount() || skip
)
566 text
+= wxS("[") + s
+ wxS("]");
568 if ( i
< iMaxMinusOne
)
570 if ( text
.length() > PWC_CHILD_SUMMARY_CHAR_LIMIT
&&
571 !(argFlags
& wxPG_EDITABLE_VALUE
) &&
572 !(argFlags
& wxPG_FULL_VALUE
) )
577 if ( !curChild
->GetChildCount() )
583 curChild
= (wxPGProperty
*) m_children
.Item(i
+1);
587 // Remove superfluous semicolon and space
589 if ( text
.EndsWith(wxS("; "), &rest
) )
592 if ( (unsigned int)i
< m_children
.GetCount() )
593 text
+= wxS("; ...");
596 wxString wxPGProperty
::GetValueAsString( int argFlags
) const
598 wxCHECK_MSG( GetChildCount() > 0,
600 wxT("If user property does not have any children, it must override GetValueAsString") );
603 GenerateComposedValue(text
, argFlags
);
607 wxString wxPGProperty
::GetValueString( int argFlags
) const
609 if ( IsValueUnspecified() )
610 return wxEmptyString
;
612 if ( m_commonValue
== -1 )
613 return GetValueAsString(argFlags
);
616 // Return common value's string representation
617 wxPropertyGrid
* pg
= GetGrid();
618 const wxPGCommonValue
* cv
= pg
->GetCommonValue(m_commonValue
);
620 if ( argFlags
& wxPG_FULL_VALUE
)
622 return cv
->GetLabel();
624 else if ( argFlags
& wxPG_EDITABLE_VALUE
)
626 return cv
->GetEditableText();
630 return cv
->GetLabel();
634 bool wxPGProperty
::IntToValue( wxVariant
& variant
, int number
, int WXUNUSED(argFlags
) ) const
636 variant
= (long)number
;
640 // Convert semicolon delimited tokens into child values.
641 bool wxPGProperty
::StringToValue( wxVariant
& variant
, const wxString
& text
, int argFlags
) const
643 if ( !GetChildCount() )
646 unsigned int curChild
= 0;
648 unsigned int iMax
= m_children
.GetCount();
650 if ( iMax
> PWC_CHILD_SUMMARY_LIMIT
&&
651 !(argFlags
& wxPG_FULL_VALUE
) )
652 iMax
= PWC_CHILD_SUMMARY_LIMIT
;
654 bool changed
= false;
659 // Its best only to add non-empty group items
660 bool addOnlyIfNotEmpty
= false;
661 const wxChar delimeter
= wxS(';');
663 size_t tokenStart
= 0xFFFFFF;
665 wxVariantList temp_list
;
666 wxVariant
list(temp_list
);
668 int propagatedFlags
= argFlags
& wxPG_REPORT_ERROR
;
671 bool debug_print
= false;
676 wxLogDebug(wxT(">> %s.StringToValue('%s')"),GetLabel().c_str(),text
.c_str());
679 wxString
::const_iterator it
= text
.begin();
682 if ( it
!= text
.end() )
689 if ( tokenStart
!= 0xFFFFFF )
692 if ( a
== delimeter
|| a
== 0 )
694 token
= text
.substr(tokenStart
,pos
-tokenStart
);
696 size_t len
= token
.length();
698 if ( !addOnlyIfNotEmpty
|| len
> 0 )
700 const wxPGProperty
* child
= Item(curChild
);
703 wxLogDebug(wxT("token = '%s', child = %s"),token
.c_str(),child
->GetLabel().c_str());
708 bool wasUnspecified
= child
->IsValueUnspecified();
710 wxVariant
variant(child
->GetValueRef());
711 if ( child
->StringToValue(variant
, token
, propagatedFlags
|wxPG_COMPOSITE_FRAGMENT
) )
713 variant
.SetName(child
->GetBaseName());
715 // Clear unspecified flag only if OnSetValue() didn't
717 if ( child
->IsValueUnspecified() &&
718 (wasUnspecified
|| !UsesAutoUnspecified()) )
720 variant
= child
->GetDefaultValue();
723 list
.Append(variant
);
730 // Empty, becomes unspecified
732 variant2
.SetName(child
->GetBaseName());
733 list
.Append(variant2
);
738 if ( curChild
>= iMax
)
742 tokenStart
= 0xFFFFFF;
747 // Token is not running
751 addOnlyIfNotEmpty
= false;
753 // Is this a group of tokens?
758 if ( it
!= text
.end() ) it
++;
760 size_t startPos
= pos
;
762 // Group item - find end
763 while ( it
!= text
.end() && depth
> 0 )
771 else if ( a
== wxS('[') )
775 token
= text
.substr(startPos
,pos
-startPos
-1);
777 if ( !token
.length() )
780 const wxPGProperty
* child
= Item(curChild
);
782 wxVariant oldChildValue
= child
->GetValue();
783 wxVariant
variant(oldChildValue
);
784 bool stvRes
= child
->StringToValue( variant
, token
, propagatedFlags
);
785 if ( stvRes
|| (variant
!= oldChildValue
) )
792 // Failed, becomes unspecified
797 variant
.SetName(child
->GetBaseName());
798 list
.Append(variant
);
801 if ( curChild
>= iMax
)
804 addOnlyIfNotEmpty
= true;
806 tokenStart
= 0xFFFFFF;
812 if ( a
== delimeter
)
825 if ( it
!= text
.end() )
842 bool wxPGProperty
::SetValueFromString( const wxString
& text
, int argFlags
)
844 wxVariant
variant(m_value
);
845 bool res
= StringToValue(variant
, text
, argFlags
);
851 bool wxPGProperty
::SetValueFromInt( long number
, int argFlags
)
853 wxVariant
variant(m_value
);
854 bool res
= IntToValue(variant
, number
, argFlags
);
860 wxSize wxPGProperty
::OnMeasureImage( int WXUNUSED(item
) ) const
863 return wxSize(m_valueBitmap
->GetWidth(),-1);
868 wxPGCellRenderer
* wxPGProperty
::GetCellRenderer( int WXUNUSED(column
) ) const
870 return wxPGGlobalVars
->m_defaultRenderer
;
873 void wxPGProperty
::OnCustomPaint( wxDC
& dc
,
877 wxBitmap
* bmp
= m_valueBitmap
;
879 wxCHECK_RET( bmp
&& bmp
->Ok(), wxT("invalid bitmap") );
881 wxCHECK_RET( rect
.x
>= 0, wxT("unexpected measure call") );
883 dc
.DrawBitmap(*bmp
,rect
.x
,rect
.y
);
886 const wxPGEditor
* wxPGProperty
::DoGetEditorClass() const
888 return wxPG_EDITOR(TextCtrl
);
891 // Default extra property event handling - that is, none at all.
892 bool wxPGProperty
::OnEvent( wxPropertyGrid
*, wxWindow
*, wxEvent
& )
898 void wxPGProperty
::SetValue( wxVariant value
, wxVariant
* pList
, int flags
)
900 if ( !value
.IsNull() )
902 wxVariant tempListVariant
;
905 // List variants are reserved a special purpose
906 // as intermediate containers for child values
907 // of properties with children.
908 if ( value
.GetType() == wxPG_VARIANT_TYPE_LIST
)
911 // However, situation is different for composed string properties
912 if ( HasFlag(wxPG_PROP_COMPOSED_VALUE
) )
914 tempListVariant
= value
;
915 pList
= &tempListVariant
;
919 AdaptListToValue(value
, &newValue
);
921 //wxLogDebug(wxT(">> %s.SetValue() adapted list value to type '%s'"),GetName().c_str(),value.GetType().c_str());
924 if ( HasFlag( wxPG_PROP_AGGREGATE
) )
925 flags
|= wxPG_SETVAL_AGGREGATED
;
927 if ( pList
&& !pList
->IsNull() )
929 wxASSERT( pList
->GetType() == wxPG_VARIANT_TYPE_LIST
);
930 wxASSERT( GetChildCount() );
931 wxASSERT( !IsCategory() );
933 wxVariantList
& list
= pList
->GetList();
934 wxVariantList
::iterator node
;
937 //wxLogDebug(wxT(">> %s.SetValue() pList parsing"),GetName().c_str());
939 // Children in list can be in any order, but we will give hint to
940 // GetPropertyByNameWH(). This optimizes for full list parsing.
941 for ( node
= list
.begin(); node
!= list
.end(); node
++ )
943 wxVariant
& childValue
= *((wxVariant
*)*node
);
944 wxPGProperty
* child
= GetPropertyByNameWH(childValue
.GetName(), i
);
947 //wxLogDebug(wxT("%i: child = %s, childValue.GetType()=%s"),i,child->GetBaseName().c_str(),childValue.GetType().c_str());
948 if ( childValue
.GetType() == wxPG_VARIANT_TYPE_LIST
)
950 if ( child
->HasFlag(wxPG_PROP_AGGREGATE
) && !(flags
& wxPG_SETVAL_AGGREGATED
) )
952 wxVariant listRefCopy
= childValue
;
953 child
->SetValue(childValue
, &listRefCopy
, flags
|wxPG_SETVAL_FROM_PARENT
);
957 wxVariant oldVal
= child
->GetValue();
958 child
->SetValue(oldVal
, &childValue
, flags
|wxPG_SETVAL_FROM_PARENT
);
961 else if ( child
->GetValue() != childValue
)
963 // For aggregate properties, we will trust RefreshChildren()
964 // to update child values.
965 if ( !HasFlag(wxPG_PROP_AGGREGATE
) )
966 child
->SetValue(childValue
, NULL
, flags
|wxPG_SETVAL_FROM_PARENT
);
967 if ( flags
& wxPG_SETVAL_BY_USER
)
968 child
->SetFlag(wxPG_PROP_MODIFIED
);
975 if ( !value
.IsNull() )
980 if ( !(flags
& wxPG_SETVAL_FROM_PARENT
) )
981 UpdateParentValues();
984 if ( flags
& wxPG_SETVAL_BY_USER
)
985 SetFlag(wxPG_PROP_MODIFIED
);
987 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
992 if ( m_commonValue
!= -1 )
994 wxPropertyGrid
* pg
= GetGrid();
995 if ( !pg
|| m_commonValue
!= pg
->GetUnspecifiedCommonValue() )
1001 // Set children to unspecified, but only if aggregate or
1002 // value is <composed>
1003 if ( AreChildrenComponents() )
1006 for ( i
=0; i
<GetChildCount(); i
++ )
1007 Item(i
)->SetValue(value
, NULL
, flags
|wxPG_SETVAL_FROM_PARENT
);
1012 // Update editor control
1015 // We need to check for these, otherwise GetGrid() may fail.
1016 if ( flags
& wxPG_SETVAL_REFRESH_EDITOR
)
1021 void wxPGProperty
::SetValueInEvent( wxVariant value
) const
1023 GetGrid()->ValueChangeInEvent(value
);
1026 void wxPGProperty
::SetFlagRecursively( FlagType flag
, bool set
)
1034 for ( i
= 0; i
< GetChildCount(); i
++ )
1035 Item(i
)->SetFlagRecursively(flag
, set
);
1038 void wxPGProperty
::RefreshEditor()
1040 if ( m_parent
&& GetParentState() )
1042 wxPropertyGrid
* pg
= GetParentState()->GetGrid();
1043 if ( pg
->GetSelectedProperty() == this )
1045 wxWindow
* editor
= pg
->GetEditorControl();
1047 GetEditorClass()->UpdateControl( this, editor
);
1053 wxVariant wxPGProperty
::GetDefaultValue() const
1055 wxVariant defVal
= GetAttribute(wxS("DefaultValue"));
1056 if ( !defVal
.IsNull() )
1059 wxVariant value
= GetValue();
1061 if ( !value
.IsNull() )
1063 wxString
valueType(value
.GetType());
1065 if ( valueType
== wxPG_VARIANT_TYPE_LONG
)
1066 return wxPGVariant_Zero
;
1067 if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1068 return wxPGVariant_EmptyString
;
1069 if ( valueType
== wxPG_VARIANT_TYPE_BOOL
)
1070 return wxPGVariant_False
;
1071 if ( valueType
== wxPG_VARIANT_TYPE_DOUBLE
)
1072 return wxVariant(0.0);
1073 if ( valueType
== wxPG_VARIANT_TYPE_ARRSTRING
)
1074 return wxVariant(wxArrayString());
1075 if ( valueType
== wxS("wxLongLong") )
1076 return WXVARIANT(wxLongLong(0));
1077 if ( valueType
== wxS("wxULongLong") )
1078 return WXVARIANT(wxULongLong(0));
1079 if ( valueType
== wxS("wxColour") )
1080 return WXVARIANT(*wxBLACK
);
1082 if ( valueType
== wxPG_VARIANT_TYPE_DATETIME
)
1083 return wxVariant(wxDateTime
::Now());
1085 if ( valueType
== wxS("wxFont") )
1086 return WXVARIANT(*wxNORMAL_FONT
);
1087 if ( valueType
== wxS("wxPoint") )
1088 return WXVARIANT(wxPoint(0, 0));
1089 if ( valueType
== wxS("wxSize") )
1090 return WXVARIANT(wxSize(0, 0));
1096 void wxPGProperty
::SetCell( int column
, wxPGCell
* cellObj
)
1098 if ( column
>= (int)m_cells
.size() )
1099 m_cells
.SetCount(column
+1, NULL
);
1101 delete (wxPGCell
*) m_cells
[column
];
1102 m_cells
[column
] = cellObj
;
1105 wxPGEditorDialogAdapter
* wxPGProperty
::GetEditorDialog() const
1110 bool wxPGProperty
::DoSetAttribute( const wxString
& WXUNUSED(name
), wxVariant
& WXUNUSED(value
) )
1115 void wxPGProperty
::SetAttribute( const wxString
& name
, wxVariant value
)
1117 if ( DoSetAttribute( name
, value
) )
1119 // Support working without grid, when possible
1120 if ( wxPGGlobalVars
->HasExtraStyle( wxPG_EX_WRITEONLY_BUILTIN_ATTRIBUTES
) )
1124 m_attributes
.Set( name
, value
);
1127 void wxPGProperty
::SetAttributes( const wxPGAttributeStorage
& attributes
)
1129 wxPGAttributeStorage
::const_iterator it
= attributes
.StartIteration();
1132 while ( attributes
.GetNext(it
, variant
) )
1133 SetAttribute( variant
.GetName(), variant
);
1136 wxVariant wxPGProperty
::DoGetAttribute( const wxString
& WXUNUSED(name
) ) const
1142 wxVariant wxPGProperty
::GetAttribute( const wxString
& name
) const
1144 return m_attributes
.FindValue(name
);
1147 wxString wxPGProperty
::GetAttribute( const wxString
& name
, const wxString
& defVal
) const
1149 wxVariant variant
= m_attributes
.FindValue(name
);
1151 if ( !variant
.IsNull() )
1152 return variant
.GetString();
1157 long wxPGProperty
::GetAttributeAsLong( const wxString
& name
, long defVal
) const
1159 wxVariant variant
= m_attributes
.FindValue(name
);
1161 return wxPGVariantToInt(variant
, defVal
);
1164 double wxPGProperty
::GetAttributeAsDouble( const wxString
& name
, double defVal
) const
1167 wxVariant variant
= m_attributes
.FindValue(name
);
1169 if ( wxPGVariantToDouble(variant
, &retVal
) )
1175 wxVariant wxPGProperty
::GetAttributesAsList() const
1177 wxVariantList tempList
;
1178 wxVariant
v( tempList
, wxString
::Format(wxS("@%s@attr"),m_name
.c_str()) );
1180 wxPGAttributeStorage
::const_iterator it
= m_attributes
.StartIteration();
1183 while ( m_attributes
.GetNext(it
, variant
) )
1189 // Slots of utility flags are NULL
1190 const unsigned int gs_propFlagToStringSize
= 14;
1192 static const wxChar
* gs_propFlagToString
[gs_propFlagToStringSize
] = {
1209 wxString wxPGProperty
::GetFlagsAsString( FlagType flagsMask
) const
1212 int relevantFlags
= m_flags
& flagsMask
& wxPG_STRING_STORED_FLAGS
;
1216 for ( i
=0; i
<gs_propFlagToStringSize
; i
++ )
1218 if ( relevantFlags
& a
)
1220 const wxChar
* fs
= gs_propFlagToString
[i
];
1232 void wxPGProperty
::SetFlagsFromString( const wxString
& str
)
1236 WX_PG_TOKENIZER1_BEGIN(str
, wxS('|'))
1238 for ( i
=0; i
<gs_propFlagToStringSize
; i
++ )
1240 const wxChar
* fs
= gs_propFlagToString
[i
];
1241 if ( fs
&& str
== fs
)
1247 WX_PG_TOKENIZER1_END()
1249 m_flags
= (m_flags
& ~wxPG_STRING_STORED_FLAGS
) | flags
;
1252 wxValidator
* wxPGProperty
::DoGetValidator() const
1254 return (wxValidator
*) NULL
;
1257 int wxPGProperty
::InsertChoice( const wxString
& label
, int index
, int value
)
1259 wxPropertyGrid
* pg
= GetGrid();
1260 int sel
= GetChoiceSelection();
1264 if ( index
== wxNOT_FOUND
)
1265 index
= m_choices
.GetCount();
1270 m_choices
.Insert(label
, index
, value
);
1272 if ( sel
!= newSel
)
1273 SetChoiceSelection(newSel
);
1275 if ( this == pg
->GetSelection() )
1276 GetEditorClass()->InsertItem(pg
->GetEditorControl(),label
,index
);
1282 void wxPGProperty
::DeleteChoice( int index
)
1284 wxPropertyGrid
* pg
= GetGrid();
1286 int sel
= GetChoiceSelection();
1289 // Adjust current value
1292 SetValueToUnspecified();
1295 else if ( index
< sel
)
1300 m_choices
.RemoveAt(index
);
1302 if ( sel
!= newSel
)
1303 SetChoiceSelection(newSel
);
1305 if ( this == pg
->GetSelection() )
1306 GetEditorClass()->DeleteItem(pg
->GetEditorControl(), index
);
1309 int wxPGProperty
::GetChoiceSelection() const
1311 wxVariant value
= GetValue();
1312 wxString valueType
= value
.GetType();
1313 int index
= wxNOT_FOUND
;
1315 if ( IsValueUnspecified() || !m_choices
.GetCount() )
1318 if ( valueType
== wxPG_VARIANT_TYPE_LONG
)
1320 index
= value
.GetLong();
1322 else if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1324 index
= m_choices
.Index(value
.GetString());
1326 else if ( valueType
== wxPG_VARIANT_TYPE_BOOL
)
1328 index
= value
.GetBool()?
1 : 0;
1334 void wxPGProperty
::SetChoiceSelection( int newValue
)
1336 // Changes value of a property with choices, but only
1337 // works if the value type is long or string.
1338 wxString valueType
= GetValue().GetType();
1340 wxCHECK_RET( m_choices
.IsOk(), wxT("invalid choiceinfo") );
1342 if ( valueType
== wxPG_VARIANT_TYPE_STRING
)
1344 SetValue( m_choices
.GetLabel(newValue
) );
1346 else // if ( valueType == wxPG_VARIANT_TYPE_LONG )
1348 SetValue( (long) newValue
);
1352 bool wxPGProperty
::SetChoices( wxPGChoices
& choices
)
1354 m_choices
.Assign(choices
);
1357 // This may be needed to trigger some initialization
1358 // (but don't do it if property is somewhat uninitialized)
1359 wxVariant defVal
= GetDefaultValue();
1360 if ( defVal
.IsNull() )
1370 const wxPGEditor
* wxPGProperty
::GetEditorClass() const
1372 const wxPGEditor
* editor
;
1374 if ( !m_customEditor
)
1376 editor
= DoGetEditorClass();
1379 editor
= m_customEditor
;
1382 // Maybe override editor if common value specified
1383 if ( GetDisplayedCommonValueCount() )
1385 // TextCtrlAndButton -> ComboBoxAndButton
1386 if ( editor
->IsKindOf(CLASSINFO(wxPGTextCtrlAndButtonEditor
)) )
1387 editor
= wxPG_EDITOR(ChoiceAndButton
);
1389 // TextCtrl -> ComboBox
1390 else if ( editor
->IsKindOf(CLASSINFO(wxPGTextCtrlEditor
)) )
1391 editor
= wxPG_EDITOR(ComboBox
);
1397 bool wxPGProperty
::HasVisibleChildren() const
1401 for ( i
=0; i
<GetChildCount(); i
++ )
1403 wxPGProperty
* child
= Item(i
);
1405 if ( !child
->HasFlag(wxPG_PROP_HIDDEN
) )
1412 bool wxPGProperty
::PrepareValueForDialogEditing( wxPropertyGrid
* propGrid
)
1414 return propGrid
->EditorValidate();
1418 bool wxPGProperty
::RecreateEditor()
1420 wxPropertyGrid
* pg
= GetGrid();
1423 wxPGProperty
* selected
= pg
->GetSelection();
1424 if ( this == selected
)
1426 pg
->DoSelectProperty(this, wxPG_SEL_FORCE
);
1433 void wxPGProperty
::SetValueImage( wxBitmap
& bmp
)
1435 delete m_valueBitmap
;
1437 if ( &bmp
&& bmp
.Ok() )
1440 wxSize maxSz
= GetGrid()->GetImageSize();
1441 wxSize
imSz(bmp
.GetWidth(),bmp
.GetHeight());
1443 if ( imSz
.x
!= maxSz
.x
|| imSz
.y
!= maxSz
.y
)
1445 // Create a memory DC
1446 wxBitmap
* bmpNew
= new wxBitmap(maxSz
.x
,maxSz
.y
,bmp
.GetDepth());
1449 dc
.SelectObject(*bmpNew
);
1452 // FIXME: This is ugly - use image or wait for scaling patch.
1453 double scaleX
= (double)maxSz
.x
/ (double)imSz
.x
;
1454 double scaleY
= (double)maxSz
.y
/ (double)imSz
.y
;
1456 dc
.SetUserScale(scaleX
,scaleY
);
1458 dc
.DrawBitmap( bmp
, 0, 0 );
1460 m_valueBitmap
= bmpNew
;
1464 m_valueBitmap
= new wxBitmap(bmp
);
1467 m_flags
|= wxPG_PROP_CUSTOMIMAGE
;
1471 m_valueBitmap
= NULL
;
1472 m_flags
&= ~(wxPG_PROP_CUSTOMIMAGE
);
1477 wxPGProperty
* wxPGProperty
::GetMainParent() const
1479 const wxPGProperty
* curChild
= this;
1480 const wxPGProperty
* curParent
= m_parent
;
1482 while ( curParent
&& !curParent
->IsCategory() )
1484 curChild
= curParent
;
1485 curParent
= curParent
->m_parent
;
1488 return (wxPGProperty
*) curChild
;
1492 const wxPGProperty
* wxPGProperty
::GetLastVisibleSubItem() const
1495 // Returns last visible sub-item, recursively.
1496 if ( !IsExpanded() || !GetChildCount() )
1499 return Last()->GetLastVisibleSubItem();
1503 bool wxPGProperty
::IsVisible() const
1505 const wxPGProperty
* parent
;
1507 if ( HasFlag(wxPG_PROP_HIDDEN
) )
1510 for ( parent
= GetParent(); parent
!= NULL
; parent
= parent
->GetParent() )
1512 if ( !parent
->IsExpanded() || parent
->HasFlag(wxPG_PROP_HIDDEN
) )
1519 wxPropertyGrid
* wxPGProperty
::GetGridIfDisplayed() const
1521 wxPropertyGridPageState
* state
= GetParentState();
1522 wxPropertyGrid
* propGrid
= state
->GetGrid();
1523 if ( state
== propGrid
->GetState() )
1529 int wxPGProperty
::GetY2( int lh
) const
1531 const wxPGProperty
* parent
;
1532 const wxPGProperty
* child
= this;
1536 for ( parent
= GetParent(); parent
!= NULL
; parent
= child
->GetParent() )
1538 if ( !parent
->IsExpanded() )
1540 y
+= parent
->GetChildrenHeight(lh
, child
->GetIndexInParent());
1545 y
-= lh
; // need to reduce one level
1551 int wxPGProperty
::GetY() const
1553 return GetY2(GetGrid()->GetRowHeight());
1556 // This is used by Insert etc.
1557 void wxPGProperty
::AddChild2( wxPGProperty
* prop
, int index
, bool correct_mode
)
1559 if ( index
< 0 || (size_t)index
>= m_children
.GetCount() )
1561 if ( correct_mode
) prop
->m_arrIndex
= m_children
.GetCount();
1562 m_children
.Add( prop
);
1566 m_children
.Insert( prop
, index
);
1567 if ( correct_mode
) FixIndexesOfChildren( index
);
1570 prop
->m_parent
= this;
1573 // This is used by properties that have fixed sub-properties
1574 void wxPGProperty
::AddChild( wxPGProperty
* prop
)
1576 wxASSERT_MSG( prop
->GetBaseName().length(),
1577 "Property's children must have unique, non-empty names within their scope" );
1579 prop
->m_arrIndex
= m_children
.GetCount();
1580 m_children
.Add( prop
);
1582 int custImgHeight
= prop
->OnMeasureImage().y
;
1583 if ( custImgHeight
< 0 /*|| custImgHeight > 1*/ )
1584 prop
->m_flags
|= wxPG_PROP_CUSTOMIMAGE
;
1586 prop
->m_parent
= this;
1590 void wxPGProperty
::AdaptListToValue( wxVariant
& list
, wxVariant
* value
) const
1592 wxASSERT( GetChildCount() );
1593 wxASSERT( !IsCategory() );
1595 *value
= GetValue();
1597 if ( !list
.GetCount() )
1600 wxASSERT( GetChildCount() >= (unsigned int)list
.GetCount() );
1602 bool allChildrenSpecified
;
1604 // Don't fully update aggregate properties unless all children have
1606 if ( HasFlag(wxPG_PROP_AGGREGATE
) )
1607 allChildrenSpecified
= AreAllChildrenSpecified(&list
);
1609 allChildrenSpecified
= true;
1611 wxVariant childValue
= list
[0];
1615 //wxLogDebug(wxT(">> %s.AdaptListToValue()"),GetBaseName().c_str());
1617 for ( i
=0; i
<GetChildCount(); i
++ )
1619 const wxPGProperty
* child
= Item(i
);
1621 if ( childValue
.GetName() == child
->GetBaseName() )
1623 //wxLogDebug(wxT(" %s(n=%i), %s"),childValue.GetName().c_str(),n,childValue.GetType().c_str());
1625 if ( childValue
.GetType() == wxPG_VARIANT_TYPE_LIST
)
1627 wxVariant
cv2(child
->GetValue());
1628 child
->AdaptListToValue(childValue
, &cv2
);
1632 if ( allChildrenSpecified
)
1633 ChildChanged(*value
, i
, childValue
);
1635 if ( n
== (unsigned int)list
.GetCount() )
1637 childValue
= list
[n
];
1643 void wxPGProperty
::FixIndexesOfChildren( size_t starthere
)
1646 for ( i
=starthere
;i
<GetChildCount();i
++)
1647 Item(i
)->m_arrIndex
= i
;
1651 // Returns (direct) child property with given name (or NULL if not found)
1652 wxPGProperty
* wxPGProperty
::GetPropertyByName( const wxString
& name
) const
1656 for ( i
=0; i
<GetChildCount(); i
++ )
1658 wxPGProperty
* p
= Item(i
);
1659 if ( p
->m_name
== name
)
1663 // Does it have point, then?
1664 int pos
= name
.Find(wxS('.'));
1666 return (wxPGProperty
*) NULL
;
1668 wxPGProperty
* p
= GetPropertyByName(name
. substr(0,pos
));
1670 if ( !p
|| !p
->GetChildCount() )
1673 return p
->GetPropertyByName(name
.substr(pos
+1,name
.length()-pos
-1));
1676 wxPGProperty
* wxPGProperty
::GetPropertyByNameWH( const wxString
& name
, unsigned int hintIndex
) const
1678 unsigned int i
= hintIndex
;
1680 if ( i
>= GetChildCount() )
1683 unsigned int lastIndex
= i
- 1;
1685 if ( lastIndex
>= GetChildCount() )
1686 lastIndex
= GetChildCount() - 1;
1690 wxPGProperty
* p
= Item(i
);
1691 if ( p
->m_name
== name
)
1694 if ( i
== lastIndex
)
1698 if ( i
== GetChildCount() )
1705 int wxPGProperty
::GetChildrenHeight( int lh
, int iMax_
) const
1707 // Returns height of children, recursively, and
1708 // by taking expanded/collapsed status into account.
1710 // iMax is used when finding property y-positions.
1716 iMax_
= GetChildCount();
1718 unsigned int iMax
= iMax_
;
1720 wxASSERT( iMax
<= GetChildCount() );
1722 if ( !IsExpanded() && GetParent() )
1727 wxPGProperty
* pwc
= (wxPGProperty
*) Item(i
);
1729 if ( !pwc
->HasFlag(wxPG_PROP_HIDDEN
) )
1731 if ( !pwc
->IsExpanded() ||
1732 pwc
->GetChildCount() == 0 )
1735 h
+= pwc
->GetChildrenHeight(lh
) + lh
;
1744 wxPGProperty
* wxPGProperty
::GetItemAtY( unsigned int y
, unsigned int lh
, unsigned int* nextItemY
) const
1746 wxASSERT( nextItemY
);
1748 // Linear search at the moment
1750 // nextItemY = y of next visible property, final value will be written back.
1751 wxPGProperty
* result
= NULL
;
1752 wxPGProperty
* current
= NULL
;
1753 unsigned int iy
= *nextItemY
;
1755 unsigned int iMax
= GetChildCount();
1759 wxPGProperty
* pwc
= Item(i
);
1761 if ( !pwc
->HasFlag(wxPG_PROP_HIDDEN
) )
1772 if ( pwc
->IsExpanded() &&
1773 pwc
->GetChildCount() > 0 )
1775 result
= (wxPGProperty
*) pwc
->GetItemAtY( y
, lh
, &iy
);
1787 if ( !result
&& y
< iy
)
1794 wxLogDebug(wxT("%s::GetItemAtY(%i) -> %s"),this->GetLabel().c_str(),y,current->GetLabel().c_str());
1796 wxLogDebug(wxT("%s::GetItemAtY(%i) -> NULL"),this->GetLabel().c_str(),y);
1799 return (wxPGProperty
*) result
;
1802 void wxPGProperty
::Empty()
1805 if ( !HasFlag(wxPG_PROP_CHILDREN_ARE_COPIES
) )
1807 for ( i
=0; i
<GetChildCount(); i
++ )
1809 wxPGProperty
* p
= (wxPGProperty
*) Item(i
);
1817 void wxPGProperty
::ChildChanged( wxVariant
& WXUNUSED(thisValue
),
1818 int WXUNUSED(childIndex
),
1819 wxVariant
& WXUNUSED(childValue
) ) const
1823 bool wxPGProperty
::AreAllChildrenSpecified( wxVariant
* pendingList
) const
1827 const wxVariantList
* pList
= NULL
;
1828 wxVariantList
::const_iterator node
;
1832 pList
= &pendingList
->GetList();
1833 node
= pList
->begin();
1836 for ( i
=0; i
<GetChildCount(); i
++ )
1838 wxPGProperty
* child
= Item(i
);
1839 const wxVariant
* listValue
= NULL
;
1844 const wxString
& childName
= child
->GetBaseName();
1846 for ( ; node
!= pList
->end(); node
++ )
1848 const wxVariant
& item
= *((const wxVariant
*)*node
);
1849 if ( item
.GetName() == childName
)
1859 value
= child
->GetValue();
1861 if ( value
.IsNull() )
1864 // Check recursively
1865 if ( child
->GetChildCount() )
1867 const wxVariant
* childList
= NULL
;
1869 if ( listValue
&& listValue
->GetType() == wxPG_VARIANT_TYPE_LIST
)
1870 childList
= listValue
;
1872 if ( !child
->AreAllChildrenSpecified((wxVariant
*)childList
) )
1880 wxPGProperty
* wxPGProperty
::UpdateParentValues()
1882 wxPGProperty
* parent
= m_parent
;
1883 if ( parent
&& parent
->HasFlag(wxPG_PROP_COMPOSED_VALUE
) &&
1884 !parent
->IsCategory() && !parent
->IsRoot() )
1887 parent
->GenerateComposedValue(s
, 0);
1888 parent
->m_value
= s
;
1889 return parent
->UpdateParentValues();
1894 bool wxPGProperty
::IsTextEditable() const
1896 if ( HasFlag(wxPG_PROP_READONLY
) )
1899 if ( HasFlag(wxPG_PROP_NOEDITOR
) &&
1901 wxString(GetEditorClass()->GetClassInfo()->GetClassName()).EndsWith(wxS("Button")))
1908 // Call for after sub-properties added with AddChild
1909 void wxPGProperty
::PrepareSubProperties()
1911 wxPropertyGridPageState
* state
= GetParentState();
1915 if ( !GetChildCount() )
1918 wxByte depth
= m_depth
+ 1;
1919 wxByte depthBgCol
= m_depthBgCol
;
1921 FlagType inheritFlags
= m_flags
& wxPG_INHERITED_PROPFLAGS
;
1923 wxByte bgColIndex
= m_bgColIndex
;
1924 wxByte fgColIndex
= m_fgColIndex
;
1927 // Set some values to the children
1930 wxPGProperty
* nparent
= this;
1932 while ( i
< nparent
->GetChildCount() )
1934 wxPGProperty
* np
= nparent
->Item(i
);
1936 np
->m_parentState
= state
;
1937 np
->m_flags
|= inheritFlags
; // Hideable also if parent.
1938 np
->m_depth
= depth
;
1939 np
->m_depthBgCol
= depthBgCol
;
1940 np
->m_bgColIndex
= bgColIndex
;
1941 np
->m_fgColIndex
= fgColIndex
;
1943 // Also handle children of children
1944 if ( np
->GetChildCount() > 0 )
1950 nparent
->SetParentalType(wxPG_PROP_AGGREGATE
);
1951 nparent
->SetExpanded(false);
1960 // After reaching last sibling, go back to processing
1961 // siblings of the parent
1962 while ( i
>= nparent
->GetChildCount() )
1964 // Exit the loop when top parent hit
1965 if ( nparent
== this )
1970 i
= nparent
->GetArrIndex() + 1;
1971 nparent
= nparent
->GetParent();
1976 // Call after fixed sub-properties added/removed after creation.
1977 // if oldSelInd >= 0 and < new max items, then selection is
1978 // moved to it. Note: oldSelInd -2 indicates that this property
1979 // should be selected.
1980 void wxPGProperty
::SubPropsChanged( int oldSelInd
)
1982 wxPropertyGridPageState
* state
= GetParentState();
1983 wxPropertyGrid
* grid
= state
->GetGrid();
1985 PrepareSubProperties();
1987 wxPGProperty
* sel
= (wxPGProperty
*) NULL
;
1988 if ( oldSelInd
>= (int)m_children
.GetCount() )
1989 oldSelInd
= (int)m_children
.GetCount() - 1;
1991 if ( oldSelInd
>= 0 )
1992 sel
= (wxPGProperty
*) m_children
[oldSelInd
];
1993 else if ( oldSelInd
== -2 )
1997 state
->DoSelectProperty(sel
);
1999 if ( state
== grid
->GetState() )
2001 grid
->GetPanel()->Refresh();
2005 // -----------------------------------------------------------------------
2007 // -----------------------------------------------------------------------
2009 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPGRootProperty
,none
,TextCtrl
)
2010 IMPLEMENT_DYNAMIC_CLASS(wxPGRootProperty
, wxPGProperty
)
2013 wxPGRootProperty
::wxPGRootProperty()
2017 m_name
= wxS("<root>");
2024 wxPGRootProperty
::~wxPGRootProperty()
2029 // -----------------------------------------------------------------------
2030 // wxPropertyCategory
2031 // -----------------------------------------------------------------------
2033 WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(wxPropertyCategory
,none
,TextCtrl
)
2034 IMPLEMENT_DYNAMIC_CLASS(wxPropertyCategory
, wxPGProperty
)
2036 void wxPropertyCategory
::Init()
2038 // don't set colour - prepareadditem method should do this
2039 SetParentalType(wxPG_PROP_CATEGORY
);
2040 m_capFgColIndex
= 1;
2044 wxPropertyCategory
::wxPropertyCategory()
2051 wxPropertyCategory
::wxPropertyCategory( const wxString
&label
, const wxString
& name
)
2052 : wxPGProperty(label
,name
)
2058 wxPropertyCategory
::~wxPropertyCategory()
2063 wxString wxPropertyCategory
::GetValueAsString( int ) const
2065 return wxEmptyString
;
2068 int wxPropertyCategory
::GetTextExtent( const wxWindow
* wnd
, const wxFont
& font
) const
2070 if ( m_textExtent
> 0 )
2071 return m_textExtent
;
2073 ((wxWindow
*)wnd
)->GetTextExtent( m_label
, &x
, &y
, 0, 0, &font
);
2077 void wxPropertyCategory
::CalculateTextExtent( wxWindow
* wnd
, const wxFont
& font
)
2080 wnd
->GetTextExtent( m_label
, &x
, &y
, 0, 0, &font
);
2084 // -----------------------------------------------------------------------
2085 // wxPGAttributeStorage
2086 // -----------------------------------------------------------------------
2088 wxPGAttributeStorage
::wxPGAttributeStorage()
2092 wxPGAttributeStorage
::~wxPGAttributeStorage()
2094 wxPGHashMapS2P
::iterator it
;
2096 for ( it
= m_map
.begin(); it
!= m_map
.end(); it
++ )
2098 wxVariantData
* data
= (wxVariantData
*) it
->second
;
2103 void wxPGAttributeStorage
::Set( const wxString
& name
, const wxVariant
& value
)
2105 wxVariantData
* data
= value
.GetData();
2108 wxPGHashMapS2P
::iterator it
= m_map
.find(name
);
2109 if ( it
!= m_map
.end() )
2110 ((wxVariantData
*)it
->second
)->DecRef();
2118 #endif // wxUSE_PROPGRID