Merge branch 'dvc-persist' from iwbnwif

See https://github.com/wxWidgets/wxWidgets/pull/541
This commit is contained in:
Vadim Zeitlin
2017-12-15 00:28:16 +01:00
5 changed files with 414 additions and 4 deletions

View File

@@ -147,6 +147,7 @@ All (GUI):
- Fix position of the rectangle returned by wxDataViewCtrl::GetItemRect().
- Add wxDataViewRenderer::GetAccessibleDescription().
- Add wxDataViewCheckIconTextRenderer class.
- Implement persistence support for wxDataViewCtrl (iwbnwif).
- Improve wxImage::Scale() handling of pixels with alpha channel (Tim Kosse).
- Fix parsing of RGBA strings in wxColour (Laurent Poujoulat).
- Refactor code in wxQuantize() for MSVC to avoid crash.

View File

@@ -50,6 +50,7 @@ Currently the following classes are supported:
- wxTopLevelWindow (and hence wxFrame and wxDialog)
- wxBookCtrlBase (i.e. wxNotebook, wxListbook, wxToolbook and wxChoicebook)
- wxDataViewCtrl (and derivatives such as wxDataViewListCtrl)
- wxTreebook
To automatically save and restore the properties of the windows of classes

View File

@@ -0,0 +1,175 @@
///////////////////////////////////////////////////////////////////////////////
// Name: wx/persist/dataview.h
// Purpose: Persistence support for wxDataViewCtrl and its derivatives
// Author: wxWidgets Team
// Created: 2017-08-21
// Copyright: (c) 2017 wxWidgets.org
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#ifndef _WX_PERSIST_DATAVIEW_H_
#define _WX_PERSIST_DATAVIEW_H_
#include "wx/persist/window.h"
#include "wx/dataview.h"
// ----------------------------------------------------------------------------
// String constants used by wxPersistentDataViewCtrl.
// ----------------------------------------------------------------------------
#define wxPERSIST_DVC_KIND "DataView"
#define wxPERSIST_DVC_COLUMNS "Columns"
#define wxPERSIST_DVC_HIDDEN "Hidden"
#define wxPERSIST_DVC_POS "Position"
#define wxPERSIST_DVC_TITLE "Title"
#define wxPERSIST_DVC_WIDTH "Width"
#define wxPERSIST_DVC_SORT_KEY "Sorting/Column"
#define wxPERSIST_DVC_SORT_ASC "Sorting/Asc"
// ----------------------------------------------------------------------------
// Helper function to search for a column by its title.
// ----------------------------------------------------------------------------
namespace wxPrivate
{
inline
wxDataViewColumn*
GetColumnByTitle(wxDataViewCtrl* control, const wxString& name)
{
for ( unsigned int col = 0; col < control->GetColumnCount(); col++)
{
if ( control->GetColumn(col)->GetTitle() == name )
return control->GetColumn(col);
}
return NULL;
}
} // namespace wxPrivate
// ----------------------------------------------------------------------------
// wxPersistentDataViewCtrl: Saves and restores user modified column widths
// and single column sort order.
//
// Future improvements could be to save and restore column order if the user
// has changed it and multicolumn sorts.
// ----------------------------------------------------------------------------
class wxPersistentDataViewCtrl : public wxPersistentWindow<wxDataViewCtrl>
{
public:
wxPersistentDataViewCtrl(wxDataViewCtrl* control)
: wxPersistentWindow<wxDataViewCtrl>(control)
{
}
virtual void Save() const wxOVERRIDE
{
wxDataViewCtrl* const control = Get();
wxDataViewColumn* sortColumn = NULL;
for ( unsigned int col = 0; col < control->GetColumnCount(); col++ )
{
wxDataViewColumn* column = control->GetColumn(col);
wxASSERT(column);
// Create a prefix string to identify each column.
wxString columnPrefix;
columnPrefix.Printf("/%s/%s/", wxPERSIST_DVC_COLUMNS,
column->GetTitle());
// Save the column attributes.
SaveValue(columnPrefix + wxPERSIST_DVC_HIDDEN, column->IsHidden());
SaveValue(columnPrefix + wxPERSIST_DVC_POS,
control->GetColumnPosition(column));
SaveValue(columnPrefix + wxPERSIST_DVC_WIDTH, column->GetWidth());
// Check if this column is the current sort key.
if ( column->IsSortKey() )
sortColumn = column;
}
// Note: The current implementation does not save and restore multi-
// column sort keys.
if (control->IsMultiColumnSortAllowed())
return;
// Save the sort key and direction if there is a valid sort.
if ( sortColumn )
{
SaveValue(wxPERSIST_DVC_SORT_KEY, sortColumn->GetTitle());
SaveValue(wxPERSIST_DVC_SORT_ASC,
sortColumn->IsSortOrderAscending());
}
}
virtual bool Restore() wxOVERRIDE
{
wxDataViewCtrl* const control = Get();
wxDataViewColumn* column;
for ( unsigned int col = 0; col < control->GetColumnCount(); col++ )
{
column = control->GetColumn(col);
wxASSERT(column);
// Create a prefix string to identify each column within the
// persistence store (columns are stored by title). The persistence
// store benignly handles cases where the title is not found.
wxString columnPrefix;
columnPrefix.Printf("/%s/%s/", wxPERSIST_DVC_COLUMNS,
column->GetTitle());
// Restore column hidden status.
bool hidden;
if ( RestoreValue(columnPrefix + wxPERSIST_DVC_HIDDEN, &hidden) )
column->SetHidden(hidden);
// Restore the column width.
int width;
if ( RestoreValue(columnPrefix + wxPERSIST_DVC_WIDTH, &width) )
column->SetWidth(width);
// TODO: Set the column's view position.
}
// Restore the sort key and order if there is a valid model and sort
// criteria.
wxString sortColumn;
if ( control->GetModel() &&
RestoreValue(wxPERSIST_DVC_SORT_KEY, &sortColumn) &&
sortColumn != "" )
{
bool sortAsc = true;
column = wxPrivate::GetColumnByTitle(control, sortColumn);
if ( column )
{
RestoreValue(wxPERSIST_DVC_SORT_ASC, &sortAsc);
column->SetSortOrder(sortAsc);
// Resort the control based on the new sort criteria.
control->GetModel()->Resort();
}
}
return true;
}
virtual wxString GetKind() const wxOVERRIDE
{
return wxPERSIST_DVC_KIND;
}
};
inline wxPersistentObject *wxCreatePersistentObject(wxDataViewCtrl* control)
{
return new wxPersistentDataViewCtrl(control);
}
#endif // _WX_PERSIST_DATAVIEW_H_

View File

@@ -204,6 +204,9 @@ protected:
/**
Base class for persistent object adapters.
See @ref overview_persistence for an overview of persistent objects within
wxWidgets.
wxWidgets persistence framework is non-intrusive, i.e. can work with the
classes which have no relationship to nor knowledge of it. To allow this,
an intermediate persistence adapter is used: this is just a simple object
@@ -292,13 +295,14 @@ protected:
bool SaveValue(const wxString& name, T value) const;
/**
Restore the value saved by Save().
Restore a value saved by SaveValue().
@param name
The same name as was used by Save().
The same name as was used by SaveValue().
@param value
Non-@NULL pointer which will be filled with the value if it was
read successfully or not modified if it wasn't.
Non-@NULL pointer to the same type that was passed to SaveValue().
The pointed to object will be filled with the saved value if it
was read successfully or not modified otherwise.
@return
@true if the value was successfully read or @false if it was not
found or an error occurred.

View File

@@ -0,0 +1,229 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/persistence/persistence.cpp
// Purpose: wxPersistentObjects unit test
// Author: wxWidgets Team
// Created: 2017-08-23
// Copyright: (c) 2017 wxWidgets Team
///////////////////////////////////////////////////////////////////////////////
// Note: The wxDataViewCtrl test currently uses the derivative class
// wxDataViewListCtrl for convenience.
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/config.h"
#include "wx/dataview.h"
#include "wx/frame.h"
#include "wx/persist/dataview.h"
#include "wx/persist/toplevel.h"
#endif // WX_PRECOMP
// ----------------------------------------------------------------------------
// macros
// ----------------------------------------------------------------------------
#define APP_NAME "cpptest"
#define PO_PREFIX "/Persistent_Options"
#define DVLC_PREFIX PO_PREFIX "/DataView/dvlc"
#define DVLC_COL "Column #"
#define DVLC_COL_PREFIX DVLC_PREFIX "/Columns/" DVLC_COL
#define DVLC_SORT_PREFIX DVLC_PREFIX "/Sorting"
#define DVLC_FRAME_PREFIX PO_PREFIX "/Window/frame"
// --------------------------------------------------------------------------
// test class
// --------------------------------------------------------------------------
class PersistenceTestCase : public CppUnit::TestCase
{
public:
PersistenceTestCase()
{
wxTheApp->SetAppName("PersistTest");
wxConfig::Get()->DeleteGroup("/Persistent_Options");
wxConfig::Get()->Flush();
}
virtual void setUp();
private:
CPPUNIT_TEST_SUITE( PersistenceTestCase );
CPPUNIT_TEST( FrameSaveTest );
CPPUNIT_TEST( FrameRestoreTest );
CPPUNIT_TEST( DVLCSaveTest );
CPPUNIT_TEST( DVLCRestoreTest );
CPPUNIT_TEST_SUITE_END();
void FrameSaveTest();
void FrameRestoreTest();
void DVLCSaveTest();
void DVLCRestoreTest();
wxDataViewListCtrl* m_list;
wxFrame* m_frame;
wxDECLARE_NO_COPY_CLASS(PersistenceTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( PersistenceTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( PersistenceTestCase, "PersistenceTestCase" );
void PersistenceTestCase::setUp()
{
// Create the objects to persist.
m_frame = new wxFrame(wxTheApp->GetTopWindow(), wxID_ANY,
"Persistence Test",
wxDefaultPosition, wxSize(400,400));
m_list = new wxDataViewListCtrl(m_frame, wxID_ANY,
wxDefaultPosition,
wxDLG_UNIT(m_frame, wxSize(-1,-1)),
wxDV_ROW_LINES|wxDV_SINGLE);
// Define names so the objects can be found using wxConfig.
m_frame->SetName("frame");
m_list->SetName("dvlc");
// Add some columns to the DVLC.
m_list->AppendTextColumn(DVLC_COL "1",
wxDATAVIEW_CELL_INERT, -1, wxALIGN_LEFT,
wxDATAVIEW_COL_RESIZABLE |
wxDATAVIEW_COL_REORDERABLE |
wxDATAVIEW_COL_SORTABLE);
m_list->AppendTextColumn(DVLC_COL "2",
wxDATAVIEW_CELL_INERT, -1, wxALIGN_LEFT,
wxDATAVIEW_COL_RESIZABLE |
wxDATAVIEW_COL_REORDERABLE |
wxDATAVIEW_COL_SORTABLE);
// Populate with DVLC data.
wxVector<wxVariant> data;
data.push_back("AAAA");
data.push_back("BBBB");
m_list->AppendItem(data);
data.clear();
data.push_back("CCCC");
data.push_back("DDDD");
m_list->AppendItem(data);
data.clear();
data.push_back("EEEE");
data.push_back("FFFF");
m_list->AppendItem(data);
}
void PersistenceTestCase::FrameSaveTest()
{
// Adjust the initial settings.
m_frame->SetPosition(wxPoint(100, 150));
m_frame->SetSize(wxSize(450, 350));
// Get default managers.
wxPersistenceManager& pm = wxPersistenceManager::Get();
wxConfigBase* conf = wxConfig::Get();
pm.Register(m_frame);
// Destroy the frame immediately.
m_frame->wxWindowBase::Destroy();
// Test that the relevant keys have been stored correctly.
int val;
CPPUNIT_ASSERT(conf->Read(DVLC_FRAME_PREFIX "/x", &val));
CPPUNIT_ASSERT_EQUAL(100, val);
CPPUNIT_ASSERT(conf->Read(DVLC_FRAME_PREFIX "/y", &val));
CPPUNIT_ASSERT_EQUAL(150, val);
CPPUNIT_ASSERT(conf->Read(DVLC_FRAME_PREFIX "/h", &val));
CPPUNIT_ASSERT_EQUAL(350, val);
CPPUNIT_ASSERT(conf->Read(DVLC_FRAME_PREFIX "/w", &val));
CPPUNIT_ASSERT_EQUAL(450, val);
CPPUNIT_ASSERT(conf->Read(DVLC_FRAME_PREFIX "/Iconized", &val));
CPPUNIT_ASSERT_EQUAL(0, val);
CPPUNIT_ASSERT(conf->Read(DVLC_FRAME_PREFIX "/Maximized", &val));
CPPUNIT_ASSERT_EQUAL(0, val);
}
void PersistenceTestCase::FrameRestoreTest()
{
// Get default manager.
wxPersistenceManager& pm = wxPersistenceManager::Get();
// Test that the objects are registered and can be restored.
CPPUNIT_ASSERT(pm.RegisterAndRestore(m_frame));
CPPUNIT_ASSERT_EQUAL(100, m_frame->GetPosition().x);
CPPUNIT_ASSERT_EQUAL(150, m_frame->GetPosition().y);
CPPUNIT_ASSERT_EQUAL(350, m_frame->GetSize().GetHeight());
CPPUNIT_ASSERT_EQUAL(450, m_frame->GetSize().GetWidth());
CPPUNIT_ASSERT(!m_frame->IsMaximized());
CPPUNIT_ASSERT(!m_frame->IsIconized());
}
void PersistenceTestCase::DVLCSaveTest()
{
// Adjust the initial settings.
m_list->GetColumn(0)->SetWidth(150);
m_list->GetColumn(1)->SetWidth(250);
m_list->GetColumn(1)->SetSortOrder(false);
// Get default managers.
wxPersistenceManager& pm = wxPersistenceManager::Get();
wxConfigBase* conf = wxConfig::Get();
pm.Register(m_list);
// Destroy the frame containing the DVLC immediately.
m_frame->wxWindowBase::Destroy();
// Test that the relevant keys have been stored correctly.
int val;
wxString text;
CPPUNIT_ASSERT(conf->Read(DVLC_COL_PREFIX "1/Width", &val));
CPPUNIT_ASSERT_EQUAL(150, val);
CPPUNIT_ASSERT(conf->Read(DVLC_COL_PREFIX "2/Width", &val));
CPPUNIT_ASSERT_EQUAL(250, val);
CPPUNIT_ASSERT(conf->Read(DVLC_SORT_PREFIX "/Column", &text));
CPPUNIT_ASSERT_EQUAL("Column #2", text);
CPPUNIT_ASSERT(conf->Read(DVLC_SORT_PREFIX "/Asc", &val));
CPPUNIT_ASSERT_EQUAL(0, val);
}
void PersistenceTestCase::DVLCRestoreTest()
{
// Get default manager.
wxPersistenceManager& pm = wxPersistenceManager::Get();
// Test that the objects are registered and can be restored.
CPPUNIT_ASSERT(pm.RegisterAndRestore(m_list));
// Test that the correct values were restored.
CPPUNIT_ASSERT_EQUAL(150, m_list->GetColumn(0)->GetWidth());
CPPUNIT_ASSERT_EQUAL(250, m_list->GetColumn(1)->GetWidth());
CPPUNIT_ASSERT(m_list->GetColumn(1)->IsSortKey());
CPPUNIT_ASSERT(!m_list->GetColumn(1)->IsSortOrderAscending());
}