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