X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f4bc1aa27cb33f679d7e9c1518a7855bbc1fa471..64ea838d8f4d1853b7d850db93ee565e901d099a:/src/propgrid/manager.cpp diff --git a/src/propgrid/manager.cpp b/src/propgrid/manager.cpp index 5864d13b5e..abb8f27c8d 100644 --- a/src/propgrid/manager.cpp +++ b/src/propgrid/manager.cpp @@ -4,9 +4,9 @@ // Author: Jaakko Salli // Modified by: // Created: 2005-01-14 -// RCS-ID: $Id: +// RCS-ID: $Id$ // Copyright: (c) Jaakko Salli -// Licence: wxWindows license +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx/wx.h". @@ -31,17 +31,9 @@ #include "wx/pen.h" #include "wx/brush.h" #include "wx/cursor.h" - #include "wx/dialog.h" #include "wx/settings.h" - #include "wx/msgdlg.h" - #include "wx/choice.h" #include "wx/textctrl.h" - #include "wx/dirdlg.h" - #include "wx/combobox.h" - #include "wx/layout.h" #include "wx/sizer.h" - #include "wx/textdlg.h" - #include "wx/filedlg.h" #include "wx/statusbr.h" #include "wx/intl.h" #endif @@ -49,9 +41,9 @@ // This define is necessary to prevent macro clearing #define __wxPG_SOURCE_FILE__ -#include +#include "wx/propgrid/propgrid.h" -#include +#include "wx/propgrid/manager.h" #define wxPG_MAN_ALTERNATE_BASE_ID 11249 // Needed for wxID_ANY madnesss @@ -80,11 +72,11 @@ // wxPropertyGridManager // ----------------------------------------------------------------------- -const wxChar *wxPropertyGridManagerNameStr = wxT("wxPropertyGridManager"); +const char wxPropertyGridManagerNameStr[] = "wxPropertyGridManager"; // Categoric Mode Icon -static const char* gs_xpm_catmode[] = { +static const char* const gs_xpm_catmode[] = { "16 16 5 1", ". c none", "B c black", @@ -110,7 +102,7 @@ static const char* gs_xpm_catmode[] = { }; // Alphabetic Mode Icon -static const char* gs_xpm_noncatmode[] = { +static const char* const gs_xpm_noncatmode[] = { "16 16 5 1", ". c none", "B c black", @@ -136,7 +128,7 @@ static const char* gs_xpm_noncatmode[] = { }; // Default Page Icon. -static const char* gs_xpm_defpage[] = { +static const char* const gs_xpm_defpage[] = { "16 16 5 1", ". c none", "B c black", @@ -161,8 +153,6 @@ static const char* gs_xpm_defpage[] = { "................" }; -#define GETPAGESTATE(page) ((wxPropertyGridPage*)m_arrPages.Item(page))->GetStatePtr() - // ----------------------------------------------------------------------- // wxPropertyGridPage // ----------------------------------------------------------------------- @@ -217,14 +207,199 @@ void wxPropertyGridPage::SetSplitterPosition( int splitterPos, int col ) DoSetSplitterPosition(splitterPos, col, false); } -void wxPropertyGridPage::DoSetSplitterPosition( int pos, int splitterColumn, bool allPages ) +void wxPropertyGridPage::DoSetSplitterPosition( int pos, + int splitterColumn, + int flags ) { - if ( allPages && m_manager->GetPageCount() ) + if ( (flags & wxPG_SPLITTER_ALL_PAGES) && m_manager->GetPageCount() ) m_manager->SetSplitterPosition( pos, splitterColumn ); else - DoSetSplitterPositionThisPage( pos, splitterColumn ); + wxPropertyGridPageState::DoSetSplitterPosition( pos, + splitterColumn, + flags ); } +// ----------------------------------------------------------------------- +// wxPGHeaderCtrl +// ----------------------------------------------------------------------- + +#if wxUSE_HEADERCTRL + +class wxPGHeaderCtrl : public wxHeaderCtrl +{ +public: + wxPGHeaderCtrl(wxPropertyGridManager* manager) : + wxHeaderCtrl() + { + m_manager = manager; + EnsureColumnCount(2); + + // Seed titles with defaults + m_columns[0]->SetTitle(_("Property")); + m_columns[1]->SetTitle(_("Value")); + } + + virtual ~wxPGHeaderCtrl() + { + for (unsigned int i=0; iGetColumnWidth(idx); + int colMinWidth = page->GetColumnMinWidth(idx); + if ( idx == 0 ) + { + wxPropertyGrid* pg = m_manager->GetGrid(); + int margin = pg->GetMarginWidth(); + + // Compensate for the internal border + margin += (pg->GetSize().x - pg->GetClientSize().x) / 2; + + colWidth += margin; + colMinWidth += margin; + } + *pMinWidth = colMinWidth; + return colWidth; + } + + void OnPageChanged(const wxPropertyGridPage* page) + { + m_page = page; + OnPageUpdated(); + } + + void OnPageUpdated() + { + // Get column info from the page + const wxPropertyGridPage* page = m_page; + unsigned int colCount = page->GetColumnCount(); + EnsureColumnCount(colCount); + + for ( unsigned int i=0; iSetWidth(colWidth); + colInfo->SetMinWidth(colMinWidth); + } + + SetColumnCount(colCount); + } + + void OnColumWidthsChanged() + { + const wxPropertyGridPage* page = m_page; + unsigned int colCount = page->GetColumnCount(); + + for ( unsigned int i=0; iSetWidth(colWidth); + colInfo->SetMinWidth(colMinWidth); + UpdateColumn(i); + } + } + + virtual const wxHeaderColumn& GetColumn(unsigned int idx) const + { + return *m_columns[idx]; + } + + void SetColumnTitle(unsigned int idx, const wxString& title) + { + EnsureColumnCount(idx+1); + m_columns[idx]->SetTitle(title); + } + +private: + void EnsureColumnCount(unsigned int count) + { + while ( m_columns.size() < count ) + { + wxHeaderColumnSimple* colInfo = new wxHeaderColumnSimple(""); + m_columns.push_back(colInfo); + } + } + + void OnSetColumnWidth(int col, int colWidth) + { + wxPropertyGrid* pg = m_manager->GetGrid(); + + // Compensate for the internal border + int x = -((pg->GetSize().x - pg->GetClientSize().x) / 2); + + for ( int i=0; iGetWidth(); + + x += colWidth; + + pg->DoSetSplitterPosition(x, col, + wxPG_SPLITTER_REFRESH | + wxPG_SPLITTER_FROM_EVENT); + } + + virtual bool ProcessEvent( wxEvent& event ) + { + if ( event.IsKindOf(wxCLASSINFO(wxHeaderCtrlEvent)) ) + { + wxHeaderCtrlEvent& hcEvent = + static_cast(event); + + wxPropertyGrid* pg = m_manager->GetGrid(); + int col = hcEvent.GetColumn(); + int evtType = event.GetEventType(); + + if ( evtType == wxEVT_COMMAND_HEADER_RESIZING ) + { + int colWidth = hcEvent.GetWidth(); + + OnSetColumnWidth(col, colWidth); + + pg->SendEvent(wxEVT_PG_COL_DRAGGING, + NULL, NULL, 0, + (unsigned int)col); + + return true; + } + else if ( evtType == wxEVT_COMMAND_HEADER_BEGIN_RESIZE ) + { + // Never allow column resize if layout is static + if ( m_manager->HasFlag(wxPG_STATIC_SPLITTER) ) + hcEvent.Veto(); + // Allow application to veto dragging + else if ( pg->SendEvent(wxEVT_PG_COL_BEGIN_DRAG, + NULL, NULL, 0, + (unsigned int)col) ) + hcEvent.Veto(); + + return true; + } + else if ( evtType == wxEVT_COMMAND_HEADER_END_RESIZE ) + { + pg->SendEvent(wxEVT_PG_COL_END_DRAG, + NULL, NULL, 0, + (unsigned int)col); + + return true; + } + } + + return wxHeaderCtrl::ProcessEvent(event); + } + + wxPropertyGridManager* m_manager; + const wxPropertyGridPage* m_page; + wxVector m_columns; +}; + +#endif // wxUSE_HEADERCTRL + // ----------------------------------------------------------------------- // wxPropertyGridManager // ----------------------------------------------------------------------- @@ -236,12 +411,6 @@ void wxPropertyGridPage::DoSetSplitterPosition( int pos, int splitterColumn, boo IMPLEMENT_CLASS(wxPropertyGridManager, wxPanel) -#define ID_ADVTOOLBAR_OFFSET 1 -#define ID_ADVHELPCAPTION_OFFSET 2 -#define ID_ADVHELPCONTENT_OFFSET 3 -#define ID_ADVBUTTON_OFFSET 4 -#define ID_ADVTBITEMSBASE_OFFSET 5 // Must be last. - // ----------------------------------------------------------------------- BEGIN_EVENT_TABLE(wxPropertyGridManager, wxPanel) @@ -269,7 +438,7 @@ wxPropertyGridManager::wxPropertyGridManager( wxWindow *parent, const wxPoint& pos, const wxSize& size, long style, - const wxChar* name ) + const wxString& name ) : wxPanel() { Init1(); @@ -283,14 +452,21 @@ bool wxPropertyGridManager::Create( wxWindow *parent, const wxPoint& pos, const wxSize& size, long style, - const wxChar* name ) + const wxString& name ) { + if ( !m_pPropGrid ) + m_pPropGrid = CreatePropertyGrid(); bool res = wxPanel::Create( parent, id, pos, size, (style&0xFFFF0000)|wxWANTS_CHARS, name ); Init2(style); + // FIXME: this changes call ordering so wxPropertyGrid is created + // immediately, before SetExtraStyle has a chance to be called. However, + // without it, we may get assertions if size is wxDefaultSize. + //SetInitialSize(size); + return res; } @@ -302,16 +478,19 @@ bool wxPropertyGridManager::Create( wxWindow *parent, void wxPropertyGridManager::Init1() { - //m_pPropGrid = (wxPropertyGrid*) NULL; - m_pPropGrid = CreatePropertyGrid(); + m_pPropGrid = NULL; #if wxUSE_TOOLBAR - m_pToolbar = (wxToolBar*) NULL; + m_pToolbar = NULL; +#endif +#if wxUSE_HEADERCTRL + m_pHeaderCtrl = NULL; + m_showHeader = false; #endif - m_pTxtHelpCaption = (wxStaticText*) NULL; - m_pTxtHelpContent = (wxStaticText*) NULL; + m_pTxtHelpCaption = NULL; + m_pTxtHelpContent = NULL; - m_emptyPage = (wxPropertyGridPage*) NULL; + m_emptyPage = NULL; m_selPage = -1; @@ -323,6 +502,9 @@ void wxPropertyGridManager::Init1() m_nextDescBoxSize = -1; + m_categorizedModeToolId = -1; + m_alphabeticModeToolId = -1; + m_extraHeight = 0; m_dragStatus = 0; m_onSplitter = 0; @@ -332,15 +514,9 @@ void wxPropertyGridManager::Init1() // ----------------------------------------------------------------------- // These flags are always used in wxPropertyGrid integrated in wxPropertyGridManager. -#ifndef __WXMAC__ - #define wxPG_MAN_PROPGRID_FORCED_FLAGS (wxSIMPLE_BORDER| \ +#define wxPG_MAN_PROPGRID_FORCED_FLAGS ( wxBORDER_THEME | \ wxNO_FULL_REPAINT_ON_RESIZE| \ wxCLIP_CHILDREN) -#else - #define wxPG_MAN_PROPGRID_FORCED_FLAGS (wxNO_BORDER| \ - wxNO_FULL_REPAINT_ON_RESIZE| \ - wxCLIP_CHILDREN) -#endif // Which flags can be passed to underlying wxPropertyGrid. #define wxPG_MAN_PASS_FLAGS_MASK (0xFFF0|wxTAB_TRAVERSAL) @@ -368,7 +544,7 @@ void wxPropertyGridManager::Init2( int style ) pd->m_manager = this; wxPropertyGridPageState* state = pd->GetStatePtr(); state->m_pPropGrid = m_pPropGrid; - m_arrPages.Add( (void*)pd ); + m_arrPages.push_back( pd ); m_pPropGrid->m_pState = state; wxWindowID baseId = GetId(); @@ -376,17 +552,28 @@ void wxPropertyGridManager::Init2( int style ) if ( baseId < 0 ) baseId = wxPG_MAN_ALTERNATE_BASE_ID; - m_baseId = baseId; - #ifdef __WXMAC__ // Smaller controls on Mac SetWindowVariant(wxWINDOW_VARIANT_SMALL); -#endif +#endif + + long propGridFlags = (m_windowStyle&wxPG_MAN_PASS_FLAGS_MASK) + |wxPG_MAN_PROPGRID_FORCED_FLAGS; + + propGridFlags &= ~wxBORDER_MASK; + + if ((style & wxPG_NO_INTERNAL_BORDER) == 0) + { + propGridFlags |= wxBORDER_THEME; + } + else + { + propGridFlags |= wxBORDER_NONE; + wxWindow::SetExtraStyle(wxPG_EX_TOOLBAR_SEPARATOR); + } // Create propertygrid. - m_pPropGrid->Create(this,baseId,wxPoint(0,0),csz, - (m_windowStyle&wxPG_MAN_PASS_FLAGS_MASK) - |wxPG_MAN_PROPGRID_FORCED_FLAGS); + m_pPropGrid->Create(this,baseId,wxPoint(0,0),csz, propGridFlags); m_pPropGrid->m_eventObject = this; @@ -398,20 +585,16 @@ void wxPropertyGridManager::Init2( int style ) m_pPropGrid->SetExtraStyle(wxPG_EX_INIT_NOCAT); - m_nextTbInd = baseId+ID_ADVTBITEMSBASE_OFFSET + 2; - - // Connect to property grid onselect event. // NB: Even if wxID_ANY is used, this doesn't connect properly in wxPython // (see wxPropertyGridManager::ProcessEvent). - Connect(m_pPropGrid->GetId()/*wxID_ANY*/, - wxEVT_PG_SELECTED, - wxPropertyGridEventHandler(wxPropertyGridManager::OnPropertyGridSelect) ); + Connect(m_pPropGrid->GetId(), + wxEVT_PG_SELECTED, + wxPropertyGridEventHandler(wxPropertyGridManager::OnPropertyGridSelect)); - // Connect to toolbar button events. - Connect(baseId+ID_ADVTBITEMSBASE_OFFSET,baseId+ID_ADVTBITEMSBASE_OFFSET+50, - wxEVT_COMMAND_TOOL_CLICKED, - wxCommandEventHandler(wxPropertyGridManager::OnToolbarClick) ); + Connect(m_pPropGrid->GetId(), + wxEVT_PG_COL_DRAGGING, + wxPropertyGridEventHandler(wxPropertyGridManager::OnPGColDrag)); // Optional initial controls. m_width = -12345; @@ -426,13 +609,13 @@ wxPropertyGridManager::~wxPropertyGridManager() { END_MOUSE_CAPTURE - m_pPropGrid->DoSelectProperty(NULL); - m_pPropGrid->m_pState = NULL; + //m_pPropGrid->ClearSelection(); + wxDELETE(m_pPropGrid); size_t i; - for ( i=0; iSetWindowStyleFlag( (m_pPropGrid->GetWindowStyleFlag()&~(wxPG_MAN_PASS_FLAGS_MASK)) | (style&wxPG_MAN_PASS_FLAGS_MASK) ); + + // Need to re-position windows? + if ( (oldWindowStyle & (wxPG_TOOLBAR|wxPG_DESCRIPTION)) != + (style & (wxPG_TOOLBAR|wxPG_DESCRIPTION)) ) + { + RecreateControls(); + } +} + +// ----------------------------------------------------------------------- + +bool wxPropertyGridManager::Reparent( wxWindowBase *newParent ) +{ + if ( m_pPropGrid ) + m_pPropGrid->OnTLPChanging((wxWindow*)newParent); + + bool res = wxPanel::Reparent(newParent); + + return res; } // ----------------------------------------------------------------------- @@ -535,7 +739,7 @@ bool wxPropertyGridManager::DoSelectPage( int index ) if ( m_selPage == index ) return true; - if ( m_pPropGrid->m_selected ) + if ( m_pPropGrid->GetSelection() ) { if ( !m_pPropGrid->ClearSelection() ) return false; @@ -552,7 +756,7 @@ bool wxPropertyGridManager::DoSelectPage( int index ) if ( index >= 0 ) { - nextPage = (wxPropertyGridPage*)m_arrPages.Item(index); + nextPage = m_arrPages[index]; nextPage->OnShow(); } @@ -579,12 +783,17 @@ bool wxPropertyGridManager::DoSelectPage( int index ) if ( m_pToolbar ) { if ( index >= 0 ) - m_pToolbar->ToggleTool( nextPage->m_id, true ); + m_pToolbar->ToggleTool( nextPage->m_toolId, true ); else - m_pToolbar->ToggleTool( prevPage->m_id, false ); + m_pToolbar->ToggleTool( prevPage->m_toolId, false ); } #endif +#if wxUSE_HEADERCTRL + if ( m_showHeader ) + m_pHeaderCtrl->OnPageChanged(nextPage); +#endif + return true; } @@ -603,7 +812,7 @@ int wxPropertyGridManager::GetPageByName( const wxString& name ) const size_t i; for ( i=0; im_label == name ) + if ( m_arrPages[i]->m_label == name ) return i; } return wxNOT_FOUND; @@ -618,7 +827,7 @@ int wxPropertyGridManager::GetPageByState( const wxPropertyGridPageState* pState size_t i; for ( i=0; iGetStatePtr() ) + if ( pState == m_arrPages[i]->GetStatePtr() ) return i; } @@ -630,7 +839,7 @@ int wxPropertyGridManager::GetPageByState( const wxPropertyGridPageState* pState const wxString& wxPropertyGridManager::GetPageName( int index ) const { wxASSERT( index >= 0 && index < (int)GetPageCount() ); - return ((wxPropertyGridPage*)m_arrPages.Item(index))->m_label; + return m_arrPages[index]->m_label; } // ----------------------------------------------------------------------- @@ -644,22 +853,21 @@ wxPropertyGridPageState* wxPropertyGridManager::GetPageState( int page ) const if ( page == -1 ) return m_pState; - return GETPAGESTATE(page); + return m_arrPages[page]; } // ----------------------------------------------------------------------- void wxPropertyGridManager::Clear() { + m_pPropGrid->ClearSelection(false); + m_pPropGrid->Freeze(); int i; for ( i=(int)GetPageCount()-1; i>=0; i-- ) RemovePage(i); - // Reset toolbar ids - m_nextTbInd = m_baseId+ID_ADVTBITEMSBASE_OFFSET + 2; - m_pPropGrid->Thaw(); } @@ -672,7 +880,7 @@ void wxPropertyGridManager::ClearPage( int page ) if ( page >= 0 && page < (int)GetPageCount() ) { - wxPropertyGridPageState* state = GETPAGESTATE(page); + wxPropertyGridPageState* state = m_arrPages[page]; if ( state == m_pPropGrid->GetState() ) m_pPropGrid->Clear(); @@ -700,39 +908,33 @@ void wxPropertyGridManager::SetColumnCount( int colCount, int page ) GetPageState(page)->SetColumnCount( colCount ); GetGrid()->Refresh(); -} -// ----------------------------------------------------------------------- - -void wxPropertyGridManager::SetPropertyAttributeAll( const wxString& attrName, wxVariant value ) -{ - size_t i; - for ( i=0; iGetStatePtr()->m_properties, attrName, value, wxPG_RECURSE); - } +#if wxUSE_HEADERCTRL + if ( m_showHeader ) + m_pHeaderCtrl->OnPageUpdated(); +#endif } - // ----------------------------------------------------------------------- size_t wxPropertyGridManager::GetPageCount() const { - if ( !(m_iFlags & wxPG_MAN_FL_PAGE_INSERTED) ) - return 0; + if ( !(m_iFlags & wxPG_MAN_FL_PAGE_INSERTED) ) + return 0; - return m_arrPages.GetCount(); + return m_arrPages.size(); } // ----------------------------------------------------------------------- -int wxPropertyGridManager::InsertPage( int index, const wxString& label, - const wxBitmap& bmp, wxPropertyGridPage* pageObj ) +wxPropertyGridPage* wxPropertyGridManager::InsertPage( int index, + const wxString& label, + const wxBitmap& bmp, + wxPropertyGridPage* pageObj ) { if ( index < 0 ) index = GetPageCount(); - wxCHECK_MSG( (size_t)index == GetPageCount(), -1, + wxCHECK_MSG( (size_t)index == GetPageCount(), NULL, wxT("wxPropertyGridManager currently only supports appending pages (due to wxToolBar limitation).")); bool needInit = true; @@ -784,17 +986,20 @@ int wxPropertyGridManager::InsertPage( int index, const wxString& label, state->InitNonCatMode(); } - if ( label.length() ) + if ( !label.empty() ) { wxASSERT_MSG( !pageObj->m_label.length(), wxT("If page label is given in constructor, empty label must be given in AddPage")); pageObj->m_label = label; } - pageObj->m_id = m_nextTbInd; + pageObj->m_toolId = -1; + + if ( !HasFlag(wxPG_SPLITTER_AUTO_CENTER) ) + pageObj->m_dontCenterSplitter = true; if ( isPageInserted ) - m_arrPages.Add( (void*)pageObj ); + m_arrPages.push_back( pageObj ); #if wxUSE_TOOLBAR if ( m_windowStyle & wxPG_TOOLBAR ) @@ -811,14 +1016,23 @@ int wxPropertyGridManager::InsertPage( int index, const wxString& label, m_pToolbar->GetToolsCount() < 3 ) m_pToolbar->AddSeparator(); + wxToolBarToolBase* tool; + if ( &bmp != &wxNullBitmap ) - m_pToolbar->AddTool(m_nextTbInd,label,bmp,label,wxITEM_RADIO); - //m_pToolbar->InsertTool(index+3,m_nextTbInd,bmp); + tool = m_pToolbar->AddTool(wxID_ANY, label, bmp, + label, wxITEM_RADIO); else - m_pToolbar->AddTool(m_nextTbInd,label,wxBitmap( (const char**)gs_xpm_defpage ), - label,wxITEM_RADIO); + tool = m_pToolbar->AddTool(wxID_ANY, label, + wxBitmap(gs_xpm_defpage), + label, wxITEM_RADIO); + + pageObj->m_toolId = tool->GetId(); - m_nextTbInd++; + // Connect to toolbar button events. + Connect(pageObj->m_toolId, + wxEVT_COMMAND_TOOL_CLICKED, + wxCommandEventHandler( + wxPropertyGridManager::OnToolbarClick)); m_pToolbar->Realize(); } @@ -847,7 +1061,7 @@ int wxPropertyGridManager::InsertPage( int index, const wxString& label, wxASSERT( pageObj->GetGrid() ); - return index; + return pageObj; } // ----------------------------------------------------------------------- @@ -857,7 +1071,7 @@ bool wxPropertyGridManager::IsAnyModified() const size_t i; for ( i=0; iGetStatePtr()->m_anyModified ) + if ( m_arrPages[i]->GetStatePtr()->m_anyModified ) return true; } return false; @@ -867,19 +1081,57 @@ bool wxPropertyGridManager::IsAnyModified() const bool wxPropertyGridManager::IsPageModified( size_t index ) const { - if ( ((wxPropertyGridPage*)m_arrPages.Item(index))->GetStatePtr()->m_anyModified ) + if ( m_arrPages[index]->GetStatePtr()->m_anyModified ) return true; return false; } // ----------------------------------------------------------------------- +#if wxUSE_HEADERCTRL +void wxPropertyGridManager::ShowHeader(bool show) +{ + if ( show != m_showHeader) + { + m_showHeader = show; + RecreateControls(); + } +} +#endif + +// ----------------------------------------------------------------------- + +#if wxUSE_HEADERCTRL +void wxPropertyGridManager::SetColumnTitle( int idx, const wxString& title ) +{ + if ( !m_pHeaderCtrl ) + ShowHeader(); + + m_pHeaderCtrl->SetColumnTitle(idx, title); +} +#endif + +// ----------------------------------------------------------------------- + +bool wxPropertyGridManager::IsPropertySelected( wxPGPropArg id ) const +{ + wxPG_PROP_ARG_CALL_PROLOG_RETVAL(false) + for ( unsigned int i=0; iDoIsPropertySelected(p) ) + return true; + } + return false; +} + +// ----------------------------------------------------------------------- + wxPGProperty* wxPropertyGridManager::GetPageRoot( int index ) const { wxASSERT( index >= 0 ); - wxASSERT( index < (int)m_arrPages.GetCount() ); + wxASSERT( index < (int)m_arrPages.size() ); - return ((wxPropertyGridPage*)m_arrPages.Item(index))->GetStatePtr()->m_properties; + return m_arrPages[index]->GetStatePtr()->m_properties; } // ----------------------------------------------------------------------- @@ -890,9 +1142,9 @@ bool wxPropertyGridManager::RemovePage( int page ) false, wxT("invalid page index") ); - wxPropertyGridPage* pd = (wxPropertyGridPage*)m_arrPages.Item(page); + wxPropertyGridPage* pd = m_arrPages[page]; - if ( m_arrPages.GetCount() == 1 ) + if ( m_arrPages.size() == 1 ) { // Last page: do not remove page entry m_pPropGrid->Clear(); @@ -900,6 +1152,7 @@ bool wxPropertyGridManager::RemovePage( int page ) m_iFlags &= ~wxPG_MAN_FL_PAGE_INSERTED; pd->m_label.clear(); } + // Change selection if current is page else if ( page == m_selPage ) { @@ -932,9 +1185,9 @@ bool wxPropertyGridManager::RemovePage( int page ) } #endif - if ( m_arrPages.GetCount() > 1 ) + if ( m_arrPages.size() > 1 ) { - m_arrPages.RemoveAt(page); + m_arrPages.erase(m_arrPages.begin() + page); delete pd; } @@ -985,44 +1238,33 @@ bool wxPropertyGridManager::ProcessEvent( wxEvent& event ) // ----------------------------------------------------------------------- -void wxPropertyGridManager::RepaintSplitter( wxDC& dc, int new_splittery, int new_width, - int new_height, bool desc_too ) +void wxPropertyGridManager::RepaintDescBoxDecorations( wxDC& dc, + int newSplitterY, + int newWidth, + int newHeight ) { - int use_hei = new_height; - // Draw background wxColour bgcol = GetBackgroundColour(); - dc.SetBrush( bgcol ); - dc.SetPen( bgcol ); - int rect_hei = use_hei-new_splittery; - if ( !desc_too ) - rect_hei = m_splitterHeight; - dc.DrawRectangle(0,new_splittery,new_width,rect_hei); - dc.SetPen ( wxSystemSettings::GetColour ( wxSYS_COLOUR_3DDKSHADOW ) ); - int splitter_bottom = new_splittery+m_splitterHeight - 1; - int box_height = use_hei-splitter_bottom; - if ( box_height > 1 ) - dc.DrawRectangle(0,splitter_bottom,new_width,box_height); + dc.SetBrush(bgcol); + dc.SetPen(bgcol); + int rectHeight = m_splitterHeight; + dc.DrawRectangle(0, newSplitterY, newWidth, rectHeight); + dc.SetPen( wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW) ); + int splitterBottom = newSplitterY + m_splitterHeight - 1; + int boxHeight = newHeight - splitterBottom; + if ( boxHeight > 1 ) + dc.DrawRectangle(0, splitterBottom, newWidth, boxHeight); else - dc.DrawLine(0,splitter_bottom,new_width,splitter_bottom); + dc.DrawLine(0, splitterBottom, newWidth, splitterBottom); } // ----------------------------------------------------------------------- -void wxPropertyGridManager::RefreshHelpBox( int new_splittery, int new_width, int new_height ) +void wxPropertyGridManager::UpdateDescriptionBox( int new_splittery, int new_width, int new_height ) { - //if ( new_splittery == m_splitterY && new_width == m_width ) - // return; - int use_hei = new_height; use_hei--; - //wxRendererNative::Get().DrawSplitterSash(this,dc, - //wxSize(width,m_splitterHeight),new_splittery,wxHORIZONTAL); - - //wxRendererNative::Get().DrawSplitterBorder(this,dc, - // wxRect(0,new_splittery,new_width,m_splitterHeight)); - // Fix help control positions. int cap_hei = m_pPropGrid->m_fontHeight; int cap_y = new_splittery+m_splitterHeight+5; @@ -1055,8 +1297,8 @@ void wxPropertyGridManager::RefreshHelpBox( int new_splittery, int new_width, in } } - wxClientDC dc(this); - RepaintSplitter( dc, new_splittery, new_width, new_height, true ); + wxRect r(0, new_splittery, new_width, new_height-new_splittery); + RefreshRect(r); m_splitterY = new_splittery; @@ -1074,25 +1316,20 @@ void wxPropertyGridManager::RecalculatePositions( int width, int height ) #if wxUSE_TOOLBAR if ( m_pToolbar ) { - int tbHeight; + m_pToolbar->SetSize(0, 0, width, -1); + propgridY += m_pToolbar->GetSize().y; - #if ( wxMINOR_VERSION < 6 || (wxMINOR_VERSION == 6 && wxRELEASE_NUMBER < 2) ) - tbHeight = -1; - #else - // In wxWidgets 2.6.2+, Toolbar default height may be broken - #if defined(__WXMSW__) - tbHeight = 24; - #elif defined(__WXGTK__) - tbHeight = -1; // 22; - #elif defined(__WXMAC__) - tbHeight = 22; - #else - tbHeight = 22; - #endif - #endif + if (GetExtraStyle() & wxPG_EX_TOOLBAR_SEPARATOR) + propgridY += 1; + } +#endif - m_pToolbar->SetSize(0,0,width,tbHeight); - propgridY += m_pToolbar->GetSize().y; + // Header comes after the tool bar +#if wxUSE_HEADERCTRL + if ( m_showHeader ) + { + m_pHeaderCtrl->SetSize(0, propgridY, width, -1); + propgridY += m_pHeaderCtrl->GetSize().y; } #endif @@ -1125,12 +1362,14 @@ void wxPropertyGridManager::RecalculatePositions( int width, int height ) propgridBottomY = new_splittery; - RefreshHelpBox( new_splittery, width, height ); + UpdateDescriptionBox( new_splittery, width, height ); } if ( m_iFlags & wxPG_FL_INITIALIZED ) { int pgh = propgridBottomY - propgridY; + if ( pgh < 0 ) + pgh = 0; m_pPropGrid->SetSize( 0, propgridY, width, pgh ); m_extraHeight = height - pgh; @@ -1146,9 +1385,12 @@ void wxPropertyGridManager::SetDescBoxHeight( int ht, bool refresh ) { if ( m_windowStyle & wxPG_DESCRIPTION ) { - m_nextDescBoxSize = ht; - if ( refresh ) - RecalculatePositions(m_width, m_height); + if ( ht != GetDescBoxHeight() ) + { + m_nextDescBoxSize = ht; + if ( refresh ) + RecalculatePositions(m_width, m_height); + } } } @@ -1156,7 +1398,7 @@ void wxPropertyGridManager::SetDescBoxHeight( int ht, bool refresh ) int wxPropertyGridManager::GetDescBoxHeight() const { - return GetClientSize().y - m_splitterY; + return GetClientSize().y - m_splitterY - m_splitterHeight; } // ----------------------------------------------------------------------- @@ -1168,11 +1410,21 @@ void wxPropertyGridManager::OnPaint( wxPaintEvent& WXUNUSED(event) ) // Update everything inside the box wxRect r = GetUpdateRegion().GetBox(); - // Repaint splitter? - int r_bottom = r.y + r.height; - int splitter_bottom = m_splitterY + m_splitterHeight; - if ( r.y < splitter_bottom && r_bottom >= m_splitterY ) - RepaintSplitter( dc, m_splitterY, m_width, m_height, false ); + if (GetExtraStyle() & wxPG_EX_TOOLBAR_SEPARATOR) + { + if (m_pToolbar && m_pPropGrid) + { + wxPen marginPen(m_pPropGrid->GetMarginColour()); + dc.SetPen(marginPen); + + int y = m_pPropGrid->GetPosition().y-1; + dc.DrawLine(0, y, GetClientSize().x, y); + } + } + + // Repaint splitter and any other description box decorations + if ( (r.y + r.height) >= m_splitterY && m_splitterY != -1) + RepaintDescBoxDecorations( dc, m_splitterY, m_width, m_height ); } // ----------------------------------------------------------------------- @@ -1202,20 +1454,21 @@ void wxPropertyGridManager::RecreateControls() if ( was_shown ) Show ( false ); - wxWindowID baseId = m_pPropGrid->GetId(); - if ( baseId < 0 ) - baseId = wxPG_MAN_ALTERNATE_BASE_ID; - #if wxUSE_TOOLBAR if ( m_windowStyle & wxPG_TOOLBAR ) { // Has toolbar. if ( !m_pToolbar ) { - m_pToolbar = new wxToolBar(this,baseId+ID_ADVTOOLBAR_OFFSET, - wxDefaultPosition,wxDefaultSize, - ((GetExtraStyle()&wxPG_EX_NO_FLAT_TOOLBAR)?0:wxTB_FLAT) - /*| wxTB_HORIZONTAL | wxNO_BORDER*/ ); + long toolBarFlags = ((GetExtraStyle()&wxPG_EX_NO_FLAT_TOOLBAR)?0:wxTB_FLAT); + if (GetExtraStyle() & wxPG_EX_NO_TOOLBAR_DIVIDER) + toolBarFlags |= wxTB_NODIVIDER; + + m_pToolbar = new wxToolBar(this, wxID_ANY, + wxDefaultPosition, + wxDefaultSize, + toolBarFlags); + m_pToolbar->SetToolBitmapSize(wxSize(16, 15)); #if defined(__WXMSW__) // Eliminate toolbar flicker on XP @@ -1240,32 +1493,62 @@ void wxPropertyGridManager::RecreateControls() { wxString desc1(_("Categorized Mode")); wxString desc2(_("Alphabetic Mode")); - m_pToolbar->AddTool(baseId+ID_ADVTBITEMSBASE_OFFSET+0, - desc1,wxBitmap ( (const char**)gs_xpm_catmode ), - desc1,wxITEM_RADIO); - m_pToolbar->AddTool(baseId+ID_ADVTBITEMSBASE_OFFSET+1, - desc2,wxBitmap ( (const char**)gs_xpm_noncatmode ), - desc2,wxITEM_RADIO); + + wxToolBarToolBase* tool; + + tool = m_pToolbar->AddTool(wxID_ANY, + desc1, + wxBitmap(gs_xpm_catmode), + desc1, + wxITEM_RADIO); + m_categorizedModeToolId = tool->GetId(); + + tool = m_pToolbar->AddTool(wxID_ANY, + desc2, + wxBitmap(gs_xpm_noncatmode), + desc2, + wxITEM_RADIO); + m_alphabeticModeToolId = tool->GetId(); + m_pToolbar->Realize(); + + Connect(m_categorizedModeToolId, + wxEVT_COMMAND_TOOL_CLICKED, + wxCommandEventHandler( + wxPropertyGridManager::OnToolbarClick)); + Connect(m_alphabeticModeToolId, + wxEVT_COMMAND_TOOL_CLICKED, + wxCommandEventHandler( + wxPropertyGridManager::OnToolbarClick)); + } + else + { + m_categorizedModeToolId = -1; + m_alphabeticModeToolId = -1; } } - if ( (GetExtraStyle()&wxPG_EX_MODE_BUTTONS) ) + if ( (GetExtraStyle() & wxPG_EX_MODE_BUTTONS) ) { // Toggle correct mode button. // TODO: This doesn't work in wxMSW (when changing, // both items will get toggled). - int toggle_but_on_ind = ID_ADVTBITEMSBASE_OFFSET+0; - int toggle_but_off_ind = ID_ADVTBITEMSBASE_OFFSET+1; + int toggle_but_on_ind; + int toggle_but_off_ind; if ( m_pPropGrid->m_pState->IsInNonCatMode() ) { - toggle_but_on_ind++; - toggle_but_off_ind--; + toggle_but_on_ind = m_alphabeticModeToolId; + toggle_but_off_ind = m_categorizedModeToolId; + } + else + { + toggle_but_on_ind = m_categorizedModeToolId; + toggle_but_off_ind = m_alphabeticModeToolId; } - m_pToolbar->ToggleTool(baseId+toggle_but_on_ind,true); - m_pToolbar->ToggleTool(baseId+toggle_but_off_ind,false); + m_pToolbar->ToggleTool(toggle_but_on_ind, true); + m_pToolbar->ToggleTool(toggle_but_off_ind, false); } } @@ -1274,7 +1557,32 @@ void wxPropertyGridManager::RecreateControls() // No toolbar. if ( m_pToolbar ) m_pToolbar->Destroy(); - m_pToolbar = (wxToolBar*) NULL; + m_pToolbar = NULL; + } +#endif + +#if wxUSE_HEADERCTRL + if ( m_showHeader ) + { + wxPGHeaderCtrl* hc; + + if ( !m_pHeaderCtrl ) + { + hc = new wxPGHeaderCtrl(this); + hc->Create(this, wxID_ANY); + m_pHeaderCtrl = hc; + } + else + { + m_pHeaderCtrl->Show(); + } + + m_pHeaderCtrl->OnPageChanged(GetCurrentPage()); + } + else + { + if ( m_pHeaderCtrl ) + m_pHeaderCtrl->Hide(); } #endif @@ -1285,16 +1593,27 @@ void wxPropertyGridManager::RecreateControls() if ( !m_pTxtHelpCaption ) { - m_pTxtHelpCaption = new wxStaticText (this,baseId+ID_ADVHELPCAPTION_OFFSET,wxEmptyString); + m_pTxtHelpCaption = new wxStaticText(this, + wxID_ANY, + wxT(""), + wxDefaultPosition, + wxDefaultSize, + wxALIGN_LEFT|wxST_NO_AUTORESIZE); m_pTxtHelpCaption->SetFont( m_pPropGrid->m_captionFont ); - m_pTxtHelpCaption->SetCursor ( *wxSTANDARD_CURSOR ); + m_pTxtHelpCaption->SetCursor( *wxSTANDARD_CURSOR ); } if ( !m_pTxtHelpContent ) { - m_pTxtHelpContent = new wxStaticText (this,baseId+ID_ADVHELPCONTENT_OFFSET, - wxEmptyString,wxDefaultPosition,wxDefaultSize,wxALIGN_LEFT|wxST_NO_AUTORESIZE); - m_pTxtHelpContent->SetCursor ( *wxSTANDARD_CURSOR ); + m_pTxtHelpContent = new wxStaticText(this, + wxID_ANY, + wxT(""), + wxDefaultPosition, + wxDefaultSize, + wxALIGN_LEFT|wxST_NO_AUTORESIZE); + m_pTxtHelpContent->SetCursor( *wxSTANDARD_CURSOR ); } + + SetDescribedProperty(GetSelection()); } else { @@ -1304,12 +1623,12 @@ void wxPropertyGridManager::RecreateControls() if ( m_pTxtHelpCaption ) m_pTxtHelpCaption->Destroy(); - m_pTxtHelpCaption = (wxStaticText*) NULL; + m_pTxtHelpCaption = NULL; if ( m_pTxtHelpContent ) m_pTxtHelpContent->Destroy(); - m_pTxtHelpContent = (wxStaticText*) NULL; + m_pTxtHelpContent = NULL; } int width, height; @@ -1329,7 +1648,7 @@ wxPGProperty* wxPropertyGridManager::DoGetPropertyByName( const wxString& name ) size_t i; for ( i=0; iGetStatePtr(); + wxPropertyGridPageState* pState = m_arrPages[i]->GetStatePtr(); wxPGProperty* p = pState->BaseGetPropertyByName(name); if ( p ) { @@ -1356,69 +1675,88 @@ bool wxPropertyGridManager::EnsureVisible( wxPGPropArg id ) // ----------------------------------------------------------------------- -size_t wxPropertyGridManager::GetChildrenCount( int page_index ) -{ - return GetChildrenCount( GetPage(page_index)->GetStatePtr()->m_properties ); -} - -// ----------------------------------------------------------------------- - void wxPropertyGridManager::OnToolbarClick( wxCommandEvent &event ) { int id = event.GetId(); - if ( id >= 0 ) - { - int baseId = m_pPropGrid->GetId(); - if ( baseId < 0 ) - baseId = wxPG_MAN_ALTERNATE_BASE_ID; - if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 0 ) ) + if ( id == m_categorizedModeToolId ) + { + // Categorized mode. + if ( m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES ) { - // Categorized mode. - if ( m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES ) - m_pPropGrid->EnableCategories( true ); + if ( !m_pPropGrid->HasInternalFlag(wxPG_FL_CATMODE_AUTO_SORT) ) + m_pPropGrid->m_windowStyle &= ~wxPG_AUTO_SORT; + m_pPropGrid->EnableCategories( true ); } - else if ( id == ( baseId + ID_ADVTBITEMSBASE_OFFSET + 1 ) ) + } + else if ( id == m_alphabeticModeToolId ) + { + // Alphabetic mode. + if ( !(m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES) ) { - // Alphabetic mode. - if ( !(m_pPropGrid->m_windowStyle & wxPG_HIDE_CATEGORIES) ) - m_pPropGrid->EnableCategories( false ); + if ( m_pPropGrid->HasFlag(wxPG_AUTO_SORT) ) + m_pPropGrid->SetInternalFlag(wxPG_FL_CATMODE_AUTO_SORT); + else + m_pPropGrid->ClearInternalFlag(wxPG_FL_CATMODE_AUTO_SORT); + + m_pPropGrid->m_windowStyle |= wxPG_AUTO_SORT; + m_pPropGrid->EnableCategories( false ); } - else - { - // Page Switching. + } + else + { + // Page Switching. - int index = -1; - size_t i; - wxPropertyGridPage* pdc; + int index = -1; + size_t i; + wxPropertyGridPage* pdc; - // Find page with given id. - for ( i=0; im_toolId == id ) { - pdc = (wxPropertyGridPage*)m_arrPages.Item(i); - if ( pdc->m_id == id ) - { - index = i; - break; - } + index = i; + break; } + } - wxASSERT( index >= 0 ); + wxASSERT( index >= 0 ); - if ( DoSelectPage( index ) ) - { + if ( DoSelectPage( index ) ) + { + // Event dispatching must be last. + m_pPropGrid->SendEvent( wxEVT_PG_PAGE_CHANGED, NULL ); + } + else + { + // TODO: Depress the old button on toolbar. + } + } +} - // Event dispatching must be last. - m_pPropGrid->SendEvent( wxEVT_PG_PAGE_CHANGED, (wxPGProperty*) NULL ); +// ----------------------------------------------------------------------- - } - else - { - // TODO: Depress the old button on toolbar. - } +bool wxPropertyGridManager::SetEditableStateItem( const wxString& name, wxVariant value ) +{ + if ( name == wxS("descboxheight") ) + { + SetDescBoxHeight(value.GetLong(), true); + return true; + } + return false; +} - } +// ----------------------------------------------------------------------- + +wxVariant wxPropertyGridManager::GetEditableStateItem( const wxString& name ) const +{ + if ( name == wxS("descboxheight") ) + { + return (long) GetDescBoxHeight(); } + return wxNullVariant; } // ----------------------------------------------------------------------- @@ -1436,8 +1774,7 @@ void wxPropertyGridManager::SetDescription( const wxString& label, const wxStrin m_pTxtHelpCaption->SetSize(-1,osz1.y); m_pTxtHelpContent->SetSize(-1,osz2.y); - if ( (m_iFlags & wxPG_FL_DESC_REFRESH_REQUIRED) || (osz2.x<(m_width-10)) ) - RefreshHelpBox( m_splitterY, m_width, m_height ); + UpdateDescriptionBox( m_splitterY, m_width, m_height ); } } @@ -1453,8 +1790,7 @@ void wxPropertyGridManager::SetDescribedProperty( wxPGProperty* p ) } else { - m_pTxtHelpCaption->SetLabel(wxEmptyString); - m_pTxtHelpContent->SetLabel(wxEmptyString); + SetDescription( wxEmptyString, wxEmptyString ); } } } @@ -1470,23 +1806,48 @@ void wxPropertyGridManager::SetSplitterLeft( bool subProps, bool allPages ) else { wxClientDC dc(this); - dc.SetFont(m_pPropGrid->m_font); + dc.SetFont(m_pPropGrid->GetFont()); int highest = 0; unsigned int i; for ( i=0; iGetColumnFitWidth(dc, GETPAGESTATE(i)->m_properties, 0, subProps ); + int maxW = m_pState->GetColumnFitWidth(dc, m_arrPages[i]->m_properties, 0, subProps ); maxW += m_pPropGrid->m_marginWidth; if ( maxW > highest ) highest = maxW; + m_pState->m_dontCenterSplitter = true; } if ( highest > 0 ) - m_pPropGrid->SetSplitterPosition( highest ); + SetSplitterPosition( highest ); + } + +#if wxUSE_HEADERCTRL + if ( m_showHeader ) + m_pHeaderCtrl->OnColumWidthsChanged(); +#endif +} - m_pPropGrid->m_iFlags |= wxPG_FL_DONT_CENTER_SPLITTER; +void wxPropertyGridManager::SetPageSplitterLeft(int page, bool subProps) +{ + wxASSERT_MSG( (page < (int) GetPageCount()), + wxT("SetPageSplitterLeft() has no effect until pages have been added") ); + + if (page < (int) GetPageCount()) + { + wxClientDC dc(this); + dc.SetFont(m_pPropGrid->GetFont()); + + int maxW = m_pState->GetColumnFitWidth(dc, m_arrPages[page]->m_properties, 0, subProps ); + maxW += m_pPropGrid->m_marginWidth; + SetPageSplitterPosition( page, maxW ); + +#if wxUSE_HEADERCTRL + if ( m_showHeader ) + m_pHeaderCtrl->OnColumWidthsChanged(); +#endif } } @@ -1504,16 +1865,52 @@ void wxPropertyGridManager::OnPropertyGridSelect( wxPropertyGridEvent& event ) // ----------------------------------------------------------------------- +void +wxPropertyGridManager::OnPGColDrag( wxPropertyGridEvent& WXUNUSED(event) ) +{ +#if wxUSE_HEADERCTRL + if ( !m_showHeader ) + return; + + m_pHeaderCtrl->OnColumWidthsChanged(); +#endif +} + +// ----------------------------------------------------------------------- + void wxPropertyGridManager::OnResize( wxSizeEvent& WXUNUSED(event) ) { int width, height; - GetClientSize(&width,&height); + GetClientSize(&width, &height); if ( m_width == -12345 ) RecreateControls(); - RecalculatePositions(width,height); + RecalculatePositions(width, height); + + if ( m_pPropGrid && m_pPropGrid->m_parent ) + { + int pgWidth, pgHeight; + m_pPropGrid->GetClientSize(&pgWidth, &pgHeight); + + // Regenerate splitter positions for non-current pages + for ( unsigned int i=0; iGetState() ) + { + page->OnClientWidthChange(pgWidth, + pgWidth - page->m_width, + true); + } + } + } + +#if wxUSE_HEADERCTRL + if ( m_showHeader ) + m_pHeaderCtrl->OnColumWidthsChanged(); +#endif } // ----------------------------------------------------------------------- @@ -1555,7 +1952,7 @@ void wxPropertyGridManager::OnMouseMove( wxMouseEvent &event ) m_splitterY = sy; m_pPropGrid->SetSize( m_width, m_splitterY - m_pPropGrid->GetPosition().y ); - RefreshHelpBox( m_splitterY, m_width, m_height ); + UpdateDescriptionBox( m_splitterY, m_width, m_height ); m_extraHeight -= change; InvalidateBestSize(); @@ -1611,7 +2008,7 @@ void wxPropertyGridManager::OnMouseClick( wxMouseEvent &event ) void wxPropertyGridManager::OnMouseUp( wxMouseEvent &event ) { - // No event type check - basicly calling this method should + // No event type check - basically calling this method should // just stop dragging. if ( m_dragStatus >= 1 ) @@ -1650,10 +2047,28 @@ void wxPropertyGridManager::SetSplitterPosition( int pos, int splitterColumn ) for ( i=0; iDoSetSplitterPositionThisPage( pos, splitterColumn ); + page->DoSetSplitterPosition( pos, splitterColumn, + wxPG_SPLITTER_REFRESH ); } - m_pPropGrid->SetInternalFlag(wxPG_FL_SPLITTER_PRE_SET); +#if wxUSE_HEADERCTRL + if ( m_showHeader ) + m_pHeaderCtrl->OnColumWidthsChanged(); +#endif +} + +// ----------------------------------------------------------------------- + +void wxPropertyGridManager::SetPageSplitterPosition( int page, + int pos, + int column ) +{ + GetPage(page)->DoSetSplitterPosition( pos, column ); + +#if wxUSE_HEADERCTRL + if ( m_showHeader ) + m_pHeaderCtrl->OnColumWidthsChanged(); +#endif } // -----------------------------------------------------------------------