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