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