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