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