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