1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/propgrid/manager.cpp
3 // Purpose: wxPropertyGridManager
4 // Author: Jaakko Salli
8 // Copyright: (c) Jaakko Salli
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
23 #include "wx/object.h"
25 #include "wx/string.h"
28 #include "wx/window.h"
33 #include "wx/cursor.h"
34 #include "wx/settings.h"
35 #include "wx/textctrl.h"
37 #include "wx/statusbr.h"
41 // This define is necessary to prevent macro clearing
42 #define __wxPG_SOURCE_FILE__
44 #include <wx/propgrid/propgrid.h>
46 #include <wx/propgrid/manager.h>
49 #define wxPG_MAN_ALTERNATE_BASE_ID 11249 // Needed for wxID_ANY madnesss
52 // -----------------------------------------------------------------------
54 // For wxMSW cursor consistency, we must do mouse capturing even
55 // when using custom controls
57 #define BEGIN_MOUSE_CAPTURE \
58 if ( !(m_iFlags & wxPG_FL_MOUSE_CAPTURED) ) \
61 m_iFlags |= wxPG_FL_MOUSE_CAPTURED; \
64 #define END_MOUSE_CAPTURE \
65 if ( m_iFlags & wxPG_FL_MOUSE_CAPTURED ) \
68 m_iFlags &= ~(wxPG_FL_MOUSE_CAPTURED); \
71 // -----------------------------------------------------------------------
72 // wxPropertyGridManager
73 // -----------------------------------------------------------------------
75 const wxChar
*wxPropertyGridManagerNameStr
= wxT("wxPropertyGridManager");
78 // Categoric Mode Icon
79 static const char* gs_xpm_catmode
[] = {
104 // Alphabetic Mode Icon
105 static const char* gs_xpm_noncatmode
[] = {
130 // Default Page Icon.
131 static const char* gs_xpm_defpage
[] = {
156 // -----------------------------------------------------------------------
157 // wxPropertyGridPage
158 // -----------------------------------------------------------------------
161 IMPLEMENT_CLASS(wxPropertyGridPage
, wxEvtHandler
)
164 BEGIN_EVENT_TABLE(wxPropertyGridPage
, wxEvtHandler
)
168 wxPropertyGridPage::wxPropertyGridPage()
169 : wxEvtHandler(), wxPropertyGridInterface(), wxPropertyGridPageState()
171 m_pState
= this; // wxPropertyGridInterface to point to State
176 wxPropertyGridPage::~wxPropertyGridPage()
180 void wxPropertyGridPage::Clear()
182 GetStatePtr()->DoClear();
185 wxSize
wxPropertyGridPage::FitColumns()
187 wxSize sz
= DoFitColumns();
191 void wxPropertyGridPage::RefreshProperty( wxPGProperty
* p
)
194 m_manager
->RefreshProperty(p
);
197 void wxPropertyGridPage::OnShow()
201 void wxPropertyGridPage::SetSplitterPosition( int splitterPos
, int col
)
203 wxPropertyGrid
* pg
= GetGrid();
204 if ( pg
->GetState() == this )
205 pg
->SetSplitterPosition(splitterPos
);
207 DoSetSplitterPosition(splitterPos
, col
, false);
210 void wxPropertyGridPage::DoSetSplitterPosition( int pos
, int splitterColumn
, bool allPages
)
212 if ( allPages
&& m_manager
->GetPageCount() )
213 m_manager
->SetSplitterPosition( pos
, splitterColumn
);
215 DoSetSplitterPositionThisPage( pos
, splitterColumn
);
218 // -----------------------------------------------------------------------
219 // wxPropertyGridManager
220 // -----------------------------------------------------------------------
222 // Final default splitter y is client height minus this.
223 #define wxPGMAN_DEFAULT_NEGATIVE_SPLITTER_Y 100
225 // -----------------------------------------------------------------------
227 IMPLEMENT_CLASS(wxPropertyGridManager
, wxPanel
)
229 #define ID_ADVTOOLBAR_OFFSET 1
230 #define ID_ADVHELPCAPTION_OFFSET 2
231 #define ID_ADVHELPCONTENT_OFFSET 3
232 #define ID_ADVBUTTON_OFFSET 4
233 #define ID_ADVTBITEMSBASE_OFFSET 5 // Must be last.
235 // -----------------------------------------------------------------------
237 BEGIN_EVENT_TABLE(wxPropertyGridManager
, wxPanel
)
238 EVT_MOTION(wxPropertyGridManager::OnMouseMove
)
239 EVT_SIZE(wxPropertyGridManager::OnResize
)
240 EVT_PAINT(wxPropertyGridManager::OnPaint
)
241 EVT_LEFT_DOWN(wxPropertyGridManager::OnMouseClick
)
242 EVT_LEFT_UP(wxPropertyGridManager::OnMouseUp
)
243 EVT_LEAVE_WINDOW(wxPropertyGridManager::OnMouseEntry
)
244 //EVT_ENTER_WINDOW(wxPropertyGridManager::OnMouseEntry)
247 // -----------------------------------------------------------------------
249 wxPropertyGridManager::wxPropertyGridManager()
255 // -----------------------------------------------------------------------
257 wxPropertyGridManager::wxPropertyGridManager( wxWindow
*parent
,
266 Create(parent
,id
,pos
,size
,style
,name
);
269 // -----------------------------------------------------------------------
271 bool wxPropertyGridManager::Create( wxWindow
*parent
,
279 bool res
= wxPanel::Create( parent
, id
, pos
, size
,
280 (style
&0xFFFF0000)|wxWANTS_CHARS
,
287 // -----------------------------------------------------------------------
290 // Initialize values to defaults
292 void wxPropertyGridManager::Init1()
295 //m_pPropGrid = (wxPropertyGrid*) NULL;
296 m_pPropGrid
= CreatePropertyGrid();
299 m_pToolbar
= (wxToolBar
*) NULL
;
301 m_pTxtHelpCaption
= (wxStaticText
*) NULL
;
302 m_pTxtHelpContent
= (wxStaticText
*) NULL
;
304 m_emptyPage
= (wxPropertyGridPage
*) NULL
;
308 m_width
= m_height
= 0;
310 m_splitterHeight
= 5;
312 m_splitterY
= -1; // -1 causes default to be set.
314 m_nextDescBoxSize
= -1;
322 // -----------------------------------------------------------------------
324 // These flags are always used in wxPropertyGrid integrated in wxPropertyGridManager.
326 #define wxPG_MAN_PROPGRID_FORCED_FLAGS (wxSIMPLE_BORDER| \
327 wxNO_FULL_REPAINT_ON_RESIZE| \
330 #define wxPG_MAN_PROPGRID_FORCED_FLAGS (wxNO_BORDER| \
331 wxNO_FULL_REPAINT_ON_RESIZE| \
335 // Which flags can be passed to underlying wxPropertyGrid.
336 #define wxPG_MAN_PASS_FLAGS_MASK (0xFFF0|wxTAB_TRAVERSAL)
339 // Initialize after parent etc. set
341 void wxPropertyGridManager::Init2( int style
)
344 if ( m_iFlags
& wxPG_FL_INITIALIZED
)
347 m_windowStyle
|= (style
&0x0000FFFF);
349 wxSize csz
= GetClientSize();
351 m_cursorSizeNS
= wxCursor(wxCURSOR_SIZENS
);
353 // Prepare the first page
354 // NB: But just prepare - you still need to call Add/InsertPage
355 // to actually add properties on it.
356 wxPropertyGridPage
* pd
= new wxPropertyGridPage();
357 pd
->m_isDefault
= true;
358 pd
->m_manager
= this;
359 wxPropertyGridPageState
* state
= pd
->GetStatePtr();
360 state
->m_pPropGrid
= m_pPropGrid
;
361 m_arrPages
.push_back( pd
);
362 m_pPropGrid
->m_pState
= state
;
364 wxWindowID baseId
= GetId();
365 wxWindowID useId
= baseId
;
367 baseId
= wxPG_MAN_ALTERNATE_BASE_ID
;
372 // Smaller controls on Mac
373 SetWindowVariant(wxWINDOW_VARIANT_SMALL
);
376 // Create propertygrid.
377 m_pPropGrid
->Create(this,baseId
,wxPoint(0,0),csz
,
378 (m_windowStyle
&wxPG_MAN_PASS_FLAGS_MASK
)
379 |wxPG_MAN_PROPGRID_FORCED_FLAGS
);
381 m_pPropGrid
->m_eventObject
= this;
383 m_pPropGrid
->SetId(useId
);
385 m_pPropGrid
->m_iFlags
|= wxPG_FL_IN_MANAGER
;
387 m_pState
= m_pPropGrid
->m_pState
;
389 m_pPropGrid
->SetExtraStyle(wxPG_EX_INIT_NOCAT
);
391 m_nextTbInd
= baseId
+ID_ADVTBITEMSBASE_OFFSET
+ 2;
394 // Connect to property grid onselect event.
395 // NB: Even if wxID_ANY is used, this doesn't connect properly in wxPython
396 // (see wxPropertyGridManager::ProcessEvent).
397 Connect(m_pPropGrid
->GetId()/*wxID_ANY*/,
399 wxPropertyGridEventHandler(wxPropertyGridManager::OnPropertyGridSelect
) );
401 // Connect to toolbar button events.
402 Connect(baseId
+ID_ADVTBITEMSBASE_OFFSET
,baseId
+ID_ADVTBITEMSBASE_OFFSET
+50,
403 wxEVT_COMMAND_TOOL_CLICKED
,
404 wxCommandEventHandler(wxPropertyGridManager::OnToolbarClick
) );
406 // Optional initial controls.
409 m_iFlags
|= wxPG_FL_INITIALIZED
;
413 // -----------------------------------------------------------------------
415 wxPropertyGridManager::~wxPropertyGridManager()
419 m_pPropGrid
->DoSelectProperty(NULL
);
420 m_pPropGrid
->m_pState
= NULL
;
423 for ( i
=0; i
<m_arrPages
.size(); i
++ )
425 delete m_arrPages
[i
];
431 // -----------------------------------------------------------------------
433 wxPropertyGrid
* wxPropertyGridManager::CreatePropertyGrid() const
435 return new wxPropertyGrid();
438 // -----------------------------------------------------------------------
440 void wxPropertyGridManager::SetId( wxWindowID winid
)
442 wxWindow::SetId(winid
);
444 // TODO: Reconnect propgrid event handler(s).
446 m_pPropGrid
->SetId(winid
);
449 // -----------------------------------------------------------------------
451 wxSize
wxPropertyGridManager::DoGetBestSize() const
453 return wxSize(60,150);
456 // -----------------------------------------------------------------------
458 bool wxPropertyGridManager::SetFont( const wxFont
& font
)
460 bool res
= wxWindow::SetFont(font
);
461 m_pPropGrid
->SetFont(font
);
463 // TODO: Need to do caption recacalculations for other pages as well.
465 for ( i
=0; i
<m_arrPages
.size(); i
++ )
467 wxPropertyGridPage
* page
= GetPage(i
);
469 if ( page
!= m_pPropGrid
->GetState() )
470 page
->CalculateFontAndBitmapStuff(-1);
476 // -----------------------------------------------------------------------
478 void wxPropertyGridManager::SetExtraStyle( long exStyle
)
480 wxWindow::SetExtraStyle( exStyle
);
481 m_pPropGrid
->SetExtraStyle( exStyle
& 0xFFFFF000 );
483 if ( (exStyle
& wxPG_EX_NO_FLAT_TOOLBAR
) && m_pToolbar
)
488 // -----------------------------------------------------------------------
490 void wxPropertyGridManager::Freeze()
492 m_pPropGrid
->Freeze();
496 // -----------------------------------------------------------------------
498 void wxPropertyGridManager::Thaw()
504 // -----------------------------------------------------------------------
506 void wxPropertyGridManager::SetWindowStyleFlag( long style
)
508 wxWindow::SetWindowStyleFlag( style
);
509 m_pPropGrid
->SetWindowStyleFlag( (m_pPropGrid
->GetWindowStyleFlag()&~(wxPG_MAN_PASS_FLAGS_MASK
)) |
510 (style
&wxPG_MAN_PASS_FLAGS_MASK
) );
513 // -----------------------------------------------------------------------
515 // Actually shows given page.
516 bool wxPropertyGridManager::DoSelectPage( int index
)
518 // -1 means no page was selected
519 //wxASSERT( m_selPage >= 0 );
521 wxCHECK_MSG( index
>= -1 && index
< (int)GetPageCount(),
523 wxT("invalid page index") );
525 if ( m_selPage
== index
)
528 if ( m_pPropGrid
->m_selected
)
530 if ( !m_pPropGrid
->ClearSelection() )
534 wxPropertyGridPage
* prevPage
;
536 if ( m_selPage
>= 0 )
537 prevPage
= GetPage(m_selPage
);
539 prevPage
= m_emptyPage
;
541 wxPropertyGridPage
* nextPage
;
545 nextPage
= m_arrPages
[index
];
553 m_emptyPage
= new wxPropertyGridPage();
554 m_emptyPage
->m_pPropGrid
= m_pPropGrid
;
557 nextPage
= m_emptyPage
;
560 m_iFlags
|= wxPG_FL_DESC_REFRESH_REQUIRED
;
562 m_pPropGrid
->SwitchState( nextPage
->GetStatePtr() );
564 m_pState
= m_pPropGrid
->m_pState
;
572 m_pToolbar
->ToggleTool( nextPage
->m_id
, true );
574 m_pToolbar
->ToggleTool( prevPage
->m_id
, false );
581 // -----------------------------------------------------------------------
583 // Changes page *and* set the target page for insertion operations.
584 void wxPropertyGridManager::SelectPage( int index
)
589 // -----------------------------------------------------------------------
591 int wxPropertyGridManager::GetPageByName( const wxString
& name
) const
594 for ( i
=0; i
<GetPageCount(); i
++ )
596 if ( m_arrPages
[i
]->m_label
== name
)
602 // -----------------------------------------------------------------------
604 int wxPropertyGridManager::GetPageByState( const wxPropertyGridPageState
* pState
) const
609 for ( i
=0; i
<GetPageCount(); i
++ )
611 if ( pState
== m_arrPages
[i
]->GetStatePtr() )
618 // -----------------------------------------------------------------------
620 const wxString
& wxPropertyGridManager::GetPageName( int index
) const
622 wxASSERT( index
>= 0 && index
< (int)GetPageCount() );
623 return m_arrPages
[index
]->m_label
;
626 // -----------------------------------------------------------------------
628 wxPropertyGridPageState
* wxPropertyGridManager::GetPageState( int page
) const
630 // Do not change this into wxCHECK because returning NULL is important
631 // for wxPropertyGridInterface page enumeration mechanics.
632 if ( page
>= (int)GetPageCount() )
637 return m_arrPages
[page
];
640 // -----------------------------------------------------------------------
642 void wxPropertyGridManager::Clear()
644 m_pPropGrid
->Freeze();
647 for ( i
=(int)GetPageCount()-1; i
>=0; i
-- )
651 m_nextTbInd
= m_baseId
+ID_ADVTBITEMSBASE_OFFSET
+ 2;
656 // -----------------------------------------------------------------------
658 void wxPropertyGridManager::ClearPage( int page
)
660 wxASSERT( page
>= 0 );
661 wxASSERT( page
< (int)GetPageCount() );
663 if ( page
>= 0 && page
< (int)GetPageCount() )
665 wxPropertyGridPageState
* state
= m_arrPages
[page
];
667 if ( state
== m_pPropGrid
->GetState() )
668 m_pPropGrid
->Clear();
674 // -----------------------------------------------------------------------
676 int wxPropertyGridManager::GetColumnCount( int page
) const
678 wxASSERT( page
>= -1 );
679 wxASSERT( page
< (int)GetPageCount() );
681 return GetPageState(page
)->GetColumnCount();
684 // -----------------------------------------------------------------------
686 void wxPropertyGridManager::SetColumnCount( int colCount
, int page
)
688 wxASSERT( page
>= -1 );
689 wxASSERT( page
< (int)GetPageCount() );
691 GetPageState(page
)->SetColumnCount( colCount
);
692 GetGrid()->Refresh();
694 // -----------------------------------------------------------------------
696 size_t wxPropertyGridManager::GetPageCount() const
698 if ( !(m_iFlags
& wxPG_MAN_FL_PAGE_INSERTED
) )
701 return m_arrPages
.size();
704 // -----------------------------------------------------------------------
706 wxPropertyGridPage
* wxPropertyGridManager::InsertPage( int index
,
707 const wxString
& label
,
709 wxPropertyGridPage
* pageObj
)
712 index
= GetPageCount();
714 wxCHECK_MSG( (size_t)index
== GetPageCount(), NULL
,
715 wxT("wxPropertyGridManager currently only supports appending pages (due to wxToolBar limitation)."));
717 bool needInit
= true;
718 bool isPageInserted
= m_iFlags
& wxPG_MAN_FL_PAGE_INSERTED
? true : false;
720 wxASSERT( index
== 0 || isPageInserted
);
724 // No custom page object was given, so we will either re-use the default base
725 // page (if index==0), or create a new default page object.
726 if ( !isPageInserted
)
728 pageObj
= GetPage(0);
729 // Of course, if the base page was custom, we need to delete and
731 if ( !pageObj
->m_isDefault
)
734 pageObj
= new wxPropertyGridPage();
735 m_arrPages
[0] = pageObj
;
741 pageObj
= new wxPropertyGridPage();
743 pageObj
->m_isDefault
= true;
747 if ( !isPageInserted
)
749 // Initial page needs to be deleted and replaced
751 m_arrPages
[0] = pageObj
;
752 m_pPropGrid
->m_pState
= pageObj
->GetStatePtr();
756 wxPropertyGridPageState
* state
= pageObj
->GetStatePtr();
758 pageObj
->m_manager
= this;
762 state
->m_pPropGrid
= m_pPropGrid
;
763 state
->InitNonCatMode();
766 if ( label
.length() )
768 wxASSERT_MSG( !pageObj
->m_label
.length(),
769 wxT("If page label is given in constructor, empty label must be given in AddPage"));
770 pageObj
->m_label
= label
;
773 pageObj
->m_id
= m_nextTbInd
;
775 if ( isPageInserted
)
776 m_arrPages
.push_back( pageObj
);
779 if ( m_windowStyle
& wxPG_TOOLBAR
)
784 if ( !(GetExtraStyle()&wxPG_EX_HIDE_PAGE_BUTTONS
) )
786 wxASSERT( m_pToolbar
);
788 // Add separator before first page.
789 if ( GetPageCount() < 2 && (GetExtraStyle()&wxPG_EX_MODE_BUTTONS
) &&
790 m_pToolbar
->GetToolsCount() < 3 )
791 m_pToolbar
->AddSeparator();
793 if ( &bmp
!= &wxNullBitmap
)
794 m_pToolbar
->AddTool(m_nextTbInd
,label
,bmp
,label
,wxITEM_RADIO
);
795 //m_pToolbar->InsertTool(index+3,m_nextTbInd,bmp);
797 m_pToolbar
->AddTool(m_nextTbInd
,label
,wxBitmap( (const char**)gs_xpm_defpage
),
802 m_pToolbar
->Realize();
809 // If selected page was above the point of insertion, fix the current page index
810 if ( isPageInserted
)
812 if ( m_selPage
>= index
)
819 // Set this value only when adding the first page
825 m_iFlags
|= wxPG_MAN_FL_PAGE_INSERTED
;
827 wxASSERT( pageObj
->GetGrid() );
832 // -----------------------------------------------------------------------
834 bool wxPropertyGridManager::IsAnyModified() const
837 for ( i
=0; i
<GetPageCount(); i
++ )
839 if ( m_arrPages
[i
]->GetStatePtr()->m_anyModified
)
845 // -----------------------------------------------------------------------
847 bool wxPropertyGridManager::IsPageModified( size_t index
) const
849 if ( m_arrPages
[index
]->GetStatePtr()->m_anyModified
)
854 // -----------------------------------------------------------------------
856 wxPGProperty
* wxPropertyGridManager::GetPageRoot( int index
) const
858 wxASSERT( index
>= 0 );
859 wxASSERT( index
< (int)m_arrPages
.size() );
861 return m_arrPages
[index
]->GetStatePtr()->m_properties
;
864 // -----------------------------------------------------------------------
866 bool wxPropertyGridManager::RemovePage( int page
)
868 wxCHECK_MSG( (page
>= 0) && (page
< (int)GetPageCount()),
870 wxT("invalid page index") );
872 wxPropertyGridPage
* pd
= m_arrPages
[page
];
874 if ( m_arrPages
.size() == 1 )
876 // Last page: do not remove page entry
877 m_pPropGrid
->Clear();
879 m_iFlags
&= ~wxPG_MAN_FL_PAGE_INSERTED
;
883 // Change selection if current is page
884 else if ( page
== m_selPage
)
886 if ( !m_pPropGrid
->ClearSelection() )
889 // Substitute page to select
890 int substitute
= page
- 1;
891 if ( substitute
< 0 )
892 substitute
= page
+ 1;
894 SelectPage(substitute
);
897 // Remove toolbar icon
899 if ( HasFlag(wxPG_TOOLBAR
) )
901 wxASSERT( m_pToolbar
);
903 int toolPos
= GetExtraStyle() & wxPG_EX_MODE_BUTTONS
? 3 : 0;
906 // Delete separator as well, for consistency
907 if ( (GetExtraStyle() & wxPG_EX_MODE_BUTTONS
) &&
908 GetPageCount() == 1 )
909 m_pToolbar
->DeleteToolByPos(2);
911 m_pToolbar
->DeleteToolByPos(toolPos
);
915 if ( m_arrPages
.size() > 1 )
917 m_arrPages
.erase(m_arrPages
.begin() + page
);
921 // Adjust indexes that were above removed
922 if ( m_selPage
> page
)
928 // -----------------------------------------------------------------------
930 bool wxPropertyGridManager::ProcessEvent( wxEvent
& event
)
932 int evtType
= event
.GetEventType();
934 // NB: For some reason, under wxPython, Connect in Init doesn't work properly,
935 // so we'll need to call OnPropertyGridSelect manually. Multiple call's
936 // don't really matter.
937 if ( evtType
== wxEVT_PG_SELECTED
)
938 OnPropertyGridSelect((wxPropertyGridEvent
&)event
);
940 // Property grid events get special attention
941 if ( evtType
>= wxPG_BASE_EVT_TYPE
&&
942 evtType
< (wxPG_MAX_EVT_TYPE
) &&
945 wxPropertyGridPage
* page
= GetPage(m_selPage
);
946 wxPropertyGridEvent
* pgEvent
= wxDynamicCast(&event
, wxPropertyGridEvent
);
948 // Add property grid events to appropriate custom pages
949 // but stop propagating to parent if page says it is
950 // handling everything.
951 if ( pgEvent
&& !page
->m_isDefault
)
953 /*if ( pgEvent->IsPending() )
954 page->AddPendingEvent(event);
956 page
->ProcessEvent(event
);
958 if ( page
->IsHandlingAllEvents() )
959 event
.StopPropagation();
963 return wxPanel::ProcessEvent(event
);
966 // -----------------------------------------------------------------------
968 void wxPropertyGridManager::RepaintSplitter( wxDC
& dc
, int new_splittery
, int new_width
,
969 int new_height
, bool desc_too
)
971 int use_hei
= new_height
;
974 wxColour bgcol
= GetBackgroundColour();
975 dc
.SetBrush( bgcol
);
977 int rect_hei
= use_hei
-new_splittery
;
979 rect_hei
= m_splitterHeight
;
980 dc
.DrawRectangle(0,new_splittery
,new_width
,rect_hei
);
981 dc
.SetPen ( wxSystemSettings::GetColour ( wxSYS_COLOUR_3DDKSHADOW
) );
982 int splitter_bottom
= new_splittery
+m_splitterHeight
- 1;
983 int box_height
= use_hei
-splitter_bottom
;
984 if ( box_height
> 1 )
985 dc
.DrawRectangle(0,splitter_bottom
,new_width
,box_height
);
987 dc
.DrawLine(0,splitter_bottom
,new_width
,splitter_bottom
);
990 // -----------------------------------------------------------------------
992 void wxPropertyGridManager::RefreshHelpBox( int new_splittery
, int new_width
, int new_height
)
994 //if ( new_splittery == m_splitterY && new_width == m_width )
997 int use_hei
= new_height
;
1000 //wxRendererNative::Get().DrawSplitterSash(this,dc,
1001 //wxSize(width,m_splitterHeight),new_splittery,wxHORIZONTAL);
1003 //wxRendererNative::Get().DrawSplitterBorder(this,dc,
1004 // wxRect(0,new_splittery,new_width,m_splitterHeight));
1006 // Fix help control positions.
1007 int cap_hei
= m_pPropGrid
->m_fontHeight
;
1008 int cap_y
= new_splittery
+m_splitterHeight
+5;
1009 int cnt_y
= cap_y
+cap_hei
+3;
1010 int sub_cap_hei
= cap_y
+cap_hei
-use_hei
;
1011 int cnt_hei
= use_hei
-cnt_y
;
1012 if ( sub_cap_hei
> 0 )
1014 cap_hei
-= sub_cap_hei
;
1019 m_pTxtHelpCaption
->Show( false );
1020 m_pTxtHelpContent
->Show( false );
1024 m_pTxtHelpCaption
->SetSize(3,cap_y
,new_width
-6,cap_hei
);
1025 m_pTxtHelpCaption
->Wrap(-1);
1026 m_pTxtHelpCaption
->Show( true );
1029 m_pTxtHelpContent
->Show( false );
1033 m_pTxtHelpContent
->SetSize(3,cnt_y
,new_width
-6,cnt_hei
);
1034 m_pTxtHelpContent
->Show( true );
1038 wxClientDC
dc(this);
1039 RepaintSplitter( dc
, new_splittery
, new_width
, new_height
, true );
1041 m_splitterY
= new_splittery
;
1043 m_iFlags
&= ~(wxPG_FL_DESC_REFRESH_REQUIRED
);
1046 // -----------------------------------------------------------------------
1048 void wxPropertyGridManager::RecalculatePositions( int width
, int height
)
1051 int propgridBottomY
= height
;
1053 // Toolbar at the top.
1059 #if ( wxMINOR_VERSION < 6 || (wxMINOR_VERSION == 6 && wxRELEASE_NUMBER < 2) )
1062 // In wxWidgets 2.6.2+, Toolbar default height may be broken
1063 #if defined(__WXMSW__)
1065 #elif defined(__WXGTK__)
1066 tbHeight
= -1; // 22;
1067 #elif defined(__WXMAC__)
1074 m_pToolbar
->SetSize(0,0,width
,tbHeight
);
1075 propgridY
+= m_pToolbar
->GetSize().y
;
1080 if ( m_pTxtHelpCaption
)
1082 int new_splittery
= m_splitterY
;
1085 if ( ( m_splitterY
>= 0 || m_nextDescBoxSize
) && m_height
> 32 )
1087 if ( m_nextDescBoxSize
>= 0 )
1089 new_splittery
= m_height
- m_nextDescBoxSize
- m_splitterHeight
;
1090 m_nextDescBoxSize
= -1;
1092 new_splittery
+= (height
-m_height
);
1096 new_splittery
= height
- wxPGMAN_DEFAULT_NEGATIVE_SPLITTER_Y
;
1097 if ( new_splittery
< 32 )
1101 // Check if beyond minimum.
1102 int nspy_min
= propgridY
+ m_pPropGrid
->m_lineHeight
;
1103 if ( new_splittery
< nspy_min
)
1104 new_splittery
= nspy_min
;
1106 propgridBottomY
= new_splittery
;
1108 RefreshHelpBox( new_splittery
, width
, height
);
1111 if ( m_iFlags
& wxPG_FL_INITIALIZED
)
1113 int pgh
= propgridBottomY
- propgridY
;
1114 m_pPropGrid
->SetSize( 0, propgridY
, width
, pgh
);
1116 m_extraHeight
= height
- pgh
;
1123 // -----------------------------------------------------------------------
1125 void wxPropertyGridManager::SetDescBoxHeight( int ht
, bool refresh
)
1127 if ( m_windowStyle
& wxPG_DESCRIPTION
)
1129 m_nextDescBoxSize
= ht
;
1131 RecalculatePositions(m_width
, m_height
);
1135 // -----------------------------------------------------------------------
1137 int wxPropertyGridManager::GetDescBoxHeight() const
1139 return GetClientSize().y
- m_splitterY
;
1142 // -----------------------------------------------------------------------
1144 void wxPropertyGridManager::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
1148 // Update everything inside the box
1149 wxRect r
= GetUpdateRegion().GetBox();
1151 // Repaint splitter?
1152 int r_bottom
= r
.y
+ r
.height
;
1153 int splitter_bottom
= m_splitterY
+ m_splitterHeight
;
1154 if ( r
.y
< splitter_bottom
&& r_bottom
>= m_splitterY
)
1155 RepaintSplitter( dc
, m_splitterY
, m_width
, m_height
, false );
1158 // -----------------------------------------------------------------------
1160 void wxPropertyGridManager::Refresh(bool eraseBackground
, const wxRect
* rect
)
1162 m_pPropGrid
->Refresh(eraseBackground
);
1163 wxWindow::Refresh(eraseBackground
,rect
);
1166 // -----------------------------------------------------------------------
1168 void wxPropertyGridManager::RefreshProperty( wxPGProperty
* p
)
1170 wxPropertyGrid
* grid
= p
->GetGrid();
1172 if ( GetPage(m_selPage
)->GetStatePtr() == p
->GetParent()->GetParentState() )
1173 grid
->RefreshProperty(p
);
1176 // -----------------------------------------------------------------------
1178 void wxPropertyGridManager::RecreateControls()
1181 bool was_shown
= IsShown();
1185 wxWindowID baseId
= m_pPropGrid
->GetId();
1187 baseId
= wxPG_MAN_ALTERNATE_BASE_ID
;
1190 if ( m_windowStyle
& wxPG_TOOLBAR
)
1195 m_pToolbar
= new wxToolBar(this,baseId
+ID_ADVTOOLBAR_OFFSET
,
1196 wxDefaultPosition
,wxDefaultSize
,
1197 ((GetExtraStyle()&wxPG_EX_NO_FLAT_TOOLBAR
)?0:wxTB_FLAT
)
1198 /*| wxTB_HORIZONTAL | wxNO_BORDER*/ );
1200 #if defined(__WXMSW__)
1201 // Eliminate toolbar flicker on XP
1202 // NOTE: Not enabled since it corrupts drawing somewhat.
1205 #ifndef WS_EX_COMPOSITED
1206 #define WS_EX_COMPOSITED 0x02000000L
1209 HWND hWnd = (HWND)m_pToolbar->GetHWND();
1211 ::SetWindowLong( hWnd, GWL_EXSTYLE,
1212 ::GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_COMPOSITED );
1217 m_pToolbar
->SetCursor ( *wxSTANDARD_CURSOR
);
1219 if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS
) )
1221 wxString
desc1(_("Categorized Mode"));
1222 wxString
desc2(_("Alphabetic Mode"));
1223 m_pToolbar
->AddTool(baseId
+ID_ADVTBITEMSBASE_OFFSET
+0,
1224 desc1
,wxBitmap ( (const char**)gs_xpm_catmode
),
1225 desc1
,wxITEM_RADIO
);
1226 m_pToolbar
->AddTool(baseId
+ID_ADVTBITEMSBASE_OFFSET
+1,
1227 desc2
,wxBitmap ( (const char**)gs_xpm_noncatmode
),
1228 desc2
,wxITEM_RADIO
);
1229 m_pToolbar
->Realize();
1234 if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS
) )
1236 // Toggle correct mode button.
1237 // TODO: This doesn't work in wxMSW (when changing,
1238 // both items will get toggled).
1239 int toggle_but_on_ind
= ID_ADVTBITEMSBASE_OFFSET
+0;
1240 int toggle_but_off_ind
= ID_ADVTBITEMSBASE_OFFSET
+1;
1241 if ( m_pPropGrid
->m_pState
->IsInNonCatMode() )
1243 toggle_but_on_ind
++;
1244 toggle_but_off_ind
--;
1247 m_pToolbar
->ToggleTool(baseId
+toggle_but_on_ind
,true);
1248 m_pToolbar
->ToggleTool(baseId
+toggle_but_off_ind
,false);
1256 m_pToolbar
->Destroy();
1257 m_pToolbar
= (wxToolBar
*) NULL
;
1261 if ( m_windowStyle
& wxPG_DESCRIPTION
)
1264 m_pPropGrid
->m_iFlags
|= (wxPG_FL_NOSTATUSBARHELP
);
1266 if ( !m_pTxtHelpCaption
)
1268 m_pTxtHelpCaption
= new wxStaticText (this,baseId
+ID_ADVHELPCAPTION_OFFSET
,wxEmptyString
);
1269 m_pTxtHelpCaption
->SetFont( m_pPropGrid
->m_captionFont
);
1270 m_pTxtHelpCaption
->SetCursor ( *wxSTANDARD_CURSOR
);
1272 if ( !m_pTxtHelpContent
)
1274 m_pTxtHelpContent
= new wxStaticText (this,baseId
+ID_ADVHELPCONTENT_OFFSET
,
1275 wxEmptyString
,wxDefaultPosition
,wxDefaultSize
,wxALIGN_LEFT
|wxST_NO_AUTORESIZE
);
1276 m_pTxtHelpContent
->SetCursor ( *wxSTANDARD_CURSOR
);
1282 m_pPropGrid
->m_iFlags
&= ~(wxPG_FL_NOSTATUSBARHELP
);
1284 if ( m_pTxtHelpCaption
)
1285 m_pTxtHelpCaption
->Destroy();
1287 m_pTxtHelpCaption
= (wxStaticText
*) NULL
;
1289 if ( m_pTxtHelpContent
)
1290 m_pTxtHelpContent
->Destroy();
1292 m_pTxtHelpContent
= (wxStaticText
*) NULL
;
1297 GetClientSize(&width
,&height
);
1299 RecalculatePositions(width
,height
);
1305 // -----------------------------------------------------------------------
1307 wxPGProperty
* wxPropertyGridManager::DoGetPropertyByName( const wxString
& name
) const
1310 for ( i
=0; i
<GetPageCount(); i
++ )
1312 wxPropertyGridPageState
* pState
= m_arrPages
[i
]->GetStatePtr();
1313 wxPGProperty
* p
= pState
->BaseGetPropertyByName(name
);
1322 // -----------------------------------------------------------------------
1324 bool wxPropertyGridManager::EnsureVisible( wxPGPropArg id
)
1326 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
1328 wxPropertyGridPageState
* parentState
= p
->GetParentState();
1330 // Select correct page.
1331 if ( m_pPropGrid
->m_pState
!= parentState
)
1332 DoSelectPage( GetPageByState(parentState
) );
1334 return m_pPropGrid
->EnsureVisible(id
);
1337 // -----------------------------------------------------------------------
1339 void wxPropertyGridManager::OnToolbarClick( wxCommandEvent
&event
)
1341 int id
= event
.GetId();
1344 int baseId
= m_pPropGrid
->GetId();
1346 baseId
= wxPG_MAN_ALTERNATE_BASE_ID
;
1348 if ( id
== ( baseId
+ ID_ADVTBITEMSBASE_OFFSET
+ 0 ) )
1350 // Categorized mode.
1351 if ( m_pPropGrid
->m_windowStyle
& wxPG_HIDE_CATEGORIES
)
1352 m_pPropGrid
->EnableCategories( true );
1354 else if ( id
== ( baseId
+ ID_ADVTBITEMSBASE_OFFSET
+ 1 ) )
1357 if ( !(m_pPropGrid
->m_windowStyle
& wxPG_HIDE_CATEGORIES
) )
1358 m_pPropGrid
->EnableCategories( false );
1366 wxPropertyGridPage
* pdc
;
1368 // Find page with given id.
1369 for ( i
=0; i
<GetPageCount(); i
++ )
1371 pdc
= m_arrPages
[i
];
1372 if ( pdc
->m_id
== id
)
1379 wxASSERT( index
>= 0 );
1381 if ( DoSelectPage( index
) )
1384 // Event dispatching must be last.
1385 m_pPropGrid
->SendEvent( wxEVT_PG_PAGE_CHANGED
, (wxPGProperty
*) NULL
);
1390 // TODO: Depress the old button on toolbar.
1397 // -----------------------------------------------------------------------
1399 void wxPropertyGridManager::SetDescription( const wxString
& label
, const wxString
& content
)
1401 if ( m_pTxtHelpCaption
)
1403 wxSize osz1
= m_pTxtHelpCaption
->GetSize();
1404 wxSize osz2
= m_pTxtHelpContent
->GetSize();
1406 m_pTxtHelpCaption
->SetLabel(label
);
1407 m_pTxtHelpContent
->SetLabel(content
);
1409 m_pTxtHelpCaption
->SetSize(-1,osz1
.y
);
1410 m_pTxtHelpContent
->SetSize(-1,osz2
.y
);
1412 if ( (m_iFlags
& wxPG_FL_DESC_REFRESH_REQUIRED
) || (osz2
.x
<(m_width
-10)) )
1413 RefreshHelpBox( m_splitterY
, m_width
, m_height
);
1417 // -----------------------------------------------------------------------
1419 void wxPropertyGridManager::SetDescribedProperty( wxPGProperty
* p
)
1421 if ( m_pTxtHelpCaption
)
1425 SetDescription( p
->GetLabel(), p
->GetHelpString() );
1429 m_pTxtHelpCaption
->SetLabel(wxEmptyString
);
1430 m_pTxtHelpContent
->SetLabel(wxEmptyString
);
1435 // -----------------------------------------------------------------------
1437 void wxPropertyGridManager::SetSplitterLeft( bool subProps
, bool allPages
)
1441 m_pPropGrid
->SetSplitterLeft(subProps
);
1445 wxClientDC
dc(this);
1446 dc
.SetFont(m_pPropGrid
->m_font
);
1451 for ( i
=0; i
<GetPageCount(); i
++ )
1453 int maxW
= m_pState
->GetColumnFitWidth(dc
, m_arrPages
[i
]->m_properties
, 0, subProps
);
1454 maxW
+= m_pPropGrid
->m_marginWidth
;
1455 if ( maxW
> highest
)
1460 m_pPropGrid
->SetSplitterPosition( highest
);
1462 m_pPropGrid
->m_iFlags
|= wxPG_FL_DONT_CENTER_SPLITTER
;
1466 // -----------------------------------------------------------------------
1468 void wxPropertyGridManager::OnPropertyGridSelect( wxPropertyGridEvent
& event
)
1471 wxASSERT_MSG( GetId() == m_pPropGrid
->GetId(),
1472 wxT("wxPropertyGridManager id must be set with wxPropertyGridManager::SetId (not wxWindow::SetId).") );
1474 SetDescribedProperty(event
.GetProperty());
1478 // -----------------------------------------------------------------------
1480 void wxPropertyGridManager::OnResize( wxSizeEvent
& WXUNUSED(event
) )
1484 GetClientSize(&width
,&height
);
1486 if ( m_width
== -12345 )
1489 RecalculatePositions(width
,height
);
1492 // -----------------------------------------------------------------------
1494 void wxPropertyGridManager::OnMouseEntry( wxMouseEvent
& WXUNUSED(event
) )
1496 // Correct cursor. This is required atleast for wxGTK, for which
1497 // setting button's cursor to *wxSTANDARD_CURSOR does not work.
1498 SetCursor( wxNullCursor
);
1502 // -----------------------------------------------------------------------
1504 void wxPropertyGridManager::OnMouseMove( wxMouseEvent
&event
)
1506 if ( !m_pTxtHelpCaption
)
1511 if ( m_dragStatus
> 0 )
1513 int sy
= y
- m_dragOffset
;
1515 // Calculate drag limits
1516 int bottom_limit
= m_height
- m_splitterHeight
+ 1;
1517 int top_limit
= m_pPropGrid
->m_lineHeight
;
1519 if ( m_pToolbar
) top_limit
+= m_pToolbar
->GetSize().y
;
1522 if ( sy
>= top_limit
&& sy
< bottom_limit
)
1525 int change
= sy
- m_splitterY
;
1530 m_pPropGrid
->SetSize( m_width
, m_splitterY
- m_pPropGrid
->GetPosition().y
);
1531 RefreshHelpBox( m_splitterY
, m_width
, m_height
);
1533 m_extraHeight
-= change
;
1534 InvalidateBestSize();
1542 if ( y
>= m_splitterY
&& y
< (m_splitterY
+m_splitterHeight
+2) )
1544 SetCursor ( m_cursorSizeNS
);
1551 SetCursor ( wxNullCursor
);
1558 // -----------------------------------------------------------------------
1560 void wxPropertyGridManager::OnMouseClick( wxMouseEvent
&event
)
1564 // Click on splitter.
1565 if ( y
>= m_splitterY
&& y
< (m_splitterY
+m_splitterHeight
+2) )
1567 if ( m_dragStatus
== 0 )
1570 // Begin draggin the splitter
1577 m_dragOffset
= y
- m_splitterY
;
1583 // -----------------------------------------------------------------------
1585 void wxPropertyGridManager::OnMouseUp( wxMouseEvent
&event
)
1587 // No event type check - basicly calling this method should
1588 // just stop dragging.
1590 if ( m_dragStatus
>= 1 )
1593 // End Splitter Dragging
1598 // DO NOT ENABLE FOLLOWING LINE!
1599 // (it is only here as a reminder to not to do it)
1602 // This is necessary to return cursor
1605 // Set back the default cursor, if necessary
1606 if ( y
< m_splitterY
|| y
>= (m_splitterY
+m_splitterHeight
+2) )
1608 SetCursor ( wxNullCursor
);
1615 // -----------------------------------------------------------------------
1617 void wxPropertyGridManager::SetSplitterPosition( int pos
, int splitterColumn
)
1619 wxASSERT_MSG( GetPageCount(),
1620 wxT("SetSplitterPosition() has no effect until pages have been added") );
1623 for ( i
=0; i
<GetPageCount(); i
++ )
1625 wxPropertyGridPage
* page
= GetPage(i
);
1626 page
->DoSetSplitterPositionThisPage( pos
, splitterColumn
);
1629 m_pPropGrid
->SetInternalFlag(wxPG_FL_SPLITTER_PRE_SET
);
1632 // -----------------------------------------------------------------------
1633 // wxPGVIterator_Manager
1634 // -----------------------------------------------------------------------
1636 // Default returned by wxPropertyGridInterface::CreateVIterator().
1637 class wxPGVIteratorBase_Manager
: public wxPGVIteratorBase
1640 wxPGVIteratorBase_Manager( wxPropertyGridManager
* manager
, int flags
)
1641 : m_manager(manager
), m_flags(flags
), m_curPage(0)
1643 m_it
.Init(manager
->GetPage(0), flags
);
1645 virtual ~wxPGVIteratorBase_Manager() { }
1654 if ( m_curPage
< m_manager
->GetPageCount() )
1655 m_it
.Init( m_manager
->GetPage(m_curPage
), m_flags
);
1659 wxPropertyGridManager
* m_manager
;
1661 unsigned int m_curPage
;
1664 wxPGVIterator
wxPropertyGridManager::GetVIterator( int flags
) const
1666 return wxPGVIterator( new wxPGVIteratorBase_Manager( (wxPropertyGridManager
*)this, flags
) );
1669 #endif // wxUSE_PROPGRID