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