wxPropertyGrid: added wxPG_NO_INTERNAL_BORDER, wxPG_EX_NO_TOOLBAR_DIVIDER
[wxWidgets.git] / src / propgrid / manager.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/propgrid/manager.cpp
3 // Purpose: wxPropertyGridManager
4 // Author: Jaakko Salli
5 // Modified by:
6 // Created: 2005-01-14
7 // RCS-ID: $Id$
8 // Copyright: (c) Jaakko Salli
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_PROPGRID
20
21 #ifndef WX_PRECOMP
22 #include "wx/defs.h"
23 #include "wx/object.h"
24 #include "wx/hash.h"
25 #include "wx/string.h"
26 #include "wx/log.h"
27 #include "wx/event.h"
28 #include "wx/window.h"
29 #include "wx/panel.h"
30 #include "wx/dc.h"
31 #include "wx/pen.h"
32 #include "wx/brush.h"
33 #include "wx/cursor.h"
34 #include "wx/settings.h"
35 #include "wx/textctrl.h"
36 #include "wx/sizer.h"
37 #include "wx/statusbr.h"
38 #include "wx/intl.h"
39 #endif
40
41 // This define is necessary to prevent macro clearing
42 #define __wxPG_SOURCE_FILE__
43
44 #include "wx/propgrid/propgrid.h"
45
46 #include "wx/propgrid/manager.h"
47
48
49 #define wxPG_MAN_ALTERNATE_BASE_ID 11249 // Needed for wxID_ANY madnesss
50
51
52 // -----------------------------------------------------------------------
53
54 // For wxMSW cursor consistency, we must do mouse capturing even
55 // when using custom controls
56
57 #define BEGIN_MOUSE_CAPTURE \
58 if ( !(m_iFlags & wxPG_FL_MOUSE_CAPTURED) ) \
59 { \
60 CaptureMouse(); \
61 m_iFlags |= wxPG_FL_MOUSE_CAPTURED; \
62 }
63
64 #define END_MOUSE_CAPTURE \
65 if ( m_iFlags & wxPG_FL_MOUSE_CAPTURED ) \
66 { \
67 ReleaseMouse(); \
68 m_iFlags &= ~(wxPG_FL_MOUSE_CAPTURED); \
69 }
70
71 // -----------------------------------------------------------------------
72 // wxPropertyGridManager
73 // -----------------------------------------------------------------------
74
75 const char wxPropertyGridManagerNameStr[] = "wxPropertyGridManager";
76
77
78 // Categoric Mode Icon
79 static const char* gs_xpm_catmode[] = {
80 "16 16 5 1",
81 ". c none",
82 "B c black",
83 "D c #868686",
84 "L c #CACACA",
85 "W c #FFFFFF",
86 ".DDD............",
87 ".DLD.BBBBBB.....",
88 ".DDD............",
89 ".....DDDDD.DDD..",
90 "................",
91 ".....DDDDD.DDD..",
92 "................",
93 ".....DDDDD.DDD..",
94 "................",
95 ".....DDDDD.DDD..",
96 "................",
97 ".DDD............",
98 ".DLD.BBBBBB.....",
99 ".DDD............",
100 ".....DDDDD.DDD..",
101 "................"
102 };
103
104 // Alphabetic Mode Icon
105 static const char* gs_xpm_noncatmode[] = {
106 "16 16 5 1",
107 ". c none",
108 "B c black",
109 "D c #868686",
110 "L c #000080",
111 "W c #FFFFFF",
112 "..DBD...DDD.DDD.",
113 ".DB.BD..........",
114 ".BBBBB..DDD.DDD.",
115 ".B...B..........",
116 "...L....DDD.DDD.",
117 "...L............",
118 ".L.L.L..DDD.DDD.",
119 "..LLL...........",
120 "...L....DDD.DDD.",
121 "................",
122 ".BBBBB..DDD.DDD.",
123 "....BD..........",
124 "...BD...DDD.DDD.",
125 "..BD............",
126 ".BBBBB..DDD.DDD.",
127 "................"
128 };
129
130 // Default Page Icon.
131 static const char* gs_xpm_defpage[] = {
132 "16 16 5 1",
133 ". c none",
134 "B c black",
135 "D c #868686",
136 "L c #000080",
137 "W c #FFFFFF",
138 "................",
139 "................",
140 "..BBBBBBBBBBBB..",
141 "..B..........B..",
142 "..B.BB.LLLLL.B..",
143 "..B..........B..",
144 "..B.BB.LLLLL.B..",
145 "..B..........B..",
146 "..B.BB.LLLLL.B..",
147 "..B..........B..",
148 "..B.BB.LLLLL.B..",
149 "..B..........B..",
150 "..BBBBBBBBBBBB..",
151 "................",
152 "................",
153 "................"
154 };
155
156 // -----------------------------------------------------------------------
157 // wxPropertyGridPage
158 // -----------------------------------------------------------------------
159
160
161 IMPLEMENT_CLASS(wxPropertyGridPage, wxEvtHandler)
162
163
164 BEGIN_EVENT_TABLE(wxPropertyGridPage, wxEvtHandler)
165 END_EVENT_TABLE()
166
167
168 wxPropertyGridPage::wxPropertyGridPage()
169 : wxEvtHandler(), wxPropertyGridInterface(), wxPropertyGridPageState()
170 {
171 m_pState = this; // wxPropertyGridInterface to point to State
172 m_manager = NULL;
173 m_isDefault = false;
174 }
175
176 wxPropertyGridPage::~wxPropertyGridPage()
177 {
178 }
179
180 void wxPropertyGridPage::Clear()
181 {
182 GetStatePtr()->DoClear();
183 }
184
185 wxSize wxPropertyGridPage::FitColumns()
186 {
187 wxSize sz = DoFitColumns();
188 return sz;
189 }
190
191 void wxPropertyGridPage::RefreshProperty( wxPGProperty* p )
192 {
193 if ( m_manager )
194 m_manager->RefreshProperty(p);
195 }
196
197 void wxPropertyGridPage::OnShow()
198 {
199 }
200
201 void wxPropertyGridPage::SetSplitterPosition( int splitterPos, int col )
202 {
203 wxPropertyGrid* pg = GetGrid();
204 if ( pg->GetState() == this )
205 pg->SetSplitterPosition(splitterPos);
206 else
207 DoSetSplitterPosition(splitterPos, col, false);
208 }
209
210 void wxPropertyGridPage::DoSetSplitterPosition( int pos,
211 int splitterColumn,
212 bool allPages,
213 bool fromAutoCenter )
214 {
215 if ( allPages && m_manager->GetPageCount() )
216 m_manager->SetSplitterPosition( pos, splitterColumn );
217 else
218 wxPropertyGridPageState::DoSetSplitterPosition( pos,
219 splitterColumn,
220 allPages,
221 fromAutoCenter );
222 }
223
224 // -----------------------------------------------------------------------
225 // wxPropertyGridManager
226 // -----------------------------------------------------------------------
227
228 // Final default splitter y is client height minus this.
229 #define wxPGMAN_DEFAULT_NEGATIVE_SPLITTER_Y 100
230
231 // -----------------------------------------------------------------------
232
233 IMPLEMENT_CLASS(wxPropertyGridManager, wxPanel)
234
235 #define ID_ADVTOOLBAR_OFFSET 1
236 #define ID_ADVHELPCAPTION_OFFSET 2
237 #define ID_ADVHELPCONTENT_OFFSET 3
238 //#define ID_ADVBUTTON_OFFSET 4
239 #define ID_ADVTBITEMSBASE_OFFSET 5 // Must be last.
240
241 // -----------------------------------------------------------------------
242
243 BEGIN_EVENT_TABLE(wxPropertyGridManager, wxPanel)
244 EVT_MOTION(wxPropertyGridManager::OnMouseMove)
245 EVT_SIZE(wxPropertyGridManager::OnResize)
246 EVT_PAINT(wxPropertyGridManager::OnPaint)
247 EVT_LEFT_DOWN(wxPropertyGridManager::OnMouseClick)
248 EVT_LEFT_UP(wxPropertyGridManager::OnMouseUp)
249 EVT_LEAVE_WINDOW(wxPropertyGridManager::OnMouseEntry)
250 //EVT_ENTER_WINDOW(wxPropertyGridManager::OnMouseEntry)
251 END_EVENT_TABLE()
252
253 // -----------------------------------------------------------------------
254
255 wxPropertyGridManager::wxPropertyGridManager()
256 : wxPanel()
257 {
258 Init1();
259 }
260
261 // -----------------------------------------------------------------------
262
263 wxPropertyGridManager::wxPropertyGridManager( wxWindow *parent,
264 wxWindowID id,
265 const wxPoint& pos,
266 const wxSize& size,
267 long style,
268 const wxString& name )
269 : wxPanel()
270 {
271 Init1();
272 Create(parent,id,pos,size,style,name);
273 }
274
275 // -----------------------------------------------------------------------
276
277 bool wxPropertyGridManager::Create( wxWindow *parent,
278 wxWindowID id,
279 const wxPoint& pos,
280 const wxSize& size,
281 long style,
282 const wxString& name )
283 {
284 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 ( isPageInserted )
819 m_arrPages.push_back( pageObj );
820
821 #if wxUSE_TOOLBAR
822 if ( m_windowStyle & wxPG_TOOLBAR )
823 {
824 if ( !m_pToolbar )
825 RecreateControls();
826
827 if ( !(GetExtraStyle()&wxPG_EX_HIDE_PAGE_BUTTONS) )
828 {
829 wxASSERT( m_pToolbar );
830
831 // Add separator before first page.
832 if ( GetPageCount() < 2 && (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) &&
833 m_pToolbar->GetToolsCount() < 3 )
834 m_pToolbar->AddSeparator();
835
836 if ( &bmp != &wxNullBitmap )
837 m_pToolbar->AddTool(m_nextTbInd,label,bmp,label,wxITEM_RADIO);
838 //m_pToolbar->InsertTool(index+3,m_nextTbInd,bmp);
839 else
840 m_pToolbar->AddTool(m_nextTbInd,label,wxBitmap( (const char**)gs_xpm_defpage ),
841 label,wxITEM_RADIO);
842
843 m_nextTbInd++;
844
845 m_pToolbar->Realize();
846 }
847 }
848 #else
849 wxUnusedVar(bmp);
850 #endif
851
852 // If selected page was above the point of insertion, fix the current page index
853 if ( isPageInserted )
854 {
855 if ( m_selPage >= index )
856 {
857 m_selPage += 1;
858 }
859 }
860 else
861 {
862 // Set this value only when adding the first page
863 m_selPage = 0;
864 }
865
866 pageObj->Init();
867
868 m_iFlags |= wxPG_MAN_FL_PAGE_INSERTED;
869
870 wxASSERT( pageObj->GetGrid() );
871
872 return pageObj;
873 }
874
875 // -----------------------------------------------------------------------
876
877 bool wxPropertyGridManager::IsAnyModified() const
878 {
879 size_t i;
880 for ( i=0; i<GetPageCount(); i++ )
881 {
882 if ( m_arrPages[i]->GetStatePtr()->m_anyModified )
883 return true;
884 }
885 return false;
886 }
887
888 // -----------------------------------------------------------------------
889
890 bool wxPropertyGridManager::IsPageModified( size_t index ) const
891 {
892 if ( m_arrPages[index]->GetStatePtr()->m_anyModified )
893 return true;
894 return false;
895 }
896
897 // -----------------------------------------------------------------------
898
899 bool wxPropertyGridManager::IsPropertySelected( wxPGPropArg id ) const
900 {
901 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
902 for ( unsigned int i=0; i<GetPageCount(); i++ )
903 {
904 if ( GetPageState(i)->DoIsPropertySelected(p) )
905 return true;
906 }
907 return false;
908 }
909
910 // -----------------------------------------------------------------------
911
912 wxPGProperty* wxPropertyGridManager::GetPageRoot( int index ) const
913 {
914 wxASSERT( index >= 0 );
915 wxASSERT( index < (int)m_arrPages.size() );
916
917 return m_arrPages[index]->GetStatePtr()->m_properties;
918 }
919
920 // -----------------------------------------------------------------------
921
922 bool wxPropertyGridManager::RemovePage( int page )
923 {
924 wxCHECK_MSG( (page >= 0) && (page < (int)GetPageCount()),
925 false,
926 wxT("invalid page index") );
927
928 wxPropertyGridPage* pd = m_arrPages[page];
929
930 if ( m_arrPages.size() == 1 )
931 {
932 // Last page: do not remove page entry
933 m_pPropGrid->Clear();
934 m_selPage = -1;
935 m_iFlags &= ~wxPG_MAN_FL_PAGE_INSERTED;
936 pd->m_label.clear();
937 }
938
939 // Change selection if current is page
940 else if ( page == m_selPage )
941 {
942 if ( !m_pPropGrid->ClearSelection() )
943 return false;
944
945 // Substitute page to select
946 int substitute = page - 1;
947 if ( substitute < 0 )
948 substitute = page + 1;
949
950 SelectPage(substitute);
951 }
952
953 // Remove toolbar icon
954 #if wxUSE_TOOLBAR
955 if ( HasFlag(wxPG_TOOLBAR) )
956 {
957 wxASSERT( m_pToolbar );
958
959 int toolPos = GetExtraStyle() & wxPG_EX_MODE_BUTTONS ? 3 : 0;
960 toolPos += page;
961
962 // Delete separator as well, for consistency
963 if ( (GetExtraStyle() & wxPG_EX_MODE_BUTTONS) &&
964 GetPageCount() == 1 )
965 m_pToolbar->DeleteToolByPos(2);
966
967 m_pToolbar->DeleteToolByPos(toolPos);
968 }
969 #endif
970
971 if ( m_arrPages.size() > 1 )
972 {
973 m_arrPages.erase(m_arrPages.begin() + page);
974 delete pd;
975 }
976
977 // Adjust indexes that were above removed
978 if ( m_selPage > page )
979 m_selPage--;
980
981 return true;
982 }
983
984 // -----------------------------------------------------------------------
985
986 bool wxPropertyGridManager::ProcessEvent( wxEvent& event )
987 {
988 int evtType = event.GetEventType();
989
990 // NB: For some reason, under wxPython, Connect in Init doesn't work properly,
991 // so we'll need to call OnPropertyGridSelect manually. Multiple call's
992 // don't really matter.
993 if ( evtType == wxEVT_PG_SELECTED )
994 OnPropertyGridSelect((wxPropertyGridEvent&)event);
995
996 // Property grid events get special attention
997 if ( evtType >= wxPG_BASE_EVT_TYPE &&
998 evtType < (wxPG_MAX_EVT_TYPE) &&
999 m_selPage >= 0 )
1000 {
1001 wxPropertyGridPage* page = GetPage(m_selPage);
1002 wxPropertyGridEvent* pgEvent = wxDynamicCast(&event, wxPropertyGridEvent);
1003
1004 // Add property grid events to appropriate custom pages
1005 // but stop propagating to parent if page says it is
1006 // handling everything.
1007 if ( pgEvent && !page->m_isDefault )
1008 {
1009 /*if ( pgEvent->IsPending() )
1010 page->AddPendingEvent(event);
1011 else*/
1012 page->ProcessEvent(event);
1013
1014 if ( page->IsHandlingAllEvents() )
1015 event.StopPropagation();
1016 }
1017 }
1018
1019 return wxPanel::ProcessEvent(event);
1020 }
1021
1022 // -----------------------------------------------------------------------
1023
1024 void wxPropertyGridManager::RepaintDescBoxDecorations( wxDC& dc,
1025 int newSplitterY,
1026 int newWidth,
1027 int newHeight )
1028 {
1029 // Draw background
1030 wxColour bgcol = GetBackgroundColour();
1031 dc.SetBrush(bgcol);
1032 dc.SetPen(bgcol);
1033 int rectHeight = m_splitterHeight;
1034 dc.DrawRectangle(0, newSplitterY, newWidth, rectHeight);
1035 dc.SetPen( wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW) );
1036 int splitterBottom = newSplitterY + m_splitterHeight - 1;
1037 int boxHeight = newHeight - splitterBottom;
1038 if ( boxHeight > 1 )
1039 dc.DrawRectangle(0, splitterBottom, newWidth, boxHeight);
1040 else
1041 dc.DrawLine(0, splitterBottom, newWidth, splitterBottom);
1042 }
1043
1044 // -----------------------------------------------------------------------
1045
1046 void wxPropertyGridManager::UpdateDescriptionBox( int new_splittery, int new_width, int new_height )
1047 {
1048 int use_hei = new_height;
1049 use_hei--;
1050
1051 // Fix help control positions.
1052 int cap_hei = m_pPropGrid->m_fontHeight;
1053 int cap_y = new_splittery+m_splitterHeight+5;
1054 int cnt_y = cap_y+cap_hei+3;
1055 int sub_cap_hei = cap_y+cap_hei-use_hei;
1056 int cnt_hei = use_hei-cnt_y;
1057 if ( sub_cap_hei > 0 )
1058 {
1059 cap_hei -= sub_cap_hei;
1060 cnt_hei = 0;
1061 }
1062 if ( cap_hei <= 2 )
1063 {
1064 m_pTxtHelpCaption->Show( false );
1065 m_pTxtHelpContent->Show( false );
1066 }
1067 else
1068 {
1069 m_pTxtHelpCaption->SetSize(3,cap_y,new_width-6,cap_hei);
1070 m_pTxtHelpCaption->Wrap(-1);
1071 m_pTxtHelpCaption->Show( true );
1072 if ( cnt_hei <= 2 )
1073 {
1074 m_pTxtHelpContent->Show( false );
1075 }
1076 else
1077 {
1078 m_pTxtHelpContent->SetSize(3,cnt_y,new_width-6,cnt_hei);
1079 m_pTxtHelpContent->Show( true );
1080 }
1081 }
1082
1083 wxRect r(0, new_splittery, new_width, new_height-new_splittery);
1084 RefreshRect(r);
1085
1086 m_splitterY = new_splittery;
1087
1088 m_iFlags &= ~(wxPG_FL_DESC_REFRESH_REQUIRED);
1089 }
1090
1091 // -----------------------------------------------------------------------
1092
1093 void wxPropertyGridManager::RecalculatePositions( int width, int height )
1094 {
1095 int propgridY = 0;
1096 int propgridBottomY = height;
1097
1098 // Toolbar at the top.
1099 #if wxUSE_TOOLBAR
1100 if ( m_pToolbar )
1101 {
1102 m_pToolbar->SetSize(0, 0, width, -1);
1103 propgridY += m_pToolbar->GetSize().y;
1104
1105 if (GetExtraStyle() & wxPG_EX_TOOLBAR_SEPARATOR)
1106 propgridY += 1;
1107 }
1108 #endif
1109
1110 // Help box.
1111 if ( m_pTxtHelpCaption )
1112 {
1113 int new_splittery = m_splitterY;
1114
1115 // Move m_splitterY
1116 if ( ( m_splitterY >= 0 || m_nextDescBoxSize ) && m_height > 32 )
1117 {
1118 if ( m_nextDescBoxSize >= 0 )
1119 {
1120 new_splittery = m_height - m_nextDescBoxSize - m_splitterHeight;
1121 m_nextDescBoxSize = -1;
1122 }
1123 new_splittery += (height-m_height);
1124 }
1125 else
1126 {
1127 new_splittery = height - wxPGMAN_DEFAULT_NEGATIVE_SPLITTER_Y;
1128 if ( new_splittery < 32 )
1129 new_splittery = 32;
1130 }
1131
1132 // Check if beyond minimum.
1133 int nspy_min = propgridY + m_pPropGrid->m_lineHeight;
1134 if ( new_splittery < nspy_min )
1135 new_splittery = nspy_min;
1136
1137 propgridBottomY = new_splittery;
1138
1139 UpdateDescriptionBox( new_splittery, width, height );
1140 }
1141
1142 if ( m_iFlags & wxPG_FL_INITIALIZED )
1143 {
1144 int pgh = propgridBottomY - propgridY;
1145 if ( pgh < 0 )
1146 pgh = 0;
1147 m_pPropGrid->SetSize( 0, propgridY, width, pgh );
1148
1149 m_extraHeight = height - pgh;
1150
1151 m_width = width;
1152 m_height = height;
1153 }
1154 }
1155
1156 // -----------------------------------------------------------------------
1157
1158 void wxPropertyGridManager::SetDescBoxHeight( int ht, bool refresh )
1159 {
1160 if ( m_windowStyle & wxPG_DESCRIPTION )
1161 {
1162 if ( ht != GetDescBoxHeight() )
1163 {
1164 m_nextDescBoxSize = ht;
1165 if ( refresh )
1166 RecalculatePositions(m_width, m_height);
1167 }
1168 }
1169 }
1170
1171 // -----------------------------------------------------------------------
1172
1173 int wxPropertyGridManager::GetDescBoxHeight() const
1174 {
1175 return GetClientSize().y - m_splitterY - m_splitterHeight;
1176 }
1177
1178 // -----------------------------------------------------------------------
1179
1180 void wxPropertyGridManager::OnPaint( wxPaintEvent& WXUNUSED(event) )
1181 {
1182 wxPaintDC dc(this);
1183
1184 // Update everything inside the box
1185 wxRect r = GetUpdateRegion().GetBox();
1186
1187 if (GetExtraStyle() & wxPG_EX_TOOLBAR_SEPARATOR)
1188 {
1189 if (m_pToolbar && m_pPropGrid)
1190 {
1191 wxPen marginPen(m_pPropGrid->GetMarginColour());
1192 dc.SetPen(marginPen);
1193
1194 int y = m_pPropGrid->GetPosition().y-1;
1195 dc.DrawLine(0, y, GetClientSize().x, y);
1196 }
1197 }
1198
1199 // Repaint splitter and any other description box decorations
1200 if ( (r.y + r.height) >= m_splitterY && m_splitterY != -1)
1201 RepaintDescBoxDecorations( dc, m_splitterY, m_width, m_height );
1202 }
1203
1204 // -----------------------------------------------------------------------
1205
1206 void wxPropertyGridManager::Refresh(bool eraseBackground, const wxRect* rect )
1207 {
1208 m_pPropGrid->Refresh(eraseBackground);
1209 wxWindow::Refresh(eraseBackground,rect);
1210 }
1211
1212 // -----------------------------------------------------------------------
1213
1214 void wxPropertyGridManager::RefreshProperty( wxPGProperty* p )
1215 {
1216 wxPropertyGrid* grid = p->GetGrid();
1217
1218 if ( GetPage(m_selPage)->GetStatePtr() == p->GetParent()->GetParentState() )
1219 grid->RefreshProperty(p);
1220 }
1221
1222 // -----------------------------------------------------------------------
1223
1224 void wxPropertyGridManager::RecreateControls()
1225 {
1226
1227 bool was_shown = IsShown();
1228 if ( was_shown )
1229 Show ( false );
1230
1231 wxWindowID baseId = m_pPropGrid->GetId();
1232 if ( baseId < 0 )
1233 baseId = wxPG_MAN_ALTERNATE_BASE_ID;
1234
1235 #if wxUSE_TOOLBAR
1236 if ( m_windowStyle & wxPG_TOOLBAR )
1237 {
1238 // Has toolbar.
1239 if ( !m_pToolbar )
1240 {
1241 long toolBarFlags = ((GetExtraStyle()&wxPG_EX_NO_FLAT_TOOLBAR)?0:wxTB_FLAT);
1242 if (GetExtraStyle() & wxPG_EX_NO_TOOLBAR_DIVIDER)
1243 toolBarFlags |= wxTB_NODIVIDER;
1244
1245 m_pToolbar = new wxToolBar(this,baseId+ID_ADVTOOLBAR_OFFSET,
1246 wxDefaultPosition,wxDefaultSize,
1247 toolBarFlags);
1248 m_pToolbar->SetToolBitmapSize(wxSize(16, 15));
1249
1250 #if defined(__WXMSW__)
1251 // Eliminate toolbar flicker on XP
1252 // NOTE: Not enabled since it corrupts drawing somewhat.
1253
1254 /*
1255 #ifndef WS_EX_COMPOSITED
1256 #define WS_EX_COMPOSITED 0x02000000L
1257 #endif
1258
1259 HWND hWnd = (HWND)m_pToolbar->GetHWND();
1260
1261 ::SetWindowLong( hWnd, GWL_EXSTYLE,
1262 ::GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_COMPOSITED );
1263 */
1264
1265 #endif
1266
1267 m_pToolbar->SetCursor ( *wxSTANDARD_CURSOR );
1268
1269 if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) )
1270 {
1271 wxString desc1(_("Categorized Mode"));
1272 wxString desc2(_("Alphabetic Mode"));
1273 m_pToolbar->AddTool(baseId+ID_ADVTBITEMSBASE_OFFSET+0,
1274 desc1,wxBitmap ( (const char**)gs_xpm_catmode ),
1275 desc1,wxITEM_RADIO);
1276 m_pToolbar->AddTool(baseId+ID_ADVTBITEMSBASE_OFFSET+1,
1277 desc2,wxBitmap ( (const char**)gs_xpm_noncatmode ),
1278 desc2,wxITEM_RADIO);
1279 m_pToolbar->Realize();
1280 }
1281
1282 }
1283
1284 if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) )
1285 {
1286 // Toggle correct mode button.
1287 // TODO: This doesn't work in wxMSW (when changing,
1288 // both items will get toggled).
1289 int toggle_but_on_ind = ID_ADVTBITEMSBASE_OFFSET+0;
1290 int toggle_but_off_ind = ID_ADVTBITEMSBASE_OFFSET+1;
1291 if ( m_pPropGrid->m_pState->IsInNonCatMode() )
1292 {
1293 toggle_but_on_ind++;
1294 toggle_but_off_ind--;
1295 }
1296
1297 m_pToolbar->ToggleTool(baseId+toggle_but_on_ind,true);
1298 m_pToolbar->ToggleTool(baseId+toggle_but_off_ind,false);
1299 }
1300
1301 }
1302 else
1303 {
1304 // No toolbar.
1305 if ( m_pToolbar )
1306 m_pToolbar->Destroy();
1307 m_pToolbar = NULL;
1308 }
1309 #endif
1310
1311 if ( m_windowStyle & wxPG_DESCRIPTION )
1312 {
1313 // Has help box.
1314 m_pPropGrid->m_iFlags |= (wxPG_FL_NOSTATUSBARHELP);
1315
1316 if ( !m_pTxtHelpCaption )
1317 {
1318 m_pTxtHelpCaption = new wxStaticText(this,
1319 baseId+ID_ADVHELPCAPTION_OFFSET,
1320 wxT(""),
1321 wxDefaultPosition,
1322 wxDefaultSize,
1323 wxALIGN_LEFT|wxST_NO_AUTORESIZE);
1324 m_pTxtHelpCaption->SetFont( m_pPropGrid->m_captionFont );
1325 m_pTxtHelpCaption->SetCursor( *wxSTANDARD_CURSOR );
1326 }
1327 if ( !m_pTxtHelpContent )
1328 {
1329 m_pTxtHelpContent = new wxStaticText(this,
1330 baseId+ID_ADVHELPCONTENT_OFFSET,
1331 wxT(""),
1332 wxDefaultPosition,
1333 wxDefaultSize,
1334 wxALIGN_LEFT|wxST_NO_AUTORESIZE);
1335 m_pTxtHelpContent->SetCursor( *wxSTANDARD_CURSOR );
1336 }
1337
1338 SetDescribedProperty(GetSelection());
1339 }
1340 else
1341 {
1342 // No help box.
1343 m_pPropGrid->m_iFlags &= ~(wxPG_FL_NOSTATUSBARHELP);
1344
1345 if ( m_pTxtHelpCaption )
1346 m_pTxtHelpCaption->Destroy();
1347
1348 m_pTxtHelpCaption = NULL;
1349
1350 if ( m_pTxtHelpContent )
1351 m_pTxtHelpContent->Destroy();
1352
1353 m_pTxtHelpContent = NULL;
1354 }
1355
1356 int width, height;
1357
1358 GetClientSize(&width,&height);
1359
1360 RecalculatePositions(width,height);
1361
1362 if ( was_shown )
1363 Show ( true );
1364 }
1365
1366 // -----------------------------------------------------------------------
1367
1368 wxPGProperty* wxPropertyGridManager::DoGetPropertyByName( const wxString& name ) const
1369 {
1370 size_t i;
1371 for ( i=0; i<GetPageCount(); i++ )
1372 {
1373 wxPropertyGridPageState* pState = m_arrPages[i]->GetStatePtr();
1374 wxPGProperty* p = pState->BaseGetPropertyByName(name);
1375 if ( p )
1376 {
1377 return p;
1378 }
1379 }
1380 return NULL;
1381 }
1382
1383 // -----------------------------------------------------------------------
1384
1385 bool wxPropertyGridManager::EnsureVisible( wxPGPropArg id )
1386 {
1387 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
1388
1389 wxPropertyGridPageState* parentState = p->GetParentState();
1390
1391 // Select correct page.
1392 if ( m_pPropGrid->m_pState != parentState )
1393 DoSelectPage( GetPageByState(parentState) );
1394
1395 return m_pPropGrid->EnsureVisible(id);
1396 }
1397
1398 // -----------------------------------------------------------------------
1399
1400 void wxPropertyGridManager::OnToolbarClick( wxCommandEvent &event )
1401 {
1402 int id = event.GetId();
1403 if ( id >= 0 )
1404 {
1405 int baseId = m_pPropGrid->GetId();
1406 if ( baseId < 0 )
1407 baseId = wxPG_MAN_ALTERNATE_BASE_ID;
1408
1409 if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 0 ) )
1410 {
1411 // Categorized mode.
1412 if ( m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES )
1413 {
1414 if ( !m_pPropGrid->HasInternalFlag(wxPG_FL_CATMODE_AUTO_SORT) )
1415 m_pPropGrid->m_windowStyle &= ~wxPG_AUTO_SORT;
1416 m_pPropGrid->EnableCategories( true );
1417 }
1418 }
1419 else if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 1 ) )
1420 {
1421 // Alphabetic mode.
1422 if ( !(m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES) )
1423 {
1424 if ( m_pPropGrid->HasFlag(wxPG_AUTO_SORT) )
1425 m_pPropGrid->SetInternalFlag(wxPG_FL_CATMODE_AUTO_SORT);
1426 else
1427 m_pPropGrid->ClearInternalFlag(wxPG_FL_CATMODE_AUTO_SORT);
1428
1429 m_pPropGrid->m_windowStyle |= wxPG_AUTO_SORT;
1430 m_pPropGrid->EnableCategories( false );
1431 }
1432 }
1433 else
1434 {
1435 // Page Switching.
1436
1437 int index = -1;
1438 size_t i;
1439 wxPropertyGridPage* pdc;
1440
1441 // Find page with given id.
1442 for ( i=0; i<GetPageCount(); i++ )
1443 {
1444 pdc = m_arrPages[i];
1445 if ( pdc->m_id == id )
1446 {
1447 index = i;
1448 break;
1449 }
1450 }
1451
1452 wxASSERT( index >= 0 );
1453
1454 if ( DoSelectPage( index ) )
1455 {
1456
1457 // Event dispatching must be last.
1458 m_pPropGrid->SendEvent( wxEVT_PG_PAGE_CHANGED, NULL );
1459
1460 }
1461 else
1462 {
1463 // TODO: Depress the old button on toolbar.
1464 }
1465
1466 }
1467 }
1468 }
1469
1470 // -----------------------------------------------------------------------
1471
1472 bool wxPropertyGridManager::SetEditableStateItem( const wxString& name, wxVariant value )
1473 {
1474 if ( name == wxS("descboxheight") )
1475 {
1476 SetDescBoxHeight(value.GetLong(), true);
1477 return true;
1478 }
1479 return false;
1480 }
1481
1482 // -----------------------------------------------------------------------
1483
1484 wxVariant wxPropertyGridManager::GetEditableStateItem( const wxString& name ) const
1485 {
1486 if ( name == wxS("descboxheight") )
1487 {
1488 return (long) GetDescBoxHeight();
1489 }
1490 return wxNullVariant;
1491 }
1492
1493 // -----------------------------------------------------------------------
1494
1495 void wxPropertyGridManager::SetDescription( const wxString& label, const wxString& content )
1496 {
1497 if ( m_pTxtHelpCaption )
1498 {
1499 wxSize osz1 = m_pTxtHelpCaption->GetSize();
1500 wxSize osz2 = m_pTxtHelpContent->GetSize();
1501
1502 m_pTxtHelpCaption->SetLabel(label);
1503 m_pTxtHelpContent->SetLabel(content);
1504
1505 m_pTxtHelpCaption->SetSize(-1,osz1.y);
1506 m_pTxtHelpContent->SetSize(-1,osz2.y);
1507
1508 UpdateDescriptionBox( m_splitterY, m_width, m_height );
1509 }
1510 }
1511
1512 // -----------------------------------------------------------------------
1513
1514 void wxPropertyGridManager::SetDescribedProperty( wxPGProperty* p )
1515 {
1516 if ( m_pTxtHelpCaption )
1517 {
1518 if ( p )
1519 {
1520 SetDescription( p->GetLabel(), p->GetHelpString() );
1521 }
1522 else
1523 {
1524 SetDescription( wxEmptyString, wxEmptyString );
1525 }
1526 }
1527 }
1528
1529 // -----------------------------------------------------------------------
1530
1531 void wxPropertyGridManager::SetSplitterLeft( bool subProps, bool allPages )
1532 {
1533 if ( !allPages )
1534 {
1535 m_pPropGrid->SetSplitterLeft(subProps);
1536 }
1537 else
1538 {
1539 wxClientDC dc(this);
1540 dc.SetFont(m_pPropGrid->GetFont());
1541
1542 int highest = 0;
1543 unsigned int i;
1544
1545 for ( i=0; i<GetPageCount(); i++ )
1546 {
1547 int maxW = m_pState->GetColumnFitWidth(dc, m_arrPages[i]->m_properties, 0, subProps );
1548 maxW += m_pPropGrid->m_marginWidth;
1549 if ( maxW > highest )
1550 highest = maxW;
1551 }
1552
1553 if ( highest > 0 )
1554 m_pPropGrid->SetSplitterPosition( highest );
1555
1556 m_pPropGrid->m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER;
1557 }
1558 }
1559
1560 // -----------------------------------------------------------------------
1561
1562 void wxPropertyGridManager::OnPropertyGridSelect( wxPropertyGridEvent& event )
1563 {
1564 // Check id.
1565 wxASSERT_MSG( GetId() == m_pPropGrid->GetId(),
1566 wxT("wxPropertyGridManager id must be set with wxPropertyGridManager::SetId (not wxWindow::SetId).") );
1567
1568 SetDescribedProperty(event.GetProperty());
1569 event.Skip();
1570 }
1571
1572 // -----------------------------------------------------------------------
1573
1574 void wxPropertyGridManager::OnResize( wxSizeEvent& WXUNUSED(event) )
1575 {
1576 int width, height;
1577
1578 GetClientSize(&width,&height);
1579
1580 if ( m_width == -12345 )
1581 RecreateControls();
1582
1583 RecalculatePositions(width,height);
1584 }
1585
1586 // -----------------------------------------------------------------------
1587
1588 void wxPropertyGridManager::OnMouseEntry( wxMouseEvent& WXUNUSED(event) )
1589 {
1590 // Correct cursor. This is required atleast for wxGTK, for which
1591 // setting button's cursor to *wxSTANDARD_CURSOR does not work.
1592 SetCursor( wxNullCursor );
1593 m_onSplitter = 0;
1594 }
1595
1596 // -----------------------------------------------------------------------
1597
1598 void wxPropertyGridManager::OnMouseMove( wxMouseEvent &event )
1599 {
1600 if ( !m_pTxtHelpCaption )
1601 return;
1602
1603 int y = event.m_y;
1604
1605 if ( m_dragStatus > 0 )
1606 {
1607 int sy = y - m_dragOffset;
1608
1609 // Calculate drag limits
1610 int bottom_limit = m_height - m_splitterHeight + 1;
1611 int top_limit = m_pPropGrid->m_lineHeight;
1612 #if wxUSE_TOOLBAR
1613 if ( m_pToolbar ) top_limit += m_pToolbar->GetSize().y;
1614 #endif
1615
1616 if ( sy >= top_limit && sy < bottom_limit )
1617 {
1618
1619 int change = sy - m_splitterY;
1620 if ( change )
1621 {
1622 m_splitterY = sy;
1623
1624 m_pPropGrid->SetSize( m_width, m_splitterY - m_pPropGrid->GetPosition().y );
1625 UpdateDescriptionBox( m_splitterY, m_width, m_height );
1626
1627 m_extraHeight -= change;
1628 InvalidateBestSize();
1629 }
1630
1631 }
1632
1633 }
1634 else
1635 {
1636 if ( y >= m_splitterY && y < (m_splitterY+m_splitterHeight+2) )
1637 {
1638 SetCursor ( m_cursorSizeNS );
1639 m_onSplitter = 1;
1640 }
1641 else
1642 {
1643 if ( m_onSplitter )
1644 {
1645 SetCursor ( wxNullCursor );
1646 }
1647 m_onSplitter = 0;
1648 }
1649 }
1650 }
1651
1652 // -----------------------------------------------------------------------
1653
1654 void wxPropertyGridManager::OnMouseClick( wxMouseEvent &event )
1655 {
1656 int y = event.m_y;
1657
1658 // Click on splitter.
1659 if ( y >= m_splitterY && y < (m_splitterY+m_splitterHeight+2) )
1660 {
1661 if ( m_dragStatus == 0 )
1662 {
1663 //
1664 // Begin draggin the splitter
1665 //
1666
1667 BEGIN_MOUSE_CAPTURE
1668
1669 m_dragStatus = 1;
1670
1671 m_dragOffset = y - m_splitterY;
1672
1673 }
1674 }
1675 }
1676
1677 // -----------------------------------------------------------------------
1678
1679 void wxPropertyGridManager::OnMouseUp( wxMouseEvent &event )
1680 {
1681 // No event type check - basicly calling this method should
1682 // just stop dragging.
1683
1684 if ( m_dragStatus >= 1 )
1685 {
1686 //
1687 // End Splitter Dragging
1688 //
1689
1690 int y = event.m_y;
1691
1692 // DO NOT ENABLE FOLLOWING LINE!
1693 // (it is only here as a reminder to not to do it)
1694 //m_splitterY = y;
1695
1696 // This is necessary to return cursor
1697 END_MOUSE_CAPTURE
1698
1699 // Set back the default cursor, if necessary
1700 if ( y < m_splitterY || y >= (m_splitterY+m_splitterHeight+2) )
1701 {
1702 SetCursor ( wxNullCursor );
1703 }
1704
1705 m_dragStatus = 0;
1706 }
1707 }
1708
1709 // -----------------------------------------------------------------------
1710
1711 void wxPropertyGridManager::SetSplitterPosition( int pos, int splitterColumn )
1712 {
1713 wxASSERT_MSG( GetPageCount(),
1714 wxT("SetSplitterPosition() has no effect until pages have been added") );
1715
1716 size_t i;
1717 for ( i=0; i<GetPageCount(); i++ )
1718 {
1719 wxPropertyGridPage* page = GetPage(i);
1720 page->DoSetSplitterPosition( pos, splitterColumn, false );
1721 }
1722
1723 m_pPropGrid->SetInternalFlag(wxPG_FL_SPLITTER_PRE_SET);
1724 }
1725
1726 // -----------------------------------------------------------------------
1727 // wxPGVIterator_Manager
1728 // -----------------------------------------------------------------------
1729
1730 // Default returned by wxPropertyGridInterface::CreateVIterator().
1731 class wxPGVIteratorBase_Manager : public wxPGVIteratorBase
1732 {
1733 public:
1734 wxPGVIteratorBase_Manager( wxPropertyGridManager* manager, int flags )
1735 : m_manager(manager), m_flags(flags), m_curPage(0)
1736 {
1737 m_it.Init(manager->GetPage(0), flags);
1738 }
1739 virtual ~wxPGVIteratorBase_Manager() { }
1740 virtual void Next()
1741 {
1742 m_it.Next();
1743
1744 // Next page?
1745 if ( m_it.AtEnd() )
1746 {
1747 m_curPage++;
1748 if ( m_curPage < m_manager->GetPageCount() )
1749 m_it.Init( m_manager->GetPage(m_curPage), m_flags );
1750 }
1751 }
1752 private:
1753 wxPropertyGridManager* m_manager;
1754 int m_flags;
1755 unsigned int m_curPage;
1756 };
1757
1758 wxPGVIterator wxPropertyGridManager::GetVIterator( int flags ) const
1759 {
1760 return wxPGVIterator( new wxPGVIteratorBase_Manager( (wxPropertyGridManager*)this, flags ) );
1761 }
1762
1763 #endif // wxUSE_PROPGRID