Add update of GenlistItem fields when text and description are changed
[profile/mobile/apps/native/accessibility-setting.git] / src / UniversalSwitchSettingsPage.cpp
1 /*
2  * Copyright 2018 Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *  http://www.apache.org/licenses/LICENSE-2.0
9
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "UniversalSwitchSettingsPage.hpp"
18
19 #include "Button.hpp"
20 #include "CtxPopup.hpp"
21 #include "Singleton.hpp"
22 #include "VConf.hpp"
23 #include "setting-accessibility.h"
24 #include "utils.hpp"
25
26 #include <app.h>
27 #include <efl_extension.h>
28 #include <sstream>
29
30 #define CTXPOPUP_DATA_AD "__CTXPOPUP_DATA_AD"
31
32 #define RANGE_MIN_AUTO_SCAN_INTERVAL 0.5
33 #define RANGE_MAX_AUTO_SCAN_INTERVAL 9.9
34 #define RANGE_MIN_SCANS_NUM 1
35 #define RANGE_MAX_SCANS_NUM 10
36 #define RANGE_MIN_SCAN_SPEED 1
37 #define RANGE_MAX_SCAN_SPEED 30
38 #define RANGE_MIN_PAUSE_ON_FIRST 0.1
39 #define RANGE_MAX_PAUSE_ON_FIRST 5.0
40 #define RANGE_MIN_TAP_DURATION 0.5
41 #define RANGE_MAX_TAP_DURATION 5.0
42 #define RANGE_MIN_SGL_IACTION_INT 0.1
43 #define RANGE_MAX_SGL_IACTION_INT 2.5
44 #define RANGE_MIN_AUTO_TAP 0.5
45 #define RANGE_MAX_AUTO_TAP 5.0
46 #define RANGE_MIN_AUTO_MOVE_INT 0.1
47 #define RANGE_MAX_AUTO_MOVE_INT 5.0
48
49 #define STEP_AUTO_SCAN_INTERVAL 0.1
50 #define STEP_SCANS_NUM 1
51 #define STEP_SCAN_SPEED 1
52 #define STEP_PAUSE_ON_FIRST 0.1
53 #define STEP_TAP_DURATION 0.1
54 #define STEP_SGL_IACTION_INT 0.1
55 #define STEP_AUTO_TAP 0.1
56 #define STEP_AUTO_MOVE_INT 0.1
57
58 enum class VoiceFeedbackAttribute : int
59 {
60         SPEECH_RATE,
61         VOLUME
62 };
63
64 enum class ManageMenuOption : int
65 {
66         GESTURES,
67         ACTIONS,
68         SETTINGS,
69         RECENT_APPS,
70         HOME_SCREEN,
71         BACK,
72         BUTTONS_AND_KEYS,
73         CONTEXTUAL_MENU
74 };
75
76 using KeyIdPairs = std::vector<std::pair<std::string, unsigned int>>;
77
78 KeyIdPairs cursorColors = {
79         {"IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_CURSOR_CL_RED", 0xff0000ff},
80         {"IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_CURSOR_CL_ORANGE", 0xff0080ff},
81         {"IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_CURSOR_CL_YELLOW", 0xff00ffff},
82         {"IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_CURSOR_CL_GREEN", 0xff00ff00},
83         {"IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_CURSOR_CL_BLUE", 0xffff0000},
84         {"IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_CURSOR_CL_GRAY", 0xff808080},
85 };
86
87 KeyIdPairs mediaLevel = {
88         {"100%", 100},
89         {"87%", 87},
90         {"75%", 75},
91         {"62%", 62},
92         {"50%", 50},
93         {"37%", 37},
94         {"25%", 25},
95         {"12%", 12},
96         {"0%", 0},
97 };
98
99 UniversalSwitchSettingsPage::UniversalSwitchSettingsPage()
100         : context_(Singleton<AppContext>::instance())
101 {
102         auto naviframe = context_.navContext_.getNaviframe();
103         genlist_ = Widget::make<Genlist>(naviframe);
104         genlist_->setMode(ELM_LIST_COMPRESS);
105         genlist_->setStyle("dialogue");
106
107         createSwitchesGroup();
108         createScanningGroup();
109         createAdditionalSettingsGroup();
110         createFeedbackGroup();
111         createManageGroup();
112
113         auto prevBtn = Widget::make<Button>(
114                 naviframe, [naviframe]() { naviframe->popBack(); }, std::string{}, Button::BACK_BUTTON_ARROW_STYLE);
115         naviframe->pushBack("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS", genlist_, []() {}, prevBtn);
116 }
117
118 void UniversalSwitchSettingsPage::createManageGroup()
119 {
120         genlist_->appendItem({"type1",
121                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_MANAGE",
122                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_MANAGE_SUB",
123                 [this](auto item) { this->onManageMenuOptions(); }});
124 }
125
126 void UniversalSwitchSettingsPage::createFeedbackGroup()
127 {
128         genlist_->appendItem({"group_index", "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK"});
129
130         cursorColor_ = genlist_->appendItem({"type1",
131                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_CURSOR_CL",
132                 findCursorColor(),
133                 [this](auto item) {
134                         setValuePage_ = std::make_unique<SetValuePage>(ValueEditorType::RADIOS, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_CURSOR_CL");
135                         setValuePage_->addRadioItemChangedCb([this](auto val) {
136                                 this->cursorColorListItemChangedCb(val);
137                         });
138
139                         for (auto i = 0u; i < cursorColors.size(); i++)
140                                 setValuePage_->addRadioItem(cursorColors[i].first, i, cursorColors[i].second == static_cast<unsigned int>(context_.usScanningProperties.getScanningProperty(Property::CURSOR_COLOR)->getFirstValue<int>()));
141                 }});
142
143         feedbackSound_ = genlist_->appendItem({"type1",
144                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_SOUND",
145                 context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_SOUND)->getState() ? "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_ON" : "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF",
146                 [this](auto item) { this->feedbackSoundCb(); },
147                 [this](auto item) {
148                         context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_SOUND)->setState(item->getState());
149                         item->setDescription(item->getState() ? "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_ON" : "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
150                 },
151                 GenlistItem::WidgetType::toggle});
152         feedbackSound_->setState(context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_SOUND)->getState());
153
154         feedbackVoice_ = genlist_->appendItem({"type1",
155                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_VOICE",
156                 context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_VOICE)->getState() ? "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_ON" : "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF",
157                 [this](auto item) { this->feedbackVoiceCb(); },
158                 [this](auto item) {
159                         context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_VOICE)->setState(item->getState());
160
161                         item->setDescription(item->getState() ? "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_ON" : "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF"); },
162                 GenlistItem::WidgetType::toggle});
163         feedbackVoice_->setState(context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_VOICE)->getState());
164 }
165
166 void UniversalSwitchSettingsPage::createAdditionalSettingsGroup()
167 {
168         genlist_->appendItem({"group_index", "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_ADD_SETTINGS"});
169         auto pauseOnFirstValue = context_.usScanningProperties.getScanningProperty(Property::PAUSE_ON_FIRST_ITEM)->getFirstValue<double>();
170         auto str = getValueUnitText(NULL,
171                 &pauseOnFirstValue,
172                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
173                 !context_.usScanningProperties.getScanningProperty(Property::PAUSE_ON_FIRST_ITEM)->getState(),
174                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
175
176         pauseOnFirst_ = genlist_->appendItem({"type1",
177                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_ADD_SETTINGS_PAUSE_ON_FIRST",
178                 str,
179                 [this](auto item) {
180                         setValuePage_ = std::make_unique<SetValuePage>(ValueEditorType::NUMERIC_SWITCH, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_ADD_SETTINGS_PAUSE_ON_FIRST");
181                         setValuePage_->setSwitch(context_.usScanningProperties.getScanningProperty(Property::PAUSE_ON_FIRST_ITEM)->getState());
182                         setValuePage_->addValueChangedCb([this](auto val) {
183                                 this->pauseOnFirstValueChangedCb(val);
184                         });
185                         setValuePage_->addSwitchChangedCb([this](auto state) {
186                                 this->pauseOnFirstSwitchChangedCb(state);
187                         });
188                         //FIXME: below description is not displayed at runtime
189                         auto totalPauseOnFirstItem = context_.usScanningProperties.getScanningProperty(Property::AUTO_SCAN)->getFirstValue<double>() + context_.usScanningProperties.getScanningProperty(Property::PAUSE_ON_FIRST_ITEM)->getFirstValue<double>();
190                         setValuePage_->setDescription(TranslatedString::create("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SET_VALUE_DESC_PAUSE_ON_FIRST", context_.usScanningProperties.getScanningProperty(Property::AUTO_SCAN)->getFirstValue<double>(), totalPauseOnFirstItem).c_str());
191                         setValuePage_->setRange(RANGE_MIN_PAUSE_ON_FIRST, RANGE_MAX_PAUSE_ON_FIRST, STEP_PAUSE_ON_FIRST);
192                         setValuePage_->setValue(context_.usScanningProperties.getScanningProperty(Property::PAUSE_ON_FIRST_ITEM)->getFirstValue<double>(), "seconds"); },
193                 [this](auto item) {
194                         context_.usScanningProperties.getScanningProperty(Property::PAUSE_ON_FIRST_ITEM)->setState(item->getState());
195                         auto pauseOnFirstValue = context_.usScanningProperties.getScanningProperty(Property::PAUSE_ON_FIRST_ITEM)->getFirstValue<double>();
196                         auto str = getValueUnitText(NULL,
197                                 &pauseOnFirstValue,
198                                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
199                                 !item->getState(),
200                                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
201                         item->setDescription(str); },
202                 GenlistItem::WidgetType::toggle});
203         if (context_.usScanningProperties.getScanningProperty(Property::PAUSE_ON_FIRST_ITEM)->getState()) {
204                 pauseOnFirst_->setState(true);
205                 auto pauseOnFirstValue = context_.usScanningProperties.getScanningProperty(Property::PAUSE_ON_FIRST_ITEM)->getFirstValue<double>();
206                 auto str = getValueUnitText(NULL,
207                         &pauseOnFirstValue,
208                         "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
209                         false,
210                         "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
211                 pauseOnFirst_->setDescription(str);
212         }
213         if (!context_.usScanningProperties.getScanningProperty(Property::AUTO_SCAN)->getState())
214                 pauseOnFirst_->disable();
215         auto tapDurationValue = context_.usScanningProperties.getScanningProperty(Property::TAP_DURATION)->getFirstValue<double>();
216         str = getValueUnitText(NULL, &tapDurationValue, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS", !context_.usScanningProperties.getScanningProperty(Property::TAP_DURATION)->getState(), "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
217
218         tapDuration_ = genlist_->appendItem({"type1",
219                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_ADD_SETTINGS_TAP_DURATION",
220                 str,
221                 [this](auto item) {
222                         setValuePage_ = std::make_unique<SetValuePage>(ValueEditorType::NUMERIC_SWITCH, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_ADD_SETTINGS_TAP_DURATION");
223                         setValuePage_->setSwitch(context_.usScanningProperties.getScanningProperty(Property::TAP_DURATION)->getState());
224                         setValuePage_->addValueChangedCb([this](auto val) {
225                                 this->tapDurationValueChangedCb(val);
226                         });
227                         setValuePage_->addSwitchChangedCb([this](auto state) {
228                                 this->tapDurationSwitchChangedCb(state);
229                         });
230                         setValuePage_->setDescription("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SET_VALUE_DESC_TAP_DURATION");
231                         setValuePage_->setRange(RANGE_MIN_TAP_DURATION, RANGE_MAX_TAP_DURATION, STEP_TAP_DURATION);
232                         setValuePage_->setValue(context_.usScanningProperties.getScanningProperty(Property::TAP_DURATION)-> getFirstValue<double>(), "seconds"); },
233                 [this](auto item) {
234                         context_.usScanningProperties.getScanningProperty(Property::TAP_DURATION)->setState(item->getState());
235                         auto tapDurationValue = context_.usScanningProperties.getScanningProperty(Property::TAP_DURATION)-> getFirstValue<double>();
236                         auto str = getValueUnitText(NULL,
237                                 &tapDurationValue,
238                                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
239                                 !item->getState(),
240                                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
241                         item->setDescription(str); },
242                 GenlistItem::WidgetType::toggle});
243
244         if (context_.usScanningProperties.getScanningProperty(Property::TAP_DURATION)->getState()) {
245                 tapDuration_->setState(true);
246                 auto tapDurationValue = context_.usScanningProperties.getScanningProperty(Property::TAP_DURATION)->getFirstValue<double>();
247                 auto str = getValueUnitText(NULL,
248                         &tapDurationValue,
249                         "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
250                         false,
251                         "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
252                 tapDuration_->setDescription(str);
253         }
254         auto sglIntInterval = context_.usScanningProperties.getScanningProperty(Property::SINGLE_INTERACTION_INTERVAL)->getFirstValue<double>();
255         str = getValueUnitText(NULL, &sglIntInterval, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS", !context_.usScanningProperties.getScanningProperty(Property::SINGLE_INTERACTION_INTERVAL)->getState(), "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
256
257         singleInteractionInterval_ = genlist_->appendItem({"type1",
258                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_ADD_SETTINGS_SGL_IACTION_INT",
259                 str,
260                 [this](auto item) {
261                         setValuePage_ = std::make_unique<SetValuePage>(ValueEditorType::NUMERIC_SWITCH, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_ADD_SETTINGS_SGL_IACTION_INT");
262                         setValuePage_->setSwitch(context_.usScanningProperties.getScanningProperty(Property::SINGLE_INTERACTION_INTERVAL)->getState());
263                         setValuePage_->addValueChangedCb([this](auto val) {
264                                 this->sglInactionIntervalValueChangedCb(val);
265                         });
266                         setValuePage_->addSwitchChangedCb([this](auto state) {
267                                 this->sglInactionIntervalSwitchChangedCb(state);
268                         });
269                         setValuePage_->setDescription("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SET_VALUE_DESC_SGL_IACTION_INT");
270                         setValuePage_->setRange(RANGE_MIN_SGL_IACTION_INT, RANGE_MAX_SGL_IACTION_INT, STEP_SGL_IACTION_INT);
271                         setValuePage_->setValue(context_.usScanningProperties.getScanningProperty(Property::SINGLE_INTERACTION_INTERVAL)->getFirstValue<double>(), "seconds"); },
272                 [this](auto item) {
273                         context_.usScanningProperties.getScanningProperty(Property::SINGLE_INTERACTION_INTERVAL)->setState(item->getState());
274                         auto sglIntInterval = context_.usScanningProperties.getScanningProperty(Property::SINGLE_INTERACTION_INTERVAL)->getFirstValue<double>();
275                         auto str = getValueUnitText(NULL,
276                                 &sglIntInterval,
277                                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
278                                 !item->getState(),
279                                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
280                         item->setDescription(str); },
281                 GenlistItem::WidgetType::toggle});
282
283         if (context_.usScanningProperties.getScanningProperty(Property::SINGLE_INTERACTION_INTERVAL)->getState()) {
284                 singleInteractionInterval_->setState(true);
285                 auto sglIntInterval = context_.usScanningProperties.getScanningProperty(Property::SINGLE_INTERACTION_INTERVAL)->getFirstValue<double>();
286                 str = getValueUnitText(NULL,
287                         &sglIntInterval,
288                         "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
289                         false,
290                         "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
291                 singleInteractionInterval_->setDescription(str);
292         }
293         auto autoTapValue = context_.usScanningProperties.getScanningProperty(Property::AUTO_TAP)->getFirstValue<double>();
294         str = getValueUnitText(NULL, &autoTapValue, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS", !context_.usScanningProperties.getScanningProperty(Property::AUTO_TAP)->getState(), "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
295
296         autoTap_ = genlist_->appendItem({"type1",
297                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_ADD_SETTINGS_AUTO_TAP",
298                 str,
299                 [this](auto item) {
300                         setValuePage_ = std::make_unique<SetValuePage>(ValueEditorType::NUMERIC_SWITCH, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_ADD_SETTINGS_AUTO_TAP");
301                         setValuePage_->setSwitch(context_.usScanningProperties.getScanningProperty(Property::AUTO_TAP)->getState());
302                         setValuePage_->addSwitchChangedCb([this](auto val) {
303                                 this->autoTapSwitchChangedCb(val);
304                         });
305                         setValuePage_->addValueChangedCb([this](auto val) {
306                                 this->autoTapValueChangedCb(val);
307                         });
308                         setValuePage_->setDescription("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SET_VALUE_DESC_AUTO_TAP");
309                         setValuePage_->setRange(RANGE_MIN_AUTO_TAP, RANGE_MAX_AUTO_TAP, STEP_AUTO_TAP);
310                         setValuePage_->setValue(context_.usScanningProperties.getScanningProperty(Property::AUTO_TAP)->getFirstValue<double>(), "seconds"); },
311                 [this](auto item) {
312                         context_.usScanningProperties.getScanningProperty(Property::AUTO_TAP)->setState(item->getState());
313                         auto autoTapValue = context_.usScanningProperties.getScanningProperty(Property::AUTO_TAP)->getFirstValue<double>();
314                         auto str = getValueUnitText(NULL,
315                                 &autoTapValue,
316                                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
317                                 !item->getState(),
318                                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
319                         item->setDescription(str); },
320                 GenlistItem::WidgetType::toggle});
321
322         if (context_.usScanningProperties.getScanningProperty(Property::AUTO_TAP)->getState()) {
323                 autoTap_->setState(true);
324                 auto autoTapValue = context_.usScanningProperties.getScanningProperty(Property::AUTO_TAP)->getFirstValue<double>();
325                 auto str = getValueUnitText(NULL,
326                         &autoTapValue,
327                         "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
328                         false,
329                         "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
330                 autoTap_->setDescription(str);
331         }
332         auto moveIntervalValue = context_.usScanningProperties.getScanningProperty(Property::AUTO_MOVE_INTERVAL)->getFirstValue<double>();
333         str = getValueUnitText(NULL, &moveIntervalValue, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS", !context_.usScanningProperties.getScanningProperty(Property::AUTO_MOVE_INTERVAL)->getState(), "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
334
335         autoMoveInterval_ = genlist_->appendItem({"type1",
336                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_ADD_SETTINGS_AUTO_MOVE_INT",
337                 str,
338                 [this](auto item) {
339                         setValuePage_ = std::make_unique<SetValuePage>(ValueEditorType::NUMERIC_SWITCH, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_ADD_SETTINGS_AUTO_MOVE_INT");
340                         setValuePage_->setSwitch(context_.usScanningProperties.getScanningProperty(Property::AUTO_MOVE_INTERVAL)->getState());
341                         setValuePage_->addValueChangedCb([this](auto val) {
342                                 this->autoMoveIntervalValueChangedCb(val);
343                         });
344                         setValuePage_->addSwitchChangedCb([this](auto state) {
345                                 this->autoMoveIntervalSwitchChangedCb(state);
346                         });
347                         setValuePage_->setDescription("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SET_VALUE_DESC_AUTO_MOVE_INT");
348                         setValuePage_->setRange(RANGE_MIN_AUTO_MOVE_INT, RANGE_MAX_AUTO_MOVE_INT, STEP_AUTO_MOVE_INT);
349                         setValuePage_->setValue(context_.usScanningProperties.getScanningProperty(Property::AUTO_MOVE_INTERVAL)->getFirstValue<double>(), "seconds"); },
350                 [this](auto item) {
351                         context_.usScanningProperties.getScanningProperty(Property::AUTO_MOVE_INTERVAL)->setState(item->getState());
352                         auto moveIntervalValue = context_.usScanningProperties.getScanningProperty(Property::AUTO_MOVE_INTERVAL)->getFirstValue<double>();
353                         auto str = getValueUnitText(NULL, &moveIntervalValue, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
354                                                                                 !item->getState(), "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
355                         item->setDescription(str); },
356                 GenlistItem::WidgetType::toggle});
357         if (context_.usScanningProperties.getScanningProperty(Property::AUTO_MOVE_INTERVAL)->getState()) {
358                 autoMoveInterval_->setState(true);
359                 auto moveIntervalValue = context_.usScanningProperties.getScanningProperty(Property::AUTO_MOVE_INTERVAL)->getFirstValue<double>();
360                 auto str = getValueUnitText(NULL,
361                         &moveIntervalValue,
362                         "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
363                         !context_.usScanningProperties.getScanningProperty(Property::AUTO_MOVE_INTERVAL)->getState(),
364                         "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
365                 autoMoveInterval_->setDescription(str);
366         }
367         if (context_.usScanningProperties.getScanningProperty(Property::AUTO_SCAN)->getState())
368                 autoMoveInterval_->disable();
369
370         auto item = genlist_->appendItem({"multiline",
371                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_ADD_SETTINGS_AUTO_TAP_KBD",
372                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_ADD_SETTINGS_AUTO_TAP_KBD_SUB",
373                 [this](auto item) {
374                         context_.usScanningProperties.getScanningProperty(Property::KEYBOARD_AUTO_TAP)->setState(item->getState());
375                 },
376                 GenlistItem::WidgetType::toggle});
377         item->setState(context_.usScanningProperties.getScanningProperty(Property::KEYBOARD_AUTO_TAP)->getState());
378 }
379
380 void UniversalSwitchSettingsPage::createScanningGroup()
381 {
382         genlist_->appendItem({"group_index", "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING"});
383
384         auto item = genlist_->appendItem({"type1",
385                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_AUTO_SCAN",
386                 {},
387                 [this](auto item) {
388                         auto state = item->getState();
389                         context_.usScanningProperties.getScanningProperty(Property::AUTO_SCAN)->setState(state);
390
391                         if (state) {
392                                 pauseOnFirst_->enable();
393                                 autoMoveInterval_->disable();
394                                 autoScanInterval_->enable();
395                                 scansNum_->enable();
396                         } else {
397                                 pauseOnFirst_->disable();
398                                 autoMoveInterval_->enable();
399                                 autoScanInterval_->disable();
400                                 scansNum_->disable();
401                         }
402                 },
403                 GenlistItem::WidgetType::toggle});
404         if (context_.usScanningProperties.getScanningProperty(Property::AUTO_SCAN)->getState())
405                 item->setState(true);
406         auto autoScanInt = context_.usScanningProperties.getScanningProperty(Property::AUTO_SCAN)->getFirstValue<double>();
407         auto str = getValueUnitText(NULL, &autoScanInt, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS", false, {});
408         autoScanInterval_ = genlist_->appendItem({"type1",
409                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_AUTO_SCAN_INT",
410                 str,
411                 [this](auto item) {
412                         setValuePage_ = std::make_unique<SetValuePage>(
413                                 ValueEditorType::NUMERIC, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_AUTO_SCAN_INT");
414                         setValuePage_->addValueChangedCb([this](auto val) { this->autoScanIntervalChangedCb(val); });
415                         setValuePage_->setDescription("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SET_VALUE_DESC_AUTO_SCAN_INT");
416                         setValuePage_->setRange(RANGE_MIN_AUTO_SCAN_INTERVAL, RANGE_MAX_AUTO_SCAN_INTERVAL, STEP_AUTO_SCAN_INTERVAL);
417                         setValuePage_->setValue(context_.usScanningProperties.getScanningProperty(Property::AUTO_SCAN)->getFirstValue<double>(), "seconds");
418                 }});
419         if (!context_.usScanningProperties.getScanningProperty(Property::AUTO_SCAN)->getState())
420                 autoScanInterval_->disable();
421
422         scansNum_ = genlist_->appendItem({"type1",
423                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_NUM_OF_SCANS",
424                 std::to_string(context_.usScanningProperties.getScanningProperty(Property::AUTO_SCAN)->getSecondValue<int>()),
425                 [this](auto item) {
426                         setValuePage_ = std::make_unique<SetValuePage>(ValueEditorType::NUMERIC, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_NUM_OF_SCANS");
427                         setValuePage_->addValueChangedCb([this](auto val) { this->scanNumberChangedCb(val); });
428                         setValuePage_->setDescription("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SET_VALUE_DESC_NUM_OF_SCANS");
429                         setValuePage_->setRange(RANGE_MIN_SCANS_NUM, RANGE_MAX_SCANS_NUM, STEP_SCANS_NUM);
430                         setValuePage_->setValue(context_.usScanningProperties.getScanningProperty(Property::AUTO_SCAN)->getSecondValue<int>(), "times");
431                 }});
432         if (!context_.usScanningProperties.getScanningProperty(Property::AUTO_SCAN)->getState())
433                 scansNum_->disable();
434
435         scanMethod_ = genlist_->appendItem({"type1",
436                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_SCAN_METHOD",
437                 getScanMethodText(context_.usScanningProperties.getScanningProperty(Property::SCAN_METHOD)->getFirstValue<ScanMethod>()),
438                 [this](auto item) {
439                         this->createScanMethodCtxPopup();
440                 }});
441
442         scanDirection_ = genlist_->appendItem({"type1",
443                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_SCAN_DIR",
444                 getScanDirectionText(context_.usScanningProperties.getScanningProperty(Property::SCAN_DIRECTION)->getFirstValue<ScanDirection>()),
445                 [this](auto item) {
446                         this->createScanDirectionCtxPopup();
447                 }});
448         scanSpeed_ = genlist_->appendItem({"type1",
449                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_PT_SPEED",
450                 std::to_string(context_.usScanningProperties.getScanningProperty(Property::POINT_SCAN_SPEED)->getFirstValue<int>()),
451                 [this](auto item) {
452                         setValuePage_ = std::make_unique<SetValuePage>(ValueEditorType::NUMERIC, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_PT_SPEED");
453                         setValuePage_->addValueChangedCb([this](auto val) { this->scanSpeedChangedCb(val); });
454                         setValuePage_->setDescription("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SET_VALUE_DESC_SCAN_SPEED");
455                         setValuePage_->setRange(RANGE_MIN_SCAN_SPEED, RANGE_MAX_SCAN_SPEED, STEP_SCAN_SPEED);
456                         setValuePage_->setValue(context_.usScanningProperties.getScanningProperty(Property::POINT_SCAN_SPEED)->getFirstValue<int>(), "");
457                 }});
458 }
459
460 void UniversalSwitchSettingsPage::createSwitchesGroup()
461 {
462         switchesItem_ = genlist_->appendItem({"type1",
463                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SWITCHES",
464                 {},
465                 [this](auto item) {
466                         switchesPage_ = std::make_unique<SwitchesPage>();
467                         switchesPage_->attachCallback(updateSwitchesCount, this);
468                 }});
469         updateSwitchesCount(this);
470 }
471
472 TranslatedString UniversalSwitchSettingsPage::getScanDirectionText(ScanDirection direction)
473 {
474         switch (direction) {
475         case ScanDirection::TO_BOTTOM:
476                 return "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_SCAN_DIR_TB";
477         case ScanDirection::TO_TOP:
478                 return "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_SCAN_DIR_BT";
479         default:
480                 return "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_UNDEFINED";
481         }
482 }
483
484 TranslatedString UniversalSwitchSettingsPage::getScanMethodText(ScanMethod method)
485 {
486         switch (method) {
487         case ScanMethod::POINT:
488                 return "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_SCAN_METHOD_POINT";
489         case ScanMethod::ROW:
490                 return "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_SCAN_METHOD_ROW";
491         default:
492                 return "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_UNDEFINED";
493         }
494 }
495
496 TranslatedString UniversalSwitchSettingsPage::getValueUnitText(int *ivalue, double *dvalue, const TranslatedString &units, bool def_trigger, const TranslatedString &def)
497 {
498         if (def_trigger)
499                 return def;
500
501         std::stringstream ss;
502
503         if (ivalue) {
504                 ss << *ivalue;
505         } else if (dvalue) {
506                 ss.precision(1);
507                 ss << std::fixed << *dvalue;
508         }
509
510         if (!units.empty())
511                 ss << " " << units.str();
512
513         return ss.str();
514 }
515
516 void UniversalSwitchSettingsPage::updateSwitchesCount(void *data)
517 {
518         RETURN_IF(!data, "Input argument is NULL");
519         auto self = static_cast<UniversalSwitchSettingsPage *>(data);
520
521         int switch_count = setting_accessibility_universal_switch_dbus_config_get_switch_count(&self->context_.config);
522
523         self->switchesItem_->setDescription(getValueUnitText(&switch_count, NULL, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SWITCHES", false, {}));
524 }
525
526 void UniversalSwitchSettingsPage::feedbackVoiceCb()
527 {
528         nestedSetValuePage_ = std::make_unique<SetValuePage>(
529                 ValueEditorType::LIST_SWITCH, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_VOICE");
530         nestedSetValuePage_->setSwitch(context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_VOICE)->getState());
531         nestedSetValuePage_->setDescription("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SET_VALUE_DESC_FEEDBACK_VOICE");
532         nestedSetValuePage_->addSwitchChangedCb([this](auto state) {
533                 feedbackVoice_->setDescription(
534                         state ? "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_ON" : "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
535                 feedbackVoice_->setState(state);
536                 context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_VOICE)->setState(state);
537         });
538         auto nestedSetValuePagePtr = nestedSetValuePage_.get();
539         context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_VOICE)->registerOnValueChangeCallback([this, nestedSetValuePagePtr](ScanningProperty *self) {
540                 nestedSetValuePagePtr->setCheckState(self->getState());
541         });
542
543         std::string str = std::to_string(static_cast<int>(context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_VOICE)->getFirstValue<double>() * 100)) + "%";
544         feedbackVoiceSpeechRate_ = nestedSetValuePage_->addRadioListItem(
545                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_VOICE_SPEECH_RATE",
546                 str.c_str(),
547                 static_cast<int>(VoiceFeedbackAttribute::SPEECH_RATE));
548
549         str = std::to_string(static_cast<int>(context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_VOICE)->getSecondValue<double>() * 100)) + "%";
550         feedbackVoiceSpeechVolume_ = nestedSetValuePage_->addRadioListItem(
551                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_VOICE_SPEECH_VOLUME",
552                 str.c_str(),
553                 static_cast<int>(VoiceFeedbackAttribute::VOLUME));
554
555         nestedSetValuePage_->addListItemOptionsRequestCb([this](auto val) { this->feedbackVoiceItemOptionsRequestCb(val); });
556 }
557
558 void UniversalSwitchSettingsPage::feedbackVoiceItemOptionsRequestCb(int option_id)
559 {
560         auto selValue = 0;
561         auto feedbackType = static_cast<VoiceFeedbackAttribute>(option_id);
562         if (feedbackType == VoiceFeedbackAttribute::SPEECH_RATE) {
563                 selValue = static_cast<int>(context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_VOICE)->getFirstValue<double>() * 100);
564                 setValuePage_ = std::make_unique<SetValuePage>(ValueEditorType::RADIOS, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_VOICE_SPEECH_RATE");
565                 setValuePage_->addRadioItemChangedCb([this](auto val) { this->feedbackVoiceSpeechRateChangedCb(val); });
566         } else if (feedbackType == VoiceFeedbackAttribute::VOLUME) {
567                 selValue = static_cast<int>(context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_VOICE)->getSecondValue<double>() * 100);
568                 setValuePage_ = std::make_unique<SetValuePage>(ValueEditorType::RADIOS, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_VOICE_SPEECH_VOLUME");
569                 setValuePage_->addRadioItemChangedCb([this](auto val) { this->feedbackVoiceSpeechVolumeChangedCb(val); });
570         } else {
571                 DEBUG("Wrong voice feedback attribute");
572                 return;
573         }
574
575         for (auto i = 0u; i < mediaLevel.size(); i++)
576                 setValuePage_->addRadioItem(mediaLevel[i].first, i, mediaLevel[i].second == static_cast<unsigned int>(selValue));
577 }
578
579 void UniversalSwitchSettingsPage::feedbackVoiceSpeechVolumeChangedCb(size_t item_id)
580 {
581         ASSERT(item_id < mediaLevel.size(), "Invalid item_id");
582
583         double media_level = mediaLevel[item_id].second / 100.0;
584         context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_VOICE)->setSecondValue(media_level);
585
586         feedbackVoiceSpeechVolume_->setDescription(mediaLevel[item_id].first);
587 }
588
589 void UniversalSwitchSettingsPage::feedbackVoiceSpeechRateChangedCb(size_t item_id)
590 {
591         ASSERT(item_id < mediaLevel.size(), "Invalid item_id");
592
593         double media_level = mediaLevel[item_id].second / 100.0;
594         context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_VOICE)->setFirstValue(media_level);
595
596         feedbackVoiceSpeechRate_->setDescription(mediaLevel[item_id].first);
597 }
598
599 void UniversalSwitchSettingsPage::feedbackSoundCb()
600 {
601         std::string str = std::to_string(static_cast<int>((context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_SOUND)->getFirstValue<double>() * 100))) + "%";
602
603         nestedSetValuePage_ = std::make_unique<SetValuePage>(
604                 ValueEditorType::LIST_SWITCH, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_SOUND");
605         nestedSetValuePage_->setSwitch(context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_SOUND)->getState());
606         nestedSetValuePage_->setDescription("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SET_VALUE_DESC_FEEDBACK_SOUND");
607         nestedSetValuePage_->addSwitchChangedCb([this](auto state) { this->feedbackSoundSwitchChangedCb(state); });
608         feedbackSoundVolume_ = nestedSetValuePage_->addRadioListItem("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_SOUND_VOLUME", str.c_str(), 0);
609         nestedSetValuePage_->addListItemOptionsRequestCb([this](auto val) { this->feedbackSoundItemOptionsRequestCb(val); });
610         auto nestedSetValuePagePtr = nestedSetValuePage_.get();
611         context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_SOUND)->registerOnValueChangeCallback([this, nestedSetValuePagePtr](ScanningProperty *self) {
612                 nestedSetValuePagePtr->setCheckState(self->getState());
613         });
614 }
615
616 void UniversalSwitchSettingsPage::feedbackSoundItemOptionsRequestCb(int option_id)
617 {
618         setValuePage_ = std::make_unique<SetValuePage>(ValueEditorType::RADIOS, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_FEEDBACK_SOUND_VOLUME");
619         setValuePage_->addRadioItemChangedCb([this](auto val) { this->feedbackSoundVolumeChangedCb(val); });
620
621         for (auto i = 0u; i < mediaLevel.size(); i++)
622                 setValuePage_->addRadioItem(
623                         mediaLevel[i].first, i, mediaLevel[i].second == static_cast<unsigned int>(context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_SOUND)->getFirstValue<double>() * 100));
624 }
625
626 void UniversalSwitchSettingsPage::feedbackSoundVolumeChangedCb(size_t item_id)
627 {
628         ASSERT(item_id < mediaLevel.size(), "Invalid item_id");
629
630         double media_level = mediaLevel[item_id].second / 100.0;
631         context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_SOUND)->setFirstValue(media_level);
632
633         feedbackSoundVolume_->setDescription(mediaLevel[item_id].first);
634 }
635
636 void UniversalSwitchSettingsPage::feedbackSoundSwitchChangedCb(bool state)
637 {
638         context_.usScanningProperties.getScanningProperty(Property::FEEDBACK_SOUND)->setState(state);
639         feedbackSound_->setState(state);
640         feedbackSound_->setDescription(state ? "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_ON" : "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
641 }
642
643 void UniversalSwitchSettingsPage::cursorColorListItemChangedCb(size_t item_id)
644 {
645         ASSERT(item_id < cursorColors.size(), "Invalid cursor color id");
646
647         context_.usScanningProperties.getScanningProperty(Property::CURSOR_COLOR)->setFirstValue<int>(cursorColors[item_id].second);
648         cursorColor_->setDescription(cursorColors[item_id].first);
649 }
650
651 void UniversalSwitchSettingsPage::autoMoveIntervalSwitchChangedCb(bool state)
652 {
653         context_.usScanningProperties.getScanningProperty(Property::AUTO_MOVE_INTERVAL)->setState(state);
654         autoMoveInterval_->setState(state);
655         auto moveIntervalValue = context_.usScanningProperties.getScanningProperty(Property::AUTO_MOVE_INTERVAL)->getFirstValue<double>();
656         auto str = getValueUnitText(NULL,
657                 &moveIntervalValue,
658                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
659                 !context_.usScanningProperties.getScanningProperty(Property::AUTO_MOVE_INTERVAL)->getState(),
660                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
661         autoMoveInterval_->setDescription(str);
662 }
663
664 void UniversalSwitchSettingsPage::autoTapSwitchChangedCb(bool state)
665 {
666         context_.usScanningProperties.getScanningProperty(Property::AUTO_TAP)->setState(state);
667         autoTap_->setState(state);
668         auto autoTapValue = context_.usScanningProperties.getScanningProperty(Property::AUTO_TAP)->getFirstValue<double>();
669         auto str = getValueUnitText(NULL,
670                 &autoTapValue,
671                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
672                 !state,
673                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
674         autoTap_->setDescription(str);
675 }
676
677 void UniversalSwitchSettingsPage::autoTapValueChangedCb(double value)
678 {
679         context_.usScanningProperties.getScanningProperty(Property::AUTO_TAP)->setFirstValue(value);
680         auto str = getValueUnitText(NULL,
681                 &value,
682                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
683                 !context_.usScanningProperties.getScanningProperty(Property::AUTO_TAP)->getState(),
684                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
685         autoTap_->setDescription(str);
686 }
687
688 void UniversalSwitchSettingsPage::sglInactionIntervalSwitchChangedCb(bool state)
689 {
690         context_.usScanningProperties.getScanningProperty(Property::SINGLE_INTERACTION_INTERVAL)->setState(state);
691         singleInteractionInterval_->setState(state);
692         auto sglIntInterval = context_.usScanningProperties.getScanningProperty(Property::SINGLE_INTERACTION_INTERVAL)->getFirstValue<double>();
693         auto str = getValueUnitText(NULL,
694                 &sglIntInterval,
695                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
696                 !state,
697                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
698         singleInteractionInterval_->setDescription(str);
699 }
700
701 void UniversalSwitchSettingsPage::sglInactionIntervalValueChangedCb(double value)
702 {
703         context_.usScanningProperties.getScanningProperty(Property::SINGLE_INTERACTION_INTERVAL)->setFirstValue(value);
704         auto str = getValueUnitText(NULL, &value, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS", !context_.usScanningProperties.getScanningProperty(Property::SINGLE_INTERACTION_INTERVAL)->getState(), "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
705         singleInteractionInterval_->setDescription(str);
706 }
707
708 void UniversalSwitchSettingsPage::tapDurationSwitchChangedCb(bool state)
709 {
710         context_.usScanningProperties.getScanningProperty(Property::TAP_DURATION)->setState(state);
711         tapDuration_->setState(state);
712         auto tapDurationValue = context_.usScanningProperties.getScanningProperty(Property::TAP_DURATION)->getFirstValue<double>();
713         auto str = getValueUnitText(NULL,
714                 &tapDurationValue,
715                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
716                 !state,
717                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
718         tapDuration_->setDescription(str);
719 }
720
721 void UniversalSwitchSettingsPage::tapDurationValueChangedCb(double value)
722 {
723         context_.usScanningProperties.getScanningProperty(Property::TAP_DURATION)->setFirstValue(value);
724         auto str = getValueUnitText(NULL,
725                 &value,
726                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
727                 !context_.usScanningProperties.getScanningProperty(Property::TAP_DURATION)->getState(),
728                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
729         tapDuration_->setDescription(str);
730 }
731
732 void UniversalSwitchSettingsPage::pauseOnFirstSwitchChangedCb(bool state)
733 {
734         context_.usScanningProperties.getScanningProperty(Property::PAUSE_ON_FIRST_ITEM)->setState(state);
735         pauseOnFirst_->setState(state);
736         auto pauseOnFirstValue = context_.usScanningProperties.getScanningProperty(Property::PAUSE_ON_FIRST_ITEM)->getFirstValue<double>();
737         auto str = getValueUnitText(NULL,
738                 &pauseOnFirstValue,
739                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
740                 !state,
741                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
742         pauseOnFirst_->setDescription(str);
743 }
744
745 void UniversalSwitchSettingsPage::pauseOnFirstValueChangedCb(double value)
746 {
747         context_.usScanningProperties.getScanningProperty(Property::PAUSE_ON_FIRST_ITEM)->setFirstValue(value);
748         auto str = getValueUnitText(NULL,
749                 &value,
750                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
751                 !context_.usScanningProperties.getScanningProperty(Property::PAUSE_ON_FIRST_ITEM)->getState(),
752                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
753         pauseOnFirst_->setDescription(str);
754 }
755
756 void UniversalSwitchSettingsPage::scanSpeedChangedCb(double value)
757 {
758         // TODO change type to avoid below cast
759         context_.usScanningProperties.getScanningProperty(Property::POINT_SCAN_SPEED)->setFirstValue<int>(value);
760         scanSpeed_->setDescription(std::to_string(static_cast<int>(value)));
761 }
762
763 void UniversalSwitchSettingsPage::createScanDirectionCtxPopup()
764 {
765         auto naviframe = context_.navContext_.getNaviframe();
766         auto ctxPopup = Widget::make<CtxPopup>(naviframe, true);
767         auto removeCb = [naviframe, ctxPopup]() { naviframe->removeChild(ctxPopup); };
768         ctxPopup->setEvasSmartCallback("dismissed", removeCb);
769         ctxPopup->setEextEventCallback(EEXT_CALLBACK_BACK, removeCb);
770
771         ctxPopup->addItem("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_SCAN_DIR_TB", [this, removeCb]() {
772                 scanDirectionCtxPopupItemClicked(ScanDirection::TO_BOTTOM);
773                 removeCb();
774         });
775         ctxPopup->addItem("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_SCAN_DIR_BT", [this, removeCb]() {
776                 scanDirectionCtxPopupItemClicked(ScanDirection::TO_TOP);
777                 removeCb();
778         });
779
780         // TODO use real genlistitem position instead click position
781         int y = 0;
782         evas_pointer_output_xy_get(evas_object_evas_get(context_.navContext_.getWindow()->getObject()), NULL, &y);
783
784         auto geometry = ctxPopup->getGeometry();
785         ctxPopup->setPosition({-1, y + geometry.size.height / 2});
786 }
787
788 void UniversalSwitchSettingsPage::scanDirectionCtxPopupItemClicked(ScanDirection scan_dir)
789 {
790         context_.usScanningProperties.getScanningProperty(Property::SCAN_DIRECTION)->setFirstValue(scan_dir);
791         scanDirection_->setDescription(getScanDirectionText(scan_dir));
792 }
793
794 void UniversalSwitchSettingsPage::createScanMethodCtxPopup()
795 {
796         auto naviframe = context_.navContext_.getNaviframe();
797         auto ctxPopup = Widget::make<CtxPopup>(naviframe, true);
798         auto removeCb = [naviframe, ctxPopup]() { naviframe->removeChild(ctxPopup); };
799         ctxPopup->setEvasSmartCallback("dismissed", removeCb);
800         ctxPopup->setEextEventCallback(EEXT_CALLBACK_BACK, removeCb);
801
802         ctxPopup->addItem("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_SCAN_METHOD_POINT", [this, removeCb]() {
803                 scanMethodCtxPopupItemClicked(ScanMethod::POINT);
804                 removeCb();
805         });
806         ctxPopup->addItem("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_SCANNING_SCAN_METHOD_ROW", [this, removeCb]() {
807                 scanMethodCtxPopupItemClicked(ScanMethod::ROW);
808                 removeCb();
809         });
810
811         // TODO use real genlistitem position instead click position
812         int y = 0;
813         evas_pointer_output_xy_get(evas_object_evas_get(context_.navContext_.getWindow()->getObject()), NULL, &y);
814
815         auto geometry = ctxPopup->getGeometry();
816         ctxPopup->setPosition({-1, y + geometry.size.height / 2});
817 }
818
819 void UniversalSwitchSettingsPage::scanMethodCtxPopupItemClicked(ScanMethod scan_method)
820 {
821         context_.usScanningProperties.getScanningProperty(Property::SCAN_METHOD)->setFirstValue(scan_method);
822         scanMethod_->setDescription(getScanMethodText(scan_method));
823 }
824
825 void UniversalSwitchSettingsPage::scanNumberChangedCb(double value)
826 {
827         context_.usScanningProperties.getScanningProperty(Property::AUTO_SCAN)->setSecondValue(static_cast<int>(value));
828         scansNum_->setDescription(std::to_string(static_cast<double>(value)));
829 }
830
831 void UniversalSwitchSettingsPage::autoScanIntervalChangedCb(double value)
832 {
833         context_.usScanningProperties.getScanningProperty(Property::AUTO_SCAN)->setFirstValue(value);
834         autoScanInterval_->setDescription(
835                 getValueUnitText(NULL, &value, "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS", false, {}));
836 }
837
838 void UniversalSwitchSettingsPage::autoMoveIntervalValueChangedCb(double value)
839 {
840         context_.usScanningProperties.getScanningProperty(Property::AUTO_MOVE_INTERVAL)->setFirstValue(value);
841         auto str = getValueUnitText(NULL,
842                 &value,
843                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_SECONDS",
844                 !context_.usScanningProperties.getScanningProperty(Property::AUTO_MOVE_INTERVAL)->getState(),
845                 "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_OFF");
846         autoMoveInterval_->setDescription(str);
847 }
848
849 void UniversalSwitchSettingsPage::onManageMenuOptions()
850 {
851         auto naviframe = context_.navContext_.getNaviframe();
852         auto genlist = Widget::make<Genlist>(naviframe);
853         genlist->setMode(ELM_LIST_COMPRESS);
854         genlist->setStyle("dialogue");
855
856         std::vector<std::pair<Property, std::pair<std::string, std::string>>> manageOptionsData =
857                 {
858                         {Property::GESTURES, {"IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_MANAGE_GESTURES", ""}},
859                         {Property::ACTIONS, {"IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_MANAGE_ACTIONS", ""}},
860                         {Property::SETTINGS, {"IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_MANAGE_SETTINGS", ""}},
861                         {Property::RECENT_APPS, {"IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_MANAGE_RECENT_APPS", ""}},
862                         {Property::HOME_SCREEN, {"IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_MANAGE_HOME_SCREEN", ""}},
863                         {Property::BACK, {"IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_MANAGE_BACK", ""}},
864                         {Property::BUTTONS_AND_KEYS, {"IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_MANAGE_BUTTONS_AND_KEYS", ""}},
865                         {Property::CONTEXTUAL_MENU, {"IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_MANAGE_CONTEXTUAL_MENU", "IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_MANAGE_CONTEXTUAL_MENU_DESC"}}};
866
867         auto prevBtn = Widget::make<Button>(
868                 naviframe, [naviframe, this]() { naviframe->popBack(); }, std::string{}, Button::BACK_BUTTON_ARROW_STYLE);
869
870         for (auto iterator : manageOptionsData) {
871                 auto manageOptionsItem = genlist->appendItem({"multiline",
872                         iterator.second.first,
873                         iterator.second.second,
874                         [iterator, this](auto item) {
875                                 context_.usScanningProperties.getScanningProperty(iterator.first)->setState(item->getState());
876                         },
877                         GenlistItem::WidgetType::toggle});
878                 manageOptionsItem->setState(context_.usScanningProperties.getScanningProperty(iterator.first)->getState());
879         }
880
881         naviframe->pushBack("IDS_ACCS_UNIVERSAL_SWITCH_SETTINGS_GROUP_MANAGE", genlist, [this]() {}, prevBtn);
882 }
883
884 std::string UniversalSwitchSettingsPage::findCursorColor()
885 {
886         for (auto i = 0u; i < cursorColors.size(); i++)
887                 if (cursorColors[i].second == static_cast<unsigned int>(context_.usScanningProperties.getScanningProperty(Property::CURSOR_COLOR)->getFirstValue<int>())) {
888                         return cursorColors[i].first;
889                 }
890
891         return "Undefined";
892 }