]> git.saurik.com Git - wxWidgets.git/blame - src/propgrid/manager.cpp
Don't query metrics that won't be used.
[wxWidgets.git] / src / propgrid / manager.cpp
CommitLineData
1c4293cb
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/propgrid/manager.cpp
3// Purpose: wxPropertyGridManager
4// Author: Jaakko Salli
5// Modified by:
6// Created: 2005-01-14
ea5af9c5 7// RCS-ID: $Id$
1c4293cb
VZ
8// Copyright: (c) Jaakko Salli
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx/wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16 #pragma hdrstop
17#endif
18
f4bc1aa2
JS
19#if wxUSE_PROPGRID
20
1c4293cb
VZ
21#ifndef WX_PRECOMP
22 #include "wx/defs.h"
23 #include "wx/object.h"
24 #include "wx/hash.h"
25 #include "wx/string.h"
26 #include "wx/log.h"
27 #include "wx/event.h"
28 #include "wx/window.h"
29 #include "wx/panel.h"
30 #include "wx/dc.h"
31 #include "wx/pen.h"
32 #include "wx/brush.h"
33 #include "wx/cursor.h"
1c4293cb 34 #include "wx/settings.h"
1c4293cb 35 #include "wx/textctrl.h"
1c4293cb 36 #include "wx/sizer.h"
1c4293cb
VZ
37 #include "wx/statusbr.h"
38 #include "wx/intl.h"
39#endif
40
41// This define is necessary to prevent macro clearing
42#define __wxPG_SOURCE_FILE__
43
3b211af1 44#include "wx/propgrid/propgrid.h"
1c4293cb 45
3b211af1 46#include "wx/propgrid/manager.h"
1c4293cb
VZ
47
48
49#define wxPG_MAN_ALTERNATE_BASE_ID 11249 // Needed for wxID_ANY madnesss
50
51
52// -----------------------------------------------------------------------
53
54// For wxMSW cursor consistency, we must do mouse capturing even
55// when using custom controls
56
57#define BEGIN_MOUSE_CAPTURE \
58 if ( !(m_iFlags & wxPG_FL_MOUSE_CAPTURED) ) \
59 { \
60 CaptureMouse(); \
61 m_iFlags |= wxPG_FL_MOUSE_CAPTURED; \
62 }
63
64#define END_MOUSE_CAPTURE \
65 if ( m_iFlags & wxPG_FL_MOUSE_CAPTURED ) \
66 { \
67 ReleaseMouse(); \
68 m_iFlags &= ~(wxPG_FL_MOUSE_CAPTURED); \
69 }
70
71// -----------------------------------------------------------------------
72// wxPropertyGridManager
73// -----------------------------------------------------------------------
74
23318a53 75const char wxPropertyGridManagerNameStr[] = "wxPropertyGridManager";
1c4293cb
VZ
76
77
78// Categoric Mode Icon
a243da29 79static const char* const gs_xpm_catmode[] = {
1c4293cb
VZ
80"16 16 5 1",
81". c none",
82"B c black",
83"D c #868686",
84"L c #CACACA",
85"W c #FFFFFF",
86".DDD............",
87".DLD.BBBBBB.....",
88".DDD............",
89".....DDDDD.DDD..",
90"................",
91".....DDDDD.DDD..",
92"................",
93".....DDDDD.DDD..",
94"................",
95".....DDDDD.DDD..",
96"................",
97".DDD............",
98".DLD.BBBBBB.....",
99".DDD............",
100".....DDDDD.DDD..",
101"................"
102};
103
104// Alphabetic Mode Icon
a243da29 105static const char* const gs_xpm_noncatmode[] = {
1c4293cb
VZ
106"16 16 5 1",
107". c none",
108"B c black",
109"D c #868686",
110"L c #000080",
111"W c #FFFFFF",
112"..DBD...DDD.DDD.",
113".DB.BD..........",
114".BBBBB..DDD.DDD.",
115".B...B..........",
116"...L....DDD.DDD.",
117"...L............",
118".L.L.L..DDD.DDD.",
119"..LLL...........",
120"...L....DDD.DDD.",
121"................",
122".BBBBB..DDD.DDD.",
123"....BD..........",
124"...BD...DDD.DDD.",
125"..BD............",
126".BBBBB..DDD.DDD.",
127"................"
128};
129
130// Default Page Icon.
a243da29 131static const char* const gs_xpm_defpage[] = {
1c4293cb
VZ
132"16 16 5 1",
133". c none",
134"B c black",
135"D c #868686",
136"L c #000080",
137"W c #FFFFFF",
138"................",
139"................",
140"..BBBBBBBBBBBB..",
141"..B..........B..",
142"..B.BB.LLLLL.B..",
143"..B..........B..",
144"..B.BB.LLLLL.B..",
145"..B..........B..",
146"..B.BB.LLLLL.B..",
147"..B..........B..",
148"..B.BB.LLLLL.B..",
149"..B..........B..",
150"..BBBBBBBBBBBB..",
151"................",
152"................",
153"................"
154};
155
1c4293cb
VZ
156// -----------------------------------------------------------------------
157// wxPropertyGridPage
158// -----------------------------------------------------------------------
159
160
161IMPLEMENT_CLASS(wxPropertyGridPage, wxEvtHandler)
162
163
164BEGIN_EVENT_TABLE(wxPropertyGridPage, wxEvtHandler)
165END_EVENT_TABLE()
166
167
168wxPropertyGridPage::wxPropertyGridPage()
169 : wxEvtHandler(), wxPropertyGridInterface(), wxPropertyGridPageState()
170{
171 m_pState = this; // wxPropertyGridInterface to point to State
172 m_manager = NULL;
173 m_isDefault = false;
174}
175
176wxPropertyGridPage::~wxPropertyGridPage()
177{
178}
179
180void wxPropertyGridPage::Clear()
181{
182 GetStatePtr()->DoClear();
183}
184
185wxSize wxPropertyGridPage::FitColumns()
186{
187 wxSize sz = DoFitColumns();
188 return sz;
189}
190
191void wxPropertyGridPage::RefreshProperty( wxPGProperty* p )
192{
193 if ( m_manager )
194 m_manager->RefreshProperty(p);
195}
196
197void wxPropertyGridPage::OnShow()
198{
199}
200
201void wxPropertyGridPage::SetSplitterPosition( int splitterPos, int col )
202{
203 wxPropertyGrid* pg = GetGrid();
204 if ( pg->GetState() == this )
205 pg->SetSplitterPosition(splitterPos);
206 else
207 DoSetSplitterPosition(splitterPos, col, false);
208}
209
4311ac1e
VZ
210void wxPropertyGridPage::DoSetSplitterPosition( int pos,
211 int splitterColumn,
f5254768 212 int flags )
1c4293cb 213{
f5254768 214 if ( (flags & wxPG_SPLITTER_ALL_PAGES) && m_manager->GetPageCount() )
1c4293cb
VZ
215 m_manager->SetSplitterPosition( pos, splitterColumn );
216 else
77db639d
JS
217 wxPropertyGridPageState::DoSetSplitterPosition( pos,
218 splitterColumn,
f5254768 219 flags );
1c4293cb
VZ
220}
221
f5254768
JS
222// -----------------------------------------------------------------------
223// wxPGHeaderCtrl
224// -----------------------------------------------------------------------
225
226#if wxUSE_HEADERCTRL
227
228class wxPGHeaderCtrl : public wxHeaderCtrl
229{
230public:
231 wxPGHeaderCtrl(wxPropertyGridManager* manager) :
232 wxHeaderCtrl()
233 {
234 m_manager = manager;
235 EnsureColumnCount(2);
236
237 // Seed titles with defaults
238 m_columns[0]->SetTitle(_("Property"));
239 m_columns[1]->SetTitle(_("Value"));
240 }
241
242 virtual ~wxPGHeaderCtrl()
243 {
244 for (unsigned int i=0; i<m_columns.size(); i++ )
245 delete m_columns[i];
246 }
247
248 int DetermineColumnWidth(unsigned int idx, int* pMinWidth) const
249 {
250 const wxPropertyGridPage* page = m_page;
251 int colWidth = page->GetColumnWidth(idx);
252 int colMinWidth = page->GetColumnMinWidth(idx);
253 if ( idx == 0 )
254 {
255 wxPropertyGrid* pg = m_manager->GetGrid();
256 int margin = pg->GetMarginWidth();
257
258 // Compensate for the internal border
259 margin += (pg->GetSize().x - pg->GetClientSize().x) / 2;
260
261 colWidth += margin;
262 colMinWidth += margin;
263 }
264 *pMinWidth = colMinWidth;
265 return colWidth;
266 }
267
268 void OnPageChanged(const wxPropertyGridPage* page)
269 {
270 m_page = page;
271 OnPageUpdated();
272 }
273
274 void OnPageUpdated()
275 {
276 // Get column info from the page
277 const wxPropertyGridPage* page = m_page;
278 unsigned int colCount = page->GetColumnCount();
279 EnsureColumnCount(colCount);
280
281 for ( unsigned int i=0; i<colCount; i++ )
282 {
283 wxHeaderColumnSimple* colInfo = m_columns[i];
284 int colMinWidth = 0;
285 int colWidth = DetermineColumnWidth(i, &colMinWidth);
286 colInfo->SetWidth(colWidth);
287 colInfo->SetMinWidth(colMinWidth);
288 }
289
290 SetColumnCount(colCount);
291 }
292
293 void OnColumWidthsChanged()
294 {
295 const wxPropertyGridPage* page = m_page;
296 unsigned int colCount = page->GetColumnCount();
297
298 for ( unsigned int i=0; i<colCount; i++ )
299 {
300 wxHeaderColumnSimple* colInfo = m_columns[i];
301 int colMinWidth = 0;
302 int colWidth = DetermineColumnWidth(i, &colMinWidth);
303 colInfo->SetWidth(colWidth);
304 colInfo->SetMinWidth(colMinWidth);
305 UpdateColumn(i);
306 }
307 }
308
309 virtual const wxHeaderColumn& GetColumn(unsigned int idx) const
310 {
311 return *m_columns[idx];
312 }
313
314 void SetColumnTitle(unsigned int idx, const wxString& title)
315 {
316 EnsureColumnCount(idx+1);
317 m_columns[idx]->SetTitle(title);
318 }
319
320private:
321 void EnsureColumnCount(unsigned int count)
322 {
323 while ( m_columns.size() < count )
324 {
325 wxHeaderColumnSimple* colInfo = new wxHeaderColumnSimple("");
326 m_columns.push_back(colInfo);
327 }
328 }
329
330 void OnSetColumnWidth(int col, int colWidth)
331 {
332 wxPropertyGrid* pg = m_manager->GetGrid();
333
334 // Compensate for the internal border
335 int x = -((pg->GetSize().x - pg->GetClientSize().x) / 2);
336
337 for ( int i=0; i<col; i++ )
338 x += m_columns[i]->GetWidth();
339
340 x += colWidth;
341
342 pg->DoSetSplitterPosition(x, col,
343 wxPG_SPLITTER_REFRESH |
344 wxPG_SPLITTER_FROM_EVENT);
345 }
346
347 virtual bool ProcessEvent( wxEvent& event )
348 {
349 if ( event.IsKindOf(CLASSINFO(wxHeaderCtrlEvent)) )
350 {
351 wxHeaderCtrlEvent& hcEvent =
352 static_cast<wxHeaderCtrlEvent&>(event);
353
354 wxPropertyGrid* pg = m_manager->GetGrid();
355 int col = hcEvent.GetColumn();
356 int evtType = event.GetEventType();
357
358 if ( evtType == wxEVT_COMMAND_HEADER_RESIZING )
359 {
360 int colWidth = hcEvent.GetWidth();
361
362 OnSetColumnWidth(col, colWidth);
363
364 pg->SendEvent(wxEVT_PG_COL_DRAGGING,
365 NULL, NULL, 0,
366 (unsigned int)col);
367
368 return true;
369 }
370 else if ( evtType == wxEVT_COMMAND_HEADER_BEGIN_RESIZE )
371 {
372 // Never allow column resize if layout is static
373 if ( m_manager->HasFlag(wxPG_STATIC_SPLITTER) )
374 hcEvent.Veto();
375 // Allow application to veto dragging
376 else if ( pg->SendEvent(wxEVT_PG_COL_BEGIN_DRAG,
377 NULL, NULL, 0,
378 (unsigned int)col) )
379 hcEvent.Veto();
380
381 return true;
382 }
383 else if ( evtType == wxEVT_COMMAND_HEADER_END_RESIZE )
384 {
385 pg->SendEvent(wxEVT_PG_COL_END_DRAG,
386 NULL, NULL, 0,
387 (unsigned int)col);
388
389 return true;
390 }
391 }
392
393 return wxHeaderCtrl::ProcessEvent(event);
394 }
395
396 wxPropertyGridManager* m_manager;
397 const wxPropertyGridPage* m_page;
398 wxVector<wxHeaderColumnSimple*> m_columns;
399};
400
401#endif // wxUSE_HEADERCTRL
402
1c4293cb
VZ
403// -----------------------------------------------------------------------
404// wxPropertyGridManager
405// -----------------------------------------------------------------------
406
407// Final default splitter y is client height minus this.
408#define wxPGMAN_DEFAULT_NEGATIVE_SPLITTER_Y 100
409
410// -----------------------------------------------------------------------
411
412IMPLEMENT_CLASS(wxPropertyGridManager, wxPanel)
413
414#define ID_ADVTOOLBAR_OFFSET 1
415#define ID_ADVHELPCAPTION_OFFSET 2
416#define ID_ADVHELPCONTENT_OFFSET 3
f5254768 417#define ID_ADVHEADERCTRL_OFFSET 4
1c4293cb
VZ
418#define ID_ADVTBITEMSBASE_OFFSET 5 // Must be last.
419
420// -----------------------------------------------------------------------
421
422BEGIN_EVENT_TABLE(wxPropertyGridManager, wxPanel)
423 EVT_MOTION(wxPropertyGridManager::OnMouseMove)
424 EVT_SIZE(wxPropertyGridManager::OnResize)
425 EVT_PAINT(wxPropertyGridManager::OnPaint)
426 EVT_LEFT_DOWN(wxPropertyGridManager::OnMouseClick)
427 EVT_LEFT_UP(wxPropertyGridManager::OnMouseUp)
428 EVT_LEAVE_WINDOW(wxPropertyGridManager::OnMouseEntry)
429 //EVT_ENTER_WINDOW(wxPropertyGridManager::OnMouseEntry)
430END_EVENT_TABLE()
431
432// -----------------------------------------------------------------------
433
434wxPropertyGridManager::wxPropertyGridManager()
435 : wxPanel()
436{
437 Init1();
438}
439
440// -----------------------------------------------------------------------
441
442wxPropertyGridManager::wxPropertyGridManager( wxWindow *parent,
443 wxWindowID id,
444 const wxPoint& pos,
445 const wxSize& size,
446 long style,
23318a53 447 const wxString& name )
1c4293cb
VZ
448 : wxPanel()
449{
450 Init1();
451 Create(parent,id,pos,size,style,name);
452}
453
454// -----------------------------------------------------------------------
455
456bool wxPropertyGridManager::Create( wxWindow *parent,
457 wxWindowID id,
458 const wxPoint& pos,
459 const wxSize& size,
460 long style,
23318a53 461 const wxString& name )
1c4293cb 462{
3cfde7c0
JS
463 if ( !m_pPropGrid )
464 m_pPropGrid = CreatePropertyGrid();
1c4293cb
VZ
465
466 bool res = wxPanel::Create( parent, id, pos, size,
467 (style&0xFFFF0000)|wxWANTS_CHARS,
468 name );
469 Init2(style);
470
521f1d83
JS
471 // FIXME: this changes call ordering so wxPropertyGrid is created
472 // immediately, before SetExtraStyle has a chance to be called. However,
473 // without it, we may get assertions if size is wxDefaultSize.
474 //SetInitialSize(size);
475
1c4293cb
VZ
476 return res;
477}
478
479// -----------------------------------------------------------------------
480
481//
482// Initialize values to defaults
483//
484void wxPropertyGridManager::Init1()
485{
486
3cfde7c0 487 m_pPropGrid = NULL;
1c4293cb
VZ
488
489#if wxUSE_TOOLBAR
d3b9f782 490 m_pToolbar = NULL;
f5254768
JS
491#endif
492#if wxUSE_HEADERCTRL
493 m_pHeaderCtrl = NULL;
494 m_showHeader = false;
1c4293cb 495#endif
d3b9f782
VZ
496 m_pTxtHelpCaption = NULL;
497 m_pTxtHelpContent = NULL;
1c4293cb 498
d3b9f782 499 m_emptyPage = NULL;
1c4293cb
VZ
500
501 m_selPage = -1;
502
503 m_width = m_height = 0;
504
505 m_splitterHeight = 5;
506
507 m_splitterY = -1; // -1 causes default to be set.
508
509 m_nextDescBoxSize = -1;
510
511 m_extraHeight = 0;
512 m_dragStatus = 0;
513 m_onSplitter = 0;
514 m_iFlags = 0;
515}
516
517// -----------------------------------------------------------------------
518
519// These flags are always used in wxPropertyGrid integrated in wxPropertyGridManager.
521f1d83 520#define wxPG_MAN_PROPGRID_FORCED_FLAGS ( wxBORDER_THEME | \
1c4293cb
VZ
521 wxNO_FULL_REPAINT_ON_RESIZE| \
522 wxCLIP_CHILDREN)
1c4293cb
VZ
523
524// Which flags can be passed to underlying wxPropertyGrid.
525#define wxPG_MAN_PASS_FLAGS_MASK (0xFFF0|wxTAB_TRAVERSAL)
526
527//
528// Initialize after parent etc. set
529//
530void wxPropertyGridManager::Init2( int style )
531{
532
533 if ( m_iFlags & wxPG_FL_INITIALIZED )
534 return;
535
536 m_windowStyle |= (style&0x0000FFFF);
537
538 wxSize csz = GetClientSize();
539
540 m_cursorSizeNS = wxCursor(wxCURSOR_SIZENS);
541
542 // Prepare the first page
543 // NB: But just prepare - you still need to call Add/InsertPage
544 // to actually add properties on it.
545 wxPropertyGridPage* pd = new wxPropertyGridPage();
546 pd->m_isDefault = true;
547 pd->m_manager = this;
548 wxPropertyGridPageState* state = pd->GetStatePtr();
549 state->m_pPropGrid = m_pPropGrid;
f7a094e1 550 m_arrPages.push_back( pd );
1c4293cb
VZ
551 m_pPropGrid->m_pState = state;
552
553 wxWindowID baseId = GetId();
554 wxWindowID useId = baseId;
555 if ( baseId < 0 )
556 baseId = wxPG_MAN_ALTERNATE_BASE_ID;
557
558 m_baseId = baseId;
559
560#ifdef __WXMAC__
561 // Smaller controls on Mac
562 SetWindowVariant(wxWINDOW_VARIANT_SMALL);
23318a53 563#endif
1c4293cb 564
521f1d83
JS
565 long propGridFlags = (m_windowStyle&wxPG_MAN_PASS_FLAGS_MASK)
566 |wxPG_MAN_PROPGRID_FORCED_FLAGS;
567
568 propGridFlags &= ~wxBORDER_MASK;
569
570 if ((style & wxPG_NO_INTERNAL_BORDER) == 0)
571 {
572 propGridFlags |= wxBORDER_THEME;
573 }
574 else
575 {
576 propGridFlags |= wxBORDER_NONE;
577 wxWindow::SetExtraStyle(wxPG_EX_TOOLBAR_SEPARATOR);
578 }
579
1c4293cb 580 // Create propertygrid.
521f1d83 581 m_pPropGrid->Create(this,baseId,wxPoint(0,0),csz, propGridFlags);
1c4293cb
VZ
582
583 m_pPropGrid->m_eventObject = this;
584
585 m_pPropGrid->SetId(useId);
586
587 m_pPropGrid->m_iFlags |= wxPG_FL_IN_MANAGER;
588
589 m_pState = m_pPropGrid->m_pState;
590
591 m_pPropGrid->SetExtraStyle(wxPG_EX_INIT_NOCAT);
592
593 m_nextTbInd = baseId+ID_ADVTBITEMSBASE_OFFSET + 2;
594
595
596 // Connect to property grid onselect event.
597 // NB: Even if wxID_ANY is used, this doesn't connect properly in wxPython
598 // (see wxPropertyGridManager::ProcessEvent).
f5254768
JS
599 Connect(m_pPropGrid->GetId(),
600 wxEVT_PG_SELECTED,
601 wxPropertyGridEventHandler(wxPropertyGridManager::OnPropertyGridSelect));
602
603 Connect(m_pPropGrid->GetId(),
604 wxEVT_PG_COL_DRAGGING,
605 wxPropertyGridEventHandler(wxPropertyGridManager::OnPGColDrag));
1c4293cb
VZ
606
607 // Connect to toolbar button events.
608 Connect(baseId+ID_ADVTBITEMSBASE_OFFSET,baseId+ID_ADVTBITEMSBASE_OFFSET+50,
609 wxEVT_COMMAND_TOOL_CLICKED,
610 wxCommandEventHandler(wxPropertyGridManager::OnToolbarClick) );
611
612 // Optional initial controls.
613 m_width = -12345;
614
615 m_iFlags |= wxPG_FL_INITIALIZED;
616
617}
618
619// -----------------------------------------------------------------------
620
621wxPropertyGridManager::~wxPropertyGridManager()
622{
623 END_MOUSE_CAPTURE
624
fc72fab6
JS
625 //m_pPropGrid->ClearSelection();
626 delete m_pPropGrid;
627 m_pPropGrid = NULL;
1c4293cb
VZ
628
629 size_t i;
f7a094e1 630 for ( i=0; i<m_arrPages.size(); i++ )
1c4293cb 631 {
f7a094e1 632 delete m_arrPages[i];
1c4293cb
VZ
633 }
634
635 delete m_emptyPage;
636}
637
638// -----------------------------------------------------------------------
639
640wxPropertyGrid* wxPropertyGridManager::CreatePropertyGrid() const
641{
642 return new wxPropertyGrid();
643}
644
645// -----------------------------------------------------------------------
646
647void wxPropertyGridManager::SetId( wxWindowID winid )
648{
649 wxWindow::SetId(winid);
650
651 // TODO: Reconnect propgrid event handler(s).
652
653 m_pPropGrid->SetId(winid);
654}
655
656// -----------------------------------------------------------------------
657
658wxSize wxPropertyGridManager::DoGetBestSize() const
659{
660 return wxSize(60,150);
661}
662
663// -----------------------------------------------------------------------
664
665bool wxPropertyGridManager::SetFont( const wxFont& font )
666{
667 bool res = wxWindow::SetFont(font);
668 m_pPropGrid->SetFont(font);
669
670 // TODO: Need to do caption recacalculations for other pages as well.
671 unsigned int i;
f7a094e1 672 for ( i=0; i<m_arrPages.size(); i++ )
1c4293cb
VZ
673 {
674 wxPropertyGridPage* page = GetPage(i);
675
676 if ( page != m_pPropGrid->GetState() )
677 page->CalculateFontAndBitmapStuff(-1);
678 }
679
680 return res;
681}
682
683// -----------------------------------------------------------------------
684
685void wxPropertyGridManager::SetExtraStyle( long exStyle )
686{
687 wxWindow::SetExtraStyle( exStyle );
688 m_pPropGrid->SetExtraStyle( exStyle & 0xFFFFF000 );
689#if wxUSE_TOOLBAR
690 if ( (exStyle & wxPG_EX_NO_FLAT_TOOLBAR) && m_pToolbar )
691 RecreateControls();
692#endif
693}
694
695// -----------------------------------------------------------------------
696
697void wxPropertyGridManager::Freeze()
698{
699 m_pPropGrid->Freeze();
700 wxWindow::Freeze();
701}
702
703// -----------------------------------------------------------------------
704
705void wxPropertyGridManager::Thaw()
706{
707 wxWindow::Thaw();
708 m_pPropGrid->Thaw();
709}
710
711// -----------------------------------------------------------------------
712
713void wxPropertyGridManager::SetWindowStyleFlag( long style )
714{
c3e57ac4
JS
715 int oldWindowStyle = GetWindowStyleFlag();
716
1c4293cb
VZ
717 wxWindow::SetWindowStyleFlag( style );
718 m_pPropGrid->SetWindowStyleFlag( (m_pPropGrid->GetWindowStyleFlag()&~(wxPG_MAN_PASS_FLAGS_MASK)) |
719 (style&wxPG_MAN_PASS_FLAGS_MASK) );
c3e57ac4
JS
720
721 // Need to re-position windows?
23318a53 722 if ( (oldWindowStyle & (wxPG_TOOLBAR|wxPG_DESCRIPTION)) !=
c3e57ac4
JS
723 (style & (wxPG_TOOLBAR|wxPG_DESCRIPTION)) )
724 {
725 RecreateControls();
726 }
1c4293cb
VZ
727}
728
729// -----------------------------------------------------------------------
730
27c1f235
JS
731bool wxPropertyGridManager::Reparent( wxWindowBase *newParent )
732{
733 if ( m_pPropGrid )
734 m_pPropGrid->OnTLPChanging((wxWindow*)newParent);
735
736 bool res = wxPanel::Reparent(newParent);
737
738 return res;
739}
740
741// -----------------------------------------------------------------------
742
1c4293cb
VZ
743// Actually shows given page.
744bool wxPropertyGridManager::DoSelectPage( int index )
745{
746 // -1 means no page was selected
747 //wxASSERT( m_selPage >= 0 );
748
749 wxCHECK_MSG( index >= -1 && index < (int)GetPageCount(),
750 false,
751 wxT("invalid page index") );
752
753 if ( m_selPage == index )
754 return true;
755
fc72fab6 756 if ( m_pPropGrid->GetSelection() )
1c4293cb
VZ
757 {
758 if ( !m_pPropGrid->ClearSelection() )
759 return false;
760 }
761
762 wxPropertyGridPage* prevPage;
763
764 if ( m_selPage >= 0 )
765 prevPage = GetPage(m_selPage);
766 else
767 prevPage = m_emptyPage;
768
769 wxPropertyGridPage* nextPage;
770
771 if ( index >= 0 )
772 {
f7a094e1 773 nextPage = m_arrPages[index];
1c4293cb
VZ
774
775 nextPage->OnShow();
776 }
777 else
778 {
779 if ( !m_emptyPage )
780 {
781 m_emptyPage = new wxPropertyGridPage();
782 m_emptyPage->m_pPropGrid = m_pPropGrid;
783 }
784
785 nextPage = m_emptyPage;
786 }
787
788 m_iFlags |= wxPG_FL_DESC_REFRESH_REQUIRED;
789
790 m_pPropGrid->SwitchState( nextPage->GetStatePtr() );
791
792 m_pState = m_pPropGrid->m_pState;
793
794 m_selPage = index;
795
796#if wxUSE_TOOLBAR
797 if ( m_pToolbar )
798 {
799 if ( index >= 0 )
800 m_pToolbar->ToggleTool( nextPage->m_id, true );
801 else
802 m_pToolbar->ToggleTool( prevPage->m_id, false );
803 }
804#endif
805
f5254768
JS
806#if wxUSE_HEADERCTRL
807 if ( m_showHeader )
808 m_pHeaderCtrl->OnPageChanged(nextPage);
809#endif
810
1c4293cb
VZ
811 return true;
812}
813
814// -----------------------------------------------------------------------
815
816// Changes page *and* set the target page for insertion operations.
817void wxPropertyGridManager::SelectPage( int index )
818{
819 DoSelectPage(index);
820}
821
822// -----------------------------------------------------------------------
823
824int wxPropertyGridManager::GetPageByName( const wxString& name ) const
825{
826 size_t i;
827 for ( i=0; i<GetPageCount(); i++ )
828 {
f7a094e1 829 if ( m_arrPages[i]->m_label == name )
1c4293cb
VZ
830 return i;
831 }
832 return wxNOT_FOUND;
833}
834
835// -----------------------------------------------------------------------
836
837int wxPropertyGridManager::GetPageByState( const wxPropertyGridPageState* pState ) const
838{
839 wxASSERT( pState );
840
841 size_t i;
842 for ( i=0; i<GetPageCount(); i++ )
843 {
f7a094e1 844 if ( pState == m_arrPages[i]->GetStatePtr() )
1c4293cb
VZ
845 return i;
846 }
847
848 return wxNOT_FOUND;
849}
850
851// -----------------------------------------------------------------------
852
853const wxString& wxPropertyGridManager::GetPageName( int index ) const
854{
855 wxASSERT( index >= 0 && index < (int)GetPageCount() );
f7a094e1 856 return m_arrPages[index]->m_label;
1c4293cb
VZ
857}
858
859// -----------------------------------------------------------------------
860
861wxPropertyGridPageState* wxPropertyGridManager::GetPageState( int page ) const
862{
863 // Do not change this into wxCHECK because returning NULL is important
864 // for wxPropertyGridInterface page enumeration mechanics.
865 if ( page >= (int)GetPageCount() )
866 return NULL;
867
868 if ( page == -1 )
869 return m_pState;
f7a094e1 870 return m_arrPages[page];
1c4293cb
VZ
871}
872
873// -----------------------------------------------------------------------
874
875void wxPropertyGridManager::Clear()
876{
8dee26e1
JS
877 m_pPropGrid->ClearSelection(false);
878
1c4293cb
VZ
879 m_pPropGrid->Freeze();
880
881 int i;
882 for ( i=(int)GetPageCount()-1; i>=0; i-- )
883 RemovePage(i);
884
885 // Reset toolbar ids
886 m_nextTbInd = m_baseId+ID_ADVTBITEMSBASE_OFFSET + 2;
887
888 m_pPropGrid->Thaw();
889}
890
891// -----------------------------------------------------------------------
892
893void wxPropertyGridManager::ClearPage( int page )
894{
895 wxASSERT( page >= 0 );
896 wxASSERT( page < (int)GetPageCount() );
897
898 if ( page >= 0 && page < (int)GetPageCount() )
899 {
f7a094e1 900 wxPropertyGridPageState* state = m_arrPages[page];
1c4293cb
VZ
901
902 if ( state == m_pPropGrid->GetState() )
903 m_pPropGrid->Clear();
904 else
905 state->DoClear();
906 }
907}
908
909// -----------------------------------------------------------------------
910
911int wxPropertyGridManager::GetColumnCount( int page ) const
912{
913 wxASSERT( page >= -1 );
914 wxASSERT( page < (int)GetPageCount() );
915
916 return GetPageState(page)->GetColumnCount();
917}
918
919// -----------------------------------------------------------------------
920
921void wxPropertyGridManager::SetColumnCount( int colCount, int page )
922{
923 wxASSERT( page >= -1 );
924 wxASSERT( page < (int)GetPageCount() );
925
926 GetPageState(page)->SetColumnCount( colCount );
927 GetGrid()->Refresh();
f5254768
JS
928
929#if wxUSE_HEADERCTRL
930 if ( m_showHeader )
931 m_pHeaderCtrl->OnPageUpdated();
932#endif
1c4293cb
VZ
933}
934// -----------------------------------------------------------------------
935
1c4293cb
VZ
936size_t wxPropertyGridManager::GetPageCount() const
937{
03647350
VZ
938 if ( !(m_iFlags & wxPG_MAN_FL_PAGE_INSERTED) )
939 return 0;
1c4293cb 940
03647350 941 return m_arrPages.size();
1c4293cb
VZ
942}
943
944// -----------------------------------------------------------------------
945
9288df34
JS
946wxPropertyGridPage* wxPropertyGridManager::InsertPage( int index,
947 const wxString& label,
948 const wxBitmap& bmp,
949 wxPropertyGridPage* pageObj )
1c4293cb
VZ
950{
951 if ( index < 0 )
952 index = GetPageCount();
953
9288df34 954 wxCHECK_MSG( (size_t)index == GetPageCount(), NULL,
1c4293cb
VZ
955 wxT("wxPropertyGridManager currently only supports appending pages (due to wxToolBar limitation)."));
956
957 bool needInit = true;
958 bool isPageInserted = m_iFlags & wxPG_MAN_FL_PAGE_INSERTED ? true : false;
959
960 wxASSERT( index == 0 || isPageInserted );
961
962 if ( !pageObj )
963 {
964 // No custom page object was given, so we will either re-use the default base
965 // page (if index==0), or create a new default page object.
966 if ( !isPageInserted )
967 {
968 pageObj = GetPage(0);
969 // Of course, if the base page was custom, we need to delete and
970 // re-create it.
971 if ( !pageObj->m_isDefault )
972 {
973 delete pageObj;
974 pageObj = new wxPropertyGridPage();
975 m_arrPages[0] = pageObj;
976 }
977 needInit = false;
978 }
979 else
980 {
981 pageObj = new wxPropertyGridPage();
982 }
983 pageObj->m_isDefault = true;
984 }
985 else
986 {
987 if ( !isPageInserted )
988 {
989 // Initial page needs to be deleted and replaced
990 delete GetPage(0);
991 m_arrPages[0] = pageObj;
992 m_pPropGrid->m_pState = pageObj->GetStatePtr();
993 }
994 }
995
996 wxPropertyGridPageState* state = pageObj->GetStatePtr();
997
998 pageObj->m_manager = this;
999
1000 if ( needInit )
1001 {
1002 state->m_pPropGrid = m_pPropGrid;
1003 state->InitNonCatMode();
1004 }
1005
1006 if ( label.length() )
1007 {
1008 wxASSERT_MSG( !pageObj->m_label.length(),
1009 wxT("If page label is given in constructor, empty label must be given in AddPage"));
1010 pageObj->m_label = label;
1011 }
1012
1013 pageObj->m_id = m_nextTbInd;
1014
0da1f1c4
JS
1015 if ( !HasFlag(wxPG_SPLITTER_AUTO_CENTER) )
1016 pageObj->m_dontCenterSplitter = true;
1017
1c4293cb 1018 if ( isPageInserted )
f7a094e1 1019 m_arrPages.push_back( pageObj );
1c4293cb
VZ
1020
1021#if wxUSE_TOOLBAR
1022 if ( m_windowStyle & wxPG_TOOLBAR )
1023 {
1024 if ( !m_pToolbar )
1025 RecreateControls();
1026
1027 if ( !(GetExtraStyle()&wxPG_EX_HIDE_PAGE_BUTTONS) )
1028 {
1029 wxASSERT( m_pToolbar );
1030
1031 // Add separator before first page.
1032 if ( GetPageCount() < 2 && (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) &&
1033 m_pToolbar->GetToolsCount() < 3 )
1034 m_pToolbar->AddSeparator();
1035
1036 if ( &bmp != &wxNullBitmap )
1037 m_pToolbar->AddTool(m_nextTbInd,label,bmp,label,wxITEM_RADIO);
1038 //m_pToolbar->InsertTool(index+3,m_nextTbInd,bmp);
1039 else
a243da29 1040 m_pToolbar->AddTool(m_nextTbInd,label,wxBitmap(gs_xpm_defpage),
1c4293cb
VZ
1041 label,wxITEM_RADIO);
1042
1043 m_nextTbInd++;
1044
1045 m_pToolbar->Realize();
1046 }
1047 }
1048#else
1049 wxUnusedVar(bmp);
1050#endif
1051
1052 // If selected page was above the point of insertion, fix the current page index
1053 if ( isPageInserted )
1054 {
1055 if ( m_selPage >= index )
1056 {
1057 m_selPage += 1;
1058 }
1059 }
1060 else
1061 {
1062 // Set this value only when adding the first page
1063 m_selPage = 0;
1064 }
1065
1066 pageObj->Init();
1067
1068 m_iFlags |= wxPG_MAN_FL_PAGE_INSERTED;
1069
1070 wxASSERT( pageObj->GetGrid() );
1071
9288df34 1072 return pageObj;
1c4293cb
VZ
1073}
1074
1075// -----------------------------------------------------------------------
1076
1077bool wxPropertyGridManager::IsAnyModified() const
1078{
1079 size_t i;
1080 for ( i=0; i<GetPageCount(); i++ )
1081 {
f7a094e1 1082 if ( m_arrPages[i]->GetStatePtr()->m_anyModified )
1c4293cb
VZ
1083 return true;
1084 }
1085 return false;
1086}
1087
1088// -----------------------------------------------------------------------
1089
1090bool wxPropertyGridManager::IsPageModified( size_t index ) const
1091{
f7a094e1 1092 if ( m_arrPages[index]->GetStatePtr()->m_anyModified )
1c4293cb
VZ
1093 return true;
1094 return false;
1095}
1096
1097// -----------------------------------------------------------------------
1098
f5254768
JS
1099#if wxUSE_HEADERCTRL
1100void wxPropertyGridManager::ShowHeader(bool show)
1101{
1102 if ( show != m_showHeader)
1103 {
1104 m_showHeader = show;
1105 RecreateControls();
1106 }
1107}
1108#endif
1109
1110// -----------------------------------------------------------------------
1111
1112#if wxUSE_HEADERCTRL
1113void wxPropertyGridManager::SetColumnTitle( int idx, const wxString& title )
1114{
1115 if ( !m_pHeaderCtrl )
1116 ShowHeader();
1117
1118 m_pHeaderCtrl->SetColumnTitle(idx, title);
1119}
1120#endif
1121
1122// -----------------------------------------------------------------------
1123
fc72fab6
JS
1124bool wxPropertyGridManager::IsPropertySelected( wxPGPropArg id ) const
1125{
1126 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
1127 for ( unsigned int i=0; i<GetPageCount(); i++ )
1128 {
1129 if ( GetPageState(i)->DoIsPropertySelected(p) )
1130 return true;
1131 }
1132 return false;
1133}
1134
1135// -----------------------------------------------------------------------
1136
1c4293cb
VZ
1137wxPGProperty* wxPropertyGridManager::GetPageRoot( int index ) const
1138{
1139 wxASSERT( index >= 0 );
f7a094e1 1140 wxASSERT( index < (int)m_arrPages.size() );
1c4293cb 1141
f7a094e1 1142 return m_arrPages[index]->GetStatePtr()->m_properties;
1c4293cb
VZ
1143}
1144
1145// -----------------------------------------------------------------------
1146
1147bool wxPropertyGridManager::RemovePage( int page )
1148{
1149 wxCHECK_MSG( (page >= 0) && (page < (int)GetPageCount()),
1150 false,
1151 wxT("invalid page index") );
1152
f7a094e1 1153 wxPropertyGridPage* pd = m_arrPages[page];
1c4293cb 1154
f7a094e1 1155 if ( m_arrPages.size() == 1 )
1c4293cb
VZ
1156 {
1157 // Last page: do not remove page entry
1158 m_pPropGrid->Clear();
1159 m_selPage = -1;
1160 m_iFlags &= ~wxPG_MAN_FL_PAGE_INSERTED;
1161 pd->m_label.clear();
1162 }
f7a094e1 1163
1c4293cb
VZ
1164 // Change selection if current is page
1165 else if ( page == m_selPage )
1166 {
1167 if ( !m_pPropGrid->ClearSelection() )
1168 return false;
1169
1170 // Substitute page to select
1171 int substitute = page - 1;
1172 if ( substitute < 0 )
1173 substitute = page + 1;
1174
1175 SelectPage(substitute);
1176 }
1177
1178 // Remove toolbar icon
1179#if wxUSE_TOOLBAR
1180 if ( HasFlag(wxPG_TOOLBAR) )
1181 {
1182 wxASSERT( m_pToolbar );
1183
1184 int toolPos = GetExtraStyle() & wxPG_EX_MODE_BUTTONS ? 3 : 0;
1185 toolPos += page;
1186
1187 // Delete separator as well, for consistency
1188 if ( (GetExtraStyle() & wxPG_EX_MODE_BUTTONS) &&
1189 GetPageCount() == 1 )
1190 m_pToolbar->DeleteToolByPos(2);
1191
1192 m_pToolbar->DeleteToolByPos(toolPos);
1193 }
1194#endif
1195
f7a094e1 1196 if ( m_arrPages.size() > 1 )
1c4293cb 1197 {
f7a094e1 1198 m_arrPages.erase(m_arrPages.begin() + page);
1c4293cb
VZ
1199 delete pd;
1200 }
1201
1202 // Adjust indexes that were above removed
1203 if ( m_selPage > page )
1204 m_selPage--;
1205
1206 return true;
1207}
1208
1209// -----------------------------------------------------------------------
1210
1211bool wxPropertyGridManager::ProcessEvent( wxEvent& event )
1212{
1213 int evtType = event.GetEventType();
1214
1215 // NB: For some reason, under wxPython, Connect in Init doesn't work properly,
1216 // so we'll need to call OnPropertyGridSelect manually. Multiple call's
1217 // don't really matter.
1218 if ( evtType == wxEVT_PG_SELECTED )
1219 OnPropertyGridSelect((wxPropertyGridEvent&)event);
1220
1221 // Property grid events get special attention
1222 if ( evtType >= wxPG_BASE_EVT_TYPE &&
1223 evtType < (wxPG_MAX_EVT_TYPE) &&
1224 m_selPage >= 0 )
1225 {
1226 wxPropertyGridPage* page = GetPage(m_selPage);
1227 wxPropertyGridEvent* pgEvent = wxDynamicCast(&event, wxPropertyGridEvent);
1228
1229 // Add property grid events to appropriate custom pages
1230 // but stop propagating to parent if page says it is
1231 // handling everything.
1232 if ( pgEvent && !page->m_isDefault )
1233 {
1234 /*if ( pgEvent->IsPending() )
1235 page->AddPendingEvent(event);
1236 else*/
1237 page->ProcessEvent(event);
1238
1239 if ( page->IsHandlingAllEvents() )
1240 event.StopPropagation();
1241 }
1242 }
1243
1244 return wxPanel::ProcessEvent(event);
1245}
1246
1247// -----------------------------------------------------------------------
1248
94f02929
JS
1249void wxPropertyGridManager::RepaintDescBoxDecorations( wxDC& dc,
1250 int newSplitterY,
1251 int newWidth,
1252 int newHeight )
1c4293cb 1253{
1c4293cb
VZ
1254 // Draw background
1255 wxColour bgcol = GetBackgroundColour();
94f02929
JS
1256 dc.SetBrush(bgcol);
1257 dc.SetPen(bgcol);
1258 int rectHeight = m_splitterHeight;
1259 dc.DrawRectangle(0, newSplitterY, newWidth, rectHeight);
1260 dc.SetPen( wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW) );
1261 int splitterBottom = newSplitterY + m_splitterHeight - 1;
1262 int boxHeight = newHeight - splitterBottom;
1263 if ( boxHeight > 1 )
1264 dc.DrawRectangle(0, splitterBottom, newWidth, boxHeight);
1c4293cb 1265 else
94f02929 1266 dc.DrawLine(0, splitterBottom, newWidth, splitterBottom);
1c4293cb
VZ
1267}
1268
1269// -----------------------------------------------------------------------
1270
3d1706f8 1271void wxPropertyGridManager::UpdateDescriptionBox( int new_splittery, int new_width, int new_height )
1c4293cb 1272{
1c4293cb
VZ
1273 int use_hei = new_height;
1274 use_hei--;
1275
1c4293cb
VZ
1276 // Fix help control positions.
1277 int cap_hei = m_pPropGrid->m_fontHeight;
1278 int cap_y = new_splittery+m_splitterHeight+5;
1279 int cnt_y = cap_y+cap_hei+3;
1280 int sub_cap_hei = cap_y+cap_hei-use_hei;
1281 int cnt_hei = use_hei-cnt_y;
1282 if ( sub_cap_hei > 0 )
1283 {
1284 cap_hei -= sub_cap_hei;
1285 cnt_hei = 0;
1286 }
1287 if ( cap_hei <= 2 )
1288 {
1289 m_pTxtHelpCaption->Show( false );
1290 m_pTxtHelpContent->Show( false );
1291 }
1292 else
1293 {
1294 m_pTxtHelpCaption->SetSize(3,cap_y,new_width-6,cap_hei);
1295 m_pTxtHelpCaption->Wrap(-1);
1296 m_pTxtHelpCaption->Show( true );
1297 if ( cnt_hei <= 2 )
1298 {
1299 m_pTxtHelpContent->Show( false );
1300 }
1301 else
1302 {
1303 m_pTxtHelpContent->SetSize(3,cnt_y,new_width-6,cnt_hei);
1304 m_pTxtHelpContent->Show( true );
1305 }
1306 }
1307
3d1706f8
JS
1308 wxRect r(0, new_splittery, new_width, new_height-new_splittery);
1309 RefreshRect(r);
1c4293cb
VZ
1310
1311 m_splitterY = new_splittery;
1312
1313 m_iFlags &= ~(wxPG_FL_DESC_REFRESH_REQUIRED);
1314}
1315
1316// -----------------------------------------------------------------------
1317
1318void wxPropertyGridManager::RecalculatePositions( int width, int height )
1319{
1320 int propgridY = 0;
1321 int propgridBottomY = height;
1322
1323 // Toolbar at the top.
1324#if wxUSE_TOOLBAR
1325 if ( m_pToolbar )
1326 {
ddc17052 1327 m_pToolbar->SetSize(0, 0, width, -1);
1c4293cb 1328 propgridY += m_pToolbar->GetSize().y;
521f1d83
JS
1329
1330 if (GetExtraStyle() & wxPG_EX_TOOLBAR_SEPARATOR)
1331 propgridY += 1;
1c4293cb
VZ
1332 }
1333#endif
1334
f5254768
JS
1335 // Header comes after the tool bar
1336#if wxUSE_HEADERCTRL
1337 if ( m_showHeader )
1338 {
1339 m_pHeaderCtrl->SetSize(0, propgridY, width, -1);
1340 propgridY += m_pHeaderCtrl->GetSize().y;
1341 }
1342#endif
1343
1c4293cb
VZ
1344 // Help box.
1345 if ( m_pTxtHelpCaption )
1346 {
1347 int new_splittery = m_splitterY;
1348
1349 // Move m_splitterY
1350 if ( ( m_splitterY >= 0 || m_nextDescBoxSize ) && m_height > 32 )
1351 {
1352 if ( m_nextDescBoxSize >= 0 )
1353 {
1354 new_splittery = m_height - m_nextDescBoxSize - m_splitterHeight;
1355 m_nextDescBoxSize = -1;
1356 }
1357 new_splittery += (height-m_height);
1358 }
1359 else
1360 {
1361 new_splittery = height - wxPGMAN_DEFAULT_NEGATIVE_SPLITTER_Y;
1362 if ( new_splittery < 32 )
1363 new_splittery = 32;
1364 }
1365
1366 // Check if beyond minimum.
1367 int nspy_min = propgridY + m_pPropGrid->m_lineHeight;
1368 if ( new_splittery < nspy_min )
1369 new_splittery = nspy_min;
1370
1371 propgridBottomY = new_splittery;
1372
3d1706f8 1373 UpdateDescriptionBox( new_splittery, width, height );
1c4293cb
VZ
1374 }
1375
1376 if ( m_iFlags & wxPG_FL_INITIALIZED )
1377 {
1378 int pgh = propgridBottomY - propgridY;
253b70f1
JS
1379 if ( pgh < 0 )
1380 pgh = 0;
1c4293cb
VZ
1381 m_pPropGrid->SetSize( 0, propgridY, width, pgh );
1382
1383 m_extraHeight = height - pgh;
1384
1385 m_width = width;
1386 m_height = height;
1387 }
1388}
1389
1390// -----------------------------------------------------------------------
1391
1392void wxPropertyGridManager::SetDescBoxHeight( int ht, bool refresh )
1393{
1394 if ( m_windowStyle & wxPG_DESCRIPTION )
1395 {
95645cce
JS
1396 if ( ht != GetDescBoxHeight() )
1397 {
1398 m_nextDescBoxSize = ht;
1399 if ( refresh )
1400 RecalculatePositions(m_width, m_height);
1401 }
1c4293cb
VZ
1402 }
1403}
1404
1405// -----------------------------------------------------------------------
1406
1407int wxPropertyGridManager::GetDescBoxHeight() const
1408{
95645cce 1409 return GetClientSize().y - m_splitterY - m_splitterHeight;
1c4293cb
VZ
1410}
1411
1412// -----------------------------------------------------------------------
1413
1414void wxPropertyGridManager::OnPaint( wxPaintEvent& WXUNUSED(event) )
1415{
1416 wxPaintDC dc(this);
1417
1418 // Update everything inside the box
1419 wxRect r = GetUpdateRegion().GetBox();
1420
521f1d83
JS
1421 if (GetExtraStyle() & wxPG_EX_TOOLBAR_SEPARATOR)
1422 {
1423 if (m_pToolbar && m_pPropGrid)
1424 {
1425 wxPen marginPen(m_pPropGrid->GetMarginColour());
1426 dc.SetPen(marginPen);
1427
1428 int y = m_pPropGrid->GetPosition().y-1;
1429 dc.DrawLine(0, y, GetClientSize().x, y);
1430 }
1431 }
1432
94f02929 1433 // Repaint splitter and any other description box decorations
521f1d83 1434 if ( (r.y + r.height) >= m_splitterY && m_splitterY != -1)
94f02929 1435 RepaintDescBoxDecorations( dc, m_splitterY, m_width, m_height );
1c4293cb
VZ
1436}
1437
1438// -----------------------------------------------------------------------
1439
1440void wxPropertyGridManager::Refresh(bool eraseBackground, const wxRect* rect )
1441{
1442 m_pPropGrid->Refresh(eraseBackground);
1443 wxWindow::Refresh(eraseBackground,rect);
1444}
1445
1446// -----------------------------------------------------------------------
1447
1448void wxPropertyGridManager::RefreshProperty( wxPGProperty* p )
1449{
1450 wxPropertyGrid* grid = p->GetGrid();
1451
1452 if ( GetPage(m_selPage)->GetStatePtr() == p->GetParent()->GetParentState() )
1453 grid->RefreshProperty(p);
1454}
1455
1456// -----------------------------------------------------------------------
1457
1458void wxPropertyGridManager::RecreateControls()
1459{
1460
1461 bool was_shown = IsShown();
1462 if ( was_shown )
1463 Show ( false );
1464
1465 wxWindowID baseId = m_pPropGrid->GetId();
1466 if ( baseId < 0 )
1467 baseId = wxPG_MAN_ALTERNATE_BASE_ID;
1468
1469#if wxUSE_TOOLBAR
1470 if ( m_windowStyle & wxPG_TOOLBAR )
1471 {
1472 // Has toolbar.
1473 if ( !m_pToolbar )
1474 {
521f1d83
JS
1475 long toolBarFlags = ((GetExtraStyle()&wxPG_EX_NO_FLAT_TOOLBAR)?0:wxTB_FLAT);
1476 if (GetExtraStyle() & wxPG_EX_NO_TOOLBAR_DIVIDER)
1477 toolBarFlags |= wxTB_NODIVIDER;
1478
1c4293cb
VZ
1479 m_pToolbar = new wxToolBar(this,baseId+ID_ADVTOOLBAR_OFFSET,
1480 wxDefaultPosition,wxDefaultSize,
521f1d83 1481 toolBarFlags);
75779c8d 1482 m_pToolbar->SetToolBitmapSize(wxSize(16, 15));
1c4293cb
VZ
1483
1484 #if defined(__WXMSW__)
1485 // Eliminate toolbar flicker on XP
1486 // NOTE: Not enabled since it corrupts drawing somewhat.
1487
1488 /*
1489 #ifndef WS_EX_COMPOSITED
1490 #define WS_EX_COMPOSITED 0x02000000L
1491 #endif
1492
1493 HWND hWnd = (HWND)m_pToolbar->GetHWND();
1494
1495 ::SetWindowLong( hWnd, GWL_EXSTYLE,
1496 ::GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_COMPOSITED );
1497 */
1498
1499 #endif
1500
1501 m_pToolbar->SetCursor ( *wxSTANDARD_CURSOR );
1502
1503 if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) )
1504 {
1505 wxString desc1(_("Categorized Mode"));
1506 wxString desc2(_("Alphabetic Mode"));
1507 m_pToolbar->AddTool(baseId+ID_ADVTBITEMSBASE_OFFSET+0,
a243da29 1508 desc1,wxBitmap (gs_xpm_catmode),
1c4293cb
VZ
1509 desc1,wxITEM_RADIO);
1510 m_pToolbar->AddTool(baseId+ID_ADVTBITEMSBASE_OFFSET+1,
a243da29 1511 desc2,wxBitmap (gs_xpm_noncatmode),
1c4293cb
VZ
1512 desc2,wxITEM_RADIO);
1513 m_pToolbar->Realize();
1514 }
1515
1516 }
1517
1518 if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) )
1519 {
1520 // Toggle correct mode button.
1521 // TODO: This doesn't work in wxMSW (when changing,
1522 // both items will get toggled).
1523 int toggle_but_on_ind = ID_ADVTBITEMSBASE_OFFSET+0;
1524 int toggle_but_off_ind = ID_ADVTBITEMSBASE_OFFSET+1;
1525 if ( m_pPropGrid->m_pState->IsInNonCatMode() )
1526 {
1527 toggle_but_on_ind++;
1528 toggle_but_off_ind--;
1529 }
1530
1531 m_pToolbar->ToggleTool(baseId+toggle_but_on_ind,true);
1532 m_pToolbar->ToggleTool(baseId+toggle_but_off_ind,false);
1533 }
1534
1535 }
1536 else
1537 {
1538 // No toolbar.
1539 if ( m_pToolbar )
1540 m_pToolbar->Destroy();
d3b9f782 1541 m_pToolbar = NULL;
1c4293cb
VZ
1542 }
1543#endif
1544
f5254768
JS
1545#if wxUSE_HEADERCTRL
1546 if ( m_showHeader )
1547 {
1548 wxPGHeaderCtrl* hc;
1549
1550 if ( !m_pHeaderCtrl )
1551 {
1552 hc = new wxPGHeaderCtrl(this);
1553 hc->Create(this, baseId+ID_ADVHEADERCTRL_OFFSET);
1554 m_pHeaderCtrl = hc;
1555 }
1556 else
1557 {
1558 m_pHeaderCtrl->Show();
1559 }
1560
1561 m_pHeaderCtrl->OnPageChanged(GetCurrentPage());
1562 }
1563 else
1564 {
1565 if ( m_pHeaderCtrl )
1566 m_pHeaderCtrl->Hide();
1567 }
1568#endif
1569
1c4293cb
VZ
1570 if ( m_windowStyle & wxPG_DESCRIPTION )
1571 {
1572 // Has help box.
1573 m_pPropGrid->m_iFlags |= (wxPG_FL_NOSTATUSBARHELP);
1574
1575 if ( !m_pTxtHelpCaption )
1576 {
3d1706f8
JS
1577 m_pTxtHelpCaption = new wxStaticText(this,
1578 baseId+ID_ADVHELPCAPTION_OFFSET,
1579 wxT(""),
1580 wxDefaultPosition,
1581 wxDefaultSize,
1582 wxALIGN_LEFT|wxST_NO_AUTORESIZE);
1c4293cb 1583 m_pTxtHelpCaption->SetFont( m_pPropGrid->m_captionFont );
3d1706f8 1584 m_pTxtHelpCaption->SetCursor( *wxSTANDARD_CURSOR );
1c4293cb
VZ
1585 }
1586 if ( !m_pTxtHelpContent )
1587 {
3d1706f8
JS
1588 m_pTxtHelpContent = new wxStaticText(this,
1589 baseId+ID_ADVHELPCONTENT_OFFSET,
1590 wxT(""),
1591 wxDefaultPosition,
1592 wxDefaultSize,
1593 wxALIGN_LEFT|wxST_NO_AUTORESIZE);
1594 m_pTxtHelpContent->SetCursor( *wxSTANDARD_CURSOR );
1c4293cb 1595 }
f3932d5a
JS
1596
1597 SetDescribedProperty(GetSelection());
1c4293cb
VZ
1598 }
1599 else
1600 {
1601 // No help box.
1602 m_pPropGrid->m_iFlags &= ~(wxPG_FL_NOSTATUSBARHELP);
1603
1604 if ( m_pTxtHelpCaption )
1605 m_pTxtHelpCaption->Destroy();
1606
d3b9f782 1607 m_pTxtHelpCaption = NULL;
1c4293cb
VZ
1608
1609 if ( m_pTxtHelpContent )
1610 m_pTxtHelpContent->Destroy();
1611
d3b9f782 1612 m_pTxtHelpContent = NULL;
1c4293cb
VZ
1613 }
1614
1615 int width, height;
1616
1617 GetClientSize(&width,&height);
1618
1619 RecalculatePositions(width,height);
1620
1621 if ( was_shown )
1622 Show ( true );
1623}
1624
1625// -----------------------------------------------------------------------
1626
1627wxPGProperty* wxPropertyGridManager::DoGetPropertyByName( const wxString& name ) const
1628{
1629 size_t i;
1630 for ( i=0; i<GetPageCount(); i++ )
1631 {
f7a094e1 1632 wxPropertyGridPageState* pState = m_arrPages[i]->GetStatePtr();
1c4293cb
VZ
1633 wxPGProperty* p = pState->BaseGetPropertyByName(name);
1634 if ( p )
1635 {
1636 return p;
1637 }
1638 }
1639 return NULL;
1640}
1641
1642// -----------------------------------------------------------------------
1643
1644bool wxPropertyGridManager::EnsureVisible( wxPGPropArg id )
1645{
1646 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
1647
1648 wxPropertyGridPageState* parentState = p->GetParentState();
1649
1650 // Select correct page.
1651 if ( m_pPropGrid->m_pState != parentState )
1652 DoSelectPage( GetPageByState(parentState) );
1653
1654 return m_pPropGrid->EnsureVisible(id);
1655}
1656
1657// -----------------------------------------------------------------------
1658
1c4293cb
VZ
1659void wxPropertyGridManager::OnToolbarClick( wxCommandEvent &event )
1660{
1661 int id = event.GetId();
1662 if ( id >= 0 )
1663 {
1664 int baseId = m_pPropGrid->GetId();
1665 if ( baseId < 0 )
1666 baseId = wxPG_MAN_ALTERNATE_BASE_ID;
1667
1668 if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 0 ) )
1669 {
1670 // Categorized mode.
1671 if ( m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES )
9bc11214
JS
1672 {
1673 if ( !m_pPropGrid->HasInternalFlag(wxPG_FL_CATMODE_AUTO_SORT) )
1674 m_pPropGrid->m_windowStyle &= ~wxPG_AUTO_SORT;
1c4293cb 1675 m_pPropGrid->EnableCategories( true );
9bc11214 1676 }
1c4293cb
VZ
1677 }
1678 else if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 1 ) )
1679 {
1680 // Alphabetic mode.
1681 if ( !(m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES) )
9bc11214
JS
1682 {
1683 if ( m_pPropGrid->HasFlag(wxPG_AUTO_SORT) )
1684 m_pPropGrid->SetInternalFlag(wxPG_FL_CATMODE_AUTO_SORT);
1685 else
1686 m_pPropGrid->ClearInternalFlag(wxPG_FL_CATMODE_AUTO_SORT);
1687
1688 m_pPropGrid->m_windowStyle |= wxPG_AUTO_SORT;
1c4293cb 1689 m_pPropGrid->EnableCategories( false );
9bc11214 1690 }
1c4293cb
VZ
1691 }
1692 else
1693 {
1694 // Page Switching.
1695
1696 int index = -1;
1697 size_t i;
1698 wxPropertyGridPage* pdc;
1699
1700 // Find page with given id.
1701 for ( i=0; i<GetPageCount(); i++ )
1702 {
f7a094e1 1703 pdc = m_arrPages[i];
1c4293cb
VZ
1704 if ( pdc->m_id == id )
1705 {
1706 index = i;
1707 break;
1708 }
1709 }
1710
1711 wxASSERT( index >= 0 );
1712
1713 if ( DoSelectPage( index ) )
1714 {
1715
1716 // Event dispatching must be last.
d3b9f782 1717 m_pPropGrid->SendEvent( wxEVT_PG_PAGE_CHANGED, NULL );
1c4293cb
VZ
1718
1719 }
1720 else
1721 {
1722 // TODO: Depress the old button on toolbar.
1723 }
1724
1725 }
1726 }
1727}
1728
1729// -----------------------------------------------------------------------
62805170
JS
1730
1731bool wxPropertyGridManager::SetEditableStateItem( const wxString& name, wxVariant value )
1732{
1733 if ( name == wxS("descboxheight") )
1734 {
1735 SetDescBoxHeight(value.GetLong(), true);
1736 return true;
1737 }
1738 return false;
1739}
1740
1741// -----------------------------------------------------------------------
1742
1743wxVariant wxPropertyGridManager::GetEditableStateItem( const wxString& name ) const
1744{
1745 if ( name == wxS("descboxheight") )
1746 {
1747 return (long) GetDescBoxHeight();
1748 }
1749 return wxNullVariant;
1750}
1751
1752// -----------------------------------------------------------------------
1c4293cb
VZ
1753
1754void wxPropertyGridManager::SetDescription( const wxString& label, const wxString& content )
1755{
1756 if ( m_pTxtHelpCaption )
1757 {
1758 wxSize osz1 = m_pTxtHelpCaption->GetSize();
1759 wxSize osz2 = m_pTxtHelpContent->GetSize();
1760
1761 m_pTxtHelpCaption->SetLabel(label);
1762 m_pTxtHelpContent->SetLabel(content);
1763
1764 m_pTxtHelpCaption->SetSize(-1,osz1.y);
1765 m_pTxtHelpContent->SetSize(-1,osz2.y);
1766
3d1706f8 1767 UpdateDescriptionBox( m_splitterY, m_width, m_height );
1c4293cb
VZ
1768 }
1769}
1770
1771// -----------------------------------------------------------------------
1772
1773void wxPropertyGridManager::SetDescribedProperty( wxPGProperty* p )
1774{
1775 if ( m_pTxtHelpCaption )
1776 {
1777 if ( p )
1778 {
1779 SetDescription( p->GetLabel(), p->GetHelpString() );
1780 }
1781 else
1782 {
3d1706f8 1783 SetDescription( wxEmptyString, wxEmptyString );
1c4293cb
VZ
1784 }
1785 }
1786}
1787
1788// -----------------------------------------------------------------------
1789
1790void wxPropertyGridManager::SetSplitterLeft( bool subProps, bool allPages )
1791{
1792 if ( !allPages )
1793 {
1794 m_pPropGrid->SetSplitterLeft(subProps);
1795 }
1796 else
1797 {
1798 wxClientDC dc(this);
2197ec80 1799 dc.SetFont(m_pPropGrid->GetFont());
1c4293cb
VZ
1800
1801 int highest = 0;
1802 unsigned int i;
1803
1804 for ( i=0; i<GetPageCount(); i++ )
1805 {
f7a094e1 1806 int maxW = m_pState->GetColumnFitWidth(dc, m_arrPages[i]->m_properties, 0, subProps );
1c4293cb
VZ
1807 maxW += m_pPropGrid->m_marginWidth;
1808 if ( maxW > highest )
1809 highest = maxW;
0da1f1c4 1810 m_pState->m_dontCenterSplitter = true;
1c4293cb
VZ
1811 }
1812
1813 if ( highest > 0 )
1814 m_pPropGrid->SetSplitterPosition( highest );
1c4293cb 1815 }
f5254768
JS
1816
1817#if wxUSE_HEADERCTRL
1818 if ( m_showHeader )
1819 m_pHeaderCtrl->OnColumWidthsChanged();
1820#endif
1c4293cb
VZ
1821}
1822
1823// -----------------------------------------------------------------------
1824
1825void wxPropertyGridManager::OnPropertyGridSelect( wxPropertyGridEvent& event )
1826{
1827 // Check id.
1828 wxASSERT_MSG( GetId() == m_pPropGrid->GetId(),
1829 wxT("wxPropertyGridManager id must be set with wxPropertyGridManager::SetId (not wxWindow::SetId).") );
1830
1831 SetDescribedProperty(event.GetProperty());
1832 event.Skip();
1833}
1834
1835// -----------------------------------------------------------------------
1836
f5254768
JS
1837void
1838wxPropertyGridManager::OnPGColDrag( wxPropertyGridEvent& WXUNUSED(event) )
1839{
1840#if wxUSE_HEADERCTRL
1841 if ( !m_showHeader )
1842 return;
1843
1844 m_pHeaderCtrl->OnColumWidthsChanged();
1845#endif
1846}
1847
1848// -----------------------------------------------------------------------
1849
1c4293cb
VZ
1850void wxPropertyGridManager::OnResize( wxSizeEvent& WXUNUSED(event) )
1851{
1852 int width, height;
1853
0da1f1c4 1854 GetClientSize(&width, &height);
1c4293cb
VZ
1855
1856 if ( m_width == -12345 )
1857 RecreateControls();
1858
0da1f1c4
JS
1859 RecalculatePositions(width, height);
1860
1861 if ( m_pPropGrid && m_pPropGrid->m_parent )
1862 {
1863 int pgWidth, pgHeight;
1864 m_pPropGrid->GetClientSize(&pgWidth, &pgHeight);
1865
1866 // Regenerate splitter positions for non-current pages
1867 for ( unsigned int i=0; i<GetPageCount(); i++ )
1868 {
1869 wxPropertyGridPage* page = GetPage(i);
1870 if ( page != m_pPropGrid->GetState() )
1871 {
1872 page->OnClientWidthChange(pgWidth,
1873 pgWidth - page->m_width,
1874 true);
1875 }
1876 }
1877 }
1c4293cb
VZ
1878}
1879
1880// -----------------------------------------------------------------------
1881
1882void wxPropertyGridManager::OnMouseEntry( wxMouseEvent& WXUNUSED(event) )
1883{
1884 // Correct cursor. This is required atleast for wxGTK, for which
1885 // setting button's cursor to *wxSTANDARD_CURSOR does not work.
1886 SetCursor( wxNullCursor );
1887 m_onSplitter = 0;
1888}
1889
1890// -----------------------------------------------------------------------
1891
1892void wxPropertyGridManager::OnMouseMove( wxMouseEvent &event )
1893{
1894 if ( !m_pTxtHelpCaption )
1895 return;
1896
1897 int y = event.m_y;
1898
1899 if ( m_dragStatus > 0 )
1900 {
1901 int sy = y - m_dragOffset;
1902
1903 // Calculate drag limits
1904 int bottom_limit = m_height - m_splitterHeight + 1;
1905 int top_limit = m_pPropGrid->m_lineHeight;
1906#if wxUSE_TOOLBAR
1907 if ( m_pToolbar ) top_limit += m_pToolbar->GetSize().y;
1908#endif
1909
1910 if ( sy >= top_limit && sy < bottom_limit )
1911 {
1912
1913 int change = sy - m_splitterY;
1914 if ( change )
1915 {
1916 m_splitterY = sy;
1917
1918 m_pPropGrid->SetSize( m_width, m_splitterY - m_pPropGrid->GetPosition().y );
3d1706f8 1919 UpdateDescriptionBox( m_splitterY, m_width, m_height );
1c4293cb
VZ
1920
1921 m_extraHeight -= change;
1922 InvalidateBestSize();
1923 }
1924
1925 }
1926
1927 }
1928 else
1929 {
1930 if ( y >= m_splitterY && y < (m_splitterY+m_splitterHeight+2) )
1931 {
1932 SetCursor ( m_cursorSizeNS );
1933 m_onSplitter = 1;
1934 }
1935 else
1936 {
1937 if ( m_onSplitter )
1938 {
1939 SetCursor ( wxNullCursor );
1940 }
1941 m_onSplitter = 0;
1942 }
1943 }
1944}
1945
1946// -----------------------------------------------------------------------
1947
1948void wxPropertyGridManager::OnMouseClick( wxMouseEvent &event )
1949{
1950 int y = event.m_y;
1951
1952 // Click on splitter.
1953 if ( y >= m_splitterY && y < (m_splitterY+m_splitterHeight+2) )
1954 {
1955 if ( m_dragStatus == 0 )
1956 {
1957 //
1958 // Begin draggin the splitter
1959 //
1960
1961 BEGIN_MOUSE_CAPTURE
1962
1963 m_dragStatus = 1;
1964
1965 m_dragOffset = y - m_splitterY;
1966
1967 }
1968 }
1969}
1970
1971// -----------------------------------------------------------------------
1972
1973void wxPropertyGridManager::OnMouseUp( wxMouseEvent &event )
1974{
1975 // No event type check - basicly calling this method should
1976 // just stop dragging.
1977
1978 if ( m_dragStatus >= 1 )
1979 {
1980 //
1981 // End Splitter Dragging
1982 //
1983
1984 int y = event.m_y;
1985
1986 // DO NOT ENABLE FOLLOWING LINE!
1987 // (it is only here as a reminder to not to do it)
1988 //m_splitterY = y;
1989
1990 // This is necessary to return cursor
1991 END_MOUSE_CAPTURE
1992
1993 // Set back the default cursor, if necessary
1994 if ( y < m_splitterY || y >= (m_splitterY+m_splitterHeight+2) )
1995 {
1996 SetCursor ( wxNullCursor );
1997 }
1998
1999 m_dragStatus = 0;
2000 }
2001}
2002
2003// -----------------------------------------------------------------------
2004
2005void wxPropertyGridManager::SetSplitterPosition( int pos, int splitterColumn )
2006{
2007 wxASSERT_MSG( GetPageCount(),
2008 wxT("SetSplitterPosition() has no effect until pages have been added") );
2009
2010 size_t i;
2011 for ( i=0; i<GetPageCount(); i++ )
2012 {
2013 wxPropertyGridPage* page = GetPage(i);
f5254768
JS
2014 page->DoSetSplitterPosition( pos, splitterColumn,
2015 wxPG_SPLITTER_REFRESH );
1c4293cb 2016 }
f5254768
JS
2017
2018#if wxUSE_HEADERCTRL
2019 if ( m_showHeader )
2020 m_pHeaderCtrl->OnColumWidthsChanged();
2021#endif
2022}
2023
2024// -----------------------------------------------------------------------
2025
2026void wxPropertyGridManager::SetPageSplitterPosition( int page,
2027 int pos,
2028 int column )
2029{
2030 GetPage(page)->DoSetSplitterPosition( pos, column );
2031
2032#if wxUSE_HEADERCTRL
2033 if ( m_showHeader )
2034 m_pHeaderCtrl->OnColumWidthsChanged();
2035#endif
1c4293cb
VZ
2036}
2037
2038// -----------------------------------------------------------------------
2039// wxPGVIterator_Manager
2040// -----------------------------------------------------------------------
2041
2042// Default returned by wxPropertyGridInterface::CreateVIterator().
2043class wxPGVIteratorBase_Manager : public wxPGVIteratorBase
2044{
2045public:
2046 wxPGVIteratorBase_Manager( wxPropertyGridManager* manager, int flags )
2047 : m_manager(manager), m_flags(flags), m_curPage(0)
2048 {
2049 m_it.Init(manager->GetPage(0), flags);
2050 }
2051 virtual ~wxPGVIteratorBase_Manager() { }
2052 virtual void Next()
2053 {
2054 m_it.Next();
2055
2056 // Next page?
2057 if ( m_it.AtEnd() )
2058 {
2059 m_curPage++;
2060 if ( m_curPage < m_manager->GetPageCount() )
2061 m_it.Init( m_manager->GetPage(m_curPage), m_flags );
2062 }
2063 }
2064private:
2065 wxPropertyGridManager* m_manager;
2066 int m_flags;
2067 unsigned int m_curPage;
2068};
2069
2070wxPGVIterator wxPropertyGridManager::GetVIterator( int flags ) const
2071{
2072 return wxPGVIterator( new wxPGVIteratorBase_Manager( (wxPropertyGridManager*)this, flags ) );
2073}
f4bc1aa2
JS
2074
2075#endif // wxUSE_PROPGRID