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