]> git.saurik.com Git - wxWidgets.git/blame - src/propgrid/propgridiface.cpp
Make it possible to use wxCharBuffer during program initialization.
[wxWidgets.git] / src / propgrid / propgridiface.cpp
CommitLineData
1c4293cb
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/propgrid/propgridiface.cpp
3// Purpose: wxPropertyGridInterface class
4// Author: Jaakko Salli
5// Modified by:
6// Created: 2008-08-24
ea5af9c5 7// RCS-ID: $Id$
1c4293cb
VZ
8// Copyright: (c) Jaakko Salli
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx/wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16 #pragma hdrstop
17#endif
18
f4bc1aa2
JS
19#if wxUSE_PROPGRID
20
1c4293cb
VZ
21#ifndef WX_PRECOMP
22 #include "wx/defs.h"
23 #include "wx/object.h"
24 #include "wx/hash.h"
25 #include "wx/string.h"
26 #include "wx/log.h"
27 #include "wx/event.h"
28 #include "wx/window.h"
29 #include "wx/panel.h"
30 #include "wx/dc.h"
31 #include "wx/dcmemory.h"
32 #include "wx/button.h"
33 #include "wx/pen.h"
34 #include "wx/brush.h"
1c4293cb 35 #include "wx/settings.h"
1c4293cb 36 #include "wx/sizer.h"
1c4293cb 37 #include "wx/intl.h"
1c4293cb
VZ
38#endif
39
3b211af1
SC
40#include "wx/propgrid/property.h"
41#include "wx/propgrid/propgrid.h"
1c4293cb
VZ
42
43
44const wxChar *wxPGTypeName_long = wxT("long");
45const wxChar *wxPGTypeName_bool = wxT("bool");
46const wxChar *wxPGTypeName_double = wxT("double");
47const wxChar *wxPGTypeName_wxString = wxT("string");
48const wxChar *wxPGTypeName_void = wxT("void*");
49const wxChar *wxPGTypeName_wxArrayString = wxT("arrstring");
50
51
52// ----------------------------------------------------------------------------
53// VariantDatas
54// ----------------------------------------------------------------------------
55
0372d42e
JS
56WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxPoint, WXDLLIMPEXP_PROPGRID)
57WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED(wxSize, WXDLLIMPEXP_PROPGRID)
58WX_PG_IMPLEMENT_VARIANT_DATA_EXPORTED_DUMMY_EQ(wxArrayInt, WXDLLIMPEXP_PROPGRID)
0372d42e 59IMPLEMENT_VARIANT_OBJECT_EXPORTED(wxFont, WXDLLIMPEXP_PROPGRID)
1c4293cb 60
f3793429
JS
61// -----------------------------------------------------------------------
62// wxPGPropArgCls
63// -----------------------------------------------------------------------
64
65wxPGProperty* wxPGPropArgCls::GetPtr( wxPropertyGridInterface* iface ) const
66{
67 if ( m_flags == IsProperty )
68 {
69 wxASSERT_MSG( m_ptr.property, wxT("invalid property ptr") );
70 return m_ptr.property;
71 }
72 else if ( m_flags & IsWxString )
73 return iface->GetPropertyByNameA(*m_ptr.stringName);
74 else if ( m_flags & IsCharPtr )
75 return iface->GetPropertyByNameA(m_ptr.charName);
76#if wxUSE_WCHAR_T
77 else if ( m_flags & IsWCharPtr )
78 return iface->GetPropertyByNameA(m_ptr.wcharName);
79#endif
80
81 return NULL;
82}
83
1c4293cb 84// -----------------------------------------------------------------------
939d9364 85// wxPropertyGridInterface
1c4293cb
VZ
86// -----------------------------------------------------------------------
87
88void wxPropertyGridInterface::RefreshGrid( wxPropertyGridPageState* state )
89{
90 if ( !state )
91 state = m_pState;
92
93 wxPropertyGrid* grid = state->GetGrid();
94 if ( grid->GetState() == state && !grid->IsFrozen() )
95 {
96 grid->Refresh();
97 }
98}
99
100// -----------------------------------------------------------------------
101
102wxPGProperty* wxPropertyGridInterface::Append( wxPGProperty* property )
103{
104 wxPGProperty* retp = m_pState->DoAppend(property);
03647350 105
1c4293cb
VZ
106 wxPropertyGrid* grid = m_pState->GetGrid();
107 if ( grid )
108 grid->RefreshGrid();
109
110 return retp;
111}
112
113// -----------------------------------------------------------------------
114
115wxPGProperty* wxPropertyGridInterface::AppendIn( wxPGPropArg id, wxPGProperty* newproperty )
116{
117 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty)
118 wxPGProperty* pwc = (wxPGProperty*) p;
119 wxPGProperty* retp = m_pState->DoInsert(pwc, pwc->GetChildCount(), newproperty);
120 return retp;
121}
122
123// -----------------------------------------------------------------------
124
125wxPGProperty* wxPropertyGridInterface::Insert( wxPGPropArg id, wxPGProperty* property )
126{
127 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty)
b96a14e3 128 wxPGProperty* retp = m_pState->DoInsert(p->GetParent(), p->GetIndexInParent(), property);
1c4293cb
VZ
129 RefreshGrid();
130 return retp;
131}
132
133// -----------------------------------------------------------------------
134
135wxPGProperty* wxPropertyGridInterface::Insert( wxPGPropArg id, int index, wxPGProperty* newproperty )
136{
137 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty)
138 wxPGProperty* retp = m_pState->DoInsert((wxPGProperty*)p,index,newproperty);
139 RefreshGrid();
140 return retp;
141}
142
143// -----------------------------------------------------------------------
144
145void wxPropertyGridInterface::DeleteProperty( wxPGPropArg id )
146{
147 wxPG_PROP_ARG_CALL_PROLOG()
148
149 wxPropertyGridPageState* state = p->GetParentState();
1c4293cb 150
f915d44b 151 state->DoDelete( p, true );
1c4293cb
VZ
152
153 RefreshGrid(state);
154}
155
156// -----------------------------------------------------------------------
157
f915d44b
JS
158wxPGProperty* wxPropertyGridInterface::RemoveProperty( wxPGPropArg id )
159{
160 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty)
161
162 wxCHECK( !p->GetChildCount() || p->HasFlag(wxPG_PROP_AGGREGATE),
163 wxNullProperty);
164
165 wxPropertyGridPageState* state = p->GetParentState();
f915d44b
JS
166
167 state->DoDelete( p, false );
168
169 // Mark the property as 'unattached'
170 p->m_parentState = NULL;
171 p->m_parent = NULL;
172
173 RefreshGrid(state);
174
175 return p;
176}
177
178// -----------------------------------------------------------------------
179
1c4293cb
VZ
180wxPGProperty* wxPropertyGridInterface::ReplaceProperty( wxPGPropArg id, wxPGProperty* property )
181{
182 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxNullProperty)
183
184 wxPGProperty* replaced = p;
185 wxCHECK_MSG( replaced && property,
186 wxNullProperty,
187 wxT("NULL property") );
188 wxCHECK_MSG( !replaced->IsCategory(),
189 wxNullProperty,
190 wxT("cannot replace this type of property") );
191 wxCHECK_MSG( !m_pState->IsInNonCatMode(),
192 wxNullProperty,
193 wxT("cannot replace properties in alphabetic mode") );
194
195 // Get address to the slot
196 wxPGProperty* parent = replaced->GetParent();
197 int ind = replaced->GetIndexInParent();
198
199 wxPropertyGridPageState* state = replaced->GetParentState();
200 DeleteProperty(replaced); // Must use generic Delete
201 state->DoInsert(parent,ind,property);
202
203 return property;
204}
205
206// -----------------------------------------------------------------------
207// wxPropertyGridInterface property operations
208// -----------------------------------------------------------------------
209
fc72fab6
JS
210wxPGProperty* wxPropertyGridInterface::GetSelection() const
211{
212 return m_pState->GetSelection();
213}
214
215// -----------------------------------------------------------------------
216
1621f192 217bool wxPropertyGridInterface::ClearSelection( bool validation )
1c4293cb 218{
58935d4a 219 bool res = DoClearSelection(validation, wxPG_SEL_DONT_SEND_EVENT);
9a30da4d
JS
220 wxPropertyGrid* pg = GetPropertyGrid();
221 if ( pg )
222 pg->Refresh();
58935d4a 223 return res;
fc72fab6
JS
224}
225
226// -----------------------------------------------------------------------
227
228bool wxPropertyGridInterface::DoClearSelection( bool validation,
229 int selFlags )
230{
1621f192 231 if ( !validation )
fc72fab6 232 selFlags |= wxPG_SEL_NOVALIDATE;
1621f192 233
1c4293cb 234 wxPropertyGridPageState* state = m_pState;
3c5c6707
JS
235
236 if ( state )
237 {
238 wxPropertyGrid* pg = state->GetGrid();
239 if ( pg->GetState() == state )
fc72fab6 240 return pg->DoSelectProperty(NULL, selFlags);
3c5c6707 241 else
fc72fab6 242 state->DoSetSelection(NULL);
3c5c6707
JS
243 }
244
1c4293cb
VZ
245 return true;
246}
247
248// -----------------------------------------------------------------------
249
250void wxPropertyGridInterface::LimitPropertyEditing( wxPGPropArg id, bool limit )
251{
252 wxPG_PROP_ARG_CALL_PROLOG()
253
254 m_pState->DoLimitPropertyEditing(p, limit);
255 RefreshProperty(p);
256}
257
258// -----------------------------------------------------------------------
259
260bool wxPropertyGridInterface::EnableProperty( wxPGPropArg id, bool enable )
261{
262 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
263
264 wxPropertyGridPageState* state = p->GetParentState();
265 wxPropertyGrid* grid = state->GetGrid();
266
267 if ( enable )
268 {
269 if ( !(p->m_flags & wxPG_PROP_DISABLED) )
270 return false;
271
272 // If active, Set active Editor.
7f344b3b 273 if ( grid && grid->GetState() == state && p == grid->GetSelection() )
1c4293cb
VZ
274 grid->DoSelectProperty( p, wxPG_SEL_FORCE );
275 }
276 else
277 {
278 if ( p->m_flags & wxPG_PROP_DISABLED )
279 return false;
280
281 // If active, Disable as active Editor.
7f344b3b 282 if ( grid && grid->GetState() == state && p == grid->GetSelection() )
1c4293cb
VZ
283 grid->DoSelectProperty( p, wxPG_SEL_FORCE );
284 }
285
286 state->DoEnableProperty(p, enable);
287
288 RefreshProperty( p );
289
290 return true;
291}
292
293// -----------------------------------------------------------------------
294
295bool wxPropertyGridInterface::ExpandAll( bool doExpand )
296{
297 wxPropertyGridPageState* state = m_pState;
298
299 if ( !state->DoGetRoot()->GetChildCount() )
300 return true;
301
302 wxPropertyGrid* pg = state->GetGrid();
303
304 if ( GetSelection() && GetSelection() != state->DoGetRoot() &&
305 !doExpand )
306 {
01b5ad3b 307 pg->DoClearSelection();
1c4293cb
VZ
308 }
309
310 wxPGVIterator it;
311
312 for ( it = GetVIterator( wxPG_ITERATE_ALL ); !it.AtEnd(); it.Next() )
313 {
314 wxPGProperty* p = (wxPGProperty*) it.GetProperty();
315 if ( p->GetChildCount() )
316 {
317 if ( doExpand )
318 {
319 if ( !p->IsExpanded() )
320 {
321 state->DoExpand(p);
322 }
323 }
324 else
325 {
326 if ( p->IsExpanded() )
327 {
328 state->DoCollapse(p);
329 }
330 }
331 }
332 }
333
334 pg->RecalculateVirtualSize();
335
336 RefreshGrid();
337
338 return true;
339}
340
341// -----------------------------------------------------------------------
342
89b44158
JS
343void wxPropertyGridInterface::ClearModifiedStatus()
344{
345 unsigned int pageIndex = 0;
346
347 for (;;)
348 {
349 wxPropertyGridPageState* page = GetPageState(pageIndex);
350 if ( !page ) break;
351
352 page->DoGetRoot()->SetFlagRecursively(wxPG_PROP_MODIFIED, false);
86a6c828 353 page->m_anyModified = false;
89b44158
JS
354
355 pageIndex++;
356 }
f521bae6
JS
357
358 // Update active editor control, if any
359 GetPropertyGrid()->RefreshEditor();
89b44158
JS
360}
361
fe01f16e
JS
362bool wxPropertyGridInterface::SetColumnProportion( unsigned int column,
363 int proportion )
364{
365 wxCHECK(m_pState, false);
366 wxPropertyGrid* pg = m_pState->GetGrid();
367 wxCHECK(pg, false);
368 wxCHECK(pg->HasFlag(wxPG_SPLITTER_AUTO_CENTER), false);
369 m_pState->DoSetColumnProportion(column, proportion);
370 return true;
371}
372
1c4293cb
VZ
373// -----------------------------------------------------------------------
374// wxPropertyGridInterface property value setting and getting
375// -----------------------------------------------------------------------
376
0372d42e 377void wxPGGetFailed( const wxPGProperty* p, const wxString& typestr )
1c4293cb 378{
0372d42e 379 wxPGTypeOperationFailed(p, typestr, wxS("Get"));
1c4293cb
VZ
380}
381
382// -----------------------------------------------------------------------
383
0372d42e
JS
384void wxPGTypeOperationFailed( const wxPGProperty* p,
385 const wxString& typestr,
386 const wxString& op )
1c4293cb
VZ
387{
388 wxASSERT( p != NULL );
389 wxLogError( _("Type operation \"%s\" failed: Property labeled \"%s\" is of type \"%s\", NOT \"%s\"."),
0372d42e 390 op.c_str(), p->GetLabel().c_str(), p->GetValue().GetType().c_str(), typestr.c_str() );
1c4293cb
VZ
391}
392
393// -----------------------------------------------------------------------
394
395void wxPropertyGridInterface::SetPropVal( wxPGPropArg id, wxVariant& value )
396{
397 wxPG_PROP_ARG_CALL_PROLOG()
398
399 if ( p )
1c4293cb 400 p->SetValue(value);
1c4293cb
VZ
401}
402
403// -----------------------------------------------------------------------
404
405void wxPropertyGridInterface::SetPropertyValueString( wxPGPropArg id, const wxString& value )
406{
407 wxPG_PROP_ARG_CALL_PROLOG()
408
e777bd14
JS
409 if ( p )
410 m_pState->DoSetPropertyValueString(p, value);
1c4293cb
VZ
411}
412
413// -----------------------------------------------------------------------
414
415void wxPropertyGridInterface::SetValidationFailureBehavior( int vfbFlags )
416{
417 GetPropertyGrid()->m_permanentValidationFailureBehavior = vfbFlags;
418}
419
420// -----------------------------------------------------------------------
421
422wxPGProperty* wxPropertyGridInterface::GetPropertyByNameA( const wxString& name ) const
423{
424 wxPGProperty* p = GetPropertyByName(name);
425 wxASSERT_MSG(p,wxString::Format(wxT("no property with name '%s'"),name.c_str()));
426 return p;
427}
428
429// ----------------------------------------------------------------------------
430
431wxPGProperty* wxPropertyGridInterface::GetPropertyByLabel( const wxString& label ) const
432{
433 wxPGVIterator it;
434
435 for ( it = GetVIterator( wxPG_ITERATE_PROPERTIES ); !it.AtEnd(); it.Next() )
436 {
437 if ( it.GetProperty()->GetLabel() == label )
438 return it.GetProperty();
439 }
440
441 return wxNullProperty;
442}
443
444// ----------------------------------------------------------------------------
445
446void wxPropertyGridInterface::DoSetPropertyAttribute( wxPGPropArg id, const wxString& name,
447 wxVariant& value, long argFlags )
448{
449 wxPG_PROP_ARG_CALL_PROLOG()
450
451 p->SetAttribute( name, value );
452
453 if ( argFlags & wxPG_RECURSE )
454 {
455 unsigned int i;
456 for ( i = 0; i < p->GetChildCount(); i++ )
457 DoSetPropertyAttribute(p->Item(i), name, value, argFlags);
458 }
459}
460
461// -----------------------------------------------------------------------
462
3c26d11b
JS
463void wxPropertyGridInterface::SetPropertyAttributeAll( const wxString& attrName,
464 wxVariant value )
465{
466 unsigned int pageIndex = 0;
467
468 for (;;)
469 {
470 wxPropertyGridPageState* page = GetPageState(pageIndex);
471 if ( !page ) break;
472
473 DoSetPropertyAttribute(page->DoGetRoot(), attrName, value, wxPG_RECURSE);
474
475 pageIndex++;
476 }
477}
478
479// -----------------------------------------------------------------------
480
1c4293cb
VZ
481void wxPropertyGridInterface::GetPropertiesWithFlag( wxArrayPGProperty* targetArr,
482 wxPGProperty::FlagType flags,
483 bool inverse,
484 int iterFlags ) const
485{
486 wxASSERT( targetArr );
487 wxPGVIterator it = GetVIterator( iterFlags );
488
489 for ( ;
490 !it.AtEnd();
491 it.Next() )
492 {
493 const wxPGProperty* property = it.GetProperty();
494
495 if ( !inverse )
496 {
497 if ( (property->GetFlags() & flags) == flags )
498 targetArr->push_back((wxPGProperty*)property);
499 }
500 else
501 {
502 if ( (property->GetFlags() & flags) != flags )
503 targetArr->push_back((wxPGProperty*)property);
504 }
505 }
506}
507
508// -----------------------------------------------------------------------
509
1c4293cb
VZ
510void wxPropertyGridInterface::SetBoolChoices( const wxString& trueChoice,
511 const wxString& falseChoice )
512{
513 wxPGGlobalVars->m_boolChoices[0] = falseChoice;
514 wxPGGlobalVars->m_boolChoices[1] = trueChoice;
515}
516
517// -----------------------------------------------------------------------
518
1c4293cb
VZ
519wxPGProperty* wxPropertyGridInterface::DoGetPropertyByName( const wxString& name ) const
520{
521 return m_pState->BaseGetPropertyByName(name);
522}
523
524// -----------------------------------------------------------------------
525
526wxPGProperty* wxPropertyGridInterface::GetPropertyByName( const wxString& name,
527 const wxString& subname ) const
528{
529 wxPGProperty* p = DoGetPropertyByName(name);
530 if ( !p || !p->GetChildCount() )
531 return wxNullProperty;
532
533 return p->GetPropertyByName(subname);
534}
535
536// -----------------------------------------------------------------------
537
538// Since GetPropertyByName is used *a lot*, this makes sense
539// since non-virtual method can be called with less code.
540wxPGProperty* wxPropertyGridInterface::GetPropertyByName( const wxString& name ) const
541{
542 wxPGProperty* p = DoGetPropertyByName(name);
543 if ( p )
544 return p;
545
546 // Check if its "Property.SubProperty" format
547 int pos = name.Find(wxT('.'));
548 if ( pos <= 0 )
549 return NULL;
550
551 return GetPropertyByName(name.substr(0,pos),
552 name.substr(pos+1,name.length()-pos-1));
553}
554
555// -----------------------------------------------------------------------
556
557bool wxPropertyGridInterface::HideProperty( wxPGPropArg id, bool hide, int flags )
558{
559 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
560
561 wxPropertyGrid* pg = m_pState->GetGrid();
562
563 if ( pg == p->GetGrid() )
564 return pg->DoHideProperty(p, hide, flags);
565 else
566 m_pState->DoHideProperty(p, hide, flags);
567
568 return true;
569}
570
571// -----------------------------------------------------------------------
572
573bool wxPropertyGridInterface::Collapse( wxPGPropArg id )
574{
575 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
576 wxPropertyGrid* pg = p->GetGridIfDisplayed();
577 if ( pg )
578 return pg->DoCollapse(p);
579
580 return p->GetParentState()->DoCollapse(p);
581}
582
583// -----------------------------------------------------------------------
584
585bool wxPropertyGridInterface::Expand( wxPGPropArg id )
586{
587 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
588 wxPropertyGrid* pg = p->GetGridIfDisplayed();
589 if ( pg )
590 return pg->DoExpand(p);
591
592 return p->GetParentState()->DoExpand(p);
593}
594
595// -----------------------------------------------------------------------
596
0eb877f2 597void wxPropertyGridInterface::Sort( int flags )
43396981
JS
598{
599 wxPropertyGrid* pg = GetPropertyGrid();
600
43396981
JS
601 unsigned int pageIndex = 0;
602
603 for (;;)
604 {
605 wxPropertyGridPageState* page = GetPageState(pageIndex);
606 if ( !page ) break;
0eb877f2 607 page->DoSort(flags);
43396981
JS
608 pageIndex++;
609 }
7261371b
JS
610
611 // Fix positions of any open editor controls
612 if ( pg )
613 pg->CorrectEditorWidgetPosY();
43396981
JS
614}
615
616// -----------------------------------------------------------------------
617
1c4293cb
VZ
618void wxPropertyGridInterface::SetPropertyLabel( wxPGPropArg id, const wxString& newproplabel )
619{
620 wxPG_PROP_ARG_CALL_PROLOG()
621
622 p->SetLabel( newproplabel );
623
624 wxPropertyGridPageState* state = p->GetParentState();
625 wxPropertyGrid* pg = state->GetGrid();
626
627 if ( pg->HasFlag(wxPG_AUTO_SORT) )
628 pg->SortChildren(p->GetParent());
629
630 if ( pg->GetState() == state )
631 {
632 if ( pg->HasFlag(wxPG_AUTO_SORT) )
633 pg->Refresh();
634 else
635 pg->DrawItem( p );
636 }
637}
638
639// -----------------------------------------------------------------------
640
641bool wxPropertyGridInterface::SetPropertyMaxLength( wxPGPropArg id, int maxLen )
642{
643 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
644
645 wxPropertyGrid* pg = m_pState->GetGrid();
646
647 p->m_maxLen = (short) maxLen;
648
649 // Adjust control if selected currently
650 if ( pg == p->GetGrid() && p == m_pState->GetSelection() )
651 {
652 wxWindow* wnd = pg->GetEditorControl();
653 wxTextCtrl* tc = wxDynamicCast(wnd,wxTextCtrl);
654 if ( tc )
655 tc->SetMaxLength( maxLen );
656 else
657 // Not a text ctrl
658 return false;
659 }
660
661 return true;
662}
663
d7e2b522
JS
664// -----------------------------------------------------------------------
665
e2ca6599
JS
666void
667wxPropertyGridInterface::SetPropertyBackgroundColour( wxPGPropArg id,
668 const wxColour& colour,
e607eac2 669 int flags )
e2ca6599
JS
670{
671 wxPG_PROP_ARG_CALL_PROLOG()
e607eac2
JS
672 p->SetBackgroundColour(colour, flags);
673 RefreshProperty(p);
e2ca6599
JS
674}
675
676// -----------------------------------------------------------------------
677
678void wxPropertyGridInterface::SetPropertyTextColour( wxPGPropArg id,
679 const wxColour& colour,
e607eac2 680 int flags )
e2ca6599
JS
681{
682 wxPG_PROP_ARG_CALL_PROLOG()
e607eac2
JS
683 p->SetTextColour(colour, flags);
684 RefreshProperty(p);
e2ca6599
JS
685}
686
687// -----------------------------------------------------------------------
688
689void wxPropertyGridInterface::SetPropertyColoursToDefault( wxPGPropArg id )
690{
691 wxPG_PROP_ARG_CALL_PROLOG()
692
693 p->m_cells.clear();
694}
695
696// -----------------------------------------------------------------------
697
d7e2b522
JS
698void wxPropertyGridInterface::SetPropertyCell( wxPGPropArg id,
699 int column,
700 const wxString& text,
701 const wxBitmap& bitmap,
702 const wxColour& fgCol,
703 const wxColour& bgCol )
704{
705 wxPG_PROP_ARG_CALL_PROLOG()
706
707 wxPGCell& cell = p->GetCell(column);
708 if ( text.length() && text != wxPG_LABEL )
709 cell.SetText(text);
710 if ( bitmap.IsOk() )
711 cell.SetBitmap(bitmap);
712 if ( fgCol != wxNullColour )
713 cell.SetFgCol(fgCol);
714 if ( bgCol != wxNullColour )
715 cell.SetBgCol(bgCol);
716}
717
1c4293cb
VZ
718// -----------------------------------------------------------------------
719// GetPropertyValueAsXXX methods
720
721#define IMPLEMENT_GET_VALUE(T,TRET,BIGNAME,DEFRETVAL) \
722TRET wxPropertyGridInterface::GetPropertyValueAs##BIGNAME( wxPGPropArg id ) const \
723{ \
724 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(DEFRETVAL) \
725 wxVariant value = p->GetValue(); \
726 if ( wxStrcmp(value.GetType(), wxPGTypeName_##T) != 0 ) \
727 { \
728 wxPGGetFailed(p,wxPGTypeName_##T); \
729 return (TRET)DEFRETVAL; \
730 } \
731 return (TRET)value.Get##BIGNAME(); \
732}
733
734// String is different than others.
735wxString wxPropertyGridInterface::GetPropertyValueAsString( wxPGPropArg id ) const
736{
737 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxEmptyString)
738 return p->GetValueAsString(wxPG_FULL_VALUE);
739}
740
741bool wxPropertyGridInterface::GetPropertyValueAsBool( wxPGPropArg id ) const
742{
743 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
744 wxVariant value = p->GetValue();
745 if ( wxStrcmp(value.GetType(), wxPGTypeName_bool) == 0 )
746 {
747 return value.GetBool();
748 }
749 if ( wxStrcmp(value.GetType(), wxPGTypeName_long) == 0 )
750 {
751 return value.GetLong()?true:false;
752 }
753 wxPGGetFailed(p,wxPGTypeName_bool);
754 return false;
755}
756
757IMPLEMENT_GET_VALUE(long,long,Long,0)
758IMPLEMENT_GET_VALUE(double,double,Double,0.0)
1c4293cb 759
1c4293cb
VZ
760bool wxPropertyGridInterface::IsPropertyExpanded( wxPGPropArg id ) const
761{
762 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
763 return p->IsExpanded();
764}
765
766// -----------------------------------------------------------------------
767// wxPropertyGridInterface wrappers
768// -----------------------------------------------------------------------
769
770bool wxPropertyGridInterface::ChangePropertyValue( wxPGPropArg id, wxVariant newValue )
771{
772 return GetPropertyGrid()->ChangePropertyValue(id, newValue);
773}
774
775// -----------------------------------------------------------------------
776
777void wxPropertyGridInterface::BeginAddChildren( wxPGPropArg id )
778{
779 wxPG_PROP_ARG_CALL_PROLOG()
780 wxCHECK_RET( p->HasFlag(wxPG_PROP_AGGREGATE), wxT("only call on properties with fixed children") );
781 p->ClearFlag(wxPG_PROP_AGGREGATE);
782 p->SetFlag(wxPG_PROP_MISC_PARENT);
783}
784
785// -----------------------------------------------------------------------
786
787bool wxPropertyGridInterface::EditorValidate()
788{
789 return GetPropertyGrid()->DoEditorValidate();
790}
791
792// -----------------------------------------------------------------------
793
794void wxPropertyGridInterface::EndAddChildren( wxPGPropArg id )
795{
796 wxPG_PROP_ARG_CALL_PROLOG()
797 wxCHECK_RET( p->HasFlag(wxPG_PROP_MISC_PARENT), wxT("only call on properties for which BeginAddChildren was called prior") );
798 p->ClearFlag(wxPG_PROP_MISC_PARENT);
799 p->SetFlag(wxPG_PROP_AGGREGATE);
800}
801
802// -----------------------------------------------------------------------
803// wxPGVIterator_State
804// -----------------------------------------------------------------------
805
806// Default returned by wxPropertyGridInterface::GetVIterator().
807class wxPGVIteratorBase_State : public wxPGVIteratorBase
808{
809public:
810 wxPGVIteratorBase_State( wxPropertyGridPageState* state, int flags )
811 {
812 m_it.Init( state, flags );
813 }
814 virtual ~wxPGVIteratorBase_State() { }
815 virtual void Next() { m_it.Next(); }
816};
817
818wxPGVIterator wxPropertyGridInterface::GetVIterator( int flags ) const
819{
820 return wxPGVIterator( new wxPGVIteratorBase_State( m_pState, flags ) );
821}
822
823// -----------------------------------------------------------------------
824// wxPGEditableState related functions
825// -----------------------------------------------------------------------
826
827// EscapeDelimiters() changes ";" into "\;" and "|" into "\|"
828// in the input string. This is an internal functions which is
829// used for saving states
830// NB: Similar function exists in aui/framemanager.cpp
831static wxString EscapeDelimiters(const wxString& s)
832{
833 wxString result;
834 result.Alloc(s.length());
835 const wxChar* ch = s.c_str();
836 while (*ch)
837 {
838 if (*ch == wxT(';') || *ch == wxT('|') || *ch == wxT(','))
839 result += wxT('\\');
840 result += *ch;
841 ++ch;
842 }
843 return result;
844}
845
846wxString wxPropertyGridInterface::SaveEditableState( int includedStates ) const
847{
848 wxString result;
849
850 //
851 // Save state on page basis
3c26d11b 852 unsigned int pageIndex = 0;
1c4293cb 853 wxArrayPtrVoid pageStates;
3c26d11b
JS
854
855 for (;;)
1c4293cb 856 {
3c26d11b
JS
857 wxPropertyGridPageState* page = GetPageState(pageIndex);
858 if ( !page ) break;
859
860 pageStates.Add(page);
861
862 pageIndex++;
1c4293cb
VZ
863 }
864
865 for ( pageIndex=0; pageIndex < pageStates.size(); pageIndex++ )
866 {
867 wxPropertyGridPageState* pageState = (wxPropertyGridPageState*) pageStates[pageIndex];
868
869 if ( includedStates & SelectionState )
870 {
871 wxString sel;
872 if ( pageState->GetSelection() )
873 sel = pageState->GetSelection()->GetName();
874 result += wxS("selection=");
875 result += EscapeDelimiters(sel);
876 result += wxS(";");
877 }
878 if ( includedStates & ExpandedState )
879 {
880 wxArrayPGProperty ptrs;
03647350 881 wxPropertyGridConstIterator it =
1c4293cb
VZ
882 wxPropertyGridConstIterator( pageState,
883 wxPG_ITERATE_ALL_PARENTS_RECURSIVELY|wxPG_ITERATE_HIDDEN,
884 wxNullProperty );
885
886 result += wxS("expanded=");
887
888 for ( ;
889 !it.AtEnd();
890 it.Next() )
891 {
892 const wxPGProperty* p = it.GetProperty();
893
894 if ( !p->HasFlag(wxPG_PROP_COLLAPSED) )
895 result += EscapeDelimiters(p->GetName());
b7bc9d80 896 result += wxS(",");
1c4293cb
VZ
897
898 }
899
900 if ( result.Last() == wxS(',') )
901 result.RemoveLast();
902
903 result += wxS(";");
904 }
905 if ( includedStates & ScrollPosState )
906 {
907 int x, y;
908 GetPropertyGrid()->GetViewStart(&x,&y);
909 result += wxString::Format(wxS("scrollpos=%i,%i;"), x, y);
910 }
911 if ( includedStates & SplitterPosState )
912 {
913 result += wxS("splitterpos=");
914
915 for ( size_t i=0; i<pageState->GetColumnCount(); i++ )
916 result += wxString::Format(wxS("%i,"), pageState->DoGetSplitterPosition(i));
917
918 result.RemoveLast(); // Remove last comma
919 result += wxS(";");
920 }
921 if ( includedStates & PageState )
922 {
923 result += wxS("ispageselected=");
924
925 if ( GetPageState(-1) == pageState )
926 result += wxS("1;");
927 else
928 result += wxS("0;");
929 }
62805170
JS
930 if ( includedStates & DescBoxState )
931 {
932 wxVariant v = GetEditableStateItem(wxS("descboxheight"));
72eb964f
JS
933 if ( !v.IsNull() )
934 result += wxString::Format(wxS("descboxheight=%i;"), (int)v.GetLong());
62805170 935 }
1c4293cb
VZ
936 result.RemoveLast(); // Remove last semicolon
937 result += wxS("|");
938 }
939
940 // Remove last '|'
941 if ( result.length() )
942 result.RemoveLast();
943
944 return result;
945}
946
947bool wxPropertyGridInterface::RestoreEditableState( const wxString& src, int restoreStates )
948{
949 wxPropertyGrid* pg = GetPropertyGrid();
950 wxPGProperty* newSelection = NULL;
951 size_t pageIndex;
952 long vx = -1;
953 long vy = -1;
954 long selectedPage = -1;
955 bool pgSelectionSet = false;
956 bool res = true;
957
958 pg->Freeze();
959 wxArrayString pageStrings = ::wxSplit(src, wxS('|'), wxS('\\'));
960
961 for ( pageIndex=0; pageIndex<pageStrings.size(); pageIndex++ )
962 {
963 wxPropertyGridPageState* pageState = GetPageState(pageIndex);
964 if ( !pageState )
965 break;
966
967 wxArrayString kvpairStrings = ::wxSplit(pageStrings[pageIndex], wxS(';'), wxS('\\'));
968
969 for ( size_t i=0; i<kvpairStrings.size(); i++ )
970 {
971 const wxString& kvs = kvpairStrings[i];
972 int eq_pos = kvs.Find(wxS('='));
973 if ( eq_pos != wxNOT_FOUND )
974 {
975 wxString key = kvs.substr(0, eq_pos);
976 wxString value = kvs.substr(eq_pos+1);
977
978 // Further split value by commas
979 wxArrayString values = ::wxSplit(value, wxS(','), wxS('\\'));
980
981 if ( key == wxS("expanded") )
982 {
983 if ( restoreStates & ExpandedState )
984 {
03647350 985 wxPropertyGridIterator it =
1c4293cb
VZ
986 wxPropertyGridIterator( pageState,
987 wxPG_ITERATE_ALL,
988 wxNullProperty );
989
990 // First collapse all
991 for ( ; !it.AtEnd(); it.Next() )
992 {
993 wxPGProperty* p = it.GetProperty();
994 pageState->DoCollapse(p);
995 }
996
997 // Then expand those which names are in values
998 for ( size_t n=0; n<values.size(); n++ )
999 {
1000 const wxString& name = values[n];
1001 wxPGProperty* prop = GetPropertyByName(name);
1002 if ( prop )
1003 pageState->DoExpand(prop);
1004 }
1005 }
1006 }
1007 else if ( key == wxS("scrollpos") )
1008 {
1009 if ( restoreStates & ScrollPosState )
1010 {
1011 if ( values.size() == 2 )
1012 {
1013 values[0].ToLong(&vx);
1014 values[1].ToLong(&vy);
1015 }
1016 else
1017 {
1018 res = false;
1019 }
1020 }
1021 }
1022 else if ( key == wxS("splitterpos") )
1023 {
1024 if ( restoreStates & SplitterPosState )
1025 {
1026 for ( size_t n=1; n<values.size(); n++ )
1027 {
1028 long pos = 0;
1029 values[n].ToLong(&pos);
1030 if ( pos > 0 )
1031 pageState->DoSetSplitterPosition(pos, n);
1032 }
1033 }
1034 }
1035 else if ( key == wxS("selection") )
1036 {
1037 if ( restoreStates & SelectionState )
1038 {
1039 if ( values.size() > 0 )
1040 {
1041 if ( pageState->IsDisplayed() )
1042 {
1043 if ( values[0].length() )
1044 newSelection = GetPropertyByName(value);
1045 pgSelectionSet = true;
1046 }
1047 else
1048 {
1049 if ( values[0].length() )
fc72fab6 1050 pageState->DoSetSelection(GetPropertyByName(value));
1c4293cb
VZ
1051 else
1052 pageState->DoClearSelection();
1053 }
1054 }
1055 }
1056 }
1057 else if ( key == wxS("ispageselected") )
1058 {
1059 if ( restoreStates & PageState )
1060 {
1061 long pageSelStatus;
1062 if ( values.size() == 1 && values[0].ToLong(&pageSelStatus) )
1063 {
1064 if ( pageSelStatus )
1065 selectedPage = pageIndex;
1066 }
1067 else
1068 {
62805170
JS
1069 res = false;
1070 }
1071 }
1072 }
1073 else if ( key == wxS("descboxheight") )
1074 {
1075 if ( restoreStates & DescBoxState )
1076 {
1077 long descBoxHeight;
1078 if ( values.size() == 1 && values[0].ToLong(&descBoxHeight) )
1079 {
1080 SetEditableStateItem(wxS("descboxheight"), descBoxHeight);
1081 }
1082 else
1083 {
1c4293cb
VZ
1084 res = false;
1085 }
1086 }
1087 }
1088 else
1089 {
1090 res = false;
1091 }
1092 }
1093 }
1094 }
1095
1096 //
1097 // Force recalculation of virtual heights of all pages
1098 // (may be needed on unclean source string).
1099 pageIndex = 0;
1100 wxPropertyGridPageState* pageState = GetPageState(pageIndex);
1101 while ( pageState )
1102 {
1103 pageState->VirtualHeightChanged();
1104 pageIndex += 1;
1105 pageState = GetPageState(pageIndex);
1106 }
1107
1108 pg->Thaw();
1109
1110 //
1111 // Selection of visible grid page must be set after Thaw() call
1112 if ( pgSelectionSet )
1113 {
1114 if ( newSelection )
01b5ad3b 1115 pg->DoSelectProperty(newSelection);
1c4293cb 1116 else
01b5ad3b 1117 pg->DoClearSelection();
1c4293cb
VZ
1118 }
1119
1120 if ( selectedPage != -1 )
1121 {
1122 DoSelectPage(selectedPage);
1123 }
1124
1125 if ( vx >= 0 )
1126 {
1127 pg->Scroll(vx, vy);
1128 }
1129
1130 return res;
1131}
1132
f4bc1aa2
JS
1133#endif // wxUSE_PROPGRID
1134