Skip to content

Commit

Permalink
WT-10578: WDateEdit: fix updating of calendar when validator is changed
Browse files Browse the repository at this point in the history
- Made the validatorChanged() function virtual in WFormWidget so it can
  be overridden in WDateEdit, to update its WCalendar
- Added regression tests in WDateEditTest
- Added internal documentation for validatorChanged() and
  WValidator::repaint(). Doxygen will only look at this documentation
  if INTERNAL_DOCS is set to YES in Doxyfile
  • Loading branch information
RockinRoel committed Jul 8, 2022
1 parent 63b1c68 commit 76cc78e
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 7 deletions.
8 changes: 8 additions & 0 deletions ReleaseNotes.html
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,14 @@ <h2>Release 4.7.3 (July 8, 2022)</h2>
properly outputted as self-closing tags. This fixes a regression introduced
in Wt 4.7.0.
</li>
<li>
Fixed <a href="https://redmine.webtoolkit.eu/issues/10578" target="_blank">issue #10578</a>:
Changing the validator of a
<a href="classWt_1_1WDateEdit.html">WDateEdit</a> would not update the
<a href="classWt_1_1WDateEdit.html#a9b3a90d5a5e9e5bc766aad3707f61736">bottom()</a> and
<a href="classWt_1_1WDateEdit.html#a68431831acb72c35f46d30b28e93e2a6">top()</a> of the
<code>WDateEdit</code> correctly.
</li>
</ul>

<h2>Release 4.7.2 (May 12, 2022)</h2>
Expand Down
26 changes: 20 additions & 6 deletions src/Wt/WDateEdit.C
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,16 @@ void WDateEdit::propagateSetEnabled(bool enabled)
WLineEdit::propagateSetEnabled(enabled);
}

void WDateEdit::validatorChanged()
{
auto dv = dateValidator();
if (dv) {
calendar_->setBottom(dv->bottom());
calendar_->setTop(dv->top());
}
WLineEdit::validatorChanged();
}

void WDateEdit::setHidden(bool hidden, const WAnimation& animation)
{
WLineEdit::setHidden(hidden, animation);
Expand All @@ -184,10 +194,12 @@ void WDateEdit::setHidden(bool hidden, const WAnimation& animation)
void WDateEdit::setBottom(const WDate& bottom)
{
std::shared_ptr<WDateValidator> dv = dateValidator();
if (dv)
if (dv) {
dv->setBottom(bottom);

calendar_->setBottom(bottom);
// validatorChanged will take care of the calendar
} else {
calendar_->setBottom(bottom);
}
}

WDate WDateEdit::bottom() const
Expand All @@ -198,10 +210,12 @@ WDate WDateEdit::bottom() const
void WDateEdit::setTop(const WDate& top)
{
std::shared_ptr<WDateValidator> dv = dateValidator();
if (dv)
if (dv) {
dv->setTop(top);

calendar_->setTop(top);
// validatorChanged will take care of the calendar
} else {
calendar_->setTop(top);
}
}

WDate WDateEdit::top() const
Expand Down
1 change: 1 addition & 0 deletions src/Wt/WDateEdit.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ class WT_API WDateEdit : public WLineEdit
protected:
virtual void render(WFlags<RenderFlag> flags) override;
virtual void propagateSetEnabled(bool enabled) override;
void validatorChanged() override;

/*! \brief Sets the value from the calendar to the line edit.
*/
Expand Down
14 changes: 13 additions & 1 deletion src/Wt/WFormWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,19 @@ class WT_API WFormWidget : public WInteractWidget

virtual void enableAjax() override;

/*! \internal
* \brief Called whenever the validator is changed
*
* The validator may be changed because of setValidator() being called, or because one of the
* validator's properties was updated, and the validator called WValidator::repaint().
*
* This can be overridden to specialize how a form widget is updated when its validator changes,
* e.g. changing the bottom and top of a WDateEdit's calendar.
*
* \note The base class's validatorChanged() MUST be called!
*/
virtual void validatorChanged();

private:
static const int BIT_ENABLED_CHANGED = 0;
static const int BIT_READONLY = 1;
Expand All @@ -178,7 +191,6 @@ class WT_API WFormWidget : public WInteractWidget

void setLabel(WLabel *label);

void validatorChanged();
void defineJavaScript(bool force = false);
void updateEmptyText();

Expand Down
3 changes: 3 additions & 0 deletions src/Wt/WValidator.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ class WT_API WValidator
virtual std::string inputFilter() const;

protected:
/*! \internal
* \brief Notifies all form widgets that this validator has changed
*/
void repaint();

private:
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ IF(ENABLE_LIBWTTEST)
utils/RoundJsString.C
utils/XmlUtils.C
widgets/WContainerWidgetTest.C
widgets/WDateEditTest.C
widgets/WSpinBoxTest.C
widgets/WTextTest.C
widgets/WTreeViewTest.C
Expand Down
86 changes: 86 additions & 0 deletions test/widgets/WDateEditTest.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (C) 2022 Emweb bv, Herent, Belgium.
*
* See the LICENSE file for terms of use.
*/
#include <boost/test/unit_test.hpp>

#include <Wt/WApplication.h>
#include <Wt/WCalendar.h>
#include <Wt/WDate.h>
#include <Wt/WDateEdit.h>
#include <Wt/WDateValidator.h>
#include <Wt/Test/WTestEnvironment.h>

BOOST_AUTO_TEST_CASE( dateedit_validator_changed1 )
{
// Regression test for issue #10578
// Changing the bottom and top of the validator should change bottom and top of
// date edit and calendar
Wt::Test::WTestEnvironment environment;
Wt::WApplication app(environment);

auto dateEdit = std::make_unique<Wt::WDateEdit>();
auto dv = dateEdit->dateValidator();
const auto bottom = Wt::WDate(1999, 1, 1);
const auto top = Wt::WDate(2042, 1, 1);
dv->setBottom(bottom);
dv->setTop(top);

BOOST_REQUIRE(dv->bottom() == bottom);
BOOST_REQUIRE(dv->top() == top);
BOOST_REQUIRE(dateEdit->bottom() == bottom);
BOOST_REQUIRE(dateEdit->top() == top);

auto calendar = dateEdit->calendar();
BOOST_REQUIRE(calendar->bottom() == bottom);
BOOST_REQUIRE(calendar->top() == top);
}

BOOST_AUTO_TEST_CASE( dateedit_validator_changed2 )
{
// Regression test for issue #10578
// Changing the bottom and top of the date edit should change bottom and top of
// date validator and calendar
Wt::Test::WTestEnvironment environment;
Wt::WApplication app(environment);

auto dateEdit = std::make_unique<Wt::WDateEdit>();
auto dv = dateEdit->dateValidator();
const auto bottom = Wt::WDate(1999, 1, 1);
const auto top = Wt::WDate(2042, 1, 1);
dateEdit->setBottom(bottom);
dateEdit->setTop(top);

BOOST_REQUIRE(dv->bottom() == bottom);
BOOST_REQUIRE(dv->top() == top);
BOOST_REQUIRE(dateEdit->bottom() == bottom);
BOOST_REQUIRE(dateEdit->top() == top);

auto calendar = dateEdit->calendar();
BOOST_REQUIRE(calendar->bottom() == bottom);
BOOST_REQUIRE(calendar->top() == top);
}

BOOST_AUTO_TEST_CASE( dateedit_validator_changed3 )
{
// Regression test for issue #10578
// Changing the bottom and top of the date edit should change bottom and top of
// the calendar, even if we have no validator
Wt::Test::WTestEnvironment environment;
Wt::WApplication app(environment);

auto dateEdit = std::make_unique<Wt::WDateEdit>();
dateEdit->setValidator(nullptr);
const auto bottom = Wt::WDate(1999, 1, 1);
const auto top = Wt::WDate(2042, 1, 1);
dateEdit->setBottom(bottom);
dateEdit->setTop(top);

BOOST_REQUIRE(dateEdit->bottom() == bottom);
BOOST_REQUIRE(dateEdit->top() == top);

auto calendar = dateEdit->calendar();
BOOST_REQUIRE(calendar->bottom() == bottom);
BOOST_REQUIRE(calendar->top() == top);
}

0 comments on commit 76cc78e

Please sign in to comment.