diff options
| author | Alexander Gavrilov | 2011-12-30 23:25:50 +0400 |
|---|---|---|
| committer | Alexander Gavrilov | 2011-12-30 23:25:50 +0400 |
| commit | 2222757e77d4c7f2a337c8b6a0f663414702d111 (patch) | |
| tree | 57f47ae94b7be0c8585de0adc23635a4df095b59 /library/PluginManager.cpp | |
| parent | 4aa77f55308236189f157f65ad9ce82c35b9dabc (diff) | |
| download | dfhack-2222757e77d4c7f2a337c8b6a0f663414702d111.tar.gz dfhack-2222757e77d4c7f2a337c8b6a0f663414702d111.tar.bz2 dfhack-2222757e77d4c7f2a337c8b6a0f663414702d111.tar.xz | |
Implement context-sensitive keybinding support.
Allow defining commands with guard conditions, and binding
one or more commands to alphabetic and function keys. When
the relevant key is pressed, the first listed command with
successfully evaluated guard is chosen.
For consistency, the guard is also checked when the command
is invoked from the console; this requires suspending the
core inside PluginManager, before invoking plugin code.
Diffstat (limited to 'library/PluginManager.cpp')
| -rw-r--r-- | library/PluginManager.cpp | 96 |
1 files changed, 82 insertions, 14 deletions
diff --git a/library/PluginManager.cpp b/library/PluginManager.cpp index 997b8e59..a520575d 100644 --- a/library/PluginManager.cpp +++ b/library/PluginManager.cpp @@ -27,6 +27,10 @@ distribution. #include "dfhack/Process.h" #include "dfhack/PluginManager.h" #include "dfhack/Console.h" + +#include "dfhack/DataDefs.h" +#include "dfhack/df/viewscreen.h" + using namespace DFHack; #include <string> @@ -273,13 +277,69 @@ command_result Plugin::invoke( std::string & command, std::vector <std::string> { for (int i = 0; i < commands.size();i++) { - if(commands[i].name == command) + PluginCommand &cmd = commands[i]; + + if(cmd.name == command) { // running interactive things from some other source than the console would break it - if(!interactive_ && commands[i].interactive) + if(!interactive_ && cmd.interactive) cr = CR_WOULD_BREAK; - else - cr = commands[i].function(&c, parameters); + else if (cmd.guard) + { + // Execute hotkey commands in a way where they can + // expect their guard conditions to be matched, + // so as to avoid duplicating checks. + // This means suspending the core beforehand. + CoreSuspender suspend(&c); + df::viewscreen *top = c.getTopViewscreen(); + + if ((cmd.viewscreen_type && !cmd.viewscreen_type->is_instance(top)) + || !cmd.guard(&c, top)) + { + c.con.printerr("Could not invoke %s: unsuitable UI state.\n", command.c_str()); + cr = CR_FAILURE; + } + else + { + cr = cmd.function(&c, parameters); + } + } + else + { + cr = cmd.function(&c, parameters); + } + break; + } + } + } + access->lock_sub(); + return cr; +} + +bool Plugin::can_invoke_hotkey( std::string & command, df::viewscreen *top ) +{ + Core & c = Core::getInstance(); + bool cr = false; + access->lock_add(); + if(state == PS_LOADED) + { + for (int i = 0; i < commands.size();i++) + { + PluginCommand &cmd = commands[i]; + + if(cmd.name == command) + { + if (cmd.interactive) + cr = false; + else if (cmd.guard) + { + cr = (!cmd.viewscreen_type || cmd.viewscreen_type->is_instance(top)) + && cmd.guard(&c, top); + } + else + { + cr = default_hotkey(&c, top); + } break; } } @@ -363,19 +423,27 @@ Plugin *PluginManager::getPluginByName (const std::string & name) return 0; } +Plugin *PluginManager::getPluginByCommand(const std::string &command) +{ + tthread::lock_guard<tthread::mutex> lock(*cmdlist_mutex); + map <string, Plugin *>::iterator iter = belongs.find(command); + if (iter != belongs.end()) + return iter->second; + else + return NULL; +} + // FIXME: handle name collisions... command_result PluginManager::InvokeCommand( std::string & command, std::vector <std::string> & parameters, bool interactive) { - command_result cr = CR_NOT_IMPLEMENTED; - Core * c = &Core::getInstance(); - cmdlist_mutex->lock(); - map <string, Plugin *>::iterator iter = belongs.find(command); - if(iter != belongs.end()) - { - cr = iter->second->invoke(command, parameters, interactive); - } - cmdlist_mutex->unlock(); - return cr; + Plugin *plugin = getPluginByCommand(command); + return plugin ? plugin->invoke(command, parameters, interactive) : CR_NOT_IMPLEMENTED; +} + +bool PluginManager::CanInvokeHotkey(std::string &command, df::viewscreen *top) +{ + Plugin *plugin = getPluginByCommand(command); + return plugin ? plugin->can_invoke_hotkey(command, top) : false; } void PluginManager::OnUpdate( void ) |
