Use wxToolBar::SetToolBitmapSize() to setup tool bitmap size to match stock bitmaps
[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 m_pToolbar->SetSize(0, 0, width, -1);
1065 propgridY += m_pToolbar->GetSize().y;
1066 }
1067 #endif
1068
1069 // Help box.
1070 if ( m_pTxtHelpCaption )
1071 {
1072 int new_splittery = m_splitterY;
1073
1074 // Move m_splitterY
1075 if ( ( m_splitterY >= 0 || m_nextDescBoxSize ) && m_height > 32 )
1076 {
1077 if ( m_nextDescBoxSize >= 0 )
1078 {
1079 new_splittery = m_height - m_nextDescBoxSize - m_splitterHeight;
1080 m_nextDescBoxSize = -1;
1081 }
1082 new_splittery += (height-m_height);
1083 }
1084 else
1085 {
1086 new_splittery = height - wxPGMAN_DEFAULT_NEGATIVE_SPLITTER_Y;
1087 if ( new_splittery < 32 )
1088 new_splittery = 32;
1089 }
1090
1091 // Check if beyond minimum.
1092 int nspy_min = propgridY + m_pPropGrid->m_lineHeight;
1093 if ( new_splittery < nspy_min )
1094 new_splittery = nspy_min;
1095
1096 propgridBottomY = new_splittery;
1097
1098 UpdateDescriptionBox( new_splittery, width, height );
1099 }
1100
1101 if ( m_iFlags & wxPG_FL_INITIALIZED )
1102 {
1103 int pgh = propgridBottomY - propgridY;
1104 if ( pgh < 0 )
1105 pgh = 0;
1106 m_pPropGrid->SetSize( 0, propgridY, width, pgh );
1107
1108 m_extraHeight = height - pgh;
1109
1110 m_width = width;
1111 m_height = height;
1112 }
1113 }
1114
1115 // -----------------------------------------------------------------------
1116
1117 void wxPropertyGridManager::SetDescBoxHeight( int ht, bool refresh )
1118 {
1119 if ( m_windowStyle & wxPG_DESCRIPTION )
1120 {
1121 if ( ht != GetDescBoxHeight() )
1122 {
1123 m_nextDescBoxSize = ht;
1124 if ( refresh )
1125 RecalculatePositions(m_width, m_height);
1126 }
1127 }
1128 }
1129
1130 // -----------------------------------------------------------------------
1131
1132 int wxPropertyGridManager::GetDescBoxHeight() const
1133 {
1134 return GetClientSize().y - m_splitterY - m_splitterHeight;
1135 }
1136
1137 // -----------------------------------------------------------------------
1138
1139 void wxPropertyGridManager::OnPaint( wxPaintEvent& WXUNUSED(event) )
1140 {
1141 wxPaintDC dc(this);
1142
1143 // Update everything inside the box
1144 wxRect r = GetUpdateRegion().GetBox();
1145
1146 // Repaint splitter?
1147 int r_bottom = r.y + r.height;
1148 int splitter_bottom = m_splitterY + m_splitterHeight;
1149 if ( r.y < splitter_bottom && r_bottom >= m_splitterY )
1150 RepaintSplitter( dc, m_splitterY, m_width, m_height, false );
1151 }
1152
1153 // -----------------------------------------------------------------------
1154
1155 void wxPropertyGridManager::Refresh(bool eraseBackground, const wxRect* rect )
1156 {
1157 m_pPropGrid->Refresh(eraseBackground);
1158 wxWindow::Refresh(eraseBackground,rect);
1159 }
1160
1161 // -----------------------------------------------------------------------
1162
1163 void wxPropertyGridManager::RefreshProperty( wxPGProperty* p )
1164 {
1165 wxPropertyGrid* grid = p->GetGrid();
1166
1167 if ( GetPage(m_selPage)->GetStatePtr() == p->GetParent()->GetParentState() )
1168 grid->RefreshProperty(p);
1169 }
1170
1171 // -----------------------------------------------------------------------
1172
1173 void wxPropertyGridManager::RecreateControls()
1174 {
1175
1176 bool was_shown = IsShown();
1177 if ( was_shown )
1178 Show ( false );
1179
1180 wxWindowID baseId = m_pPropGrid->GetId();
1181 if ( baseId < 0 )
1182 baseId = wxPG_MAN_ALTERNATE_BASE_ID;
1183
1184 #if wxUSE_TOOLBAR
1185 if ( m_windowStyle & wxPG_TOOLBAR )
1186 {
1187 // Has toolbar.
1188 if ( !m_pToolbar )
1189 {
1190 m_pToolbar = new wxToolBar(this,baseId+ID_ADVTOOLBAR_OFFSET,
1191 wxDefaultPosition,wxDefaultSize,
1192 ((GetExtraStyle()&wxPG_EX_NO_FLAT_TOOLBAR)?0:wxTB_FLAT)
1193 /*| wxTB_HORIZONTAL | wxNO_BORDER*/ );
1194 m_pToolbar->SetToolBitmapSize(wxSize(16, 15));
1195
1196 #if defined(__WXMSW__)
1197 // Eliminate toolbar flicker on XP
1198 // NOTE: Not enabled since it corrupts drawing somewhat.
1199
1200 /*
1201 #ifndef WS_EX_COMPOSITED
1202 #define WS_EX_COMPOSITED 0x02000000L
1203 #endif
1204
1205 HWND hWnd = (HWND)m_pToolbar->GetHWND();
1206
1207 ::SetWindowLong( hWnd, GWL_EXSTYLE,
1208 ::GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_COMPOSITED );
1209 */
1210
1211 #endif
1212
1213 m_pToolbar->SetCursor ( *wxSTANDARD_CURSOR );
1214
1215 if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) )
1216 {
1217 wxString desc1(_("Categorized Mode"));
1218 wxString desc2(_("Alphabetic Mode"));
1219 m_pToolbar->AddTool(baseId+ID_ADVTBITEMSBASE_OFFSET+0,
1220 desc1,wxBitmap ( (const char**)gs_xpm_catmode ),
1221 desc1,wxITEM_RADIO);
1222 m_pToolbar->AddTool(baseId+ID_ADVTBITEMSBASE_OFFSET+1,
1223 desc2,wxBitmap ( (const char**)gs_xpm_noncatmode ),
1224 desc2,wxITEM_RADIO);
1225 m_pToolbar->Realize();
1226 }
1227
1228 }
1229
1230 if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) )
1231 {
1232 // Toggle correct mode button.
1233 // TODO: This doesn't work in wxMSW (when changing,
1234 // both items will get toggled).
1235 int toggle_but_on_ind = ID_ADVTBITEMSBASE_OFFSET+0;
1236 int toggle_but_off_ind = ID_ADVTBITEMSBASE_OFFSET+1;
1237 if ( m_pPropGrid->m_pState->IsInNonCatMode() )
1238 {
1239 toggle_but_on_ind++;
1240 toggle_but_off_ind--;
1241 }
1242
1243 m_pToolbar->ToggleTool(baseId+toggle_but_on_ind,true);
1244 m_pToolbar->ToggleTool(baseId+toggle_but_off_ind,false);
1245 }
1246
1247 }
1248 else
1249 {
1250 // No toolbar.
1251 if ( m_pToolbar )
1252 m_pToolbar->Destroy();
1253 m_pToolbar = NULL;
1254 }
1255 #endif
1256
1257 if ( m_windowStyle & wxPG_DESCRIPTION )
1258 {
1259 // Has help box.
1260 m_pPropGrid->m_iFlags |= (wxPG_FL_NOSTATUSBARHELP);
1261
1262 if ( !m_pTxtHelpCaption )
1263 {
1264 m_pTxtHelpCaption = new wxStaticText(this,
1265 baseId+ID_ADVHELPCAPTION_OFFSET,
1266 wxT(""),
1267 wxDefaultPosition,
1268 wxDefaultSize,
1269 wxALIGN_LEFT|wxST_NO_AUTORESIZE);
1270 m_pTxtHelpCaption->SetFont( m_pPropGrid->m_captionFont );
1271 m_pTxtHelpCaption->SetCursor( *wxSTANDARD_CURSOR );
1272 }
1273 if ( !m_pTxtHelpContent )
1274 {
1275 m_pTxtHelpContent = new wxStaticText(this,
1276 baseId+ID_ADVHELPCONTENT_OFFSET,
1277 wxT(""),
1278 wxDefaultPosition,
1279 wxDefaultSize,
1280 wxALIGN_LEFT|wxST_NO_AUTORESIZE);
1281 m_pTxtHelpContent->SetCursor( *wxSTANDARD_CURSOR );
1282 }
1283
1284 SetDescribedProperty(GetSelection());
1285 }
1286 else
1287 {
1288 // No help box.
1289 m_pPropGrid->m_iFlags &= ~(wxPG_FL_NOSTATUSBARHELP);
1290
1291 if ( m_pTxtHelpCaption )
1292 m_pTxtHelpCaption->Destroy();
1293
1294 m_pTxtHelpCaption = NULL;
1295
1296 if ( m_pTxtHelpContent )
1297 m_pTxtHelpContent->Destroy();
1298
1299 m_pTxtHelpContent = NULL;
1300 }
1301
1302 int width, height;
1303
1304 GetClientSize(&width,&height);
1305
1306 RecalculatePositions(width,height);
1307
1308 if ( was_shown )
1309 Show ( true );
1310 }
1311
1312 // -----------------------------------------------------------------------
1313
1314 wxPGProperty* wxPropertyGridManager::DoGetPropertyByName( const wxString& name ) const
1315 {
1316 size_t i;
1317 for ( i=0; i<GetPageCount(); i++ )
1318 {
1319 wxPropertyGridPageState* pState = m_arrPages[i]->GetStatePtr();
1320 wxPGProperty* p = pState->BaseGetPropertyByName(name);
1321 if ( p )
1322 {
1323 return p;
1324 }
1325 }
1326 return NULL;
1327 }
1328
1329 // -----------------------------------------------------------------------
1330
1331 bool wxPropertyGridManager::EnsureVisible( wxPGPropArg id )
1332 {
1333 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
1334
1335 wxPropertyGridPageState* parentState = p->GetParentState();
1336
1337 // Select correct page.
1338 if ( m_pPropGrid->m_pState != parentState )
1339 DoSelectPage( GetPageByState(parentState) );
1340
1341 return m_pPropGrid->EnsureVisible(id);
1342 }
1343
1344 // -----------------------------------------------------------------------
1345
1346 void wxPropertyGridManager::OnToolbarClick( wxCommandEvent &event )
1347 {
1348 int id = event.GetId();
1349 if ( id >= 0 )
1350 {
1351 int baseId = m_pPropGrid->GetId();
1352 if ( baseId < 0 )
1353 baseId = wxPG_MAN_ALTERNATE_BASE_ID;
1354
1355 if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 0 ) )
1356 {
1357 // Categorized mode.
1358 if ( m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES )
1359 {
1360 if ( !m_pPropGrid->HasInternalFlag(wxPG_FL_CATMODE_AUTO_SORT) )
1361 m_pPropGrid->m_windowStyle &= ~wxPG_AUTO_SORT;
1362 m_pPropGrid->EnableCategories( true );
1363 }
1364 }
1365 else if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 1 ) )
1366 {
1367 // Alphabetic mode.
1368 if ( !(m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES) )
1369 {
1370 if ( m_pPropGrid->HasFlag(wxPG_AUTO_SORT) )
1371 m_pPropGrid->SetInternalFlag(wxPG_FL_CATMODE_AUTO_SORT);
1372 else
1373 m_pPropGrid->ClearInternalFlag(wxPG_FL_CATMODE_AUTO_SORT);
1374
1375 m_pPropGrid->m_windowStyle |= wxPG_AUTO_SORT;
1376 m_pPropGrid->EnableCategories( false );
1377 }
1378 }
1379 else
1380 {
1381 // Page Switching.
1382
1383 int index = -1;
1384 size_t i;
1385 wxPropertyGridPage* pdc;
1386
1387 // Find page with given id.
1388 for ( i=0; i<GetPageCount(); i++ )
1389 {
1390 pdc = m_arrPages[i];
1391 if ( pdc->m_id == id )
1392 {
1393 index = i;
1394 break;
1395 }
1396 }
1397
1398 wxASSERT( index >= 0 );
1399
1400 if ( DoSelectPage( index ) )
1401 {
1402
1403 // Event dispatching must be last.
1404 m_pPropGrid->SendEvent( wxEVT_PG_PAGE_CHANGED, NULL );
1405
1406 }
1407 else
1408 {
1409 // TODO: Depress the old button on toolbar.
1410 }
1411
1412 }
1413 }
1414 }
1415
1416 // -----------------------------------------------------------------------
1417
1418 bool wxPropertyGridManager::SetEditableStateItem( const wxString& name, wxVariant value )
1419 {
1420 if ( name == wxS("descboxheight") )
1421 {
1422 SetDescBoxHeight(value.GetLong(), true);
1423 return true;
1424 }
1425 return false;
1426 }
1427
1428 // -----------------------------------------------------------------------
1429
1430 wxVariant wxPropertyGridManager::GetEditableStateItem( const wxString& name ) const
1431 {
1432 if ( name == wxS("descboxheight") )
1433 {
1434 return (long) GetDescBoxHeight();
1435 }
1436 return wxNullVariant;
1437 }
1438
1439 // -----------------------------------------------------------------------
1440
1441 void wxPropertyGridManager::SetDescription( const wxString& label, const wxString& content )
1442 {
1443 if ( m_pTxtHelpCaption )
1444 {
1445 wxSize osz1 = m_pTxtHelpCaption->GetSize();
1446 wxSize osz2 = m_pTxtHelpContent->GetSize();
1447
1448 m_pTxtHelpCaption->SetLabel(label);
1449 m_pTxtHelpContent->SetLabel(content);
1450
1451 m_pTxtHelpCaption->SetSize(-1,osz1.y);
1452 m_pTxtHelpContent->SetSize(-1,osz2.y);
1453
1454 UpdateDescriptionBox( m_splitterY, m_width, m_height );
1455 }
1456 }
1457
1458 // -----------------------------------------------------------------------
1459
1460 void wxPropertyGridManager::SetDescribedProperty( wxPGProperty* p )
1461 {
1462 if ( m_pTxtHelpCaption )
1463 {
1464 if ( p )
1465 {
1466 SetDescription( p->GetLabel(), p->GetHelpString() );
1467 }
1468 else
1469 {
1470 SetDescription( wxEmptyString, wxEmptyString );
1471 }
1472 }
1473 }
1474
1475 // -----------------------------------------------------------------------
1476
1477 void wxPropertyGridManager::SetSplitterLeft( bool subProps, bool allPages )
1478 {
1479 if ( !allPages )
1480 {
1481 m_pPropGrid->SetSplitterLeft(subProps);
1482 }
1483 else
1484 {
1485 wxClientDC dc(this);
1486 dc.SetFont(m_pPropGrid->m_font);
1487
1488 int highest = 0;
1489 unsigned int i;
1490
1491 for ( i=0; i<GetPageCount(); i++ )
1492 {
1493 int maxW = m_pState->GetColumnFitWidth(dc, m_arrPages[i]->m_properties, 0, subProps );
1494 maxW += m_pPropGrid->m_marginWidth;
1495 if ( maxW > highest )
1496 highest = maxW;
1497 }
1498
1499 if ( highest > 0 )
1500 m_pPropGrid->SetSplitterPosition( highest );
1501
1502 m_pPropGrid->m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER;
1503 }
1504 }
1505
1506 // -----------------------------------------------------------------------
1507
1508 void wxPropertyGridManager::OnPropertyGridSelect( wxPropertyGridEvent& event )
1509 {
1510 // Check id.
1511 wxASSERT_MSG( GetId() == m_pPropGrid->GetId(),
1512 wxT("wxPropertyGridManager id must be set with wxPropertyGridManager::SetId (not wxWindow::SetId).") );
1513
1514 SetDescribedProperty(event.GetProperty());
1515 event.Skip();
1516 }
1517
1518 // -----------------------------------------------------------------------
1519
1520 void wxPropertyGridManager::OnResize( wxSizeEvent& WXUNUSED(event) )
1521 {
1522 int width, height;
1523
1524 GetClientSize(&width,&height);
1525
1526 if ( m_width == -12345 )
1527 RecreateControls();
1528
1529 RecalculatePositions(width,height);
1530 }
1531
1532 // -----------------------------------------------------------------------
1533
1534 void wxPropertyGridManager::OnMouseEntry( wxMouseEvent& WXUNUSED(event) )
1535 {
1536 // Correct cursor. This is required atleast for wxGTK, for which
1537 // setting button's cursor to *wxSTANDARD_CURSOR does not work.
1538 SetCursor( wxNullCursor );
1539 m_onSplitter = 0;
1540 }
1541
1542 // -----------------------------------------------------------------------
1543
1544 void wxPropertyGridManager::OnMouseMove( wxMouseEvent &event )
1545 {
1546 if ( !m_pTxtHelpCaption )
1547 return;
1548
1549 int y = event.m_y;
1550
1551 if ( m_dragStatus > 0 )
1552 {
1553 int sy = y - m_dragOffset;
1554
1555 // Calculate drag limits
1556 int bottom_limit = m_height - m_splitterHeight + 1;
1557 int top_limit = m_pPropGrid->m_lineHeight;
1558 #if wxUSE_TOOLBAR
1559 if ( m_pToolbar ) top_limit += m_pToolbar->GetSize().y;
1560 #endif
1561
1562 if ( sy >= top_limit && sy < bottom_limit )
1563 {
1564
1565 int change = sy - m_splitterY;
1566 if ( change )
1567 {
1568 m_splitterY = sy;
1569
1570 m_pPropGrid->SetSize( m_width, m_splitterY - m_pPropGrid->GetPosition().y );
1571 UpdateDescriptionBox( m_splitterY, m_width, m_height );
1572
1573 m_extraHeight -= change;
1574 InvalidateBestSize();
1575 }
1576
1577 }
1578
1579 }
1580 else
1581 {
1582 if ( y >= m_splitterY && y < (m_splitterY+m_splitterHeight+2) )
1583 {
1584 SetCursor ( m_cursorSizeNS );
1585 m_onSplitter = 1;
1586 }
1587 else
1588 {
1589 if ( m_onSplitter )
1590 {
1591 SetCursor ( wxNullCursor );
1592 }
1593 m_onSplitter = 0;
1594 }
1595 }
1596 }
1597
1598 // -----------------------------------------------------------------------
1599
1600 void wxPropertyGridManager::OnMouseClick( wxMouseEvent &event )
1601 {
1602 int y = event.m_y;
1603
1604 // Click on splitter.
1605 if ( y >= m_splitterY && y < (m_splitterY+m_splitterHeight+2) )
1606 {
1607 if ( m_dragStatus == 0 )
1608 {
1609 //
1610 // Begin draggin the splitter
1611 //
1612
1613 BEGIN_MOUSE_CAPTURE
1614
1615 m_dragStatus = 1;
1616
1617 m_dragOffset = y - m_splitterY;
1618
1619 }
1620 }
1621 }
1622
1623 // -----------------------------------------------------------------------
1624
1625 void wxPropertyGridManager::OnMouseUp( wxMouseEvent &event )
1626 {
1627 // No event type check - basicly calling this method should
1628 // just stop dragging.
1629
1630 if ( m_dragStatus >= 1 )
1631 {
1632 //
1633 // End Splitter Dragging
1634 //
1635
1636 int y = event.m_y;
1637
1638 // DO NOT ENABLE FOLLOWING LINE!
1639 // (it is only here as a reminder to not to do it)
1640 //m_splitterY = y;
1641
1642 // This is necessary to return cursor
1643 END_MOUSE_CAPTURE
1644
1645 // Set back the default cursor, if necessary
1646 if ( y < m_splitterY || y >= (m_splitterY+m_splitterHeight+2) )
1647 {
1648 SetCursor ( wxNullCursor );
1649 }
1650
1651 m_dragStatus = 0;
1652 }
1653 }
1654
1655 // -----------------------------------------------------------------------
1656
1657 void wxPropertyGridManager::SetSplitterPosition( int pos, int splitterColumn )
1658 {
1659 wxASSERT_MSG( GetPageCount(),
1660 wxT("SetSplitterPosition() has no effect until pages have been added") );
1661
1662 size_t i;
1663 for ( i=0; i<GetPageCount(); i++ )
1664 {
1665 wxPropertyGridPage* page = GetPage(i);
1666 page->DoSetSplitterPosition( pos, splitterColumn, false );
1667 }
1668
1669 m_pPropGrid->SetInternalFlag(wxPG_FL_SPLITTER_PRE_SET);
1670 }
1671
1672 // -----------------------------------------------------------------------
1673 // wxPGVIterator_Manager
1674 // -----------------------------------------------------------------------
1675
1676 // Default returned by wxPropertyGridInterface::CreateVIterator().
1677 class wxPGVIteratorBase_Manager : public wxPGVIteratorBase
1678 {
1679 public:
1680 wxPGVIteratorBase_Manager( wxPropertyGridManager* manager, int flags )
1681 : m_manager(manager), m_flags(flags), m_curPage(0)
1682 {
1683 m_it.Init(manager->GetPage(0), flags);
1684 }
1685 virtual ~wxPGVIteratorBase_Manager() { }
1686 virtual void Next()
1687 {
1688 m_it.Next();
1689
1690 // Next page?
1691 if ( m_it.AtEnd() )
1692 {
1693 m_curPage++;
1694 if ( m_curPage < m_manager->GetPageCount() )
1695 m_it.Init( m_manager->GetPage(m_curPage), m_flags );
1696 }
1697 }
1698 private:
1699 wxPropertyGridManager* m_manager;
1700 int m_flags;
1701 unsigned int m_curPage;
1702 };
1703
1704 wxPGVIterator wxPropertyGridManager::GetVIterator( int flags ) const
1705 {
1706 return wxPGVIterator( new wxPGVIteratorBase_Manager( (wxPropertyGridManager*)this, flags ) );
1707 }
1708
1709 #endif // wxUSE_PROPGRID