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