Fixed bug: SetPropertyValueUnspecified(p) and p->SetValue(wxNullVariant) were out...
[wxWidgets.git] / include / wx / propgrid / propgridpagestate.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/propgrid/propgridpagestate.h
3 // Purpose: wxPropertyGridPageState class
4 // Author: Jaakko Salli
5 // Modified by:
6 // Created: 2008-08-24
7 // RCS-ID: $Id$
8 // Copyright: (c) Jaakko Salli
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _WX_PROPGRID_PROPGRIDPAGESTATE_H_
13 #define _WX_PROPGRID_PROPGRIDPAGESTATE_H_
14
15 #if wxUSE_PROPGRID
16
17 #include "wx/propgrid/property.h"
18
19 // -----------------------------------------------------------------------
20
21 /** @section propgrid_hittestresult wxPropertyGridHitTestResult
22
23 A return value from wxPropertyGrid::HitTest(),
24 contains all you need to know about an arbitrary location on the grid.
25 */
26 struct WXDLLIMPEXP_PROPGRID wxPropertyGridHitTestResult
27 {
28 friend class wxPropertyGridPageState;
29 public:
30
31 wxPGProperty* GetProperty() const { return property; }
32
33 /** Column. -1 for margin. */
34 int column;
35
36 /** Index of splitter hit, -1 for none. */
37 int splitter;
38
39 /** If splitter hit, offset to that */
40 int splitterHitOffset;
41
42 private:
43 /** Property. NULL if empty space below properties was hit */
44 wxPGProperty* property;
45 };
46
47 // -----------------------------------------------------------------------
48
49 #define wxPG_IT_CHILDREN(A) ((A)<<16)
50
51 /** @section propgrid_iterator_flags wxPropertyGridIterator Flags
52 @{
53
54 NOTES: At lower 16-bits, there are flags to check if item will be included.
55 At higher 16-bits, there are same flags, but to instead check if children
56 will be included.
57 */
58
59 enum wxPG_ITERATOR_FLAGS
60 {
61
62 /**
63 Iterate through 'normal' property items (does not include children of
64 aggregate or hidden items by default).
65 */
66 wxPG_ITERATE_PROPERTIES = wxPG_PROP_PROPERTY |
67 wxPG_PROP_MISC_PARENT |
68 wxPG_PROP_AGGREGATE |
69 wxPG_PROP_COLLAPSED |
70 wxPG_IT_CHILDREN(wxPG_PROP_MISC_PARENT) |
71 wxPG_IT_CHILDREN(wxPG_PROP_CATEGORY),
72
73 /** Iterate children of collapsed parents, and individual items that are hidden.
74 */
75 wxPG_ITERATE_HIDDEN = wxPG_PROP_HIDDEN |
76 wxPG_IT_CHILDREN(wxPG_PROP_COLLAPSED),
77
78 /**
79 Iterate children of parent that is an aggregate property (ie has fixed
80 children).
81 */
82 wxPG_ITERATE_FIXED_CHILDREN = wxPG_IT_CHILDREN(wxPG_PROP_AGGREGATE) |
83 wxPG_ITERATE_PROPERTIES,
84
85 /** Iterate categories.
86 Note that even without this flag, children of categories are still iterated
87 through.
88 */
89 wxPG_ITERATE_CATEGORIES = wxPG_PROP_CATEGORY |
90 wxPG_IT_CHILDREN(wxPG_PROP_CATEGORY) |
91 wxPG_PROP_COLLAPSED,
92
93 wxPG_ITERATE_ALL_PARENTS = wxPG_PROP_MISC_PARENT |
94 wxPG_PROP_AGGREGATE |
95 wxPG_PROP_CATEGORY,
96
97 wxPG_ITERATE_ALL_PARENTS_RECURSIVELY = wxPG_ITERATE_ALL_PARENTS |
98 wxPG_IT_CHILDREN(
99 wxPG_ITERATE_ALL_PARENTS),
100
101 wxPG_ITERATOR_FLAGS_ALL = wxPG_PROP_PROPERTY |
102 wxPG_PROP_MISC_PARENT |
103 wxPG_PROP_AGGREGATE |
104 wxPG_PROP_HIDDEN |
105 wxPG_PROP_CATEGORY |
106 wxPG_PROP_COLLAPSED,
107
108 wxPG_ITERATOR_MASK_OP_ITEM = wxPG_ITERATOR_FLAGS_ALL,
109
110 // (wxPG_PROP_MISC_PARENT|wxPG_PROP_AGGREGATE|wxPG_PROP_CATEGORY)
111 wxPG_ITERATOR_MASK_OP_PARENT = wxPG_ITERATOR_FLAGS_ALL,
112
113 /** Combines all flags needed to iterate through visible properties
114 (ie hidden properties and children of collapsed parents are skipped).
115 */
116 wxPG_ITERATE_VISIBLE = wxPG_ITERATE_PROPERTIES |
117 wxPG_PROP_CATEGORY |
118 wxPG_IT_CHILDREN(wxPG_PROP_AGGREGATE),
119
120 /** Iterate all items.
121 */
122 wxPG_ITERATE_ALL = wxPG_ITERATE_VISIBLE |
123 wxPG_ITERATE_HIDDEN,
124
125 /** Iterate through individual properties (ie categories and children of
126 aggregate properties are skipped).
127 */
128 wxPG_ITERATE_NORMAL = wxPG_ITERATE_PROPERTIES |
129 wxPG_ITERATE_HIDDEN,
130
131 /** Default iterator flags.
132 */
133 wxPG_ITERATE_DEFAULT = wxPG_ITERATE_NORMAL
134
135 };
136
137 /** @}
138 */
139
140
141 #define wxPG_ITERATOR_CREATE_MASKS(FLAGS, A, B) \
142 A = (FLAGS ^ wxPG_ITERATOR_MASK_OP_ITEM) & \
143 wxPG_ITERATOR_MASK_OP_ITEM & 0xFFFF; \
144 B = ((FLAGS>>16) ^ wxPG_ITERATOR_MASK_OP_PARENT) & \
145 wxPG_ITERATOR_MASK_OP_PARENT & 0xFFFF;
146
147
148 // Macro to test if children of PWC should be iterated through
149 #define wxPG_ITERATOR_PARENTEXMASK_TEST(PWC, PARENTMASK) \
150 ( \
151 !(PWC->GetFlags() & PARENTMASK) && \
152 PWC->GetChildCount() \
153 )
154
155
156 // Base for wxPropertyGridIterator classes.
157 class WXDLLIMPEXP_PROPGRID wxPropertyGridIteratorBase
158 {
159 public:
160 wxPropertyGridIteratorBase()
161 {
162 }
163
164 void Assign( const wxPropertyGridIteratorBase& it );
165
166 bool AtEnd() const { return m_property == NULL; }
167
168 /** Get current property.
169 */
170 wxPGProperty* GetProperty() const { return m_property; }
171
172 void Init( wxPropertyGridPageState* state,
173 int flags,
174 wxPGProperty* property,
175 int dir = 1 );
176
177 void Init( wxPropertyGridPageState* state,
178 int flags,
179 int startPos = wxTOP,
180 int dir = 0 );
181
182 /** Iterate to the next property.
183 */
184 void Next( bool iterateChildren = true );
185
186 /** Iterate to the previous property.
187 */
188 void Prev();
189
190 /**
191 Set base parent, ie a property when, in which iteration returns, it
192 ends.
193
194 Default base parent is the root of the used wxPropertyGridPageState.
195 */
196 void SetBaseParent( wxPGProperty* baseParent )
197 { m_baseParent = baseParent; }
198
199 protected:
200
201 wxPGProperty* m_property;
202
203 private:
204 wxPropertyGridPageState* m_state;
205 wxPGProperty* m_baseParent;
206
207 // Masks are used to quickly exclude items
208 int m_itemExMask;
209 int m_parentExMask;
210 };
211
212
213 #define wxPG_IMPLEMENT_ITERATOR(CLASS, PROPERTY, STATE) \
214 CLASS( STATE* state, int flags = wxPG_ITERATE_DEFAULT, \
215 PROPERTY* property = NULL, int dir = 1 ) \
216 : wxPropertyGridIteratorBase() \
217 { Init( (wxPropertyGridPageState*)state, flags, \
218 (wxPGProperty*)property, dir ); } \
219 CLASS( STATE* state, int flags, int startPos, int dir = 0 ) \
220 : wxPropertyGridIteratorBase() \
221 { Init( (wxPropertyGridPageState*)state, flags, startPos, dir ); } \
222 CLASS() \
223 : wxPropertyGridIteratorBase() \
224 { \
225 m_property = NULL; \
226 } \
227 CLASS( const CLASS& it ) \
228 : wxPropertyGridIteratorBase( ) \
229 { \
230 Assign(it); \
231 } \
232 ~CLASS() \
233 { \
234 } \
235 const CLASS& operator=( const CLASS& it ) \
236 { \
237 if (this != &it) \
238 Assign(it); \
239 return *this; \
240 } \
241 CLASS& operator++() { Next(); return *this; } \
242 CLASS operator++(int) { CLASS it=*this;Next();return it; } \
243 CLASS& operator--() { Prev(); return *this; } \
244 CLASS operator--(int) { CLASS it=*this;Prev();return it; } \
245 PROPERTY* operator *() const { return (PROPERTY*)m_property; } \
246 static PROPERTY* OneStep( STATE* state, \
247 int flags = wxPG_ITERATE_DEFAULT, \
248 PROPERTY* property = NULL, \
249 int dir = 1 ) \
250 { \
251 CLASS it( state, flags, property, dir ); \
252 if ( property ) \
253 { \
254 if ( dir == 1 ) it.Next(); \
255 else it.Prev(); \
256 } \
257 return *it; \
258 }
259
260
261 /** @class wxPropertyGridIterator
262
263 Preferable way to iterate through contents of wxPropertyGrid,
264 wxPropertyGridManager, and wxPropertyGridPage.
265
266 See wxPropertyGridInterface::GetIterator() for more information about usage.
267
268 @library{wxpropgrid}
269 @category{propgrid}
270 */
271 class WXDLLIMPEXP_PROPGRID
272 wxPropertyGridIterator : public wxPropertyGridIteratorBase
273 {
274 public:
275
276 wxPG_IMPLEMENT_ITERATOR(wxPropertyGridIterator,
277 wxPGProperty,
278 wxPropertyGridPageState)
279
280 protected:
281 };
282
283
284 // Const version of wxPropertyGridIterator.
285 class WXDLLIMPEXP_PROPGRID
286 wxPropertyGridConstIterator : public wxPropertyGridIteratorBase
287 {
288 public:
289 wxPG_IMPLEMENT_ITERATOR(wxPropertyGridConstIterator,
290 const wxPGProperty,
291 const wxPropertyGridPageState)
292
293 /**
294 Additional copy constructor.
295 */
296 wxPropertyGridConstIterator( const wxPropertyGridIterator& other )
297 {
298 Assign(other);
299 }
300
301 /**
302 Additional assignment operator.
303 */
304 const wxPropertyGridConstIterator& operator=( const wxPropertyGridIterator& it )
305 {
306 Assign(it);
307 return *this;
308 }
309
310 protected:
311 };
312
313 // -----------------------------------------------------------------------
314
315 /** Base class to derive new viterators.
316 */
317 class WXDLLIMPEXP_PROPGRID wxPGVIteratorBase
318 {
319 friend class wxPGVIterator;
320 public:
321 wxPGVIteratorBase() { m_refCount = 1; }
322 virtual void Next() = 0;
323 void IncRef()
324 {
325 m_refCount++;
326 }
327 void DecRef()
328 {
329 m_refCount--;
330 if ( m_refCount <= 0 )
331 delete this;
332 }
333 protected:
334 virtual ~wxPGVIteratorBase() { }
335
336 wxPropertyGridIterator m_it;
337 private:
338 int m_refCount;
339 };
340
341 /** @class wxPGVIterator
342
343 Abstract implementation of a simple iterator. Can only be used
344 to iterate in forward order, and only through the entire container.
345 Used to have functions dealing with all properties work with both
346 wxPropertyGrid and wxPropertyGridManager.
347 */
348 class WXDLLIMPEXP_PROPGRID wxPGVIterator
349 {
350 public:
351 wxPGVIterator() { m_pIt = NULL; }
352 wxPGVIterator( wxPGVIteratorBase* obj ) { m_pIt = obj; }
353 ~wxPGVIterator() { UnRef(); }
354 void UnRef() { if (m_pIt) m_pIt->DecRef(); }
355 wxPGVIterator( const wxPGVIterator& it )
356 {
357 m_pIt = it.m_pIt;
358 m_pIt->IncRef();
359 }
360 #ifndef SWIG
361 const wxPGVIterator& operator=( const wxPGVIterator& it )
362 {
363 if (this != &it)
364 {
365 UnRef();
366 m_pIt = it.m_pIt;
367 m_pIt->IncRef();
368 }
369 return *this;
370 }
371 #endif
372 void Next() { m_pIt->Next(); }
373 bool AtEnd() const { return m_pIt->m_it.AtEnd(); }
374 wxPGProperty* GetProperty() const { return m_pIt->m_it.GetProperty(); }
375 protected:
376 wxPGVIteratorBase* m_pIt;
377 };
378
379 // -----------------------------------------------------------------------
380
381 #ifndef SWIG
382 // We won't need this class from wxPython
383
384 /** @class wxPropertyGridPageState
385
386 Contains low-level property page information (properties, column widths,
387 etc) of a single wxPropertyGrid or single wxPropertyGridPage. Generally you
388 should not use this class directly, but instead member functions in
389 wxPropertyGridInterface, wxPropertyGrid, wxPropertyGridPage, and
390 wxPropertyGridManager.
391
392 @remarks
393 - In separate wxPropertyGrid component this class was known as
394 wxPropertyGridState.
395 - Currently this class is not implemented in wxPython.
396
397 @library{wxpropgrid}
398 @category{propgrid}
399 */
400 class WXDLLIMPEXP_PROPGRID wxPropertyGridPageState
401 {
402 friend class wxPGProperty;
403 friend class wxPropertyGrid;
404 friend class wxPGCanvas;
405 friend class wxPropertyGridInterface;
406 friend class wxPropertyGridPage;
407 friend class wxPropertyGridManager;
408 public:
409
410 /** Default constructor. */
411 wxPropertyGridPageState();
412
413 /** Destructor. */
414 virtual ~wxPropertyGridPageState();
415
416 /** Makes sure all columns have minimum width.
417 */
418 void CheckColumnWidths( int widthChange = 0 );
419
420 /**
421 Override this member function to add custom behavior on property
422 deletion.
423 */
424 virtual void DoDelete( wxPGProperty* item, bool doDelete = true );
425
426 wxSize DoFitColumns( bool allowGridResize = false );
427
428 wxPGProperty* DoGetItemAtY( int y ) const;
429
430 /**
431 Override this member function to add custom behavior on property
432 insertion.
433 */
434 virtual wxPGProperty* DoInsert( wxPGProperty* parent,
435 int index,
436 wxPGProperty* property );
437
438 /**
439 This needs to be overridden in grid used the manager so that splitter
440 changes can be propagated to other pages.
441 */
442 virtual void DoSetSplitterPosition( int pos,
443 int splitterColumn = 0,
444 bool allPages = false,
445 bool fromAutoCenter = false );
446
447 bool EnableCategories( bool enable );
448
449 /** Make sure virtual height is up-to-date.
450 */
451 void EnsureVirtualHeight()
452 {
453 if ( m_vhCalcPending )
454 {
455 RecalculateVirtualHeight();
456 m_vhCalcPending = 0;
457 }
458 }
459
460 /** Enables or disables given property and its subproperties. */
461 bool DoEnableProperty( wxPGProperty* p, bool enable );
462
463 /** Returns (precalculated) height of contained visible properties.
464 */
465 unsigned int GetVirtualHeight() const
466 {
467 wxASSERT( !m_vhCalcPending );
468 return m_virtualHeight;
469 }
470
471 /** Returns (precalculated) height of contained visible properties.
472 */
473 unsigned int GetVirtualHeight()
474 {
475 EnsureVirtualHeight();
476 return m_virtualHeight;
477 }
478
479 /** Returns actual height of contained visible properties.
480 @remarks
481 Mostly used for internal diagnostic purposes.
482 */
483 inline unsigned int GetActualVirtualHeight() const;
484
485 unsigned int GetColumnCount() const
486 {
487 return (unsigned int) m_colWidths.size();
488 }
489
490 wxPGProperty* GetSelection() const
491 {
492 return m_selected;
493 }
494
495 int GetColumnMinWidth( int column ) const;
496
497 int GetColumnWidth( unsigned int column ) const
498 {
499 return m_colWidths[column];
500 }
501
502 wxPropertyGrid* GetGrid() const { return m_pPropGrid; }
503
504 /** Returns last item which could be iterated using given flags.
505 @param flags
506 @link iteratorflags List of iterator flags@endlink
507 */
508 wxPGProperty* GetLastItem( int flags = wxPG_ITERATE_DEFAULT );
509
510 const wxPGProperty* GetLastItem( int flags = wxPG_ITERATE_DEFAULT ) const
511 {
512 return ((wxPropertyGridPageState*)this)->GetLastItem(flags);
513 }
514
515 wxPropertyCategory* GetPropertyCategory( const wxPGProperty* p ) const;
516
517 wxPGProperty* GetPropertyByLabel( const wxString& name,
518 wxPGProperty* parent = NULL ) const;
519
520 wxVariant DoGetPropertyValues( const wxString& listname,
521 wxPGProperty* baseparent,
522 long flags ) const;
523
524 wxPGProperty* DoGetRoot() const { return m_properties; }
525
526 void DoSetPropertyName( wxPGProperty* p, const wxString& newName );
527
528 // Returns combined width of margin and all the columns
529 int GetVirtualWidth() const
530 {
531 return m_width;
532 }
533
534 /**
535 Returns minimal width for given column so that all images and texts
536 will fit entirely.
537
538 Used by SetSplitterLeft() and DoFitColumns().
539 */
540 int GetColumnFitWidth(wxClientDC& dc,
541 wxPGProperty* pwc,
542 unsigned int col,
543 bool subProps) const;
544
545 /** Returns information about arbitrary position in the grid.
546
547 wxPropertyGridHitTestResult definition:
548 @code
549 struct wxPropertyGridHitTestResult
550 {
551 wxPGProperty* GetProperty() const;
552
553 // column. -1 for margin
554 int column;
555
556 // Index of splitter hit, -1 for none.
557 int splitter;
558
559 // If splitter hit, then offset to that.
560 int splitterHitOffset;
561 };
562 @endcode
563 */
564 wxPropertyGridHitTestResult HitTest( const wxPoint& pt ) const;
565
566 /** Returns true if page is visibly displayed.
567 */
568 inline bool IsDisplayed() const;
569
570 bool IsInNonCatMode() const { return (bool)(m_properties == m_abcArray); }
571
572 /** Only inits arrays, doesn't migrate things or such. */
573 void InitNonCatMode ();
574
575 void DoLimitPropertyEditing( wxPGProperty* p, bool limit = true )
576 {
577 p->SetFlagRecursively(wxPG_PROP_NOEDITOR, limit);
578 }
579
580 bool DoSelectProperty( wxPGProperty* p, unsigned int flags = 0 );
581
582 /** widthChange is non-client.
583 */
584 void OnClientWidthChange( int newWidth,
585 int widthChange,
586 bool fromOnResize = false );
587
588 /** Recalculates m_virtualHeight.
589 */
590 void RecalculateVirtualHeight()
591 {
592 m_virtualHeight = GetActualVirtualHeight();
593 }
594
595 void SetColumnCount( int colCount );
596
597 void PropagateColSizeDec( int column, int decrease, int dir );
598
599 bool DoHideProperty( wxPGProperty* p, bool hide, int flags = wxPG_RECURSE );
600
601 bool DoSetPropertyValueString( wxPGProperty* p, const wxString& value );
602
603 bool DoSetPropertyValue( wxPGProperty* p, wxVariant& value );
604
605 bool DoSetPropertyValueWxObjectPtr( wxPGProperty* p, wxObject* value );
606 void DoSetPropertyValues( const wxVariantList& list,
607 wxPGProperty* default_category );
608
609 void SetSplitterLeft( bool subProps = false );
610
611 /** Set virtual width for this particular page. */
612 void SetVirtualWidth( int width );
613
614 void DoSortChildren( wxPGProperty* p, int flags = 0 );
615 void DoSort( int flags = 0 );
616
617 bool PrepareAfterItemsAdded();
618
619 void SetSelection( wxPGProperty* p ) { m_selected = p; }
620
621 /** Called after virtual height needs to be recalculated.
622 */
623 void VirtualHeightChanged()
624 {
625 m_vhCalcPending = 1;
626 }
627
628 /** Base append. */
629 wxPGProperty* DoAppend( wxPGProperty* property );
630
631 /** Returns property by its name. */
632 wxPGProperty* BaseGetPropertyByName( const wxString& name ) const;
633
634 void DoClearSelection()
635 {
636 m_selected = NULL;
637 }
638
639 /** Called in, for example, wxPropertyGrid::Clear. */
640 void DoClear();
641
642 bool DoCollapse( wxPGProperty* p );
643
644 bool DoExpand( wxPGProperty* p );
645
646 void CalculateFontAndBitmapStuff( int vspacing );
647
648 protected:
649
650 int DoGetSplitterPosition( int splitterIndex = 0 ) const;
651
652 /** Returns column at x coordinate (in GetGrid()->GetPanel()).
653 @param pSplitterHit
654 Give pointer to int that receives index to splitter that is at x.
655 @param pSplitterHitOffset
656 Distance from said splitter.
657 */
658 int HitTestH( int x, int* pSplitterHit, int* pSplitterHitOffset ) const;
659
660 bool PrepareToAddItem( wxPGProperty* property,
661 wxPGProperty* scheduledParent );
662
663 /** If visible, then this is pointer to wxPropertyGrid.
664 This shall *never* be NULL to indicate that this state is not visible.
665 */
666 wxPropertyGrid* m_pPropGrid;
667
668 /** Pointer to currently used array. */
669 wxPGProperty* m_properties;
670
671 /** Array for categoric mode. */
672 wxPGRootProperty m_regularArray;
673
674 /** Array for root of non-categoric mode. */
675 wxPGRootProperty* m_abcArray;
676
677 /** Dictionary for name-based access. */
678 wxPGHashMapS2P m_dictName;
679
680 /** List of column widths (first column does not include margin). */
681 wxArrayInt m_colWidths;
682
683 double m_fSplitterX;
684
685 /** Most recently added category. */
686 wxPropertyCategory* m_currentCategory;
687
688 /** Pointer to selected property. */
689 wxPGProperty* m_selected;
690
691 /** Virtual width. */
692 int m_width;
693
694 /** Indicates total virtual height of visible properties. */
695 unsigned int m_virtualHeight;
696
697 /** 1 if m_lastCaption is also the bottommost caption. */
698 unsigned char m_lastCaptionBottomnest;
699
700 /** 1 items appended/inserted, so stuff needs to be done before drawing;
701 If m_virtualHeight == 0, then calcylatey's must be done.
702 Otherwise just sort.
703 */
704 unsigned char m_itemsAdded;
705
706 /** 1 if any value is modified. */
707 unsigned char m_anyModified;
708
709 unsigned char m_vhCalcPending;
710 };
711
712 #endif // #ifndef SWIG
713
714 // -----------------------------------------------------------------------
715
716 #endif // wxUSE_PROPGRID
717
718 #endif // _WX_PROPGRID_PROPGRIDPAGESTATE_H_
719