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