]> git.saurik.com Git - wxWidgets.git/blob - src/propgrid/manager.cpp
compilation fix after wxFont changes (closes #10152)
[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, 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 wxString& 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 wxString& 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 {
1367 if ( !m_pPropGrid->HasInternalFlag(wxPG_FL_CATMODE_AUTO_SORT) )
1368 m_pPropGrid->m_windowStyle &= ~wxPG_AUTO_SORT;
1369 m_pPropGrid->EnableCategories( true );
1370 }
1371 }
1372 else if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 1 ) )
1373 {
1374 // Alphabetic mode.
1375 if ( !(m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES) )
1376 {
1377 if ( m_pPropGrid->HasFlag(wxPG_AUTO_SORT) )
1378 m_pPropGrid->SetInternalFlag(wxPG_FL_CATMODE_AUTO_SORT);
1379 else
1380 m_pPropGrid->ClearInternalFlag(wxPG_FL_CATMODE_AUTO_SORT);
1381
1382 m_pPropGrid->m_windowStyle |= wxPG_AUTO_SORT;
1383 m_pPropGrid->EnableCategories( false );
1384 }
1385 }
1386 else
1387 {
1388 // Page Switching.
1389
1390 int index = -1;
1391 size_t i;
1392 wxPropertyGridPage* pdc;
1393
1394 // Find page with given id.
1395 for ( i=0; i<GetPageCount(); i++ )
1396 {
1397 pdc = m_arrPages[i];
1398 if ( pdc->m_id == id )
1399 {
1400 index = i;
1401 break;
1402 }
1403 }
1404
1405 wxASSERT( index >= 0 );
1406
1407 if ( DoSelectPage( index ) )
1408 {
1409
1410 // Event dispatching must be last.
1411 m_pPropGrid->SendEvent( wxEVT_PG_PAGE_CHANGED, (wxPGProperty*) NULL );
1412
1413 }
1414 else
1415 {
1416 // TODO: Depress the old button on toolbar.
1417 }
1418
1419 }
1420 }
1421 }
1422
1423 // -----------------------------------------------------------------------
1424
1425 bool wxPropertyGridManager::SetEditableStateItem( const wxString& name, wxVariant value )
1426 {
1427 if ( name == wxS("descboxheight") )
1428 {
1429 SetDescBoxHeight(value.GetLong(), true);
1430 return true;
1431 }
1432 return false;
1433 }
1434
1435 // -----------------------------------------------------------------------
1436
1437 wxVariant wxPropertyGridManager::GetEditableStateItem( const wxString& name ) const
1438 {
1439 if ( name == wxS("descboxheight") )
1440 {
1441 return (long) GetDescBoxHeight();
1442 }
1443 return wxNullVariant;
1444 }
1445
1446 // -----------------------------------------------------------------------
1447
1448 void wxPropertyGridManager::SetDescription( const wxString& label, const wxString& content )
1449 {
1450 if ( m_pTxtHelpCaption )
1451 {
1452 wxSize osz1 = m_pTxtHelpCaption->GetSize();
1453 wxSize osz2 = m_pTxtHelpContent->GetSize();
1454
1455 m_pTxtHelpCaption->SetLabel(label);
1456 m_pTxtHelpContent->SetLabel(content);
1457
1458 m_pTxtHelpCaption->SetSize(-1,osz1.y);
1459 m_pTxtHelpContent->SetSize(-1,osz2.y);
1460
1461 if ( (m_iFlags & wxPG_FL_DESC_REFRESH_REQUIRED) || (osz2.x<(m_width-10)) )
1462 RefreshHelpBox( m_splitterY, m_width, m_height );
1463 }
1464 }
1465
1466 // -----------------------------------------------------------------------
1467
1468 void wxPropertyGridManager::SetDescribedProperty( wxPGProperty* p )
1469 {
1470 if ( m_pTxtHelpCaption )
1471 {
1472 if ( p )
1473 {
1474 SetDescription( p->GetLabel(), p->GetHelpString() );
1475 }
1476 else
1477 {
1478 m_pTxtHelpCaption->SetLabel(wxEmptyString);
1479 m_pTxtHelpContent->SetLabel(wxEmptyString);
1480 }
1481 }
1482 }
1483
1484 // -----------------------------------------------------------------------
1485
1486 void wxPropertyGridManager::SetSplitterLeft( bool subProps, bool allPages )
1487 {
1488 if ( !allPages )
1489 {
1490 m_pPropGrid->SetSplitterLeft(subProps);
1491 }
1492 else
1493 {
1494 wxClientDC dc(this);
1495 dc.SetFont(m_pPropGrid->m_font);
1496
1497 int highest = 0;
1498 unsigned int i;
1499
1500 for ( i=0; i<GetPageCount(); i++ )
1501 {
1502 int maxW = m_pState->GetColumnFitWidth(dc, m_arrPages[i]->m_properties, 0, subProps );
1503 maxW += m_pPropGrid->m_marginWidth;
1504 if ( maxW > highest )
1505 highest = maxW;
1506 }
1507
1508 if ( highest > 0 )
1509 m_pPropGrid->SetSplitterPosition( highest );
1510
1511 m_pPropGrid->m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER;
1512 }
1513 }
1514
1515 // -----------------------------------------------------------------------
1516
1517 void wxPropertyGridManager::OnPropertyGridSelect( wxPropertyGridEvent& event )
1518 {
1519 // Check id.
1520 wxASSERT_MSG( GetId() == m_pPropGrid->GetId(),
1521 wxT("wxPropertyGridManager id must be set with wxPropertyGridManager::SetId (not wxWindow::SetId).") );
1522
1523 SetDescribedProperty(event.GetProperty());
1524 event.Skip();
1525 }
1526
1527 // -----------------------------------------------------------------------
1528
1529 void wxPropertyGridManager::OnResize( wxSizeEvent& WXUNUSED(event) )
1530 {
1531 int width, height;
1532
1533 GetClientSize(&width,&height);
1534
1535 if ( m_width == -12345 )
1536 RecreateControls();
1537
1538 RecalculatePositions(width,height);
1539 }
1540
1541 // -----------------------------------------------------------------------
1542
1543 void wxPropertyGridManager::OnMouseEntry( wxMouseEvent& WXUNUSED(event) )
1544 {
1545 // Correct cursor. This is required atleast for wxGTK, for which
1546 // setting button's cursor to *wxSTANDARD_CURSOR does not work.
1547 SetCursor( wxNullCursor );
1548 m_onSplitter = 0;
1549 }
1550
1551 // -----------------------------------------------------------------------
1552
1553 void wxPropertyGridManager::OnMouseMove( wxMouseEvent &event )
1554 {
1555 if ( !m_pTxtHelpCaption )
1556 return;
1557
1558 int y = event.m_y;
1559
1560 if ( m_dragStatus > 0 )
1561 {
1562 int sy = y - m_dragOffset;
1563
1564 // Calculate drag limits
1565 int bottom_limit = m_height - m_splitterHeight + 1;
1566 int top_limit = m_pPropGrid->m_lineHeight;
1567 #if wxUSE_TOOLBAR
1568 if ( m_pToolbar ) top_limit += m_pToolbar->GetSize().y;
1569 #endif
1570
1571 if ( sy >= top_limit && sy < bottom_limit )
1572 {
1573
1574 int change = sy - m_splitterY;
1575 if ( change )
1576 {
1577 m_splitterY = sy;
1578
1579 m_pPropGrid->SetSize( m_width, m_splitterY - m_pPropGrid->GetPosition().y );
1580 RefreshHelpBox( m_splitterY, m_width, m_height );
1581
1582 m_extraHeight -= change;
1583 InvalidateBestSize();
1584 }
1585
1586 }
1587
1588 }
1589 else
1590 {
1591 if ( y >= m_splitterY && y < (m_splitterY+m_splitterHeight+2) )
1592 {
1593 SetCursor ( m_cursorSizeNS );
1594 m_onSplitter = 1;
1595 }
1596 else
1597 {
1598 if ( m_onSplitter )
1599 {
1600 SetCursor ( wxNullCursor );
1601 }
1602 m_onSplitter = 0;
1603 }
1604 }
1605 }
1606
1607 // -----------------------------------------------------------------------
1608
1609 void wxPropertyGridManager::OnMouseClick( wxMouseEvent &event )
1610 {
1611 int y = event.m_y;
1612
1613 // Click on splitter.
1614 if ( y >= m_splitterY && y < (m_splitterY+m_splitterHeight+2) )
1615 {
1616 if ( m_dragStatus == 0 )
1617 {
1618 //
1619 // Begin draggin the splitter
1620 //
1621
1622 BEGIN_MOUSE_CAPTURE
1623
1624 m_dragStatus = 1;
1625
1626 m_dragOffset = y - m_splitterY;
1627
1628 }
1629 }
1630 }
1631
1632 // -----------------------------------------------------------------------
1633
1634 void wxPropertyGridManager::OnMouseUp( wxMouseEvent &event )
1635 {
1636 // No event type check - basicly calling this method should
1637 // just stop dragging.
1638
1639 if ( m_dragStatus >= 1 )
1640 {
1641 //
1642 // End Splitter Dragging
1643 //
1644
1645 int y = event.m_y;
1646
1647 // DO NOT ENABLE FOLLOWING LINE!
1648 // (it is only here as a reminder to not to do it)
1649 //m_splitterY = y;
1650
1651 // This is necessary to return cursor
1652 END_MOUSE_CAPTURE
1653
1654 // Set back the default cursor, if necessary
1655 if ( y < m_splitterY || y >= (m_splitterY+m_splitterHeight+2) )
1656 {
1657 SetCursor ( wxNullCursor );
1658 }
1659
1660 m_dragStatus = 0;
1661 }
1662 }
1663
1664 // -----------------------------------------------------------------------
1665
1666 void wxPropertyGridManager::SetSplitterPosition( int pos, int splitterColumn )
1667 {
1668 wxASSERT_MSG( GetPageCount(),
1669 wxT("SetSplitterPosition() has no effect until pages have been added") );
1670
1671 size_t i;
1672 for ( i=0; i<GetPageCount(); i++ )
1673 {
1674 wxPropertyGridPage* page = GetPage(i);
1675 page->DoSetSplitterPositionThisPage( pos, splitterColumn );
1676 }
1677
1678 m_pPropGrid->SetInternalFlag(wxPG_FL_SPLITTER_PRE_SET);
1679 }
1680
1681 // -----------------------------------------------------------------------
1682 // wxPGVIterator_Manager
1683 // -----------------------------------------------------------------------
1684
1685 // Default returned by wxPropertyGridInterface::CreateVIterator().
1686 class wxPGVIteratorBase_Manager : public wxPGVIteratorBase
1687 {
1688 public:
1689 wxPGVIteratorBase_Manager( wxPropertyGridManager* manager, int flags )
1690 : m_manager(manager), m_flags(flags), m_curPage(0)
1691 {
1692 m_it.Init(manager->GetPage(0), flags);
1693 }
1694 virtual ~wxPGVIteratorBase_Manager() { }
1695 virtual void Next()
1696 {
1697 m_it.Next();
1698
1699 // Next page?
1700 if ( m_it.AtEnd() )
1701 {
1702 m_curPage++;
1703 if ( m_curPage < m_manager->GetPageCount() )
1704 m_it.Init( m_manager->GetPage(m_curPage), m_flags );
1705 }
1706 }
1707 private:
1708 wxPropertyGridManager* m_manager;
1709 int m_flags;
1710 unsigned int m_curPage;
1711 };
1712
1713 wxPGVIterator wxPropertyGridManager::GetVIterator( int flags ) const
1714 {
1715 return wxPGVIterator( new wxPGVIteratorBase_Manager( (wxPropertyGridManager*)this, flags ) );
1716 }
1717
1718 #endif // wxUSE_PROPGRID