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