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