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