Add synchronization View-Presenter and Model-Presenter 91/204591/7
authorLukasz Wlazly <l.wlazly@partner.samsung.com>
Wed, 17 Apr 2019 14:38:03 +0000 (16:38 +0200)
committerLukasz Wlazly <l.wlazly@partner.samsung.com>
Thu, 25 Apr 2019 11:57:40 +0000 (13:57 +0200)
This patch add ObservableProperty class, which allows
to send notifications from one class to other on value change.
Usage of this mechanism is used in ListView.

Change-Id: I430372637b390c38093b30981187cc3fddd2ea39

17 files changed:
src/AccessibilityLauncherPage.cpp [deleted file]
src/AccessibilityLauncherPage.hpp [deleted file]
src/model/AccessibilityLauncherModel.cpp [new file with mode: 0644]
src/model/AccessibilityLauncherModel.hpp [new file with mode: 0644]
src/presenter/AccessibilityLauncherPagePresenter.cpp [new file with mode: 0644]
src/presenter/AccessibilityLauncherPagePresenter.hpp [new file with mode: 0644]
src/presenter/ListGroup.cpp [new file with mode: 0644]
src/presenter/ListGroup.hpp
src/presenter/ListItem.cpp
src/presenter/ListItem.hpp
src/presenter/ListPresenter.cpp
src/presenter/MainPagePresenter.cpp
src/presenter/MainPagePresenter.hpp
src/utils/Observable.hpp
src/utils/ObservableProperty.hpp [new file with mode: 0644]
src/view/ListView.cpp
src/view/ListView.hpp

diff --git a/src/AccessibilityLauncherPage.cpp b/src/AccessibilityLauncherPage.cpp
deleted file mode 100644 (file)
index 05b157b..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2018 Samsung Electronics Co., Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "AccessibilityLauncherPage.hpp"
-
-#include "AccessibilitySettingLog.hpp"
-#include "AppContext.hpp"
-#include "Button.hpp"
-#include "Genlist.hpp"
-#include "Singleton.hpp"
-#include "VConf.hpp"
-#include "setting-accessibility.h"
-#include "utils.hpp"
-
-#include <app.h>
-#include <string>
-#include <vconf.h>
-
-AccessibilityLauncherPage::AccessibilityLauncherPage()
-{
-       auto naviframe = Singleton<AppContext>::instance().navContext_.getNaviframe();
-       auto genlist = Widget::make<Genlist>(naviframe);
-       genlist->setMode(ELM_LIST_COMPRESS);
-       genlist->setStyle("dialogue");
-
-       auto launcherState = Singleton<VConfInterface>::instance().get(VCONFKEY_SETAPPL_ACCESSIBILITY_ACCESSIBILITY_LAUNCHER_STATE, false);
-       auto item = genlist->appendItem({"type1",
-               launcherState ? "IDS_ACCS_ACCESSIBILITY_LAUNCHER_ON" : "IDS_ACCS_ACCESSIBILITY_LAUNCHER_OFF",
-               {},
-               [this](auto item) {
-                       ERROR("onSelection_ lambda");
-                       item->setText(item->getState() ? "IDS_ACCS_ACCESSIBILITY_LAUNCHER_ON" : "IDS_ACCS_ACCESSIBILITY_LAUNCHER_OFF");
-
-                       Singleton<VConfInterface>::instance().set(VCONFKEY_SETAPPL_ACCESSIBILITY_ACCESSIBILITY_LAUNCHER_STATE, item->getState());
-
-                       if (item->getState())
-                               for (auto it : items_)
-                                       it->enable();
-                       else
-                               for (auto it : items_)
-                                       it->disable();
-                       item->update();
-               },
-               GenlistItem::WidgetType::toggle});
-       item->setState(launcherState);
-
-       genlist->appendItem({"multiline", {}, "IDS_ACCS_ACCESSIBILITY_LAUNCHER_COMMENT"});
-
-       auto updateLaunchState = [this](GenlistItem *item) {
-               auto state = 0;
-               for (auto i = 0u; i < items_.size(); i++)
-                       if (items_[i]->getState())
-                               state = state | (1 << i);
-               Singleton<VConfInterface>::instance().set(VCONFKEY_SETAPPL_ACCESSIBILITY_ACCESSIBILITY_LAUNCHER_LAUNCH, state);
-       };
-
-       items_.push_back(genlist->appendItem({"type1", "IDS_ST_BODY_ACCESSIBILITY", {}, updateLaunchState, GenlistItem::WidgetType::toggle}));
-       items_.push_back(genlist->appendItem({"type1", "IDS_ST_MBODY_SCREEN_READER_HTTS", {}, updateLaunchState, GenlistItem::WidgetType::toggle}));
-       items_.push_back(genlist->appendItem({"type1", "IDS_ACCS_UNIVERSAL_SWITCH", {}, updateLaunchState, GenlistItem::WidgetType::toggle}));
-
-       auto accessibilityLauncherLaunchState = Singleton<VConfInterface>::instance().get(VCONFKEY_SETAPPL_ACCESSIBILITY_ACCESSIBILITY_LAUNCHER_LAUNCH, 0);
-       for (auto i = 0u; i < items_.size(); ++i)
-               items_[i]->setState(accessibilityLauncherLaunchState & (1 << i));
-
-       if (item->getState())
-               for (auto it : items_)
-                       it->enable();
-       else
-               for (auto it : items_)
-                       it->disable();
-
-       auto prevBtn = Widget::make<Button>(
-               naviframe, [naviframe]() { naviframe->popBack(); }, std::string{}, Button::BACK_BUTTON_ARROW_STYLE);
-       naviframe->pushBack("IDS_ACCS_ACCESSIBILITY_LAUNCHER", genlist, {}, prevBtn);
-}
diff --git a/src/AccessibilityLauncherPage.hpp b/src/AccessibilityLauncherPage.hpp
deleted file mode 100644 (file)
index a7d4f36..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2018 Samsung Electronics Co., Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
-
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ACCESSIBILITY_LAUNCHER_PAGE_HPP
-#define ACCESSIBILITY_LAUNCHER_PAGE_HPP
-
-#include "GenlistItem.hpp"
-
-#include <Elementary.h>
-#include <vector>
-
-/**
- * View allowing to turn on/off Accessibility Launcher and to start configuration of its options
- *
- * @param ad global context of application
- *
- */
-class AccessibilityLauncherPage
-{
-       public:
-       AccessibilityLauncherPage();
-
-       private:
-       std::vector<GenlistItem *> items_;
-};
-
-#endif
diff --git a/src/model/AccessibilityLauncherModel.cpp b/src/model/AccessibilityLauncherModel.cpp
new file mode 100644 (file)
index 0000000..7823c1b
--- /dev/null
@@ -0,0 +1,47 @@
+#include "AccessibilityLauncherModel.hpp"
+
+#include "Singleton.hpp"
+#include "setting-accessibility.h"
+
+AccessibilityLauncherModel::AccessibilityLauncherModel()
+{
+       stateHandle_ = Singleton<VConfInterface>::instance().registerAndGet<bool>(VCONFKEY_SETAPPL_ACCESSIBILITY_ACCESSIBILITY_LAUNCHER_STATE, false, [this](auto val) {
+               state_ = val;
+       });
+
+       state_.attach([](auto val) {
+               Singleton<VConfInterface>::instance().set(VCONFKEY_SETAPPL_ACCESSIBILITY_ACCESSIBILITY_LAUNCHER_STATE, val);
+       });
+
+       launchedHandle_ = Singleton<VConfInterface>::instance().registerAndGet<int>(VCONFKEY_SETAPPL_ACCESSIBILITY_ACCESSIBILITY_LAUNCHER_LAUNCH, 0, [this](auto val) {
+               bool a = val & 0x1;
+               if (a != accessibilityLaunched_.value())
+                       accessibilityLaunched_ = a;
+
+               bool sr = val & 0x2;
+               if (sr != screenReaderLaunched_.value())
+                       screenReaderLaunched_ = sr;
+
+               bool us = val & 0x4;
+               if (us != universalSwitchLaunched_.value())
+                       universalSwitchLaunched_ = us;
+       });
+
+       auto calculateLauncherState = [this]() {
+               int a = accessibilityLaunched_.value() ? 0x1 : 0x0;
+               int sr = screenReaderLaunched_.value() ? 0x2 : 0x0;
+               int us = universalSwitchLaunched_.value() ? 0x4 : 0x0;
+
+               return us | sr | a;
+       };
+
+       accessibilityLaunched_.attach([this, calculateLauncherState](auto val) {
+               Singleton<VConfInterface>::instance().set(VCONFKEY_SETAPPL_ACCESSIBILITY_ACCESSIBILITY_LAUNCHER_LAUNCH, calculateLauncherState());
+       });
+       screenReaderLaunched_.attach([this, calculateLauncherState](auto val) {
+               Singleton<VConfInterface>::instance().set(VCONFKEY_SETAPPL_ACCESSIBILITY_ACCESSIBILITY_LAUNCHER_LAUNCH, calculateLauncherState());
+       });
+       universalSwitchLaunched_.attach([this, calculateLauncherState](auto val) {
+               Singleton<VConfInterface>::instance().set(VCONFKEY_SETAPPL_ACCESSIBILITY_ACCESSIBILITY_LAUNCHER_LAUNCH, calculateLauncherState());
+       });
+}
\ No newline at end of file
diff --git a/src/model/AccessibilityLauncherModel.hpp b/src/model/AccessibilityLauncherModel.hpp
new file mode 100644 (file)
index 0000000..c5b10cd
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef ACCESSIBILITY_LAUNCHER_MODEL_HPP
+#define ACCESSIBILITY_LAUNCHER_MODEL_HPP
+
+#include "ObservableProperty.hpp"
+#include "VConf.hpp"
+
+class AccessibilityLauncherModel
+{
+       public:
+       AccessibilityLauncherModel();
+
+       ObservableProperty<bool> state_;
+       ObservableProperty<bool> accessibilityLaunched_;
+       ObservableProperty<bool> screenReaderLaunched_;
+       ObservableProperty<bool> universalSwitchLaunched_;
+
+       private:
+       VConfInterface::CallbackHandle stateHandle_;
+       VConfInterface::CallbackHandle launchedHandle_;
+};
+
+#endif
diff --git a/src/presenter/AccessibilityLauncherPagePresenter.cpp b/src/presenter/AccessibilityLauncherPagePresenter.cpp
new file mode 100644 (file)
index 0000000..dbfa7d5
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2018 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AccessibilityLauncherPagePresenter.hpp"
+
+#include "AccessibilitySettingLog.hpp"
+#include "AppContext.hpp"
+#include "Button.hpp"
+#include "Genlist.hpp"
+#include "Singleton.hpp"
+#include "VConf.hpp"
+#include "setting-accessibility.h"
+#include "utils.hpp"
+
+#include <app.h>
+#include <string>
+#include <vconf.h>
+
+AccessibilityLauncherPagePresenter::AccessibilityLauncherPagePresenter()
+       : ListPresenter("IDS_ACCS_ACCESSIBILITY_LAUNCHER")
+{
+       model_.state_.attach([this](auto val) {
+               groups_[0].items_[0]->title_ = val ? "IDS_ACCS_ACCESSIBILITY_LAUNCHER_ON" : "IDS_ACCS_ACCESSIBILITY_LAUNCHER_OFF";
+               groups_[0].items_[0]->widgetState_ = val;
+       });
+
+       groups_.emplace_back("");
+
+       groups_.back().items_.push_back(std::make_unique<ListItem>(
+               model_.state_.value() ? "IDS_ACCS_ACCESSIBILITY_LAUNCHER_ON" : "IDS_ACCS_ACCESSIBILITY_LAUNCHER_OFF",
+               std::string{},
+               [this](auto item) {
+                       model_.state_ = item->widgetState_.value();
+               },
+               ListItem::WidgetType::toggle));
+       groups_.back().items_.back()->widgetState_ = model_.state_.value();
+
+       groups_.back().items_.push_back(std::make_unique<ListItem>(std::string{}, "IDS_ACCS_ACCESSIBILITY_LAUNCHER_COMMENT"));
+
+       groups_.emplace_back("");
+
+       groups_.back().items_.push_back(std::make_unique<ListItem>("IDS_ST_BODY_ACCESSIBILITY",
+               std::string{},
+               [this](auto item) { model_.accessibilityLaunched_ = item->widgetState_.value(); },
+               ListItem::WidgetType::toggle));
+       groups_.back().items_.back()->enabled_ = groups_[0].items_[0]->widgetState_.value();
+       groups_.back().items_.push_back(std::make_unique<ListItem>("IDS_ST_MBODY_SCREEN_READER_HTTS",
+               std::string{},
+               [this](auto item) { model_.screenReaderLaunched_ = item->widgetState_.value(); },
+               ListItem::WidgetType::toggle));
+       groups_.back().items_.back()->enabled_ = groups_[0].items_[0]->widgetState_.value();
+       groups_.back().items_.push_back(std::make_unique<ListItem>("IDS_ACCS_UNIVERSAL_SWITCH",
+               std::string{},
+               [this](auto item) { model_.universalSwitchLaunched_ = item->widgetState_.value(); },
+               ListItem::WidgetType::toggle));
+       groups_.back().items_.back()->enabled_ = groups_[0].items_[0]->widgetState_.value();
+
+       groups_[0].items_[0]->widgetState_.attach([this](auto val) {
+               for (auto &it : groups_[1].items_)
+                       it->enabled_ = val;
+       });
+}
diff --git a/src/presenter/AccessibilityLauncherPagePresenter.hpp b/src/presenter/AccessibilityLauncherPagePresenter.hpp
new file mode 100644 (file)
index 0000000..465dd55
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2018 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ACCESSIBILITY_LAUNCHER_PAGE_PRESENTER_HPP
+#define ACCESSIBILITY_LAUNCHER_PAGE_PRESENTER_HPP
+
+#include "AccessibilityLauncherModel.hpp"
+#include "ListPresenter.hpp"
+
+#include <vector>
+
+class AccessibilityLauncherPagePresenter : public ListPresenter
+{
+       public:
+       AccessibilityLauncherPagePresenter();
+
+       private:
+       AccessibilityLauncherModel model_;
+};
+
+#endif
diff --git a/src/presenter/ListGroup.cpp b/src/presenter/ListGroup.cpp
new file mode 100644 (file)
index 0000000..0387837
--- /dev/null
@@ -0,0 +1,5 @@
+#include "ListGroup.hpp"
+
+ListGroup::ListGroup(std::string name)
+       : name_(std::move(name))
+{}
\ No newline at end of file
index 3bfb52dfbf3a8780fea2bd6acf98641994d08878..ea065d92039fe41eef6aefa4cb9ac80deb8b86f3 100644 (file)
@@ -3,13 +3,15 @@
 
 #include "ListItem.hpp"
 
+#include <memory>
 #include <string>
 #include <vector>
 
 struct ListGroup
 {
+       ListGroup(std::string name);
        std::string name_;
-       std::vector<ListItem> items_;
+       std::vector<std::unique_ptr<ListItem>> items_;
 };
 
 #endif
\ No newline at end of file
index 4fd9c38348af190d4f81b9fad7495d5c3823c7df..a8a44fd0023703631db532c9df291b9d60ce071d 100644 (file)
@@ -2,16 +2,16 @@
 
 ListItem::ListItem(std::string title,
        std::string description,
-       std::function<void()> onItemSelection,
-       std::function<void()> onWidgetSelection,
+       std::function<void(ListItem *item)> onItemSelection,
        WidgetType type,
+       std::function<void(ListItem *item)> onWidgetSelection,
        bool state,
        std::string iconPath)
        : title_(std::move(title)),
          description_(std::move(description)),
          onItemSelection_(std::move(onItemSelection)),
-         onWidgetSelection_(std::move(onWidgetSelection)),
          widgetType_(type),
+         onWidgetSelection_(std::move(onWidgetSelection)),
          widgetState_(state),
          iconPath_(std::move(iconPath))
-{}
\ No newline at end of file
+{}
index b479b8b205bd9773eda643220665a9e7345cb7a2..32d6ef9ab3591a2c2bbfd8f28c731af2da0382ba 100644 (file)
@@ -1,13 +1,14 @@
 #ifndef LIST_ITEM_HPP
 #define LIST_ITEM_HPP
 
-#include "Observable.hpp"
+#include "ObservableProperty.hpp"
 
 #include <functional>
 #include <string>
 
-struct ListItem : public Observable<>
+struct ListItem
 {
+       public:
        enum class WidgetType
        {
                none,
@@ -19,18 +20,20 @@ struct ListItem : public Observable<>
 
        ListItem(std::string title,
                std::string description,
-               std::function<void()> onItemSelection = {},
-               std::function<void()> onWidgetSelection = {},
+               std::function<void(ListItem *item)> onItemSelection = {},
                WidgetType type = WidgetType::none,
+               std::function<void(ListItem *item)> onWidgetSelection = {},
                bool state = false,
                std::string iconPath = {});
-       std::string title_;
-       std::string description_;
-       std::function<void()> onItemSelection_;
-       std::function<void()> onWidgetSelection_;
-       WidgetType widgetType_ = WidgetType::none;
-       bool widgetState_ = false;
-       std::string iconPath_;
+
+       ObservableProperty<std::string> title_;
+       ObservableProperty<std::string> description_;
+       const std::function<void(ListItem *item)> onItemSelection_;
+       const WidgetType widgetType_ = WidgetType::none;
+       const std::function<void(ListItem *item)> onWidgetSelection_;
+       ObservableProperty<bool> widgetState_ = false;
+       const std::string iconPath_;
+       ObservableProperty<bool> enabled_ = true;
 };
 
 #endif
\ No newline at end of file
index e3e8b28a832cd00455b2a876597f6d1635c158a3..1ebee3131ce650c2ec424bb6cc0a7fdbf0bec1b7 100644 (file)
@@ -3,4 +3,4 @@
 const std::vector<ListGroup> &ListPresenter::getListGroups() const
 {
        return groups_;
-}
\ No newline at end of file
+}
index 21935738c7c36b859940fd99f33b21d720340c04..c2c68ec12779dc077f5d6525540e22ce337bd1be 100644 (file)
@@ -5,17 +5,19 @@
 MainPagePresenter::MainPagePresenter()
        : ListPresenter("IDS_ST_BODY_ACCESSIBILITY")
 {
-       auto group = ListGroup{"IDS_ST_HEADER_VISION"};
-       group.items_.emplace_back("IDS_ST_MBODY_SCREEN_READER_HTTS",
+       groups_.emplace_back("IDS_ST_HEADER_VISION");
+       groups_.back().items_.push_back(std::make_unique<ListItem>(
+               "IDS_ST_MBODY_SCREEN_READER_HTTS",
                "IDS_ST_BODY_OFF",
-               [this]() { screenReaderPage_ = std::make_unique<ScreenReaderPage>(); });
-       group.items_.emplace_back("IDS_ACCS_UNIVERSAL_SWITCH",
+               [this](auto item) { screenReaderPage_ = std::make_unique<ScreenReaderPage>(); }));
+       groups_.back().items_.push_back(std::make_unique<ListItem>(
+               "IDS_ACCS_UNIVERSAL_SWITCH",
                "IDS_ACCS_UNIVERSAL_SWITCH_HINT",
-               [this]() { universalSwitchPage_ = std::make_unique<UniversalSwitchPage>(); });
-       group.items_.emplace_back("IDS_ACCS_ACCESSIBILITY_LAUNCHER",
+               [this](auto item) { universalSwitchPage_ = std::make_unique<UniversalSwitchPage>(); }));
+       groups_.back().items_.push_back(std::make_unique<ListItem>(
+               "IDS_ACCS_ACCESSIBILITY_LAUNCHER",
                "IDS_ACCS_ACCESSIBILITY_LAUNCHER_HINT",
-               [this]() { accessibilityLauncherPage_ = std::make_unique<AccessibilityLauncherPage>(); });
-       groups_.push_back(group);
+               [this](auto item) { Singleton<AppContext>::instance().push(std::make_unique<AccessibilityLauncherPagePresenter>()); }));
 
        onPopCallback_ = [this]() {
                screenReaderStateHandle_ = {};
index b48b02b91a7b1c1eaa4e0e30a3916e22c8277a67..fd1bcdaf25f1ae1e0a604477ae0309a6c666314f 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef MAIN_PAGE_PRESENTER_HPP
 #define MAIN_PAGE_PRESENTER_HPP
 
-#include "AccessibilityLauncherPage.hpp"
+#include "AccessibilityLauncherPagePresenter.hpp"
 #include "ListPresenter.hpp"
 #include "ScreenReaderPage.hpp"
 #include "UniversalSwitchPage.hpp"
@@ -15,7 +15,7 @@ class MainPagePresenter : public ListPresenter
        private:
        std::unique_ptr<ScreenReaderPage> screenReaderPage_;
        std::unique_ptr<UniversalSwitchPage> universalSwitchPage_;
-       std::unique_ptr<AccessibilityLauncherPage> accessibilityLauncherPage_;
+       std::unique_ptr<AccessibilityLauncherPagePresenter> accessibilityLauncherPage_;
        VConfInterface::CallbackHandle screenReaderStateHandle_;
 };
 
index 5d011b01114dbb4246f41cc60dd3fca3482eb391..3661709310f077081ae34ca605ac325f44608679 100644 (file)
@@ -16,14 +16,17 @@ class Observable
        }
 
        protected:
-       void notify()
-       {
-               for (auto &c : onChangeCallbacks_)
-                       if (c)
-                               c();
-       }
+       void notify();
 
        std::vector<std::function<void(ARGS...)>> onChangeCallbacks_;
 };
 
+template <>
+inline void Observable<>::notify()
+{
+       for (auto &c : this->onChangeCallbacks_)
+               if (c)
+                       c();
+}
+
 #endif
\ No newline at end of file
diff --git a/src/utils/ObservableProperty.hpp b/src/utils/ObservableProperty.hpp
new file mode 100644 (file)
index 0000000..906f647
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef OBSERVABLE_PROPERTY_HPP
+#define OBSERVABLE_PROPERTY_HPP
+
+#include "Observable.hpp"
+
+template <typename V>
+class ObservableProperty : public Observable<V>
+{
+       public:
+       ObservableProperty() = default;
+       ObservableProperty(V val)
+               : value_(std::move(val))
+       {}
+
+       V value() const
+       {
+               return value_;
+       }
+
+       ObservableProperty &operator=(V val)
+       {
+               if (value_ == val)
+                       return *this;
+
+               value_ = std::move(val);
+               notify();
+               return *this;
+       }
+
+       protected:
+       void notify()
+       {
+               for (auto &c : this->onChangeCallbacks_)
+                       if (c)
+                               c(value_);
+       }
+
+       V value_{};
+};
+
+#endif
\ No newline at end of file
index 90bb23e9d529bfafd263d937073d57862935f0b8..57138fa1840c4143c6fe77d9ac1ccf0da8afe513 100644 (file)
@@ -21,12 +21,51 @@ ListView::ListView(const NavigationContext &context, Presenter *presenter)
 
 void ListView::addItemsToGenlist()
 {
+       auto wrappedOnItemSelection = [this](GenlistItem *item) {
+               auto search = itemsMapping_.find(item);
+               ASSERT(search != itemsMapping_.end(), "Item not mapped");
+               search->second->widgetState_ = item->getState();
+               if (search->second->onItemSelection_)
+                       search->second->onItemSelection_(search->second);
+       };
+
+       auto wrappedOnWidgetSelection = [this](GenlistItem *item) {
+               auto search = itemsMapping_.find(item);
+               ASSERT(search != itemsMapping_.end(), "Item not mapped");
+               search->second->widgetState_ = item->getState();
+               if (search->second->onWidgetSelection_)
+                       search->second->onWidgetSelection_(search->second);
+       };
+
        for (const auto &g : listPresenter_->getListGroups()) {
-               auto groupItem = genlist_->appendItem({"group_index", g.name_});
+               GenlistItem *groupItem = nullptr;
+               if (!g.name_.empty())
+                       groupItem = genlist_->appendItem({"group_index", g.name_});
 
                for (const auto &it : g.items_) {
-                       auto type = translateType(it.widgetType_);
-                       genlist_->appendItem({"multiline", it.title_, it.description_, [it](auto item) { it.onItemSelection_(); }, [it](auto item) { it.onWidgetSelection_(); }, type}, groupItem);
+                       auto type = translateType(it->widgetType_);
+                       auto style = it->description_.value().empty() ? "type1" : "multiline";
+                       auto genlistItem = genlist_->appendItem({style,
+                                                                                                               it->title_.value(),
+                                                                                                               it->description_.value(),
+                                                                                                               it->onItemSelection_ ? wrappedOnItemSelection : std::function<void(GenlistItem *)>{},
+                                                                                                               it->onWidgetSelection_ ? wrappedOnWidgetSelection : std::function<void(GenlistItem *)>{},
+                                                                                                               type},
+                               groupItem);
+
+                       if (!it->enabled_.value())
+                               genlistItem->disable();
+
+                       itemsMapping_.emplace(genlistItem, it.get());
+                       it->title_.attach([this, gi = genlistItem](auto val) { gi->setText(val); });
+                       it->description_.attach([this, gi = genlistItem](auto val) { gi->setDescription(val); });
+                       it->widgetState_.attach([this, gi = genlistItem](auto val) { gi->setState(val); });
+                       it->enabled_.attach([this, gi = genlistItem](auto val) {
+                               if (val)
+                                       gi->enable();
+                               else
+                                       gi->disable();
+                       });
                }
        }
 }
@@ -51,4 +90,4 @@ GenlistItem::WidgetType ListView::translateType(ListItem::WidgetType t)
        }
        ERROR("Invalid type");
        return {};
-}
\ No newline at end of file
+}
index 5980b38749d28c88c5c3f058bf759c1f75b32c5f..8d42c3b7223681569db16844aa46f3f070dfe150 100644 (file)
@@ -5,6 +5,8 @@
 #include "Presenter.hpp"
 #include "View.hpp"
 
+#include <unordered_map>
+
 class ListView : public View
 {
        public:
@@ -16,6 +18,7 @@ class ListView : public View
 
        ListPresenter *listPresenter_ = nullptr;
        Genlist *genlist_ = nullptr;
+       std::unordered_map<GenlistItem *, ListItem *> itemsMapping_;
 };
 
 #endif
\ No newline at end of file