Allow reparenting wxPropertyGrid(Manager) to work; Show error and suggest calling...
[wxWidgets.git] / src / propgrid / manager.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/propgrid/manager.cpp
3 // Purpose: wxPropertyGridManager
4 // Author: Jaakko Salli
5 // Modified by:
6 // Created: 2005-01-14
7 // RCS-ID: $Id$
8 // Copyright: (c) Jaakko Salli
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_PROPGRID
20
21 #ifndef WX_PRECOMP
22 #include "wx/defs.h"
23 #include "wx/object.h"
24 #include "wx/hash.h"
25 #include "wx/string.h"
26 #include "wx/log.h"
27 #include "wx/event.h"
28 #include "wx/window.h"
29 #include "wx/panel.h"
30 #include "wx/dc.h"
31 #include "wx/pen.h"
32 #include "wx/brush.h"
33 #include "wx/cursor.h"
34 #include "wx/settings.h"
35 #include "wx/textctrl.h"
36 #include "wx/sizer.h"
37 #include "wx/statusbr.h"
38 #include "wx/intl.h"
39 #endif
40
41 // This define is necessary to prevent macro clearing
42 #define __wxPG_SOURCE_FILE__
43
44 #include "wx/propgrid/propgrid.h"
45
46 #include "wx/propgrid/manager.h"
47
48
49 #define wxPG_MAN_ALTERNATE_BASE_ID 11249 // Needed for wxID_ANY madnesss
50
51
52 // -----------------------------------------------------------------------
53
54 // For wxMSW cursor consistency, we must do mouse capturing even
55 // when using custom controls
56
57 #define BEGIN_MOUSE_CAPTURE \
58 if ( !(m_iFlags & wxPG_FL_MOUSE_CAPTURED) ) \
59 { \
60 CaptureMouse(); \
61 m_iFlags |= wxPG_FL_MOUSE_CAPTURED; \
62 }
63
64 #define END_MOUSE_CAPTURE \
65 if ( m_iFlags & wxPG_FL_MOUSE_CAPTURED ) \
66 { \
67 ReleaseMouse(); \
68 m_iFlags &= ~(wxPG_FL_MOUSE_CAPTURED); \
69 }
70
71 // -----------------------------------------------------------------------
72 // wxPropertyGridManager
73 // -----------------------------------------------------------------------
74
75 const char wxPropertyGridManagerNameStr[] = "wxPropertyGridManager";
76
77
78 // Categoric Mode Icon
79 static const char* gs_xpm_catmode[] = {
80 "16 16 5 1",
81 ". c none",
82 "B c black",
83 "D c #868686",
84 "L c #CACACA",
85 "W c #FFFFFF",
86 ".DDD............",
87 ".DLD.BBBBBB.....",
88 ".DDD............",
89 ".....DDDDD.DDD..",
90 "................",
91 ".....DDDDD.DDD..",
92 "................",
93 ".....DDDDD.DDD..",
94 "................",
95 ".....DDDDD.DDD..",
96 "................",
97 ".DDD............",
98 ".DLD.BBBBBB.....",
99 ".DDD............",
100 ".....DDDDD.DDD..",
101 "................"
102 };
103
104 // Alphabetic Mode Icon
105 static const char* gs_xpm_noncatmode[] = {
106 "16 16 5 1",
107 ". c none",
108 "B c black",
109 "D c #868686",
110 "L c #000080",
111 "W c #FFFFFF",
112 "..DBD...DDD.DDD.",
113 ".DB.BD..........",
114 ".BBBBB..DDD.DDD.",
115 ".B...B..........",
116 "...L....DDD.DDD.",
117 "...L............",
118 ".L.L.L..DDD.DDD.",
119 "..LLL...........",
120 "...L....DDD.DDD.",
121 "................",
122 ".BBBBB..DDD.DDD.",
123 "....BD..........",
124 "...BD...DDD.DDD.",
125 "..BD............",
126 ".BBBBB..DDD.DDD.",
127 "................"
128 };
129
130 // Default Page Icon.
131 static const char* gs_xpm_defpage[] = {
132 "16 16 5 1",
133 ". c none",
134 "B c black",
135 "D c #868686",
136 "L c #000080",
137 "W c #FFFFFF",
138 "................",
139 "................",
140 "..BBBBBBBBBBBB..",
141 "..B..........B..",
142 "..B.BB.LLLLL.B..",
143 "..B..........B..",
144 "..B.BB.LLLLL.B..",
145 "..B..........B..",
146 "..B.BB.LLLLL.B..",
147 "..B..........B..",
148 "..B.BB.LLLLL.B..",
149 "..B..........B..",
150 "..BBBBBBBBBBBB..",
151 "................",
152 "................",
153 "................"
154 };
155
156 // -----------------------------------------------------------------------
157 // wxPropertyGridPage
158 // -----------------------------------------------------------------------
159
160
161 IMPLEMENT_CLASS(wxPropertyGridPage, wxEvtHandler)
162
163
164 BEGIN_EVENT_TABLE(wxPropertyGridPage, wxEvtHandler)
165 END_EVENT_TABLE()
166
167
168 wxPropertyGridPage::wxPropertyGridPage()
169 : wxEvtHandler(), wxPropertyGridInterface(), wxPropertyGridPageState()
170 {
171 m_pState = this; // wxPropertyGridInterface to point to State
172 m_manager = NULL;
173 m_isDefault = false;
174 }
175
176 wxPropertyGridPage::~wxPropertyGridPage()
177 {
178 }
179
180 void wxPropertyGridPage::Clear()
181 {
182 GetStatePtr()->DoClear();
183 }
184
185 wxSize wxPropertyGridPage::FitColumns()
186 {
187 wxSize sz = DoFitColumns();
188 return sz;
189 }
190
191 void wxPropertyGridPage::RefreshProperty( wxPGProperty* p )
192 {
193 if ( m_manager )
194 m_manager->RefreshProperty(p);
195 }
196
197 void wxPropertyGridPage::OnShow()
198 {
199 }
200
201 void wxPropertyGridPage::SetSplitterPosition( int splitterPos, int col )
202 {
203 wxPropertyGrid* pg = GetGrid();
204 if ( pg->GetState() == this )
205 pg->SetSplitterPosition(splitterPos);
206 else
207 DoSetSplitterPosition(splitterPos, col, false);
208 }
209
210 void wxPropertyGridPage::DoSetSplitterPosition( int pos,
211 int splitterColumn,
212 bool allPages,
213 bool fromAutoCenter )
214 {
215 if ( allPages && m_manager->GetPageCount() )
216 m_manager->SetSplitterPosition( pos, splitterColumn );
217 else
218 wxPropertyGridPageState::DoSetSplitterPosition( pos,
219 splitterColumn,
220 allPages,
221 fromAutoCenter );
222 }
223
224 // -----------------------------------------------------------------------
225 // wxPropertyGridManager
226 // -----------------------------------------------------------------------
227
228 // Final default splitter y is client height minus this.
229 #define wxPGMAN_DEFAULT_NEGATIVE_SPLITTER_Y 100
230
231 // -----------------------------------------------------------------------
232
233 IMPLEMENT_CLASS(wxPropertyGridManager, wxPanel)
234
235 #define ID_ADVTOOLBAR_OFFSET 1
236 #define ID_ADVHELPCAPTION_OFFSET 2
237 #define ID_ADVHELPCONTENT_OFFSET 3
238 //#define ID_ADVBUTTON_OFFSET 4
239 #define ID_ADVTBITEMSBASE_OFFSET 5 // Must be last.
240
241 // -----------------------------------------------------------------------
242
243 BEGIN_EVENT_TABLE(wxPropertyGridManager, wxPanel)
244 EVT_MOTION(wxPropertyGridManager::OnMouseMove)
245 EVT_SIZE(wxPropertyGridManager::OnResize)
246 EVT_PAINT(wxPropertyGridManager::OnPaint)
247 EVT_LEFT_DOWN(wxPropertyGridManager::OnMouseClick)
248 EVT_LEFT_UP(wxPropertyGridManager::OnMouseUp)
249 EVT_LEAVE_WINDOW(wxPropertyGridManager::OnMouseEntry)
250 //EVT_ENTER_WINDOW(wxPropertyGridManager::OnMouseEntry)
251 END_EVENT_TABLE()
252
253 // -----------------------------------------------------------------------
254
255 wxPropertyGridManager::wxPropertyGridManager()
256 : wxPanel()
257 {
258 Init1();
259 }
260
261 // -----------------------------------------------------------------------
262
263 wxPropertyGridManager::wxPropertyGridManager( wxWindow *parent,
264 wxWindowID id,
265 const wxPoint& pos,
266 const wxSize& size,
267 long style,
268 const wxString& name )
269 : wxPanel()
270 {
271 Init1();
272 Create(parent,id,pos,size,style,name);
273 }
274
275 // -----------------------------------------------------------------------
276
277 bool wxPropertyGridManager::Create( wxWindow *parent,
278 wxWindowID id,
279 const wxPoint& pos,
280 const wxSize& size,
281 long style,
282 const wxString& name )
283 {
284 if ( !m_pPropGrid )
285 m_pPropGrid = CreatePropertyGrid();
286
287 bool res = wxPanel::Create( parent, id, pos, size,
288 (style&0xFFFF0000)|wxWANTS_CHARS,
289 name );
290 Init2(style);
291
292 return res;
293 }
294
295 // -----------------------------------------------------------------------
296
297 //
298 // Initialize values to defaults
299 //
300 void wxPropertyGridManager::Init1()
301 {
302
303 m_pPropGrid = NULL;
304
305 #if wxUSE_TOOLBAR
306 m_pToolbar = NULL;
307 #endif
308 m_pTxtHelpCaption = NULL;
309 m_pTxtHelpContent = NULL;
310
311 m_emptyPage = NULL;
312
313 m_selPage = -1;
314
315 m_width = m_height = 0;
316
317 m_splitterHeight = 5;
318
319 m_splitterY = -1; // -1 causes default to be set.
320
321 m_nextDescBoxSize = -1;
322
323 m_extraHeight = 0;
324 m_dragStatus = 0;
325 m_onSplitter = 0;
326 m_iFlags = 0;
327 }
328
329 // -----------------------------------------------------------------------
330
331 // These flags are always used in wxPropertyGrid integrated in wxPropertyGridManager.
332 #ifndef __WXMAC__
333 #define wxPG_MAN_PROPGRID_FORCED_FLAGS (wxSIMPLE_BORDER| \
334 wxNO_FULL_REPAINT_ON_RESIZE| \
335 wxCLIP_CHILDREN)
336 #else
337 #define wxPG_MAN_PROPGRID_FORCED_FLAGS (wxNO_BORDER| \
338 wxNO_FULL_REPAINT_ON_RESIZE| \
339 wxCLIP_CHILDREN)
340 #endif
341
342 // Which flags can be passed to underlying wxPropertyGrid.
343 #define wxPG_MAN_PASS_FLAGS_MASK (0xFFF0|wxTAB_TRAVERSAL)
344
345 //
346 // Initialize after parent etc. set
347 //
348 void wxPropertyGridManager::Init2( int style )
349 {
350
351 if ( m_iFlags & wxPG_FL_INITIALIZED )
352 return;
353
354 m_windowStyle |= (style&0x0000FFFF);
355
356 wxSize csz = GetClientSize();
357
358 m_cursorSizeNS = wxCursor(wxCURSOR_SIZENS);
359
360 // Prepare the first page
361 // NB: But just prepare - you still need to call Add/InsertPage
362 // to actually add properties on it.
363 wxPropertyGridPage* pd = new wxPropertyGridPage();
364 pd->m_isDefault = true;
365 pd->m_manager = this;
366 wxPropertyGridPageState* state = pd->GetStatePtr();
367 state->m_pPropGrid = m_pPropGrid;
368 m_arrPages.push_back( pd );
369 m_pPropGrid->m_pState = state;
370
371 wxWindowID baseId = GetId();
372 wxWindowID useId = baseId;
373 if ( baseId < 0 )
374 baseId = wxPG_MAN_ALTERNATE_BASE_ID;
375
376 m_baseId = baseId;
377
378 #ifdef __WXMAC__
379 // Smaller controls on Mac
380 SetWindowVariant(wxWINDOW_VARIANT_SMALL);
381 #endif
382
383 // Create propertygrid.
384 m_pPropGrid->Create(this,baseId,wxPoint(0,0),csz,
385 (m_windowStyle&wxPG_MAN_PASS_FLAGS_MASK)
386 |wxPG_MAN_PROPGRID_FORCED_FLAGS);
387
388 m_pPropGrid->m_eventObject = this;
389
390 m_pPropGrid->SetId(useId);
391
392 m_pPropGrid->m_iFlags |= wxPG_FL_IN_MANAGER;
393
394 m_pState = m_pPropGrid->m_pState;
395
396 m_pPropGrid->SetExtraStyle(wxPG_EX_INIT_NOCAT);
397
398 m_nextTbInd = baseId+ID_ADVTBITEMSBASE_OFFSET + 2;
399
400
401 // Connect to property grid onselect event.
402 // NB: Even if wxID_ANY is used, this doesn't connect properly in wxPython
403 // (see wxPropertyGridManager::ProcessEvent).
404 Connect(m_pPropGrid->GetId()/*wxID_ANY*/,
405 wxEVT_PG_SELECTED,
406 wxPropertyGridEventHandler(wxPropertyGridManager::OnPropertyGridSelect) );
407
408 // Connect to toolbar button events.
409 Connect(baseId+ID_ADVTBITEMSBASE_OFFSET,baseId+ID_ADVTBITEMSBASE_OFFSET+50,
410 wxEVT_COMMAND_TOOL_CLICKED,
411 wxCommandEventHandler(wxPropertyGridManager::OnToolbarClick) );
412
413 // Optional initial controls.
414 m_width = -12345;
415
416 m_iFlags |= wxPG_FL_INITIALIZED;
417
418 }
419
420 // -----------------------------------------------------------------------
421
422 wxPropertyGridManager::~wxPropertyGridManager()
423 {
424 END_MOUSE_CAPTURE
425
426 m_pPropGrid->DoSelectProperty(NULL);
427 m_pPropGrid->m_pState = NULL;
428
429 size_t i;
430 for ( i=0; i<m_arrPages.size(); i++ )
431 {
432 delete m_arrPages[i];
433 }
434
435 delete m_emptyPage;
436 }
437
438 // -----------------------------------------------------------------------
439
440 wxPropertyGrid* wxPropertyGridManager::CreatePropertyGrid() const
441 {
442 return new wxPropertyGrid();
443 }
444
445 // -----------------------------------------------------------------------
446
447 void wxPropertyGridManager::SetId( wxWindowID winid )
448 {
449 wxWindow::SetId(winid);
450
451 // TODO: Reconnect propgrid event handler(s).
452
453 m_pPropGrid->SetId(winid);
454 }
455
456 // -----------------------------------------------------------------------
457
458 wxSize wxPropertyGridManager::DoGetBestSize() const
459 {
460 return wxSize(60,150);
461 }
462
463 // -----------------------------------------------------------------------
464
465 bool wxPropertyGridManager::SetFont( const wxFont& font )
466 {
467 bool res = wxWindow::SetFont(font);
468 m_pPropGrid->SetFont(font);
469
470 // TODO: Need to do caption recacalculations for other pages as well.
471 unsigned int i;
472 for ( i=0; i<m_arrPages.size(); i++ )
473 {
474 wxPropertyGridPage* page = GetPage(i);
475
476 if ( page != m_pPropGrid->GetState() )
477 page->CalculateFontAndBitmapStuff(-1);
478 }
479
480 return res;
481 }
482
483 // -----------------------------------------------------------------------
484
485 void wxPropertyGridManager::SetExtraStyle( long exStyle )
486 {
487 wxWindow::SetExtraStyle( exStyle );
488 m_pPropGrid->SetExtraStyle( exStyle & 0xFFFFF000 );
489 #if wxUSE_TOOLBAR
490 if ( (exStyle & wxPG_EX_NO_FLAT_TOOLBAR) && m_pToolbar )
491 RecreateControls();
492 #endif
493 }
494
495 // -----------------------------------------------------------------------
496
497 void wxPropertyGridManager::Freeze()
498 {
499 m_pPropGrid->Freeze();
500 wxWindow::Freeze();
501 }
502
503 // -----------------------------------------------------------------------
504
505 void wxPropertyGridManager::Thaw()
506 {
507 wxWindow::Thaw();
508 m_pPropGrid->Thaw();
509 }
510
511 // -----------------------------------------------------------------------
512
513 void wxPropertyGridManager::SetWindowStyleFlag( long style )
514 {
515 int oldWindowStyle = GetWindowStyleFlag();
516
517 wxWindow::SetWindowStyleFlag( style );
518 m_pPropGrid->SetWindowStyleFlag( (m_pPropGrid->GetWindowStyleFlag()&~(wxPG_MAN_PASS_FLAGS_MASK)) |
519 (style&wxPG_MAN_PASS_FLAGS_MASK) );
520
521 // Need to re-position windows?
522 if ( (oldWindowStyle & (wxPG_TOOLBAR|wxPG_DESCRIPTION)) !=
523 (style & (wxPG_TOOLBAR|wxPG_DESCRIPTION)) )
524 {
525 RecreateControls();
526 }
527 }
528
529 // -----------------------------------------------------------------------
530
531 bool wxPropertyGridManager::Reparent( wxWindowBase *newParent )
532 {
533 if ( m_pPropGrid )
534 m_pPropGrid->OnTLPChanging((wxWindow*)newParent);
535
536 bool res = wxPanel::Reparent(newParent);
537
538 return res;
539 }
540
541 // -----------------------------------------------------------------------
542
543 // Actually shows given page.
544 bool wxPropertyGridManager::DoSelectPage( int index )
545 {
546 // -1 means no page was selected
547 //wxASSERT( m_selPage >= 0 );
548
549 wxCHECK_MSG( index >= -1 && index < (int)GetPageCount(),
550 false,
551 wxT("invalid page index") );
552
553 if ( m_selPage == index )
554 return true;
555
556 if ( m_pPropGrid->m_selected )
557 {
558 if ( !m_pPropGrid->ClearSelection() )
559 return false;
560 }
561
562 wxPropertyGridPage* prevPage;
563
564 if ( m_selPage >= 0 )
565 prevPage = GetPage(m_selPage);
566 else
567 prevPage = m_emptyPage;
568
569 wxPropertyGridPage* nextPage;
570
571 if ( index >= 0 )
572 {
573 nextPage = m_arrPages[index];
574
575 nextPage->OnShow();
576 }
577 else
578 {
579 if ( !m_emptyPage )
580 {
581 m_emptyPage = new wxPropertyGridPage();
582 m_emptyPage->m_pPropGrid = m_pPropGrid;
583 }
584
585 nextPage = m_emptyPage;
586 }
587
588 m_iFlags |= wxPG_FL_DESC_REFRESH_REQUIRED;
589
590 m_pPropGrid->SwitchState( nextPage->GetStatePtr() );
591
592 m_pState = m_pPropGrid->m_pState;
593
594 m_selPage = index;
595
596 #if wxUSE_TOOLBAR
597 if ( m_pToolbar )
598 {
599 if ( index >= 0 )
600 m_pToolbar->ToggleTool( nextPage->m_id, true );
601 else
602 m_pToolbar->ToggleTool( prevPage->m_id, false );
603 }
604 #endif
605
606 return true;
607 }
608
609 // -----------------------------------------------------------------------
610
611 // Changes page *and* set the target page for insertion operations.
612 void wxPropertyGridManager::SelectPage( int index )
613 {
614 DoSelectPage(index);
615 }
616
617 // -----------------------------------------------------------------------
618
619 int wxPropertyGridManager::GetPageByName( const wxString& name ) const
620 {
621 size_t i;
622 for ( i=0; i<GetPageCount(); i++ )
623 {
624 if ( m_arrPages[i]->m_label == name )
625 return i;
626 }
627 return wxNOT_FOUND;
628 }
629
630 // -----------------------------------------------------------------------
631
632 int wxPropertyGridManager::GetPageByState( const wxPropertyGridPageState* pState ) const
633 {
634 wxASSERT( pState );
635
636 size_t i;
637 for ( i=0; i<GetPageCount(); i++ )
638 {
639 if ( pState == m_arrPages[i]->GetStatePtr() )
640 return i;
641 }
642
643 return wxNOT_FOUND;
644 }
645
646 // -----------------------------------------------------------------------
647
648 const wxString& wxPropertyGridManager::GetPageName( int index ) const
649 {
650 wxASSERT( index >= 0 && index < (int)GetPageCount() );
651 return m_arrPages[index]->m_label;
652 }
653
654 // -----------------------------------------------------------------------
655
656 wxPropertyGridPageState* wxPropertyGridManager::GetPageState( int page ) const
657 {
658 // Do not change this into wxCHECK because returning NULL is important
659 // for wxPropertyGridInterface page enumeration mechanics.
660 if ( page >= (int)GetPageCount() )
661 return NULL;
662
663 if ( page == -1 )
664 return m_pState;
665 return m_arrPages[page];
666 }
667
668 // -----------------------------------------------------------------------
669
670 void wxPropertyGridManager::Clear()
671 {
672 m_pPropGrid->ClearSelection(false);
673
674 m_pPropGrid->Freeze();
675
676 int i;
677 for ( i=(int)GetPageCount()-1; i>=0; i-- )
678 RemovePage(i);
679
680 // Reset toolbar ids
681 m_nextTbInd = m_baseId+ID_ADVTBITEMSBASE_OFFSET + 2;
682
683 m_pPropGrid->Thaw();
684 }
685
686 // -----------------------------------------------------------------------
687
688 void wxPropertyGridManager::ClearPage( int page )
689 {
690 wxASSERT( page >= 0 );
691 wxASSERT( page < (int)GetPageCount() );
692
693 if ( page >= 0 && page < (int)GetPageCount() )
694 {
695 wxPropertyGridPageState* state = m_arrPages[page];
696
697 if ( state == m_pPropGrid->GetState() )
698 m_pPropGrid->Clear();
699 else
700 state->DoClear();
701 }
702 }
703
704 // -----------------------------------------------------------------------
705
706 int wxPropertyGridManager::GetColumnCount( int page ) const
707 {
708 wxASSERT( page >= -1 );
709 wxASSERT( page < (int)GetPageCount() );
710
711 return GetPageState(page)->GetColumnCount();
712 }
713
714 // -----------------------------------------------------------------------
715
716 void wxPropertyGridManager::SetColumnCount( int colCount, int page )
717 {
718 wxASSERT( page >= -1 );
719 wxASSERT( page < (int)GetPageCount() );
720
721 GetPageState(page)->SetColumnCount( colCount );
722 GetGrid()->Refresh();
723 }
724 // -----------------------------------------------------------------------
725
726 size_t wxPropertyGridManager::GetPageCount() const
727 {
728 if ( !(m_iFlags & wxPG_MAN_FL_PAGE_INSERTED) )
729 return 0;
730
731 return m_arrPages.size();
732 }
733
734 // -----------------------------------------------------------------------
735
736 wxPropertyGridPage* wxPropertyGridManager::InsertPage( int index,
737 const wxString& label,
738 const wxBitmap& bmp,
739 wxPropertyGridPage* pageObj )
740 {
741 if ( index < 0 )
742 index = GetPageCount();
743
744 wxCHECK_MSG( (size_t)index == GetPageCount(), NULL,
745 wxT("wxPropertyGridManager currently only supports appending pages (due to wxToolBar limitation)."));
746
747 bool needInit = true;
748 bool isPageInserted = m_iFlags & wxPG_MAN_FL_PAGE_INSERTED ? true : false;
749
750 wxASSERT( index == 0 || isPageInserted );
751
752 if ( !pageObj )
753 {
754 // No custom page object was given, so we will either re-use the default base
755 // page (if index==0), or create a new default page object.
756 if ( !isPageInserted )
757 {
758 pageObj = GetPage(0);
759 // Of course, if the base page was custom, we need to delete and
760 // re-create it.
761 if ( !pageObj->m_isDefault )
762 {
763 delete pageObj;
764 pageObj = new wxPropertyGridPage();
765 m_arrPages[0] = pageObj;
766 }
767 needInit = false;
768 }
769 else
770 {
771 pageObj = new wxPropertyGridPage();
772 }
773 pageObj->m_isDefault = true;
774 }
775 else
776 {
777 if ( !isPageInserted )
778 {
779 // Initial page needs to be deleted and replaced
780 delete GetPage(0);
781 m_arrPages[0] = pageObj;
782 m_pPropGrid->m_pState = pageObj->GetStatePtr();
783 }
784 }
785
786 wxPropertyGridPageState* state = pageObj->GetStatePtr();
787
788 pageObj->m_manager = this;
789
790 if ( needInit )
791 {
792 state->m_pPropGrid = m_pPropGrid;
793 state->InitNonCatMode();
794 }
795
796 if ( label.length() )
797 {
798 wxASSERT_MSG( !pageObj->m_label.length(),
799 wxT("If page label is given in constructor, empty label must be given in AddPage"));
800 pageObj->m_label = label;
801 }
802
803 pageObj->m_id = m_nextTbInd;
804
805 if ( isPageInserted )
806 m_arrPages.push_back( pageObj );
807
808 #if wxUSE_TOOLBAR
809 if ( m_windowStyle & wxPG_TOOLBAR )
810 {
811 if ( !m_pToolbar )
812 RecreateControls();
813
814 if ( !(GetExtraStyle()&wxPG_EX_HIDE_PAGE_BUTTONS) )
815 {
816 wxASSERT( m_pToolbar );
817
818 // Add separator before first page.
819 if ( GetPageCount() < 2 && (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) &&
820 m_pToolbar->GetToolsCount() < 3 )
821 m_pToolbar->AddSeparator();
822
823 if ( &bmp != &wxNullBitmap )
824 m_pToolbar->AddTool(m_nextTbInd,label,bmp,label,wxITEM_RADIO);
825 //m_pToolbar->InsertTool(index+3,m_nextTbInd,bmp);
826 else
827 m_pToolbar->AddTool(m_nextTbInd,label,wxBitmap( (const char**)gs_xpm_defpage ),
828 label,wxITEM_RADIO);
829
830 m_nextTbInd++;
831
832 m_pToolbar->Realize();
833 }
834 }
835 #else
836 wxUnusedVar(bmp);
837 #endif
838
839 // If selected page was above the point of insertion, fix the current page index
840 if ( isPageInserted )
841 {
842 if ( m_selPage >= index )
843 {
844 m_selPage += 1;
845 }
846 }
847 else
848 {
849 // Set this value only when adding the first page
850 m_selPage = 0;
851 }
852
853 pageObj->Init();
854
855 m_iFlags |= wxPG_MAN_FL_PAGE_INSERTED;
856
857 wxASSERT( pageObj->GetGrid() );
858
859 return pageObj;
860 }
861
862 // -----------------------------------------------------------------------
863
864 bool wxPropertyGridManager::IsAnyModified() const
865 {
866 size_t i;
867 for ( i=0; i<GetPageCount(); i++ )
868 {
869 if ( m_arrPages[i]->GetStatePtr()->m_anyModified )
870 return true;
871 }
872 return false;
873 }
874
875 // -----------------------------------------------------------------------
876
877 bool wxPropertyGridManager::IsPageModified( size_t index ) const
878 {
879 if ( m_arrPages[index]->GetStatePtr()->m_anyModified )
880 return true;
881 return false;
882 }
883
884 // -----------------------------------------------------------------------
885
886 wxPGProperty* wxPropertyGridManager::GetPageRoot( int index ) const
887 {
888 wxASSERT( index >= 0 );
889 wxASSERT( index < (int)m_arrPages.size() );
890
891 return m_arrPages[index]->GetStatePtr()->m_properties;
892 }
893
894 // -----------------------------------------------------------------------
895
896 bool wxPropertyGridManager::RemovePage( int page )
897 {
898 wxCHECK_MSG( (page >= 0) && (page < (int)GetPageCount()),
899 false,
900 wxT("invalid page index") );
901
902 wxPropertyGridPage* pd = m_arrPages[page];
903
904 if ( m_arrPages.size() == 1 )
905 {
906 // Last page: do not remove page entry
907 m_pPropGrid->Clear();
908 m_selPage = -1;
909 m_iFlags &= ~wxPG_MAN_FL_PAGE_INSERTED;
910 pd->m_label.clear();
911 }
912
913 // Change selection if current is page
914 else if ( page == m_selPage )
915 {
916 if ( !m_pPropGrid->ClearSelection() )
917 return false;
918
919 // Substitute page to select
920 int substitute = page - 1;
921 if ( substitute < 0 )
922 substitute = page + 1;
923
924 SelectPage(substitute);
925 }
926
927 // Remove toolbar icon
928 #if wxUSE_TOOLBAR
929 if ( HasFlag(wxPG_TOOLBAR) )
930 {
931 wxASSERT( m_pToolbar );
932
933 int toolPos = GetExtraStyle() & wxPG_EX_MODE_BUTTONS ? 3 : 0;
934 toolPos += page;
935
936 // Delete separator as well, for consistency
937 if ( (GetExtraStyle() & wxPG_EX_MODE_BUTTONS) &&
938 GetPageCount() == 1 )
939 m_pToolbar->DeleteToolByPos(2);
940
941 m_pToolbar->DeleteToolByPos(toolPos);
942 }
943 #endif
944
945 if ( m_arrPages.size() > 1 )
946 {
947 m_arrPages.erase(m_arrPages.begin() + page);
948 delete pd;
949 }
950
951 // Adjust indexes that were above removed
952 if ( m_selPage > page )
953 m_selPage--;
954
955 return true;
956 }
957
958 // -----------------------------------------------------------------------
959
960 bool wxPropertyGridManager::ProcessEvent( wxEvent& event )
961 {
962 int evtType = event.GetEventType();
963
964 // NB: For some reason, under wxPython, Connect in Init doesn't work properly,
965 // so we'll need to call OnPropertyGridSelect manually. Multiple call's
966 // don't really matter.
967 if ( evtType == wxEVT_PG_SELECTED )
968 OnPropertyGridSelect((wxPropertyGridEvent&)event);
969
970 // Property grid events get special attention
971 if ( evtType >= wxPG_BASE_EVT_TYPE &&
972 evtType < (wxPG_MAX_EVT_TYPE) &&
973 m_selPage >= 0 )
974 {
975 wxPropertyGridPage* page = GetPage(m_selPage);
976 wxPropertyGridEvent* pgEvent = wxDynamicCast(&event, wxPropertyGridEvent);
977
978 // Add property grid events to appropriate custom pages
979 // but stop propagating to parent if page says it is
980 // handling everything.
981 if ( pgEvent && !page->m_isDefault )
982 {
983 /*if ( pgEvent->IsPending() )
984 page->AddPendingEvent(event);
985 else*/
986 page->ProcessEvent(event);
987
988 if ( page->IsHandlingAllEvents() )
989 event.StopPropagation();
990 }
991 }
992
993 return wxPanel::ProcessEvent(event);
994 }
995
996 // -----------------------------------------------------------------------
997
998 void wxPropertyGridManager::RepaintDescBoxDecorations( wxDC& dc,
999 int newSplitterY,
1000 int newWidth,
1001 int newHeight )
1002 {
1003 // Draw background
1004 wxColour bgcol = GetBackgroundColour();
1005 dc.SetBrush(bgcol);
1006 dc.SetPen(bgcol);
1007 int rectHeight = m_splitterHeight;
1008 dc.DrawRectangle(0, newSplitterY, newWidth, rectHeight);
1009 dc.SetPen( wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW) );
1010 int splitterBottom = newSplitterY + m_splitterHeight - 1;
1011 int boxHeight = newHeight - splitterBottom;
1012 if ( boxHeight > 1 )
1013 dc.DrawRectangle(0, splitterBottom, newWidth, boxHeight);
1014 else
1015 dc.DrawLine(0, splitterBottom, newWidth, splitterBottom);
1016 }
1017
1018 // -----------------------------------------------------------------------
1019
1020 void wxPropertyGridManager::UpdateDescriptionBox( int new_splittery, int new_width, int new_height )
1021 {
1022 int use_hei = new_height;
1023 use_hei--;
1024
1025 // Fix help control positions.
1026 int cap_hei = m_pPropGrid->m_fontHeight;
1027 int cap_y = new_splittery+m_splitterHeight+5;
1028 int cnt_y = cap_y+cap_hei+3;
1029 int sub_cap_hei = cap_y+cap_hei-use_hei;
1030 int cnt_hei = use_hei-cnt_y;
1031 if ( sub_cap_hei > 0 )
1032 {
1033 cap_hei -= sub_cap_hei;
1034 cnt_hei = 0;
1035 }
1036 if ( cap_hei <= 2 )
1037 {
1038 m_pTxtHelpCaption->Show( false );
1039 m_pTxtHelpContent->Show( false );
1040 }
1041 else
1042 {
1043 m_pTxtHelpCaption->SetSize(3,cap_y,new_width-6,cap_hei);
1044 m_pTxtHelpCaption->Wrap(-1);
1045 m_pTxtHelpCaption->Show( true );
1046 if ( cnt_hei <= 2 )
1047 {
1048 m_pTxtHelpContent->Show( false );
1049 }
1050 else
1051 {
1052 m_pTxtHelpContent->SetSize(3,cnt_y,new_width-6,cnt_hei);
1053 m_pTxtHelpContent->Show( true );
1054 }
1055 }
1056
1057 wxRect r(0, new_splittery, new_width, new_height-new_splittery);
1058 RefreshRect(r);
1059
1060 m_splitterY = new_splittery;
1061
1062 m_iFlags &= ~(wxPG_FL_DESC_REFRESH_REQUIRED);
1063 }
1064
1065 // -----------------------------------------------------------------------
1066
1067 void wxPropertyGridManager::RecalculatePositions( int width, int height )
1068 {
1069 int propgridY = 0;
1070 int propgridBottomY = height;
1071
1072 // Toolbar at the top.
1073 #if wxUSE_TOOLBAR
1074 if ( m_pToolbar )
1075 {
1076 m_pToolbar->SetSize(0, 0, width, -1);
1077 propgridY += m_pToolbar->GetSize().y;
1078 }
1079 #endif
1080
1081 // Help box.
1082 if ( m_pTxtHelpCaption )
1083 {
1084 int new_splittery = m_splitterY;
1085
1086 // Move m_splitterY
1087 if ( ( m_splitterY >= 0 || m_nextDescBoxSize ) && m_height > 32 )
1088 {
1089 if ( m_nextDescBoxSize >= 0 )
1090 {
1091 new_splittery = m_height - m_nextDescBoxSize - m_splitterHeight;
1092 m_nextDescBoxSize = -1;
1093 }
1094 new_splittery += (height-m_height);
1095 }
1096 else
1097 {
1098 new_splittery = height - wxPGMAN_DEFAULT_NEGATIVE_SPLITTER_Y;
1099 if ( new_splittery < 32 )
1100 new_splittery = 32;
1101 }
1102
1103 // Check if beyond minimum.
1104 int nspy_min = propgridY + m_pPropGrid->m_lineHeight;
1105 if ( new_splittery < nspy_min )
1106 new_splittery = nspy_min;
1107
1108 propgridBottomY = new_splittery;
1109
1110 UpdateDescriptionBox( new_splittery, width, height );
1111 }
1112
1113 if ( m_iFlags & wxPG_FL_INITIALIZED )
1114 {
1115 int pgh = propgridBottomY - propgridY;
1116 if ( pgh < 0 )
1117 pgh = 0;
1118 m_pPropGrid->SetSize( 0, propgridY, width, pgh );
1119
1120 m_extraHeight = height - pgh;
1121
1122 m_width = width;
1123 m_height = height;
1124 }
1125 }
1126
1127 // -----------------------------------------------------------------------
1128
1129 void wxPropertyGridManager::SetDescBoxHeight( int ht, bool refresh )
1130 {
1131 if ( m_windowStyle & wxPG_DESCRIPTION )
1132 {
1133 if ( ht != GetDescBoxHeight() )
1134 {
1135 m_nextDescBoxSize = ht;
1136 if ( refresh )
1137 RecalculatePositions(m_width, m_height);
1138 }
1139 }
1140 }
1141
1142 // -----------------------------------------------------------------------
1143
1144 int wxPropertyGridManager::GetDescBoxHeight() const
1145 {
1146 return GetClientSize().y - m_splitterY - m_splitterHeight;
1147 }
1148
1149 // -----------------------------------------------------------------------
1150
1151 void wxPropertyGridManager::OnPaint( wxPaintEvent& WXUNUSED(event) )
1152 {
1153 wxPaintDC dc(this);
1154
1155 // Update everything inside the box
1156 wxRect r = GetUpdateRegion().GetBox();
1157
1158 // Repaint splitter and any other description box decorations
1159 if ( (r.y + r.height) >= m_splitterY )
1160 RepaintDescBoxDecorations( dc, m_splitterY, m_width, m_height );
1161 }
1162
1163 // -----------------------------------------------------------------------
1164
1165 void wxPropertyGridManager::Refresh(bool eraseBackground, const wxRect* rect )
1166 {
1167 m_pPropGrid->Refresh(eraseBackground);
1168 wxWindow::Refresh(eraseBackground,rect);
1169 }
1170
1171 // -----------------------------------------------------------------------
1172
1173 void wxPropertyGridManager::RefreshProperty( wxPGProperty* p )
1174 {
1175 wxPropertyGrid* grid = p->GetGrid();
1176
1177 if ( GetPage(m_selPage)->GetStatePtr() == p->GetParent()->GetParentState() )
1178 grid->RefreshProperty(p);
1179 }
1180
1181 // -----------------------------------------------------------------------
1182
1183 void wxPropertyGridManager::RecreateControls()
1184 {
1185
1186 bool was_shown = IsShown();
1187 if ( was_shown )
1188 Show ( false );
1189
1190 wxWindowID baseId = m_pPropGrid->GetId();
1191 if ( baseId < 0 )
1192 baseId = wxPG_MAN_ALTERNATE_BASE_ID;
1193
1194 #if wxUSE_TOOLBAR
1195 if ( m_windowStyle & wxPG_TOOLBAR )
1196 {
1197 // Has toolbar.
1198 if ( !m_pToolbar )
1199 {
1200 m_pToolbar = new wxToolBar(this,baseId+ID_ADVTOOLBAR_OFFSET,
1201 wxDefaultPosition,wxDefaultSize,
1202 ((GetExtraStyle()&wxPG_EX_NO_FLAT_TOOLBAR)?0:wxTB_FLAT)
1203 /*| wxTB_HORIZONTAL | wxNO_BORDER*/ );
1204 m_pToolbar->SetToolBitmapSize(wxSize(16, 15));
1205
1206 #if defined(__WXMSW__)
1207 // Eliminate toolbar flicker on XP
1208 // NOTE: Not enabled since it corrupts drawing somewhat.
1209
1210 /*
1211 #ifndef WS_EX_COMPOSITED
1212 #define WS_EX_COMPOSITED 0x02000000L
1213 #endif
1214
1215 HWND hWnd = (HWND)m_pToolbar->GetHWND();
1216
1217 ::SetWindowLong( hWnd, GWL_EXSTYLE,
1218 ::GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_COMPOSITED );
1219 */
1220
1221 #endif
1222
1223 m_pToolbar->SetCursor ( *wxSTANDARD_CURSOR );
1224
1225 if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) )
1226 {
1227 wxString desc1(_("Categorized Mode"));
1228 wxString desc2(_("Alphabetic Mode"));
1229 m_pToolbar->AddTool(baseId+ID_ADVTBITEMSBASE_OFFSET+0,
1230 desc1,wxBitmap ( (const char**)gs_xpm_catmode ),
1231 desc1,wxITEM_RADIO);
1232 m_pToolbar->AddTool(baseId+ID_ADVTBITEMSBASE_OFFSET+1,
1233 desc2,wxBitmap ( (const char**)gs_xpm_noncatmode ),
1234 desc2,wxITEM_RADIO);
1235 m_pToolbar->Realize();
1236 }
1237
1238 }
1239
1240 if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) )
1241 {
1242 // Toggle correct mode button.
1243 // TODO: This doesn't work in wxMSW (when changing,
1244 // both items will get toggled).
1245 int toggle_but_on_ind = ID_ADVTBITEMSBASE_OFFSET+0;
1246 int toggle_but_off_ind = ID_ADVTBITEMSBASE_OFFSET+1;
1247 if ( m_pPropGrid->m_pState->IsInNonCatMode() )
1248 {
1249 toggle_but_on_ind++;
1250 toggle_but_off_ind--;
1251 }
1252
1253 m_pToolbar->ToggleTool(baseId+toggle_but_on_ind,true);
1254 m_pToolbar->ToggleTool(baseId+toggle_but_off_ind,false);
1255 }
1256
1257 }
1258 else
1259 {
1260 // No toolbar.
1261 if ( m_pToolbar )
1262 m_pToolbar->Destroy();
1263 m_pToolbar = NULL;
1264 }
1265 #endif
1266
1267 if ( m_windowStyle & wxPG_DESCRIPTION )
1268 {
1269 // Has help box.
1270 m_pPropGrid->m_iFlags |= (wxPG_FL_NOSTATUSBARHELP);
1271
1272 if ( !m_pTxtHelpCaption )
1273 {
1274 m_pTxtHelpCaption = new wxStaticText(this,
1275 baseId+ID_ADVHELPCAPTION_OFFSET,
1276 wxT(""),
1277 wxDefaultPosition,
1278 wxDefaultSize,
1279 wxALIGN_LEFT|wxST_NO_AUTORESIZE);
1280 m_pTxtHelpCaption->SetFont( m_pPropGrid->m_captionFont );
1281 m_pTxtHelpCaption->SetCursor( *wxSTANDARD_CURSOR );
1282 }
1283 if ( !m_pTxtHelpContent )
1284 {
1285 m_pTxtHelpContent = new wxStaticText(this,
1286 baseId+ID_ADVHELPCONTENT_OFFSET,
1287 wxT(""),
1288 wxDefaultPosition,
1289 wxDefaultSize,
1290 wxALIGN_LEFT|wxST_NO_AUTORESIZE);
1291 m_pTxtHelpContent->SetCursor( *wxSTANDARD_CURSOR );
1292 }
1293
1294 SetDescribedProperty(GetSelection());
1295 }
1296 else
1297 {
1298 // No help box.
1299 m_pPropGrid->m_iFlags &= ~(wxPG_FL_NOSTATUSBARHELP);
1300
1301 if ( m_pTxtHelpCaption )
1302 m_pTxtHelpCaption->Destroy();
1303
1304 m_pTxtHelpCaption = NULL;
1305
1306 if ( m_pTxtHelpContent )
1307 m_pTxtHelpContent->Destroy();
1308
1309 m_pTxtHelpContent = NULL;
1310 }
1311
1312 int width, height;
1313
1314 GetClientSize(&width,&height);
1315
1316 RecalculatePositions(width,height);
1317
1318 if ( was_shown )
1319 Show ( true );
1320 }
1321
1322 // -----------------------------------------------------------------------
1323
1324 wxPGProperty* wxPropertyGridManager::DoGetPropertyByName( const wxString& name ) const
1325 {
1326 size_t i;
1327 for ( i=0; i<GetPageCount(); i++ )
1328 {
1329 wxPropertyGridPageState* pState = m_arrPages[i]->GetStatePtr();
1330 wxPGProperty* p = pState->BaseGetPropertyByName(name);
1331 if ( p )
1332 {
1333 return p;
1334 }
1335 }
1336 return NULL;
1337 }
1338
1339 // -----------------------------------------------------------------------
1340
1341 bool wxPropertyGridManager::EnsureVisible( wxPGPropArg id )
1342 {
1343 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
1344
1345 wxPropertyGridPageState* parentState = p->GetParentState();
1346
1347 // Select correct page.
1348 if ( m_pPropGrid->m_pState != parentState )
1349 DoSelectPage( GetPageByState(parentState) );
1350
1351 return m_pPropGrid->EnsureVisible(id);
1352 }
1353
1354 // -----------------------------------------------------------------------
1355
1356 void wxPropertyGridManager::OnToolbarClick( wxCommandEvent &event )
1357 {
1358 int id = event.GetId();
1359 if ( id >= 0 )
1360 {
1361 int baseId = m_pPropGrid->GetId();
1362 if ( baseId < 0 )
1363 baseId = wxPG_MAN_ALTERNATE_BASE_ID;
1364
1365 if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 0 ) )
1366 {
1367 // Categorized mode.
1368 if ( m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES )
1369 {
1370 if ( !m_pPropGrid->HasInternalFlag(wxPG_FL_CATMODE_AUTO_SORT) )
1371 m_pPropGrid->m_windowStyle &= ~wxPG_AUTO_SORT;
1372 m_pPropGrid->EnableCategories( true );
1373 }
1374 }
1375 else if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 1 ) )
1376 {
1377 // Alphabetic mode.
1378 if ( !(m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES) )
1379 {
1380 if ( m_pPropGrid->HasFlag(wxPG_AUTO_SORT) )
1381 m_pPropGrid->SetInternalFlag(wxPG_FL_CATMODE_AUTO_SORT);
1382 else
1383 m_pPropGrid->ClearInternalFlag(wxPG_FL_CATMODE_AUTO_SORT);
1384
1385 m_pPropGrid->m_windowStyle |= wxPG_AUTO_SORT;
1386 m_pPropGrid->EnableCategories( false );
1387 }
1388 }
1389 else
1390 {
1391 // Page Switching.
1392
1393 int index = -1;
1394 size_t i;
1395 wxPropertyGridPage* pdc;
1396
1397 // Find page with given id.
1398 for ( i=0; i<GetPageCount(); i++ )
1399 {
1400 pdc = m_arrPages[i];
1401 if ( pdc->m_id == id )
1402 {
1403 index = i;
1404 break;
1405 }
1406 }
1407
1408 wxASSERT( index >= 0 );
1409
1410 if ( DoSelectPage( index ) )
1411 {
1412
1413 // Event dispatching must be last.
1414 m_pPropGrid->SendEvent( wxEVT_PG_PAGE_CHANGED, NULL );
1415
1416 }
1417 else
1418 {
1419 // TODO: Depress the old button on toolbar.
1420 }
1421
1422 }
1423 }
1424 }
1425
1426 // -----------------------------------------------------------------------
1427
1428 bool wxPropertyGridManager::SetEditableStateItem( const wxString& name, wxVariant value )
1429 {
1430 if ( name == wxS("descboxheight") )
1431 {
1432 SetDescBoxHeight(value.GetLong(), true);
1433 return true;
1434 }
1435 return false;
1436 }
1437
1438 // -----------------------------------------------------------------------
1439
1440 wxVariant wxPropertyGridManager::GetEditableStateItem( const wxString& name ) const
1441 {
1442 if ( name == wxS("descboxheight") )
1443 {
1444 return (long) GetDescBoxHeight();
1445 }
1446 return wxNullVariant;
1447 }
1448
1449 // -----------------------------------------------------------------------
1450
1451 void wxPropertyGridManager::SetDescription( const wxString& label, const wxString& content )
1452 {
1453 if ( m_pTxtHelpCaption )
1454 {
1455 wxSize osz1 = m_pTxtHelpCaption->GetSize();
1456 wxSize osz2 = m_pTxtHelpContent->GetSize();
1457
1458 m_pTxtHelpCaption->SetLabel(label);
1459 m_pTxtHelpContent->SetLabel(content);
1460
1461 m_pTxtHelpCaption->SetSize(-1,osz1.y);
1462 m_pTxtHelpContent->SetSize(-1,osz2.y);
1463
1464 UpdateDescriptionBox( m_splitterY, m_width, m_height );
1465 }
1466 }
1467
1468 // -----------------------------------------------------------------------
1469
1470 void wxPropertyGridManager::SetDescribedProperty( wxPGProperty* p )
1471 {
1472 if ( m_pTxtHelpCaption )
1473 {
1474 if ( p )
1475 {
1476 SetDescription( p->GetLabel(), p->GetHelpString() );
1477 }
1478 else
1479 {
1480 SetDescription( wxEmptyString, wxEmptyString );
1481 }
1482 }
1483 }
1484
1485 // -----------------------------------------------------------------------
1486
1487 void wxPropertyGridManager::SetSplitterLeft( bool subProps, bool allPages )
1488 {
1489 if ( !allPages )
1490 {
1491 m_pPropGrid->SetSplitterLeft(subProps);
1492 }
1493 else
1494 {
1495 wxClientDC dc(this);
1496 dc.SetFont(m_pPropGrid->GetFont());
1497
1498 int highest = 0;
1499 unsigned int i;
1500
1501 for ( i=0; i<GetPageCount(); i++ )
1502 {
1503 int maxW = m_pState->GetColumnFitWidth(dc, m_arrPages[i]->m_properties, 0, subProps );
1504 maxW += m_pPropGrid->m_marginWidth;
1505 if ( maxW > highest )
1506 highest = maxW;
1507 }
1508
1509 if ( highest > 0 )
1510 m_pPropGrid->SetSplitterPosition( highest );
1511
1512 m_pPropGrid->m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER;
1513 }
1514 }
1515
1516 // -----------------------------------------------------------------------
1517
1518 void wxPropertyGridManager::OnPropertyGridSelect( wxPropertyGridEvent& event )
1519 {
1520 // Check id.
1521 wxASSERT_MSG( GetId() == m_pPropGrid->GetId(),
1522 wxT("wxPropertyGridManager id must be set with wxPropertyGridManager::SetId (not wxWindow::SetId).") );
1523
1524 SetDescribedProperty(event.GetProperty());
1525 event.Skip();
1526 }
1527
1528 // -----------------------------------------------------------------------
1529
1530 void wxPropertyGridManager::OnResize( wxSizeEvent& WXUNUSED(event) )
1531 {
1532 int width, height;
1533
1534 GetClientSize(&width,&height);
1535
1536 if ( m_width == -12345 )
1537 RecreateControls();
1538
1539 RecalculatePositions(width,height);
1540 }
1541
1542 // -----------------------------------------------------------------------
1543
1544 void wxPropertyGridManager::OnMouseEntry( wxMouseEvent& WXUNUSED(event) )
1545 {
1546 // Correct cursor. This is required atleast for wxGTK, for which
1547 // setting button's cursor to *wxSTANDARD_CURSOR does not work.
1548 SetCursor( wxNullCursor );
1549 m_onSplitter = 0;
1550 }
1551
1552 // -----------------------------------------------------------------------
1553
1554 void wxPropertyGridManager::OnMouseMove( wxMouseEvent &event )
1555 {
1556 if ( !m_pTxtHelpCaption )
1557 return;
1558
1559 int y = event.m_y;
1560
1561 if ( m_dragStatus > 0 )
1562 {
1563 int sy = y - m_dragOffset;
1564
1565 // Calculate drag limits
1566 int bottom_limit = m_height - m_splitterHeight + 1;
1567 int top_limit = m_pPropGrid->m_lineHeight;
1568 #if wxUSE_TOOLBAR
1569 if ( m_pToolbar ) top_limit += m_pToolbar->GetSize().y;
1570 #endif
1571
1572 if ( sy >= top_limit && sy < bottom_limit )
1573 {
1574
1575 int change = sy - m_splitterY;
1576 if ( change )
1577 {
1578 m_splitterY = sy;
1579
1580 m_pPropGrid->SetSize( m_width, m_splitterY - m_pPropGrid->GetPosition().y );
1581 UpdateDescriptionBox( m_splitterY, m_width, m_height );
1582
1583 m_extraHeight -= change;
1584 InvalidateBestSize();
1585 }
1586
1587 }
1588
1589 }
1590 else
1591 {
1592 if ( y >= m_splitterY && y < (m_splitterY+m_splitterHeight+2) )
1593 {
1594 SetCursor ( m_cursorSizeNS );
1595 m_onSplitter = 1;
1596 }
1597 else
1598 {
1599 if ( m_onSplitter )
1600 {
1601 SetCursor ( wxNullCursor );
1602 }
1603 m_onSplitter = 0;
1604 }
1605 }
1606 }
1607
1608 // -----------------------------------------------------------------------
1609
1610 void wxPropertyGridManager::OnMouseClick( wxMouseEvent &event )
1611 {
1612 int y = event.m_y;
1613
1614 // Click on splitter.
1615 if ( y >= m_splitterY && y < (m_splitterY+m_splitterHeight+2) )
1616 {
1617 if ( m_dragStatus == 0 )
1618 {
1619 //
1620 // Begin draggin the splitter
1621 //
1622
1623 BEGIN_MOUSE_CAPTURE
1624
1625 m_dragStatus = 1;
1626
1627 m_dragOffset = y - m_splitterY;
1628
1629 }
1630 }
1631 }
1632
1633 // -----------------------------------------------------------------------
1634
1635 void wxPropertyGridManager::OnMouseUp( wxMouseEvent &event )
1636 {
1637 // No event type check - basicly calling this method should
1638 // just stop dragging.
1639
1640 if ( m_dragStatus >= 1 )
1641 {
1642 //
1643 // End Splitter Dragging
1644 //
1645
1646 int y = event.m_y;
1647
1648 // DO NOT ENABLE FOLLOWING LINE!
1649 // (it is only here as a reminder to not to do it)
1650 //m_splitterY = y;
1651
1652 // This is necessary to return cursor
1653 END_MOUSE_CAPTURE
1654
1655 // Set back the default cursor, if necessary
1656 if ( y < m_splitterY || y >= (m_splitterY+m_splitterHeight+2) )
1657 {
1658 SetCursor ( wxNullCursor );
1659 }
1660
1661 m_dragStatus = 0;
1662 }
1663 }
1664
1665 // -----------------------------------------------------------------------
1666
1667 void wxPropertyGridManager::SetSplitterPosition( int pos, int splitterColumn )
1668 {
1669 wxASSERT_MSG( GetPageCount(),
1670 wxT("SetSplitterPosition() has no effect until pages have been added") );
1671
1672 size_t i;
1673 for ( i=0; i<GetPageCount(); i++ )
1674 {
1675 wxPropertyGridPage* page = GetPage(i);
1676 page->DoSetSplitterPosition( pos, splitterColumn, false );
1677 }
1678
1679 m_pPropGrid->SetInternalFlag(wxPG_FL_SPLITTER_PRE_SET);
1680 }
1681
1682 // -----------------------------------------------------------------------
1683 // wxPGVIterator_Manager
1684 // -----------------------------------------------------------------------
1685
1686 // Default returned by wxPropertyGridInterface::CreateVIterator().
1687 class wxPGVIteratorBase_Manager : public wxPGVIteratorBase
1688 {
1689 public:
1690 wxPGVIteratorBase_Manager( wxPropertyGridManager* manager, int flags )
1691 : m_manager(manager), m_flags(flags), m_curPage(0)
1692 {
1693 m_it.Init(manager->GetPage(0), flags);
1694 }
1695 virtual ~wxPGVIteratorBase_Manager() { }
1696 virtual void Next()
1697 {
1698 m_it.Next();
1699
1700 // Next page?
1701 if ( m_it.AtEnd() )
1702 {
1703 m_curPage++;
1704 if ( m_curPage < m_manager->GetPageCount() )
1705 m_it.Init( m_manager->GetPage(m_curPage), m_flags );
1706 }
1707 }
1708 private:
1709 wxPropertyGridManager* m_manager;
1710 int m_flags;
1711 unsigned int m_curPage;
1712 };
1713
1714 wxPGVIterator wxPropertyGridManager::GetVIterator( int flags ) const
1715 {
1716 return wxPGVIterator( new wxPGVIteratorBase_Manager( (wxPropertyGridManager*)this, flags ) );
1717 }
1718
1719 #endif // wxUSE_PROPGRID