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