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