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