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