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