ADD_DEPENDENCIES(${PROJECT_NAME} genlist.edj)
INSTALL(FILES ${CMAKE_BINARY_DIR}/genlist.edj DESTINATION ${EDJDIR})
+ADD_CUSTOM_TARGET(spinner-layout.edj
+ COMMAND edje_cc -id ${CMAKE_SOURCE_DIR}/resource/images -id ${CMAKE_SOURCE_DIR}/resource/icons -sd ${CMAKE_SOURCE_DIR}/resource/sounds
+ ${CMAKE_SOURCE_DIR}/resource/spinner-layout.edc ${CMAKE_BINARY_DIR}/spinner-layout.edj
+ DEPENDS ${CMAKE_SOURCE_DIR}/resource/spinner-layout.edc
+)
+ADD_DEPENDENCIES(${PROJECT_NAME} spinner-layout.edj)
+INSTALL(FILES ${CMAKE_BINARY_DIR}/spinner-layout.edj DESTINATION ${EDJDIR})
+
+ADD_CUSTOM_TARGET(spinner-layout-toggle.edj
+ COMMAND edje_cc -id ${CMAKE_SOURCE_DIR}/resource/images -id ${CMAKE_SOURCE_DIR}/resource/icons -sd ${CMAKE_SOURCE_DIR}/resource/sounds
+ ${CMAKE_SOURCE_DIR}/resource/spinner-layout-toggle.edc ${CMAKE_BINARY_DIR}/spinner-layout-toggle.edj
+ DEPENDS ${CMAKE_SOURCE_DIR}/resource/spinner-layout-toggle.edc
+)
+ADD_DEPENDENCIES(${PROJECT_NAME} spinner-layout-toggle.edj)
+INSTALL(FILES ${CMAKE_BINARY_DIR}/spinner-layout-toggle.edj DESTINATION ${EDJDIR})
+
INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/resource/icons DESTINATION ${RESDIR} FILES_MATCHING PATTERN "*.png")
INSTALL(FILES ${CMAKE_SOURCE_DIR}/${PKGNAME}.xml DESTINATION ${TZ_SYS_RO_PACKAGES})
--- /dev/null
+#define TXT_STYLE_RANGE "style,range"
+#define TXT_STYLE_DESC "style,desc"
+#define TXT_STYLE_STATE "style,state"
+
+styles {
+ style {
+ name: TXT_STYLE_RANGE;
+ base: "font=BreezeSans:style=medium font_size=31 color=#404040 wrap=mixed align=center valign=top";
+ }
+ style {
+ name: TXT_STYLE_DESC;
+ base: "font=BreezeSans:style=medium font_size=35 color=#404040 wrap=mixed align=center valign=top";
+ }
+ style {
+ name: TXT_STYLE_STATE;
+ base: "font=BreezeSans:style=medium font_size=35 color=#404040 wrap=mixed align=left valign=center";
+ }
+}
+
+collections {
+ group { name: "spinner-layout-toggle";
+ parts {
+ part { name: "spinner-background"; type: RECT;
+ description { state: "default";
+ }
+ }
+
+ part {
+ name: "toggle-widget-state";
+ type: TEXTBLOCK;
+ description {
+ state: "default" 0.0;
+ text.style: TXT_STYLE_STATE;
+ rel1.to: "spinner-background";
+ rel1.relative: 0.05 0;
+ rel2.to: "spinner-background";
+ rel2.relative: 0.85 0.10;
+ }
+ }
+
+ part {
+ name: "toggle-widget";
+ type: SWALLOW;
+ description {
+ state: "default" 0.0;
+ rel1.to: "spinner-background";
+ rel1.relative: 0.85 0;
+ rel2.to: "spinner-background";
+ rel2.relative: 1.0 0.10;
+ }
+ }
+
+ part {
+ name: "separator";
+ type: RECT;
+ description {
+ state: "default" 0.0;
+ rel1.to: "spinner-background";
+ rel1.relative: 0.0 0.10;
+ rel2.relative: 1.0 0.10;
+ align: 0 0;
+ min: 0 1;
+ max: -1 1;
+ fixed: 0 1;
+ color: 127 127 127 192;
+ }
+ }
+
+ part {
+ name: "spinner-widget";
+ type: SWALLOW;
+ description {
+ state: "default" 0.0;
+ rel1.to: "spinner-background";
+ rel1.relative: 0 0.10;
+ rel2.to: "spinner-background";
+ rel2.relative: 1.0 0.25;
+ }
+ }
+
+ part {
+ name: "accepted-range";
+ type: TEXTBLOCK;
+ description {
+ state: "default" 0.0;
+ text.style: TXT_STYLE_RANGE;
+ rel1.to: "spinner-background";
+ rel1.relative: 0 0.25;
+ rel2.to: "spinner-background";
+ rel2.relative: 1.0 0.3;
+ }
+ }
+
+ part {
+ name: "description";
+ type: TEXTBLOCK;
+ description {
+ state: "default" 0.0;
+ text.style: TXT_STYLE_DESC;
+ rel1.to: "spinner-background";
+ rel1.relative: 0.05 0.3;
+ rel2.to: "spinner-background";
+ rel2.relative: 0.95 0.6;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+#define TXT_STYLE_RANGE "style,range"
+#define TXT_STYLE_DESC "style,desc"
+
+styles {
+ style {
+ name: TXT_STYLE_RANGE;
+ base: "font=BreezeSans:style=medium font_size=31 color=#404040 wrap=mixed align=center valign=top";
+ }
+ style {
+ name: TXT_STYLE_DESC;
+ base: "font=BreezeSans:style=medium font_size=35 color=#404040 wrap=mixed align=center valign=top";
+ }
+}
+
+collections {
+ group { name: "spinner-layout";
+ parts {
+ part { name: "spinner-background"; type: RECT;
+ description { state: "default";
+ }
+ }
+ part {
+ name: "spinner-widget";
+ type: SWALLOW;
+ description {
+ state: "default" 0.0;
+ rel1.to: "spinner-background";
+ rel1.relative: 0 0;
+ rel2.to: "spinner-background";
+ rel2.relative: 1.0 0.15;
+ }
+ }
+
+ part {
+ name: "accepted-range";
+ type: TEXTBLOCK;
+ description {
+ state: "default" 0.0;
+ text.style: TXT_STYLE_RANGE;
+ rel1.to: "spinner-background";
+ rel1.relative: 0 0.15;
+ rel2.to: "spinner-background";
+ rel2.relative: 1.0 0.2;
+ }
+ }
+
+ part {
+ name: "description";
+ type: TEXTBLOCK;
+ description {
+ state: "default" 0.0;
+ text.style: TXT_STYLE_DESC;
+ rel1.to: "spinner-background";
+ rel1.relative: 0.05 0.2;
+ rel2.to: "spinner-background";
+ rel2.relative: 0.95 0.5;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+#include "AutoScanIntervalModel.hpp"
+
+#include "Singleton.hpp"
+
+AutoScanIntervalModel::AutoScanIntervalModel()
+{
+ autoScanIntervalValueHandle_ = Singleton<VConfInterface>::instance().registerAndGet<double>("db/setting/accessibility/universal-switch/AUTO_SCAN_INTERVAL", 1, [this](auto val) {
+ this->autoScanIntervalValue_ = val;
+ });
+
+ autoScanIntervalValue_.attach([](auto val) {
+ Singleton<VConfInterface>::instance().set("db/setting/accessibility/universal-switch/AUTO_SCAN_INTERVAL", val);
+ });
+}
\ No newline at end of file
--- /dev/null
+#ifndef AUTO_SCAN_INTERVAL_MODEL_HPP
+#define AUTO_SCAN_INTERVAL_MODEL_HPP
+
+#include "ObservableProperty.hpp"
+#include "VConf.hpp"
+#include "utils.hpp"
+
+class AutoScanIntervalModel
+{
+ public:
+ AutoScanIntervalModel();
+ ObservableProperty<double> autoScanIntervalValue_;
+
+ const utils::Range<double> range_ = {0.5, 9.9};
+ const double step_ = 0.1;
+ const bool editable_ = true;
+
+ private:
+ VConfInterface::CallbackHandle autoScanIntervalValueHandle_;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "PauseOnFirstModel.hpp"
+
+PauseOnFirstModel::PauseOnFirstModel()
+{
+ stateHandle_ = Singleton<VConfInterface>::instance().registerAndGet<bool>("db/setting/accessibility/universal-switch/PAUSE_ON_FIRST_ELEMENT_ENABLED", false, [this](auto val) {
+ this->state_ = val;
+ });
+
+ state_.attach([](auto val) {
+ Singleton<VConfInterface>::instance().set("db/setting/accessibility/universal-switch/PAUSE_ON_FIRST_ELEMENT_ENABLED", val);
+ });
+
+ valueHandle_ = Singleton<VConfInterface>::instance().registerAndGet<double>("db/setting/accessibility/universal-switch/PAUSE_ON_FIRST_ELEMENT_TIME", 1, [this](auto val) {
+ this->value_ = val;
+ });
+
+ value_.attach([](auto val) {
+ Singleton<VConfInterface>::instance().set("db/setting/accessibility/universal-switch/PAUSE_ON_FIRST_ELEMENT_TIME", val);
+ });
+}
\ No newline at end of file
--- /dev/null
+#ifndef PAUSE_ON_FIRST_MODEL_HPP_
+#define PAUSE_ON_FIRST_MODEL_HPP_
+
+#include "ObservableProperty.hpp"
+#include "VConf.hpp"
+#include "utils.hpp"
+
+class PauseOnFirstModel
+{
+ public:
+ PauseOnFirstModel();
+ ObservableProperty<bool> state_;
+ ObservableProperty<double> value_;
+
+ const utils::Range<double> range_ = {0.1, 5.0};
+ const double step_ = 0.1;
+ const bool editable_ = true;
+
+ private:
+ VConfInterface::CallbackHandle stateHandle_;
+ VConfInterface::CallbackHandle valueHandle_;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "AutoScanIntervalPresenter.hpp"
+
+AutoScanIntervalPresenter::AutoScanIntervalPresenter()
+ : SpinnerPresenter("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_AUTO_SCAN_INT")
+{
+ value_ = model_.autoScanIntervalValue_;
+ value_.attach([this](auto val) {
+ model_.autoScanIntervalValue_ = val;
+ });
+}
+
+utils::Range<double> AutoScanIntervalPresenter::getRange()
+{
+ return model_.range_;
+}
+
+double AutoScanIntervalPresenter::getStep()
+{
+ return model_.step_;
+}
+
+bool AutoScanIntervalPresenter::isEditable()
+{
+ return model_.editable_;
+}
+
+std::string AutoScanIntervalPresenter::getLabel()
+{
+ return "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SET_VALUE_DESC_AUTO_SCAN_INT";
+}
+
+std::string AutoScanIntervalPresenter::getFormat()
+{
+ return "%1.1f seconds";
+}
\ No newline at end of file
--- /dev/null
+#ifndef AUTO_SCAN_INTERVAL_PRESENTER
+#define AUTO_SCAN_INTERVAL_PRESENTER
+
+#include "AutoScanIntervalModel.hpp"
+#include "SpinnerPresenter.hpp"
+
+class AutoScanIntervalPresenter : public SpinnerPresenter
+{
+ public:
+ AutoScanIntervalPresenter();
+ utils::Range<double> getRange() override;
+ double getStep() override;
+ bool isEditable() override;
+ std::string getLabel() override;
+ std::string getFormat() override;
+
+ private:
+ AutoScanIntervalModel model_;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "PauseOnFirstPresenter.hpp"
+
+PauseOnFirstPresenter::PauseOnFirstPresenter()
+ : SpinnerPresenterWithToggle("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_ADD_SETTINGS_PAUSE_ON_FIRST")
+{
+ state_ = model_.state_.value();
+ state_.attach([this](auto state) {
+ model_.state_ = state;
+ });
+
+ value_ = model_.value_.value();
+ value_.attach([this](auto val) {
+ model_.value_ = val;
+ });
+}
+
+utils::Range<double> PauseOnFirstPresenter::getRange()
+{
+ return model_.range_;
+}
+
+double PauseOnFirstPresenter::getStep()
+{
+ return model_.step_;
+}
+
+bool PauseOnFirstPresenter::isEditable()
+{
+ return model_.editable_;
+}
+
+std::string PauseOnFirstPresenter::getLabel()
+{
+ return "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_ADD_SETTINGS_PAUSE_ON_FIRST";
+}
+
+std::string PauseOnFirstPresenter::getFormat()
+{
+ return "%1.1f seconds";
+}
\ No newline at end of file
--- /dev/null
+#ifndef PAUSE_ON_FIRST_PRESENTER_HPP_
+#define PAUSE_ON_FIRST_PRESENTER_HPP_
+
+#include "PauseOnFirstModel.hpp"
+#include "SpinnerPresenterWithToggle.hpp"
+
+class PauseOnFirstPresenter : public SpinnerPresenterWithToggle
+{
+ public:
+ PauseOnFirstPresenter();
+
+ utils::Range<double> getRange() override;
+ double getStep() override;
+ bool isEditable() override;
+ std::string getLabel() override;
+ std::string getFormat() override;
+
+ private:
+ PauseOnFirstModel model_;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "SpinnerPresenter.hpp"
+
+#include <sstream>
+
+SpinnerPresenter::SpinnerPresenter(std::string title)
+ : Presenter(title)
+{}
+
+std::string SpinnerPresenter::getRangeDescription()
+{
+ std::ostringstream out;
+ if (getStep() < 1.0)
+ out.precision(1);
+ else
+ out.precision(0);
+
+ out << std::fixed << "Accepted range: " << getRange().begin << " to " << getRange().end; // TODO translation
+
+ return out.str();
+}
--- /dev/null
+#ifndef SPINNER_PRESENTER_HPP
+#define SPINNER_PRESENTER_HPP
+
+#include "ObservableProperty.hpp"
+#include "Presenter.hpp"
+#include "TranslatedString.hpp"
+#include "utils.hpp"
+
+#include <functional>
+#include <string>
+
+class SpinnerPresenter : public Presenter
+{
+ public:
+ SpinnerPresenter(std::string title);
+
+ virtual utils::Range<double> getRange() = 0;
+ virtual double getStep() = 0;
+ virtual bool isEditable() = 0;
+ virtual std::string getLabel() = 0;
+ virtual std::string getFormat() = 0;
+
+ std::string getRangeDescription();
+
+ ObservableProperty<double> value_;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#ifndef SPINNER_PRESENTER_WITH_TOGGLE_HPP
+#define SPINNER_PRESENTER_WITH_TOGGLE_HPP
+
+#include "SpinnerPresenter.hpp"
+
+class SpinnerPresenterWithToggle : public SpinnerPresenter
+{
+ public:
+ using SpinnerPresenter::SpinnerPresenter;
+
+ ObservableProperty<bool> state_;
+};
+
+#endif
\ No newline at end of file
#include "UniversalSwitchSettingsPagePresenter.hpp"
+#include "AutoScanIntervalPresenter.hpp"
#include "ManageMenuOptionsPagePresenter.hpp"
+#include "PauseOnFirstPresenter.hpp"
UniversalSwitchSettingsPagePresenter::UniversalSwitchSettingsPagePresenter()
{
std::string{"IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_AUTO_SCAN_INT"},
TranslatedString::create("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS", model_.autoScanInterval_.value()).str(),
[this](auto item) {
- DEBUG("Auto scan");
+ DEBUG("Auto scan interval");
+ Singleton<AppContext>::instance().push(std::make_unique<AutoScanIntervalPresenter>());
}));
item = items.back().get();
model_.autoScanInterval_.attach([item](auto value) {
model_.pauseOnFirstState_.value() ? TranslatedString::create("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS", model_.pauseOnFirstTime_.value()).str()
: std::string{"IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF"},
[this](auto item) {
-
+ DEBUG("Pause on first");
+ Singleton<AppContext>::instance().push(std::make_unique<PauseOnFirstPresenter>());
},
ListItem::WidgetType::toggle,
[this](auto item) {
--- /dev/null
+#include "Spinner.hpp"
+
+void Spinner::createEflObject()
+{
+ uniqueObj_.reset(elm_spinner_add(parent_->getObject()));
+ setWeightHint(EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ setAlignHint(EVAS_HINT_FILL, -1.0);
+}
+
+void Spinner::setRange(utils::Range<double> range)
+{
+ elm_spinner_min_max_set(uniqueObj_.get(), range.begin, range.end);
+}
+
+void Spinner::setStep(double step)
+{
+ elm_spinner_step_set(uniqueObj_.get(), step);
+}
+
+void Spinner::setEditable(bool editable)
+{
+ elm_spinner_editable_set(uniqueObj_.get(), editable ? EINA_TRUE : EINA_FALSE);
+}
+
+void Spinner::setValue(double val)
+{
+ elm_spinner_value_set(uniqueObj_.get(), val);
+}
+
+double Spinner::getValue()
+{
+ return elm_spinner_value_get(uniqueObj_.get());
+}
+
+void Spinner::setLabelFormat(const std::string &format)
+{
+ elm_spinner_label_format_set(uniqueObj_.get(), format.c_str());
+}
\ No newline at end of file
--- /dev/null
+#ifndef SPINNER_HPP
+#define SPINNER_HPP
+
+#include "Widget.hpp"
+#include "utils.hpp"
+
+#include <string>
+
+class Spinner : public Widget
+{
+ template <typename T, typename... Args>
+ friend T *Widget::make(Widget *parent, Args &&... args);
+
+ public:
+ void setRange(utils::Range<double> range);
+ void setStep(double step);
+ void setEditable(bool editable);
+ void setValue(double val);
+ double getValue();
+ void setLabelFormat(const std::string &format);
+
+ protected:
+ using Widget::Widget;
+
+ private:
+ void createEflObject();
+};
+
+#endif
\ No newline at end of file
#include "ListPresenter.hpp"
#include "ListView.hpp"
#include "Singleton.hpp"
+#include "SpinnerPresenterWithToggle.hpp"
+#include "SpinnerView.hpp"
+#include "SpinnerViewWithToggle.hpp"
NavigationContext::NavigationContext()
{
return;
}
+ if (auto sp = dynamic_cast<SpinnerPresenterWithToggle *>(presenter)) {
+ viewsStack_.push_back(std::make_unique<SpinnerViewWithToggle>(*this, sp));
+ return;
+ }
+
+ if (auto sp = dynamic_cast<SpinnerPresenter *>(presenter)) {
+ viewsStack_.push_back(std::make_unique<SpinnerView>(*this, sp));
+ return;
+ }
+
ASSERT(0, "Presenter not supported");
}
--- /dev/null
+#include "SpinnerView.hpp"
+
+#include "Box.hpp"
+#include "Label.hpp"
+#include "Layout.hpp"
+#include "NavigationContext.hpp"
+
+SpinnerView::SpinnerView(const NavigationContext &context, Presenter *presenter)
+ : View(context), spinnerPresenter_(dynamic_cast<SpinnerPresenter *>(presenter))
+{
+ ASSERT(spinnerPresenter_, "SpinnerPresenter required");
+
+ auto naviframe = context.getNaviframe();
+
+ auto layout = Widget::make<Layout>(naviframe, "edje/spinner-layout.edj", "spinner-layout");
+
+ spinner_ = Widget::make<Spinner>(layout);
+ spinner_->setRange(spinnerPresenter_->getRange());
+ spinner_->setStep(spinnerPresenter_->getStep());
+ spinner_->setEditable(spinnerPresenter_->isEditable());
+ spinner_->setLabelFormat(spinnerPresenter_->getFormat());
+ spinner_->setValue(spinnerPresenter_->value_.value());
+ spinner_->setEvasSmartCallback("delay,changed", [this]() {
+ spinnerPresenter_->value_ = spinner_->getValue();
+ });
+ layout->setPartContent("spinner-widget", spinner_);
+ layout->setPartText("accepted-range", spinnerPresenter_->getRangeDescription());
+ layout->setPartText("description", spinnerPresenter_->getLabel());
+
+ backItem_ = Widget::make<Button>(context.getNaviframe(),
+ [naviframe = context.getNaviframe()]() { naviframe->popBack(); },
+ "IDS_ST_BUTTON_BACK",
+ Button::BACK_BUTTON_ARROW_STYLE);
+
+ naviframe->pushBack(spinnerPresenter_->getTitle(), layout, spinnerPresenter_->getOnPopCallback(), backItem_);
+}
\ No newline at end of file
--- /dev/null
+#ifndef SPINNER_VIEW_HPP
+#define SPINNER_VIEW_HPP
+
+#include "Button.hpp"
+#include "Spinner.hpp"
+#include "SpinnerPresenter.hpp"
+#include "View.hpp"
+
+class SpinnerView : public View
+{
+ public:
+ SpinnerView(const NavigationContext &context, Presenter *presenter);
+
+ protected:
+ Button *titleRightButton_ = nullptr;
+ SpinnerPresenter *spinnerPresenter_ = nullptr;
+ Spinner *spinner_ = nullptr;
+ Widget *backItem_ = nullptr;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "SpinnerViewWithToggle.hpp"
+
+#include "AppContext.hpp"
+#include "Layout.hpp"
+#include "NavigationContext.hpp"
+
+SpinnerViewWithToggle::SpinnerViewWithToggle(const NavigationContext &context, Presenter *presenter)
+ : View(context), spinnerPresenter_(dynamic_cast<SpinnerPresenterWithToggle *>(presenter))
+{
+ ASSERT(spinnerPresenter_, "SpinnerPresenterWithToggle required");
+
+ auto naviframe = context.getNaviframe();
+
+ layout_ = Widget::make<Layout>(naviframe, "edje/spinner-layout-toggle.edj", "spinner-layout-toggle");
+
+ layout_->setPartText("toggle-widget-state", spinnerPresenter_->state_.value() ? "On" : "Off");
+
+ check_ = Widget::make<Check>(layout_, false, "on&off", [this]() {
+ layout_->setPartText("toggle-widget-state", check_->getState() ? "On" : "Off");
+ spinnerPresenter_->state_ = check_->getState();
+ });
+ check_->setState(spinnerPresenter_->state_.value());
+ layout_->setPartContent("toggle-widget", check_);
+
+ spinner_ = Widget::make<Spinner>(layout_);
+ spinner_->setRange(spinnerPresenter_->getRange());
+ spinner_->setStep(spinnerPresenter_->getStep());
+ spinner_->setEditable(spinnerPresenter_->isEditable());
+ spinner_->setLabelFormat(spinnerPresenter_->getFormat());
+ spinner_->setValue(spinnerPresenter_->value_.value());
+ spinner_->setEvasSmartCallback("delay,changed", [this]() {
+ spinnerPresenter_->value_ = spinner_->getValue();
+ });
+ layout_->setPartContent("spinner-widget", spinner_);
+ layout_->setPartText("accepted-range", spinnerPresenter_->getRangeDescription());
+ layout_->setPartText("description", spinnerPresenter_->getLabel());
+
+ backItem_ = Widget::make<Button>(context.getNaviframe(),
+ [naviframe = context.getNaviframe()]() { naviframe->popBack(); },
+ "IDS_ST_BUTTON_BACK",
+ Button::BACK_BUTTON_ARROW_STYLE);
+
+ naviframe->pushBack(spinnerPresenter_->getTitle(), layout_, spinnerPresenter_->getOnPopCallback(), backItem_);
+}
\ No newline at end of file
--- /dev/null
+#ifndef SPINNER_VIEW_WITH_TOGGLE_HPP_
+#define SPINNER_VIEW_WITH_TOGGLE_HPP_
+
+#include "Button.hpp"
+#include "Check.hpp"
+#include "Layout.hpp"
+#include "Spinner.hpp"
+#include "SpinnerPresenterWithToggle.hpp"
+#include "View.hpp"
+
+class SpinnerViewWithToggle : public View
+{
+ public:
+ SpinnerViewWithToggle(const NavigationContext &context, Presenter *presenter);
+
+ protected:
+ Button *titleRightButton_ = nullptr;
+ SpinnerPresenterWithToggle *spinnerPresenter_ = nullptr;
+ Spinner *spinner_ = nullptr;
+ Widget *backItem_ = nullptr;
+ Check *check_ = nullptr;
+ Layout *layout_ = nullptr;
+};
+
+#endif
\ No newline at end of file