forked from mia/Aegisub
Add support for modifying hotkeys while the program is running
Originally committed to SVN as r5793.
This commit is contained in:
parent
cba0b1edb8
commit
6c995e7780
6 changed files with 124 additions and 96 deletions
|
@ -43,9 +43,9 @@
|
||||||
namespace agi {
|
namespace agi {
|
||||||
namespace hotkey {
|
namespace hotkey {
|
||||||
|
|
||||||
Hotkey *hotkey;
|
|
||||||
|
|
||||||
std::string Combo::Str() const {
|
std::string Combo::Str() const {
|
||||||
|
if (key_map.empty()) return "";
|
||||||
|
|
||||||
std::string str(key_map[0]);
|
std::string str(key_map[0]);
|
||||||
str.reserve(str.size() + (key_map.size() - 1) * 2);
|
str.reserve(str.size() + (key_map.size() - 1) * 2);
|
||||||
for (unsigned int i=1; i < key_map.size(); i++) {
|
for (unsigned int i=1; i < key_map.size(); i++) {
|
||||||
|
@ -63,10 +63,6 @@ void Hotkey::ComboInsert(Combo const& combo) {
|
||||||
cmd_map.insert(std::make_pair(combo.CmdName(), combo));
|
cmd_map.insert(std::make_pair(combo.CmdName(), combo));
|
||||||
}
|
}
|
||||||
|
|
||||||
Hotkey::~Hotkey() {
|
|
||||||
Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
Hotkey::Hotkey(const std::string &file, const std::string &default_config)
|
Hotkey::Hotkey(const std::string &file, const std::string &default_config)
|
||||||
: config_file(file)
|
: config_file(file)
|
||||||
{
|
{
|
||||||
|
@ -75,26 +71,23 @@ Hotkey::Hotkey(const std::string &file, const std::string &default_config)
|
||||||
json::UnknownElement hotkey_root = agi::json_util::file(config_file, default_config);
|
json::UnknownElement hotkey_root = agi::json_util::file(config_file, default_config);
|
||||||
json::Object object = hotkey_root;
|
json::Object object = hotkey_root;
|
||||||
|
|
||||||
for (json::Object::const_iterator index(object.begin()); index != object.end(); index++) {
|
for (json::Object::const_iterator index(object.begin()); index != object.end(); ++index)
|
||||||
BuildHotkey(index->first, index->second);
|
BuildHotkey(index->first, index->second);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Hotkey::BuildHotkey(std::string const& context, const json::Object& object) {
|
void Hotkey::BuildHotkey(std::string const& context, const json::Object& object) {
|
||||||
for (json::Object::const_iterator index(object.begin()); index != object.end(); index++) {
|
for (json::Object::const_iterator index(object.begin()); index != object.end(); ++index) {
|
||||||
const json::Array& array = index->second;
|
const json::Array& array = index->second;
|
||||||
|
|
||||||
for (json::Array::const_iterator arr_index(array.begin()); arr_index != array.end(); arr_index++) {
|
for (json::Array::const_iterator arr_index(array.begin()); arr_index != array.end(); ++arr_index) {
|
||||||
Combo combo(context, index->first);
|
|
||||||
|
|
||||||
const json::Array& arr_mod = (*arr_index)["modifiers"];
|
const json::Array& arr_mod = (*arr_index)["modifiers"];
|
||||||
for (json::Array::const_iterator arr_mod_index(arr_mod.begin()); arr_mod_index != arr_mod.end(); arr_mod_index++) {
|
std::vector<std::string> keys;
|
||||||
combo.KeyInsert(*arr_mod_index);
|
keys.reserve(arr_mod.size() + 1);
|
||||||
}
|
copy(arr_mod.begin(), arr_mod.end(), back_inserter(keys));
|
||||||
|
keys.push_back((*arr_index)["key"]);
|
||||||
|
|
||||||
combo.KeyInsert((*arr_index)["key"]);
|
ComboInsert(Combo(context, index->first, keys));
|
||||||
ComboInsert(combo);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,13 +104,11 @@ bool Hotkey::Scan(const std::string &context, const std::string &str, bool alway
|
||||||
LOG_D("agi/hotkey/found") << "Found: " << str << " Context (req/found): " << context << "/Always Command: " << cmd;
|
LOG_D("agi/hotkey/found") << "Found: " << str << " Context (req/found): " << context << "/Always Command: " << cmd;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ctext == "Default") {
|
if (ctext == "Default")
|
||||||
dfault = index->second.CmdName();
|
dfault = index->second.CmdName();
|
||||||
}
|
else if (ctext == context)
|
||||||
else if (ctext == context) {
|
|
||||||
local = index->second.CmdName();
|
local = index->second.CmdName();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!local.empty()) {
|
if (!local.empty()) {
|
||||||
cmd = local;
|
cmd = local;
|
||||||
|
@ -139,10 +130,9 @@ std::vector<std::string> Hotkey::GetHotkeys(const std::string &context, const st
|
||||||
HotkeyMap::const_iterator it, end;
|
HotkeyMap::const_iterator it, end;
|
||||||
for (std::tr1::tie(it, end) = cmd_map.equal_range(command); it != end; ++it) {
|
for (std::tr1::tie(it, end) = cmd_map.equal_range(command); it != end; ++it) {
|
||||||
std::string ctext = it->second.Context();
|
std::string ctext = it->second.Context();
|
||||||
if (ctext == "Always" || ctext == "Default" || ctext == context) {
|
if (ctext == "Always" || ctext == "Default" || ctext == context)
|
||||||
ret.push_back(it->second.StrMenu());
|
ret.push_back(it->second.StrMenu());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
sort(ret.begin(), ret.end());
|
sort(ret.begin(), ret.end());
|
||||||
ret.erase(unique(ret.begin(), ret.end()), ret.end());
|
ret.erase(unique(ret.begin(), ret.end()), ret.end());
|
||||||
|
@ -156,8 +146,10 @@ std::string Hotkey::GetHotkey(const std::string &context, const std::string &com
|
||||||
for (std::tr1::tie(it, end) = cmd_map.equal_range(command); it != end; ++it) {
|
for (std::tr1::tie(it, end) = cmd_map.equal_range(command); it != end; ++it) {
|
||||||
std::string ctext = it->second.Context();
|
std::string ctext = it->second.Context();
|
||||||
if (ctext == context) return it->second.StrMenu();
|
if (ctext == context) return it->second.StrMenu();
|
||||||
if (ctext == "Default") ret = it->second.StrMenu();
|
if (ctext == "Default")
|
||||||
else if (ret.empty() && ctext == "Always") it->second.StrMenu();
|
ret = it->second.StrMenu();
|
||||||
|
else if (ret.empty() && ctext == "Always")
|
||||||
|
it->second.StrMenu();
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -166,12 +158,10 @@ void Hotkey::Flush() {
|
||||||
json::Object root;
|
json::Object root;
|
||||||
|
|
||||||
for (HotkeyMap::iterator index = str_map.begin(); index != str_map.end(); ++index) {
|
for (HotkeyMap::iterator index = str_map.begin(); index != str_map.end(); ++index) {
|
||||||
Combo::ComboMap combo_map(index->second.Get());
|
std::vector<std::string> const& combo_map(index->second.Get());
|
||||||
|
|
||||||
json::Array modifiers;
|
json::Array modifiers;
|
||||||
for (int i = 0; i != combo_map.size()-1; i++) {
|
copy(combo_map.begin(), combo_map.end() - 1, std::back_inserter(modifiers));
|
||||||
modifiers.push_back(json::String(combo_map[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
json::Object hotkey;
|
json::Object hotkey;
|
||||||
hotkey["modifiers"] = modifiers;
|
hotkey["modifiers"] = modifiers;
|
||||||
|
@ -185,5 +175,15 @@ void Hotkey::Flush() {
|
||||||
json::Writer::Write(root, file.Get());
|
json::Writer::Write(root, file.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Hotkey::SetHotkeyMap(HotkeyMap const& new_map) {
|
||||||
|
cmd_map = new_map;
|
||||||
|
|
||||||
|
str_map.clear();
|
||||||
|
for (HotkeyMap::iterator it = cmd_map.begin(); it != cmd_map.end(); ++it)
|
||||||
|
str_map.insert(make_pair(it->second.Str(), it->second));
|
||||||
|
|
||||||
|
HotkeysChanged();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace toolbar
|
} // namespace toolbar
|
||||||
} // namespace agi
|
} // namespace agi
|
||||||
|
|
|
@ -19,13 +19,14 @@
|
||||||
/// @ingroup hotkey menu event window
|
/// @ingroup hotkey menu event window
|
||||||
|
|
||||||
#ifndef LAGI_PRE
|
#ifndef LAGI_PRE
|
||||||
#include <cmath>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <libaegisub/signal.h>
|
||||||
|
|
||||||
namespace json {
|
namespace json {
|
||||||
class UnknownElement;
|
class UnknownElement;
|
||||||
typedef std::map<std::string, UnknownElement> Object;
|
typedef std::map<std::string, UnknownElement> Object;
|
||||||
|
@ -34,27 +35,23 @@ namespace json {
|
||||||
namespace agi {
|
namespace agi {
|
||||||
namespace hotkey {
|
namespace hotkey {
|
||||||
|
|
||||||
class Hotkey;
|
|
||||||
/// Hotkey instance.
|
|
||||||
extern Hotkey *hotkey;
|
|
||||||
|
|
||||||
/// @class Combo
|
/// @class Combo
|
||||||
/// A Combo represents a linear sequence of characters set in an std::vector. This makes up
|
/// A Combo represents a linear sequence of characters set in an std::vector. This makes up
|
||||||
/// a single combination, or "Hotkey".
|
/// a single combination, or "Hotkey".
|
||||||
class Combo {
|
class Combo {
|
||||||
friend class Hotkey;
|
std::vector<std::string> key_map;
|
||||||
|
std::string cmd_name;
|
||||||
|
std::string context;
|
||||||
public:
|
public:
|
||||||
/// Linear key sequence that forms a combination or "Combo"
|
|
||||||
typedef std::vector<std::string> ComboMap;
|
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// @param ctx Context
|
/// @param ctx Context
|
||||||
/// @param cmd Command name
|
/// @param cmd Command name
|
||||||
Combo(std::string const& ctx, std::string const& cmd): cmd_name(cmd), context(ctx) {}
|
Combo(std::string const& ctx, std::string const& cmd, std::vector<std::string> const& keys)
|
||||||
|
: key_map(keys)
|
||||||
/// Destructor
|
, cmd_name(cmd)
|
||||||
~Combo() {}
|
, context(ctx)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// String representation of the Combo
|
/// String representation of the Combo
|
||||||
std::string Str() const;
|
std::string Str() const;
|
||||||
|
@ -64,7 +61,7 @@ public:
|
||||||
|
|
||||||
/// Get the literal combo map.
|
/// Get the literal combo map.
|
||||||
/// @return ComboMap (std::vector) of linear key sequence.
|
/// @return ComboMap (std::vector) of linear key sequence.
|
||||||
const ComboMap& Get() const { return key_map; }
|
const std::vector<std::string>& Get() const { return key_map; }
|
||||||
|
|
||||||
/// Command name triggered by the combination.
|
/// Command name triggered by the combination.
|
||||||
/// @return Command name
|
/// @return Command name
|
||||||
|
@ -72,30 +69,40 @@ public:
|
||||||
|
|
||||||
/// Context this Combo is triggered in.
|
/// Context this Combo is triggered in.
|
||||||
const std::string& Context() const { return context; }
|
const std::string& Context() const { return context; }
|
||||||
|
|
||||||
private:
|
|
||||||
ComboMap key_map; ///< Map.
|
|
||||||
const std::string cmd_name; ///< Command name.
|
|
||||||
const std::string context; ///< Context
|
|
||||||
|
|
||||||
/// Insert a key into the ComboMap.
|
|
||||||
/// @param key Key to insert.
|
|
||||||
void KeyInsert(std::string key) { key_map.push_back(key); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// @class Hotkey
|
/// @class Hotkey
|
||||||
/// Holds the map of Combo instances and handles searching for matching key sequences.
|
/// Holds the map of Combo instances and handles searching for matching key sequences.
|
||||||
class Hotkey {
|
class Hotkey {
|
||||||
|
public:
|
||||||
|
/// Map to hold Combo instances
|
||||||
|
typedef std::multimap<std::string, Combo> HotkeyMap;
|
||||||
|
private:
|
||||||
|
HotkeyMap str_map; ///< String representation -> Combo
|
||||||
|
HotkeyMap cmd_map; ///< Command name -> Combo
|
||||||
|
const std::string config_file; ///< Default user config location.
|
||||||
|
|
||||||
|
/// Build hotkey map.
|
||||||
|
/// @param context Context being parsed.
|
||||||
|
/// @param object json::Object holding items for context being parsed.
|
||||||
|
void BuildHotkey(std::string const& context, const json::Object& object);
|
||||||
|
|
||||||
|
/// Insert Combo into HotkeyMap instance.
|
||||||
|
/// @param combo Combo to insert.
|
||||||
|
void ComboInsert(Combo const& combo);
|
||||||
|
|
||||||
|
/// Write active Hotkey configuration to disk.
|
||||||
|
void Flush();
|
||||||
|
|
||||||
|
/// Announce that the loaded hotkeys have been changed
|
||||||
|
agi::signal::Signal<> HotkeysChanged;
|
||||||
public:
|
public:
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// @param file Location of user config file.
|
/// @param file Location of user config file.
|
||||||
/// @param default_config Default config.
|
/// @param default_config Default config.
|
||||||
Hotkey(const std::string &file, const std::string &default_config);
|
Hotkey(const std::string &file, const std::string &default_config);
|
||||||
|
|
||||||
/// Destructor.
|
|
||||||
~Hotkey();
|
|
||||||
|
|
||||||
/// Scan for a matching key.
|
/// Scan for a matching key.
|
||||||
/// @param context Context requested.
|
/// @param context Context requested.
|
||||||
/// @param str Hyphen separated key sequence.
|
/// @param str Hyphen separated key sequence.
|
||||||
|
@ -115,23 +122,13 @@ public:
|
||||||
/// @return A hotkey for the given command or "" if there are none
|
/// @return A hotkey for the given command or "" if there are none
|
||||||
std::string GetHotkey(const std::string &context, const std::string &command) const;
|
std::string GetHotkey(const std::string &context, const std::string &command) const;
|
||||||
|
|
||||||
private:
|
/// Get the raw command name -> combo map for all registered hotkeys
|
||||||
typedef std::multimap<std::string, Combo> HotkeyMap; ///< Map to hold Combo instances.
|
HotkeyMap const& GetHotkeyMap() const { return cmd_map; }
|
||||||
HotkeyMap str_map; ///< String representation -> Combo
|
|
||||||
HotkeyMap cmd_map; ///< Command name -> Combo
|
|
||||||
const std::string config_file; ///< Default user config location.
|
|
||||||
|
|
||||||
/// Build hotkey map.
|
/// Replace the loaded hotkeys with a new set
|
||||||
/// @param context Context being parsed.
|
void SetHotkeyMap(HotkeyMap const& new_map);
|
||||||
/// @param object json::Object holding items for context being parsed.
|
|
||||||
void BuildHotkey(std::string const& context, const json::Object& object);
|
|
||||||
|
|
||||||
/// Insert Combo into HotkeyMap instance.
|
DEFINE_SIGNAL_ADDERS(HotkeysChanged, AddHotkeyChangeListener)
|
||||||
/// @param combo Combo to insert.
|
|
||||||
void ComboInsert(Combo const& combo);
|
|
||||||
|
|
||||||
/// Write active Hotkey configuration to disk.
|
|
||||||
void Flush();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace hotkey
|
} // namespace hotkey
|
||||||
|
|
|
@ -186,9 +186,8 @@ bool AegisubApp::OnInit() {
|
||||||
// Init commands.
|
// Init commands.
|
||||||
cmd::init_builtin_commands();
|
cmd::init_builtin_commands();
|
||||||
|
|
||||||
// Init hotkeys.
|
// Init hotkeys
|
||||||
const std::string conf_user_hotkey(StandardPaths::DecodePath("?user/hotkey.json"));
|
hotkey::init();
|
||||||
agi::hotkey::hotkey = new agi::hotkey::Hotkey(conf_user_hotkey, GET_DEFAULT_CONFIG(default_hotkey));
|
|
||||||
|
|
||||||
// Init icons.
|
// Init icons.
|
||||||
icon::icon_init();
|
icon::icon_init();
|
||||||
|
@ -327,7 +326,7 @@ int AegisubApp::OnExit() {
|
||||||
delete plugins;
|
delete plugins;
|
||||||
delete config::opt;
|
delete config::opt;
|
||||||
delete config::mru;
|
delete config::mru;
|
||||||
delete agi::hotkey::hotkey;
|
hotkey::clear();
|
||||||
delete config::path;
|
delete config::path;
|
||||||
cmd::clear();
|
cmd::clear();
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "standard_paths.h"
|
#include "standard_paths.h"
|
||||||
|
|
||||||
|
#include <libaegisub/hotkey.h>
|
||||||
#include <libaegisub/json.h>
|
#include <libaegisub/json.h>
|
||||||
#include <libaegisub/log.h>
|
#include <libaegisub/log.h>
|
||||||
|
|
||||||
|
@ -133,6 +134,8 @@ struct menu_item_cmp {
|
||||||
class CommandManager {
|
class CommandManager {
|
||||||
/// Menu items which need to do something on menu open
|
/// Menu items which need to do something on menu open
|
||||||
std::deque<std::pair<cmd::Command*, wxMenuItem*> > dynamic_items;
|
std::deque<std::pair<cmd::Command*, wxMenuItem*> > dynamic_items;
|
||||||
|
/// Menu items which need to be updated only when hotkeys change
|
||||||
|
std::deque<std::pair<cmd::Command*, wxMenuItem*> > static_items;
|
||||||
/// window id -> command map
|
/// window id -> command map
|
||||||
std::vector<cmd::Command*> items;
|
std::vector<cmd::Command*> items;
|
||||||
/// MRU menus which need to be updated on menu open
|
/// MRU menus which need to be updated on menu open
|
||||||
|
@ -141,19 +144,30 @@ class CommandManager {
|
||||||
/// Project context
|
/// Project context
|
||||||
agi::Context *context;
|
agi::Context *context;
|
||||||
|
|
||||||
|
/// Connection for hotkey change signal
|
||||||
|
agi::signal::Connection hotkeys_changed;
|
||||||
|
|
||||||
/// Update a single dynamic menu item
|
/// Update a single dynamic menu item
|
||||||
void UpdateItem(std::pair<cmd::Command*, wxMenuItem*> const& item) {
|
void UpdateItem(std::pair<cmd::Command*, wxMenuItem*> const& item) {
|
||||||
int flags = item.first->Type();
|
int flags = item.first->Type();
|
||||||
if (flags & cmd::COMMAND_DYNAMIC_NAME)
|
if (flags & cmd::COMMAND_DYNAMIC_NAME)
|
||||||
item.second->SetItemLabel(get_menu_text(item.first, context));
|
UpdateItemName(item);
|
||||||
if (flags & cmd::COMMAND_VALIDATE)
|
if (flags & cmd::COMMAND_VALIDATE)
|
||||||
item.second->Enable(item.first->Validate(context));
|
item.second->Enable(item.first->Validate(context));
|
||||||
if (flags & cmd::COMMAND_RADIO || flags & cmd::COMMAND_TOGGLE)
|
if (flags & cmd::COMMAND_RADIO || flags & cmd::COMMAND_TOGGLE)
|
||||||
item.second->Check(item.first->IsActive(context));
|
item.second->Check(item.first->IsActive(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateItemName(std::pair<cmd::Command*, wxMenuItem*> const& item) {
|
||||||
|
item.second->SetItemLabel(get_menu_text(item.first, context));
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CommandManager(agi::Context *context) : context(context) { }
|
CommandManager(agi::Context *context)
|
||||||
|
: context(context)
|
||||||
|
, hotkeys_changed(hotkey::inst->AddHotkeyChangeListener(&CommandManager::OnHotkeysChanged, this))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// Append a command to a menu and register the needed handlers
|
/// Append a command to a menu and register the needed handlers
|
||||||
int AddCommand(cmd::Command *co, wxMenu *parent, std::string const& text) {
|
int AddCommand(cmd::Command *co, wxMenu *parent, std::string const& text) {
|
||||||
|
@ -177,6 +191,8 @@ public:
|
||||||
|
|
||||||
if (flags != cmd::COMMAND_NORMAL)
|
if (flags != cmd::COMMAND_NORMAL)
|
||||||
dynamic_items.push_back(std::make_pair(co, item));
|
dynamic_items.push_back(std::make_pair(co, item));
|
||||||
|
else
|
||||||
|
static_items.push_back(std::make_pair(co, item));
|
||||||
|
|
||||||
return item->GetId();
|
return item->GetId();
|
||||||
}
|
}
|
||||||
|
@ -209,6 +225,12 @@ public:
|
||||||
if (id < items.size())
|
if (id < items.size())
|
||||||
(*items[id])(context);
|
(*items[id])(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the hotkeys for all menu items
|
||||||
|
void OnHotkeysChanged() {
|
||||||
|
for_each(dynamic_items.begin(), dynamic_items.end(), bind(&CommandManager::UpdateItemName, this, _1));
|
||||||
|
for_each(static_items.begin(), static_items.end(), bind(&CommandManager::UpdateItemName, this, _1));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Wrapper for wxMenu to add a command manager
|
/// Wrapper for wxMenu to add a command manager
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <wx/toolbar.h>
|
#include <wx/toolbar.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <libaegisub/hotkey.h>
|
||||||
#include <libaegisub/json.h>
|
#include <libaegisub/json.h>
|
||||||
#include <libaegisub/log.h>
|
#include <libaegisub/log.h>
|
||||||
#include <libaegisub/signal.h>
|
#include <libaegisub/signal.h>
|
||||||
|
@ -64,6 +65,9 @@ namespace {
|
||||||
/// Listener for icon size change signal
|
/// Listener for icon size change signal
|
||||||
agi::signal::Connection icon_size_slot;
|
agi::signal::Connection icon_size_slot;
|
||||||
|
|
||||||
|
/// Listener for hotkey change signal
|
||||||
|
agi::signal::Connection hotkeys_changed_slot;
|
||||||
|
|
||||||
/// Enable/disable the toolbar buttons
|
/// Enable/disable the toolbar buttons
|
||||||
void OnIdle(wxIdleEvent &) {
|
void OnIdle(wxIdleEvent &) {
|
||||||
for (size_t i = 0; i < commands.size(); ++i) {
|
for (size_t i = 0; i < commands.size(); ++i) {
|
||||||
|
@ -81,8 +85,8 @@ namespace {
|
||||||
(*commands[evt.GetId() - TOOL_ID_BASE])(context);
|
(*commands[evt.GetId() - TOOL_ID_BASE])(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear the toolbar and recreate it with the new icon size
|
/// Clear the toolbar and recreate it
|
||||||
void OnIconSizeChanged() {
|
void RegenerateToolbar() {
|
||||||
Unbind(wxEVT_IDLE, &Toolbar::OnIdle, this);
|
Unbind(wxEVT_IDLE, &Toolbar::OnIdle, this);
|
||||||
ClearTools();
|
ClearTools();
|
||||||
commands.clear();
|
commands.clear();
|
||||||
|
@ -130,20 +134,7 @@ namespace {
|
||||||
flags & cmd::COMMAND_TOGGLE ? wxITEM_CHECK :
|
flags & cmd::COMMAND_TOGGLE ? wxITEM_CHECK :
|
||||||
wxITEM_NORMAL;
|
wxITEM_NORMAL;
|
||||||
|
|
||||||
wxString tooltip = command->StrHelp();
|
AddTool(TOOL_ID_BASE + commands.size(), command->StrDisplay(context), icon, GetTooltip(command), kind);
|
||||||
|
|
||||||
std::vector<std::string> hotkeys = hotkey::get_hotkey_strs(ht_context, command->name());
|
|
||||||
|
|
||||||
for (size_t i = 0; i < hotkeys.size(); ++i) {
|
|
||||||
if (i == 0)
|
|
||||||
tooltip += " (";
|
|
||||||
else
|
|
||||||
tooltip += "/";
|
|
||||||
tooltip += hotkeys[i];
|
|
||||||
}
|
|
||||||
if (hotkeys.size()) tooltip += ")";
|
|
||||||
|
|
||||||
AddTool(TOOL_ID_BASE + commands.size(), command->StrDisplay(context), icon, tooltip, kind);
|
|
||||||
|
|
||||||
commands.push_back(command);
|
commands.push_back(command);
|
||||||
needs_onidle = needs_onidle || flags != cmd::COMMAND_NORMAL;
|
needs_onidle = needs_onidle || flags != cmd::COMMAND_NORMAL;
|
||||||
|
@ -157,14 +148,31 @@ namespace {
|
||||||
|
|
||||||
Realize();
|
Realize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxString GetTooltip(cmd::Command *command) {
|
||||||
|
wxString ret = command->StrHelp();
|
||||||
|
|
||||||
|
std::vector<std::string> hotkeys = hotkey::get_hotkey_strs(ht_context, command->name());
|
||||||
|
for (size_t i = 0; i < hotkeys.size(); ++i) {
|
||||||
|
if (i == 0)
|
||||||
|
ret += " (";
|
||||||
|
else
|
||||||
|
ret += "/";
|
||||||
|
ret += hotkeys[i];
|
||||||
|
}
|
||||||
|
if (hotkeys.size()) ret += ")";
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Toolbar(wxWindow *parent, std::string const& name, agi::Context *c, std::string const& ht_context)
|
Toolbar(wxWindow *parent, std::string const& name, agi::Context *c, std::string const& ht_context)
|
||||||
: wxToolBar(parent, -1, wxDefaultPosition, wxDefaultSize, wxTB_FLAT | wxTB_HORIZONTAL)
|
: wxToolBar(parent, -1, wxDefaultPosition, wxDefaultSize, wxTB_FLAT | wxTB_HORIZONTAL)
|
||||||
, name(name)
|
, name(name)
|
||||||
, context(c)
|
, context(c)
|
||||||
, ht_context(ht_context)
|
, ht_context(ht_context)
|
||||||
, icon_size_slot(OPT_SUB("App/Toolbar Icon Size", &Toolbar::OnIconSizeChanged, this))
|
, icon_size_slot(OPT_SUB("App/Toolbar Icon Size", &Toolbar::RegenerateToolbar, this))
|
||||||
/// @todo bind to hotkey changed event when such a thing exists
|
, hotkeys_changed_slot(hotkey::inst->AddHotkeyChangeListener(&Toolbar::RegenerateToolbar, this))
|
||||||
{
|
{
|
||||||
Populate();
|
Populate();
|
||||||
Bind(wxEVT_COMMAND_TOOL_CLICKED, &Toolbar::OnClick, this);
|
Bind(wxEVT_COMMAND_TOOL_CLICKED, &Toolbar::OnClick, this);
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
|
|
||||||
#include "include/aegisub/hotkey.h"
|
#include "include/aegisub/hotkey.h"
|
||||||
|
|
||||||
|
#include <libaegisub/hotkey.h>
|
||||||
|
|
||||||
struct ToolTipBinding {
|
struct ToolTipBinding {
|
||||||
wxWindow *window;
|
wxWindow *window;
|
||||||
wxString toolTip;
|
wxString toolTip;
|
||||||
|
@ -54,10 +56,10 @@ ToolTipManager::~ToolTipManager() { }
|
||||||
void ToolTipManager::Bind(wxWindow *window, wxString tooltip, const char *context, const char *command) {
|
void ToolTipManager::Bind(wxWindow *window, wxString tooltip, const char *context, const char *command) {
|
||||||
ToolTipBinding tip = { window, tooltip, command, context };
|
ToolTipBinding tip = { window, tooltip, command, context };
|
||||||
tip.Update();
|
tip.Update();
|
||||||
/// @todo bind to hotkey changed signal once such a thing exists
|
|
||||||
|
|
||||||
static ToolTipManager instance;
|
static ToolTipManager instance;
|
||||||
instance.tips.push_back(tip);
|
instance.tips.push_back(tip);
|
||||||
|
hotkey::inst->AddHotkeyChangeListener(&ToolTipBinding::Update, &instance.tips.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToolTipBinding::Update() {
|
void ToolTipBinding::Update() {
|
||||||
|
|
Loading…
Reference in a new issue