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