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