summaryrefslogtreecommitdiff
path: root/library/PluginManager.cpp
diff options
context:
space:
mode:
authorAlexander Gavrilov2011-12-30 23:25:50 +0400
committerAlexander Gavrilov2011-12-30 23:25:50 +0400
commit2222757e77d4c7f2a337c8b6a0f663414702d111 (patch)
tree57f47ae94b7be0c8585de0adc23635a4df095b59 /library/PluginManager.cpp
parent4aa77f55308236189f157f65ad9ce82c35b9dabc (diff)
downloaddfhack-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.cpp96
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 )