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