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