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