4
4
//
5
5
// 2013-05-26 GONG Chen <[email protected] >
6
6
//
7
- #include < utf8.h >
7
+ #include < boost/algorithm/string.hpp >
8
8
#include < rime/candidate.h>
9
9
#include < rime/common.h>
10
10
#include < rime/config.h>
11
11
#include < rime/context.h>
12
12
#include < rime/schema.h>
13
13
#include < rime/switcher.h>
14
+ #include < rime/switches.h>
14
15
#include < rime/translation.h>
15
16
#include < rime/gear/switch_translator.h>
16
17
@@ -20,20 +21,30 @@ static const char* kRadioSelected = " \xe2\x9c\x93"; // U+2713 CHECK MARK
20
21
21
22
namespace rime {
22
23
24
+ using SwitchOption = Switches::SwitchOption;
25
+
26
+ inline static string get_state_label (const SwitchOption& option,
27
+ size_t state_index,
28
+ bool abbreviate = false ) {
29
+ return string (Switches::GetStateLabel (option.the_switch ,
30
+ state_index,
31
+ abbreviate));
32
+ }
33
+
23
34
class Switch : public SimpleCandidate , public SwitcherCommand {
24
35
public:
25
- Switch (const string& current_state_label,
26
- const string& next_state_label,
27
- const string& option_name,
36
+ Switch (const SwitchOption& option,
28
37
bool current_state,
29
38
bool auto_save)
30
39
: SimpleCandidate(" switch" , 0 , 0 ,
31
- current_state_label, kRightArrow + next_state_label),
32
- SwitcherCommand (option_name),
40
+ get_state_label (option, current_state),
41
+ kRightArrow +
42
+ get_state_label(option, 1 - current_state)),
43
+ SwitcherCommand(option.option_name),
33
44
target_state_(!current_state),
34
45
auto_save_(auto_save) {
35
46
}
36
- virtual void Apply (Switcher* switcher);
47
+ void Apply (Switcher* switcher) override ;
37
48
38
49
protected:
39
50
bool target_state_;
@@ -59,8 +70,8 @@ class RadioGroup : public std::enable_shared_from_this<RadioGroup> {
59
70
RadioGroup (Context* context, Switcher* switcher)
60
71
: context_(context), switcher_(switcher) {
61
72
}
62
- an<RadioOption> CreateOption (const string& state_label ,
63
- const string& option_name );
73
+ an<RadioOption> CreateOption (const SwitchOption& option ,
74
+ size_t option_index );
64
75
void SelectOption (RadioOption* option);
65
76
RadioOption* GetSelectedOption () const ;
66
77
@@ -79,7 +90,7 @@ class RadioOption : public SimpleCandidate, public SwitcherCommand {
79
90
SwitcherCommand (option_name),
80
91
group_(group) {
81
92
}
82
- virtual void Apply (Switcher* switcher);
93
+ void Apply (Switcher* switcher) override ;
83
94
void UpdateState (bool selected);
84
95
bool selected () const { return selected_; }
85
96
@@ -99,13 +110,12 @@ void RadioOption::UpdateState(bool selected) {
99
110
}
100
111
101
112
an<RadioOption>
102
- RadioGroup::CreateOption (const string& state_label,
103
- const string& option_name) {
104
- auto option = New<RadioOption>(shared_from_this (),
105
- state_label,
106
- option_name);
107
- options_.push_back (option.get ());
108
- return option;
113
+ RadioGroup::CreateOption (const SwitchOption& option, size_t option_index) {
114
+ auto radio_option = New<RadioOption>(shared_from_this (),
115
+ get_state_label (option, option_index),
116
+ option.option_name );
117
+ options_.push_back (radio_option.get ());
118
+ return radio_option;
109
119
}
110
120
111
121
void RadioGroup::SelectOption (RadioOption* option) {
@@ -142,14 +152,13 @@ class FoldedOptions : public SimpleCandidate, public SwitcherCommand {
142
152
SwitcherCommand (" _fold_options" ) {
143
153
LoadConfig (config);
144
154
}
145
- virtual void Apply (Switcher* switcher);
146
- void Append (const string& label) {
147
- labels_. push_back (label );
148
- }
155
+ void Apply (Switcher* switcher) override ;
156
+ void Append (const SwitchOption& option, size_t state_index);
157
+ void Finish ( );
158
+
149
159
size_t size () const {
150
160
return labels_.size ();
151
161
}
152
- void Finish ();
153
162
154
163
private:
155
164
void LoadConfig (Config* config);
@@ -178,30 +187,13 @@ void FoldedOptions::Apply(Switcher* switcher) {
178
187
switcher->RefreshMenu ();
179
188
}
180
189
181
- static string FirstCharOf (const string& str) {
182
- if (str.empty ()) {
183
- return str;
184
- }
185
- string first_char;
186
- const char * start = str.c_str ();
187
- const char * end = start;
188
- utf8::unchecked::next (end);
189
- return string (start, end - start);
190
+ void FoldedOptions::Append (const SwitchOption& option, size_t state_index) {
191
+ labels_.push_back (
192
+ get_state_label (option, state_index, abbreviate_options_));
190
193
}
191
194
192
195
void FoldedOptions::Finish () {
193
- text_ = prefix_;
194
- bool first = true ;
195
- for (const auto & label : labels_) {
196
- if (first) {
197
- first = false ;
198
- }
199
- else {
200
- text_ += separator_;
201
- }
202
- text_ += abbreviate_options_ ? FirstCharOf (label) : label;
203
- }
204
- text_ += suffix_;
196
+ text_ = prefix_ + boost::algorithm::join (labels_, separator_) + suffix_;
205
197
}
206
198
207
199
class SwitchTranslation : public FifoTranslation {
@@ -220,54 +212,49 @@ void SwitchTranslation::LoadSwitches(Switcher* switcher) {
220
212
Config* config = engine->schema ()->config ();
221
213
if (!config)
222
214
return ;
223
- auto switches = config->GetList (" switches" );
224
- if (!switches)
225
- return ;
226
215
Context* context = engine->context ();
227
- for (size_t i = 0 ; i < switches->size (); ++i) {
228
- auto item = As<ConfigMap>(switches->GetAt (i));
229
- if (!item)
230
- continue ;
231
- auto states = As<ConfigList>(item->Get (" states" ));
232
- if (!states)
233
- continue ;
234
- if (auto option_name = item->GetValue (" name" )) {
235
- // toggle
236
- if (states->size () != 2 )
237
- continue ;
238
- bool current_state = context->get_option (option_name->str ());
239
- Append (New<Switch>(
240
- states->GetValueAt (current_state)->str (),
241
- states->GetValueAt (1 - current_state)->str (),
242
- option_name->str (),
243
- current_state,
244
- switcher->IsAutoSave (option_name->str ())));
245
- }
246
- else if (auto options = As<ConfigList>(item->Get (" options" ))) {
247
- // radio
248
- if (states->size () < 2 )
249
- continue ;
250
- if (states->size () != options->size ())
251
- continue ;
252
- auto group = New<RadioGroup>(context, switcher);
253
- for (size_t i = 0 ; i < options->size (); ++i) {
254
- auto option_name = options->GetValueAt (i);
255
- auto state_label = states->GetValueAt (i);
256
- if (!option_name || !state_label)
257
- continue ;
258
- Append (group->CreateOption (state_label->str (), option_name->str ()));
216
+ vector<an<RadioGroup>> groups;
217
+ Switches switches (config);
218
+ switches.FindOption (
219
+ [this , switcher, context, &groups]
220
+ (Switches::SwitchOption option) -> Switches::FindResult {
221
+ if (option.type == Switches::kToggleOption ) {
222
+ bool current_state = context->get_option (option.option_name );
223
+ Append (
224
+ New<Switch>(option,
225
+ current_state,
226
+ switcher->IsAutoSave (option.option_name )));
227
+ } else if (option.type == Switches::kRadioGroup ) {
228
+ an<RadioGroup> group;
229
+ if (option.option_index == 0 ) {
230
+ group = New<RadioGroup>(context, switcher);
231
+ groups.push_back (group);
232
+ } else {
233
+ group = groups.back ();
234
+ }
235
+ Append (
236
+ group->CreateOption (option, option.option_index ));
259
237
}
260
- group->SelectOption (group->GetSelectedOption ());
261
- }
238
+ return Switches::kContinue ;
239
+ });
240
+ for (auto & group : groups) {
241
+ group->SelectOption (group->GetSelectedOption ());
262
242
}
263
243
if (switcher->context ()->get_option (" _fold_options" )) {
264
244
auto folded_options = New<FoldedOptions>(switcher->schema ()->config ());
265
- for (auto x : candies_) {
266
- if (Is<Switch>(x) ||
267
- (Is<RadioOption>(x) && As<RadioOption>(x)->selected ())) {
268
- folded_options->Append (x->text ());
269
- }
270
- }
245
+ switches.FindOption (
246
+ [context, &folded_options]
247
+ (Switches::SwitchOption option) -> Switches::FindResult {
248
+ bool current_state = context->get_option (option.option_name );
249
+ if (option.type == Switches::kToggleOption ) {
250
+ folded_options->Append (option, current_state);
251
+ } else if (option.type == Switches::kRadioGroup ) {
252
+ if (current_state) {
253
+ folded_options->Append (option, option.option_index );
254
+ }
255
+ }
256
+ return Switches::kContinue ;
257
+ });
271
258
if (folded_options->size () > 1 ) {
272
259
folded_options->Finish ();
273
260
candies_.clear ();
0 commit comments