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