[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] master 1273a62: Remove wxDataViewCtrl implementation
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] master 1273a62: Remove wxDataViewCtrl implementation of the census view |
Date: |
Wed, 19 Aug 2020 16:53:03 -0400 (EDT) |
branch: master
commit 1273a6244bb4f853a5646cd8017bde622479456a
Author: Ilya Sinitsyn <isinitsyn@tt-solutions.com>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>
Remove wxDataViewCtrl implementation of the census view
Keep only wxGrid census view implementation.
---
census_document.cpp | 17 +-
census_document.hpp | 35 +-
census_view.cpp | 1354 +------------------------------------------
census_view.hpp | 139 +----
skeleton.cpp | 6 +-
wx_test_paste_census.cpp | 287 ++-------
wx_test_validate_output.cpp | 19 +-
7 files changed, 122 insertions(+), 1735 deletions(-)
diff --git a/census_document.cpp b/census_document.cpp
index c7bc078..8e7071a 100644
--- a/census_document.cpp
+++ b/census_document.cpp
@@ -33,22 +33,13 @@
#include <fstream>
-IMPLEMENT_DYNAMIC_CLASS(CensusDVCDocument, CensusDocument)
-IMPLEMENT_DYNAMIC_CLASS(CensusGridDocument, CensusDocument)
+IMPLEMENT_DYNAMIC_CLASS(CensusDocument, wxDocument)
-wxDataViewCtrl& CensusDVCDocument::PredominantViewWindow() const
+wxGrid& CensusDocument::PredominantViewWindow() const
{
- return ::PredominantViewWindow<CensusDVCView,wxDataViewCtrl>
+ return ::PredominantViewWindow<CensusView,wxGrid>
(*this
- ,&CensusDVCView::list_window_
- );
-}
-
-wxGrid& CensusGridDocument::PredominantViewWindow() const
-{
- return ::PredominantViewWindow<CensusGridView,wxGrid>
- (*this
- ,&CensusGridView::grid_window_
+ ,&CensusView::grid_window_
);
}
diff --git a/census_document.hpp b/census_document.hpp
index 30cffe2..f00d572 100644
--- a/census_document.hpp
+++ b/census_document.hpp
@@ -29,7 +29,6 @@
#include <wx/docview.h>
-class WXDLLIMPEXP_FWD_ADV wxDataViewCtrl;
class WXDLLIMPEXP_FWD_ADV wxGrid;
class CensusDocument
@@ -45,44 +44,16 @@ class CensusDocument
CensusDocument(CensusDocument const&) = delete;
CensusDocument& operator=(CensusDocument const&) = delete;
+ wxGrid& PredominantViewWindow() const;
+
// wxDocument overrides.
bool OnCreate(wxString const& filename, long int flags) override;
bool DoOpenDocument(wxString const& filename) override;
bool DoSaveDocument(wxString const& filename) override;
multiple_cell_document doc_;
-};
-
-class CensusDVCDocument final
- :public CensusDocument
-{
- public:
- CensusDVCDocument() = default;
- ~CensusDVCDocument() override = default;
-
- private:
- CensusDVCDocument(CensusDVCDocument const&) = delete;
- CensusDVCDocument& operator=(CensusDVCDocument const&) = delete;
-
- wxDataViewCtrl& PredominantViewWindow() const;
-
- DECLARE_DYNAMIC_CLASS(CensusDVCDocument)
-};
-
-class CensusGridDocument final
- :public CensusDocument
-{
- public:
- CensusGridDocument() = default;
- ~CensusGridDocument() override = default;
-
- private:
- CensusGridDocument(CensusGridDocument const&) = delete;
- CensusGridDocument& operator=(CensusGridDocument const&) = delete;
-
- wxGrid& PredominantViewWindow() const;
- DECLARE_DYNAMIC_CLASS(CensusGridDocument)
+ DECLARE_DYNAMIC_CLASS(CensusDocument)
};
#endif // census_document_hpp
diff --git a/census_view.cpp b/census_view.cpp
index 214e149..c919081 100644
--- a/census_view.cpp
+++ b/census_view.cpp
@@ -52,7 +52,6 @@
#include <boost/filesystem/convenience.hpp> // basename()
-#include <wx/dataview.h>
#include <wx/datectrl.h>
#include <wx/grid.h>
#include <wx/headercol.h> // wxCOL_WIDTH_DEFAULT
@@ -90,854 +89,6 @@ std::string insert_spaces_between_words(std::string const&
s)
return r;
}
-/// Data needed to create UI for tn_range<> types.
-
-struct tn_range_variant_data
- :public wxVariantData
-{
- tn_range_variant_data(std::string const& a_value, double a_min, double
a_max)
- :value {a_value}
- ,min {a_min}
- ,max {a_max}
- {
- }
-
- tn_range_variant_data(tn_range_base const& r)
- :value {r.str()}
- ,min {r.universal_minimum()}
- ,max {r.universal_maximum()}
- {
- }
-
- bool Eq(wxVariantData& data) const override
- {
- tn_range_variant_data* d = dynamic_cast<tn_range_variant_data*>(&data);
- if(!d)
- return false;
- return value == d->value && min == d->min && max == d->max;
- }
-
- wxString GetType() const override { return
typeid(tn_range_variant_data).name(); }
-
- wxVariantData* Clone() const override
- {
- return new(wx) tn_range_variant_data(value, min, max);
- }
-
- std::string value;
- double min, max;
-};
-
-// class RangeTypeRenderer
-
-class RangeTypeRenderer
- :public wxDataViewCustomRenderer
-{
- protected:
- RangeTypeRenderer();
-
- public:
- bool HasEditorCtrl() const override { return true; }
- wxWindow* CreateEditorCtrl
- (wxWindow* parent
- ,wxRect label_rect
- ,wxVariant const& value
- ) override;
- bool GetValueFromEditorCtrl(wxWindow* editor, wxVariant& value) override;
- bool Render(wxRect rect, wxDC* dc, int state) override;
- wxSize GetSize() const override;
- bool SetValue(wxVariant const& value) override;
- bool GetValue(wxVariant& value) const override;
-
- protected:
- virtual wxWindow* DoCreateEditor
- (wxWindow* parent
- ,wxRect const& rect
- ,tn_range_variant_data const& data
- ) = 0;
- virtual std::string DoGetValueFromEditor(wxWindow* editor) = 0;
-
- std::string value_;
- double min_;
- double max_;
-};
-
-RangeTypeRenderer::RangeTypeRenderer()
- :wxDataViewCustomRenderer
- (typeid(tn_range_variant_data).name()
- ,wxDATAVIEW_CELL_EDITABLE
- ,wxDVR_DEFAULT_ALIGNMENT
- )
-{
-}
-
-wxWindow* RangeTypeRenderer::CreateEditorCtrl
- (wxWindow* parent
- ,wxRect label_rect
- ,wxVariant const& value
- )
-{
- tn_range_variant_data const* data =
dynamic_cast<tn_range_variant_data*>(value.GetData());
- LMI_ASSERT(data);
-
- // Always use default height for editor controls
- wxRect rect(label_rect);
- rect.height = -1;
-
- return DoCreateEditor(parent, rect, *data);
-}
-
-bool RangeTypeRenderer::GetValueFromEditorCtrl(wxWindow* editor, wxVariant&
value)
-{
- std::string const val = DoGetValueFromEditor(editor);
- value = new(wx) tn_range_variant_data(val, min_, max_);
- return true;
-}
-
-bool RangeTypeRenderer::Render(wxRect rect, wxDC* dc, int state)
-{
- RenderText(value_, 0, rect, dc, state);
- return true;
-}
-
-wxSize RangeTypeRenderer::GetSize() const
-{
- wxSize sz = GetTextExtent(value_);
-
- // Allow some space for the spin button, which is approximately the size of
- // a scrollbar (and getting pixel-exact value would be complicated). Also
- // add some whitespace between the text and the button:
- sz.x += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
- sz.x += GetTextExtent("M").x;
-
- return sz;
-}
-
-bool RangeTypeRenderer::SetValue(wxVariant const& value)
-{
- tn_range_variant_data const* data =
dynamic_cast<tn_range_variant_data*>(value.GetData());
- LMI_ASSERT(data);
-
- value_ = data->value;
- min_ = data->min;
- max_ = data->max;
- return true;
-}
-
-bool RangeTypeRenderer::GetValue(wxVariant& value) const
-{
- value = new(wx) tn_range_variant_data(value_, min_, max_);
- return true;
-}
-
-// class IntSpinRenderer
-
-class IntSpinRenderer
- :public RangeTypeRenderer
-{
- public:
- IntSpinRenderer() : RangeTypeRenderer() {}
-
- protected:
- wxWindow* DoCreateEditor
- (wxWindow* parent
- ,wxRect const& rect
- ,tn_range_variant_data const& data
- ) override;
- std::string DoGetValueFromEditor(wxWindow* editor) override;
-};
-
-wxWindow* IntSpinRenderer::DoCreateEditor
- (wxWindow* parent
- ,wxRect const& rect
- ,tn_range_variant_data const& data
- )
-{
- return new(wx) wxSpinCtrl
- (parent
- ,wxID_ANY
- ,data.value
- ,rect.GetTopLeft()
- ,rect.GetSize()
- ,wxSP_ARROW_KEYS | wxTE_PROCESS_ENTER
- ,bourn_cast<int>(data.min)
- ,bourn_cast<int>(data.max)
- ,value_cast<int>(data.value)
- );
-}
-
-std::string IntSpinRenderer::DoGetValueFromEditor(wxWindow* editor)
-{
- wxSpinCtrl* spin = dynamic_cast<wxSpinCtrl*>(editor);
- LMI_ASSERT(spin);
-
- return value_cast<std::string>(spin->GetValue());
-}
-
-// class DoubleRangeRenderer
-
-class DoubleRangeRenderer
- :public RangeTypeRenderer
-{
- public:
- DoubleRangeRenderer() : RangeTypeRenderer() {}
-
- protected:
- wxWindow* DoCreateEditor
- (wxWindow* parent
- ,wxRect const& rect
- ,tn_range_variant_data const& data
- ) override;
- std::string DoGetValueFromEditor(wxWindow* editor) override;
-};
-
-wxWindow* DoubleRangeRenderer::DoCreateEditor
- (wxWindow* parent
- ,wxRect const& rect
- ,tn_range_variant_data const& data
- )
-{
- wxFloatingPointValidator<double> val;
- val.SetRange(data.min, data.max);
-
- wxTextCtrl* ctrl = new(wx) wxTextCtrl
- (parent
- ,wxID_ANY
- ,data.value
- ,rect.GetTopLeft()
- ,rect.GetSize()
- ,wxTE_PROCESS_ENTER
- ,val);
-
- // select the text in the control an place the cursor at the end
- // (same as wxDataViewTextRenderer)
- ctrl->SetInsertionPointEnd();
- ctrl->SelectAll();
-
- return ctrl;
-}
-
-std::string DoubleRangeRenderer::DoGetValueFromEditor(wxWindow* editor)
-{
- wxTextCtrl* ctrl = dynamic_cast<wxTextCtrl*>(editor);
- LMI_ASSERT(ctrl);
-
- return ctrl->GetValue().ToStdString();
-}
-
-// class DateRenderer
-
-class DateRenderer
- :public RangeTypeRenderer
-{
- public:
- DateRenderer() : RangeTypeRenderer() {}
- bool Render(wxRect rect, wxDC* dc, int state) override;
-
- protected:
- wxWindow* DoCreateEditor
- (wxWindow* parent
- ,wxRect const& rect
- ,tn_range_variant_data const& data
- ) override;
- std::string DoGetValueFromEditor(wxWindow* editor) override;
-};
-
-wxWindow* DateRenderer::DoCreateEditor
- (wxWindow* parent
- ,wxRect const& rect
- ,tn_range_variant_data const& data
- )
-{
- // Always use default height for editor controls
- wxRect r(rect);
- r.height = -1;
-
- wxDatePickerCtrl* ctrl = new(wx) wxDatePickerCtrl
- (parent
- ,wxID_ANY
- ,ConvertDateToWx(value_cast<calendar_date>(data.value))
- ,r.GetTopLeft()
- ,r.GetSize());
-
- ctrl->SetRange
- (ConvertDateToWx(jdn_t(static_cast<int>(data.min)))
- ,ConvertDateToWx(jdn_t(static_cast<int>(data.max)))
- );
-
- return ctrl;
-}
-
-bool DateRenderer::Render(wxRect rect, wxDC* dc, int state)
-{
- // Use wx for date formatting so that it is identical to the way
wxDatePickerCtrl does it.
- wxDateTime const date = ConvertDateToWx(value_cast<calendar_date>(value_));
- RenderText(date.FormatDate(), 0, rect, dc, state);
- return true;
-}
-
-std::string DateRenderer::DoGetValueFromEditor(wxWindow* editor)
-{
- wxDatePickerCtrl* ctrl = dynamic_cast<wxDatePickerCtrl*>(editor);
- LMI_ASSERT(ctrl);
-
- return value_cast<std::string>(ConvertDateFromWx(ctrl->GetValue()));
-}
-
-/// Data needed to create UI for input sequences.
-
-struct input_sequence_variant_data
- :public wxVariantData
-{
- input_sequence_variant_data
- (std::string const& a_value
- ,Input const* a_input
- ,std::string const& a_field
- )
- :value {a_value}
- ,input {a_input}
- ,field {a_field}
- {
- }
-
- input_sequence_variant_data(input_sequence_variant_data const&) = delete;
- input_sequence_variant_data& operator=(input_sequence_variant_data const&)
= delete;
-
- bool Eq(wxVariantData& data) const override
- {
- input_sequence_variant_data* d =
dynamic_cast<input_sequence_variant_data*>(&data);
- if(!d)
- return false;
- return value == d->value;
- }
-
- wxString GetType() const override { return
typeid(input_sequence_variant_data).name(); }
-
- wxVariantData* Clone() const override
- {
- return new(wx) input_sequence_variant_data(value, input, field);
- }
-
- std::string value;
- Input const* input;
- std::string field;
-};
-
-class DatumSequenceRenderer
- :public wxDataViewCustomRenderer
-{
- public:
- DatumSequenceRenderer();
- DatumSequenceRenderer(DatumSequenceRenderer const&) = delete;
- DatumSequenceRenderer& operator=(DatumSequenceRenderer const&) = delete;
- bool HasEditorCtrl() const override { return true; }
- wxWindow* CreateEditorCtrl
- (wxWindow* parent
- ,wxRect label_rect
- ,wxVariant const& value
- ) override;
- bool GetValueFromEditorCtrl(wxWindow* editor, wxVariant& value) override;
- bool Render(wxRect rect, wxDC* dc, int state) override;
- wxSize GetSize() const override;
- bool SetValue(wxVariant const& value) override;
- bool GetValue(wxVariant& value) const override;
-
- std::string value_;
- Input const* input_;
- std::string field_;
-};
-
-DatumSequenceRenderer::DatumSequenceRenderer()
- :wxDataViewCustomRenderer
- (typeid(input_sequence_variant_data).name()
- ,wxDATAVIEW_CELL_EDITABLE
- ,wxDVR_DEFAULT_ALIGNMENT
- )
- ,input_(nullptr)
-{
-}
-
-wxWindow* DatumSequenceRenderer::CreateEditorCtrl
- (wxWindow* parent
- ,wxRect label_rect
- ,wxVariant const& value
- )
-{
- input_sequence_variant_data const* data =
dynamic_cast<input_sequence_variant_data*>(value.GetData());
- LMI_ASSERT(data);
- LMI_ASSERT(data->input);
-
- InputSequenceEntry* ctrl = new(wx) InputSequenceEntry(parent, wxID_ANY,
"sequence_editor");
-
- ctrl->text_ctrl().SetValue(data->value.c_str());
- ctrl->input(*data->input);
- ctrl->field_name(data->field);
-
- ctrl->SetSize(label_rect);
-
- return ctrl;
-}
-
-bool DatumSequenceRenderer::GetValueFromEditorCtrl(wxWindow* editor,
wxVariant& value)
-{
- InputSequenceEntry* ctrl = dynamic_cast<InputSequenceEntry*>(editor);
- LMI_ASSERT(ctrl);
-
- value = new(wx) input_sequence_variant_data
- (ctrl->text_ctrl().GetValue().ToStdString()
- ,&ctrl->input()
- ,ctrl->field_name());
- return true;
-}
-
-bool DatumSequenceRenderer::Render(wxRect rect, wxDC* dc, int state)
-{
- RenderText(value_, 0, rect, dc, state);
- return true;
-}
-
-wxSize DatumSequenceRenderer::GetSize() const
-{
- wxSize sz = GetTextExtent(value_);
-
- // Add size of the "..." button. We assume it will use the same font that
this renderer
- // uses and add some extra whitespace in addition to InputSequenceButton's
8px padding.
- sz.x += 16 + GetTextExtent("...").x;
-
- return sz;
-}
-
-bool DatumSequenceRenderer::SetValue(wxVariant const& value)
-{
- input_sequence_variant_data const* data =
dynamic_cast<input_sequence_variant_data*>(value.GetData());
- LMI_ASSERT(data);
-
- value_ = data->value;
- input_ = data->input;
- field_ = data->field;
- return true;
-}
-
-bool DatumSequenceRenderer::GetValue(wxVariant& value) const
-{
- value = new(wx) input_sequence_variant_data(value_, input_, field_);
- return true;
-}
-
-// This class is used to implement conversion to and from wxVariant for use by
-// wxDVC renderers in a single place.
-
-class renderer_type_converter
-{
- public:
- virtual ~renderer_type_converter() = default;
- virtual wxVariant to_variant
- (any_member<Input> const& x
- ,Input const& row
- ,std::string const& col
- ) const = 0;
- virtual std::string from_variant(wxVariant const& x) const = 0;
- virtual char const* variant_type() const = 0;
- virtual wxDataViewRenderer* create_renderer(any_member<Input> const&
exemplar) const = 0;
-
- static renderer_type_converter const& get(any_member<Input> const& value);
-
- private:
- template<typename T>
- static renderer_type_converter const& get_impl();
-};
-
-// class renderer_bool_converter
-
-class renderer_bool_converter : public renderer_type_converter
-{
- wxVariant to_variant
- (any_member<Input> const& x
- ,Input const&
- ,std::string const&
- ) const override
- {
- std::string const s(x.str());
- return
- "Yes" == s ? true
- : "No" == s ? false
- : throw "Invalid boolean value."
- ;
- }
-
- std::string from_variant(wxVariant const& x) const override
- {
- return x.GetBool() ? "Yes" : "No";
- }
-
- char const* variant_type() const override
- {
- return "bool";
- }
-
- wxDataViewRenderer* create_renderer(any_member<Input> const&) const
override
- {
- return new(wx) wxDataViewToggleRenderer
- ("bool"
- ,wxDATAVIEW_CELL_ACTIVATABLE
- ,wxALIGN_CENTER
- );
- }
-};
-
-// class renderer_enum_converter
-
-class renderer_enum_converter : public renderer_type_converter
-{
- wxVariant to_variant
- (any_member<Input> const& x
- ,Input const&
- ,std::string const&
- ) const override
- {
- return wxString(x.str());
- }
-
- std::string from_variant(wxVariant const& x) const override
- {
- return x.GetString().ToStdString();
- }
-
- char const* variant_type() const override
- {
- return "string";
- }
-
- wxDataViewRenderer* create_renderer(any_member<Input> const& exemplar)
const override
- {
- mc_enum_base const* as_enum = member_cast<mc_enum_base>(exemplar);
-
- std::vector<std::string> const& all_strings = as_enum->all_strings();
- wxArrayString choices;
- choices.assign(all_strings.begin(), all_strings.end());
- return new(wx) wxDataViewChoiceRenderer(choices,
wxDATAVIEW_CELL_EDITABLE);
- }
-};
-
-// class renderer_sequence_converter
-
-class renderer_sequence_converter : public renderer_type_converter
-{
- public:
- wxVariant to_variant
- (any_member<Input> const& x
- ,Input const& row
- ,std::string const& col
- ) const override
- {
- return new(wx) input_sequence_variant_data(x.str(), &row, col);
- }
-
- std::string from_variant(wxVariant const& x) const override
- {
- input_sequence_variant_data const* data =
dynamic_cast<input_sequence_variant_data*>(x.GetData());
- LMI_ASSERT(data);
- return data->value;
- }
-
- char const* variant_type() const override
- {
- return typeid(input_sequence_variant_data).name();
- }
-
- wxDataViewRenderer* create_renderer(any_member<Input> const&) const
override
- {
- return new(wx) DatumSequenceRenderer();
- }
-};
-
-// class renderer_range_converter
-
-class renderer_range_converter : public renderer_type_converter
-{
- public:
- wxVariant to_variant
- (any_member<Input> const& x
- ,Input const&
- ,std::string const&
- ) const override
- {
- tn_range_base const* as_range = member_cast<tn_range_base>(x);
- LMI_ASSERT(as_range);
- return new(wx) tn_range_variant_data(*as_range);
- }
-
- std::string from_variant(wxVariant const& x) const override
- {
- tn_range_variant_data const* data =
dynamic_cast<tn_range_variant_data*>(x.GetData());
- LMI_ASSERT(data);
- return data->value;
- }
-
- char const* variant_type() const override
- {
- return typeid(tn_range_variant_data).name();
- }
-};
-
-class renderer_int_range_converter : public renderer_range_converter
-{
- public:
- wxDataViewRenderer* create_renderer(any_member<Input> const&) const
override
- {
- return new(wx) IntSpinRenderer();
- }
-};
-
-class renderer_double_range_converter : public renderer_range_converter
-{
- public:
- wxDataViewRenderer* create_renderer(any_member<Input> const&) const
override
- {
- return new(wx) DoubleRangeRenderer();
- }
-};
-
-class renderer_date_converter : public renderer_range_converter
-{
- public:
- wxDataViewRenderer* create_renderer(any_member<Input> const&) const
override
- {
- return new(wx) DateRenderer();
- }
-};
-
-// class renderer_fallback_converter
-
-class renderer_fallback_converter : public renderer_type_converter
-{
- public:
- wxVariant to_variant
- (any_member<Input> const& x
- ,Input const&
- ,std::string const&
- ) const override
- {
- // Strings containing new line characters are currently not displayed
- // correctly by wxDataViewCtrl, so display the value on a single line
- // after converting any optional new lines to the Unicode character
- // representing them.
- wxString s(x.str());
- s.Replace("\n", RETURN_SYMBOL, true);
- return s;
- }
-
- std::string from_variant(wxVariant const& x) const override
- {
- // Undo the replacement done above. Notice that this will (wrongly)
- // translate any RETURN_SYMBOL characters entered by the user into the
- // string to new lines, but this character is not supposed to be used
- // in any of the cells values, so just ignore this problem for now.
- wxString s = x.GetString();
- s.Replace(RETURN_SYMBOL, "\n", true);
- return s.ToStdString();
- }
-
- char const* variant_type() const override
- {
- return "string";
- }
-
- wxDataViewRenderer* create_renderer(any_member<Input> const&) const
override
- {
- return new(wx) wxDataViewTextRenderer("string",
wxDATAVIEW_CELL_EDITABLE);
- }
-
- private:
- static const wchar_t RETURN_SYMBOL = 0x23ce;
-};
-
-renderer_type_converter const& renderer_type_converter::get(any_member<Input>
const& value)
-{
- if(exact_cast<mce_yes_or_no>(value))
- {
- return get_impl<renderer_bool_converter>();
- }
- else if(exact_cast<datum_string>(value))
- {
- return get_impl<renderer_fallback_converter>();
- }
- else if(is_reconstitutable_as<datum_sequence>(value))
- {
- return get_impl<renderer_sequence_converter>();
- }
- else if(is_reconstitutable_as<mc_enum_base >(value))
- {
- return get_impl<renderer_enum_converter>();
- }
- else if(is_reconstitutable_as<tn_range_base >(value))
- {
- tn_range_base const* as_range = member_cast<tn_range_base>(value);
- if(typeid(int) == as_range->value_type())
- {
- return get_impl<renderer_int_range_converter>();
- }
- else if(typeid(double) == as_range->value_type())
- {
- return get_impl<renderer_double_range_converter>();
- }
- else if(typeid(calendar_date) == as_range->value_type())
- {
- return get_impl<renderer_date_converter>();
- }
- else
- {
- // Fall through to warn and treat datum as string.
- }
- }
- else
- {
- warning()
- << "Type '"
- << lmi::TypeInfo(value.type())
- << "' not recognized. Please report this anomaly."
- << LMI_FLUSH
- ;
- // Fall through to treat datum as string.
- }
-
- return get_impl<renderer_fallback_converter>();
-}
-
-template<typename T>
-renderer_type_converter const& renderer_type_converter::get_impl()
-{
- static T singleton;
- return singleton;
-}
-
-} // Unnamed namespace.
-
-/// Interface to the data for wxDataViewCtrl.
-
-class CensusViewDataViewModel : public wxDataViewIndexListModel
-{
- public:
- // Cell serial number: always shown in first column.
- static int const Col_CellNum = 0;
-
- CensusViewDataViewModel(CensusDVCView& view)
- :view_ {view}
- {
- }
-
- void GetValueByRow(wxVariant& variant, unsigned int row, unsigned int col)
const override;
- bool SetValueByRow(wxVariant const&, unsigned int, unsigned int) override;
-
- unsigned int GetColumnCount() const override;
-
- wxString GetColumnType(unsigned int col) const override;
-
- std::string const& col_name(int col) const;
- any_member<Input>& cell_at(int row, int col);
- any_member<Input> const& cell_at(int row, int col) const;
-
- private:
- std::vector<std::string> const& all_headers() const;
-
- CensusDVCView& view_;
-};
-
-void CensusViewDataViewModel::GetValueByRow
- (wxVariant& variant
- ,unsigned int row
- ,unsigned int col
- ) const
-{
- if(col == Col_CellNum)
- {
- // WX !! wxVariant::operator=() is overloaded for numerous
- // types, including 'long int' but excluding 'int'.
- variant = static_cast<long int>(bourn_cast<int>(1 + row));
- }
- else
- {
- any_member<Input> const& cell = cell_at(row, col);
- renderer_type_converter const& conv =
renderer_type_converter::get(cell);
- Input const& row_data = view_.cell_parms()[row];
-
- variant = conv.to_variant(cell, row_data, col_name(col));
- }
-}
-
-bool CensusViewDataViewModel::SetValueByRow
- (wxVariant const& variant
- ,unsigned int row
- ,unsigned int col
- )
-{
- LMI_ASSERT(col != Col_CellNum);
-
- any_member<Input>& cell = cell_at(row, col);
- renderer_type_converter const& conv = renderer_type_converter::get(cell);
-
- std::string const prev_val = cell.str();
- std::string new_val = conv.from_variant(variant);
-
- if(prev_val == new_val)
- return false;
-
- cell = new_val;
-
- Input& model = view_.cell_parms()[row];
- model.Reconcile();
-
- view_.document().Modify(true);
-
- return true;
-}
-
-// Avoid using unsigned types in an interface.
-unsigned int CensusViewDataViewModel::GetColumnCount() const
-{
- // "+ 1" for cell serial number in first column.
- return bourn_cast<unsigned int>(lmi::ssize(all_headers()) + 1);
-}
-
-wxString CensusViewDataViewModel::GetColumnType(unsigned int col) const
-{
- if(col == Col_CellNum)
- {
- return "long";
- }
- else
- {
- any_member<Input> const& exemplar = cell_at(0, col);
- renderer_type_converter const& conv =
renderer_type_converter::get(exemplar);
- return conv.variant_type();
- }
-}
-
-std::string const& CensusViewDataViewModel::col_name(int col) const
-{
- LMI_ASSERT(0 < col);
- // "- 1" because first column is cell serial number.
- return all_headers()[col - 1];
-}
-
-inline any_member<Input>& CensusViewDataViewModel::cell_at(int row, int col)
-{
- return view_.cell_parms()[row][col_name(col)];
-}
-
-inline any_member<Input> const& CensusViewDataViewModel::cell_at(int row, int
col) const
-{
- return view_.cell_parms()[row][col_name(col)];
-}
-
-inline std::vector<std::string> const& CensusViewDataViewModel::all_headers()
const
-{
- return view_.case_parms()[0].member_names();
-}
-
-namespace
-{
-
// Declare free functions corresponding to their namesakes in
CensusViewGridTable
// that can be used in the implementation of the custom editors below, which
// are defined before CensusViewGridTable is declared.
@@ -1482,7 +633,7 @@ class CensusViewGridTable
// Cell serial number: always shown in the first column.
static int const Col_CellNum = 0;
- explicit CensusViewGridTable(CensusGridView& view);
+ explicit CensusViewGridTable(CensusView& view);
// return the number of rows and columns in this table.
int GetNumberRows() override;
@@ -1527,12 +678,12 @@ class CensusViewGridTable
any_member<Input> const& cell_at(int row, std::string const& col) const;
std::vector<std::string> const& all_headers() const;
- CensusGridView& view_;
+ CensusView& view_;
std::vector<int> visible_columns_;
};
-CensusViewGridTable::CensusViewGridTable(CensusGridView& view)
+CensusViewGridTable::CensusViewGridTable(CensusView& view)
:view_ {view}
{
wxGrid const* grid = view.grid_window_;
@@ -1785,7 +936,12 @@ std::string const& col_name(wxGridTableBase const& table,
int col)
// class CensusView
+IMPLEMENT_DYNAMIC_CLASS(CensusView, ViewEx)
+
BEGIN_EVENT_TABLE(CensusView, ViewEx)
+ EVT_GRID_CELL_RIGHT_CLICK( CensusView::UponRightClick
)
+ EVT_GRID_CELL_CHANGED( CensusView::UponValueChanged
)
+ EVT_GRID_COL_AUTO_SIZE(
CensusView::UponColumnAutoSize )
EVT_MENU(XRCID("edit_cell" ),CensusView::UponEditCell
)
EVT_MENU(XRCID("edit_class" ),CensusView::UponEditClass
)
EVT_MENU(XRCID("edit_case" ),CensusView::UponEditCase
)
@@ -1818,6 +974,7 @@ BEGIN_EVENT_TABLE(CensusView, ViewEx)
EVT_UPDATE_UI(XRCID("copy_census"
),CensusView::UponUpdateColumnValuesVary )
EVT_UPDATE_UI(XRCID("paste_census"
),CensusView::UponUpdateAlwaysEnabled )
EVT_UPDATE_UI(XRCID("add_cell"
),CensusView::UponUpdateAlwaysEnabled )
+ EVT_UPDATE_UI(XRCID("delete_cells"
),CensusView::UponUpdateAlwaysEnabled )
EVT_UPDATE_UI(XRCID("column_width_varying"
),CensusView::UponUpdateAlwaysEnabled )
EVT_UPDATE_UI(XRCID("column_width_fixed"
),CensusView::UponUpdateAlwaysEnabled )
// Disable these printing commands on the "File" menu: specialized
@@ -1828,36 +985,12 @@ BEGIN_EVENT_TABLE(CensusView, ViewEx)
EVT_UPDATE_UI(XRCID("print_pdf"
),CensusView::UponUpdateAlwaysDisabled )
END_EVENT_TABLE()
-IMPLEMENT_DYNAMIC_CLASS(CensusDVCView, CensusView)
-
-BEGIN_EVENT_TABLE(CensusDVCView, CensusView)
- EVT_DATAVIEW_ITEM_CONTEXT_MENU (wxID_ANY ,CensusDVCView::UponRightClick
)
- EVT_DATAVIEW_ITEM_VALUE_CHANGED(wxID_ANY
,CensusDVCView::UponValueChanged )
- EVT_UPDATE_UI(XRCID("delete_cells"
),CensusDVCView::UponUpdateNonemptySelection)
-END_EVENT_TABLE()
-
-IMPLEMENT_DYNAMIC_CLASS(CensusGridView, CensusView)
-
-BEGIN_EVENT_TABLE(CensusGridView, CensusView)
- EVT_GRID_CELL_RIGHT_CLICK(
CensusGridView::UponRightClick )
- EVT_GRID_CELL_CHANGED(
CensusGridView::UponValueChanged )
- EVT_GRID_COL_AUTO_SIZE(
CensusGridView::UponColumnAutoSize )
- EVT_UPDATE_UI(XRCID("delete_cells"
),CensusGridView::UponUpdateAlwaysEnabled)
-END_EVENT_TABLE()
-
CensusView::CensusView()
:ViewEx {}
,autosize_columns_ {false}
{
}
-CensusDVCView::CensusDVCView()
- :CensusView {}
- ,list_window_ {nullptr}
- ,list_model_ {new(wx) CensusViewDataViewModel(*this)}
-{
-}
-
inline std::vector<Input>& CensusView::case_parms()
{
return document().doc_.case_parms_;
@@ -1948,29 +1081,7 @@ bool
CensusView::column_value_varies_across_cells(std::string const& header) con
return false;
}
-wxWindow* CensusDVCView::CreateChildWindow()
-{
- list_window_ = new(wx) wxDataViewCtrl
- (GetFrame()
- ,wxID_ANY
- ,wxDefaultPosition
- ,wxDefaultSize
- ,wxDV_ROW_LINES | wxDV_MULTIPLE
- );
-
- list_window_->AssociateModel(list_model_.get());
-
- // Show headers.
- document().Modify(false);
- list_model_->Reset(lmi::ssize(cell_parms()));
- Update();
-
- list_window_->Select(list_model_->GetItem(0));
-
- return list_window_;
-}
-
-wxWindow* CensusGridView::CreateChildWindow()
+wxWindow* CensusView::CreateChildWindow()
{
// Create and customize the grid window: we want to hide its row labels
// because we show our own row number column, tweak its alignment slightly
@@ -2027,14 +1138,7 @@ oenum_mvc_dv_rc CensusView::edit_parameters
);
}
-int CensusDVCView::current_row()
-{
- int row = list_model_->GetRow(list_window_->GetSelection());
- LMI_ASSERT(0 <= row && row < bourn_cast<int>(list_model_->GetCount()));
- return row;
-}
-
-int CensusGridView::current_row()
+int CensusView::current_row()
{
auto const& row = grid_window_->GetGridCursorRow();
LMI_ASSERT(0 <= row && row < grid_table_->GetRowsCount());
@@ -2182,56 +1286,7 @@ void CensusView::apply_changes
}
}
-void CensusDVCView::update_visible_columns()
-{
- int width = autosize_columns_ ? wxCOL_WIDTH_AUTOSIZE : wxCOL_WIDTH_DEFAULT;
-
- list_window_->ClearColumns();
-
- // Column zero (cell serial number) is always shown.
- list_window_->AppendColumn
- (new(wx) wxDataViewColumn
- ("Cell"
- ,new(wx) wxDataViewTextRenderer("long", wxDATAVIEW_CELL_INERT)
- ,CensusViewDataViewModel::Col_CellNum
- ,width
- ,wxALIGN_LEFT
- ,wxDATAVIEW_COL_RESIZABLE
- )
- );
-
- // Display exactly those columns whose rows aren't all identical. For
- // this purpose, consider as "rows" the individual cells--and also the
- // case and class defaults, even though they aren't displayed in rows.
- // Reason: although the case and class defaults are hidden, they're
- // still information--so if the user made them different from any cell
- // wrt some column, we respect that conscious decision.
- std::vector<std::string> const&
all_headers(case_parms()[0].member_names());
- int column = 0;
- for(auto const& header : all_headers)
- {
- ++column;
- if(column_value_varies_across_cells(header))
- {
- any_member<Input> const& exemplar = list_model_->cell_at(0,
column);
- renderer_type_converter const& conv =
renderer_type_converter::get(exemplar);
- wxDataViewRenderer* renderer = conv.create_renderer(exemplar);
- LMI_ASSERT(renderer);
- list_window_->AppendColumn
- (new(wx) wxDataViewColumn
- (insert_spaces_between_words(header)
- ,renderer
- ,column
- ,width
- ,wxALIGN_LEFT
- ,wxDATAVIEW_COL_RESIZABLE
- )
- );
- }
- }
-}
-
-void CensusGridView::update_visible_columns()
+void CensusView::update_visible_columns()
{
// Display exactly those columns whose rows aren't all identical. For
// this purpose, consider as "rows" the individual cells--and also the
@@ -2360,19 +1415,7 @@ void CensusView::UponEditCase(wxCommandEvent&)
/// Make each nonfrozen column wide enough to display its widest entry,
/// ignoring column headers.
-void CensusDVCView::UponColumnWidthVarying(wxCommandEvent&)
-{
- autosize_columns_ = true;
-
- wxWindowUpdateLocker u(list_window_);
- for(int j = 0; j < bourn_cast<int>(list_window_->GetColumnCount()); ++j)
- {
- list_window_->GetColumn(j)->SetWidth(wxCOL_WIDTH_AUTOSIZE);
- }
- Update();
-}
-
-void CensusGridView::UponColumnWidthVarying(wxCommandEvent&)
+void CensusView::UponColumnWidthVarying(wxCommandEvent&)
{
autosize_columns_ = true;
@@ -2382,19 +1425,7 @@ void
CensusGridView::UponColumnWidthVarying(wxCommandEvent&)
/// Shrink all nonfrozen columns to default width.
-void CensusDVCView::UponColumnWidthFixed(wxCommandEvent&)
-{
- autosize_columns_ = false;
-
- wxWindowUpdateLocker u(list_window_);
- for(int j = 0; j < bourn_cast<int>(list_window_->GetColumnCount()); ++j)
- {
- list_window_->GetColumn(j)->SetWidth(wxCOL_WIDTH_DEFAULT);
- }
- Update();
-}
-
-void CensusGridView::UponColumnWidthFixed(wxCommandEvent&)
+void CensusView::UponColumnWidthFixed(wxCommandEvent&)
{
autosize_columns_ = false;
@@ -2405,7 +1436,7 @@ void CensusGridView::UponColumnWidthFixed(wxCommandEvent&)
}
}
-void CensusGridView::UponRightClick(wxGridEvent&)
+void CensusView::UponRightClick(wxGridEvent&)
{
wxMenu* census_menu = wxXmlResource::Get()->LoadMenu("census_menu_ref");
LMI_ASSERT(census_menu);
@@ -2413,37 +1444,14 @@ void CensusGridView::UponRightClick(wxGridEvent&)
delete census_menu;
}
-void CensusDVCView::UponRightClick(wxDataViewEvent& e)
-{
- if(e.GetEventObject() != list_window_)
- {
- // This event should come only from the window pointed to by
- // list_window_. Ignore it if it happens to come elsewhence.
- e.Skip();
- return;
- }
-
- wxMenu* census_menu = wxXmlResource::Get()->LoadMenu("census_menu_ref");
- LMI_ASSERT(census_menu);
- list_window_->PopupMenu(census_menu);
- delete census_menu;
-}
-
-void CensusDVCView::UponValueChanged(wxDataViewEvent&)
-{
- Timer timer;
- Update();
- status() << "Update: " << timer.stop().elapsed_msec_str() << std::flush;
-}
-
-void CensusGridView::UponValueChanged(wxGridEvent&)
+void CensusView::UponValueChanged(wxGridEvent&)
{
Timer timer;
Update();
status() << "Update: " << timer.stop().elapsed_msec_str() << std::flush;
}
-void CensusGridView::UponColumnAutoSize(wxGridSizeEvent& e)
+void CensusView::UponColumnAutoSize(wxGridSizeEvent& e)
{
// Pass false to avoid setting min size to the best size.
grid_window_->AutoSizeColumn(e.GetRowOrCol(), false);
@@ -2459,13 +1467,7 @@ void
CensusView::UponUpdateAlwaysEnabled(wxUpdateUIEvent& e)
e.Enable(true);
}
-void CensusDVCView::UponUpdateSingleSelection(wxUpdateUIEvent& e)
-{
- bool const is_single_sel = list_window_->GetSelection().IsOk();
- e.Enable(is_single_sel);
-}
-
-void CensusGridView::UponUpdateSingleSelection(wxUpdateUIEvent& e)
+void CensusView::UponUpdateSingleSelection(wxUpdateUIEvent& e)
{
// We consider that in absence of any selected rows, the current row is the
// selected/active one, so what we actually check for here is that we do
@@ -2484,13 +1486,7 @@ void
CensusGridView::UponUpdateSingleSelection(wxUpdateUIEvent& e)
}
}
- e.Enable(is_single_sel);
-}
-
-void CensusDVCView::UponUpdateNonemptySelection(wxUpdateUIEvent& e)
-{
- wxDataViewItemArray selection;
- e.Enable(0 < list_window_->GetSelections(selection));
+ e.Enable(is_single_sel);
}
/// Conditionally enable copying.
@@ -2508,18 +1504,7 @@ void
CensusDVCView::UponUpdateNonemptySelection(wxUpdateUIEvent& e)
/// because if "IssueAge" varies, then so must either "DateOfBirth"
/// or "EffectiveDate".
-void CensusDVCView::UponUpdateColumnValuesVary(wxUpdateUIEvent& e)
-{
- static const std::string dob_header =
insert_spaces_between_words("UseDOB");
- int const n_cols = bourn_cast<int>(list_window_->GetColumnCount());
- bool const disable =
- 1 == n_cols
- || (2 == n_cols && dob_header ==
list_window_->GetColumn(1)->GetTitle())
- ;
- e.Enable(!disable);
-}
-
-void CensusGridView::UponUpdateColumnValuesVary(wxUpdateUIEvent& e)
+void CensusView::UponUpdateColumnValuesVary(wxUpdateUIEvent& e)
{
static const std::string dob_header =
insert_spaces_between_words("UseDOB");
int const n_cols = grid_table_->GetColsCount();
@@ -2539,7 +1524,7 @@ void
CensusGridView::UponUpdateColumnValuesVary(wxUpdateUIEvent& e)
/// Similarly, if an old employee class is no longer used, remove it; and
/// if a new one comes into use, display it.
-void CensusGridView::Update()
+void CensusView::Update()
{
LMI_ASSERT(grid_table_->GetRowsCount() == lmi::ssize(cell_parms()));
@@ -2549,16 +1534,6 @@ void CensusGridView::Update()
update_visible_columns();
}
-void CensusDVCView::Update()
-{
- LMI_ASSERT(list_model_->GetCount() == cell_parms().size());
-
- wxWindowUpdateLocker u(list_window_);
-
- update_class_names();
- update_visible_columns();
-}
-
void CensusView::UponPrintCase(wxCommandEvent&)
{
DoAllCells(mce_emit_pdf_to_printer);
@@ -2624,26 +1599,7 @@ bool CensusView::DoAllCells(mcenum_emission emission)
return true;
}
-void CensusDVCView::UponAddCell(wxCommandEvent&)
-{
- wxBusyCursor reverie;
- Timer timer;
-
- cell_parms().push_back(case_parms()[0]);
- list_model_->RowAppended();
-
- Update();
- document().Modify(true);
-
- wxDataViewItem const& z = list_model_->GetItem(list_model_->GetCount() -
1);
- list_window_->UnselectAll();
- list_window_->Select(z);
- list_window_->EnsureVisible(z);
-
- status() << "Add: " << timer.stop().elapsed_msec_str() << std::flush;
-}
-
-void CensusGridView::UponAddCell(wxCommandEvent&)
+void CensusView::UponAddCell(wxCommandEvent&)
{
wxBusyCursor reverie;
Timer timer;
@@ -2664,87 +1620,7 @@ void CensusGridView::UponAddCell(wxCommandEvent&)
status() << "Add: " << timer.stop().elapsed_msec_str() << std::flush;
}
-void CensusDVCView::UponDeleteCells(wxCommandEvent&)
-{
- int n_items = bourn_cast<int>(list_model_->GetCount());
- wxDataViewItemArray selection;
- int n_sel_items = bourn_cast<int>(list_window_->GetSelections(selection));
- LMI_ASSERT(n_sel_items == lmi::ssize(selection));
- // This handler should have been disabled if no cell is selected.
- LMI_ASSERT(0 < n_sel_items);
-
- if(n_items == n_sel_items)
- {
- warning()
- << "Cannot delete all cells. A census must always"
- << " contain at least one cell."
- << LMI_FLUSH
- ;
- return;
- }
-
- LMI_ASSERT(n_sel_items < n_items);
-
- std::ostringstream oss;
- oss
- << "Irrevocably delete "
- << n_sel_items
- << " of "
- << n_items
- << " cells?"
- ;
- int yes_or_no = wxMessageBox
- (oss.str()
- ,"Confirm deletion"
- ,wxYES_NO | wxICON_QUESTION
- );
- if(wxYES != yes_or_no)
- {
- return;
- }
-
- wxBusyCursor reverie;
- Timer timer;
-
- wxArrayInt erasures;
- for(auto const& i : selection)
- {
- erasures.push_back(list_model_->GetRow(i));
- }
- std::sort(erasures.begin(), erasures.end());
-
- LMI_ASSERT(lmi::ssize(cell_parms()) == n_items);
-
- for(int j = lmi::ssize(erasures) - 1; 0 <= j; --j)
- {
- cell_parms().erase(erasures[j] + cell_parms().begin());
- }
- LMI_ASSERT(lmi::ssize(cell_parms()) == n_items - n_sel_items);
-
- // Send notifications about changes to the wxDataViewCtrl model. Two things
- // changed: some rows were deleted and cell number of some rows shifted
- // accordingly.
- list_model_->RowsDeleted(erasures);
- for(int j = erasures.front(); j < lmi::ssize(cell_parms()); ++j)
- {
- list_model_->RowValueChanged(j, CensusViewDataViewModel::Col_CellNum);
- }
-
- int const newsel = std::min
- (erasures.front()
- ,lmi::ssize(cell_parms()) - 1
- );
- wxDataViewItem const& z = list_model_->GetItem(newsel);
- list_window_->Select(z);
- list_window_->EnsureVisible(z);
-
- Update();
- document().Modify(true);
-
- status() << "Delete: " << timer.stop().elapsed_msec_str() << std::flush;
-}
-
-void CensusGridView::UponDeleteCells(wxCommandEvent&)
+void CensusView::UponDeleteCells(wxCommandEvent&)
{
auto const n_items = grid_table_->GetRowsCount();
@@ -2878,189 +1754,7 @@ void
CensusView::UponRunCaseToGroupQuote(wxCommandEvent&)
/// file are assumed to represent user intention). In this case,
/// pasted data is appended to the cells that were already present.
-void CensusDVCView::UponPasteCensus(wxCommandEvent&)
-{
- std::string const census_data = ClipboardEx::GetText();
-
- std::vector<std::string> headers;
- std::vector<Input> cells;
-
- std::istringstream iss_census(census_data);
- iss_census.imbue(tab_is_not_whitespace_locale());
- std::string line;
-
- // Get header line; parse into field names.
- if(std::getline(iss_census, line, '\n'))
- {
- iss_census >> std::ws;
-
- std::istringstream iss_line(line);
- std::string token;
-
- while(std::getline(iss_line, token, '\t'))
- {
- headers.push_back(token);
- }
- }
- else
- {
- warning() << "Error pasting census data: no header line." << LMI_FLUSH;
- return;
- }
-
- // Use a modifiable copy of case defaults as an archetype for new
- // cells to be created by pasting. Modifications are conditionally
- // written back to case defaults later.
- Input archetype(case_parms()[0]);
-
- // Force 'UseDOB' prn. Pasting it as a column never makes sense.
- if(contains(headers, "UseDOB"))
- {
- warning() << "'UseDOB' is unnecessary and will be ignored." <<
std::flush;
- }
- bool const dob_pasted = contains(headers, "DateOfBirth");
- bool const age_pasted = contains(headers, "IssueAge");
- if(dob_pasted && age_pasted)
- {
- alarum()
- << "Cannot paste both 'DateOfBirth' and 'IssueAge'."
- << LMI_FLUSH
- ;
- }
- else if(dob_pasted)
- {
- archetype["UseDOB"] = "Yes";
- }
- else if(age_pasted)
- {
- archetype["UseDOB"] = "No";
- }
- else
- {
- ; // Do nothing: neither age nor DOB pasted.
- }
-
- cells.reserve(std::count(census_data.begin(), census_data.end(), '\n'));
-
- // Read each subsequent line into an input object representing one cell.
- int current_line = 0;
- while(std::getline(iss_census, line, '\n'))
- {
- ++current_line;
-
- iss_census >> std::ws;
-
- Input current_cell(archetype);
-
- std::istringstream iss_line(line);
- std::string token;
- std::vector<std::string> values;
-
- while(std::getline(iss_line, token, '\t'))
- {
- values.push_back(token);
- }
-
- if(values.size() != headers.size())
- {
- alarum()
- << "Line #" << current_line << ": "
- << " (" << line << ") "
- << "should have one value per column. "
- << "Number of values: " << values.size() << "; "
- << "number expected: " << headers.size() << "."
- << LMI_FLUSH
- ;
- }
-
- for(int j = 0; j < lmi::ssize(headers); ++j)
- {
- if(exact_cast<tnr_date>(current_cell[headers[j]]))
- {
- static int const jdn_min = calendar_date::gregorian_epoch_jdn;
- static int const jdn_max = calendar_date::last_yyyy_date_jdn;
- static int const ymd_min = JdnToYmd(jdn_t(jdn_min)).value();
- static int const ymd_max = JdnToYmd(jdn_t(jdn_max)).value();
- int z = value_cast<int>(values[j]);
- if(jdn_min <= z && z <= jdn_max)
- {
- ; // Do nothing: JDN is the default expectation.
- }
- else if(ymd_min <= z && z <= ymd_max)
- {
- z = YmdToJdn(ymd_t(z)).value();
- values[j] = value_cast<std::string>(z);
- }
- else
- {
- alarum()
- << "Invalid date " << values[j]
- << " for '" << headers[j] << "'"
- << " on line " << current_line << "."
- << LMI_FLUSH
- ;
- }
- }
- current_cell[headers[j]] = values[j];
- }
- current_cell.Reconcile();
- current_cell.RealizeAllSequenceInput();
- cells.push_back(current_cell);
-
- status() << "Added cell number " << cells.size() << '.' << std::flush;
- }
-
- if(0 == current_line)
- {
- warning() << "No cells to paste." << LMI_FLUSH;
- return;
- }
-
- auto selection = lmi::ssize(cell_parms());
-
- if(!document().IsModified() && !document().GetDocumentSaved())
- {
- case_parms ().clear();
- case_parms ().push_back(archetype);
- class_parms().clear();
- class_parms().push_back(archetype);
- cell_parms ().swap(cells);
- selection = 0;
- }
- else if(configurable_settings::instance().census_paste_palimpsestically())
- {
- cell_parms().swap(cells);
- // Cells that were copied from lmi have DOB and not IssueAge,
- // so pasting them back in sets UseDOB. Force UseDOB for case
- // and class defaults to prevent showing a UseDOB column with
- // each cell set to "Yes".
- for(auto& j : case_parms ()) {j["UseDOB"] = "Yes";}
- for(auto& j : class_parms()) {j["UseDOB"] = "Yes";}
- selection = 0;
- }
- else
- {
- cell_parms().reserve(cell_parms().size() + cells.size());
- std::back_insert_iterator<std::vector<Input>> iip(cell_parms());
- std::copy(cells.begin(), cells.end(), iip);
- }
-
- document().Modify(true);
- list_model_->Reset(lmi::ssize(cell_parms()));
- Update();
- // Reset() leaves the listview unreachable from the keyboard
- // because no row is selected--so select the first added row
- // if possible, else the row after which no row was inserted.
- wxDataViewItem const& z = list_model_->GetItem(selection);
- list_window_->Select(z);
- list_window_->EnsureVisible(z);
-
- LMI_ASSERT(1 == case_parms().size());
- LMI_ASSERT(!cell_parms ().empty());
- LMI_ASSERT(!class_parms().empty());
-}
-
-void CensusGridView::UponPasteCensus(wxCommandEvent&)
+void CensusView::UponPasteCensus(wxCommandEvent&)
{
std::string const census_data = ClipboardEx::GetText();
diff --git a/census_view.hpp b/census_view.hpp
index ddf8568..50710c9 100644
--- a/census_view.hpp
+++ b/census_view.hpp
@@ -38,18 +38,18 @@
#include <vector>
class CensusDocument;
-class CensusViewDataViewModel;
class CensusViewGridTable;
-class WXDLLIMPEXP_FWD_ADV wxDataViewEvent;
-class WXDLLIMPEXP_FWD_ADV wxDataViewCtrl;
class WXDLLIMPEXP_FWD_ADV wxGrid;
class WXDLLIMPEXP_FWD_ADV wxGridEvent;
class WXDLLIMPEXP_FWD_ADV wxGridSizeEvent;
-class CensusView
+class CensusView final
:public ViewEx
{
+ friend class CensusDocument;
+ friend class CensusViewGridTable;
+
public:
CensusView();
@@ -57,40 +57,43 @@ class CensusView
CensusView(CensusView const&) = delete;
CensusView& operator=(CensusView const&) = delete;
- virtual void update_visible_columns() = 0;
+ void update_visible_columns();
- protected:
CensusDocument& document() const;
// ViewEx required implementation.
+ wxWindow* CreateChildWindow() override;
char const* icon_xrc_resource () const override;
char const* menubar_xrc_resource() const override;
// Event handlers, in event-table order (reflecting GUI order)
- void UponEditCell (wxCommandEvent&);
- void UponEditClass (wxCommandEvent&);
- void UponEditCase (wxCommandEvent&);
- void UponRunCell (wxCommandEvent&);
- void UponRunCase (wxCommandEvent&);
- void UponPrintCase (wxCommandEvent&);
- void UponPrintCaseToDisk (wxCommandEvent&);
- void UponRunCaseToSpreadsheet (wxCommandEvent&);
- void UponRunCaseToGroupRoster (wxCommandEvent&);
- void UponRunCaseToGroupQuote (wxCommandEvent&);
- void UponCopyCensus (wxCommandEvent&);
- virtual void UponPasteCensus (wxCommandEvent&) = 0;
- virtual void UponAddCell (wxCommandEvent&) = 0;
- virtual void UponDeleteCells (wxCommandEvent&) = 0;
- virtual void UponColumnWidthVarying (wxCommandEvent&) = 0;
- virtual void UponColumnWidthFixed (wxCommandEvent&) = 0;
- void UponUpdateAlwaysDisabled (wxUpdateUIEvent&);
- void UponUpdateAlwaysEnabled (wxUpdateUIEvent&);
- virtual void UponUpdateSingleSelection (wxUpdateUIEvent&) = 0;
- virtual void UponUpdateColumnValuesVary (wxUpdateUIEvent&) = 0;
+ void UponRightClick (wxGridEvent&);
+ void UponValueChanged (wxGridEvent&);
+ void UponColumnAutoSize (wxGridSizeEvent&);
+ void UponEditCell (wxCommandEvent&);
+ void UponEditClass (wxCommandEvent&);
+ void UponEditCase (wxCommandEvent&);
+ void UponRunCell (wxCommandEvent&);
+ void UponRunCase (wxCommandEvent&);
+ void UponPrintCase (wxCommandEvent&);
+ void UponPrintCaseToDisk (wxCommandEvent&);
+ void UponRunCaseToSpreadsheet (wxCommandEvent&);
+ void UponRunCaseToGroupRoster (wxCommandEvent&);
+ void UponRunCaseToGroupQuote (wxCommandEvent&);
+ void UponCopyCensus (wxCommandEvent&);
+ void UponPasteCensus (wxCommandEvent&);
+ void UponAddCell (wxCommandEvent&);
+ void UponDeleteCells (wxCommandEvent&);
+ void UponColumnWidthVarying (wxCommandEvent&);
+ void UponColumnWidthFixed (wxCommandEvent&);
+ void UponUpdateAlwaysDisabled (wxUpdateUIEvent&);
+ void UponUpdateAlwaysEnabled (wxUpdateUIEvent&);
+ void UponUpdateSingleSelection (wxUpdateUIEvent&);
+ void UponUpdateColumnValuesVary (wxUpdateUIEvent&);
bool DoAllCells(mcenum_emission);
- virtual void Update() = 0;
+ void Update();
void ViewOneCell(int);
void ViewComposite();
@@ -119,7 +122,7 @@ class CensusView
,std::string const& title
);
- virtual int current_row() = 0;
+ int current_row();
void update_class_names();
@@ -129,88 +132,10 @@ class CensusView
std::shared_ptr<Ledger const> composite_ledger_;
- DECLARE_EVENT_TABLE()
-};
-
-class CensusDVCView final
- :public CensusView
-{
- friend class CensusDVCDocument;
- friend class CensusViewDataViewModel;
-
- public:
- CensusDVCView();
-
- private:
- CensusDVCView(CensusDVCView const&) = delete;
- CensusDVCView& operator=(CensusDVCView const&) = delete;
-
- void update_visible_columns() override;
-
- // ViewEx required implementation.
- wxWindow* CreateChildWindow() override;
-
- // Event handlers, in event-table order (reflecting GUI order)
- void UponRightClick (wxDataViewEvent&);
- void UponValueChanged (wxDataViewEvent&);
- void UponPasteCensus (wxCommandEvent&) override;
- void UponAddCell (wxCommandEvent&) override;
- void UponDeleteCells (wxCommandEvent&) override;
- void UponColumnWidthVarying (wxCommandEvent&) override;
- void UponColumnWidthFixed (wxCommandEvent&) override;
- void UponUpdateSingleSelection (wxUpdateUIEvent&) override;
- void UponUpdateNonemptySelection(wxUpdateUIEvent&);
- void UponUpdateColumnValuesVary (wxUpdateUIEvent&) override;
-
- void Update() override;
-
- int current_row() override;
-
- wxDataViewCtrl* list_window_;
- wxObjectDataPtr<CensusViewDataViewModel> list_model_;
-
- DECLARE_DYNAMIC_CLASS(CensusDVCView)
- DECLARE_EVENT_TABLE()
-};
-
-class CensusGridView final
- :public CensusView
-{
- friend class CensusGridDocument;
- friend class CensusViewGridTable;
-
- public:
- CensusGridView() = default;
-
- private:
- CensusGridView(CensusGridView const&) = delete;
- CensusGridView& operator=(CensusGridView const&) = delete;
-
- void update_visible_columns() override;
-
- // ViewEx required implementation.
- wxWindow* CreateChildWindow() override;
-
- // Event handlers, in event-table order (reflecting GUI order)
- void UponRightClick (wxGridEvent&);
- void UponValueChanged (wxGridEvent&);
- void UponColumnAutoSize (wxGridSizeEvent&);
- void UponPasteCensus (wxCommandEvent&) override;
- void UponAddCell (wxCommandEvent&) override;
- void UponDeleteCells (wxCommandEvent&) override;
- void UponColumnWidthVarying (wxCommandEvent&) override;
- void UponColumnWidthFixed (wxCommandEvent&) override;
- void UponUpdateSingleSelection (wxUpdateUIEvent&) override;
- void UponUpdateColumnValuesVary (wxUpdateUIEvent&) override;
-
- void Update() override;
-
- int current_row() override;
-
wxGrid* grid_window_ {nullptr};
CensusViewGridTable* grid_table_ {nullptr};
- DECLARE_DYNAMIC_CLASS(CensusGridView)
+ DECLARE_DYNAMIC_CLASS(CensusView)
DECLARE_EVENT_TABLE()
};
diff --git a/skeleton.cpp b/skeleton.cpp
index 74047fd..4686fb0 100644
--- a/skeleton.cpp
+++ b/skeleton.cpp
@@ -297,8 +297,6 @@ void Skeleton::InitDocManager()
doc_manager_ = CreateDocManager();
doc_manager_->FileHistoryLoad(*config_);
- auto const use_grid =
- contains(global_settings::instance().pyx(), "use_census_grid");
new(wx) wxDocTemplate
(doc_manager_
,"Census"
@@ -307,8 +305,8 @@ void Skeleton::InitDocManager()
,"cns"
,"Census document"
,"Census view"
- ,use_grid ? CLASSINFO(CensusGridDocument) :
CLASSINFO(CensusDVCDocument)
- ,use_grid ? CLASSINFO(CensusGridView) : CLASSINFO(CensusDVCView)
+ ,CLASSINFO(CensusDocument)
+ ,CLASSINFO(CensusView)
);
new(wx) wxDocTemplate
diff --git a/wx_test_paste_census.cpp b/wx_test_paste_census.cpp
index 8cb3f52..107ab4d 100644
--- a/wx_test_paste_census.cpp
+++ b/wx_test_paste_census.cpp
@@ -23,9 +23,7 @@
#include "assert_lmi.hpp"
#include "bourn_cast.hpp"
-#include "contains.hpp"
#include "data_directory.hpp"
-#include "global_settings.hpp"
#include "mvc_controller.hpp"
#include "ssize_lmi.hpp"
#include "wx_test_case.hpp"
@@ -34,7 +32,6 @@
#include "wx_utility.hpp"
#include <wx/app.h>
-#include <wx/dataview.h>
#include <wx/dialog.h>
#include <wx/grid.h>
#include <wx/mdi.h>
@@ -51,12 +48,10 @@
namespace
{
-// wxDataViewCtrl functions.
-
-// Helper function to find the wxDataViewCtrl used for the census display.
+// Helper function to find the wxGrid used for the census display.
//
// Precondition: the currently active window must be a CensusView.
-wxDataViewCtrl* find_census_list_window()
+wxGrid* find_census_grid_window()
{
wxWindow* const top_window = wxTheApp->GetTopWindow();
LMI_ASSERT(top_window);
@@ -72,25 +67,10 @@ wxDataViewCtrl* find_census_list_window()
wxWindowList::const_iterator z = census_children.begin();
LMI_ASSERT(z != census_children.end());
- wxDataViewCtrl* const dvc = dynamic_cast<wxDataViewCtrl*>(*z);
- LMI_ASSERT(dvc);
-
- return dvc;
-}
-
-// Retrieve the list model from list window.
-//
-// Precondition: this wxDataViewCtrl must actually use a list model.
-wxDataViewListModel* get_census_list_model(wxDataViewCtrl* dvc)
-{
- wxDataViewModel* const model = dvc->GetModel();
- LMI_ASSERT(model);
-
- wxDataViewListModel* const
- list_model = dynamic_cast<wxDataViewListModel*>(model);
- LMI_ASSERT(list_model);
+ wxGrid* const grid = dynamic_cast<wxGrid*>(*z);
+ LMI_ASSERT(grid);
- return list_model;
+ return grid;
}
// Helper for building the diagnostic message.
@@ -122,86 +102,6 @@ std::string build_not_found_message(std::set<std::string>
const& remaining)
//
// The 'when' parameter is used solely for the diagnostic messages in case of
// the check failure.
-void check_list_columns
- (wxDataViewCtrl* dvc
- ,char const* when
- ,std::set<std::string> const& expected
- ,std::string const& unexpected = std::string()
- )
-{
- std::set<std::string> remaining(expected.begin(), expected.end());
-
- for(int n = 0; n < bourn_cast<int>(dvc->GetColumnCount()); ++n)
- {
- std::string const title = dvc->GetColumn(n)->GetTitle().ToStdString();
- LMI_ASSERT_WITH_MSG
- (title != unexpected
- ,"column '" << title << "' unexpectedly found " << when
- );
-
- // Notice that it is not an error if the column is not in the expected
- // columns set, it is not exhaustive.
- remaining.erase(title);
- }
-
- LMI_ASSERT_WITH_MSG
- (remaining.empty()
- ,build_not_found_message(remaining) << when
- );
-}
-
-// Find the index of the column with the given title.
-//
-// Throws an exception if the column is not found.
-int find_model_column_by_title
- (wxDataViewCtrl* dvc
- ,std::string const& title
- )
-{
- for(int n = 0; n < bourn_cast<int>(dvc->GetColumnCount()); ++n)
- {
- wxDataViewColumn const* column = dvc->GetColumn(n);
- if(column->GetTitle().ToStdString() == title)
- {
- return column->GetModelColumn();
- }
- }
-
- throw std::runtime_error("column " + title + " not found");
-}
-
-// wxGrid functions.
-
-// Helper function to find the wxGrid used for the census display.
-//
-// Precondition: the currently active window must be a CensusView.
-wxGrid* find_census_grid_window()
-{
- wxWindow* const top_window = wxTheApp->GetTopWindow();
- LMI_ASSERT(top_window);
-
- wxMDIParentFrame* const
- parent_frame = dynamic_cast<wxMDIParentFrame*>(top_window);
- LMI_ASSERT(parent_frame);
-
- wxMDIChildFrame* const child_frame = parent_frame->GetActiveChild();
- LMI_ASSERT(child_frame);
-
- wxWindowList const& census_children = child_frame->GetChildren();
- wxWindowList::const_iterator z = census_children.begin();
- LMI_ASSERT(z != census_children.end());
-
- wxGrid* const grid = dynamic_cast<wxGrid*>(*z);
- LMI_ASSERT(grid);
-
- return grid;
-}
-
-// Check for the presence of all columns with the given name and, if specified,
-// for the absence of the given one.
-//
-// The 'when' parameter is used solely for the diagnostic messages in case of
-// the check failure.
void check_grid_columns
(wxGrid* grid
,char const* when
@@ -332,9 +232,6 @@ LMI_WX_TEST_CASE(paste_census)
// Put the data to paste on clipboard.
ClipboardEx::SetText(census_data);
- auto const use_grid =
- contains(global_settings::instance().pyx(), "use_census_grid");
-
// Create a new census.
wx_test_new_census census;
@@ -343,70 +240,33 @@ LMI_WX_TEST_CASE(paste_census)
ui.Char('s', wxMOD_CONTROL | wxMOD_SHIFT); // "Census | Paste census"
wxYield();
- wxGrid* grid_window = nullptr;
- wxGridTableBase* table = nullptr;
- wxDataViewCtrl* list_window = nullptr;
- wxDataViewListModel* list_model = nullptr;
-
- if (use_grid)
- {
- // Find the model containing the cells and check that it was filled in
- // correctly.
- grid_window = find_census_grid_window();
- table = grid_window->GetTable();
- LMI_ASSERT(table);
- LMI_ASSERT_EQUAL(table->GetNumberRows(), number_of_rows);
-
- check_grid_columns
- (grid_window
- ,"after pasting initial census data"
- ,column_titles
- );
-
- // Change class defaults: this requires a selection, so ensure we have
one
- // by clicking somewhere inside the control.
- ui.MouseMove
- (grid_window->ClientToScreen
- (wxPoint
- (10 * grid_window->GetCharWidth()
- , 3 * grid_window->GetCharHeight()
- )
- )
- );
- ui.MouseClick();
- wxYield();
-
- LMI_ASSERT_EQUAL(lmi::ssize(grid_window->GetSelectedRows()), 1);
- }
- else
- {
- // Find the model containing the cells and check that it was filled in
- // correctly.
- list_window = find_census_list_window();
- list_model = get_census_list_model(list_window);
- LMI_ASSERT_EQUAL(bourn_cast<int>(list_model->GetCount()),
number_of_rows);
-
- check_list_columns
- (list_window
- ,"after pasting initial census data"
- ,column_titles
- );
+ // Find the model containing the cells and check that it was filled in
+ // correctly.
+ wxGrid* const grid_window = find_census_grid_window();
+ wxGridTableBase* const table = grid_window->GetTable();
+ LMI_ASSERT(table);
+ LMI_ASSERT_EQUAL(table->GetNumberRows(), number_of_rows);
+
+ check_grid_columns
+ (grid_window
+ ,"after pasting initial census data"
+ ,column_titles
+ );
- // Change class defaults: this requires a selection, so ensure we have
one
- // by clicking somewhere inside the control.
- ui.MouseMove
- (list_window->ClientToScreen
- (wxPoint
- (10 * list_window->GetCharWidth()
- , 3 * list_window->GetCharHeight()
- )
+ // Change class defaults: this requires a selection, so ensure we have one
+ // by clicking somewhere inside the control.
+ ui.MouseMove
+ (grid_window->ClientToScreen
+ (wxPoint
+ (10 * grid_window->GetCharWidth()
+ , 3 * grid_window->GetCharHeight()
)
- );
- ui.MouseClick();
- wxYield();
+ )
+ );
+ ui.MouseClick();
+ wxYield();
- LMI_ASSERT_EQUAL(list_window->GetSelectedItemsCount(), 1);
- }
+ LMI_ASSERT_EQUAL(lmi::ssize(grid_window->GetSelectedRows()), 1);
ui.Char('e', wxMOD_CONTROL | wxMOD_ALT); // "Census|Edit class defaults"
@@ -460,45 +320,21 @@ LMI_WX_TEST_CASE(paste_census)
Describe("message box asking whether to apply gender changes to
all")
);
- if (use_grid)
- {
- // Check that all columns, including the "Gender" one, are still shown.
- check_grid_columns
- (grid_window
- ,"after changing gender in class defaults"
- ,column_titles
- );
+ // Check that all columns, including the "Gender" one, are still shown.
+ check_grid_columns
+ (grid_window
+ ,"after changing gender in class defaults"
+ ,column_titles
+ );
- // Verify that the "Gender" column value is "Unisex" in every row now.
- int const gender_column = find_table_column_by_title(grid_window,
"Gender");
- LMI_ASSERT_EQUAL(table->GetNumberRows(), number_of_rows);
- // Only the first two rows are affected, because only they belong
- // to the first employee class.
- for(int row = 0; row < 2; ++row)
- {
- LMI_ASSERT_EQUAL(table->GetValue(row, gender_column), "Unisex");
- }
- }
- else
+ // Verify that the "Gender" column value is "Unisex" in every row now.
+ int const gender_column = find_table_column_by_title(grid_window,
"Gender");
+ LMI_ASSERT_EQUAL(table->GetNumberRows(), number_of_rows);
+ // Only the first two rows are affected, because only they belong
+ // to the first employee class.
+ for(int row = 0; row < 2; ++row)
{
- // Check that all columns, including the "Gender" one, are still shown.
- check_list_columns
- (list_window
- ,"after changing gender in class defaults"
- ,column_titles
- );
-
- // Verify that the "Gender" column value is "Unisex" in every row now.
- int const gender_column = find_model_column_by_title(list_window,
"Gender");
- LMI_ASSERT_EQUAL(bourn_cast<int>(list_model->GetCount()),
number_of_rows);
- // Only the first two rows are affected, because only they belong
- // to the first employee class.
- for(int row = 0; row < 2; ++row)
- {
- wxVariant value;
- list_model->GetValueByRow(value, row, gender_column);
- LMI_ASSERT_EQUAL(value.GetString(), "Unisex");
- }
+ LMI_ASSERT_EQUAL(table->GetValue(row, gender_column), "Unisex");
}
// Change the case defaults to get rid of the underwriting class.
@@ -550,34 +386,17 @@ LMI_WX_TEST_CASE(paste_census)
Describe("message box asking whether to apply class changes to
all")
);
- if (use_grid)
- {
- // Check that we still have the same cells but that now the
underwriting
- // class column has disappeared as its value has been fixed.
- LMI_ASSERT_EQUAL(table->GetNumberRows(), number_of_rows);
-
- column_titles.erase("Underwriting Class");
- check_grid_columns
- (grid_window
- ,"after changing class in case defaults"
- ,column_titles
- ,"Underwriting Class"
- );
- }
- else
- {
- // Check that we still have the same cells but that now the
underwriting
- // class column has disappeared as its value has been fixed.
- LMI_ASSERT_EQUAL(bourn_cast<int>(list_model->GetCount()),
number_of_rows);
-
- column_titles.erase("Underwriting Class");
- check_list_columns
- (list_window
- ,"after changing class in case defaults"
- ,column_titles
- ,"Underwriting Class"
- );
- }
+ // Check that we still have the same cells but that now the underwriting
+ // class column has disappeared as its value has been fixed.
+ LMI_ASSERT_EQUAL(table->GetNumberRows(), number_of_rows);
+
+ column_titles.erase("Underwriting Class");
+ check_grid_columns
+ (grid_window
+ ,"after changing class in case defaults"
+ ,column_titles
+ ,"Underwriting Class"
+ );
// Finally save the census with the pasted data for later inspection.
std::string const census_file_name =
get_test_file_path_for("PasteCensus.cns");
diff --git a/wx_test_validate_output.cpp b/wx_test_validate_output.cpp
index 62277ac..c527848 100644
--- a/wx_test_validate_output.cpp
+++ b/wx_test_validate_output.cpp
@@ -23,7 +23,6 @@
#include "assert_lmi.hpp"
#include "configurable_settings.hpp"
-#include "contains.hpp"
#include "mvc_controller.hpp"
#include "path_utility.hpp"
#include "wx_test_case.hpp"
@@ -345,21 +344,11 @@ void validate_run_cell_and_copy_output
wxUIActionSimulator ui;
- auto const use_grid =
- contains(global_settings::instance().pyx(), "use_census_grid");
+ ui.Char(WXK_UP); // Clear the current selection if any.
+ ui.Char(WXK_HOME, wxMOD_CONTROL); // Go to the left top cell.
+ ui.Char(WXK_RIGHT, wxMOD_SHIFT); // Select the first row.
- if(use_grid)
- {
- ui.Char(WXK_UP); // Clear the current selection if
any.
- ui.Char(WXK_HOME, wxMOD_CONTROL); // Go to the left top cell.
- ui.Char(WXK_RIGHT, wxMOD_SHIFT); // Select the first row.
- }
- else
- {
- ui.Char(WXK_HOME); // Select the first cell.
- }
-
- ui.Char('r', wxMOD_CONTROL); // "Census|Run cell"
+ ui.Char('r', wxMOD_CONTROL); // "Census|Run cell"
wxYield();
LMI_ASSERT_WITH_MSG
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [lmi-commits] [lmi] master 1273a62: Remove wxDataViewCtrl implementation of the census view,
Greg Chicares <=