Skip to content

Commit

Permalink
feat(key_binder): toggle the switch defined at index toggle: '@n'
Browse files Browse the repository at this point in the history
Closes #554
  • Loading branch information
lotem committed Jun 23, 2022
1 parent 5e8aca2 commit 6ca7803
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 40 deletions.
23 changes: 21 additions & 2 deletions src/rime/gear/key_binder.cc
Expand Up @@ -5,6 +5,7 @@
// 2011-11-23 GONG Chen <chen.sst@gmail.com>
//
#include <algorithm>
#include <boost/lexical_cast.hpp>
#include <rime/common.h>
#include <rime/composition.h>
#include <rime/context.h>
Expand Down Expand Up @@ -77,12 +78,27 @@ static void radio_select_option(Context* ctx,
});
}

inline static bool is_switch_index(const string& option) {
return !option.empty() && option.front() == '@';
}

static Switches::SwitchOption switch_by_index(Switches& switches,
const string& option) {
try {
size_t index = boost::lexical_cast<size_t>(option.substr(1));
return switches.ByIndex(index);
} catch (...) {}
return {};
}

static void toggle_option(Engine* engine, const string& option) {
if (!engine)
return;
Context* ctx = engine->context();
Switches switches(engine->schema()->config());
auto the_option = switches.OptionByName(option);
auto the_option = is_switch_index(option)
? switch_by_index(switches, option)
: switches.OptionByName(option);
if (the_option.found() && the_option.type == Switches::kRadioGroup) {
auto selected_option = switches.FindRadioGroupOption(
the_option.the_switch,
Expand All @@ -102,7 +118,10 @@ static void toggle_option(Engine* engine, const string& option) {
radio_select_option(ctx, next_option);
}
} else { // toggle
ctx->set_option(option, !ctx->get_option(option));
// option can be an index. use the found option name, or an arbitrary
// option name specified by caller.
auto option_name = the_option.found() ? the_option.option_name : option;
ctx->set_option(option_name, !ctx->get_option(option_name));
}
}

Expand Down
93 changes: 56 additions & 37 deletions src/rime/switches.cc
Expand Up @@ -3,64 +3,83 @@

namespace rime {

Switches::SwitchOption Switches::FindOption(
inline static int reset_value(ConfigItemRef& item) {
auto reset = item["reset"];
return reset.IsValue() ? reset.ToInt() : -1;
}

Switches::SwitchOption Switches::FindOptionFromConfigItem(
ConfigItemRef& item,
size_t switch_index,
function<FindResult (SwitchOption option)> callback) {
auto switches = (*config_)["switches"];
if (!switches.IsList())
return {};
for (size_t i = 0; i < switches.size(); ++i) {
auto item = switches[i];
if (!item.IsMap())
continue;
auto the_switch = As<ConfigMap>(*item);
auto reset = item["reset"];
int reset_value = reset.IsValue() ? reset.ToInt() : -1;
auto name = item["name"];
if (name.IsValue()) {
auto the_switch = As<ConfigMap>(*item);
auto name = item["name"];
auto options = item["options"];
if (name.IsValue()) {
SwitchOption option{
the_switch,
kToggleOption,
name.ToString(),
reset_value(item),
switch_index,
};
if (callback(option) == kFound)
return option;
} else if (options.IsList()) {
for (size_t option_index = 0; option_index < options.size();
++option_index) {
SwitchOption option{
the_switch,
kToggleOption,
name.ToString(),
reset_value,
i,
kRadioGroup,
options[option_index].ToString(),
reset_value(item),
switch_index,
option_index,
};
if (callback(option) == kFound)
return option;
continue;
}
auto options = item["options"];
if (options.IsList()) {
for (size_t j = 0; j < options.size(); ++j) {
SwitchOption option{
the_switch,
kRadioGroup,
options[j].ToString(),
reset_value,
i,
j,
};
if (callback(option) == kFound)
return option;
}
}
}
return {};
}

Switches::SwitchOption Switches::FindOption(
function<FindResult (SwitchOption option)> callback) {
auto switches = (*config_)["switches"];
if (!switches.IsList())
return {};
for (size_t switch_index = 0; switch_index < switches.size();
++switch_index) {
auto item = switches[switch_index];
if (!item.IsMap())
continue;
auto option = FindOptionFromConfigItem(item, switch_index, callback);
if (option.found())
return option;
}
return {};
}

Switches::SwitchOption Switches::OptionByName(const string& option_name) {
return FindOption([&option_name](SwitchOption option) {
return option.option_name == option_name ? kFound : kContinue;
});
}

an<ConfigMap> Switches::ByIndex(size_t switch_index) {
Switches::SwitchOption Switches::ByIndex(size_t switch_index) {
auto switches = (*config_)["switches"];
if (!switches.IsList())
return nullptr;
return {};
if (switches.size() <= switch_index)
return nullptr;
return {};
auto item = switches[switch_index];
return As<ConfigMap>(*item);
return FindOptionFromConfigItem(
item,
switch_index,
// return the very first found option.
[](SwitchOption option) {
return kFound;
});
}

Switches::SwitchOption Switches::Cycle(const SwitchOption& current) {
Expand Down
10 changes: 9 additions & 1 deletion src/rime/switches.h
Expand Up @@ -6,6 +6,7 @@
namespace rime {

class Config;
class ConfigItemRef;
class ConfigMap;
class ConfigValue;

Expand Down Expand Up @@ -43,7 +44,9 @@ class Switches {

SwitchOption OptionByName(const string& option_name);

an<ConfigMap> ByIndex(size_t switch_index);
// Returns the switch option defined at switch_index.
// If the swtich is a radio group, return the first option in the group.
SwitchOption ByIndex(size_t switch_index);

static SwitchOption Cycle(const SwitchOption& option);

Expand All @@ -59,6 +62,11 @@ class Switches {
an<ConfigValue> GetStateLabel(const string& option_name, int state);

private:
SwitchOption FindOptionFromConfigItem(
ConfigItemRef& item,
size_t switch_index,
function<FindResult (SwitchOption option)> callback);

Config* config_;
};

Expand Down

0 comments on commit 6ca7803

Please sign in to comment.