mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 11:56:06 +08:00
Further implementation of UI_Checkbox, tying it to a Slic3r::ConfigOptionDef.
Implemented (with tests) mechanisms for enable/disable and the on_change and on_kill_focus widgets. Implemented set_value with boost::any.
This commit is contained in:
parent
30b5635068
commit
dbff12c4e0
@ -294,7 +294,7 @@ IF(wxWidgets_FOUND)
|
|||||||
endif()
|
endif()
|
||||||
add_executable(gui_test ${UI_TEST_SOURCES})
|
add_executable(gui_test ${UI_TEST_SOURCES})
|
||||||
add_test(NAME TestGUI COMMAND gui_test)
|
add_test(NAME TestGUI COMMAND gui_test)
|
||||||
target_link_libraries(gui_test PUBLIC libslic3r slic3r_gui Catch ${wxWidgets_LIBRARIES})
|
target_link_libraries(gui_test PUBLIC libslic3r slic3r_gui Catch ${wxWidgets_LIBRARIES} ${LIBSLIC3R_DEPENDS})
|
||||||
endif()
|
endif()
|
||||||
ELSE(wxWidgets_FOUND)
|
ELSE(wxWidgets_FOUND)
|
||||||
# For convenience. When we cannot continue, inform the user
|
# For convenience. When we cannot continue, inform the user
|
||||||
|
@ -2,16 +2,24 @@
|
|||||||
#define SLIC3R_FIELD_HPP
|
#define SLIC3R_FIELD_HPP
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <boost/any.hpp>
|
||||||
|
#include "ConfigBase.hpp"
|
||||||
|
|
||||||
namespace Slic3r { namespace GUI {
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
class UI_Checkbox {
|
class UI_Checkbox {
|
||||||
public:
|
public:
|
||||||
UI_Checkbox(wxWindow* parent, wxWindowID checkid = wxID_ANY) : parent(parent) {
|
UI_Checkbox(wxWindow* parent, Slic3r::ConfigOptionDef _opt, wxWindowID checkid = wxID_ANY) : parent(parent), opt(_opt) {
|
||||||
ui_window = new wxCheckBox(parent, checkid, "");
|
ui_window = new wxCheckBox(parent, checkid, "");
|
||||||
_check = dynamic_cast<wxCheckBox*>(ui_window);
|
_check = dynamic_cast<wxCheckBox*>(ui_window);
|
||||||
|
|
||||||
|
// Set some defaults.
|
||||||
|
if (this->opt.readonly) { this->_check->Disable(); }
|
||||||
|
if (this->opt.default_value != nullptr) { this->_check->SetValue(this->opt.default_value->getBool()); }
|
||||||
|
|
||||||
|
// Set up event handlers
|
||||||
_check->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& e) { this->_on_change(""); e.Skip(); });
|
_check->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& e) { this->_on_change(""); e.Skip(); });
|
||||||
_check->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& e) { this->on_kill_focus(""); e.Skip(); });
|
_check->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& e) { if (this->on_kill_focus != nullptr) {this->on_kill_focus("");} e.Skip(); });
|
||||||
}
|
}
|
||||||
~UI_Checkbox() { wxDELETE(_check); ui_window = _check = nullptr; }
|
~UI_Checkbox() { wxDELETE(_check); ui_window = _check = nullptr; }
|
||||||
/// Function to call when the contents of this change.
|
/// Function to call when the contents of this change.
|
||||||
@ -21,18 +29,29 @@ public:
|
|||||||
/// Don't trigger on_change when this is true.
|
/// Don't trigger on_change when this is true.
|
||||||
bool disable_change_event {false};
|
bool disable_change_event {false};
|
||||||
|
|
||||||
void enable() { this->ui_window->Enable(); }
|
/// Enables the underlying UI widget.
|
||||||
|
void enable() { this->_check->Enable(); }
|
||||||
|
|
||||||
|
/// Disables the underlying UI widget.
|
||||||
void disable() { this->ui_window->Disable(); }
|
void disable() { this->ui_window->Disable(); }
|
||||||
|
|
||||||
|
/// Set the underlying widget to either enabled or disabled.
|
||||||
void toggle(bool enable = true) { enable ? this->enable() : this->disable(); }
|
void toggle(bool enable = true) { enable ? this->enable() : this->disable(); }
|
||||||
|
|
||||||
wxCheckBox* check() { return _check; }
|
wxCheckBox* check() { return _check; }
|
||||||
|
|
||||||
|
/// Returns the value of the enclosed checkbox.
|
||||||
|
/// Implements get_bool
|
||||||
bool get_bool() { return _check->GetValue();}
|
bool get_bool() { return _check->GetValue();}
|
||||||
|
|
||||||
|
/// Casts the containing value to boolean and sets the built-in checkbox appropriately.
|
||||||
|
/// implements set_value
|
||||||
|
void set_value(boost::any value) { this->_check->SetValue(boost::any_cast<bool>(value)); }
|
||||||
private:
|
private:
|
||||||
wxWindow* parent {nullptr};
|
wxWindow* parent {nullptr};
|
||||||
wxWindow* ui_window {nullptr};
|
wxWindow* ui_window {nullptr};
|
||||||
wxCheckBox* _check {nullptr};
|
wxCheckBox* _check {nullptr};
|
||||||
|
const Slic3r::ConfigOptionDef opt; //< Reference to the UI-specific bits of this option
|
||||||
|
|
||||||
void _on_change(std::string opt_id) {
|
void _on_change(std::string opt_id) {
|
||||||
if (!this->disable_change_event && this->on_change != nullptr) {
|
if (!this->disable_change_event && this->on_change != nullptr) {
|
||||||
|
@ -8,7 +8,10 @@
|
|||||||
#endif // WX_PRECOMP
|
#endif // WX_PRECOMP
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "testableframe.h"
|
#include "testableframe.h"
|
||||||
|
|
||||||
#include "OptionsGroup/Field.hpp"
|
#include "OptionsGroup/Field.hpp"
|
||||||
|
#include "ConfigBase.hpp"
|
||||||
|
|
||||||
using namespace Slic3r::GUI;
|
using namespace Slic3r::GUI;
|
||||||
|
|
||||||
SCENARIO( "GUI Checkbox option items fire their on_kill_focus when focus leaves the checkbox." ) {
|
SCENARIO( "GUI Checkbox option items fire their on_kill_focus when focus leaves the checkbox." ) {
|
||||||
@ -19,7 +22,7 @@ SCENARIO( "GUI Checkbox option items fire their on_kill_focus when focus leaves
|
|||||||
wxMilliSleep(500);
|
wxMilliSleep(500);
|
||||||
GIVEN( "A checkbox field item exists on a window") {
|
GIVEN( "A checkbox field item exists on a window") {
|
||||||
auto exec_counter {0};
|
auto exec_counter {0};
|
||||||
auto* test_field {new UI_Checkbox(wxTheApp->GetTopWindow(), wxID_ANY)};
|
auto* test_field {new Slic3r::GUI::UI_Checkbox(wxTheApp->GetTopWindow(), Slic3r::ConfigOptionDef())};
|
||||||
|
|
||||||
auto killfunc {[&exec_counter](const std::string& opt_id) { exec_counter += 1; }};
|
auto killfunc {[&exec_counter](const std::string& opt_id) { exec_counter += 1; }};
|
||||||
|
|
||||||
@ -42,21 +45,80 @@ SCENARIO( "GUI Checkbox option items fire their on_kill_focus when focus leaves
|
|||||||
REQUIRE(exec_counter == 1);
|
REQUIRE(exec_counter == 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WHEN ( "focus leaves the checkbox and no callback is assigned") {
|
||||||
|
test_field->on_kill_focus = nullptr;
|
||||||
|
exec_counter = 0;
|
||||||
|
|
||||||
|
test_field->check()->SetFocus();
|
||||||
|
wxMilliSleep(500);
|
||||||
|
|
||||||
|
auto ev {wxFocusEvent(wxEVT_KILL_FOCUS, test_field->check()->GetId())};
|
||||||
|
ev.SetEventObject(test_field->check());
|
||||||
|
test_field->check()->ProcessWindowEvent(ev);
|
||||||
|
wxYield();
|
||||||
|
wxMilliSleep(500);
|
||||||
|
THEN( "on_focus_kill doesn't try to execute nullptr") {
|
||||||
|
REQUIRE(1 == 1);
|
||||||
|
REQUIRE(exec_counter == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
delete test_field;
|
delete test_field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SCENARIO( "GUI Checkbox set_value and get_bool work as expected." ) {
|
||||||
|
wxTestableFrame* old = dynamic_cast<wxTestableFrame*>(wxTheApp->GetTopWindow());
|
||||||
|
old->Destroy();
|
||||||
|
wxTheApp->SetTopWindow(new wxTestableFrame());
|
||||||
|
wxMilliSleep(500);
|
||||||
|
|
||||||
|
auto* test_field {new Slic3r::GUI::UI_Checkbox(wxTheApp->GetTopWindow(), Slic3r::ConfigOptionDef())};
|
||||||
|
|
||||||
|
GIVEN( "A checkbox field item exists on a window") {
|
||||||
|
WHEN ( "set_value is an bool and true") {
|
||||||
|
test_field->set_value(true);
|
||||||
|
THEN( " Result is converted correctly.") {
|
||||||
|
REQUIRE( test_field->get_bool() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN ( "set_value is an bool and false") {
|
||||||
|
test_field->set_value(false);
|
||||||
|
THEN( " Result is converted correctly.") {
|
||||||
|
REQUIRE( test_field->get_bool() == false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN ( "set_value is a floating point number > 0") {
|
||||||
|
test_field->set_value(true);
|
||||||
|
try {
|
||||||
|
test_field->set_value(10.2);
|
||||||
|
} catch (boost::bad_any_cast &e) {
|
||||||
|
THEN( " Nothing happens; exception was thrown (and caught).") {
|
||||||
|
REQUIRE(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
THEN( " Value did not change.") {
|
||||||
|
REQUIRE( test_field->get_bool() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete test_field;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
SCENARIO( "GUI Checkbox option items fire their on_change event when clicked and appropriate." ) {
|
SCENARIO( "GUI Checkbox option items fire their on_change event when clicked and appropriate." ) {
|
||||||
wxUIActionSimulator sim;
|
wxUIActionSimulator sim;
|
||||||
wxTestableFrame* old = dynamic_cast<wxTestableFrame*>(wxTheApp->GetTopWindow());
|
wxTestableFrame* old = dynamic_cast<wxTestableFrame*>(wxTheApp->GetTopWindow());
|
||||||
old->Destroy();
|
old->Destroy();
|
||||||
wxTheApp->SetTopWindow(new wxTestableFrame());
|
wxTheApp->SetTopWindow(new wxTestableFrame());
|
||||||
|
auto* boolopt { new Slic3r::ConfigOptionBool(true) };
|
||||||
|
|
||||||
wxMilliSleep(500);
|
wxMilliSleep(500);
|
||||||
GIVEN( "A checkbox field item and disable_change = false") {
|
GIVEN( "A checkbox field item and disable_change = false") {
|
||||||
auto exec_counter {0};
|
auto exec_counter {0};
|
||||||
|
|
||||||
auto changefunc {[&exec_counter](const std::string& opt_id, bool value) { exec_counter += 1; }};
|
auto changefunc {[&exec_counter](const std::string& opt_id, bool value) { exec_counter += 1; }};
|
||||||
auto* test_field {new UI_Checkbox(wxTheApp->GetTopWindow(), wxID_ANY)};
|
auto* test_field {new Slic3r::GUI::UI_Checkbox(wxTheApp->GetTopWindow(), Slic3r::ConfigOptionDef())};
|
||||||
|
|
||||||
test_field->disable_change_event = false;
|
test_field->disable_change_event = false;
|
||||||
test_field->on_change = changefunc;
|
test_field->on_change = changefunc;
|
||||||
@ -97,7 +159,7 @@ SCENARIO( "GUI Checkbox option items fire their on_change event when clicked and
|
|||||||
GIVEN( "A checkbox field item and disable_change = true") {
|
GIVEN( "A checkbox field item and disable_change = true") {
|
||||||
auto exec_counter {0};
|
auto exec_counter {0};
|
||||||
auto changefunc {[&exec_counter] (const std::string& opt_id, bool value) { exec_counter++; }};
|
auto changefunc {[&exec_counter] (const std::string& opt_id, bool value) { exec_counter++; }};
|
||||||
auto* test_field {new Slic3r::GUI::UI_Checkbox(wxTheApp->GetTopWindow(), wxID_ANY)};
|
auto* test_field {new Slic3r::GUI::UI_Checkbox(wxTheApp->GetTopWindow(), Slic3r::ConfigOptionDef())};
|
||||||
wxTheApp->GetTopWindow()->Show();
|
wxTheApp->GetTopWindow()->Show();
|
||||||
wxTheApp->GetTopWindow()->Fit();
|
wxTheApp->GetTopWindow()->Fit();
|
||||||
test_field->disable_change_event = true;
|
test_field->disable_change_event = true;
|
||||||
@ -133,4 +195,133 @@ SCENARIO( "GUI Checkbox option items fire their on_change event when clicked and
|
|||||||
}
|
}
|
||||||
delete test_field;
|
delete test_field;
|
||||||
}
|
}
|
||||||
|
GIVEN( "A checkbox field item and readonly") {
|
||||||
|
|
||||||
|
struct Slic3r::ConfigOptionDef simple_option;
|
||||||
|
simple_option.default_value = boolopt;
|
||||||
|
simple_option.readonly = true;
|
||||||
|
|
||||||
|
auto exec_counter {0};
|
||||||
|
auto changefunc {[&exec_counter] (const std::string& opt_id, bool value) { exec_counter++; }};
|
||||||
|
auto* test_field {new Slic3r::GUI::UI_Checkbox(wxTheApp->GetTopWindow(), simple_option)};
|
||||||
|
wxTheApp->GetTopWindow()->Show();
|
||||||
|
wxTheApp->GetTopWindow()->Fit();
|
||||||
|
test_field->disable_change_event = false; // don't disable :D
|
||||||
|
test_field->on_change = changefunc;
|
||||||
|
|
||||||
|
WHEN ( "the box is clicked and readonly") {
|
||||||
|
exec_counter = 0;
|
||||||
|
test_field->set_value(false);
|
||||||
|
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
|
||||||
|
wxYield();
|
||||||
|
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
|
||||||
|
wxYield();
|
||||||
|
sim.MouseClick(wxMOUSE_BTN_LEFT);
|
||||||
|
wxYield();
|
||||||
|
sim.MouseClick(wxMOUSE_BTN_LEFT);
|
||||||
|
wxYield();
|
||||||
|
THEN ( "on_change is not executed.") {
|
||||||
|
REQUIRE(exec_counter == 0);
|
||||||
|
}
|
||||||
|
THEN ( "Box is not checked.") {
|
||||||
|
REQUIRE(test_field->get_bool() == false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN ( "the box is clicked and readonly") {
|
||||||
|
exec_counter = 0;
|
||||||
|
test_field->set_value(true);
|
||||||
|
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
|
||||||
|
wxYield();
|
||||||
|
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
|
||||||
|
wxYield();
|
||||||
|
sim.MouseClick(wxMOUSE_BTN_LEFT);
|
||||||
|
wxYield();
|
||||||
|
sim.MouseClick(wxMOUSE_BTN_LEFT);
|
||||||
|
wxYield();
|
||||||
|
THEN ( "on_change is not executed.") {
|
||||||
|
REQUIRE(exec_counter == 0);
|
||||||
|
}
|
||||||
|
THEN ( "Box is checked.") {
|
||||||
|
REQUIRE(test_field->get_bool() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN ( "the box is clicked and enabled") {
|
||||||
|
exec_counter = 0;
|
||||||
|
test_field->enable();
|
||||||
|
test_field->set_value(true);
|
||||||
|
wxMilliSleep(500);
|
||||||
|
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
|
||||||
|
wxYield();
|
||||||
|
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
|
||||||
|
wxYield();
|
||||||
|
sim.MouseClick(wxMOUSE_BTN_LEFT);
|
||||||
|
wxYield();
|
||||||
|
sim.MouseClick(wxMOUSE_BTN_LEFT);
|
||||||
|
wxYield();
|
||||||
|
THEN ( "on_change is executed.") {
|
||||||
|
REQUIRE(exec_counter == 1);
|
||||||
|
}
|
||||||
|
THEN ( "Box is not checked.") {
|
||||||
|
REQUIRE(test_field->get_bool() == false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN ( "the box is clicked and disabled") {
|
||||||
|
exec_counter = 0;
|
||||||
|
test_field->set_value(true);
|
||||||
|
test_field->disable();
|
||||||
|
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
|
||||||
|
wxYield();
|
||||||
|
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
|
||||||
|
wxYield();
|
||||||
|
sim.MouseClick(wxMOUSE_BTN_LEFT);
|
||||||
|
wxYield();
|
||||||
|
sim.MouseClick(wxMOUSE_BTN_LEFT);
|
||||||
|
wxYield();
|
||||||
|
THEN ( "on_change is not executed.") {
|
||||||
|
REQUIRE(exec_counter == 0);
|
||||||
|
}
|
||||||
|
THEN ( "Box is checked.") {
|
||||||
|
REQUIRE(test_field->get_bool() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN ( "the box is clicked and toggled true") {
|
||||||
|
exec_counter = 0;
|
||||||
|
test_field->set_value(true);
|
||||||
|
test_field->toggle(true);
|
||||||
|
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
|
||||||
|
wxYield();
|
||||||
|
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
|
||||||
|
wxYield();
|
||||||
|
sim.MouseClick(wxMOUSE_BTN_LEFT);
|
||||||
|
wxYield();
|
||||||
|
sim.MouseClick(wxMOUSE_BTN_LEFT);
|
||||||
|
wxYield();
|
||||||
|
THEN ( "on_change is executed.") {
|
||||||
|
REQUIRE(exec_counter == 1);
|
||||||
|
}
|
||||||
|
THEN ( "Box is not checked.") {
|
||||||
|
REQUIRE(test_field->get_bool() == false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN ( "the box is clicked and toggled false") {
|
||||||
|
exec_counter = 0;
|
||||||
|
test_field->set_value(true);
|
||||||
|
test_field->toggle(false);
|
||||||
|
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
|
||||||
|
wxYield();
|
||||||
|
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
|
||||||
|
wxYield();
|
||||||
|
sim.MouseClick(wxMOUSE_BTN_LEFT);
|
||||||
|
wxYield();
|
||||||
|
sim.MouseClick(wxMOUSE_BTN_LEFT);
|
||||||
|
wxYield();
|
||||||
|
THEN ( "on_change is not executed.") {
|
||||||
|
REQUIRE(exec_counter == 0);
|
||||||
|
}
|
||||||
|
THEN ( "Box is checked.") {
|
||||||
|
REQUIRE(test_field->get_bool() == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete test_field;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user