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