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