]> git.saurik.com Git - wxWidgets.git/blame - src/propgrid/propgridiface.cpp
Use correct array size for weekday names.
[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
JS
219 bool res = DoClearSelection(validation, wxPG_SEL_DONT_SEND_EVENT);
220 GetPropertyGrid()->Refresh();
221 return res;
fc72fab6
JS
222}
223
224// -----------------------------------------------------------------------
225
226bool wxPropertyGridInterface::DoClearSelection( bool validation,
227 int selFlags )
228{
1621f192 229 if ( !validation )
fc72fab6 230 selFlags |= wxPG_SEL_NOVALIDATE;
1621f192 231
1c4293cb 232 wxPropertyGridPageState* state = m_pState;
3c5c6707
JS
233
234 if ( state )
235 {
236 wxPropertyGrid* pg = state->GetGrid();
237 if ( pg->GetState() == state )
fc72fab6 238 return pg->DoSelectProperty(NULL, selFlags);
3c5c6707 239 else
fc72fab6 240 state->DoSetSelection(NULL);
3c5c6707
JS
241 }
242
1c4293cb
VZ
243 return true;
244}
245
246// -----------------------------------------------------------------------
247
248void wxPropertyGridInterface::LimitPropertyEditing( wxPGPropArg id, bool limit )
249{
250 wxPG_PROP_ARG_CALL_PROLOG()
251
252 m_pState->DoLimitPropertyEditing(p, limit);
253 RefreshProperty(p);
254}
255
256// -----------------------------------------------------------------------
257
258bool wxPropertyGridInterface::EnableProperty( wxPGPropArg id, bool enable )
259{
260 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
261
262 wxPropertyGridPageState* state = p->GetParentState();
263 wxPropertyGrid* grid = state->GetGrid();
264
265 if ( enable )
266 {
267 if ( !(p->m_flags & wxPG_PROP_DISABLED) )
268 return false;
269
270 // If active, Set active Editor.
271 if ( grid->GetState() == state && p == grid->GetSelection() )
272 grid->DoSelectProperty( p, wxPG_SEL_FORCE );
273 }
274 else
275 {
276 if ( p->m_flags & wxPG_PROP_DISABLED )
277 return false;
278
279 // If active, Disable as active Editor.
280 if ( grid->GetState() == state && p == grid->GetSelection() )
281 grid->DoSelectProperty( p, wxPG_SEL_FORCE );
282 }
283
284 state->DoEnableProperty(p, enable);
285
286 RefreshProperty( p );
287
288 return true;
289}
290
291// -----------------------------------------------------------------------
292
293bool wxPropertyGridInterface::ExpandAll( bool doExpand )
294{
295 wxPropertyGridPageState* state = m_pState;
296
297 if ( !state->DoGetRoot()->GetChildCount() )
298 return true;
299
300 wxPropertyGrid* pg = state->GetGrid();
301
302 if ( GetSelection() && GetSelection() != state->DoGetRoot() &&
303 !doExpand )
304 {
01b5ad3b 305 pg->DoClearSelection();
1c4293cb
VZ
306 }
307
308 wxPGVIterator it;
309
310 for ( it = GetVIterator( wxPG_ITERATE_ALL ); !it.AtEnd(); it.Next() )
311 {
312 wxPGProperty* p = (wxPGProperty*) it.GetProperty();
313 if ( p->GetChildCount() )
314 {
315 if ( doExpand )
316 {
317 if ( !p->IsExpanded() )
318 {
319 state->DoExpand(p);
320 }
321 }
322 else
323 {
324 if ( p->IsExpanded() )
325 {
326 state->DoCollapse(p);
327 }
328 }
329 }
330 }
331
332 pg->RecalculateVirtualSize();
333
334 RefreshGrid();
335
336 return true;
337}
338
339// -----------------------------------------------------------------------
340
89b44158
JS
341void wxPropertyGridInterface::ClearModifiedStatus()
342{
343 unsigned int pageIndex = 0;
344
345 for (;;)
346 {
347 wxPropertyGridPageState* page = GetPageState(pageIndex);
348 if ( !page ) break;
349
350 page->DoGetRoot()->SetFlagRecursively(wxPG_PROP_MODIFIED, false);
351
352 pageIndex++;
353 }
f521bae6
JS
354
355 // Update active editor control, if any
356 GetPropertyGrid()->RefreshEditor();
89b44158
JS
357}
358
1c4293cb
VZ
359// -----------------------------------------------------------------------
360// wxPropertyGridInterface property value setting and getting
361// -----------------------------------------------------------------------
362
0372d42e 363void wxPGGetFailed( const wxPGProperty* p, const wxString& typestr )
1c4293cb 364{
0372d42e 365 wxPGTypeOperationFailed(p, typestr, wxS("Get"));
1c4293cb
VZ
366}
367
368// -----------------------------------------------------------------------
369
0372d42e
JS
370void wxPGTypeOperationFailed( const wxPGProperty* p,
371 const wxString& typestr,
372 const wxString& op )
1c4293cb
VZ
373{
374 wxASSERT( p != NULL );
375 wxLogError( _("Type operation \"%s\" failed: Property labeled \"%s\" is of type \"%s\", NOT \"%s\"."),
0372d42e 376 op.c_str(), p->GetLabel().c_str(), p->GetValue().GetType().c_str(), typestr.c_str() );
1c4293cb
VZ
377}
378
379// -----------------------------------------------------------------------
380
381void wxPropertyGridInterface::SetPropVal( wxPGPropArg id, wxVariant& value )
382{
383 wxPG_PROP_ARG_CALL_PROLOG()
384
385 if ( p )
1c4293cb 386 p->SetValue(value);
1c4293cb
VZ
387}
388
389// -----------------------------------------------------------------------
390
391void wxPropertyGridInterface::SetPropertyValueString( wxPGPropArg id, const wxString& value )
392{
393 wxPG_PROP_ARG_CALL_PROLOG()
394
e777bd14
JS
395 if ( p )
396 m_pState->DoSetPropertyValueString(p, value);
1c4293cb
VZ
397}
398
399// -----------------------------------------------------------------------
400
401void wxPropertyGridInterface::SetValidationFailureBehavior( int vfbFlags )
402{
403 GetPropertyGrid()->m_permanentValidationFailureBehavior = vfbFlags;
404}
405
406// -----------------------------------------------------------------------
407
408wxPGProperty* wxPropertyGridInterface::GetPropertyByNameA( const wxString& name ) const
409{
410 wxPGProperty* p = GetPropertyByName(name);
411 wxASSERT_MSG(p,wxString::Format(wxT("no property with name '%s'"),name.c_str()));
412 return p;
413}
414
415// ----------------------------------------------------------------------------
416
417wxPGProperty* wxPropertyGridInterface::GetPropertyByLabel( const wxString& label ) const
418{
419 wxPGVIterator it;
420
421 for ( it = GetVIterator( wxPG_ITERATE_PROPERTIES ); !it.AtEnd(); it.Next() )
422 {
423 if ( it.GetProperty()->GetLabel() == label )
424 return it.GetProperty();
425 }
426
427 return wxNullProperty;
428}
429
430// ----------------------------------------------------------------------------
431
432void wxPropertyGridInterface::DoSetPropertyAttribute( wxPGPropArg id, const wxString& name,
433 wxVariant& value, long argFlags )
434{
435 wxPG_PROP_ARG_CALL_PROLOG()
436
437 p->SetAttribute( name, value );
438
439 if ( argFlags & wxPG_RECURSE )
440 {
441 unsigned int i;
442 for ( i = 0; i < p->GetChildCount(); i++ )
443 DoSetPropertyAttribute(p->Item(i), name, value, argFlags);
444 }
445}
446
447// -----------------------------------------------------------------------
448
3c26d11b
JS
449void wxPropertyGridInterface::SetPropertyAttributeAll( const wxString& attrName,
450 wxVariant value )
451{
452 unsigned int pageIndex = 0;
453
454 for (;;)
455 {
456 wxPropertyGridPageState* page = GetPageState(pageIndex);
457 if ( !page ) break;
458
459 DoSetPropertyAttribute(page->DoGetRoot(), attrName, value, wxPG_RECURSE);
460
461 pageIndex++;
462 }
463}
464
465// -----------------------------------------------------------------------
466
1c4293cb
VZ
467void wxPropertyGridInterface::GetPropertiesWithFlag( wxArrayPGProperty* targetArr,
468 wxPGProperty::FlagType flags,
469 bool inverse,
470 int iterFlags ) const
471{
472 wxASSERT( targetArr );
473 wxPGVIterator it = GetVIterator( iterFlags );
474
475 for ( ;
476 !it.AtEnd();
477 it.Next() )
478 {
479 const wxPGProperty* property = it.GetProperty();
480
481 if ( !inverse )
482 {
483 if ( (property->GetFlags() & flags) == flags )
484 targetArr->push_back((wxPGProperty*)property);
485 }
486 else
487 {
488 if ( (property->GetFlags() & flags) != flags )
489 targetArr->push_back((wxPGProperty*)property);
490 }
491 }
492}
493
494// -----------------------------------------------------------------------
495
1c4293cb
VZ
496void wxPropertyGridInterface::SetBoolChoices( const wxString& trueChoice,
497 const wxString& falseChoice )
498{
499 wxPGGlobalVars->m_boolChoices[0] = falseChoice;
500 wxPGGlobalVars->m_boolChoices[1] = trueChoice;
501}
502
503// -----------------------------------------------------------------------
504
1c4293cb
VZ
505wxPGProperty* wxPropertyGridInterface::DoGetPropertyByName( const wxString& name ) const
506{
507 return m_pState->BaseGetPropertyByName(name);
508}
509
510// -----------------------------------------------------------------------
511
512wxPGProperty* wxPropertyGridInterface::GetPropertyByName( const wxString& name,
513 const wxString& subname ) const
514{
515 wxPGProperty* p = DoGetPropertyByName(name);
516 if ( !p || !p->GetChildCount() )
517 return wxNullProperty;
518
519 return p->GetPropertyByName(subname);
520}
521
522// -----------------------------------------------------------------------
523
524// Since GetPropertyByName is used *a lot*, this makes sense
525// since non-virtual method can be called with less code.
526wxPGProperty* wxPropertyGridInterface::GetPropertyByName( const wxString& name ) const
527{
528 wxPGProperty* p = DoGetPropertyByName(name);
529 if ( p )
530 return p;
531
532 // Check if its "Property.SubProperty" format
533 int pos = name.Find(wxT('.'));
534 if ( pos <= 0 )
535 return NULL;
536
537 return GetPropertyByName(name.substr(0,pos),
538 name.substr(pos+1,name.length()-pos-1));
539}
540
541// -----------------------------------------------------------------------
542
543bool wxPropertyGridInterface::HideProperty( wxPGPropArg id, bool hide, int flags )
544{
545 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
546
547 wxPropertyGrid* pg = m_pState->GetGrid();
548
549 if ( pg == p->GetGrid() )
550 return pg->DoHideProperty(p, hide, flags);
551 else
552 m_pState->DoHideProperty(p, hide, flags);
553
554 return true;
555}
556
557// -----------------------------------------------------------------------
558
559bool wxPropertyGridInterface::Collapse( wxPGPropArg id )
560{
561 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
562 wxPropertyGrid* pg = p->GetGridIfDisplayed();
563 if ( pg )
564 return pg->DoCollapse(p);
565
566 return p->GetParentState()->DoCollapse(p);
567}
568
569// -----------------------------------------------------------------------
570
571bool wxPropertyGridInterface::Expand( wxPGPropArg id )
572{
573 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
574 wxPropertyGrid* pg = p->GetGridIfDisplayed();
575 if ( pg )
576 return pg->DoExpand(p);
577
578 return p->GetParentState()->DoExpand(p);
579}
580
581// -----------------------------------------------------------------------
582
0eb877f2 583void wxPropertyGridInterface::Sort( int flags )
43396981
JS
584{
585 wxPropertyGrid* pg = GetPropertyGrid();
586
01b5ad3b 587 pg->DoClearSelection();
43396981
JS
588
589 unsigned int pageIndex = 0;
590
591 for (;;)
592 {
593 wxPropertyGridPageState* page = GetPageState(pageIndex);
594 if ( !page ) break;
0eb877f2 595 page->DoSort(flags);
43396981
JS
596 pageIndex++;
597 }
598}
599
600// -----------------------------------------------------------------------
601
1c4293cb
VZ
602void wxPropertyGridInterface::SetPropertyLabel( wxPGPropArg id, const wxString& newproplabel )
603{
604 wxPG_PROP_ARG_CALL_PROLOG()
605
606 p->SetLabel( newproplabel );
607
608 wxPropertyGridPageState* state = p->GetParentState();
609 wxPropertyGrid* pg = state->GetGrid();
610
611 if ( pg->HasFlag(wxPG_AUTO_SORT) )
612 pg->SortChildren(p->GetParent());
613
614 if ( pg->GetState() == state )
615 {
616 if ( pg->HasFlag(wxPG_AUTO_SORT) )
617 pg->Refresh();
618 else
619 pg->DrawItem( p );
620 }
621}
622
623// -----------------------------------------------------------------------
624
625bool wxPropertyGridInterface::SetPropertyMaxLength( wxPGPropArg id, int maxLen )
626{
627 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
628
629 wxPropertyGrid* pg = m_pState->GetGrid();
630
631 p->m_maxLen = (short) maxLen;
632
633 // Adjust control if selected currently
634 if ( pg == p->GetGrid() && p == m_pState->GetSelection() )
635 {
636 wxWindow* wnd = pg->GetEditorControl();
637 wxTextCtrl* tc = wxDynamicCast(wnd,wxTextCtrl);
638 if ( tc )
639 tc->SetMaxLength( maxLen );
640 else
641 // Not a text ctrl
642 return false;
643 }
644
645 return true;
646}
647
d7e2b522
JS
648// -----------------------------------------------------------------------
649
e2ca6599
JS
650void
651wxPropertyGridInterface::SetPropertyBackgroundColour( wxPGPropArg id,
652 const wxColour& colour,
653 bool recursively )
654{
655 wxPG_PROP_ARG_CALL_PROLOG()
656 p->SetBackgroundColour( colour, recursively );
657 RefreshProperty( p );
658}
659
660// -----------------------------------------------------------------------
661
662void wxPropertyGridInterface::SetPropertyTextColour( wxPGPropArg id,
663 const wxColour& colour,
664 bool recursively )
665{
666 wxPG_PROP_ARG_CALL_PROLOG()
667 p->SetTextColour( colour, recursively );
668 RefreshProperty( p );
669}
670
671// -----------------------------------------------------------------------
672
673void wxPropertyGridInterface::SetPropertyColoursToDefault( wxPGPropArg id )
674{
675 wxPG_PROP_ARG_CALL_PROLOG()
676
677 p->m_cells.clear();
678}
679
680// -----------------------------------------------------------------------
681
d7e2b522
JS
682void wxPropertyGridInterface::SetPropertyCell( wxPGPropArg id,
683 int column,
684 const wxString& text,
685 const wxBitmap& bitmap,
686 const wxColour& fgCol,
687 const wxColour& bgCol )
688{
689 wxPG_PROP_ARG_CALL_PROLOG()
690
691 wxPGCell& cell = p->GetCell(column);
692 if ( text.length() && text != wxPG_LABEL )
693 cell.SetText(text);
694 if ( bitmap.IsOk() )
695 cell.SetBitmap(bitmap);
696 if ( fgCol != wxNullColour )
697 cell.SetFgCol(fgCol);
698 if ( bgCol != wxNullColour )
699 cell.SetBgCol(bgCol);
700}
701
1c4293cb
VZ
702// -----------------------------------------------------------------------
703// GetPropertyValueAsXXX methods
704
705#define IMPLEMENT_GET_VALUE(T,TRET,BIGNAME,DEFRETVAL) \
706TRET wxPropertyGridInterface::GetPropertyValueAs##BIGNAME( wxPGPropArg id ) const \
707{ \
708 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(DEFRETVAL) \
709 wxVariant value = p->GetValue(); \
710 if ( wxStrcmp(value.GetType(), wxPGTypeName_##T) != 0 ) \
711 { \
712 wxPGGetFailed(p,wxPGTypeName_##T); \
713 return (TRET)DEFRETVAL; \
714 } \
715 return (TRET)value.Get##BIGNAME(); \
716}
717
718// String is different than others.
719wxString wxPropertyGridInterface::GetPropertyValueAsString( wxPGPropArg id ) const
720{
721 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(wxEmptyString)
722 return p->GetValueAsString(wxPG_FULL_VALUE);
723}
724
725bool wxPropertyGridInterface::GetPropertyValueAsBool( wxPGPropArg id ) const
726{
727 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
728 wxVariant value = p->GetValue();
729 if ( wxStrcmp(value.GetType(), wxPGTypeName_bool) == 0 )
730 {
731 return value.GetBool();
732 }
733 if ( wxStrcmp(value.GetType(), wxPGTypeName_long) == 0 )
734 {
735 return value.GetLong()?true:false;
736 }
737 wxPGGetFailed(p,wxPGTypeName_bool);
738 return false;
739}
740
741IMPLEMENT_GET_VALUE(long,long,Long,0)
742IMPLEMENT_GET_VALUE(double,double,Double,0.0)
1c4293cb 743
1c4293cb
VZ
744bool wxPropertyGridInterface::IsPropertyExpanded( wxPGPropArg id ) const
745{
746 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
747 return p->IsExpanded();
748}
749
750// -----------------------------------------------------------------------
751// wxPropertyGridInterface wrappers
752// -----------------------------------------------------------------------
753
754bool wxPropertyGridInterface::ChangePropertyValue( wxPGPropArg id, wxVariant newValue )
755{
756 return GetPropertyGrid()->ChangePropertyValue(id, newValue);
757}
758
759// -----------------------------------------------------------------------
760
761void wxPropertyGridInterface::BeginAddChildren( wxPGPropArg id )
762{
763 wxPG_PROP_ARG_CALL_PROLOG()
764 wxCHECK_RET( p->HasFlag(wxPG_PROP_AGGREGATE), wxT("only call on properties with fixed children") );
765 p->ClearFlag(wxPG_PROP_AGGREGATE);
766 p->SetFlag(wxPG_PROP_MISC_PARENT);
767}
768
769// -----------------------------------------------------------------------
770
771bool wxPropertyGridInterface::EditorValidate()
772{
773 return GetPropertyGrid()->DoEditorValidate();
774}
775
776// -----------------------------------------------------------------------
777
778void wxPropertyGridInterface::EndAddChildren( wxPGPropArg id )
779{
780 wxPG_PROP_ARG_CALL_PROLOG()
781 wxCHECK_RET( p->HasFlag(wxPG_PROP_MISC_PARENT), wxT("only call on properties for which BeginAddChildren was called prior") );
782 p->ClearFlag(wxPG_PROP_MISC_PARENT);
783 p->SetFlag(wxPG_PROP_AGGREGATE);
784}
785
786// -----------------------------------------------------------------------
787// wxPGVIterator_State
788// -----------------------------------------------------------------------
789
790// Default returned by wxPropertyGridInterface::GetVIterator().
791class wxPGVIteratorBase_State : public wxPGVIteratorBase
792{
793public:
794 wxPGVIteratorBase_State( wxPropertyGridPageState* state, int flags )
795 {
796 m_it.Init( state, flags );
797 }
798 virtual ~wxPGVIteratorBase_State() { }
799 virtual void Next() { m_it.Next(); }
800};
801
802wxPGVIterator wxPropertyGridInterface::GetVIterator( int flags ) const
803{
804 return wxPGVIterator( new wxPGVIteratorBase_State( m_pState, flags ) );
805}
806
807// -----------------------------------------------------------------------
808// wxPGEditableState related functions
809// -----------------------------------------------------------------------
810
811// EscapeDelimiters() changes ";" into "\;" and "|" into "\|"
812// in the input string. This is an internal functions which is
813// used for saving states
814// NB: Similar function exists in aui/framemanager.cpp
815static wxString EscapeDelimiters(const wxString& s)
816{
817 wxString result;
818 result.Alloc(s.length());
819 const wxChar* ch = s.c_str();
820 while (*ch)
821 {
822 if (*ch == wxT(';') || *ch == wxT('|') || *ch == wxT(','))
823 result += wxT('\\');
824 result += *ch;
825 ++ch;
826 }
827 return result;
828}
829
830wxString wxPropertyGridInterface::SaveEditableState( int includedStates ) const
831{
832 wxString result;
833
834 //
835 // Save state on page basis
3c26d11b 836 unsigned int pageIndex = 0;
1c4293cb 837 wxArrayPtrVoid pageStates;
3c26d11b
JS
838
839 for (;;)
1c4293cb 840 {
3c26d11b
JS
841 wxPropertyGridPageState* page = GetPageState(pageIndex);
842 if ( !page ) break;
843
844 pageStates.Add(page);
845
846 pageIndex++;
1c4293cb
VZ
847 }
848
849 for ( pageIndex=0; pageIndex < pageStates.size(); pageIndex++ )
850 {
851 wxPropertyGridPageState* pageState = (wxPropertyGridPageState*) pageStates[pageIndex];
852
853 if ( includedStates & SelectionState )
854 {
855 wxString sel;
856 if ( pageState->GetSelection() )
857 sel = pageState->GetSelection()->GetName();
858 result += wxS("selection=");
859 result += EscapeDelimiters(sel);
860 result += wxS(";");
861 }
862 if ( includedStates & ExpandedState )
863 {
864 wxArrayPGProperty ptrs;
03647350 865 wxPropertyGridConstIterator it =
1c4293cb
VZ
866 wxPropertyGridConstIterator( pageState,
867 wxPG_ITERATE_ALL_PARENTS_RECURSIVELY|wxPG_ITERATE_HIDDEN,
868 wxNullProperty );
869
870 result += wxS("expanded=");
871
872 for ( ;
873 !it.AtEnd();
874 it.Next() )
875 {
876 const wxPGProperty* p = it.GetProperty();
877
878 if ( !p->HasFlag(wxPG_PROP_COLLAPSED) )
879 result += EscapeDelimiters(p->GetName());
b7bc9d80 880 result += wxS(",");
1c4293cb
VZ
881
882 }
883
884 if ( result.Last() == wxS(',') )
885 result.RemoveLast();
886
887 result += wxS(";");
888 }
889 if ( includedStates & ScrollPosState )
890 {
891 int x, y;
892 GetPropertyGrid()->GetViewStart(&x,&y);
893 result += wxString::Format(wxS("scrollpos=%i,%i;"), x, y);
894 }
895 if ( includedStates & SplitterPosState )
896 {
897 result += wxS("splitterpos=");
898
899 for ( size_t i=0; i<pageState->GetColumnCount(); i++ )
900 result += wxString::Format(wxS("%i,"), pageState->DoGetSplitterPosition(i));
901
902 result.RemoveLast(); // Remove last comma
903 result += wxS(";");
904 }
905 if ( includedStates & PageState )
906 {
907 result += wxS("ispageselected=");
908
909 if ( GetPageState(-1) == pageState )
910 result += wxS("1;");
911 else
912 result += wxS("0;");
913 }
62805170
JS
914 if ( includedStates & DescBoxState )
915 {
916 wxVariant v = GetEditableStateItem(wxS("descboxheight"));
72eb964f
JS
917 if ( !v.IsNull() )
918 result += wxString::Format(wxS("descboxheight=%i;"), (int)v.GetLong());
62805170 919 }
1c4293cb
VZ
920 result.RemoveLast(); // Remove last semicolon
921 result += wxS("|");
922 }
923
924 // Remove last '|'
925 if ( result.length() )
926 result.RemoveLast();
927
928 return result;
929}
930
931bool wxPropertyGridInterface::RestoreEditableState( const wxString& src, int restoreStates )
932{
933 wxPropertyGrid* pg = GetPropertyGrid();
934 wxPGProperty* newSelection = NULL;
935 size_t pageIndex;
936 long vx = -1;
937 long vy = -1;
938 long selectedPage = -1;
939 bool pgSelectionSet = false;
940 bool res = true;
941
942 pg->Freeze();
943 wxArrayString pageStrings = ::wxSplit(src, wxS('|'), wxS('\\'));
944
945 for ( pageIndex=0; pageIndex<pageStrings.size(); pageIndex++ )
946 {
947 wxPropertyGridPageState* pageState = GetPageState(pageIndex);
948 if ( !pageState )
949 break;
950
951 wxArrayString kvpairStrings = ::wxSplit(pageStrings[pageIndex], wxS(';'), wxS('\\'));
952
953 for ( size_t i=0; i<kvpairStrings.size(); i++ )
954 {
955 const wxString& kvs = kvpairStrings[i];
956 int eq_pos = kvs.Find(wxS('='));
957 if ( eq_pos != wxNOT_FOUND )
958 {
959 wxString key = kvs.substr(0, eq_pos);
960 wxString value = kvs.substr(eq_pos+1);
961
962 // Further split value by commas
963 wxArrayString values = ::wxSplit(value, wxS(','), wxS('\\'));
964
965 if ( key == wxS("expanded") )
966 {
967 if ( restoreStates & ExpandedState )
968 {
03647350 969 wxPropertyGridIterator it =
1c4293cb
VZ
970 wxPropertyGridIterator( pageState,
971 wxPG_ITERATE_ALL,
972 wxNullProperty );
973
974 // First collapse all
975 for ( ; !it.AtEnd(); it.Next() )
976 {
977 wxPGProperty* p = it.GetProperty();
978 pageState->DoCollapse(p);
979 }
980
981 // Then expand those which names are in values
982 for ( size_t n=0; n<values.size(); n++ )
983 {
984 const wxString& name = values[n];
985 wxPGProperty* prop = GetPropertyByName(name);
986 if ( prop )
987 pageState->DoExpand(prop);
988 }
989 }
990 }
991 else if ( key == wxS("scrollpos") )
992 {
993 if ( restoreStates & ScrollPosState )
994 {
995 if ( values.size() == 2 )
996 {
997 values[0].ToLong(&vx);
998 values[1].ToLong(&vy);
999 }
1000 else
1001 {
1002 res = false;
1003 }
1004 }
1005 }
1006 else if ( key == wxS("splitterpos") )
1007 {
1008 if ( restoreStates & SplitterPosState )
1009 {
1010 for ( size_t n=1; n<values.size(); n++ )
1011 {
1012 long pos = 0;
1013 values[n].ToLong(&pos);
1014 if ( pos > 0 )
1015 pageState->DoSetSplitterPosition(pos, n);
1016 }
1017 }
1018 }
1019 else if ( key == wxS("selection") )
1020 {
1021 if ( restoreStates & SelectionState )
1022 {
1023 if ( values.size() > 0 )
1024 {
1025 if ( pageState->IsDisplayed() )
1026 {
1027 if ( values[0].length() )
1028 newSelection = GetPropertyByName(value);
1029 pgSelectionSet = true;
1030 }
1031 else
1032 {
1033 if ( values[0].length() )
fc72fab6 1034 pageState->DoSetSelection(GetPropertyByName(value));
1c4293cb
VZ
1035 else
1036 pageState->DoClearSelection();
1037 }
1038 }
1039 }
1040 }
1041 else if ( key == wxS("ispageselected") )
1042 {
1043 if ( restoreStates & PageState )
1044 {
1045 long pageSelStatus;
1046 if ( values.size() == 1 && values[0].ToLong(&pageSelStatus) )
1047 {
1048 if ( pageSelStatus )
1049 selectedPage = pageIndex;
1050 }
1051 else
1052 {
62805170
JS
1053 res = false;
1054 }
1055 }
1056 }
1057 else if ( key == wxS("descboxheight") )
1058 {
1059 if ( restoreStates & DescBoxState )
1060 {
1061 long descBoxHeight;
1062 if ( values.size() == 1 && values[0].ToLong(&descBoxHeight) )
1063 {
1064 SetEditableStateItem(wxS("descboxheight"), descBoxHeight);
1065 }
1066 else
1067 {
1c4293cb
VZ
1068 res = false;
1069 }
1070 }
1071 }
1072 else
1073 {
1074 res = false;
1075 }
1076 }
1077 }
1078 }
1079
1080 //
1081 // Force recalculation of virtual heights of all pages
1082 // (may be needed on unclean source string).
1083 pageIndex = 0;
1084 wxPropertyGridPageState* pageState = GetPageState(pageIndex);
1085 while ( pageState )
1086 {
1087 pageState->VirtualHeightChanged();
1088 pageIndex += 1;
1089 pageState = GetPageState(pageIndex);
1090 }
1091
1092 pg->Thaw();
1093
1094 //
1095 // Selection of visible grid page must be set after Thaw() call
1096 if ( pgSelectionSet )
1097 {
1098 if ( newSelection )
01b5ad3b 1099 pg->DoSelectProperty(newSelection);
1c4293cb 1100 else
01b5ad3b 1101 pg->DoClearSelection();
1c4293cb
VZ
1102 }
1103
1104 if ( selectedPage != -1 )
1105 {
1106 DoSelectPage(selectedPage);
1107 }
1108
1109 if ( vx >= 0 )
1110 {
1111 pg->Scroll(vx, vy);
1112 }
1113
1114 return res;
1115}
1116
f4bc1aa2
JS
1117#endif // wxUSE_PROPGRID
1118