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