Implement the Automation menu

Originally committed to SVN as r5648.
This commit is contained in:
Thomas Goyne 2011-09-28 19:49:56 +00:00
parent 5bb5f146a7
commit d419c7a447
4 changed files with 100 additions and 25 deletions

View file

@ -325,6 +325,8 @@ namespace Automation4 {
{ {
if (find(scripts.begin(), scripts.end(), script) == scripts.end()) if (find(scripts.begin(), scripts.end(), script) == scripts.end())
scripts.push_back(script); scripts.push_back(script);
ScriptsChanged();
} }
void ScriptManager::Remove(Script *script) void ScriptManager::Remove(Script *script)
@ -334,11 +336,14 @@ namespace Automation4 {
delete *i; delete *i;
scripts.erase(i); scripts.erase(i);
} }
ScriptsChanged();
} }
void ScriptManager::RemoveAll() void ScriptManager::RemoveAll()
{ {
delete_clear(scripts); delete_clear(scripts);
ScriptsChanged();
} }
const std::vector<cmd::Command*>& ScriptManager::GetMacros() const std::vector<cmd::Command*>& ScriptManager::GetMacros()
@ -361,7 +366,7 @@ namespace Automation4 {
void AutoloadScriptManager::Reload() void AutoloadScriptManager::Reload()
{ {
RemoveAll(); delete_clear(scripts);
int error_count = 0; int error_count = 0;
@ -386,7 +391,7 @@ namespace Automation4 {
wxString fullpath = script_path.GetFullPath(); wxString fullpath = script_path.GetFullPath();
if (ScriptFactory::CanHandleScriptFormat(fullpath)) { if (ScriptFactory::CanHandleScriptFormat(fullpath)) {
Script *s = ScriptFactory::CreateFromFile(fullpath, true); Script *s = ScriptFactory::CreateFromFile(fullpath, true);
Add(s); scripts.push_back(s);
if (!s->GetLoadedState()) error_count++; if (!s->GetLoadedState()) error_count++;
} }
more = dir.GetNext(&fn); more = dir.GetNext(&fn);
@ -395,6 +400,8 @@ namespace Automation4 {
if (error_count > 0) { if (error_count > 0) {
wxLogWarning("One or more scripts placed in the Automation autoload directory failed to load\nPlease review the errors above, correct them and use the Reload Autoload dir button in Automation Manager to attempt loading the scripts again."); wxLogWarning("One or more scripts placed in the Automation autoload directory failed to load\nPlease review the errors above, correct them and use the Reload Autoload dir button in Automation Manager to attempt loading the scripts again.");
} }
ScriptsChanged();
} }
LocalScriptManager::LocalScriptManager(agi::Context *c) LocalScriptManager::LocalScriptManager(agi::Context *c)
@ -406,7 +413,7 @@ namespace Automation4 {
void LocalScriptManager::Reload() void LocalScriptManager::Reload()
{ {
RemoveAll(); delete_clear(scripts);
wxString local_scripts = context->ass->GetScriptInfo("Automation Scripts"); wxString local_scripts = context->ass->GetScriptInfo("Automation Scripts");
if (local_scripts.empty()) return; if (local_scripts.empty()) return;
@ -434,12 +441,15 @@ namespace Automation4 {
wxFileName sfname(trimmed); wxFileName sfname(trimmed);
sfname.MakeAbsolute(basepath); sfname.MakeAbsolute(basepath);
if (sfname.FileExists()) { if (sfname.FileExists()) {
Add(Automation4::ScriptFactory::CreateFromFile(sfname.GetFullPath(), true)); scripts.push_back(Automation4::ScriptFactory::CreateFromFile(sfname.GetFullPath(), true));
} else { }
else {
wxLogWarning("Automation Script referenced could not be found.\nFilename specified: %c%s\nSearched relative to: %s\nResolved filename: %s", wxLogWarning("Automation Script referenced could not be found.\nFilename specified: %c%s\nSearched relative to: %s\nResolved filename: %s",
first_char, trimmed, basepath, sfname.GetFullPath()); first_char, trimmed, basepath, sfname.GetFullPath());
} }
} }
ScriptsChanged();
} }
void LocalScriptManager::OnSubtitlesSave() void LocalScriptManager::OnSubtitlesSave()

View file

@ -206,9 +206,12 @@ namespace Automation4 {
/// A manager of loaded automation scripts /// A manager of loaded automation scripts
class ScriptManager { class ScriptManager {
protected:
std::vector<Script*> scripts; std::vector<Script*> scripts;
std::vector<cmd::Command*> macros; std::vector<cmd::Command*> macros;
agi::signal::Signal<> ScriptsChanged;
public: public:
/// Deletes all scripts managed /// Deletes all scripts managed
virtual ~ScriptManager(); virtual ~ScriptManager();
@ -227,6 +230,8 @@ namespace Automation4 {
const std::vector<cmd::Command*>& GetMacros(); const std::vector<cmd::Command*>& GetMacros();
// No need to have getters for the other kinds of features, I think. // No need to have getters for the other kinds of features, I think.
// They automatically register themselves in the relevant places. // They automatically register themselves in the relevant places.
DEFINE_SIGNAL_ADDERS(ScriptsChanged, AddScriptChangeListener)
}; };
/// Manager for scripts specified by a subtitle file /// Manager for scripts specified by a subtitle file

View file

@ -26,15 +26,15 @@
{ "command" : "edit/line/delete" } { "command" : "edit/line/delete" }
], ],
"main" : [ "main" : [
{ "submenu" : "main/file", "text" : "&File" }, { "submenu" : "main/file", "text" : "&File" },
{ "submenu" : "main/edit", "text" : "&Edit" }, { "submenu" : "main/edit", "text" : "&Edit" },
{ "submenu" : "main/subtitle", "text" : "&Subtitle" }, { "submenu" : "main/subtitle", "text" : "&Subtitle" },
{ "submenu" : "main/timing", "text" : "&Timing" }, { "submenu" : "main/timing", "text" : "&Timing" },
{ "submenu" : "main/video", "text" : "&Video" }, { "submenu" : "main/video", "text" : "&Video" },
{ "submenu" : "main/audio", "text" : "&Audio" }, { "submenu" : "main/audio", "text" : "&Audio" },
{ "submenu" : "main/automation", "text" : "A&utomation" }, { "special" : "automation", "text" : "A&utomation" },
{ "submenu" : "main/view", "text" : "&View" }, { "submenu" : "main/view", "text" : "&View" },
{ "submenu" : "main/help", "text" : "&Help", "special" : "help" } { "submenu" : "main/help", "text" : "&Help", "special" : "help" }
], ],
"main/file" : [ "main/file" : [
{ "command" : "subtitle/new" }, { "command" : "subtitle/new" },
@ -168,10 +168,6 @@
{ "command" : "audio/open/blank" }, { "command" : "audio/open/blank" },
{ "command" : "audio/open/noise" } { "command" : "audio/open/noise" }
], ],
"main/automation" : [
{ "command" : "am/manager" },
{}
],
"main/view" : [ "main/view" : [
{ "command" : "app/language" }, { "command" : "app/language" },
{ "command" : "app/options", "special" : "options" }, { "command" : "app/options", "special" : "options" },

View file

@ -22,8 +22,10 @@
#include "include/aegisub/menu.h" #include "include/aegisub/menu.h"
#include "include/aegisub/context.h"
#include "include/aegisub/hotkey.h" #include "include/aegisub/hotkey.h"
#include "auto4_base.h"
#include "command/command.h" #include "command/command.h"
#include "compat.h" #include "compat.h"
#include "libresrc/libresrc.h" #include "libresrc/libresrc.h"
@ -113,6 +115,14 @@ public:
} }
}; };
struct menu_item_cmp {
wxMenuItem *item;
menu_item_cmp(wxMenuItem *item) : item(item) { }
bool operator()(std::pair<cmd::Command*, wxMenuItem*> o) const {
return o.second == item;
}
};
/// @class CommandManager /// @class CommandManager
/// @brief Event dispatcher to update menus on open and handle click events /// @brief Event dispatcher to update menus on open and handle click events
/// ///
@ -171,6 +181,14 @@ public:
return item->GetId(); return item->GetId();
} }
/// Unregister a dynamic menu item
void Remove(wxMenuItem *item) {
std::deque<std::pair<cmd::Command*, wxMenuItem*> >::iterator it =
find_if(dynamic_items.begin(), dynamic_items.end(), menu_item_cmp(item));
if (it != dynamic_items.end())
dynamic_items.erase(it);
}
/// Create a MRU menu and register the needed handlers /// Create a MRU menu and register the needed handlers
/// @param name MRU type /// @param name MRU type
/// @param parent Menu to append the new MRU menu to /// @param parent Menu to append the new MRU menu to
@ -280,12 +298,6 @@ void process_menu_item(wxMenu *parent, agi::Context *c, json::Object const& ele,
return; return;
} }
if (special == "automation") {
/// @todo Actually implement this
parent->Append(-1, _("No Automation macros loaded"))->Enable(false);
return;
}
if (!read_entry(ele, "command", &command)) if (!read_entry(ele, "command", &command))
return; return;
@ -325,6 +337,51 @@ wxMenu *build_menu(std::string const& name, agi::Context *c, CommandManager *cm,
return menu; return menu;
} }
struct comp_str_menu {
agi::Context *c;
comp_str_menu(agi::Context *c) : c(c) { }
bool operator()(const cmd::Command *lft, const cmd::Command *rgt) const {
return lft->StrMenu(c) < rgt->StrMenu(c);
}
};
class AutomationMenu : public wxMenu {
agi::Context *c;
CommandManager *cm;
agi::signal::Connection global_slot;
agi::signal::Connection local_slot;
void Regenerate() {
wxMenuItemList &items = GetMenuItems();
for (size_t i = items.size() - 1; i >= 2; --i) {
cm->Remove(items[i]);
Delete(items[i]);
}
std::vector<cmd::Command*> macros = wxGetApp().global_scripts->GetMacros();
std::vector<cmd::Command*> local_macros = c->local_scripts->GetMacros();
copy(local_macros.begin(), local_macros.end(), back_inserter(macros));
sort(macros.begin(), macros.end(), comp_str_menu(c));
if (macros.empty())
Append(-1, _("No Automation macros loaded"))->Enable(false);
else {
for (size_t i = 0; i < macros.size(); ++i)
cm->AddCommand(macros[i], this, "");
}
}
public:
AutomationMenu(agi::Context *c, CommandManager *cm)
: c(c)
, cm(cm)
, global_slot(wxGetApp().global_scripts->AddScriptChangeListener(&AutomationMenu::Regenerate, this))
, local_slot(c->local_scripts->AddScriptChangeListener(&AutomationMenu::Regenerate, this))
{
cm->AddCommand(cmd::get("am/manager"), this, "");
AppendSeparator();
Regenerate();
}
};
} }
namespace menu { namespace menu {
@ -336,7 +393,14 @@ namespace menu {
std::string submenu, disp; std::string submenu, disp;
read_entry(*it, "submenu", &submenu); read_entry(*it, "submenu", &submenu);
read_entry(*it, "text", &disp); read_entry(*it, "text", &disp);
menu->Append(build_menu(submenu, c, &menu->cm), lagi_wxString(disp)); if (!submenu.empty()) {
menu->Append(build_menu(submenu, c, &menu->cm), lagi_wxString(disp));
}
else {
read_entry(*it, "special", &submenu);
if (submenu == "automation")
menu->Append(new AutomationMenu(c, &menu->cm), lagi_wxString(disp));
}
} }
window->SetMenuBar(menu); window->SetMenuBar(menu);