Call RecreateControls() if relevant window style flag was toggled
[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 m_nextDescBoxSize = ht;
1139 if ( refresh )
1140 RecalculatePositions(m_width, m_height);
1141 }
1142 }
1143
1144 // -----------------------------------------------------------------------
1145
1146 int wxPropertyGridManager::GetDescBoxHeight() const
1147 {
1148 return GetClientSize().y - m_splitterY;
1149 }
1150
1151 // -----------------------------------------------------------------------
1152
1153 void wxPropertyGridManager::OnPaint( wxPaintEvent& WXUNUSED(event) )
1154 {
1155 wxPaintDC dc(this);
1156
1157 // Update everything inside the box
1158 wxRect r = GetUpdateRegion().GetBox();
1159
1160 // Repaint splitter?
1161 int r_bottom = r.y + r.height;
1162 int splitter_bottom = m_splitterY + m_splitterHeight;
1163 if ( r.y < splitter_bottom && r_bottom >= m_splitterY )
1164 RepaintSplitter( dc, m_splitterY, m_width, m_height, false );
1165 }
1166
1167 // -----------------------------------------------------------------------
1168
1169 void wxPropertyGridManager::Refresh(bool eraseBackground, const wxRect* rect )
1170 {
1171 m_pPropGrid->Refresh(eraseBackground);
1172 wxWindow::Refresh(eraseBackground,rect);
1173 }
1174
1175 // -----------------------------------------------------------------------
1176
1177 void wxPropertyGridManager::RefreshProperty( wxPGProperty* p )
1178 {
1179 wxPropertyGrid* grid = p->GetGrid();
1180
1181 if ( GetPage(m_selPage)->GetStatePtr() == p->GetParent()->GetParentState() )
1182 grid->RefreshProperty(p);
1183 }
1184
1185 // -----------------------------------------------------------------------
1186
1187 void wxPropertyGridManager::RecreateControls()
1188 {
1189
1190 bool was_shown = IsShown();
1191 if ( was_shown )
1192 Show ( false );
1193
1194 wxWindowID baseId = m_pPropGrid->GetId();
1195 if ( baseId < 0 )
1196 baseId = wxPG_MAN_ALTERNATE_BASE_ID;
1197
1198 #if wxUSE_TOOLBAR
1199 if ( m_windowStyle & wxPG_TOOLBAR )
1200 {
1201 // Has toolbar.
1202 if ( !m_pToolbar )
1203 {
1204 m_pToolbar = new wxToolBar(this,baseId+ID_ADVTOOLBAR_OFFSET,
1205 wxDefaultPosition,wxDefaultSize,
1206 ((GetExtraStyle()&wxPG_EX_NO_FLAT_TOOLBAR)?0:wxTB_FLAT)
1207 /*| wxTB_HORIZONTAL | wxNO_BORDER*/ );
1208
1209 #if defined(__WXMSW__)
1210 // Eliminate toolbar flicker on XP
1211 // NOTE: Not enabled since it corrupts drawing somewhat.
1212
1213 /*
1214 #ifndef WS_EX_COMPOSITED
1215 #define WS_EX_COMPOSITED 0x02000000L
1216 #endif
1217
1218 HWND hWnd = (HWND)m_pToolbar->GetHWND();
1219
1220 ::SetWindowLong( hWnd, GWL_EXSTYLE,
1221 ::GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_COMPOSITED );
1222 */
1223
1224 #endif
1225
1226 m_pToolbar->SetCursor ( *wxSTANDARD_CURSOR );
1227
1228 if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) )
1229 {
1230 wxString desc1(_("Categorized Mode"));
1231 wxString desc2(_("Alphabetic Mode"));
1232 m_pToolbar->AddTool(baseId+ID_ADVTBITEMSBASE_OFFSET+0,
1233 desc1,wxBitmap ( (const char**)gs_xpm_catmode ),
1234 desc1,wxITEM_RADIO);
1235 m_pToolbar->AddTool(baseId+ID_ADVTBITEMSBASE_OFFSET+1,
1236 desc2,wxBitmap ( (const char**)gs_xpm_noncatmode ),
1237 desc2,wxITEM_RADIO);
1238 m_pToolbar->Realize();
1239 }
1240
1241 }
1242
1243 if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) )
1244 {
1245 // Toggle correct mode button.
1246 // TODO: This doesn't work in wxMSW (when changing,
1247 // both items will get toggled).
1248 int toggle_but_on_ind = ID_ADVTBITEMSBASE_OFFSET+0;
1249 int toggle_but_off_ind = ID_ADVTBITEMSBASE_OFFSET+1;
1250 if ( m_pPropGrid->m_pState->IsInNonCatMode() )
1251 {
1252 toggle_but_on_ind++;
1253 toggle_but_off_ind--;
1254 }
1255
1256 m_pToolbar->ToggleTool(baseId+toggle_but_on_ind,true);
1257 m_pToolbar->ToggleTool(baseId+toggle_but_off_ind,false);
1258 }
1259
1260 }
1261 else
1262 {
1263 // No toolbar.
1264 if ( m_pToolbar )
1265 m_pToolbar->Destroy();
1266 m_pToolbar = (wxToolBar*) NULL;
1267 }
1268 #endif
1269
1270 if ( m_windowStyle & wxPG_DESCRIPTION )
1271 {
1272 // Has help box.
1273 m_pPropGrid->m_iFlags |= (wxPG_FL_NOSTATUSBARHELP);
1274
1275 if ( !m_pTxtHelpCaption )
1276 {
1277 m_pTxtHelpCaption = new wxStaticText (this,baseId+ID_ADVHELPCAPTION_OFFSET,wxEmptyString);
1278 m_pTxtHelpCaption->SetFont( m_pPropGrid->m_captionFont );
1279 m_pTxtHelpCaption->SetCursor ( *wxSTANDARD_CURSOR );
1280 }
1281 if ( !m_pTxtHelpContent )
1282 {
1283 m_pTxtHelpContent = new wxStaticText (this,baseId+ID_ADVHELPCONTENT_OFFSET,
1284 wxEmptyString,wxDefaultPosition,wxDefaultSize,wxALIGN_LEFT|wxST_NO_AUTORESIZE);
1285 m_pTxtHelpContent->SetCursor ( *wxSTANDARD_CURSOR );
1286 }
1287 }
1288 else
1289 {
1290 // No help box.
1291 m_pPropGrid->m_iFlags &= ~(wxPG_FL_NOSTATUSBARHELP);
1292
1293 if ( m_pTxtHelpCaption )
1294 m_pTxtHelpCaption->Destroy();
1295
1296 m_pTxtHelpCaption = (wxStaticText*) NULL;
1297
1298 if ( m_pTxtHelpContent )
1299 m_pTxtHelpContent->Destroy();
1300
1301 m_pTxtHelpContent = (wxStaticText*) NULL;
1302 }
1303
1304 int width, height;
1305
1306 GetClientSize(&width,&height);
1307
1308 RecalculatePositions(width,height);
1309
1310 if ( was_shown )
1311 Show ( true );
1312 }
1313
1314 // -----------------------------------------------------------------------
1315
1316 wxPGProperty* wxPropertyGridManager::DoGetPropertyByName( const wxString& name ) const
1317 {
1318 size_t i;
1319 for ( i=0; i<GetPageCount(); i++ )
1320 {
1321 wxPropertyGridPageState* pState = m_arrPages[i]->GetStatePtr();
1322 wxPGProperty* p = pState->BaseGetPropertyByName(name);
1323 if ( p )
1324 {
1325 return p;
1326 }
1327 }
1328 return NULL;
1329 }
1330
1331 // -----------------------------------------------------------------------
1332
1333 bool wxPropertyGridManager::EnsureVisible( wxPGPropArg id )
1334 {
1335 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
1336
1337 wxPropertyGridPageState* parentState = p->GetParentState();
1338
1339 // Select correct page.
1340 if ( m_pPropGrid->m_pState != parentState )
1341 DoSelectPage( GetPageByState(parentState) );
1342
1343 return m_pPropGrid->EnsureVisible(id);
1344 }
1345
1346 // -----------------------------------------------------------------------
1347
1348 void wxPropertyGridManager::OnToolbarClick( wxCommandEvent &event )
1349 {
1350 int id = event.GetId();
1351 if ( id >= 0 )
1352 {
1353 int baseId = m_pPropGrid->GetId();
1354 if ( baseId < 0 )
1355 baseId = wxPG_MAN_ALTERNATE_BASE_ID;
1356
1357 if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 0 ) )
1358 {
1359 // Categorized mode.
1360 if ( m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES )
1361 m_pPropGrid->EnableCategories( true );
1362 }
1363 else if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 1 ) )
1364 {
1365 // Alphabetic mode.
1366 if ( !(m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES) )
1367 m_pPropGrid->EnableCategories( false );
1368 }
1369 else
1370 {
1371 // Page Switching.
1372
1373 int index = -1;
1374 size_t i;
1375 wxPropertyGridPage* pdc;
1376
1377 // Find page with given id.
1378 for ( i=0; i<GetPageCount(); i++ )
1379 {
1380 pdc = m_arrPages[i];
1381 if ( pdc->m_id == id )
1382 {
1383 index = i;
1384 break;
1385 }
1386 }
1387
1388 wxASSERT( index >= 0 );
1389
1390 if ( DoSelectPage( index ) )
1391 {
1392
1393 // Event dispatching must be last.
1394 m_pPropGrid->SendEvent( wxEVT_PG_PAGE_CHANGED, (wxPGProperty*) NULL );
1395
1396 }
1397 else
1398 {
1399 // TODO: Depress the old button on toolbar.
1400 }
1401
1402 }
1403 }
1404 }
1405
1406 // -----------------------------------------------------------------------
1407
1408 bool wxPropertyGridManager::SetEditableStateItem( const wxString& name, wxVariant value )
1409 {
1410 if ( name == wxS("descboxheight") )
1411 {
1412 SetDescBoxHeight(value.GetLong(), true);
1413 return true;
1414 }
1415 return false;
1416 }
1417
1418 // -----------------------------------------------------------------------
1419
1420 wxVariant wxPropertyGridManager::GetEditableStateItem( const wxString& name ) const
1421 {
1422 if ( name == wxS("descboxheight") )
1423 {
1424 return (long) GetDescBoxHeight();
1425 }
1426 return wxNullVariant;
1427 }
1428
1429 // -----------------------------------------------------------------------
1430
1431 void wxPropertyGridManager::SetDescription( const wxString& label, const wxString& content )
1432 {
1433 if ( m_pTxtHelpCaption )
1434 {
1435 wxSize osz1 = m_pTxtHelpCaption->GetSize();
1436 wxSize osz2 = m_pTxtHelpContent->GetSize();
1437
1438 m_pTxtHelpCaption->SetLabel(label);
1439 m_pTxtHelpContent->SetLabel(content);
1440
1441 m_pTxtHelpCaption->SetSize(-1,osz1.y);
1442 m_pTxtHelpContent->SetSize(-1,osz2.y);
1443
1444 if ( (m_iFlags & wxPG_FL_DESC_REFRESH_REQUIRED) || (osz2.x<(m_width-10)) )
1445 RefreshHelpBox( m_splitterY, m_width, m_height );
1446 }
1447 }
1448
1449 // -----------------------------------------------------------------------
1450
1451 void wxPropertyGridManager::SetDescribedProperty( wxPGProperty* p )
1452 {
1453 if ( m_pTxtHelpCaption )
1454 {
1455 if ( p )
1456 {
1457 SetDescription( p->GetLabel(), p->GetHelpString() );
1458 }
1459 else
1460 {
1461 m_pTxtHelpCaption->SetLabel(wxEmptyString);
1462 m_pTxtHelpContent->SetLabel(wxEmptyString);
1463 }
1464 }
1465 }
1466
1467 // -----------------------------------------------------------------------
1468
1469 void wxPropertyGridManager::SetSplitterLeft( bool subProps, bool allPages )
1470 {
1471 if ( !allPages )
1472 {
1473 m_pPropGrid->SetSplitterLeft(subProps);
1474 }
1475 else
1476 {
1477 wxClientDC dc(this);
1478 dc.SetFont(m_pPropGrid->m_font);
1479
1480 int highest = 0;
1481 unsigned int i;
1482
1483 for ( i=0; i<GetPageCount(); i++ )
1484 {
1485 int maxW = m_pState->GetColumnFitWidth(dc, m_arrPages[i]->m_properties, 0, subProps );
1486 maxW += m_pPropGrid->m_marginWidth;
1487 if ( maxW > highest )
1488 highest = maxW;
1489 }
1490
1491 if ( highest > 0 )
1492 m_pPropGrid->SetSplitterPosition( highest );
1493
1494 m_pPropGrid->m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER;
1495 }
1496 }
1497
1498 // -----------------------------------------------------------------------
1499
1500 void wxPropertyGridManager::OnPropertyGridSelect( wxPropertyGridEvent& event )
1501 {
1502 // Check id.
1503 wxASSERT_MSG( GetId() == m_pPropGrid->GetId(),
1504 wxT("wxPropertyGridManager id must be set with wxPropertyGridManager::SetId (not wxWindow::SetId).") );
1505
1506 SetDescribedProperty(event.GetProperty());
1507 event.Skip();
1508 }
1509
1510 // -----------------------------------------------------------------------
1511
1512 void wxPropertyGridManager::OnResize( wxSizeEvent& WXUNUSED(event) )
1513 {
1514 int width, height;
1515
1516 GetClientSize(&width,&height);
1517
1518 if ( m_width == -12345 )
1519 RecreateControls();
1520
1521 RecalculatePositions(width,height);
1522 }
1523
1524 // -----------------------------------------------------------------------
1525
1526 void wxPropertyGridManager::OnMouseEntry( wxMouseEvent& WXUNUSED(event) )
1527 {
1528 // Correct cursor. This is required atleast for wxGTK, for which
1529 // setting button's cursor to *wxSTANDARD_CURSOR does not work.
1530 SetCursor( wxNullCursor );
1531 m_onSplitter = 0;
1532 }
1533
1534 // -----------------------------------------------------------------------
1535
1536 void wxPropertyGridManager::OnMouseMove( wxMouseEvent &event )
1537 {
1538 if ( !m_pTxtHelpCaption )
1539 return;
1540
1541 int y = event.m_y;
1542
1543 if ( m_dragStatus > 0 )
1544 {
1545 int sy = y - m_dragOffset;
1546
1547 // Calculate drag limits
1548 int bottom_limit = m_height - m_splitterHeight + 1;
1549 int top_limit = m_pPropGrid->m_lineHeight;
1550 #if wxUSE_TOOLBAR
1551 if ( m_pToolbar ) top_limit += m_pToolbar->GetSize().y;
1552 #endif
1553
1554 if ( sy >= top_limit && sy < bottom_limit )
1555 {
1556
1557 int change = sy - m_splitterY;
1558 if ( change )
1559 {
1560 m_splitterY = sy;
1561
1562 m_pPropGrid->SetSize( m_width, m_splitterY - m_pPropGrid->GetPosition().y );
1563 RefreshHelpBox( m_splitterY, m_width, m_height );
1564
1565 m_extraHeight -= change;
1566 InvalidateBestSize();
1567 }
1568
1569 }
1570
1571 }
1572 else
1573 {
1574 if ( y >= m_splitterY && y < (m_splitterY+m_splitterHeight+2) )
1575 {
1576 SetCursor ( m_cursorSizeNS );
1577 m_onSplitter = 1;
1578 }
1579 else
1580 {
1581 if ( m_onSplitter )
1582 {
1583 SetCursor ( wxNullCursor );
1584 }
1585 m_onSplitter = 0;
1586 }
1587 }
1588 }
1589
1590 // -----------------------------------------------------------------------
1591
1592 void wxPropertyGridManager::OnMouseClick( wxMouseEvent &event )
1593 {
1594 int y = event.m_y;
1595
1596 // Click on splitter.
1597 if ( y >= m_splitterY && y < (m_splitterY+m_splitterHeight+2) )
1598 {
1599 if ( m_dragStatus == 0 )
1600 {
1601 //
1602 // Begin draggin the splitter
1603 //
1604
1605 BEGIN_MOUSE_CAPTURE
1606
1607 m_dragStatus = 1;
1608
1609 m_dragOffset = y - m_splitterY;
1610
1611 }
1612 }
1613 }
1614
1615 // -----------------------------------------------------------------------
1616
1617 void wxPropertyGridManager::OnMouseUp( wxMouseEvent &event )
1618 {
1619 // No event type check - basicly calling this method should
1620 // just stop dragging.
1621
1622 if ( m_dragStatus >= 1 )
1623 {
1624 //
1625 // End Splitter Dragging
1626 //
1627
1628 int y = event.m_y;
1629
1630 // DO NOT ENABLE FOLLOWING LINE!
1631 // (it is only here as a reminder to not to do it)
1632 //m_splitterY = y;
1633
1634 // This is necessary to return cursor
1635 END_MOUSE_CAPTURE
1636
1637 // Set back the default cursor, if necessary
1638 if ( y < m_splitterY || y >= (m_splitterY+m_splitterHeight+2) )
1639 {
1640 SetCursor ( wxNullCursor );
1641 }
1642
1643 m_dragStatus = 0;
1644 }
1645 }
1646
1647 // -----------------------------------------------------------------------
1648
1649 void wxPropertyGridManager::SetSplitterPosition( int pos, int splitterColumn )
1650 {
1651 wxASSERT_MSG( GetPageCount(),
1652 wxT("SetSplitterPosition() has no effect until pages have been added") );
1653
1654 size_t i;
1655 for ( i=0; i<GetPageCount(); i++ )
1656 {
1657 wxPropertyGridPage* page = GetPage(i);
1658 page->DoSetSplitterPositionThisPage( pos, splitterColumn );
1659 }
1660
1661 m_pPropGrid->SetInternalFlag(wxPG_FL_SPLITTER_PRE_SET);
1662 }
1663
1664 // -----------------------------------------------------------------------
1665 // wxPGVIterator_Manager
1666 // -----------------------------------------------------------------------
1667
1668 // Default returned by wxPropertyGridInterface::CreateVIterator().
1669 class wxPGVIteratorBase_Manager : public wxPGVIteratorBase
1670 {
1671 public:
1672 wxPGVIteratorBase_Manager( wxPropertyGridManager* manager, int flags )
1673 : m_manager(manager), m_flags(flags), m_curPage(0)
1674 {
1675 m_it.Init(manager->GetPage(0), flags);
1676 }
1677 virtual ~wxPGVIteratorBase_Manager() { }
1678 virtual void Next()
1679 {
1680 m_it.Next();
1681
1682 // Next page?
1683 if ( m_it.AtEnd() )
1684 {
1685 m_curPage++;
1686 if ( m_curPage < m_manager->GetPageCount() )
1687 m_it.Init( m_manager->GetPage(m_curPage), m_flags );
1688 }
1689 }
1690 private:
1691 wxPropertyGridManager* m_manager;
1692 int m_flags;
1693 unsigned int m_curPage;
1694 };
1695
1696 wxPGVIterator wxPropertyGridManager::GetVIterator( int flags ) const
1697 {
1698 return wxPGVIterator( new wxPGVIteratorBase_Manager( (wxPropertyGridManager*)this, flags ) );
1699 }
1700
1701 #endif // wxUSE_PROPGRID