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 char wxPropertyGridManagerNameStr
[] = "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
,
213 bool fromAutoCenter
)
215 if ( allPages
&& m_manager
->GetPageCount() )
216 m_manager
->SetSplitterPosition( pos
, splitterColumn
);
218 wxPropertyGridPageState::DoSetSplitterPosition( pos
,
224 // -----------------------------------------------------------------------
225 // wxPropertyGridManager
226 // -----------------------------------------------------------------------
228 // Final default splitter y is client height minus this.
229 #define wxPGMAN_DEFAULT_NEGATIVE_SPLITTER_Y 100
231 // -----------------------------------------------------------------------
233 IMPLEMENT_CLASS(wxPropertyGridManager
, wxPanel
)
235 #define ID_ADVTOOLBAR_OFFSET 1
236 #define ID_ADVHELPCAPTION_OFFSET 2
237 #define ID_ADVHELPCONTENT_OFFSET 3
238 //#define ID_ADVBUTTON_OFFSET 4
239 #define ID_ADVTBITEMSBASE_OFFSET 5 // Must be last.
241 // -----------------------------------------------------------------------
243 BEGIN_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)
253 // -----------------------------------------------------------------------
255 wxPropertyGridManager::wxPropertyGridManager()
261 // -----------------------------------------------------------------------
263 wxPropertyGridManager::wxPropertyGridManager( wxWindow
*parent
,
268 const wxString
& name
)
272 Create(parent
,id
,pos
,size
,style
,name
);
275 // -----------------------------------------------------------------------
277 bool wxPropertyGridManager::Create( wxWindow
*parent
,
282 const wxString
& name
)
285 m_pPropGrid
= CreatePropertyGrid();
287 bool res
= wxPanel::Create( parent
, id
, pos
, size
,
288 (style
&0xFFFF0000)|wxWANTS_CHARS
,
292 // FIXME: this changes call ordering so wxPropertyGrid is created
293 // immediately, before SetExtraStyle has a chance to be called. However,
294 // without it, we may get assertions if size is wxDefaultSize.
295 //SetInitialSize(size);
300 // -----------------------------------------------------------------------
303 // Initialize values to defaults
305 void wxPropertyGridManager::Init1()
313 m_pTxtHelpCaption
= NULL
;
314 m_pTxtHelpContent
= NULL
;
320 m_width
= m_height
= 0;
322 m_splitterHeight
= 5;
324 m_splitterY
= -1; // -1 causes default to be set.
326 m_nextDescBoxSize
= -1;
334 // -----------------------------------------------------------------------
336 // These flags are always used in wxPropertyGrid integrated in wxPropertyGridManager.
337 #define wxPG_MAN_PROPGRID_FORCED_FLAGS ( wxBORDER_THEME | \
338 wxNO_FULL_REPAINT_ON_RESIZE| \
341 // Which flags can be passed to underlying wxPropertyGrid.
342 #define wxPG_MAN_PASS_FLAGS_MASK (0xFFF0|wxTAB_TRAVERSAL)
345 // Initialize after parent etc. set
347 void wxPropertyGridManager::Init2( int style
)
350 if ( m_iFlags
& wxPG_FL_INITIALIZED
)
353 m_windowStyle
|= (style
&0x0000FFFF);
355 wxSize csz
= GetClientSize();
357 m_cursorSizeNS
= wxCursor(wxCURSOR_SIZENS
);
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
;
367 m_arrPages
.push_back( pd
);
368 m_pPropGrid
->m_pState
= state
;
370 wxWindowID baseId
= GetId();
371 wxWindowID useId
= baseId
;
373 baseId
= wxPG_MAN_ALTERNATE_BASE_ID
;
378 // Smaller controls on Mac
379 SetWindowVariant(wxWINDOW_VARIANT_SMALL
);
382 long propGridFlags
= (m_windowStyle
&wxPG_MAN_PASS_FLAGS_MASK
)
383 |wxPG_MAN_PROPGRID_FORCED_FLAGS
;
385 propGridFlags
&= ~wxBORDER_MASK
;
387 if ((style
& wxPG_NO_INTERNAL_BORDER
) == 0)
389 propGridFlags
|= wxBORDER_THEME
;
393 propGridFlags
|= wxBORDER_NONE
;
394 wxWindow::SetExtraStyle(wxPG_EX_TOOLBAR_SEPARATOR
);
397 // Create propertygrid.
398 m_pPropGrid
->Create(this,baseId
,wxPoint(0,0),csz
, propGridFlags
);
400 m_pPropGrid
->m_eventObject
= this;
402 m_pPropGrid
->SetId(useId
);
404 m_pPropGrid
->m_iFlags
|= wxPG_FL_IN_MANAGER
;
406 m_pState
= m_pPropGrid
->m_pState
;
408 m_pPropGrid
->SetExtraStyle(wxPG_EX_INIT_NOCAT
);
410 m_nextTbInd
= baseId
+ID_ADVTBITEMSBASE_OFFSET
+ 2;
413 // Connect to property grid onselect event.
414 // NB: Even if wxID_ANY is used, this doesn't connect properly in wxPython
415 // (see wxPropertyGridManager::ProcessEvent).
416 Connect(m_pPropGrid
->GetId()/*wxID_ANY*/,
418 wxPropertyGridEventHandler(wxPropertyGridManager::OnPropertyGridSelect
) );
420 // Connect to toolbar button events.
421 Connect(baseId
+ID_ADVTBITEMSBASE_OFFSET
,baseId
+ID_ADVTBITEMSBASE_OFFSET
+50,
422 wxEVT_COMMAND_TOOL_CLICKED
,
423 wxCommandEventHandler(wxPropertyGridManager::OnToolbarClick
) );
425 // Optional initial controls.
428 m_iFlags
|= wxPG_FL_INITIALIZED
;
432 // -----------------------------------------------------------------------
434 wxPropertyGridManager::~wxPropertyGridManager()
438 //m_pPropGrid->ClearSelection();
443 for ( i
=0; i
<m_arrPages
.size(); i
++ )
445 delete m_arrPages
[i
];
451 // -----------------------------------------------------------------------
453 wxPropertyGrid
* wxPropertyGridManager::CreatePropertyGrid() const
455 return new wxPropertyGrid();
458 // -----------------------------------------------------------------------
460 void wxPropertyGridManager::SetId( wxWindowID winid
)
462 wxWindow::SetId(winid
);
464 // TODO: Reconnect propgrid event handler(s).
466 m_pPropGrid
->SetId(winid
);
469 // -----------------------------------------------------------------------
471 wxSize
wxPropertyGridManager::DoGetBestSize() const
473 return wxSize(60,150);
476 // -----------------------------------------------------------------------
478 bool wxPropertyGridManager::SetFont( const wxFont
& font
)
480 bool res
= wxWindow::SetFont(font
);
481 m_pPropGrid
->SetFont(font
);
483 // TODO: Need to do caption recacalculations for other pages as well.
485 for ( i
=0; i
<m_arrPages
.size(); i
++ )
487 wxPropertyGridPage
* page
= GetPage(i
);
489 if ( page
!= m_pPropGrid
->GetState() )
490 page
->CalculateFontAndBitmapStuff(-1);
496 // -----------------------------------------------------------------------
498 void wxPropertyGridManager::SetExtraStyle( long exStyle
)
500 wxWindow::SetExtraStyle( exStyle
);
501 m_pPropGrid
->SetExtraStyle( exStyle
& 0xFFFFF000 );
503 if ( (exStyle
& wxPG_EX_NO_FLAT_TOOLBAR
) && m_pToolbar
)
508 // -----------------------------------------------------------------------
510 void wxPropertyGridManager::Freeze()
512 m_pPropGrid
->Freeze();
516 // -----------------------------------------------------------------------
518 void wxPropertyGridManager::Thaw()
524 // -----------------------------------------------------------------------
526 void wxPropertyGridManager::SetWindowStyleFlag( long style
)
528 int oldWindowStyle
= GetWindowStyleFlag();
530 wxWindow::SetWindowStyleFlag( style
);
531 m_pPropGrid
->SetWindowStyleFlag( (m_pPropGrid
->GetWindowStyleFlag()&~(wxPG_MAN_PASS_FLAGS_MASK
)) |
532 (style
&wxPG_MAN_PASS_FLAGS_MASK
) );
534 // Need to re-position windows?
535 if ( (oldWindowStyle
& (wxPG_TOOLBAR
|wxPG_DESCRIPTION
)) !=
536 (style
& (wxPG_TOOLBAR
|wxPG_DESCRIPTION
)) )
542 // -----------------------------------------------------------------------
544 bool wxPropertyGridManager::Reparent( wxWindowBase
*newParent
)
547 m_pPropGrid
->OnTLPChanging((wxWindow
*)newParent
);
549 bool res
= wxPanel::Reparent(newParent
);
554 // -----------------------------------------------------------------------
556 // Actually shows given page.
557 bool wxPropertyGridManager::DoSelectPage( int index
)
559 // -1 means no page was selected
560 //wxASSERT( m_selPage >= 0 );
562 wxCHECK_MSG( index
>= -1 && index
< (int)GetPageCount(),
564 wxT("invalid page index") );
566 if ( m_selPage
== index
)
569 if ( m_pPropGrid
->GetSelection() )
571 if ( !m_pPropGrid
->ClearSelection() )
575 wxPropertyGridPage
* prevPage
;
577 if ( m_selPage
>= 0 )
578 prevPage
= GetPage(m_selPage
);
580 prevPage
= m_emptyPage
;
582 wxPropertyGridPage
* nextPage
;
586 nextPage
= m_arrPages
[index
];
594 m_emptyPage
= new wxPropertyGridPage();
595 m_emptyPage
->m_pPropGrid
= m_pPropGrid
;
598 nextPage
= m_emptyPage
;
601 m_iFlags
|= wxPG_FL_DESC_REFRESH_REQUIRED
;
603 m_pPropGrid
->SwitchState( nextPage
->GetStatePtr() );
605 m_pState
= m_pPropGrid
->m_pState
;
613 m_pToolbar
->ToggleTool( nextPage
->m_id
, true );
615 m_pToolbar
->ToggleTool( prevPage
->m_id
, false );
622 // -----------------------------------------------------------------------
624 // Changes page *and* set the target page for insertion operations.
625 void wxPropertyGridManager::SelectPage( int index
)
630 // -----------------------------------------------------------------------
632 int wxPropertyGridManager::GetPageByName( const wxString
& name
) const
635 for ( i
=0; i
<GetPageCount(); i
++ )
637 if ( m_arrPages
[i
]->m_label
== name
)
643 // -----------------------------------------------------------------------
645 int wxPropertyGridManager::GetPageByState( const wxPropertyGridPageState
* pState
) const
650 for ( i
=0; i
<GetPageCount(); i
++ )
652 if ( pState
== m_arrPages
[i
]->GetStatePtr() )
659 // -----------------------------------------------------------------------
661 const wxString
& wxPropertyGridManager::GetPageName( int index
) const
663 wxASSERT( index
>= 0 && index
< (int)GetPageCount() );
664 return m_arrPages
[index
]->m_label
;
667 // -----------------------------------------------------------------------
669 wxPropertyGridPageState
* wxPropertyGridManager::GetPageState( int page
) const
671 // Do not change this into wxCHECK because returning NULL is important
672 // for wxPropertyGridInterface page enumeration mechanics.
673 if ( page
>= (int)GetPageCount() )
678 return m_arrPages
[page
];
681 // -----------------------------------------------------------------------
683 void wxPropertyGridManager::Clear()
685 m_pPropGrid
->ClearSelection(false);
687 m_pPropGrid
->Freeze();
690 for ( i
=(int)GetPageCount()-1; i
>=0; i
-- )
694 m_nextTbInd
= m_baseId
+ID_ADVTBITEMSBASE_OFFSET
+ 2;
699 // -----------------------------------------------------------------------
701 void wxPropertyGridManager::ClearPage( int page
)
703 wxASSERT( page
>= 0 );
704 wxASSERT( page
< (int)GetPageCount() );
706 if ( page
>= 0 && page
< (int)GetPageCount() )
708 wxPropertyGridPageState
* state
= m_arrPages
[page
];
710 if ( state
== m_pPropGrid
->GetState() )
711 m_pPropGrid
->Clear();
717 // -----------------------------------------------------------------------
719 int wxPropertyGridManager::GetColumnCount( int page
) const
721 wxASSERT( page
>= -1 );
722 wxASSERT( page
< (int)GetPageCount() );
724 return GetPageState(page
)->GetColumnCount();
727 // -----------------------------------------------------------------------
729 void wxPropertyGridManager::SetColumnCount( int colCount
, int page
)
731 wxASSERT( page
>= -1 );
732 wxASSERT( page
< (int)GetPageCount() );
734 GetPageState(page
)->SetColumnCount( colCount
);
735 GetGrid()->Refresh();
737 // -----------------------------------------------------------------------
739 size_t wxPropertyGridManager::GetPageCount() const
741 if ( !(m_iFlags
& wxPG_MAN_FL_PAGE_INSERTED
) )
744 return m_arrPages
.size();
747 // -----------------------------------------------------------------------
749 wxPropertyGridPage
* wxPropertyGridManager::InsertPage( int index
,
750 const wxString
& label
,
752 wxPropertyGridPage
* pageObj
)
755 index
= GetPageCount();
757 wxCHECK_MSG( (size_t)index
== GetPageCount(), NULL
,
758 wxT("wxPropertyGridManager currently only supports appending pages (due to wxToolBar limitation)."));
760 bool needInit
= true;
761 bool isPageInserted
= m_iFlags
& wxPG_MAN_FL_PAGE_INSERTED
? true : false;
763 wxASSERT( index
== 0 || isPageInserted
);
767 // No custom page object was given, so we will either re-use the default base
768 // page (if index==0), or create a new default page object.
769 if ( !isPageInserted
)
771 pageObj
= GetPage(0);
772 // Of course, if the base page was custom, we need to delete and
774 if ( !pageObj
->m_isDefault
)
777 pageObj
= new wxPropertyGridPage();
778 m_arrPages
[0] = pageObj
;
784 pageObj
= new wxPropertyGridPage();
786 pageObj
->m_isDefault
= true;
790 if ( !isPageInserted
)
792 // Initial page needs to be deleted and replaced
794 m_arrPages
[0] = pageObj
;
795 m_pPropGrid
->m_pState
= pageObj
->GetStatePtr();
799 wxPropertyGridPageState
* state
= pageObj
->GetStatePtr();
801 pageObj
->m_manager
= this;
805 state
->m_pPropGrid
= m_pPropGrid
;
806 state
->InitNonCatMode();
809 if ( label
.length() )
811 wxASSERT_MSG( !pageObj
->m_label
.length(),
812 wxT("If page label is given in constructor, empty label must be given in AddPage"));
813 pageObj
->m_label
= label
;
816 pageObj
->m_id
= m_nextTbInd
;
818 if ( !HasFlag(wxPG_SPLITTER_AUTO_CENTER
) )
819 pageObj
->m_dontCenterSplitter
= true;
821 if ( isPageInserted
)
822 m_arrPages
.push_back( pageObj
);
825 if ( m_windowStyle
& wxPG_TOOLBAR
)
830 if ( !(GetExtraStyle()&wxPG_EX_HIDE_PAGE_BUTTONS
) )
832 wxASSERT( m_pToolbar
);
834 // Add separator before first page.
835 if ( GetPageCount() < 2 && (GetExtraStyle()&wxPG_EX_MODE_BUTTONS
) &&
836 m_pToolbar
->GetToolsCount() < 3 )
837 m_pToolbar
->AddSeparator();
839 if ( &bmp
!= &wxNullBitmap
)
840 m_pToolbar
->AddTool(m_nextTbInd
,label
,bmp
,label
,wxITEM_RADIO
);
841 //m_pToolbar->InsertTool(index+3,m_nextTbInd,bmp);
843 m_pToolbar
->AddTool(m_nextTbInd
,label
,wxBitmap( (const char**)gs_xpm_defpage
),
848 m_pToolbar
->Realize();
855 // If selected page was above the point of insertion, fix the current page index
856 if ( isPageInserted
)
858 if ( m_selPage
>= index
)
865 // Set this value only when adding the first page
871 m_iFlags
|= wxPG_MAN_FL_PAGE_INSERTED
;
873 wxASSERT( pageObj
->GetGrid() );
878 // -----------------------------------------------------------------------
880 bool wxPropertyGridManager::IsAnyModified() const
883 for ( i
=0; i
<GetPageCount(); i
++ )
885 if ( m_arrPages
[i
]->GetStatePtr()->m_anyModified
)
891 // -----------------------------------------------------------------------
893 bool wxPropertyGridManager::IsPageModified( size_t index
) const
895 if ( m_arrPages
[index
]->GetStatePtr()->m_anyModified
)
900 // -----------------------------------------------------------------------
902 bool wxPropertyGridManager::IsPropertySelected( wxPGPropArg id
) const
904 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
905 for ( unsigned int i
=0; i
<GetPageCount(); i
++ )
907 if ( GetPageState(i
)->DoIsPropertySelected(p
) )
913 // -----------------------------------------------------------------------
915 wxPGProperty
* wxPropertyGridManager::GetPageRoot( int index
) const
917 wxASSERT( index
>= 0 );
918 wxASSERT( index
< (int)m_arrPages
.size() );
920 return m_arrPages
[index
]->GetStatePtr()->m_properties
;
923 // -----------------------------------------------------------------------
925 bool wxPropertyGridManager::RemovePage( int page
)
927 wxCHECK_MSG( (page
>= 0) && (page
< (int)GetPageCount()),
929 wxT("invalid page index") );
931 wxPropertyGridPage
* pd
= m_arrPages
[page
];
933 if ( m_arrPages
.size() == 1 )
935 // Last page: do not remove page entry
936 m_pPropGrid
->Clear();
938 m_iFlags
&= ~wxPG_MAN_FL_PAGE_INSERTED
;
942 // Change selection if current is page
943 else if ( page
== m_selPage
)
945 if ( !m_pPropGrid
->ClearSelection() )
948 // Substitute page to select
949 int substitute
= page
- 1;
950 if ( substitute
< 0 )
951 substitute
= page
+ 1;
953 SelectPage(substitute
);
956 // Remove toolbar icon
958 if ( HasFlag(wxPG_TOOLBAR
) )
960 wxASSERT( m_pToolbar
);
962 int toolPos
= GetExtraStyle() & wxPG_EX_MODE_BUTTONS
? 3 : 0;
965 // Delete separator as well, for consistency
966 if ( (GetExtraStyle() & wxPG_EX_MODE_BUTTONS
) &&
967 GetPageCount() == 1 )
968 m_pToolbar
->DeleteToolByPos(2);
970 m_pToolbar
->DeleteToolByPos(toolPos
);
974 if ( m_arrPages
.size() > 1 )
976 m_arrPages
.erase(m_arrPages
.begin() + page
);
980 // Adjust indexes that were above removed
981 if ( m_selPage
> page
)
987 // -----------------------------------------------------------------------
989 bool wxPropertyGridManager::ProcessEvent( wxEvent
& event
)
991 int evtType
= event
.GetEventType();
993 // NB: For some reason, under wxPython, Connect in Init doesn't work properly,
994 // so we'll need to call OnPropertyGridSelect manually. Multiple call's
995 // don't really matter.
996 if ( evtType
== wxEVT_PG_SELECTED
)
997 OnPropertyGridSelect((wxPropertyGridEvent
&)event
);
999 // Property grid events get special attention
1000 if ( evtType
>= wxPG_BASE_EVT_TYPE
&&
1001 evtType
< (wxPG_MAX_EVT_TYPE
) &&
1004 wxPropertyGridPage
* page
= GetPage(m_selPage
);
1005 wxPropertyGridEvent
* pgEvent
= wxDynamicCast(&event
, wxPropertyGridEvent
);
1007 // Add property grid events to appropriate custom pages
1008 // but stop propagating to parent if page says it is
1009 // handling everything.
1010 if ( pgEvent
&& !page
->m_isDefault
)
1012 /*if ( pgEvent->IsPending() )
1013 page->AddPendingEvent(event);
1015 page
->ProcessEvent(event
);
1017 if ( page
->IsHandlingAllEvents() )
1018 event
.StopPropagation();
1022 return wxPanel::ProcessEvent(event
);
1025 // -----------------------------------------------------------------------
1027 void wxPropertyGridManager::RepaintDescBoxDecorations( wxDC
& dc
,
1033 wxColour bgcol
= GetBackgroundColour();
1036 int rectHeight
= m_splitterHeight
;
1037 dc
.DrawRectangle(0, newSplitterY
, newWidth
, rectHeight
);
1038 dc
.SetPen( wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
) );
1039 int splitterBottom
= newSplitterY
+ m_splitterHeight
- 1;
1040 int boxHeight
= newHeight
- splitterBottom
;
1041 if ( boxHeight
> 1 )
1042 dc
.DrawRectangle(0, splitterBottom
, newWidth
, boxHeight
);
1044 dc
.DrawLine(0, splitterBottom
, newWidth
, splitterBottom
);
1047 // -----------------------------------------------------------------------
1049 void wxPropertyGridManager::UpdateDescriptionBox( int new_splittery
, int new_width
, int new_height
)
1051 int use_hei
= new_height
;
1054 // Fix help control positions.
1055 int cap_hei
= m_pPropGrid
->m_fontHeight
;
1056 int cap_y
= new_splittery
+m_splitterHeight
+5;
1057 int cnt_y
= cap_y
+cap_hei
+3;
1058 int sub_cap_hei
= cap_y
+cap_hei
-use_hei
;
1059 int cnt_hei
= use_hei
-cnt_y
;
1060 if ( sub_cap_hei
> 0 )
1062 cap_hei
-= sub_cap_hei
;
1067 m_pTxtHelpCaption
->Show( false );
1068 m_pTxtHelpContent
->Show( false );
1072 m_pTxtHelpCaption
->SetSize(3,cap_y
,new_width
-6,cap_hei
);
1073 m_pTxtHelpCaption
->Wrap(-1);
1074 m_pTxtHelpCaption
->Show( true );
1077 m_pTxtHelpContent
->Show( false );
1081 m_pTxtHelpContent
->SetSize(3,cnt_y
,new_width
-6,cnt_hei
);
1082 m_pTxtHelpContent
->Show( true );
1086 wxRect
r(0, new_splittery
, new_width
, new_height
-new_splittery
);
1089 m_splitterY
= new_splittery
;
1091 m_iFlags
&= ~(wxPG_FL_DESC_REFRESH_REQUIRED
);
1094 // -----------------------------------------------------------------------
1096 void wxPropertyGridManager::RecalculatePositions( int width
, int height
)
1099 int propgridBottomY
= height
;
1101 // Toolbar at the top.
1105 m_pToolbar
->SetSize(0, 0, width
, -1);
1106 propgridY
+= m_pToolbar
->GetSize().y
;
1108 if (GetExtraStyle() & wxPG_EX_TOOLBAR_SEPARATOR
)
1114 if ( m_pTxtHelpCaption
)
1116 int new_splittery
= m_splitterY
;
1119 if ( ( m_splitterY
>= 0 || m_nextDescBoxSize
) && m_height
> 32 )
1121 if ( m_nextDescBoxSize
>= 0 )
1123 new_splittery
= m_height
- m_nextDescBoxSize
- m_splitterHeight
;
1124 m_nextDescBoxSize
= -1;
1126 new_splittery
+= (height
-m_height
);
1130 new_splittery
= height
- wxPGMAN_DEFAULT_NEGATIVE_SPLITTER_Y
;
1131 if ( new_splittery
< 32 )
1135 // Check if beyond minimum.
1136 int nspy_min
= propgridY
+ m_pPropGrid
->m_lineHeight
;
1137 if ( new_splittery
< nspy_min
)
1138 new_splittery
= nspy_min
;
1140 propgridBottomY
= new_splittery
;
1142 UpdateDescriptionBox( new_splittery
, width
, height
);
1145 if ( m_iFlags
& wxPG_FL_INITIALIZED
)
1147 int pgh
= propgridBottomY
- propgridY
;
1150 m_pPropGrid
->SetSize( 0, propgridY
, width
, pgh
);
1152 m_extraHeight
= height
- pgh
;
1159 // -----------------------------------------------------------------------
1161 void wxPropertyGridManager::SetDescBoxHeight( int ht
, bool refresh
)
1163 if ( m_windowStyle
& wxPG_DESCRIPTION
)
1165 if ( ht
!= GetDescBoxHeight() )
1167 m_nextDescBoxSize
= ht
;
1169 RecalculatePositions(m_width
, m_height
);
1174 // -----------------------------------------------------------------------
1176 int wxPropertyGridManager::GetDescBoxHeight() const
1178 return GetClientSize().y
- m_splitterY
- m_splitterHeight
;
1181 // -----------------------------------------------------------------------
1183 void wxPropertyGridManager::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
1187 // Update everything inside the box
1188 wxRect r
= GetUpdateRegion().GetBox();
1190 if (GetExtraStyle() & wxPG_EX_TOOLBAR_SEPARATOR
)
1192 if (m_pToolbar
&& m_pPropGrid
)
1194 wxPen
marginPen(m_pPropGrid
->GetMarginColour());
1195 dc
.SetPen(marginPen
);
1197 int y
= m_pPropGrid
->GetPosition().y
-1;
1198 dc
.DrawLine(0, y
, GetClientSize().x
, y
);
1202 // Repaint splitter and any other description box decorations
1203 if ( (r
.y
+ r
.height
) >= m_splitterY
&& m_splitterY
!= -1)
1204 RepaintDescBoxDecorations( dc
, m_splitterY
, m_width
, m_height
);
1207 // -----------------------------------------------------------------------
1209 void wxPropertyGridManager::Refresh(bool eraseBackground
, const wxRect
* rect
)
1211 m_pPropGrid
->Refresh(eraseBackground
);
1212 wxWindow::Refresh(eraseBackground
,rect
);
1215 // -----------------------------------------------------------------------
1217 void wxPropertyGridManager::RefreshProperty( wxPGProperty
* p
)
1219 wxPropertyGrid
* grid
= p
->GetGrid();
1221 if ( GetPage(m_selPage
)->GetStatePtr() == p
->GetParent()->GetParentState() )
1222 grid
->RefreshProperty(p
);
1225 // -----------------------------------------------------------------------
1227 void wxPropertyGridManager::RecreateControls()
1230 bool was_shown
= IsShown();
1234 wxWindowID baseId
= m_pPropGrid
->GetId();
1236 baseId
= wxPG_MAN_ALTERNATE_BASE_ID
;
1239 if ( m_windowStyle
& wxPG_TOOLBAR
)
1244 long toolBarFlags
= ((GetExtraStyle()&wxPG_EX_NO_FLAT_TOOLBAR
)?0:wxTB_FLAT
);
1245 if (GetExtraStyle() & wxPG_EX_NO_TOOLBAR_DIVIDER
)
1246 toolBarFlags
|= wxTB_NODIVIDER
;
1248 m_pToolbar
= new wxToolBar(this,baseId
+ID_ADVTOOLBAR_OFFSET
,
1249 wxDefaultPosition
,wxDefaultSize
,
1251 m_pToolbar
->SetToolBitmapSize(wxSize(16, 15));
1253 #if defined(__WXMSW__)
1254 // Eliminate toolbar flicker on XP
1255 // NOTE: Not enabled since it corrupts drawing somewhat.
1258 #ifndef WS_EX_COMPOSITED
1259 #define WS_EX_COMPOSITED 0x02000000L
1262 HWND hWnd = (HWND)m_pToolbar->GetHWND();
1264 ::SetWindowLong( hWnd, GWL_EXSTYLE,
1265 ::GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_COMPOSITED );
1270 m_pToolbar
->SetCursor ( *wxSTANDARD_CURSOR
);
1272 if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS
) )
1274 wxString
desc1(_("Categorized Mode"));
1275 wxString
desc2(_("Alphabetic Mode"));
1276 m_pToolbar
->AddTool(baseId
+ID_ADVTBITEMSBASE_OFFSET
+0,
1277 desc1
,wxBitmap ( (const char**)gs_xpm_catmode
),
1278 desc1
,wxITEM_RADIO
);
1279 m_pToolbar
->AddTool(baseId
+ID_ADVTBITEMSBASE_OFFSET
+1,
1280 desc2
,wxBitmap ( (const char**)gs_xpm_noncatmode
),
1281 desc2
,wxITEM_RADIO
);
1282 m_pToolbar
->Realize();
1287 if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS
) )
1289 // Toggle correct mode button.
1290 // TODO: This doesn't work in wxMSW (when changing,
1291 // both items will get toggled).
1292 int toggle_but_on_ind
= ID_ADVTBITEMSBASE_OFFSET
+0;
1293 int toggle_but_off_ind
= ID_ADVTBITEMSBASE_OFFSET
+1;
1294 if ( m_pPropGrid
->m_pState
->IsInNonCatMode() )
1296 toggle_but_on_ind
++;
1297 toggle_but_off_ind
--;
1300 m_pToolbar
->ToggleTool(baseId
+toggle_but_on_ind
,true);
1301 m_pToolbar
->ToggleTool(baseId
+toggle_but_off_ind
,false);
1309 m_pToolbar
->Destroy();
1314 if ( m_windowStyle
& wxPG_DESCRIPTION
)
1317 m_pPropGrid
->m_iFlags
|= (wxPG_FL_NOSTATUSBARHELP
);
1319 if ( !m_pTxtHelpCaption
)
1321 m_pTxtHelpCaption
= new wxStaticText(this,
1322 baseId
+ID_ADVHELPCAPTION_OFFSET
,
1326 wxALIGN_LEFT
|wxST_NO_AUTORESIZE
);
1327 m_pTxtHelpCaption
->SetFont( m_pPropGrid
->m_captionFont
);
1328 m_pTxtHelpCaption
->SetCursor( *wxSTANDARD_CURSOR
);
1330 if ( !m_pTxtHelpContent
)
1332 m_pTxtHelpContent
= new wxStaticText(this,
1333 baseId
+ID_ADVHELPCONTENT_OFFSET
,
1337 wxALIGN_LEFT
|wxST_NO_AUTORESIZE
);
1338 m_pTxtHelpContent
->SetCursor( *wxSTANDARD_CURSOR
);
1341 SetDescribedProperty(GetSelection());
1346 m_pPropGrid
->m_iFlags
&= ~(wxPG_FL_NOSTATUSBARHELP
);
1348 if ( m_pTxtHelpCaption
)
1349 m_pTxtHelpCaption
->Destroy();
1351 m_pTxtHelpCaption
= NULL
;
1353 if ( m_pTxtHelpContent
)
1354 m_pTxtHelpContent
->Destroy();
1356 m_pTxtHelpContent
= NULL
;
1361 GetClientSize(&width
,&height
);
1363 RecalculatePositions(width
,height
);
1369 // -----------------------------------------------------------------------
1371 wxPGProperty
* wxPropertyGridManager::DoGetPropertyByName( const wxString
& name
) const
1374 for ( i
=0; i
<GetPageCount(); i
++ )
1376 wxPropertyGridPageState
* pState
= m_arrPages
[i
]->GetStatePtr();
1377 wxPGProperty
* p
= pState
->BaseGetPropertyByName(name
);
1386 // -----------------------------------------------------------------------
1388 bool wxPropertyGridManager::EnsureVisible( wxPGPropArg id
)
1390 wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false)
1392 wxPropertyGridPageState
* parentState
= p
->GetParentState();
1394 // Select correct page.
1395 if ( m_pPropGrid
->m_pState
!= parentState
)
1396 DoSelectPage( GetPageByState(parentState
) );
1398 return m_pPropGrid
->EnsureVisible(id
);
1401 // -----------------------------------------------------------------------
1403 void wxPropertyGridManager::OnToolbarClick( wxCommandEvent
&event
)
1405 int id
= event
.GetId();
1408 int baseId
= m_pPropGrid
->GetId();
1410 baseId
= wxPG_MAN_ALTERNATE_BASE_ID
;
1412 if ( id
== ( baseId
+ ID_ADVTBITEMSBASE_OFFSET
+ 0 ) )
1414 // Categorized mode.
1415 if ( m_pPropGrid
->m_windowStyle
& wxPG_HIDE_CATEGORIES
)
1417 if ( !m_pPropGrid
->HasInternalFlag(wxPG_FL_CATMODE_AUTO_SORT
) )
1418 m_pPropGrid
->m_windowStyle
&= ~wxPG_AUTO_SORT
;
1419 m_pPropGrid
->EnableCategories( true );
1422 else if ( id
== ( baseId
+ ID_ADVTBITEMSBASE_OFFSET
+ 1 ) )
1425 if ( !(m_pPropGrid
->m_windowStyle
& wxPG_HIDE_CATEGORIES
) )
1427 if ( m_pPropGrid
->HasFlag(wxPG_AUTO_SORT
) )
1428 m_pPropGrid
->SetInternalFlag(wxPG_FL_CATMODE_AUTO_SORT
);
1430 m_pPropGrid
->ClearInternalFlag(wxPG_FL_CATMODE_AUTO_SORT
);
1432 m_pPropGrid
->m_windowStyle
|= wxPG_AUTO_SORT
;
1433 m_pPropGrid
->EnableCategories( false );
1442 wxPropertyGridPage
* pdc
;
1444 // Find page with given id.
1445 for ( i
=0; i
<GetPageCount(); i
++ )
1447 pdc
= m_arrPages
[i
];
1448 if ( pdc
->m_id
== id
)
1455 wxASSERT( index
>= 0 );
1457 if ( DoSelectPage( index
) )
1460 // Event dispatching must be last.
1461 m_pPropGrid
->SendEvent( wxEVT_PG_PAGE_CHANGED
, NULL
);
1466 // TODO: Depress the old button on toolbar.
1473 // -----------------------------------------------------------------------
1475 bool wxPropertyGridManager::SetEditableStateItem( const wxString
& name
, wxVariant value
)
1477 if ( name
== wxS("descboxheight") )
1479 SetDescBoxHeight(value
.GetLong(), true);
1485 // -----------------------------------------------------------------------
1487 wxVariant
wxPropertyGridManager::GetEditableStateItem( const wxString
& name
) const
1489 if ( name
== wxS("descboxheight") )
1491 return (long) GetDescBoxHeight();
1493 return wxNullVariant
;
1496 // -----------------------------------------------------------------------
1498 void wxPropertyGridManager::SetDescription( const wxString
& label
, const wxString
& content
)
1500 if ( m_pTxtHelpCaption
)
1502 wxSize osz1
= m_pTxtHelpCaption
->GetSize();
1503 wxSize osz2
= m_pTxtHelpContent
->GetSize();
1505 m_pTxtHelpCaption
->SetLabel(label
);
1506 m_pTxtHelpContent
->SetLabel(content
);
1508 m_pTxtHelpCaption
->SetSize(-1,osz1
.y
);
1509 m_pTxtHelpContent
->SetSize(-1,osz2
.y
);
1511 UpdateDescriptionBox( m_splitterY
, m_width
, m_height
);
1515 // -----------------------------------------------------------------------
1517 void wxPropertyGridManager::SetDescribedProperty( wxPGProperty
* p
)
1519 if ( m_pTxtHelpCaption
)
1523 SetDescription( p
->GetLabel(), p
->GetHelpString() );
1527 SetDescription( wxEmptyString
, wxEmptyString
);
1532 // -----------------------------------------------------------------------
1534 void wxPropertyGridManager::SetSplitterLeft( bool subProps
, bool allPages
)
1538 m_pPropGrid
->SetSplitterLeft(subProps
);
1542 wxClientDC
dc(this);
1543 dc
.SetFont(m_pPropGrid
->GetFont());
1548 for ( i
=0; i
<GetPageCount(); i
++ )
1550 int maxW
= m_pState
->GetColumnFitWidth(dc
, m_arrPages
[i
]->m_properties
, 0, subProps
);
1551 maxW
+= m_pPropGrid
->m_marginWidth
;
1552 if ( maxW
> highest
)
1554 m_pState
->m_dontCenterSplitter
= true;
1558 m_pPropGrid
->SetSplitterPosition( highest
);
1562 // -----------------------------------------------------------------------
1564 void wxPropertyGridManager::OnPropertyGridSelect( wxPropertyGridEvent
& event
)
1567 wxASSERT_MSG( GetId() == m_pPropGrid
->GetId(),
1568 wxT("wxPropertyGridManager id must be set with wxPropertyGridManager::SetId (not wxWindow::SetId).") );
1570 SetDescribedProperty(event
.GetProperty());
1574 // -----------------------------------------------------------------------
1576 void wxPropertyGridManager::OnResize( wxSizeEvent
& WXUNUSED(event
) )
1580 GetClientSize(&width
, &height
);
1582 if ( m_width
== -12345 )
1585 RecalculatePositions(width
, height
);
1587 if ( m_pPropGrid
&& m_pPropGrid
->m_parent
)
1589 int pgWidth
, pgHeight
;
1590 m_pPropGrid
->GetClientSize(&pgWidth
, &pgHeight
);
1592 // Regenerate splitter positions for non-current pages
1593 for ( unsigned int i
=0; i
<GetPageCount(); i
++ )
1595 wxPropertyGridPage
* page
= GetPage(i
);
1596 if ( page
!= m_pPropGrid
->GetState() )
1598 page
->OnClientWidthChange(pgWidth
,
1599 pgWidth
- page
->m_width
,
1606 // -----------------------------------------------------------------------
1608 void wxPropertyGridManager::OnMouseEntry( wxMouseEvent
& WXUNUSED(event
) )
1610 // Correct cursor. This is required atleast for wxGTK, for which
1611 // setting button's cursor to *wxSTANDARD_CURSOR does not work.
1612 SetCursor( wxNullCursor
);
1616 // -----------------------------------------------------------------------
1618 void wxPropertyGridManager::OnMouseMove( wxMouseEvent
&event
)
1620 if ( !m_pTxtHelpCaption
)
1625 if ( m_dragStatus
> 0 )
1627 int sy
= y
- m_dragOffset
;
1629 // Calculate drag limits
1630 int bottom_limit
= m_height
- m_splitterHeight
+ 1;
1631 int top_limit
= m_pPropGrid
->m_lineHeight
;
1633 if ( m_pToolbar
) top_limit
+= m_pToolbar
->GetSize().y
;
1636 if ( sy
>= top_limit
&& sy
< bottom_limit
)
1639 int change
= sy
- m_splitterY
;
1644 m_pPropGrid
->SetSize( m_width
, m_splitterY
- m_pPropGrid
->GetPosition().y
);
1645 UpdateDescriptionBox( m_splitterY
, m_width
, m_height
);
1647 m_extraHeight
-= change
;
1648 InvalidateBestSize();
1656 if ( y
>= m_splitterY
&& y
< (m_splitterY
+m_splitterHeight
+2) )
1658 SetCursor ( m_cursorSizeNS
);
1665 SetCursor ( wxNullCursor
);
1672 // -----------------------------------------------------------------------
1674 void wxPropertyGridManager::OnMouseClick( wxMouseEvent
&event
)
1678 // Click on splitter.
1679 if ( y
>= m_splitterY
&& y
< (m_splitterY
+m_splitterHeight
+2) )
1681 if ( m_dragStatus
== 0 )
1684 // Begin draggin the splitter
1691 m_dragOffset
= y
- m_splitterY
;
1697 // -----------------------------------------------------------------------
1699 void wxPropertyGridManager::OnMouseUp( wxMouseEvent
&event
)
1701 // No event type check - basicly calling this method should
1702 // just stop dragging.
1704 if ( m_dragStatus
>= 1 )
1707 // End Splitter Dragging
1712 // DO NOT ENABLE FOLLOWING LINE!
1713 // (it is only here as a reminder to not to do it)
1716 // This is necessary to return cursor
1719 // Set back the default cursor, if necessary
1720 if ( y
< m_splitterY
|| y
>= (m_splitterY
+m_splitterHeight
+2) )
1722 SetCursor ( wxNullCursor
);
1729 // -----------------------------------------------------------------------
1731 void wxPropertyGridManager::SetSplitterPosition( int pos
, int splitterColumn
)
1733 wxASSERT_MSG( GetPageCount(),
1734 wxT("SetSplitterPosition() has no effect until pages have been added") );
1737 for ( i
=0; i
<GetPageCount(); i
++ )
1739 wxPropertyGridPage
* page
= GetPage(i
);
1740 page
->DoSetSplitterPosition( pos
, splitterColumn
, false );
1741 page
->m_isSplitterPreSet
= true;
1745 // -----------------------------------------------------------------------
1746 // wxPGVIterator_Manager
1747 // -----------------------------------------------------------------------
1749 // Default returned by wxPropertyGridInterface::CreateVIterator().
1750 class wxPGVIteratorBase_Manager
: public wxPGVIteratorBase
1753 wxPGVIteratorBase_Manager( wxPropertyGridManager
* manager
, int flags
)
1754 : m_manager(manager
), m_flags(flags
), m_curPage(0)
1756 m_it
.Init(manager
->GetPage(0), flags
);
1758 virtual ~wxPGVIteratorBase_Manager() { }
1767 if ( m_curPage
< m_manager
->GetPageCount() )
1768 m_it
.Init( m_manager
->GetPage(m_curPage
), m_flags
);
1772 wxPropertyGridManager
* m_manager
;
1774 unsigned int m_curPage
;
1777 wxPGVIterator
wxPropertyGridManager::GetVIterator( int flags
) const
1779 return wxPGVIterator( new wxPGVIteratorBase_Manager( (wxPropertyGridManager
*)this, flags
) );
1782 #endif // wxUSE_PROPGRID