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