diff --git a/aegisub/Makefile.target b/aegisub/Makefile.target index faca12b97..cedeb5b77 100644 --- a/aegisub/Makefile.target +++ b/aegisub/Makefile.target @@ -30,7 +30,7 @@ ifdef LIB_SHARED LIB_SHARED_FULL = $(LIB_SHARED).$(LIB_VERSION) $(LIB_SHARED) : $(OBJ) $(BIN_CXX) $(LIB_SHARED_LINK) $(LDFLAGS) $(OBJ) -o $(LIB_SHARED_FULL) - $(BIN_LN) -s $(LIB_SHARED_FULL) $(LIB_SHARED) + $(BIN_LN) -sf $(LIB_SHARED_FULL) $(LIB_SHARED) CLEANFILES+= $(LIB_SHARED_FULL) endif diff --git a/aegisub/docs/doxygen/doxyfile_base b/aegisub/docs/doxygen/doxyfile_base index 704d97afa..64e241d61 100644 --- a/aegisub/docs/doxygen/doxyfile_base +++ b/aegisub/docs/doxygen/doxyfile_base @@ -12,7 +12,7 @@ OUTPUT_LANGUAGE = English BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = -ALWAYS_DETAILED_SEC = YES +ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = YES STRIP_FROM_PATH = $(SRC_TRIM) @@ -48,7 +48,7 @@ EXTRACT_PRIVATE = YES EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = YES -EXTRACT_ANON_NSPACES = YES +EXTRACT_ANON_NSPACES = NO HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO @@ -56,12 +56,12 @@ HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES +SHOW_INCLUDE_FILES = NO INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_GROUP_NAMES = NO -SORT_BY_SCOPE_NAME = NO +SORT_BY_SCOPE_NAME = YES GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES @@ -111,7 +111,7 @@ INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES # FIXME: set these two to NO? REFERENCED_BY_RELATION = YES -REFERENCES_RELATION = YES +REFERENCES_RELATION = NO REFERENCES_LINK_SOURCE = YES USE_HTAGS = NO VERBATIM_HEADERS = YES @@ -216,7 +216,12 @@ INCLUDE_PATH = INCLUDE_FILE_PATTERNS = #PREDEFINED = PREDEFINED += WXUNUSED(x)= -EXPAND_AS_DEFINED = +PREDEFINED += "CMD_NAME(a)=const char* name() { return a; } ///< a" +PREDEFINED += "STR_MENU(a)=wxString StrMenu() const { return a; } ///< a" +PREDEFINED += "STR_DISP(a)=wxString StrDisplay() const { return a; } ///< a" +PREDEFINED += "STR_HELP(a)=wxString StrHelp() const { return a; } ///< a" + +#EXPAND_AS_DEFINED = CMD_NAME STR_MENU STR_DISP STR_HELP SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references @@ -260,3 +265,4 @@ DOT_CLEANUP = YES # Options related to the search engine #--------------------------------------------------------------------------- SEARCHENGINE = NO +SERVER_BASED_SEARCH = YES diff --git a/aegisub/docs/doxygen/pages_aegisub/index.dox b/aegisub/docs/doxygen/pages_aegisub/index.dox index 3ae3cc409..e309597ce 100644 --- a/aegisub/docs/doxygen/pages_aegisub/index.dox +++ b/aegisub/docs/doxygen/pages_aegisub/index.dox @@ -1,5 +1,8 @@ /** @mainpage +

Source Groups

+ + +
Main - @ref main - @ref main_headers @@ -24,6 +27,8 @@ Dialogues - @ref thesaurus - @ref visual_ts + Miscellanous - @ref build - @ref tools_ui @@ -46,4 +51,26 @@ Video - @ref video_input - @ref video_output +
+ +
+ + +

Available Command List

+ - @ref cmd-app + - @ref cmd-audio + - @ref cmd-am + - @ref cmd-edit + - @ref cmd-grid + - @ref cmd-help + - @ref cmd-keyframed + - @ref cmd-menu + - @ref cmd-recent + - @ref cmd-subtitle + - @ref cmd-time + - @ref cmd-timecode + - @ref cmd-tool + - @ref cmd-video + + */ diff --git a/aegisub/libaegisub/Makefile b/aegisub/libaegisub/Makefile index fe87afa85..1e9e7d5da 100644 --- a/aegisub/libaegisub/Makefile +++ b/aegisub/libaegisub/Makefile @@ -21,6 +21,8 @@ SRC = \ common/charset.cpp \ common/charset_conv.cpp \ common/charset_ucd.cpp \ + common/hotkey.cpp \ + common/json.cpp \ common/mru.cpp \ common/option.cpp \ common/option_visit.cpp \ diff --git a/aegisub/libaegisub/common/hotkey.cpp b/aegisub/libaegisub/common/hotkey.cpp new file mode 100644 index 000000000..a0cfd68fe --- /dev/null +++ b/aegisub/libaegisub/common/hotkey.cpp @@ -0,0 +1,196 @@ +// Copyright (c) 2010, Amar Takhar +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// $Id$ + +/// @file hotkey.cpp +/// @brief Hotkey handler +/// @ingroup hotkey menu event window + +#include "config.h" + +#ifndef LAGI_PRE +#include + +#include +#endif + +#include "libaegisub/access.h" +#include "libaegisub/io.h" +#include "libaegisub/json.h" +#include "libaegisub/log.h" +#include "libaegisub/hotkey.h" + +namespace agi { + namespace hotkey { + +Hotkey *hotkey; + +std::string Combo::Str() { + std::string str(key_map[0]); + for (unsigned int i=1; i < key_map.size(); i++) { + str.append("-" + key_map[i]); + } + return str; +} + +std::string Combo::StrMenu() { + return Str(); +} + +void Hotkey::ComboInsert(Combo *combo) { + map.insert(HotkeyMapPair(combo->Str(), combo)); +} + +Hotkey::~Hotkey() { + Flush(); +} + +Hotkey::Hotkey(const std::string &file, const std::string &default_config): + config_file(file), config_default(default_config) { + + LOG_D("hotkey/init") << "Generating hotkeys."; + + std::istream *stream; + + try { + stream = agi::io::Open(config_file); + } catch (const acs::AcsNotFound&) { +stream = new std::istringstream(config_default); + } + + + json::UnknownElement hotkey_root; + try { + hotkey_root = agi::json_util::parse(stream); + } catch (json::Reader::ParseException& e) { + // There's definatly a better way to do this. + std::istringstream *stream = new std::istringstream(config_default); + hotkey_root = agi::json_util::parse(stream); + } + + json::Object object = hotkey_root; + + + for (json::Object::const_iterator index(object.Begin()); index != object.End(); index++) { + const json::Object::Member& member = *index; + const json::Object& obj = member.element; + BuildHotkey(member.name, obj); + } +} + + +void Hotkey::BuildHotkey(std::string context, const json::Object& object) { + + for (json::Object::const_iterator index(object.Begin()); index != object.End(); index++) { + const json::Object::Member& member = *index; + + + const json::Array& array = member.element; + for (json::Array::const_iterator arr_index(array.Begin()); arr_index != array.End(); arr_index++) { + + Combo *combo = new Combo(context, member.name); + + const json::Object& obj = *arr_index; + + const json::Array& arr_mod = obj["modifiers"]; + + if (arr_mod.Size() > 0) { + for (json::Array::const_iterator arr_mod_index(arr_mod.Begin()); arr_mod_index != arr_mod.End(); arr_mod_index++) { + const json::String& key_mod = *arr_mod_index; + combo->KeyInsert(key_mod.Value()); + } // for arr_mod_index + + } + const json::String& key = obj["key"]; + combo->KeyInsert(key.Value()); + + const json::Boolean& enable = obj["enable"]; + combo->Enable(enable); + + ComboInsert(combo); + } // for arr_index + } // for index +} + + +bool Hotkey::Scan(const std::string context, const std::string str, std::string &cmd) { + HotkeyMap::iterator index; + std::pair range; + + range = map.equal_range(str); + std::string local, dfault; + + + for (index = range.first; index != range.second; ++index) { + + std::string ctext = (*index).second->Context(); + + if (ctext == "Always") { + cmd = (*index).second->CmdName(); + LOG_D("agi/hotkey/found") << "Found: " << str << " Context (req/found): " << context << "/Always Command: " << cmd; + return 0; + } else if (ctext == "Default") { + dfault = (*index).second->CmdName(); + } else if (ctext == context) { + local = (*index).second->CmdName(); + } + } + + if (!local.empty()) { + cmd = local; + LOG_D("agi/hotkey/found") << "Found: " << str << " Context: " << context << " Command: " << local; + return 0; + } else if (!dfault.empty()) { + cmd = dfault; + LOG_D("agi/hotkey/found") << "Found: " << str << " Context (req/found): " << context << "/Default Command: " << dfault; + return 0; + } + + return 1; + +} + +void Hotkey::Flush() { + + json::Object root; + + HotkeyMap::iterator index; + for (index = map.begin(); index != map.end(); ++index) { + + Combo::ComboMap combo_map(index->second->Get()); + + json::Array modifiers; + for (int i = 0; i != combo_map.size()-1; i++) { + modifiers.Insert(json::String(combo_map[i])); + } + + json::Object hotkey; + hotkey["modifiers"] = modifiers; + hotkey["key"] = json::String(combo_map.back()); + hotkey["enable"] = json::Boolean(index->second->IsEnabled()); + + json::Object& context_obj = root[index->second->Context()]; + json::Array& combo_array = context_obj[index->second->CmdName()]; + + combo_array.Insert(hotkey); + } + + io::Save file(config_file); + json::Writer::Write(root, file.Get()); + +} + + } // namespace toolbar +} // namespace agi diff --git a/aegisub/libaegisub/common/json.cpp b/aegisub/libaegisub/common/json.cpp new file mode 100644 index 000000000..c78574ec1 --- /dev/null +++ b/aegisub/libaegisub/common/json.cpp @@ -0,0 +1,73 @@ +// Copyright (c) 2010, Amar Takhar +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// $Id$ + +/// @file json.cpp +/// @brief Parse JSON files and return json::UnknownElement +/// @ingroup libaegisub io + + +#ifdef LAGI_PRE +#include +#include +#endif + +#include "libaegisub/access.h" +#include "libaegisub/io.h" +#include "libaegisub/json.h" + + +namespace agi { + namespace json_util { + +json::UnknownElement parse(std::istream *stream) { + json::UnknownElement root; + + try { + json::Reader::Read(root, *stream); + } catch (json::Reader::ParseException& e) { + std::cout << "json::ParseException: " << e.what() << ", Line/offset: " << e.m_locTokenBegin.m_nLine + 1 << '/' << e.m_locTokenBegin.m_nLineOffset + 1 << std::endl << std::endl; + } catch (json::Exception& e) { + /// @todo Do something better here, maybe print the exact error + std::cout << "json::Exception: " << e.what() << std::endl; + } + + delete stream; + return root; +} + + +json::UnknownElement file(const std::string file) { + return parse(io::Open(file)); +} + + +json::UnknownElement file(const std::string file, const std::string &default_config) { + + try { + return parse(io::Open(file)); + + // We only want to catch this single error as anything else could + // reflect a deeper problem. ie, failed i/o, wrong permissions etc. + } catch (const acs::AcsNotFound&) { + + std::istringstream stream(default_config); + return parse(&stream); + } +} + + + } // namespace json_util +} // namespace agi diff --git a/aegisub/libaegisub/common/log.cpp b/aegisub/libaegisub/common/log.cpp index 4f30d38bc..968eab747 100644 --- a/aegisub/libaegisub/common/log.cpp +++ b/aegisub/libaegisub/common/log.cpp @@ -27,6 +27,9 @@ #include #endif +#include "libaegisub/cajun/elements.h" +#include "libaegisub/cajun/writer.h" +#include "libaegisub/io.h" #include "libaegisub/log.h" #include "libaegisub/mutex.h" #include "libaegisub/types.h" @@ -36,7 +39,7 @@ namespace agi { namespace log { /// Global log sink. -std::auto_ptr log(new LogSink()); +LogSink *log; /// Short Severity ID /// Keep this ordered the same as Severity @@ -61,11 +64,51 @@ SinkMessage::~SinkMessage() { } -LogSink::LogSink() { +LogSink::LogSink(const std::string dir_log): dir_log(dir_log) { + util::time_log(time_start); } +/// @todo The log files need to be trimed after N amount. LogSink::~LogSink() { -/// @todo This needs to flush all log data to disk on quit. + json::Object root; + json::Array array; + + agi_timeval time_close; + util::time_log(time_close); + + std::stringstream str; + str << dir_log << time_start.tv_sec << ".json"; + io::Save file(str.str()); + + for (unsigned int i=0; i < sink.size(); i++) { + json::Object entry; + entry["sec"] = json::Number(sink[i]->tv.tv_sec); + entry["usec"] = json::Number(sink[i]->tv.tv_usec); + entry["severity"] = json::Number(sink[i]->severity), + entry["section"] = json::String(sink[i]->section); + entry["file"] = json::String(sink[i]->file); + entry["func"] = json::String(sink[i]->func); + entry["line"] = json::Number(sink[i]->line); + entry["message"] = json::String(std::string(sink[i]->message, sink[i]->len)); + + array.Insert(entry); + } + + json::Array timeval_open; + timeval_open.Insert(json::Number(time_start.tv_sec)); + timeval_open.Insert(json::Number(time_start.tv_usec)); + root["timeval"]["open"] = timeval_open; + + json::Array timeval_close; + timeval_close.Insert(json::Number(time_close.tv_sec)); + timeval_close.Insert(json::Number(time_close.tv_usec)); + root["timeval"]["close"] = timeval_close; + + + root["log"] = array; + + json::Writer::Write(root, file.Get()); + agi::util::delete_clear(sink); } diff --git a/aegisub/libaegisub/include/libaegisub/charset.h b/aegisub/libaegisub/include/libaegisub/charset.h index fca82fa68..83fe98507 100644 --- a/aegisub/libaegisub/include/libaegisub/charset.h +++ b/aegisub/libaegisub/include/libaegisub/charset.h @@ -27,6 +27,7 @@ #include namespace agi { + /// Character set conversion and detection. namespace charset { DEFINE_BASE_EXCEPTION_NOINNER(CharsetError, agi::Exception) diff --git a/aegisub/libaegisub/include/libaegisub/exception.h b/aegisub/libaegisub/include/libaegisub/exception.h index 1353244f2..b6b28b355 100644 --- a/aegisub/libaegisub/include/libaegisub/exception.h +++ b/aegisub/libaegisub/include/libaegisub/exception.h @@ -63,11 +63,11 @@ namespace agi { /// When throwing exceptions, throw temporaries, not heap allocated /// objects. (C++ FAQ Lite 17.6.) I.e. this is correct: /// @code - /// throw Aegisub::SomeException("Message for exception"); + /// throw agi::SomeException("Message for exception"); /// @endcode /// This is wrong: /// @code - /// throw new Aegisub::SomeException("Remember this is the wrong way!"); + /// throw new agi::SomeException("Remember this is the wrong way!"); /// @endcode /// Exceptions must not be allocated on heap, because of the risks of /// leaking memory that way. (C++ FAQ Lite 17.8.) @@ -81,10 +81,10 @@ namespace agi { /// try { /// /* ... */ /// } - /// catch (Aegisub::UserCancelException &e) { + /// catch (agi::UserCancelException &e) { /// /* handle the fact that the user cancelled */ /// } - /// catch (Aegisub::VideoInputException &e) { + /// catch (agi::VideoInputException &e) { /// /* handle the video provider failing */ /// } /// @endcode @@ -238,8 +238,8 @@ namespace agi { }; - /// @class Aegisub::UserCancelException - /// @extends Aegisub::Exception + /// @class agi::UserCancelException + /// @extends agi::Exception /// @brief Exception for "user cancel" events /// /// I.e. when we want to abort an operation because the user requested that we do so. @@ -253,8 +253,8 @@ namespace agi { DEFINE_SIMPLE_EXCEPTION_NOINNER(UserCancelException,Exception,"nonerror/user_cancel") - /// @class Aegisub::InternalError - /// @extends Aegisub::Exception + /// @class agi::InternalError + /// @extends agi:Exception /// @brief Errors that should never happen and point to some invalid assumption in the code /// /// Throw an internal error when a sanity check fails, and the insanity should have @@ -265,8 +265,8 @@ namespace agi { DEFINE_SIMPLE_EXCEPTION(InternalError, Exception, "internal_error") - /// @class Aegisub::FileSystemError - /// @extends Aegisub::Exception + /// @class agi::FileSystemError + /// @extends agi::Exception /// @brief Base class for errors related to the file system /// /// This base class can not be instantiated. @@ -274,8 +274,8 @@ namespace agi { /// causes for errors. DEFINE_BASE_EXCEPTION_NOINNER(FileSystemError,Exception) - /// @class Aegisub::FileNotAccessibleError - /// @extends Aegisub::FileSystemError + /// @class agi::FileNotAccessibleError + /// @extends agi::FileSystemError /// @brief A file can't be accessed for some reason DEFINE_SIMPLE_EXCEPTION_NOINNER(FileNotAccessibleError,FileSystemError,"filesystem/not_accessible") @@ -289,16 +289,16 @@ namespace agi { /// @param filename Name of the file that could not be found FileNotFoundError(const std::string &filename) : FileNotAccessibleError(std::string("File not found: ") + filename) { } - // Not documented, see Aegisub::Exception class + // Not documented, see agi::Exception class const char * GetName() const { return "filesystem/not_accessible/not_found"; } - // Not documented, see Aegisub::Exception class + // Not documented, see agi::Exception class Exception * Copy() const { return new FileNotFoundError(*this); } }; - /// @class Aegisub::InvalidInputException - /// @extends Aegisub::Exception + /// @class agi::InvalidInputException + /// @extends agi::Exception /// @brief Some input data were invalid and could not be processed DEFINE_BASE_EXCEPTION(InvalidInputException,Exception) diff --git a/aegisub/libaegisub/include/libaegisub/hotkey.h b/aegisub/libaegisub/include/libaegisub/hotkey.h new file mode 100644 index 000000000..a274c5e91 --- /dev/null +++ b/aegisub/libaegisub/include/libaegisub/hotkey.h @@ -0,0 +1,134 @@ +// Copyright (c) 2010, Amar Takhar +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// $Id$ + +/// @file hotkey.h +/// @brief Hotkey handler +/// @ingroup hotkey menu event window + +#include "config.h" + +#ifndef LAGI_PRE +#include + +#include +#endif + +#include + + +namespace agi { + namespace hotkey { + + +class Hotkey; +/// Hotkey instance. +extern Hotkey *hotkey; + +/// @class Combo +/// A Combo represents a linear sequence of characters set in an std::vector. This makes up +/// a single combination, or "Hotkey". +class Combo { +friend class Hotkey; + +public: + /// Linear key sequence that forms a combination or "Combo" + typedef std::vector ComboMap; + + /// Constructor + /// @param ctx Context + /// @param cmd Command name + Combo(std::string ctx, std::string cmd): cmd_name(cmd), context(ctx) {} + + /// Destructor + ~Combo() {} + + /// String representation of the Combo + std::string Str(); + + /// String suitable for usage in a menu. + std::string StrMenu(); + + /// Get the literal combo map. + /// @return ComboMap (std::vector) of linear key sequence. + const ComboMap& Get() { return key_map; } + + /// Command name triggered by the combination. + /// @return Command name + const std::string& CmdName() { return cmd_name; } + + /// Context this Combo is triggered in. + const std::string& Context() { return context; } + + /// Enable or disable Combo or "Hotkey". + /// @param e Bool state. + void Enable(bool e) { enable = e; } + + /// Check whether Combo is currently enabled or disabled. + /// @return State. + const bool& IsEnabled() { return enable; } + +private: + ComboMap key_map; ///< Map. + const std::string cmd_name; ///< Command name. + const std::string context; ///< Context + bool enable; ///< Enable/Disable state + + /// Insert a key into the ComboMap. + /// @param key Key to insert. + void KeyInsert(std::string key) { key_map.push_back(key); } +}; + + +/// @class Hotkey +/// Holds the map of Combo instances and handles searching for matching key sequences. +class Hotkey { +public: + /// Constructor + /// @param file Location of user config file. + /// @param default_config Default config. + Hotkey(const std::string &file, const std::string &default_config); + + /// Destructor. + ~Hotkey(); + + /// Scan for a matching key. + /// @param context Context requested. + /// @param str Hyphen seperated key squence. + /// @param[out] cmd Command found. + bool Scan(const std::string context, const std::string str, std::string &cmd); + +private: + typedef std::multimap HotkeyMap; ///< Map to hold Combo instances. + typedef std::pair HotkeyMapPair; ///< Pair for HotkeyMap. + HotkeyMap map; ///< HotkeyMap Instance. + const std::string config_file; ///< Default user config location. + const std::string config_default; ///< Default config. + + /// Build hotkey map. + /// @param context Context being parsed. + /// @param object json::Object holding items for context being parsed. + void BuildHotkey(std::string context, const ::json::Object& object); + + /// Insert Combo into HotkeyMap instance. + /// @param combo Combo to insert. + void ComboInsert(Combo *combo); + + /// Write active Hotkey configuration to disk. + void Flush(); +}; + + } // namespace hotkey +} // namespace agi diff --git a/aegisub/libaegisub/include/libaegisub/json.h b/aegisub/libaegisub/include/libaegisub/json.h new file mode 100644 index 000000000..e2f5623a1 --- /dev/null +++ b/aegisub/libaegisub/include/libaegisub/json.h @@ -0,0 +1,46 @@ +// Copyright (c) 2010, Amar Takhar +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// $Id$ + +/// @file json.h +/// @brief Parse JSON files and return json::UnknownElement +/// @ingroup libaegisub io + + +#include +#include + +namespace agi { + namespace json_util { + +/// Parse a JSON stream. +/// @param stream JSON stream, this is deleted internally. +/// @return json::UnknownElement +json::UnknownElement parse(std::istream *stream); + +/// Parse a JSON file. +/// @param file Path JSON to file +/// @return json::UnknownElement +json::UnknownElement file(const std::string file); + +/// Parse a json stream, with default handler. +/// @param file Path to JSON file. +/// @param Default config file to load incase of nonexistent file +/// @return json::UnknownElement +json::UnknownElement file(const std::string file, const std::string &default_config); + + + } // namespace json_util +} // namespace agi diff --git a/aegisub/libaegisub/include/libaegisub/log.h b/aegisub/libaegisub/include/libaegisub/log.h index 7c579b752..26d7c53b5 100644 --- a/aegisub/libaegisub/include/libaegisub/log.h +++ b/aegisub/libaegisub/include/libaegisub/log.h @@ -68,7 +68,7 @@ enum Severity { extern const char *Severity_ID; /// Global log sink. -extern std::auto_ptr log; +extern LogSink *log; /// Container to hold a single message struct SinkMessage { @@ -111,9 +111,17 @@ class LogSink { /// List of function pointers to emitters std::vector emitters; + /// Init time for log writing purposes. + agi_timeval time_start; + + /// Directory to place logfiles. + const std::string dir_log; + + public: /// Constructor - LogSink(); + /// @param dir_log Directory to place log files. + LogSink(const std::string dir_log); /// Destructor ~LogSink(); diff --git a/aegisub/libaegisub/include/libaegisub/mru.h b/aegisub/libaegisub/include/libaegisub/mru.h index 887486ef4..2e363c3db 100644 --- a/aegisub/libaegisub/include/libaegisub/mru.h +++ b/aegisub/libaegisub/include/libaegisub/mru.h @@ -97,7 +97,7 @@ private: /// Internal MRUMap values. MRUMap mru; - void Load(const std::string &key, const json::Array& array); + void Load(const std::string &key, const ::json::Array& array); inline void Prune(MRUListMap& map); }; diff --git a/aegisub/libaegisub/include/libaegisub/option.h b/aegisub/libaegisub/include/libaegisub/option.h index 1c4f81387..77919f3be 100644 --- a/aegisub/libaegisub/include/libaegisub/option.h +++ b/aegisub/libaegisub/include/libaegisub/option.h @@ -65,7 +65,7 @@ private: /// @brief Create option object. /// @param path Path to store - json::Object CreateObject(std::string path); + ::json::Object CreateObject(std::string path); /// User config (file that will be written to disk) const std::string config_file; @@ -89,7 +89,7 @@ protected: /// @param[out] obj Parent object /// @param[in] path Path option should be stored in. /// @param[in] value Value to write. - static bool PutOption(json::Object &obj, const std::string &path, const json::UnknownElement &value); + static bool PutOption(::json::Object &obj, const std::string &path, const ::json::UnknownElement &value); public: diff --git a/aegisub/libaegisub/include/libaegisub/scoped_ptr.h b/aegisub/libaegisub/include/libaegisub/scoped_ptr.h index c0d25e209..44eb9d1fc 100644 --- a/aegisub/libaegisub/include/libaegisub/scoped_ptr.h +++ b/aegisub/libaegisub/include/libaegisub/scoped_ptr.h @@ -12,7 +12,7 @@ // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // -// $Id$ +// $Id: scoped_ptr.h 153 2010-12-08 14:45:38Z verm $ /// @file scoped_ptr.h /// @brief diff --git a/aegisub/libaegisub/include/libaegisub/vfr.h b/aegisub/libaegisub/include/libaegisub/vfr.h index 2aff1d1e5..0574cf269 100644 --- a/aegisub/libaegisub/include/libaegisub/vfr.h +++ b/aegisub/libaegisub/include/libaegisub/vfr.h @@ -28,7 +28,8 @@ #include namespace agi { -namespace vfr { + /// Framerate handling. + namespace vfr { enum Time { /// Use the actual frame times @@ -134,5 +135,5 @@ public: double FPS() const { return fps; } }; -} -} + } // namespace vfr +} // namespace agi diff --git a/aegisub/po/make_pot.bat b/aegisub/po/make_pot.bat new file mode 100644 index 000000000..6bf402791 --- /dev/null +++ b/aegisub/po/make_pot.bat @@ -0,0 +1,4 @@ +del /s list.txt +dir /w /b ..\aegisub\*.cpp ..\aegisub\*.h >> list.txt +"C:\Program Files (x86)\GnuWin32\bin\xgettext.exe" --files-from=list.txt --directory=../aegisub/ --output=aegisub.pot --c++ -k_ +pause \ No newline at end of file diff --git a/aegisub/src/Makefile b/aegisub/src/Makefile index 7299a5b62..07f8ab542 100644 --- a/aegisub/src/Makefile +++ b/aegisub/src/Makefile @@ -5,14 +5,14 @@ PROGRAM_INSTALL = yes PRECOMPILED_HEADER_NAME=agi_pre.h -SUBDIRS = libresrc +SUBDIRS = command libresrc -CXXFLAGS += -DAEGISUB -I. -I.. -Iinclude -I../libaegisub/include $(CPPFLAGS_WX) +CXXFLAGS += -DAEGISUB -I. -I.. -Iinclude -I../libaegisub/include $(CFLAGS_PTHREAD) $(CPPFLAGS_WX) LDFLAGS += -L../libaegisub -laegisub-3.0 LDFLAGS += $(CFLAGS_DEBUG) $(CFLAGS_PROFILE) $(LDFLAGS_CCMALLOC) $(LDFLAGS_EFENCE) LDFLAGS += $(LDFLAGS_GL) $(LDFLAGS_PTHREAD) $(LDFLAGS_WX) $(LDFLAGS_FREETYPE) $(LDFLAGS_FONTCONFIG) -LDFLAGS_POST += libresrc/libresrc.a $(LDFLAGS_UCHARDET) +LDFLAGS_POST += libresrc/libresrc.a $(LDFLAGS_UCHARDET) command/aegisub_command.a ifdef BUILD_DARWIN LDFLAGS += -lz @@ -188,13 +188,13 @@ SRC += \ font_file_lister.cpp \ font_file_lister_fontconfig.cpp \ frame_main.cpp \ - frame_main_events.cpp \ gl_text.cpp \ gl_wrap.cpp \ help_button.cpp \ - hotkeys.cpp \ + hotkey.cpp \ kana_table.cpp \ main.cpp \ + menu.cpp \ md5.c \ mkv_wrap.cpp \ mythes.cxx \ @@ -230,6 +230,7 @@ SRC += \ timeedit_ctrl.cpp \ threaded_frame_source.cpp \ toggle_bitmap.cpp \ + toolbar.cpp \ tooltip_manager.cpp \ utils.cpp \ validators.cpp \ diff --git a/aegisub/src/audio_box.cpp b/aegisub/src/audio_box.cpp index 59f1b6c9f..2a40f365f 100644 --- a/aegisub/src/audio_box.cpp +++ b/aegisub/src/audio_box.cpp @@ -55,7 +55,6 @@ #include "audio_karaoke.h" #include "audio_timing.h" #include "frame_main.h" -#include "hotkeys.h" #include "include/aegisub/audio_player.h" #include "libresrc/libresrc.h" #include "main.h" diff --git a/aegisub/src/audio_controller.h b/aegisub/src/audio_controller.h index 81d7adfa4..aa016347e 100644 --- a/aegisub/src/audio_controller.h +++ b/aegisub/src/audio_controller.h @@ -33,6 +33,7 @@ /// @see audio_controller.cpp /// @ingroup audio_ui +#pragma once #ifndef AGI_PRE #include diff --git a/aegisub/src/base_grid.cpp b/aegisub/src/base_grid.cpp index f8551fcb1..6d3a89801 100644 --- a/aegisub/src/base_grid.cpp +++ b/aegisub/src/base_grid.cpp @@ -42,9 +42,12 @@ #include #include +#include #include #endif +#include "aegisub/hotkey.h" + #include "base_grid.h" #include "ass_dialogue.h" @@ -518,7 +521,7 @@ BEGIN_EVENT_TABLE(BaseGrid,wxWindow) EVT_SIZE(BaseGrid::OnSize) EVT_COMMAND_SCROLL(GRID_SCROLLBAR,BaseGrid::OnScroll) EVT_MOUSE_EVENTS(BaseGrid::OnMouseEvent) - EVT_KEY_DOWN(BaseGrid::OnKeyPress) + EVT_KEY_DOWN(BaseGrid::OnKeyDown) END_EVENT_TABLE() @@ -1142,11 +1145,15 @@ bool BaseGrid::IsDisplayed(AssDialogue *line) { /// @param event /// @return /// -void BaseGrid::OnKeyPress(wxKeyEvent &event) { +void BaseGrid::OnKeyDown(wxKeyEvent &event) { // Get size int w,h; GetClientSize(&w,&h); + hotkey::check("Subtitle Grid", event.GetKeyCode(), event.GetUnicodeKey(), event.GetModifiers()); + event.StopPropagation(); + + // Get scan code int key = event.GetKeyCode(); #ifdef __APPLE__ diff --git a/aegisub/src/base_grid.h b/aegisub/src/base_grid.h index c323a03fe..fb96b86b4 100644 --- a/aegisub/src/base_grid.h +++ b/aegisub/src/base_grid.h @@ -93,7 +93,7 @@ class BaseGrid : public wxWindow, public BaseSelectionController { void OnSize(wxSizeEvent &event); void OnScroll(wxScrollEvent &event); void OnMouseEvent(wxMouseEvent &event); - void OnKeyPress(wxKeyEvent &event); + void OnKeyDown(wxKeyEvent &event); void DrawImage(wxDC &dc); diff --git a/aegisub/src/command/Makefile b/aegisub/src/command/Makefile new file mode 100644 index 000000000..0f0111c3a --- /dev/null +++ b/aegisub/src/command/Makefile @@ -0,0 +1,34 @@ +include ../../Makefile.inc + +CXXFLAGS += -I../../ -I.. -I. -I../../libaegisub/include -I../include -DAEGISUB + +CXXFLAGS += $(CFLAGS_WX) +PRECOMPILED_HEADER_NAME=../agi_pre.h + + +LIB = aegisub_command.a + +SRC = \ + app.cpp \ + audio.cpp \ + automation.cpp \ + edit.cpp \ + grid.cpp \ + help.cpp \ + keyframe.cpp \ + medusa.cpp \ + menu.cpp \ + recent.cpp \ + subtitle.cpp \ + time.cpp \ + timecode.cpp \ + tool.cpp \ + video.cpp + +SRC += \ + icon.cpp \ + command.cpp + +HEADER = *.h + +include ../../Makefile.target diff --git a/aegisub/src/command/app.cpp b/aegisub/src/command/app.cpp new file mode 100644 index 000000000..67d804be2 --- /dev/null +++ b/aegisub/src/command/app.cpp @@ -0,0 +1,265 @@ +// Copyright (c) 2005-2010, Niels Martin Hansen +// Copyright (c) 2005-2010, Rodrigo Braz Monteiro +// Copyright (c) 2010, Amar Takhar +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Aegisub Project http://www.aegisub.org/ +// +// $Id$ + +/// @file app.cpp +/// @brief app/ commands. +/// @ingroup command +/// + +#include "config.h" + +#ifndef AGI_PRE +#endif + +#include "command.h" + +#include "aegisub/context.h" +#include "main.h" + +#include "dialog_about.h" +#include "audio_controller.h" +#include "frame_main.h" +#include "video_context.h" +#include "utils.h" +#include "dialog_log.h" +#include "preferences.h" +#include "dialog_version_check.h" + + +namespace cmd { +/// @defgroup cmd-app Application related +/// @{ + +/// Launch about dialogue. +class app_about: public Command { +public: + CMD_NAME("app/about") + STR_MENU("&About..") + STR_DISP("About") + STR_HELP("About Aegisub.") + + void operator()(agi::Context *c) { + AboutScreen About(c->parent); + About.ShowModal(); + } +}; + + +/// Display audio and subtitles. +class app_display_audio_subs: public Command { +public: + CMD_NAME("app/display/audio_subs") + STR_MENU("Audio+Subs View") + STR_DISP("Audio+Subs View") + STR_HELP("Display audio and subtitles only.") + + void operator()(agi::Context *c) { + if (!c->audioController->IsAudioOpen()) return; + wxGetApp().frame->SetDisplayMode(0,1); + } +}; + + +/// Display audio, video and subtitles. +class app_display_full: public Command { +public: + CMD_NAME("app/display/full") + STR_MENU("Full view") + STR_DISP("Full view") + STR_HELP("Display audio, video and subtitles.") + + void operator()(agi::Context *c) { + if (!c->audioController->IsAudioOpen() || !VideoContext::Get()->IsLoaded()) return; + wxGetApp().frame->SetDisplayMode(1,1); + } +}; + + +/// Display subtitles only. +class app_display_subs: public Command { +public: + CMD_NAME("app/display/subs") + STR_MENU("Subs Only View") + STR_DISP("Subs Only View") + STR_HELP("Display subtitles only.") + + void operator()(agi::Context *c) { + wxGetApp().frame->SetDisplayMode(0,0); + } +}; + + +/// Display video and subtitles only. +class app_display_video_subs: public Command { +public: + CMD_NAME("app/display/video_subs") + STR_MENU("Video+Subs View") + STR_DISP("Video+Subs View") + STR_HELP("Display video and subtitles only.") + + void operator()(agi::Context *c) { + wxGetApp().frame->SetDisplayMode(1,0); + } +}; + + +/// Exit the application. +class app_exit: public Command { +public: + CMD_NAME("app/exit") + STR_MENU("E&xit") + STR_DISP("Exit") + STR_HELP("Exit the application.") + + void operator()(agi::Context *c) { + printf("XXX: not working yet\n"); + } +}; + + +/// Select Aegisub interface language +class app_language: public Command { +public: + CMD_NAME("app/language") + STR_MENU("&Language...") + STR_DISP("Language") + STR_HELP("Select Aegisub interface language") + + void operator()(agi::Context *c) { + // Get language + AegisubApp *app = (AegisubApp*) wxTheApp; + int old = app->locale.curCode; + int newCode = app->locale.PickLanguage(); + // Is OK? + if (newCode != -1) { + // Set code + OPT_SET("App/Locale")->SetInt(newCode); + + // Language actually changed? + if (newCode != old) { + // Ask to restart program + int result = wxMessageBox(_T("Aegisub needs to be restarted so that the new language can be applied. Restart now?"),_T("Restart Aegisub?"),wxICON_QUESTION | wxYES_NO); + if (result == wxYES) { + // Restart Aegisub + if (wxGetApp().frame->Close()) { + RestartAegisub(); + //wxStandardPaths stand; + //wxExecute(_T("\"") + stand.GetExecutablePath() + _T("\"")); + } + } + } + } + } +}; + + +/// Event log. +class app_log: public Command { +public: + CMD_NAME("app/log") + STR_MENU("&Log window...") + STR_DISP("Log window") + STR_HELP("Event log.") + + void operator()(agi::Context *c) { + LogWindow *log = new LogWindow(c->parent); + log->Show(1); + } +}; + + +/// Open a new application window. +class app_new_window: public Command { +public: + CMD_NAME("app/new_window") + STR_MENU("New Window") + STR_DISP("New Window") + STR_HELP("Open a new application window.") + + void operator()(agi::Context *c) { + RestartAegisub(); + } +}; + + +/// Configure Aegisub. +class app_options: public Command { +public: + CMD_NAME("app/options") + STR_MENU("&Options..") + STR_DISP("Options") + STR_HELP("Configure Aegisub.") + + void operator()(agi::Context *c) { + try { + Preferences pref(c->parent); + pref.ShowModal(); + } catch (agi::Exception& e) { + LOG_E("config/init") << "Caught exception: " << e.GetName() << " -> " << e.GetMessage(); + } + } +}; + + +/// Check to see if there is a new version of Aegisub available. +class app_updates: public Command { +public: + CMD_NAME("app/updates") + STR_MENU("&Check for Updates..") + STR_DISP("Check for Updates") + STR_HELP("Check to see if there is a new version of Aegisub available.") + + void operator()(agi::Context *c) { + PerformVersionCheck(true); + } +}; + +/// @} + +/// Init app/ commands +void init_app(CommandManager *cm) { + cm->reg(new app_about()); + cm->reg(new app_display_audio_subs()); + cm->reg(new app_display_full()); + cm->reg(new app_display_subs()); + cm->reg(new app_display_video_subs()); + cm->reg(new app_exit()); + cm->reg(new app_language()); + cm->reg(new app_log()); + cm->reg(new app_new_window()); + cm->reg(new app_options()); + cm->reg(new app_updates()); +} + +} // namespace cmd + diff --git a/aegisub/src/command/audio.cpp b/aegisub/src/command/audio.cpp new file mode 100644 index 000000000..06fb685b4 --- /dev/null +++ b/aegisub/src/command/audio.cpp @@ -0,0 +1,174 @@ +// Copyright (c) 2005-2010, Niels Martin Hansen +// Copyright (c) 2005-2010, Rodrigo Braz Monteiro +// Copyright (c) 2010, Amar Takhar +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Aegisub Project http://www.aegisub.org/ +// +// $Id$ + +/// @file audio.cpp +/// @brief audio/ commands. +/// @ingroup command +/// + +#include "config.h" + +#ifndef AGI_PRE +#include +#endif + +#include "command.h" + +#include "aegisub/context.h" +#include "compat.h" +#include "main.h" + +namespace cmd { +/// @defgroup cmd-audio Audio commands. +/// @{ + + +/// Closes the currently open audio file. +class audio_close: public Command { +public: + CMD_NAME("audio/close") + STR_MENU("&Close Audio") + STR_DISP("Close Audio") + STR_HELP("Closes the currently open audio file.") + + void operator()(agi::Context *c) { + c->audioController->CloseAudio(); + } +}; + + +/// Opens an audio file. +class audio_open: public Command { +public: + CMD_NAME("audio/open") + STR_MENU("&Open Audio File..") + STR_DISP("Open Audio File") + STR_HELP("Opens an audio file.") + + void operator()(agi::Context *c) { + wxString path = lagi_wxString(OPT_GET("Path/Last/Audio")->GetString()); + wxString str = wxString(_("Audio Formats")) + _T(" (*.wav,*.mp3,*.ogg,*.flac,*.mp4,*.ac3,*.aac,*.mka,*.m4a,*.w64)|*.wav;*.mp3;*.ogg;*.flac;*.mp4;*.ac3;*.aac;*.mka;*.m4a;*.w64|") + + _("Video Formats") + _T(" (*.avi,*.mkv,*.ogm,*.mpg,*.mpeg)|*.avi;*.mkv;*.ogm;*.mp4;*.mpeg;*.mpg|") + + _("All files") + _T(" (*.*)|*.*"); + wxString filename = wxFileSelector(_("Open audio file"),path,_T(""),_T(""),str,wxFD_OPEN | wxFD_FILE_MUST_EXIST); + if (!filename.empty()) { + c->audioController->OpenAudio(filename); + OPT_SET("Path/Last/Audio")->SetString(STD_STR(filename)); + } + } +}; + + +/// Open a 150 minutes blank audio clip, for debugging. +class audio_open_blank: public Command { +public: + CMD_NAME("audio/open/blank") + STR_MENU("Open 2h30 Blank Audio") + STR_DISP("Open 2h30 Blank Audio") + STR_HELP("Open a 150 minutes blank audio clip, for debugging.") + + void operator()(agi::Context *c) { + c->audioController->OpenAudio(_T("dummy-audio:silence?sr=44100&bd=16&ch=1&ln=396900000")); + } +}; + + +/// Open a 150 minutes noise-filled audio clip, for debugging. +class audio_open_noise: public Command { +public: + CMD_NAME("audio/open/noise") + STR_MENU("Open 2h30 Noise Audio") + STR_DISP("Open 2h30 Noise Audio") + STR_HELP("Open a 150 minutes noise-filled audio clip, for debugging.") + + void operator()(agi::Context *c) { + c->audioController->OpenAudio(_T("dummy-audio:noise?sr=44100&bd=16&ch=1&ln=396900000")); + } +}; + + +/// Opens the audio from the current video file. +class audio_open_video: public Command { +public: + CMD_NAME("audio/open/video") + STR_MENU("Open Audio from &Video") + STR_DISP("Open Audio from Video") + STR_HELP("Opens the audio from the current video file.") + + void operator()(agi::Context *c) { + c->audioController->OpenAudio(_T("audio-video:cache")); + } +}; + + +/// Display audio as a frequency-power spectrograph. +class audio_view_spectrum: public Command { +public: + CMD_NAME("audio/view/spectrum") + STR_MENU("Spectrum Display") + STR_DISP("Spectrum Display") + STR_HELP("Display audio as a frequency-power spectrograph.") + + void operator()(agi::Context *c) { + printf("XXX: fixme\n"); + } +}; + + +/// Display audio as a linear amplitude graph. +class audio_view_waveform: public Command { +public: + CMD_NAME("audio/view/waveform") + STR_MENU("Waveform Display") + STR_DISP("Waveform Display") + STR_HELP("Display audio as a linear amplitude graph.") + + void operator()(agi::Context *c) { + printf("XXX: fixme\n"); + } +}; + +/// @} + +/// Init audio/ commands +void init_audio(CommandManager *cm) { + cm->reg(new audio_close()); + cm->reg(new audio_open()); + cm->reg(new audio_open_blank()); + cm->reg(new audio_open_noise()); + cm->reg(new audio_open_video()); + cm->reg(new audio_view_spectrum()); + cm->reg(new audio_view_waveform()); +} + +} // namespace cmd diff --git a/aegisub/src/command/automation.cpp b/aegisub/src/command/automation.cpp new file mode 100644 index 000000000..2dd968ef0 --- /dev/null +++ b/aegisub/src/command/automation.cpp @@ -0,0 +1,107 @@ +// Copyright (c) 2005-2010, Niels Martin Hansen +// Copyright (c) 2005-2010, Rodrigo Braz Monteiro +// Copyright (c) 2010, Amar Takhar +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Aegisub Project http://www.aegisub.org/ +// +// $Id$ + +/// @file automation.cpp +/// @brief am/ (automation) commands +/// @ingroup command +/// + +#include "config.h" + +#ifndef AGI_PRE +#endif + +#include "command.h" + +#include "main.h" +#include "aegisub/context.h" +#include "dialog_automation.h" +#include "auto4_base.h" +#include "video_context.h" +#include "frame_main.h" + +namespace cmd { +/// @defgroup cmd-am Automation commands +/// @{ + + +/// Open automation manager. +class am_manager: public Command { +public: + CMD_NAME("am/manager") + STR_MENU("&Automation..") + STR_DISP("Automation") + STR_HELP("Open automation manager.") + + void operator()(agi::Context *c) { +#ifdef WITH_AUTOMATION +#ifdef __APPLE__ + if (wxGetMouseState().CmdDown()) { +#else + if (wxGetMouseState().ControlDown()) { +#endif + wxGetApp().global_scripts->Reload(); + if (wxGetMouseState().ShiftDown()) { + const std::vector scripts = c->local_scripts->GetScripts(); + for (size_t i = 0; i < scripts.size(); ++i) { + try { + scripts[i]->Reload(); + } catch (const wchar_t *e) { + wxLogError(e); + } catch (...) { + wxLogError(_T("An unknown error occurred reloading Automation script '%s'."), scripts[i]->GetName().c_str()); + } + } + + wxGetApp().frame->StatusTimeout(_("Reloaded all Automation scripts")); + } else { + wxGetApp().frame->StatusTimeout(_("Reloaded autoload Automation scripts")); + } + } else { + VideoContext::Get()->Stop(); + DialogAutomation dlg(c->parent, c->local_scripts); + dlg.ShowModal(); + } +#endif + } +}; + +/// @} + +/// Init am/ commands. (automation) +void init_automation(CommandManager *cm) { + cm->reg(new am_manager()); +} + + +} // namespace cmd diff --git a/aegisub/src/command/command.cpp b/aegisub/src/command/command.cpp new file mode 100644 index 000000000..c7de64dc1 --- /dev/null +++ b/aegisub/src/command/command.cpp @@ -0,0 +1,129 @@ +// Copyright (c) 2010, Amar Takhar +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// $Id$ + +/// @file command.cpp +/// @brief Command system base file. +/// @ingroup command + +#include "command.h" +#include + +namespace cmd { + +CommandManager *cm; + +int id(std::string name) { return cm->id(name); } +void call(agi::Context *c, const int id) { return cm->call(c, id); } +int count() { return cm->count(); } +Command* get(std::string name) { return cm->get(name); } + + +wxBitmap* Command::Icon(int size) { + if (size == 16) { + return icon::get(name(), 16); + } else if (size == 24) { + return icon::get(name(), 24); + } else { + throw CommandIconInvalid("Valid icon sizes are 16 or 24."); + } +} + + +int CommandManager::id(std::string name) { + + cmdMap::iterator index; + + if ((index = map.find(name)) != map.end()) { + int id = std::distance(map.begin(), index); + return id; + } + // XXX: throw + printf("cmd::id NOT FOUND (%s)\n", name.c_str()); + return 60003; +} + + +Command* CommandManager::get(std::string name) { + cmdMap::iterator index; + + if ((index = map.find(name)) != map.end()) { + return index->second; + } + // XXX: throw + printf("cmd::id NOT FOUND (%s)\n", name.c_str()); +} + + + + +void CommandManager::call(agi::Context *c, const int id) { + cmdMap::iterator index(map.begin()); + std::advance(index, id); + + if (index != map.end()) { + LOG_D("event/command") << index->first << " " << "(Id: " << id << ")"; + (*index->second)(c); + } else { + LOG_W("event/command/not_found") << "EVENT ID NOT FOUND: " << id; + // XXX: throw + } +} + + +void CommandManager::reg(Command *cmd) { + map.insert(cmdPair(cmd->name(), cmd)); +} + + +// These forward declarations exist here since we don't want to expose +// them in a header, they're strictly internal-use. +void init_app(CommandManager *cm); +void init_audio(CommandManager *cm); +void init_automation(CommandManager *cm); +void init_command(CommandManager *cm); +void init_edit(CommandManager *cm); +void init_grid(CommandManager *cm); +void init_help(CommandManager *cm); +void init_keyframe(CommandManager *cm); +void init_medusa(CommandManager *cm); +void init_menu(CommandManager *cm); +void init_recent(CommandManager *cm); +void init_subtitle(CommandManager *cm); +void init_time(CommandManager *cm); +void init_timecode(CommandManager *cm); +void init_tool(CommandManager *cm); +void init_video(CommandManager *cm); + +void init_command(CommandManager *cm) { + LOG_D("command/init") << "Populating command map"; + init_app(cm); + init_audio(cm); + init_automation(cm); + init_edit(cm); + init_grid(cm); + init_help(cm); + init_keyframe(cm); + init_medusa(cm); + init_menu(cm); + init_recent(cm); + init_subtitle(cm); + init_time(cm); + init_timecode(cm); + init_tool(cm); + init_video(cm); +} + +} // namespace cmd diff --git a/aegisub/src/command/command.h b/aegisub/src/command/command.h new file mode 100644 index 000000000..993b5049e --- /dev/null +++ b/aegisub/src/command/command.h @@ -0,0 +1,102 @@ +// Copyright (c) 2010, Amar Takhar +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// $Id$ + +/// @file command.h +/// @brief Command base class and main header. +/// @ingroup command + +#include "aegisub/context.h" +#include "icon.h" + +DEFINE_BASE_EXCEPTION_NOINNER(CommandError, agi::Exception) +DEFINE_SIMPLE_EXCEPTION_NOINNER(CommandIconNone, CommandError, "command/icon") +DEFINE_SIMPLE_EXCEPTION_NOINNER(CommandIconInvalid, CommandError, "command/icon/invalid") + +#define CMD_NAME(a) const char* name() { return a; } +#define STR_MENU(a) wxString StrMenu() const { return a; } +#define STR_DISP(a) wxString StrDisplay() const { return a; } +#define STR_HELP(a) wxString StrHelp() const { return a; } + +/// Commands +namespace cmd { + class CommandManager; + class Command; + + /// CommandManager instance. + extern CommandManager *cm; + + /// Init all commands. + /// @param cm CommandManager instance. + void init_command(CommandManager *cm); + + // The following are nothing more than glorified macros. + int id(std::string name); ///< @see CommandManager::id + void call(agi::Context *c, const int id); ///< @see CommandManager::call + int count(); ///< @see CommandManager::count + Command* get(std::string name); ///< @see CommandManager::get + + + /// Holds an individual Command + class Command { + public: + virtual const char* name()=0; ///< Command name. + virtual wxString StrMenu() const=0; ///< String for menu purposes including accelerators. + virtual wxString StrDisplay() const=0; ///< Plain string for display purposes. + virtual wxString StrHelp() const=0; ///< Short help string descripting the command purpose. + + /// Request icon. + /// @param size Icon size. + wxBitmap* Icon(int size); + + /// Command function + virtual void operator()(agi::Context *c)=0; + + /// Destructor + virtual ~Command() {}; + }; + + + /// Manager for commands + class CommandManager { + typedef std::map cmdMap; ///< Map to hold commands. + typedef std::pair cmdPair; ///< Pair for command insertion. + cmdMap map; ///< Actual map. + + public: + /// Register a command. + /// @param cmd Command object. + void reg(Command *cmd); + + /// Retrieve an ID for event usage or otherwise + /// @param name Command name + /// @return Command ID + /// @note This is guaranteed to be unique. + int id(std::string name); + + /// Call a command. + /// @param c Current Context. + /// @param id ID for Command to call. + void call(agi::Context *c, const int id); + + /// Count number of commands. + /// @return ID number. + int count() { return map.size(); } + + /// Retrieve a Command object. + /// @param Command object. + Command* get(std::string name); + }; +} // namespace cmd diff --git a/aegisub/src/command/edit.cpp b/aegisub/src/command/edit.cpp new file mode 100644 index 000000000..9e20b9b28 --- /dev/null +++ b/aegisub/src/command/edit.cpp @@ -0,0 +1,318 @@ +// Copyright (c) 2005-2010, Niels Martin Hansen +// Copyright (c) 2005-2010, Rodrigo Braz Monteiro +// Copyright (c) 2010, Amar Takhar +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Aegisub Project http://www.aegisub.org/ +// +// $Id$ + +/// @file edit.cpp +/// @brief edit/ commands. +/// @ingroup command +/// + +#include "config.h" + +#ifndef AGI_PRE +#endif + +#include "command.h" + +#include "aegisub/context.h" +#include "aegisub/context.h" +#include "subs_edit_box.h" +#include "subs_edit_ctrl.h" +#include "dialog_search_replace.h" +#include "video_context.h" + +namespace cmd { +/// @defgroup cmd-edit Editing commands. +/// @{ + + +/// Copy subtitles. +class edit_line_copy: public Command { +public: + CMD_NAME("edit/line/copy") + STR_MENU("Copy Lines") + STR_DISP("Copy Lines") + STR_HELP("Copy subtitles.") + + void operator()(agi::Context *c) { + if (c->parent->FindFocus() == c->EditBox->TextEdit) { + c->EditBox->TextEdit->Copy(); + return; + } + c->SubsGrid->CopyLines(c->SubsGrid->GetSelection()); + } +}; + + +/// Cut subtitles. +class edit_line_cut: public Command { +public: + CMD_NAME("edit/line/cut") + STR_MENU("Cut Lines") + STR_DISP("Cut Lines") + STR_HELP("Cut subtitles.") + + void operator()(agi::Context *c) { + if (c->parent->FindFocus() == c->EditBox->TextEdit) { + c->EditBox->TextEdit->Cut(); + return; + } + c->SubsGrid->CutLines(c->SubsGrid->GetSelection()); + } +}; + + +/// Delete currently selected lines. +class edit_line_delete: public Command { +public: + CMD_NAME("edit/line/delete") + STR_MENU("Delete Lines") + STR_DISP("Delete Lines") + STR_HELP("Delete currently selected lines.") + + void operator()(agi::Context *c) { +//XXX: subs_grid.cpp + } +}; + + +/// Duplicate the selected lines. +class edit_line_duplicate: public Command { +public: + CMD_NAME("edit/line/duplicate") + STR_MENU("&Duplicate Lines") + STR_DISP("Duplicate Lines") + STR_HELP("Duplicate the selected lines.") + + void operator()(agi::Context *c) { +//XXX: subs_grid.cpp + } +}; + + +/// Duplicate lines and shift by one frame. +class edit_line_duplicate_shift: public Command { +public: + CMD_NAME("edit/line/duplicate/shift") + STR_MENU("&Duplicate and Shift by 1 Frame") + STR_DISP("Duplicate and Shift by 1 Frame") + STR_HELP("Duplicate lines and shift by one frame.") + + void operator()(agi::Context *c) { +//XXX: subs_grid.cpp + } +}; + + +/// Joins selected lines in a single one, as karaoke. +class edit_line_join_as_karaoke: public Command { +public: + CMD_NAME("edit/line/join/as_karaoke") + STR_MENU("As &Karaoke") + STR_DISP("As Karaoke") + STR_HELP("Joins selected lines in a single one, as karaoke.") + + void operator()(agi::Context *c) { +//XXX: subs_grid.cpp + } +}; + + +/// Joins selected lines in a single one, concatenating text together. +class edit_line_join_concatenate: public Command { +public: + CMD_NAME("edit/line/join/concatenate") + STR_MENU("&Concatenate") + STR_DISP("Concatenate") + STR_HELP("Joins selected lines in a single one, concatenating text together.") + + void operator()(agi::Context *c) { +//XXX: subs_grid.cpp + } +}; + + +/// Joins selected lines in a single one, keeping text of first and discarding remaining. +class edit_line_join_keep_first: public Command { +public: + CMD_NAME("edit/line/join/keep_first") + STR_MENU("Keep &First") + STR_DISP("Keep First") + STR_HELP("Joins selected lines in a single one, keeping text of first and discarding remaining.") + + void operator()(agi::Context *c) { +//XXX: subs_grid.cpp + } +}; + + +/// Paste subtitles. +class edit_line_paste: public Command { +public: + CMD_NAME("edit/line/paste") + STR_MENU("Paste Lines") + STR_DISP("Paste Lines") + STR_HELP("Paste subtitles.") + + void operator()(agi::Context *c) { + if (c->parent->FindFocus() == c->EditBox->TextEdit) { + c->EditBox->TextEdit->Paste(); + return; + } + c->SubsGrid->PasteLines(c->SubsGrid->GetFirstSelRow()); + } +}; + + +/// Paste subtitles over others. +class edit_line_paste_over: public Command { +public: + CMD_NAME("edit/line/paste/over") + STR_MENU("Paste Lines Over..") + STR_DISP("Paste Lines Over") + STR_HELP("Paste subtitles over others.") + + void operator()(agi::Context *c) { + c->SubsGrid->PasteLines(c->SubsGrid->GetFirstSelRow(),true); + } +}; + + +/// Recombine subtitles when they have been split and merged. +class edit_line_recombine: public Command { +public: + CMD_NAME("edit/line/recombine") + STR_MENU("Recombine Lines") + STR_DISP("Recombine Lines") + STR_HELP("Recombine subtitles when they have been split and merged.") + + void operator()(agi::Context *c) { +//XXX: subs_grid.cpp + } +}; + + +/// Uses karaoke timing to split line into multiple smaller lines. +class edit_line_split_by_karaoke: public Command { +public: + CMD_NAME("edit/line/split/by_karaoke") + STR_MENU("Split Lines (by karaoke)") + STR_DISP("Split Lines (by karaoke)") + STR_HELP("Uses karaoke timing to split line into multiple smaller lines.") + + void operator()(agi::Context *c) { +//XXX: subs_grid.cpp + } +}; + + +/// Swaps the two selected lines. +class edit_line_swap: public Command { +public: + CMD_NAME("edit/line/swap") + STR_MENU("Swap Lines") + STR_DISP("Swap Lines") + STR_HELP("Swaps the two selected lines.") + + void operator()(agi::Context *c) { +//XXX: subs_grid.cpp + } +}; + + +/// Redoes last action. +class edit_redo: public Command { +public: + CMD_NAME("edit/redo") + STR_MENU("&Redo") + STR_DISP("Redo") + STR_HELP("Redoes last action.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + c->ass->Redo(); + } +}; + + +/// Find and replace words in subtitles. +class edit_search_replace: public Command { +public: + CMD_NAME("edit/search_replace") + STR_MENU("Search and &Replace..") + STR_DISP("Search and Replace") + STR_HELP("Find and replace words in subtitles.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + Search.OpenDialog(true); + } +}; + + +/// Undoes last action. +class edit_undo: public Command { +public: + CMD_NAME("edit/undo") + STR_MENU("&Undo") + STR_DISP("Undo") + STR_HELP("Undoes last action.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + c->ass->Undo(); + } +}; + +/// @} + +/// Init edit/ commands +void init_edit(CommandManager *cm) { + cm->reg(new edit_line_copy()); + cm->reg(new edit_line_cut()); + cm->reg(new edit_line_delete()); + cm->reg(new edit_line_duplicate()); + cm->reg(new edit_line_duplicate_shift()); + cm->reg(new edit_line_join_as_karaoke()); + cm->reg(new edit_line_join_concatenate()); + cm->reg(new edit_line_join_keep_first()); + cm->reg(new edit_line_paste()); + cm->reg(new edit_line_paste_over()); + cm->reg(new edit_line_recombine()); + cm->reg(new edit_line_split_by_karaoke()); + cm->reg(new edit_line_swap()); + cm->reg(new edit_redo()); + cm->reg(new edit_search_replace()); + cm->reg(new edit_undo()); +} + +} // namespace cmd diff --git a/aegisub/src/command/grid.cpp b/aegisub/src/command/grid.cpp new file mode 100644 index 000000000..b3427f361 --- /dev/null +++ b/aegisub/src/command/grid.cpp @@ -0,0 +1,171 @@ +// Copyright (c) 2005-2010, Niels Martin Hansen +// Copyright (c) 2005-2010, Rodrigo Braz Monteiro +// Copyright (c) 2010, Amar Takhar +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Aegisub Project http://www.aegisub.org/ +// +// $Id$ + +/// @file grid.cpp +/// @brief grid/ commands. +/// @ingroup command +/// + +#include "config.h" + +#ifndef AGI_PRE +#endif + +#include "command.h" + +#include "aegisub/context.h" +#include "subs_grid.h" +#include "main.h" +#include "frame_main.h" + +namespace cmd { +/// @defgroup cmd-grid Subtitle grid commands. +/// @{ + + + +/// Move to the next subtitle line. +class grid_line_next: public Command { +public: + CMD_NAME("grid/line/next") + STR_MENU("Next Line") + STR_DISP("Next Line") + STR_HELP("Move to the next subtitle line.") + + void operator()(agi::Context *c) { + c->SubsGrid->NextLine(); + } +}; + + +/// Move to the previous line. +class grid_line_prev: public Command { +public: + CMD_NAME("grid/line/prev") + STR_MENU("Previous Line") + STR_DISP("Previous Line") + STR_HELP("Move to the previous line.") + + void operator()(agi::Context *c) { + c->SubsGrid->PrevLine(); + } +}; + + +/// Cycle through tag hiding modes. +class grid_tag_cycle_hiding: public Command { +public: + CMD_NAME("grid/tag/cycle_hiding") + STR_MENU("Cycle Tag Hiding") + STR_DISP("Cycle Tag Hiding") + STR_HELP("Cycle through tag hiding modes.") + + void operator()(agi::Context *c) { + int tagMode = OPT_GET("Subtitle/Grid/Hide Overrides")->GetInt(); + + // Cycle to next + tagMode = (tagMode+1)%3; + + // Show on status bar + wxString message = _("ASS Override Tag mode set to "); + if (tagMode == 0) message += _("show full tags."); + if (tagMode == 1) message += _("simplify tags."); + if (tagMode == 2) message += _("hide tags."); + wxGetApp().frame->StatusTimeout(message,10000); + + // Set option + OPT_SET("Subtitle/Grid/Hide Overrides")->SetInt(tagMode); + + // Refresh grid + c->SubsGrid->Refresh(false); + } +}; + + +/// Hide override tags in the subtitle grid. +class grid_tags_hide: public Command { +public: + CMD_NAME("grid/tags/hide") + STR_MENU("Hide Tags") + STR_DISP("Hide Tags") + STR_HELP("Hide override tags in the subtitle grid.") + + void operator()(agi::Context *c) { +// XXX: Needs fixing. +// OPT_SET("Subtitle/Grid/Hide Overrides")->SetInt(event.GetId() - cmd::id("subtitle/tags/show")); +// SubsGrid->Refresh(false); + } +}; + + +/// Show full override tags in the subtitle grid. +class grid_tags_show: public Command { +public: + CMD_NAME("grid/tags/show") + STR_MENU("Show Tags") + STR_DISP("Show Tags") + STR_HELP("Show full override tags in the subtitle grid.") + + void operator()(agi::Context *c) { + //XXX: see grid_tags_hide + } +}; + + +/// Replace override tags in the subtitle grid with a simplified placeholder. +class grid_tags_simplify: public Command { +public: + CMD_NAME("grid/tags/simplify") + STR_MENU("Simplify Tags") + STR_DISP("Simplify Tags") + STR_HELP("Replace override tags in the subtitle grid with a simplified placeholder.") + + void operator()(agi::Context *c) { + //XXX: see grid_tags_hide + } +}; + +/// @} + + +/// Init grid/ commands. +void init_grid(CommandManager *cm) { + cm->reg(new grid_line_next()); + cm->reg(new grid_line_prev()); + cm->reg(new grid_tag_cycle_hiding()); + cm->reg(new grid_tags_hide()); + cm->reg(new grid_tags_show()); + cm->reg(new grid_tags_simplify()); +} + +} // namespace cmd diff --git a/aegisub/src/hotkeys.h b/aegisub/src/command/header similarity index 50% rename from aegisub/src/hotkeys.h rename to aegisub/src/command/header index 9668ca25e..cc146d1ac 100644 --- a/aegisub/src/hotkeys.h +++ b/aegisub/src/command/header @@ -1,4 +1,4 @@ -// Copyright (c) 2005, Rodrigo Braz Monteiro +// Copyright (c) 2010, Amar Takhar // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -29,107 +29,11 @@ // // $Id$ -/// @file hotkeys.h -/// @see hotkeys.cpp -/// @ingroup main_ui +/// @file +/// @brief +/// @ingroup command /// +namespace cmd { - -/////////// -// Headers -#ifndef AGI_PRE -#include - -#include -#include -#endif - - -////////////// -// Prototypes -class DialogOptions; - - - -/// DOCME -/// @class HotkeyType -/// @brief DOCME -/// -/// DOCME -class HotkeyType { -public: - - /// DOCME - int flags; - - /// DOCME - int keycode; - - /// DOCME - wxString origName; - - HotkeyType(); - HotkeyType(wxString text,wxString name); - - void Parse(wxString text); - wxString GetText() const; - - - /// DOCME - static std::map keyName; - static wxString GetKeyName(int keycode); - static void FillMap(); -}; - - - -/// DOCME -/// @class HotkeyManager -/// @brief DOCME -/// -/// DOCME -class HotkeyManager { - friend class DialogOptions; -private: - - /// DOCME - bool modified; - - /// DOCME - wxString filename; - - - /// DOCME - int lastKey; - - /// DOCME - int lastMod; - -public: - - /// DOCME - std::map key; - - HotkeyManager(); - ~HotkeyManager(); - - void SetFile(wxString file); - void SetHotkey(wxString function,HotkeyType hotkey); - void SetHotkey(wxString function,wxString hotkey); - void Save(); - void Load(); - void LoadDefaults(); - HotkeyType *Find(int keycode,int mod); - - const wxString GetText(wxString function) const; - wxAcceleratorEntry GetAccelerator(wxString function,int id) const; - bool IsPressed(wxString function) const; - void SetPressed(int key,bool ctrl=false,bool alt=false,bool shift=false); -}; - - -/////////////////// -// Global instance -extern HotkeyManager Hotkeys; diff --git a/aegisub/src/command/help.cpp b/aegisub/src/command/help.cpp new file mode 100644 index 000000000..15f4012ec --- /dev/null +++ b/aegisub/src/command/help.cpp @@ -0,0 +1,165 @@ +// Copyright (c) 2005-2010, Niels Martin Hansen +// Copyright (c) 2005-2010, Rodrigo Braz Monteiro +// Copyright (c) 2010, Amar Takhar +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Aegisub Project http://www.aegisub.org/ +// +// $Id$ + +/// @file help.cpp +/// @brief help/ commands +/// @ingroup command +/// + +#include "config.h" + +#ifndef AGI_PRE +#endif + +#include "command.h" +#include "aegisub/context.h" + +#include "help_button.h" // help_contents +#include "main.h" + +namespace cmd { +/// @defgroup cmd-help Help commands. +/// @{ + + + +/// Visit Aegisub's bug tracker. +class help_bugs: public Command { +public: + CMD_NAME("help/bugs") + STR_MENU("&Bug Tracker..") + STR_DISP("Bug Tracker") + STR_HELP("Visit Aegisub's bug tracker to report bugs and request new features.") + + void operator()(agi::Context *c) { + if (wxGetMouseState().CmdDown()) { + if (wxGetMouseState().ShiftDown()) { + wxMessageBox(_T("Now crashing with an access violation...")); + for (char *foo = (char*)0;;) *foo++ = 42; + } else { + wxMessageBox(_T("Now crashing with an unhandled exception...")); + throw c->parent; + } + } + AegisubApp::OpenURL(_T("http://devel.aegisub.org/")); + } +}; + + +/// Help topics. +class help_contents: public Command { +public: + CMD_NAME("help/contents") + STR_MENU("&Contents..") + STR_DISP("Contents") + STR_HELP("Help topics.") + + void operator()(agi::Context *c) { + HelpButton::OpenPage(_T("Main")); + } +}; + + +/// Resource files. +class help_files: public Command { +public: + CMD_NAME("help/files") + STR_MENU("&All Files") + STR_DISP("All Files") + STR_HELP("Resource files.") + + void operator()(agi::Context *c) { +#ifdef __WXMAC__ + char *shared_path = agi::util::OSX_GetBundleSharedSupportDirectory(); + wxString help_path = wxString::Format(_T("%s/doc"), wxString(shared_path, wxConvUTF8).c_str()); + agi::util::OSX_OpenLocation(help_path.c_str()); + free(shared_path); +#endif + } +}; + + +/// Visit Aegisub's forums. +class help_forums: public Command { +public: + CMD_NAME("help/forums") + STR_MENU("&Forums..") + STR_DISP("Forums") + STR_HELP("Visit Aegisub's forums.") + + void operator()(agi::Context *c) { + AegisubApp::OpenURL(_T("http://forum.aegisub.org/")); + } +}; + + +/// Visit Aegisub's official IRC channel. +class help_irc: public Command { +public: + CMD_NAME("help/irc") + STR_MENU("&IRC Channel..") + STR_DISP("IRC Channel") + STR_HELP("Visit Aegisub's official IRC channel.") + + void operator()(agi::Context *c) { + AegisubApp::OpenURL(_T("irc://irc.rizon.net/aegisub")); + } +}; + + +/// Visit Aegisub's official website. +class help_website: public Command { +public: + CMD_NAME("help/website") + STR_MENU("&Website..") + STR_DISP("Website") + STR_HELP("Visit Aegisub's official website.") + + void operator()(agi::Context *c) { + AegisubApp::OpenURL(_T("http://www.aegisub.org/")); + } +}; + +/// @} + +/// Init help/ commands. +void init_help(CommandManager *cm) { + cm->reg(new help_bugs()); + cm->reg(new help_contents()); + cm->reg(new help_files()); + cm->reg(new help_forums()); + cm->reg(new help_irc()); + cm->reg(new help_website()); +} + +} // namespace cmd diff --git a/aegisub/src/command/icon.cpp b/aegisub/src/command/icon.cpp new file mode 100644 index 000000000..dff538538 --- /dev/null +++ b/aegisub/src/command/icon.cpp @@ -0,0 +1,183 @@ +// Copyright (c) 2010, Amar Takhar +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// $Id$ + +/// @file icon.h +/// @brief Icon for commands. +/// @ingroup command + + +#ifndef AGI_PRE +#include +#include +#include +#endif + +#include + +#include "icon.h" +#include "../libresrc/bitmap.h" + +namespace icon { +typedef std::map iconMap; +typedef std::pair iconPair; + +iconMap icon16; +iconMap icon24; + +wxBitmap* get(std::string name, const int size) { + + // XXX: This code will go away with dynamic icon generation so I'm not + // concerned about it. + if (size == 16) { + iconMap::iterator index; + + if ((index = icon16.find(name)) != icon16.end()) { + return index->second; + } + printf("icon::get NOT FOUND (%s)\n", name.c_str()); + + } else if (size == 24) { + iconMap::iterator index; + + if ((index = icon24.find(name)) != icon24.end()) { + return index->second; + } + printf("icon::get NOT FOUND (%s)\n", name.c_str()); + } else { + throw IconInvalid("Valid icon sizes are 16 or 24."); + } + + + wxBitmap *img = new wxBitmap(); // stub to silence compiler warnings. + return img; +} + + +wxBitmap* getimage(const unsigned char *buff, size_t size) { + wxMemoryInputStream mem(buff, size); + wxImage img(mem); + wxBitmap *bitmap = new wxBitmap(img); + return bitmap; +} + + +#define INSERT_ICON(a, b) \ + icon16.insert(iconPair(a, getimage(b##_16, sizeof(b##_16)))); \ + icon24.insert(iconPair(a, getimage(b##_24, sizeof(b##_24)))); + + +void icon_init() { + // Seems that WX doesn't install the handlers early enough for our use. + wxPNGHandler *handler = new wxPNGHandler(); + wxImage::AddHandler(handler); + wxString handler_name(handler->GetName()); + + LOG_D("icon/init") << "Generating 24x24, 16x16 icons"; + +INSERT_ICON("am/manager", automation_toolbutton) +INSERT_ICON("app/about", about_menu) +INSERT_ICON("app/exit", exit_button) +INSERT_ICON("app/language", languages_menu) +INSERT_ICON("app/log", about_menu) +INSERT_ICON("app/new_window", new_window_menu) +INSERT_ICON("app/options", options_button) +INSERT_ICON("app/updates", blank_button) +INSERT_ICON("audio/close", close_audio_menu) +INSERT_ICON("audio/open", open_audio_menu) +INSERT_ICON("audio/open/video", open_audio_from_video_menu) +INSERT_ICON("edit/line/copy", copy_button) +INSERT_ICON("edit/line/cut", cut_button) +INSERT_ICON("edit/line/delete", delete_button) +INSERT_ICON("edit/line/duplicate", blank_button) +INSERT_ICON("edit/line/duplicate/shift", blank_button) +INSERT_ICON("edit/line/join/as_karaoke", blank_button) +INSERT_ICON("edit/line/join/concatenate", blank_button) +INSERT_ICON("edit/line/join/keep_first", blank_button) +INSERT_ICON("edit/line/paste", paste_button) +INSERT_ICON("edit/line/paste/over", paste_over_button) +INSERT_ICON("edit/line/recombine", blank_button) +INSERT_ICON("edit/line/split/by_karaoke", blank_button) +INSERT_ICON("edit/line/swap", arrow_sort) +INSERT_ICON("edit/redo", redo_button) +INSERT_ICON("edit/search_replace", find_replace_menu) +INSERT_ICON("edit/undo", undo_button) +INSERT_ICON("grid/tag/cycle_hiding", toggle_tag_hiding) +INSERT_ICON("help/bugs", bugtracker_button) +INSERT_ICON("help/contents", contents_button) +INSERT_ICON("help/files", contents_button) +INSERT_ICON("help/forums", forums_button) +INSERT_ICON("help/irc", irc_button) +INSERT_ICON("help/website", website_button) +INSERT_ICON("keyframe/close", close_keyframes_menu) +INSERT_ICON("keyframe/open", open_keyframes_menu) +INSERT_ICON("keyframe/save", save_keyframes_menu) +INSERT_ICON("subtitle/attachment", attach_button) +INSERT_ICON("subtitle/find", find_button) +INSERT_ICON("subtitle/find/next", find_next_menu) +INSERT_ICON("subtitle/insert/after", blank_button) +INSERT_ICON("subtitle/insert/after/videotime", blank_button) +INSERT_ICON("subtitle/insert/before", blank_button) +INSERT_ICON("subtitle/insert/before/videotime", blank_button) +INSERT_ICON("subtitle/new", new_toolbutton) +INSERT_ICON("subtitle/open", open_toolbutton) +INSERT_ICON("subtitle/open/charset", open_with_toolbutton) +INSERT_ICON("subtitle/properties", properties_toolbutton) +INSERT_ICON("subtitle/save", save_toolbutton) +INSERT_ICON("subtitle/save/as", save_as_toolbutton) +INSERT_ICON("subtitle/select/visible", select_visible_button) +INSERT_ICON("subtitle/spellcheck", spellcheck_toolbutton) +INSERT_ICON("time/continous/end", blank_button) +INSERT_ICON("time/continous/start", blank_button) +INSERT_ICON("time/frame/current", shift_to_frame) +INSERT_ICON("time/shift", shift_times_toolbutton) +INSERT_ICON("time/snap/end_video", subend_to_video) +INSERT_ICON("time/snap/frame", shift_to_frame) +INSERT_ICON("time/snap/scene", snap_subs_to_scene) +INSERT_ICON("time/snap/start_video", substart_to_video) +INSERT_ICON("time/sort/end", blank_button) +INSERT_ICON("time/sort/start", blank_button) +INSERT_ICON("time/sort/style", blank_button) +INSERT_ICON("timecode/close", close_timecodes_menu) +INSERT_ICON("timecode/open", open_timecodes_menu) +INSERT_ICON("timecode/save", save_timecodes_menu) +INSERT_ICON("tool/assdraw", assdraw) +INSERT_ICON("tool/export", export_menu) +INSERT_ICON("tool/font_collector", font_collector_button) +INSERT_ICON("tool/line/select", select_lines_button) +INSERT_ICON("tool/resampleres", resample_toolbutton) +INSERT_ICON("tool/style/assistant", styling_toolbutton) +INSERT_ICON("tool/style/manager", style_toolbutton) +INSERT_ICON("tool/time/kanji", kara_timing_copier) +INSERT_ICON("tool/time/kanji", spellcheck_toolbutton) +INSERT_ICON("tool/time/postprocess", timing_processor_toolbutton) +INSERT_ICON("tool/translation_assistant", translation_toolbutton) +INSERT_ICON("video/close", close_video_menu) +INSERT_ICON("video/detach", detach_video_menu) +INSERT_ICON("video/details", show_video_details_menu) +INSERT_ICON("video/jump", jumpto_button) +INSERT_ICON("video/jump/end", video_to_subend) +INSERT_ICON("video/jump/start", video_to_substart) +INSERT_ICON("video/open", open_video_menu) +INSERT_ICON("video/open/dummy", use_dummy_video_menu) +INSERT_ICON("video/zoom/in", zoom_in_button) +INSERT_ICON("video/zoom/out", zoom_out_button) + + + // Remove the handler to aboid "Duplicate handler" warnings from WX since + // it will attempt to install all the handlers later on. + wxImage::RemoveHandler(handler_name); +} +} // namespace icon diff --git a/aegisub/src/command/icon.h b/aegisub/src/command/icon.h new file mode 100644 index 000000000..b3f76565e --- /dev/null +++ b/aegisub/src/command/icon.h @@ -0,0 +1,35 @@ +// Copyright (c) 2010, Amar Takhar +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// $Id$ + +/// @file icon.h +/// @brief Icon for commands. +/// @ingroup command + +#pragma once + +#ifndef AGI_PRE +#include +#endif + +#include + +DEFINE_BASE_EXCEPTION_NOINNER(IconError, agi::Exception) +DEFINE_SIMPLE_EXCEPTION_NOINNER(IconInvalid, IconError, "icon/invalid") + +namespace icon { + void icon_init(); + wxBitmap* get(std::string name, const int size); +} // namespace cmd diff --git a/aegisub/src/command/keyframe.cpp b/aegisub/src/command/keyframe.cpp new file mode 100644 index 000000000..02b7e1d87 --- /dev/null +++ b/aegisub/src/command/keyframe.cpp @@ -0,0 +1,123 @@ +// Copyright (c) 2005-2010, Niels Martin Hansen +// Copyright (c) 2005-2010, Rodrigo Braz Monteiro +// Copyright (c) 2010, Amar Takhar +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Aegisub Project http://www.aegisub.org/ +// +// $Id$ + +/// @file keyframe.cpp +/// @brief keyframe/ commands. +/// @ingroup command +/// + +#include "config.h" + +#ifndef AGI_PRE +#endif + +#include "command.h" + +#include "aegisub/context.h" +#include "main.h" +#include "compat.h" +#include "video_context.h" + +namespace cmd { +/// @defgroup cmd-keyframed Keyframe commands. +/// @{ + + +/// Closes the currently open keyframes list. +class keyframe_close: public Command { +public: + CMD_NAME("keyframe/close") + STR_MENU("Close Keyframes") + STR_DISP("Close Keyframes") + STR_HELP("Closes the currently open keyframes list.") + + void operator()(agi::Context *c) { + VideoContext::Get()->CloseKeyframes(); + } +}; + + +/// Opens a keyframe list file. +class keyframe_open: public Command { +public: + CMD_NAME("keyframe/open") + STR_MENU("Open Keyframes..") + STR_DISP("Open Keyframes") + STR_HELP("Opens a keyframe list file.") + + void operator()(agi::Context *c) { + wxString path = lagi_wxString(OPT_GET("Path/Last/Keyframes")->GetString()); + wxString filename = wxFileSelector( + _T("Select the keyframes file to open"), + path, + _T("") + ,_T(".txt"), + _T("All supported formats (*.txt, *.pass, *.stats, *.log)|*.txt;*.pass;*.stats;*.log|All files (*.*)|*.*"), + wxFD_FILE_MUST_EXIST | wxFD_OPEN); + + if (filename.empty()) return; + OPT_SET("Path/Last/Keyframes")->SetString(STD_STR(filename)); + + // Load + VideoContext::Get()->LoadKeyframes(filename); + } +}; + + +/// Saves the current keyframe list. +class keyframe_save: public Command { +public: + CMD_NAME("keyframe/save") + STR_MENU("Save Keyframes..") + STR_DISP("Save Keyframes") + STR_HELP("Saves the current keyframe list.") + + void operator()(agi::Context *c) { + wxString path = lagi_wxString(OPT_GET("Path/Last/Keyframes")->GetString()); + wxString filename = wxFileSelector(_T("Select the Keyframes file to open"),path,_T(""),_T("*.key.txt"),_T("Text files (*.txt)|*.txt"),wxFD_OVERWRITE_PROMPT | wxFD_SAVE); + if (filename.IsEmpty()) return; + OPT_SET("Path/Last/Keyframes")->SetString(STD_STR(filename)); + VideoContext::Get()->SaveKeyframes(filename); + } +}; + +/// @} + +/// Init keyframe/ commands. +void init_keyframe(CommandManager *cm) { + cm->reg(new keyframe_close()); + cm->reg(new keyframe_open()); + cm->reg(new keyframe_save()); +} + +} // namespace cmd diff --git a/aegisub/src/command/medusa.cpp b/aegisub/src/command/medusa.cpp new file mode 100644 index 000000000..0e2925459 --- /dev/null +++ b/aegisub/src/command/medusa.cpp @@ -0,0 +1,245 @@ +// Copyright (c) 2005-2010, Niels Martin Hansen +// Copyright (c) 2005-2010, Rodrigo Braz Monteiro +// Copyright (c) 2010, Amar Takhar +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Aegisub Project http://www.aegisub.org/ +// +// $Id$ + +/// @file medusa.cpp +/// @brief medusa/ commands. +/// @ingroup command +/// + +#include "config.h" + +#ifndef AGI_PRE +#endif + +#include "command.h" + +#include "aegisub/context.h" +#include "audio_timing.h" + +namespace cmd { + +class medusa_enter: public Command { +public: + CMD_NAME("medusa/enter") + STR_MENU("Medusa Enter") + STR_DISP("Medusa Enter") + STR_HELP("") + + void operator()(agi::Context *c) { + /// @todo Figure out how to handle this in the audio controller + //audioBox->audioDisplay->Prev(false); + } +}; + +class medusa_next: public Command { +public: + CMD_NAME("medusa/next") + STR_MENU("Medusa Next") + STR_DISP("Medusa Next") + STR_HELP("") + + void operator()(agi::Context *c) { + /// @todo Figure out how to handle this in the audio controller + //audioBox->audioDisplay->Next(false); + } +}; + + +class medusa_play: public Command { +public: + CMD_NAME("medusa/play") + STR_MENU("Medusa Play") + STR_DISP("Medusa Play") + STR_HELP("Medusa play hotkey.") + + void operator()(agi::Context *c) { + c->audioController->PlayPrimaryRange(); + } +}; + + +class medusa_play_after: public Command { +public: + CMD_NAME("medusa/play/after") + STR_MENU("Medusa Play After") + STR_DISP("Medusa Play After") + STR_HELP("Medusa play after hotkey.") + + void operator()(agi::Context *c) { + SampleRange sel(c->audioController->GetPrimaryPlaybackRange()); + c->audioController->PlayRange(SampleRange( + sel.end(), + sel.end() + c->audioController->SamplesFromMilliseconds(500)));; + } +}; + + +class medusa_play_before: public Command { +public: + CMD_NAME("medusa/play/before") + STR_MENU("Medusa Play Before") + STR_DISP("Medusa Play Before") + STR_HELP("Medusa play before hotkey.") + + void operator()(agi::Context *c) { + SampleRange sel(c->audioController->GetPrimaryPlaybackRange()); + c->audioController->PlayRange(SampleRange( + sel.begin() - c->audioController->SamplesFromMilliseconds(500), + sel.begin()));; + } +}; + + +class medusa_previous: public Command { +public: + CMD_NAME("medusa/previous") + STR_MENU("Medusa Previous") + STR_DISP("Medusa Previous") + STR_HELP("Medusa previous hotkey.") + + void operator()(agi::Context *c) { + /// @todo Figure out how to handle this in the audio controller + //audioBox->audioDisplay->Prev(false); + } +}; + + +class medusa_shift_end_back: public Command { +public: + CMD_NAME("medusa/shift/end/back") + STR_MENU("Medusa Shift End Back") + STR_DISP("Medusa Shift End Back") + STR_HELP("Medusa shift end back hotkey.") + + void operator()(agi::Context *c) { + SampleRange newsel( + c->audioController->GetPrimaryPlaybackRange(), + 0, + -c->audioController->SamplesFromMilliseconds(10)); + /// @todo Make this use the timing controller instead + //audioController->SetSelection(newsel); + } +}; + + +class medusa_shift_end_forward: public Command { +public: + CMD_NAME("medusa/shift/end/forward") + STR_MENU("Medusa Shift End Forward") + STR_DISP("Medusa Shift End Forward") + STR_HELP("Medusa shift end forward hotkey.") + + void operator()(agi::Context *c) { + SampleRange newsel( + c->audioController->GetPrimaryPlaybackRange(), + 0, + c->audioController->SamplesFromMilliseconds(10)); + /// @todo Make this use the timing controller instead + //audioController->SetSelection(newsel); + } +}; + + +class medusa_shift_start_back: public Command { +public: + CMD_NAME("medusa/shift/start/back") + STR_MENU("Medusa Shift Start Back") + STR_DISP("Medusa Shift Start Back") + STR_HELP("Medusa shift start back hotkey.") + + void operator()(agi::Context *c) { + SampleRange newsel( + c->audioController->GetPrimaryPlaybackRange(), + -c->audioController->SamplesFromMilliseconds(10), + 0); + /// @todo Make this use the timing controller instead + //audioController->SetSelection(newsel); + } +}; + + +class medusa_shift_start_forward: public Command { +public: + CMD_NAME("medusa/shift/start/forward") + STR_MENU("Medusa Shift Start Forward") + STR_DISP("Medusa Shift Start Forward") + STR_HELP("Medusa shift start forward hotkey.") + + void operator()(agi::Context *c) { + SampleRange newsel( + c->audioController->GetPrimaryPlaybackRange(), + c->audioController->SamplesFromMilliseconds(10), + 0); + /// @todo Make this use the timing controller instead + //audioController->SetSelection(newsel); + } +}; + + +class medusa_stop: public Command { +public: + CMD_NAME("medusa/stop") + STR_MENU("Medusa Stop") + STR_DISP("Medusa Stop") + STR_HELP("Medusa stop hotkey.") + + void operator()(agi::Context *c) { + // Playing, stop + if (c->audioController->IsPlaying()) { + c->audioController->Stop(); + } else { + // Otherwise, play the last 500 ms + SampleRange sel(c->audioController->GetPrimaryPlaybackRange()); + c->audioController->PlayRange(SampleRange( + sel.end() - c->audioController->SamplesFromMilliseconds(500), + sel.end()));; + } + } +}; + + +void init_medusa(CommandManager *cm) { + cm->reg(new medusa_enter()); + cm->reg(new medusa_next()); + cm->reg(new medusa_play()); + cm->reg(new medusa_play_after()); + cm->reg(new medusa_play_before()); + cm->reg(new medusa_previous()); + cm->reg(new medusa_shift_end_back()); + cm->reg(new medusa_shift_end_forward()); + cm->reg(new medusa_shift_start_back()); + cm->reg(new medusa_shift_start_forward()); + cm->reg(new medusa_stop()); +} + +} // namespace cmd diff --git a/aegisub/src/command/menu.cpp b/aegisub/src/command/menu.cpp new file mode 100644 index 000000000..15496e8e9 --- /dev/null +++ b/aegisub/src/command/menu.cpp @@ -0,0 +1,280 @@ +// Copyright (c) 2010, Amar Takhar +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Aegisub Project http://www.aegisub.org/ +// +// $Id$ + +/// @file menu.cpp +/// @brief menu/ commands, related to activating/deactivating/populating menu items +/// @ingroup command +/// + +#include "config.h" + +#ifndef AGI_PRE +#endif + +#include "command.h" + +#include "aegisub/context.h" + +namespace cmd { +/// @defgroup cmd-menu Main menu dropdown and submenu related commands. +/// @{ + + +/// Audio manipulation. +class main_audio: public Command { +public: + CMD_NAME("main/audio") + STR_MENU("Audio") + STR_DISP("Audio") + STR_HELP("Audio manipulation.") + + void operator()(agi::Context *c) { + } +}; + +/// Automation manipulation and scripts. +class main_automation: public Command { +public: + CMD_NAME("main/automation") + STR_MENU("Automation") + STR_DISP("Automation") + STR_HELP("Automation manipulation and scripts.") + + void operator()(agi::Context *c) { + } +}; + + + + +/// Editing operations. +class main_edit: public Command { +public: + CMD_NAME("main/edit") + STR_MENU("&Edit") + STR_DISP("Edit") + STR_HELP("Editing operations.") + + void operator()(agi::Context *c) { + } +}; + + +/// Sort lines by column. +class main_edit_sort_lines: public Command { +public: + CMD_NAME("main/edit/sort lines") + STR_MENU("Sort Lines") + STR_DISP("Sort Lines") + STR_HELP("Sort lines by column.") + + void operator()(agi::Context *c) { + } +}; + + +/// Operations on subtitles. +class main_file: public Command { +public: + CMD_NAME("main/file") + STR_MENU("&File") + STR_DISP("File") + STR_HELP("Operations on subtitles.") + + void operator()(agi::Context *c) { + } +}; + + +/// Help options. +class main_help: public Command { +public: + CMD_NAME("main/help") + STR_MENU("Help") + STR_DISP("Help") + STR_HELP("Help options.") + + void operator()(agi::Context *c) { + } +}; + + +/// Subtitle manipulation. +class main_main_subtitle: public Command { +public: + CMD_NAME("main/subtitle") + STR_MENU("&Subtitle") + STR_DISP("Subtitle") + STR_HELP("Subtitle manipulation.") + + void operator()(agi::Context *c) { + } +}; + +/// Insert lines into currently active subtitle file. +class main_subtitle_insert_lines: public Command { +public: + CMD_NAME("main/subtitle/insert lines") + STR_MENU("&Insert Lines") + STR_DISP("Insert Lines") + STR_HELP("Insert lines into currently active subtitle file.") + + void operator()(agi::Context *c) { + } +}; + + +/// Sort lines by column. +class main_subtitle_sort_lines: public Command { +public: + CMD_NAME("main/subtitle/sort lines") + STR_MENU("Sort Lines") + STR_DISP("Sort Lines") + STR_HELP("Sort lines by column.") + + void operator()(agi::Context *c) { + } +}; + + +/// Merge 2 or more lines together. +class main_subtitle_join_lines: public Command { +public: + CMD_NAME("main/subtitle/join lines") + STR_MENU("Join Lines") + STR_DISP("Join Lines") + STR_HELP("Merge 2 or more lines together.") + + void operator()(agi::Context *c) { + } +}; + + +/// Time manipulation. +class main_timing: public Command { +public: + CMD_NAME("main/timing") + STR_MENU("&Timing") + STR_DISP("Timing") + STR_HELP("Time manipulation.") + + void operator()(agi::Context *c) { + } +}; + + +/// Make time continous. +class main_timing_make_times_continous: public Command { +public: + CMD_NAME("main/timing/make times continous") + STR_MENU("Make Times Continous") + STR_DISP("Make Times Continous") + STR_HELP("Make time continous.") + + void operator()(agi::Context *c) { + } +}; + + +/// Video operations. +class main_video: public Command { +public: + CMD_NAME("main/video") + STR_MENU("&Video") + STR_DISP("Video") + STR_HELP("Video operations.") + + void operator()(agi::Context *c) { + } +}; + + +/// Override Aspect Ratio +class main_video_override_ar: +public Command { public: + CMD_NAME("main/video/override ar") + STR_MENU("Override AR") + STR_DISP("Override AR") + STR_HELP("Override Aspect Ratio") + + void operator()(agi::Context *c) { + } +}; + + +/// Set zoom level. +class main_video_set_zoom: public Command { +public: + CMD_NAME("main/video/set zoom") + STR_MENU("Set Zoom") + STR_DISP("Set Zoom") + STR_HELP("Set zoom level.") + + void operator()(agi::Context *c) { + } +}; + + +/// View options. +class main_view: public Command { +public: + CMD_NAME("main/view") + STR_MENU("View") + STR_DISP("View") + STR_HELP("View options.") + + void operator()(agi::Context *c) { + } +}; + +/// @} + +/// Init menu/ commands. +void init_menu(CommandManager *cm) { + cm->reg(new main_audio()); + cm->reg(new main_automation()); + cm->reg(new main_edit()); + cm->reg(new main_edit_sort_lines()); + cm->reg(new main_file()); + cm->reg(new main_help()); + cm->reg(new main_main_subtitle()); + cm->reg(new main_subtitle_insert_lines()); + cm->reg(new main_subtitle_join_lines()); + cm->reg(new main_subtitle_sort_lines()); + cm->reg(new main_timing()); + cm->reg(new main_timing_make_times_continous()); + cm->reg(new main_video()); + cm->reg(new main_video_override_ar()); + cm->reg(new main_video_set_zoom()); + cm->reg(new main_view()); +} + +} // namespace cmd diff --git a/aegisub/src/command/recent.cpp b/aegisub/src/command/recent.cpp new file mode 100644 index 000000000..bee22cd2b --- /dev/null +++ b/aegisub/src/command/recent.cpp @@ -0,0 +1,139 @@ +// Copyright (c) 2010, Amar Takhar +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Aegisub Project http://www.aegisub.org/ +// +// $Id$ + +/// @file recent.cpp +/// @brief recent/ commands, rebuild MRU-based lists. +/// @ingroup command +/// + +#include "config.h" + +#ifndef AGI_PRE +#include +#endif + +#include "command.h" + +#include "aegisub/context.h" +#include "main.h" +#include "frame_main.h" +#include "compat.h" +#include "video_context.h" + +namespace cmd { +/// @defgroup cmd-recent MRU (Most Recently Used) commands. +/// @{ + + +/// Open recent audio. +class recent_audio: public Command { +public: + CMD_NAME("recent/audio") + STR_MENU("Recent") + STR_DISP("Recent") + STR_HELP("Open recent audio.") + + void operator()(agi::Context *c) { +// c->audioController->OpenAudio(lagi_wxString(config::mru->GetEntry("Audio", event.GetId()-cmd::id("recent/audio")))); + } +}; + + +/// Recent keyframes. +class recent_keyframe: public Command { +public: + CMD_NAME("recent/keyframe") + STR_MENU("Recent") + STR_DISP("Recent") + STR_HELP("Recent keyframes.") + + void operator()(agi::Context *c) { +// VideoContext::Get()->LoadKeyframes(lagi_wxString(config::mru->GetEntry("Keyframes", event.GetId()-cmd::id("recent/keyframe")))); + } +}; + + +/// Recently opened subtitles. +class recent_subtitle: public Command { +public: + CMD_NAME("recent/subtitle") + STR_MENU("Recent") + STR_DISP("Recent") + STR_HELP("Recently opened subtitles.") + + void operator()(agi::Context *c) { +// int number = event.GetId()-cmd::id("recent/subtitle"); +// wxGetApp().frame->LoadSubtitles(lagi_wxString(config::mru->GetEntry("Subtitle", number))); + } +}; + + +/// Recent timecodes. +class recent_timecode: public Command { +public: + CMD_NAME("recent/timecode") + STR_MENU("Recent") + STR_DISP("Recent") + STR_HELP("Recent timecodes.") + + void operator()(agi::Context *c) { +// int number = event.GetId()-cmd::id("recent/timecode"); +// wxGetApp().frame->LoadVFR(lagi_wxString(config::mru->GetEntry("Timecodes", number))); + } +}; + + +/// Recently opened videos. +class recent_video: public Command { +public: + CMD_NAME("recent/video") + STR_MENU("Recent") + STR_DISP("Recent") + STR_HELP("Recently opened videos.") + + void operator()(agi::Context *c) { +// int number = event.GetId()-cmd::id("recent/video"); +// wxGetApp().frame->LoadVideo(lagi_wxString(config::mru->GetEntry("Video", number))); + } +}; + +/// @} + +/// Init recent/ commands. +void init_recent(CommandManager *cm) { + cm->reg(new recent_audio()); + cm->reg(new recent_keyframe()); + cm->reg(new recent_subtitle()); + cm->reg(new recent_timecode()); + cm->reg(new recent_video()); +} + +} // namespace cmd diff --git a/aegisub/src/command/subtitle.cpp b/aegisub/src/command/subtitle.cpp new file mode 100644 index 000000000..22cbc55cd --- /dev/null +++ b/aegisub/src/command/subtitle.cpp @@ -0,0 +1,354 @@ +// Copyright (c) 2005-2010, Niels Martin Hansen +// Copyright (c) 2005-2010, Rodrigo Braz Monteiro +// Copyright (c) 2010, Amar Takhar +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Aegisub Project http://www.aegisub.org/ +// +// $Id$ + +/// @file subtitle.cpp +/// @brief subtitle/ commands. +/// @ingroup command +/// + +#include "config.h" + +#ifndef AGI_PRE +#include +#include +#endif + +#include + +#include "command.h" + +#include "aegisub/context.h" +#include "dialog_search_replace.h" +#include "dialog_attachments.h" +#include "video_context.h" +#include "main.h" +#include "frame_main.h" +#include "compat.h" +#include "dialog_properties.h" +#include "dialog_spellchecker.h" + + +namespace cmd { +/// @defgroup cmd-subtitle Subtitle commands. +/// @{ + + +/// Open the attachment list. +class subtitle_attachment: public Command { +public: + CMD_NAME("subtitle/attachment") + STR_MENU("&Attachments..") + STR_DISP("Attachments") + STR_HELP("Open the attachment list.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + DialogAttachments attachments(c->parent, c->ass); + attachments.ShowModal(); + } +}; + + +/// Find words in subtitles. +class subtitle_find: public Command { +public: + CMD_NAME("subtitle/find") + STR_MENU("&Find..") + STR_DISP("Find") + STR_HELP("Find words in subtitles.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + Search.OpenDialog(false); + } +}; + + +/// Find next match of last word. +class subtitle_find_next: public Command { +public: + CMD_NAME("subtitle/find/next") + STR_MENU("Find Next") + STR_DISP("Find Next") + STR_HELP("Find next match of last word.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + Search.FindNext(); + } +}; + + +/// Inserts a line after current. +class subtitle_insert_after: public Command { +public: + CMD_NAME("subtitle/insert/after") + STR_MENU("&After Current") + STR_DISP("After Current") + STR_HELP("Inserts a line after current.") + + void operator()(agi::Context *c) { +//XXX: subs_grid.cpp + } +}; + + +/// Inserts a line after current, starting at video time. +class subtitle_insert_after_videotime: public Command { +public: + CMD_NAME("subtitle/insert/after/videotime") + STR_MENU("After Current, at Video Time") + STR_DISP("After Current, at Video Time") + STR_HELP("Inserts a line after current, starting at video time.") + + void operator()(agi::Context *c) { +//XXX: subs_grid.cpp + } +}; + + +/// Inserts a line before current. +class subtitle_insert_before: public Command { +public: + CMD_NAME("subtitle/insert/before") + STR_MENU("&Before Current") + STR_DISP("Before Current") + STR_HELP("Inserts a line before current.") + + void operator()(agi::Context *c) { +//XXX: subs_grid.cpp + } +}; + + +/// Inserts a line before current, starting at video time. +class subtitle_insert_before_videotime: public Command { +public: + CMD_NAME("subtitle/insert/before/videotime") + STR_MENU("Before Current, at Video Time") + STR_DISP("Before Current, at Video Time") + STR_HELP("Inserts a line before current, starting at video time.") + + void operator()(agi::Context *c) { +//XXX: subs_grid.cpp + } +}; + + +/// New subtitles. +class subtitle_new: public Command { +public: + CMD_NAME("subtitle/new") + STR_MENU("&New Subtitles") + STR_DISP("New Subtitles") + STR_HELP("New subtitles.") + + void operator()(agi::Context *c) { + wxGetApp().frame->LoadSubtitles(_T("")); + } +}; + + +/// Opens a subtitles file. +class subtitle_open: public Command { +public: + CMD_NAME("subtitle/open") + STR_MENU("&Open Subtitles..") + STR_DISP("Open Subtitles") + STR_HELP("Opens a subtitles file.") + + void operator()(agi::Context *c) { + wxString path = lagi_wxString(OPT_GET("Path/Last/Subtitles")->GetString()); + wxString filename = wxFileSelector(_("Open subtitles file"),path,_T(""),_T(""),AssFile::GetWildcardList(0),wxFD_OPEN | wxFD_FILE_MUST_EXIST); + if (!filename.empty()) { + wxGetApp().frame->LoadSubtitles(filename); + wxFileName filepath(filename); + OPT_SET("Path/Last/Subtitles")->SetString(STD_STR(filepath.GetPath())); + } + } +}; + + +/// Opens a subtitles file with a specific charset. +class subtitle_open_charset: public Command { +public: + CMD_NAME("subtitle/open/charset") + STR_MENU("&Open Subtitles with Charset..") + STR_DISP("Open Subtitles with Charset") + STR_HELP("Opens a subtitles file with a specific charset.") + + void operator()(agi::Context *c) { + // Initialize charsets + wxString path = lagi_wxString(OPT_GET("Path/Last/Subtitles")->GetString()); + + // Get options and load + wxString filename = wxFileSelector(_("Open subtitles file"),path,_T(""),_T(""),AssFile::GetWildcardList(0),wxFD_OPEN | wxFD_FILE_MUST_EXIST); + if (!filename.empty()) { + wxString charset = wxGetSingleChoice(_("Choose charset code:"), _("Charset"), agi::charset::GetEncodingsList(), c->parent, -1, -1, true, 250, 200); + if (!charset.empty()) { + wxGetApp().frame->LoadSubtitles(filename,charset); + } + OPT_SET("Path/Last/Subtitles")->SetString(STD_STR(filename)); + } + } +}; + + +/// Opens the subtitles from the current video file. +class subtitle_open_video: public Command { +public: + CMD_NAME("subtitle/open/video") + STR_MENU("Open Subtitles from &Video") + STR_DISP("Open Subtitles from Video") + STR_HELP("Opens the subtitles from the current video file.") + + void operator()(agi::Context *c) { + wxGetApp().frame->LoadSubtitles(VideoContext::Get()->videoName, "binary"); + } +}; + + +/// Open script properties window. +class subtitle_properties: public Command { +public: + CMD_NAME("subtitle/properties") + STR_MENU("&Properties..") + STR_DISP("Properties") + STR_HELP("Open script properties window.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + DialogProperties Properties(c->parent, c->ass); + Properties.ShowModal(); + } +}; + + + +/// Saves subtitles. +class subtitle_save: public Command { +public: + CMD_NAME("subtitle/save") + STR_MENU("&Save Subtitles") + STR_DISP("Save Subtitles") + STR_HELP("Saves subtitles.") + + void operator()(agi::Context *c) { + wxGetApp().frame->SaveSubtitles(false); + } +}; + + +/// Saves subtitles with another name. +class subtitle_save_as: public Command { +public: + CMD_NAME("subtitle/save/as") + STR_MENU("Save Subtitles as..") + STR_DISP("Save Subtitles as") + STR_HELP("Saves subtitles with another name.") + + void operator()(agi::Context *c) { + wxGetApp().frame->SaveSubtitles(true); + } +}; + + +/// Selects all lines that are currently visible on video frame. +class subtitle_select_visiblek: public Command { +public: + CMD_NAME("subtitle/select/visible") + STR_MENU("Select Visible") + STR_DISP("Select Visible") + STR_HELP("Selects all lines that are currently visible on video frame.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + c->SubsGrid->SelectVisible(); + } +}; + + +/// Open spell checker. +class subtitle_spellcheck: public Command { +public: + CMD_NAME("subtitle/spellcheck") + STR_MENU("Spe&ll Checker..") + STR_DISP("Spell Checker") + STR_HELP("Open spell checker.") + + void operator()(agi::Context *c) { +//XXX: This is obscene, requires refactoring the spellchecker. +// VideoContext::Get()->Stop(); +// new DialogSpellChecker; + } +}; + + +/// +class subtitle_tags_show: public Command { +public: + CMD_NAME("subtitle/tags/show") + STR_MENU("XXX: No idea") + STR_DISP("XXX: No idea") + STR_HELP("XXX: No idea") + + void operator()(agi::Context *c) { +//XXX: see grid.cpp:grid_tags_hide() + } +}; + +/// @} + +/// Init subtitle/ commands. +void init_subtitle(CommandManager *cm) { + cm->reg(new subtitle_attachment()); + cm->reg(new subtitle_find()); + cm->reg(new subtitle_find_next()); + cm->reg(new subtitle_insert_after()); + cm->reg(new subtitle_insert_after_videotime()); + cm->reg(new subtitle_insert_before()); + cm->reg(new subtitle_insert_before_videotime()); + cm->reg(new subtitle_new()); + cm->reg(new subtitle_open()); + cm->reg(new subtitle_open_charset()); + cm->reg(new subtitle_open_video()); + cm->reg(new subtitle_properties()); + cm->reg(new subtitle_save()); + cm->reg(new subtitle_save_as()); + cm->reg(new subtitle_select_visiblek()); + cm->reg(new subtitle_spellcheck()); + cm->reg(new subtitle_tags_show()); +} + + +} // namespace cmd diff --git a/aegisub/src/command/time.cpp b/aegisub/src/command/time.cpp new file mode 100644 index 000000000..832377a56 --- /dev/null +++ b/aegisub/src/command/time.cpp @@ -0,0 +1,298 @@ +// Copyright (c) 2005-2010, Niels Martin Hansen +// Copyright (c) 2005-2010, Rodrigo Braz Monteiro +// Copyright (c) 2010, Amar Takhar +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Aegisub Project http://www.aegisub.org/ +// +// $Id$ + +/// @file time.cpp +/// @brief time/ commands. +/// @ingroup command +/// + +#include "config.h" + +#ifndef AGI_PRE +#endif + +#include "command.h" + +#include "aegisub/context.h" +#include "subs_grid.h" +#include "video_context.h" +#include "ass_dialogue.h" +#include "dialog_shift_times.h" +#include "ass_file.h" + +namespace cmd { +/// @defgroup cmd-time Time manipulation commands. +/// @{ + + +/// Changes times of subs so end times begin on next's start time. +class time_continous_end: public Command { +public: + CMD_NAME("time/continous/end") + STR_MENU("Change &End") + STR_DISP("Change End") + STR_HELP("Changes times of subs so end times begin on next's start time.") + + void operator()(agi::Context *c) { +//XXX: subs_grid.cpp + } +}; + + +/// Changes times of subs so start times begin on previous's end time. +class time_continous_start: public Command { +public: + CMD_NAME("time/continous/start") + STR_MENU("Change &Start") + STR_DISP("Change Start") + STR_HELP("Changes times of subs so start times begin on previous's end time.") + + void operator()(agi::Context *c) { +//XXX: subs_grid.cpp + } + +}; + + +/// Shift selection so first selected line starts at current frame. +class time_frame_current: public Command { +public: + CMD_NAME("time/frame/current") + STR_MENU("Shift to Current Frame") + STR_DISP("Shift to Current Frame") + STR_HELP("Shift selection so first selected line starts at current frame.") + + void operator()(agi::Context *c) { + if (!VideoContext::Get()->IsLoaded()) return; + + wxArrayInt sels = c->SubsGrid->GetSelection(); + size_t n=sels.Count(); + if (n == 0) return; + + // Get shifting in ms + AssDialogue *cur = c->SubsGrid->GetDialogue(sels[0]); + if (!cur) return; + int shiftBy = VideoContext::Get()->TimeAtFrame(VideoContext::Get()->GetFrameN(),agi::vfr::START) - cur->Start.GetMS(); + + // Update + for (size_t i=0;iSubsGrid->GetDialogue(sels[i]); + if (cur) { + cur->Start.SetMS(cur->Start.GetMS()+shiftBy); + cur->End.SetMS(cur->End.GetMS()+shiftBy); + } + } + + // Commit + c->SubsGrid->ass->Commit(_("shift to frame"), AssFile::COMMIT_TIMES); + } +}; + + +/// Shift subtitles by time or frames. +class time_shift: public Command { +public: + CMD_NAME("time/shift") + STR_MENU("S&hift Times..") + STR_DISP("Shift Times") + STR_HELP("Shift subtitles by time or frames.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + DialogShiftTimes Shift(c->parent, c->SubsGrid); + Shift.ShowModal(); + } +}; + + + +/// Set end of selected subtitles to current video frame. +class time_snap_end_video: public Command { +public: + CMD_NAME("time/snap/end_video") + STR_MENU("Snap End to Video") + STR_DISP("Snap End to Video") + STR_HELP("Set end of selected subtitles to current video frame.") + + void operator()(agi::Context *c) { + c->SubsGrid->SetSubsToVideo(false); + } +}; + + +/// Shift selected subtitles so first selected starts at this frame. +class time_snap_frame: public Command { +public: + CMD_NAME("time/snap/frame") + STR_MENU("Shift Subtitles to Frame") + STR_DISP("Shift Subtitles to Frame") + STR_HELP("Shift selected subtitles so first selected starts at this frame.") + + void operator()(agi::Context *c) { +//XXX: needs contents. + } +}; + + +/// Set start and end of subtitles to the keyframes around current video frame. +class time_snap_scene: public Command { +public: + CMD_NAME("time/snap/scene") + STR_MENU("Snap to Scene") + STR_DISP("Snap to Scene") + STR_HELP("Set start and end of subtitles to the keyframes around current video frame.") + + void operator()(agi::Context *c) { + VideoContext *con = VideoContext::Get(); + if (!con->IsLoaded() || !con->KeyFramesLoaded()) return; + + // Get frames + wxArrayInt sel = c->SubsGrid->GetSelection(); + int curFrame = con->GetFrameN(); + int prev = 0; + int next = 0; + + const std::vector &keyframes = con->GetKeyFrames(); + if (curFrame < keyframes.front()) { + next = keyframes.front(); + } + else if (curFrame >= keyframes.back()) { + prev = keyframes.back(); + next = con->GetLength(); + } + else { + std::vector::const_iterator kf = std::lower_bound(keyframes.begin(), keyframes.end(), curFrame); + if (*kf == curFrame) { + prev = *kf; + next = *(kf + 1); + } + else { + prev = *(kf - 1); + next = *kf; + } + } + + // Get times + int start_ms = con->TimeAtFrame(prev,agi::vfr::START); + int end_ms = con->TimeAtFrame(next-1,agi::vfr::END); + AssDialogue *cur; + + // Update rows + for (size_t i=0;iSubsGrid->GetDialogue(sel[i]); + cur->Start.SetMS(start_ms); + cur->End.SetMS(end_ms); + } + + // Commit + c->SubsGrid->ass->Commit(_("snap to scene"), AssFile::COMMIT_TIMES); + } +}; + + +/// Set start of selected subtitles to current video frame. +class time_snap_start_video: public Command { +public: + CMD_NAME("time/snap/start_video") + STR_MENU("Snap Start to Video") + STR_DISP("Snap Start to Video") + STR_HELP("Set start of selected subtitles to current video frame.") + + void operator()(agi::Context *c) { + c->SubsGrid->SetSubsToVideo(false); + } +}; + + +/// Sort all subtitles by their end times. +class time_sort_end: public Command { +public: + CMD_NAME("time/sort/end") + STR_MENU("&End Time") + STR_DISP("End Time") + STR_HELP("Sort all subtitles by their end times.") + + void operator()(agi::Context *c) { + c->ass->Sort(AssFile::CompEnd); + c->ass->Commit(_("sort")); + } +}; + + +/// Sort all subtitles by their start times. +class time_sort_start: public Command { +public: + CMD_NAME("time/sort/start") + STR_MENU("&Start Time") + STR_DISP("Start Time") + STR_HELP("Sort all subtitles by their start times.") + + void operator()(agi::Context *c) { + c->ass->Sort(); + c->ass->Commit(_("sort")); + } +}; + + +/// Sort all subtitles by their style names. +class time_sort_style: public Command { +public: + CMD_NAME("time/sort/style") + STR_MENU("St&yle Name") + STR_DISP("Style Name") + STR_HELP("Sort all subtitles by their style names.") + + void operator()(agi::Context *c) { + c->ass->Sort(AssFile::CompStyle); + c->ass->Commit(_("sort")); + } +}; + +/// @} + +/// Init time/ commands. +void init_time(CommandManager *cm) { + cm->reg(new time_continous_end()); + cm->reg(new time_continous_start()); + cm->reg(new time_frame_current()); + cm->reg(new time_shift()); + cm->reg(new time_snap_end_video()); + cm->reg(new time_snap_frame()); + cm->reg(new time_snap_scene()); + cm->reg(new time_snap_start_video()); + cm->reg(new time_sort_end()); + cm->reg(new time_sort_start()); + cm->reg(new time_sort_style()); +} + +} // namespace cmd diff --git a/aegisub/src/command/timecode.cpp b/aegisub/src/command/timecode.cpp new file mode 100644 index 000000000..8123a747c --- /dev/null +++ b/aegisub/src/command/timecode.cpp @@ -0,0 +1,120 @@ +// Copyright (c) 2005-2010, Niels Martin Hansen +// Copyright (c) 2005-2010, Rodrigo Braz Monteiro +// Copyright (c) 2010, Amar Takhar +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Aegisub Project http://www.aegisub.org/ +// +// $Id$ + +/// @file timecode.cpp +/// @brief timecode/ commands. +/// @ingroup command +/// + +#include "config.h" + +#ifndef AGI_PRE +#include +#endif + +#include "command.h" + +#include "aegisub/context.h" +#include "video_context.h" +#include "main.h" +#include "compat.h" +#include "subs_edit_box.h" + +namespace cmd { +/// @defgroup cmd-timecode Timecode commands. +/// @{ + + +/// Closes the currently open timecodes file. +class timecode_close: public Command { +public: + CMD_NAME("timecode/close") + STR_MENU("Close Timecodes File") + STR_DISP("Close Timecodes File") + STR_HELP("Closes the currently open timecodes file.") + + void operator()(agi::Context *c) { + VideoContext::Get()->CloseTimecodes(); + } +}; + + +/// Opens a VFR timecodes v1 or v2 file. +class timecode_open: public Command { +public: + CMD_NAME("timecode/open") + STR_MENU("Open Timecodes File..") + STR_DISP("Open Timecodes File") + STR_HELP("Opens a VFR timecodes v1 or v2 file.") + + void operator()(agi::Context *c) { + wxString path = lagi_wxString(OPT_GET("Path/Last/Timecodes")->GetString()); + wxString str = wxString(_("All Supported Types")) + _T("(*.txt)|*.txt|") + _("All Files") + _T(" (*.*)|*.*"); + wxString filename = wxFileSelector(_("Open timecodes file"),path,_T(""),_T(""),str,wxFD_OPEN | wxFD_FILE_MUST_EXIST); + if (!filename.empty()) { + VideoContext::Get()->LoadTimecodes(filename); + OPT_SET("Path/Last/Timecodes")->SetString(STD_STR(filename)); + } + } +}; + + +/// Saves a VFR timecodes v2 file. +class timecode_save: public Command { +public: + CMD_NAME("timecode/save") + STR_MENU("Save Timecodes File..") + STR_DISP("Save Timecodes File") + STR_HELP("Saves a VFR timecodes v2 file.") + + void operator()(agi::Context *c) { + wxString path = lagi_wxString(OPT_GET("Path/Last/Timecodes")->GetString()); + wxString str = wxString(_("All Supported Types")) + _T("(*.txt)|*.txt|") + _("All Files") + _T(" (*.*)|*.*"); + wxString filename = wxFileSelector(_("Save timecodes file"),path,_T(""),_T(""),str,wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + if (!filename.empty()) { + VideoContext::Get()->SaveTimecodes(filename); + OPT_SET("Path/Last/Timecodes")->SetString(STD_STR(filename)); + } + } +}; + +/// @} + +/// Init timecode/ commands. +void init_timecode(CommandManager *cm) { + cm->reg(new timecode_close()); + cm->reg(new timecode_open()); + cm->reg(new timecode_save()); +} + +} // namespace cmd diff --git a/aegisub/src/command/tool.cpp b/aegisub/src/command/tool.cpp new file mode 100644 index 000000000..79c230508 --- /dev/null +++ b/aegisub/src/command/tool.cpp @@ -0,0 +1,237 @@ +// Copyright (c) 2005-2010, Niels Martin Hansen +// Copyright (c) 2005-2010, Rodrigo Braz Monteiro +// Copyright (c) 2010, Amar Takhar +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Aegisub Project http://www.aegisub.org/ +// +// $Id$ + +/// @file tool.cpp +/// @brief tool/ commands. +/// @ingroup command +/// + +#include "config.h" + +#ifndef AGI_PRE +#include +#endif + +#include "command.h" + +#include "aegisub/context.h" + +#include "dialog_fonts_collector.h" +#include "standard_paths.h" // tool_assdraw +#include "video_context.h" // tool_font_collector +#include "dialog_resample.h" +#include "dialog_selection.h" +#include "dialog_style_manager.h" +#include "dialog_timing_processor.h" +#include "dialog_translation.h" +#include "dialog_kara_timing_copy.h" + +namespace cmd { +/// @defgroup cmd-tool Various tool and utilities +/// @{ + + +/// Launch ASSDraw3 tool for vector drawing. +class tool_assdraw: public Command { +public: + CMD_NAME("tool/assdraw") + STR_MENU("ASSDraw3...") + STR_DISP("ASSDraw3") + STR_HELP("Launch ASSDraw3 tool for vector drawing.") + + void operator()(agi::Context *c) { + wxExecute(_T("\"") + StandardPaths::DecodePath(_T("?data/ASSDraw3.exe")) + _T("\"")); + } +}; + +/// Saves a copy of subtitles with processing applied to it. +class tool_export: public Command { +public: + CMD_NAME("tool/export") + STR_MENU("Export Subtitles..") + STR_DISP("Export Subtitles") + STR_HELP("Saves a copy of subtitles with processing applied to it.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + DialogResample diag(c->parent, c->SubsGrid); + diag.ShowModal(); + } +}; + + +/// Open fonts collector. +class tool_font_collector: public Command { +public: + CMD_NAME("tool/font_collector") + STR_MENU("&Fonts Collector..") + STR_DISP("Fonts Collector") + STR_HELP("Open fonts collector.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + DialogFontsCollector Collector(c->parent, c->ass); + Collector.ShowModal(); + } +}; + + +/// Selects lines based on defined criterea. +class tool_line_select: public Command { +public: + CMD_NAME("tool/line/select") + STR_MENU("Select Lines..") + STR_DISP("Select Lines") + STR_HELP("Selects lines based on defined criterea.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + DialogSelection select(c->parent, c->SubsGrid); + select.ShowModal(); + } +}; + + +/// Changes resolution and modifies subtitles to conform to change. +class tool_resampleres: public Command { +public: + CMD_NAME("tool/resampleres") + STR_MENU("Resample Resolution..") + STR_DISP("Resample Resolution") + STR_HELP("Changes resolution and modifies subtitles to conform to change.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + DialogResample diag(c->parent, c->SubsGrid); + diag.ShowModal(); + } +}; + + +/// Open styling assistant. +class tool_style_assistant: public Command { +public: + CMD_NAME("tool/style/assistant") + STR_MENU("St&yling Assistant..") + STR_DISP("Styling Assistant") + STR_HELP("Open styling assistant.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + if (!c->stylingAssistant) c->stylingAssistant = new DialogStyling(c->parent, c->SubsGrid); + c->stylingAssistant->Show(true); + } +}; + + +/// Open styles manager. +class tool_style_manager: public Command { +public: + CMD_NAME("tool/style/manager") + STR_MENU("&Styles Manager..") + STR_DISP("Styles Manager") + STR_HELP("Open styles manager.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + DialogStyleManager StyleManager(c->parent, c->SubsGrid); + StyleManager.ShowModal(); + } +}; + + +/// Open Kanji timer. +class tool_time_kanji: public Command { +public: + CMD_NAME("tool/time/kanji") + STR_MENU("Kanji Timer..") + STR_DISP("Kanji Timer") + STR_HELP("Open Kanji timer.") + + void operator()(agi::Context *c) { + DialogKanjiTimer kanjitimer(c->parent, c->SubsGrid); + kanjitimer.ShowModal(); + } +}; + + +/// Launch timing post-processor. +class tool_time_postprocess: public Command { +public: + CMD_NAME("tool/time/postprocess") + STR_MENU("Timing Post-Processor..") + STR_DISP("Timing Post-Processor") + STR_HELP("Runs a post-processor for timing to deal with lead-ins, lead-outs, scene timing and etc.") + + void operator()(agi::Context *c) { + DialogTimingProcessor timing(c->parent, c->SubsGrid); + timing.ShowModal(); + } +}; + + +/// Open translation assistant. +class tool_translation_assistant: public Command { +public: + CMD_NAME("tool/translation_assistant") + STR_MENU("&Translation Assistant..") + STR_DISP("Translation Assistant") + STR_HELP("Open translation assistant.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + int start = c->SubsGrid->GetFirstSelRow(); + if (start == -1) start = 0; + DialogTranslation Trans(c->parent, c->ass, c->SubsGrid, start, true); + Trans.ShowModal(); + } +}; + +/// @} + +/// Init tool/ commands. +void init_tool(CommandManager *cm) { + cm->reg(new tool_assdraw()); + cm->reg(new tool_export()); + cm->reg(new tool_font_collector()); + cm->reg(new tool_line_select()); + cm->reg(new tool_resampleres()); + cm->reg(new tool_style_assistant()); + cm->reg(new tool_style_manager()); + cm->reg(new tool_time_kanji()); + cm->reg(new tool_time_postprocess()); + cm->reg(new tool_translation_assistant()); +} + + +} // namespace cmd diff --git a/aegisub/src/command/video.cpp b/aegisub/src/command/video.cpp new file mode 100644 index 000000000..30d0752ee --- /dev/null +++ b/aegisub/src/command/video.cpp @@ -0,0 +1,499 @@ +// Copyright (c) 2005-2010, Niels Martin Hansen +// Copyright (c) 2005-2010, Rodrigo Braz Monteiro +// Copyright (c) 2010, Amar Takhar +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Aegisub Project http://www.aegisub.org/ +// +// $Id$ + +/// @file video.cpp +/// @brief video/ commands. +/// @ingroup command +/// + +#include "config.h" + +#ifndef AGI_PRE +#endif + +#include "command.h" + +#include "aegisub/context.h" +#include "video_context.h" +#include "main.h" +#include "utils.h" +#include "frame_main.h" +#include "video_display.h" +#include "dialog_detached_video.h" +#include "dialog_video_details.h" +#include "video_slider.h" +#include "dialog_dummy_video.h" +#include "compat.h" +#include "dialog_jumpto.h" + +namespace cmd { +/// @defgroup cmd-video Video commands. +/// @{ + + +/// Forces video to 2.35 aspect ratio. +class video_aspect_cinematic: public Command { +public: + CMD_NAME("video/aspect/cinematic") + STR_MENU("&Cinematic (2.35)") + STR_DISP("Cinematic (235)") + STR_HELP("Forces video to 2.35 aspect ratio.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + VideoContext::Get()->SetAspectRatio(3); + wxGetApp().frame->SetDisplayMode(1,-1); + } +}; + + +/// Forces video to a custom aspect ratio. +class video_aspect_custom: public Command { +public: + CMD_NAME("video/aspect/custom") + STR_MENU("Custom..") + STR_DISP("Custom") + STR_HELP("Forces video to a custom aspect ratio.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + + wxString value = wxGetTextFromUser(_("Enter aspect ratio in either:\n decimal (e.g. 2.35)\n fractional (e.g. 16:9)\n specific resolution (e.g. 853x480)"),_("Enter aspect ratio"),AegiFloatToString(VideoContext::Get()->GetAspectRatioValue())); + if (value.IsEmpty()) return; + + value.MakeLower(); + + // Process text + double numval; + if (value.ToDouble(&numval)) { + //Nothing to see here, move along + } + else { + double a,b; + int pos=0; + bool scale=false; + + //Why bloat using Contains when we can just check the output of Find? + pos = value.Find(':'); + if (pos==wxNOT_FOUND) pos = value.Find('/'); + if (pos==wxNOT_FOUND&&value.Contains(_T('x'))) { + pos = value.Find('x'); + scale=true; + } + + if (pos>0) { + wxString num = value.Left(pos); + wxString denum = value.Mid(pos+1); + if (num.ToDouble(&a) && denum.ToDouble(&b) && b!=0) { + numval = a/b; + if (scale) c->videoBox->videoDisplay->SetZoom(b / VideoContext::Get()->GetHeight()); + } + } + else numval = 0.0; + } + + // Sanity check + if (numval < 0.5 || numval > 5.0) wxMessageBox(_("Invalid value! Aspect ratio must be between 0.5 and 5.0."),_("Invalid Aspect Ratio"),wxICON_ERROR|wxOK); + + // Set value + else { + VideoContext::Get()->SetAspectRatio(4,numval); + wxGetApp().frame->SetDisplayMode(1,-1); + } + } +}; + + + +/// Leave video on original aspect ratio. +class video_aspect_default: public Command { +public: + CMD_NAME("video/aspect/default") + STR_MENU("&Default") + STR_DISP("Default") + STR_HELP("Leave video on original aspect ratio.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + VideoContext::Get()->SetAspectRatio(0); + wxGetApp().frame->SetDisplayMode(1,-1); + } +}; + + + +/// Forces video to 4:3 aspect ratio. +class video_aspect_full: public Command { +public: + CMD_NAME("video/aspect/full") + STR_MENU("&Fullscreen (4:3)") + STR_DISP("Fullscreen (4:3)") + STR_HELP("Forces video to 4:3 aspect ratio.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + VideoContext::Get()->SetAspectRatio(1); + wxGetApp().frame->SetDisplayMode(1,-1); + } +}; + + +/// Forces video to 16:9 aspect ratio. +class video_aspect_wide: public Command { +public: + CMD_NAME("video/aspect/wide") + STR_MENU("&Widescreen (16:9)") + STR_DISP("Widescreen (16:9)") + STR_HELP("Forces video to 16:9 aspect ratio.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + VideoContext::Get()->SetAspectRatio(2); + wxGetApp().frame->SetDisplayMode(1,-1); + } +}; + + +/// Closes the currently open video file. +class video_close: public Command { +public: + CMD_NAME("video/close") + STR_MENU("&Close Video") + STR_DISP("Close Video") + STR_HELP("Closes the currently open video file.") + + void operator()(agi::Context *c) { + wxGetApp().frame->LoadVideo(_T("")); + } +}; + + + +/// Detach video, displaying it in a separate Window. +class video_detach: public Command { +public: + CMD_NAME("video/detach") + STR_MENU("Detach Video") + STR_DISP("Detach Video") + STR_HELP("Detach video, displaying it in a separate Window.") + + void operator()(agi::Context *c) { + wxGetApp().frame->DetachVideo(!c->detachedVideo); + } +}; + + +/// Shows video details. +class video_details: public Command { +public: + CMD_NAME("video/details") + STR_MENU("Show Video Details..") + STR_DISP("Show Video Details") + STR_HELP("Shows video details.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + DialogVideoDetails videodetails(c->parent); + videodetails.ShowModal(); + } +}; + + +/// +class video_focus_seek: public Command { +public: + CMD_NAME("video/focus_seek") + STR_MENU("XXX: no idea") + STR_DISP("XXX: no idea") + STR_HELP("XXX: no idea") + + void operator()(agi::Context *c) { + wxWindow *curFocus = wxWindow::FindFocus(); + if (curFocus == c->videoBox->videoSlider) { + if (c->PreviousFocus) c->PreviousFocus->SetFocus(); + } + else { + c->PreviousFocus = curFocus; + c->videoBox->videoSlider->SetFocus(); + } + } +}; + + +/// Seek to the next frame. +class video_frame_next: public Command { +public: + CMD_NAME("video/frame/next") + STR_MENU("Next Frame") + STR_DISP("Next Frame") + STR_HELP("Seek to the next frame.") + + void operator()(agi::Context *c) { + c->videoBox->videoSlider->NextFrame(); + } +}; + + +/// Play video. +class video_frame_play: public Command { +public: + CMD_NAME("video/frame/play") + STR_MENU("Play") + STR_DISP("Play") + STR_HELP("Play video.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Play(); + } +}; + + +/// Seek to the previous frame. +class video_frame_prev: public Command { +public: + CMD_NAME("video/frame/prev") + STR_MENU("Previous Frame") + STR_DISP("Previous Frame") + STR_HELP("Seek to the previous frame.") + + void operator()(agi::Context *c) { + c->videoBox->videoSlider->PrevFrame(); + } +}; + + +/// Jump to frame or time. +class video_jump: public Command { +public: + CMD_NAME("video/jump") + STR_MENU("&Jump to..") + STR_DISP("Jump to") + STR_HELP("Jump to frame or time.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + if (VideoContext::Get()->IsLoaded()) { + DialogJumpTo JumpTo(c->parent); + JumpTo.ShowModal(); + c->videoBox->videoSlider->SetFocus(); + } + } +}; + + +/// Jumps the video to the end frame of current subtitle. +class video_jump_end: public Command { +public: + CMD_NAME("video/jump/end") + STR_MENU("Jump Video to End") + STR_DISP("Jump Video to End") + STR_HELP("Jumps the video to the end frame of current subtitle.") + + void operator()(agi::Context *c) { + c->SubsGrid->SetVideoToSubs(false); + } +}; + + +/// Jumps the video to the start frame of current subtitle. +class video_jump_start: public Command { +public: + CMD_NAME("video/jump/start") + STR_MENU("Jump Video to Start") + STR_DISP("Jump Video to Start") + STR_HELP("Jumps the video to the start frame of current subtitle.") + + void operator()(agi::Context *c) { + c->SubsGrid->SetVideoToSubs(true); + } +}; + + +/// Opens a video file. +class video_open: public Command { +public: + CMD_NAME("video/open") + STR_MENU("&Open Video..") + STR_DISP("Open Video") + STR_HELP("Opens a video file.") + + void operator()(agi::Context *c) { + wxString path = lagi_wxString(OPT_GET("Path/Last/Video")->GetString()); + wxString str = wxString(_("Video Formats")) + _T(" (*.avi,*.mkv,*.mp4,*.avs,*.d2v,*.ogm,*.mpeg,*.mpg,*.vob,*.mov)|*.avi;*.avs;*.d2v;*.mkv;*.ogm;*.mp4;*.mpeg;*.mpg;*.vob;*.mov|") + + _("All Files") + _T(" (*.*)|*.*"); + wxString filename = wxFileSelector(_("Open video file"),path,_T(""),_T(""),str,wxFD_OPEN | wxFD_FILE_MUST_EXIST); + if (!filename.empty()) { + wxGetApp().frame->LoadVideo(filename); + OPT_SET("Path/Last/Video")->SetString(STD_STR(filename)); + } + } +}; + + +/// Opens a video clip with solid colour. +class video_open_dummy: public Command { +public: + CMD_NAME("video/open/dummy") + STR_MENU("Use Dummy Video..") + STR_DISP("Use Dummy Video") + STR_HELP("Opens a video clip with solid colour.") + + void operator()(agi::Context *c) { + wxString fn; + if (DialogDummyVideo::CreateDummyVideo(c->parent, fn)) { + wxGetApp().frame->LoadVideo(fn); + } + } +}; + + +/// Show a mask over the video. +class video_show_overscan: public Command { +public: + CMD_NAME("video/show_overscan") + STR_MENU("Show Overscan Mask") + STR_DISP("Show Overscan Mask") + STR_HELP("Show a mask over the video, indicating areas that might get cropped off by overscan on televisions.") + + void operator()(agi::Context *c) { +//XXX: Fix to not require using an event. (maybe) +// OPT_SET("Video/Overscan Mask")->SetBool(event.IsChecked()); + VideoContext::Get()->Stop(); + c->videoBox->videoDisplay->Render(); + } +}; + + +/// Set zoom to 100%. +class video_zoom_100: public Command { +public: + CMD_NAME("video/zoom/100") + STR_MENU("&100%") + STR_DISP("100%") + STR_HELP("Set zoom to 100%.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + c->videoBox->videoDisplay->SetZoom(1.); + } +}; + + + +/// Set zoom to 200%. +class video_zoom_200: public Command { +public: + CMD_NAME("video/zoom/200") + STR_MENU("&200%") + STR_DISP("200%") + STR_HELP("Set zoom to 200%.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + c->videoBox->videoDisplay->SetZoom(2.); + } +}; + + +/// Set zoom to 50%. +class video_zoom_50: public Command { +public: + CMD_NAME("video/zoom/50") + STR_MENU("&50%") + STR_DISP("50%") + STR_HELP("Set zoom to 50%.") + + void operator()(agi::Context *c) { + VideoContext::Get()->Stop(); + c->videoBox->videoDisplay->SetZoom(.5); + } +}; + + +/// Zoom video in. +class video_zoom_in: public Command { +public: + CMD_NAME("video/zoom/in") + STR_MENU("Zoom In") + STR_DISP("Zoom In") + STR_HELP("Zoom video in.") + + void operator()(agi::Context *c) { + c->videoBox->videoDisplay->SetZoom(c->videoBox->videoDisplay->GetZoom() + .125); + } +}; + + +/// Zoom video out. +class video_zoom_out: public Command { +public: + CMD_NAME("video/zoom/out") + STR_MENU("Zoom Out") + STR_DISP("Zoom Out") + STR_HELP("Zoom video out.") + + void operator()(agi::Context *c) { + c->videoBox->videoDisplay->SetZoom(c->videoBox->videoDisplay->GetZoom() - .125); + } +}; + +/// @} + +/// Init video/ commands. +void init_video(CommandManager *cm) { + cm->reg(new video_aspect_cinematic()); + cm->reg(new video_aspect_custom()); + cm->reg(new video_aspect_default()); + cm->reg(new video_aspect_full()); + cm->reg(new video_aspect_wide()); + cm->reg(new video_close()); + cm->reg(new video_detach()); + cm->reg(new video_details()); + cm->reg(new video_focus_seek()); + cm->reg(new video_frame_next()); + cm->reg(new video_frame_play()); + cm->reg(new video_frame_prev()); + cm->reg(new video_jump()); + cm->reg(new video_jump_end()); + cm->reg(new video_jump_start()); + cm->reg(new video_open()); + cm->reg(new video_open_dummy()); + cm->reg(new video_show_overscan()); + cm->reg(new video_zoom_100()); + cm->reg(new video_zoom_200()); + cm->reg(new video_zoom_50()); + cm->reg(new video_zoom_in()); + cm->reg(new video_zoom_out()); +} + +} // namespace cmd diff --git a/aegisub/src/dialog_detached_video.h b/aegisub/src/dialog_detached_video.h index c7ca7653d..10c131c82 100644 --- a/aegisub/src/dialog_detached_video.h +++ b/aegisub/src/dialog_detached_video.h @@ -34,6 +34,8 @@ /// @ingroup main_ui /// +#pragma once + #ifndef AGI_PRE #include #endif diff --git a/aegisub/src/dialog_styling_assistant.cpp b/aegisub/src/dialog_styling_assistant.cpp index b6c8f0d91..6aceca72b 100644 --- a/aegisub/src/dialog_styling_assistant.cpp +++ b/aegisub/src/dialog_styling_assistant.cpp @@ -43,6 +43,8 @@ #include #endif +#include "aegisub/hotkey.h" + #include "ass_dialogue.h" #include "ass_file.h" #include "ass_style.h" @@ -52,7 +54,6 @@ #include "dialog_styling_assistant.h" #include "frame_main.h" #include "help_button.h" -#include "hotkeys.h" #include "libresrc/libresrc.h" #include "subs_edit_box.h" #include "subs_grid.h" @@ -99,17 +100,17 @@ wxDialog (parent, -1, _("Styling assistant"), wxDefaultPosition, wxDefaultSize, // Shortcuts //wxStaticText *Keys = new wxStaticText(this,-1,_("Enter:\t\tAccept changes\nPage up:\tPrevious line\nPage down:\tNext line\nEnd:\t\tPlay sound\nClick on list:\tSet style\nCtrl+enter:\tAccept without going to next")); wxSizer *KeysInnerSizer = new wxGridSizer(2,0,5); - KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Styling Assistant Accept")) + _T(": "))); +//H KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Styling Assistant Accept")) + _T(": "))); KeysInnerSizer->Add(new wxStaticText(this,-1,_("Accept changes"))); - KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Styling Assistant Preview")) + _T(": "))); +//H KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Styling Assistant Preview")) + _T(": "))); KeysInnerSizer->Add(new wxStaticText(this,-1,_("Preview changes"))); - KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Styling Assistant Prev")) + _T(": "))); +//H KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Styling Assistant Prev")) + _T(": "))); KeysInnerSizer->Add(new wxStaticText(this,-1,_("Previous line"))); - KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Styling Assistant Next")) + _T(": "))); +//H KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Styling Assistant Next")) + _T(": "))); KeysInnerSizer->Add(new wxStaticText(this,-1,_("Next line"))); - KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Styling Assistant Play Video")) + _T(": "))); +//H KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Styling Assistant Play Video")) + _T(": "))); KeysInnerSizer->Add(new wxStaticText(this,-1,_("Play Video"))); - KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Styling Assistant Play Audio")) + _T(": "))); +//H KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Styling Assistant Play Audio")) + _T(": "))); KeysInnerSizer->Add(new wxStaticText(this,-1,_("Play Audio"))); KeysInnerSizer->Add(new wxStaticText(this,-1,_("Click on list:"))); KeysInnerSizer->Add(new wxStaticText(this,-1,_("Select style"))); @@ -410,7 +411,14 @@ END_EVENT_TABLE() /// @return /// void StyleEditBox::OnKeyDown(wxKeyEvent &event) { + + hotkey::check("Styling Assistant", event.GetKeyCode(), event.GetUnicodeKey(), event.GetModifiers()); + event.StopPropagation(); + +//H I think most of this can be removed. //int keycode = event.GetKeyCode(); +/* +* #ifdef __APPLE__ Hotkeys.SetPressed(event.GetKeyCode(),event.m_metaDown,event.m_altDown,event.m_shiftDown); #else @@ -451,11 +459,10 @@ void StyleEditBox::OnKeyDown(wxKeyEvent &event) { // Play audio if (Hotkeys.IsPressed(_T("Styling Assistant Play Audio"))) { /// @todo Reinstate this when the audio controller is made reachable from here - /* - if (diag->audio->loaded) { - diag->audio->Play(diag->line->Start.GetMS(),diag->line->End.GetMS()); - } - */ + + //if (diag->audio->loaded) { + // diag->audio->Play(diag->line->Start.GetMS(),diag->line->End.GetMS()); + //} return; } @@ -481,6 +488,7 @@ void StyleEditBox::OnKeyDown(wxKeyEvent &event) { } event.Skip(); +*/ } diff --git a/aegisub/src/dialog_styling_assistant.h b/aegisub/src/dialog_styling_assistant.h index de21ccac2..1b1beeac8 100644 --- a/aegisub/src/dialog_styling_assistant.h +++ b/aegisub/src/dialog_styling_assistant.h @@ -34,7 +34,7 @@ /// @ingroup tools_ui /// - +#pragma once /////////// diff --git a/aegisub/src/dialog_translation.cpp b/aegisub/src/dialog_translation.cpp index c2cf9e8df..c93d3530d 100644 --- a/aegisub/src/dialog_translation.cpp +++ b/aegisub/src/dialog_translation.cpp @@ -43,13 +43,14 @@ #include #endif +#include "aegisub/hotkey.h" + #include "ass_dialogue.h" #include "ass_file.h" #include "audio_controller.h" #include "dialog_translation.h" #include "frame_main.h" #include "help_button.h" -#include "hotkeys.h" #include "libresrc/libresrc.h" #include "selection_controller.h" #include "subs_edit_box.h" @@ -108,19 +109,19 @@ DialogTranslation::DialogTranslation (wxWindow *parent,AssFile *_subs,SubtitlesG // Hotkeys wxSizer *KeysSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Keys")); wxSizer *KeysInnerSizer = new wxGridSizer(2,0,5); - KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Translation Assistant Accept")) + _T(": "))); +//H KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Translation Assistant Accept")) + _T(": "))); KeysInnerSizer->Add(new wxStaticText(this,-1,_("Accept changes"))); - KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Translation Assistant Preview")) + _T(": "))); +//H KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Translation Assistant Preview")) + _T(": "))); KeysInnerSizer->Add(new wxStaticText(this,-1,_("Preview changes"))); - KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Translation Assistant Prev")) + _T(": "))); +//H KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Translation Assistant Prev")) + _T(": "))); KeysInnerSizer->Add(new wxStaticText(this,-1,_("Previous line"))); - KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Translation Assistant Next")) + _T(": "))); +//H KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Translation Assistant Next")) + _T(": "))); KeysInnerSizer->Add(new wxStaticText(this,-1,_("Next line"))); - KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Translation Assistant Insert Original")) + _T(": "))); +//H KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Translation Assistant Insert Original")) + _T(": "))); KeysInnerSizer->Add(new wxStaticText(this,-1,_("Insert original"))); - KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Translation Assistant Play Video")) + _T(": "))); +//H KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Translation Assistant Play Video")) + _T(": "))); KeysInnerSizer->Add(new wxStaticText(this,-1,_("Play Video"))); - KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Translation Assistant Play Audio")) + _T(": "))); +//H KeysInnerSizer->Add(new wxStaticText(this,-1,Hotkeys.GetText(_T("Translation Assistant Play Audio")) + _T(": "))); KeysInnerSizer->Add(new wxStaticText(this,-1,_("Play Audio"))); PreviewCheck = new wxCheckBox(this,PREVIEW_CHECK,_("Enable preview")); PreviewCheck->SetValue(preview); @@ -312,6 +313,11 @@ void DialogTranslationEvent::OnTransBoxKey(wxKeyEvent &event) { control->OnTrans /// @return /// void DialogTranslation::OnTransBoxKey(wxKeyEvent &event) { + hotkey::check("Translation Assistant", event.GetKeyCode(), event.GetUnicodeKey(), event.GetModifiers()); + event.StopPropagation(); + +// H convert below to commands. +/* #ifdef __APPLE__ Hotkeys.SetPressed(event.GetKeyCode(),event.m_metaDown,event.m_altDown,event.m_shiftDown); #else @@ -355,7 +361,7 @@ void DialogTranslation::OnTransBoxKey(wxKeyEvent &event) { break; } } - + // Update line cur->UpdateText(); cur->ClearBlocks(); @@ -409,12 +415,10 @@ void DialogTranslation::OnTransBoxKey(wxKeyEvent &event) { // Play audio if (Hotkeys.IsPressed(_T("Translation Assistant Play Audio"))) { /// @todo Reinstate this when the audio controller is made reachable from here - /* - if (audio->loaded) { - audio->Play(current->Start.GetMS(),current->End.GetMS()); - TransText->SetFocus(); - } - */ + //if (audio->loaded) { + // audio->Play(current->Start.GetMS(),current->End.GetMS()); + // TransText->SetFocus(); + //} return; } @@ -426,6 +430,7 @@ void DialogTranslation::OnTransBoxKey(wxKeyEvent &event) { // Skip anything else event.Skip(); +*/ } diff --git a/aegisub/src/frame_main.cpp b/aegisub/src/frame_main.cpp index 71e2029b3..fe7c9e555 100644 --- a/aegisub/src/frame_main.cpp +++ b/aegisub/src/frame_main.cpp @@ -44,6 +44,11 @@ #include #endif +#include + +#include "aegisub/menu.h" +#include "aegisub/toolbar.h" +#include "aegisub/hotkey.h" #include "ass_file.h" #include "selection_controller.h" @@ -56,14 +61,13 @@ #include "avisynth_wrap.h" #endif #include "compat.h" +#include "command/command.h" #include "dialog_detached_video.h" #include "dialog_search_replace.h" -#include "dialog_styling_assistant.h" #include "dialog_version_check.h" #include "drop.h" #include "frame_main.h" #include "help_button.h" -#include "hotkeys.h" #include "libresrc/libresrc.h" #include "main.h" #include "standard_paths.h" @@ -97,6 +101,22 @@ FrameMain::FrameMain (wxArrayString args) : wxFrame ((wxFrame*)NULL,-1,_T(""),wxDefaultPosition,wxSize(920,700),wxDEFAULT_FRAME_STYLE | wxCLIP_CHILDREN) { StartupLog(_T("Entering FrameMain constructor")); + temp_context.parent = this; + + // Bind all commands. + // XXX: This is a hack for now, it will need to be dealt with when other frames are involved. + int count = cmd::count(); + for (int i = 0; i < count; i++) { + Bind(wxEVT_COMMAND_MENU_SELECTED, &FrameMain::cmd_call, this, i); + } + +#ifdef __WXMAC__ + Bind(FrameMain::OnAbout, &FrameMain::cmd_call, this, cmd::id("app/about")); +#endif + + + + #ifdef __WXGTK__ /* XXX HACK XXX * Gtk just got initialized. And if we're using the SCIM IME, @@ -127,10 +147,12 @@ FrameMain::FrameMain (wxArrayString args) #ifdef WITH_AUTOMATION StartupLog(_T("Create local Automation script manager")); local_scripts = new Automation4::ScriptManager(); + temp_context.local_scripts = local_scripts; #endif // Contexts and controllers audioController = new AudioController; + temp_context.audioController = audioController; audioController->AddAudioOpenListener(&FrameMain::OnAudioOpen, this); audioController->AddAudioCloseListener(&FrameMain::OnAudioClose, this); @@ -161,22 +183,22 @@ FrameMain::FrameMain (wxArrayString args) showAudio = true; detachedVideo = NULL; stylingAssistant = NULL; + temp_context.stylingAssistant = stylingAssistant; StartupLog(_T("Initialize inner main window controls")); InitContents(); // Set autosave timer StartupLog(_T("Set up Auto Save")); - AutoSave.SetOwner(this,AutoSave_Timer); + AutoSave.SetOwner(this, ID_APP_TIMER_AUTOSAVE); int time = OPT_GET("App/Auto/Save Every Seconds")->GetInt(); if (time > 0) { AutoSave.Start(time*1000); } OPT_SUB("App/Auto/Save Every Seconds", autosave_timer_changed, &AutoSave, agi::signal::_1); - // Set accelerator keys - StartupLog(_T("Install hotkeys")); - PreviousFocus = NULL; - SetAccelerators(); + + PreviousFocus = NULL; // Artifact from old hotkey removal not sure what it does. + temp_context.PreviousFocus = PreviousFocus; // Artifact from old hotkey removal not sure what it does. // Set drop target StartupLog(_T("Set up drag/drop target")); @@ -219,22 +241,24 @@ FrameMain::~FrameMain () { #endif } + + +void FrameMain::cmd_call(wxCommandEvent& event) { + int id = event.GetId(); + LOG_D("event/select") << "Id: " << id; + cmd::call(&temp_context, id); +} + + + /// @brief Initialize toolbar void FrameMain::InitToolbar () { // Create toolbar wxSystemOptions::SetOption(_T("msw.remap"), 0); Toolbar = CreateToolBar(wxTB_FLAT | wxTB_HORIZONTAL,-1,_T("Toolbar")); - // Subtitle control buttons - Toolbar->AddTool(Menu_File_New_Subtitles,_("New"),GETIMAGE(new_toolbutton_24),_("New subtitles")); - Toolbar->AddTool(Menu_File_Open_Subtitles,_("Open"),GETIMAGE(open_toolbutton_24),_("Open subtitles")); - Toolbar->AddTool(Menu_File_Save_Subtitles,_("Save"),GETIMAGE(save_toolbutton_24),_("Save subtitles")); - Toolbar->AddSeparator(); + toolbar::toolbar->GetToolbar("main", Toolbar); - // Video zoom controls - Toolbar->AddTool(Menu_Video_JumpTo,_("Jump To..."),GETIMAGE(jumpto_button_24),wxNullBitmap,wxITEM_NORMAL,_("Jump video to time/frame")); - Toolbar->AddTool(Menu_Video_Zoom_In,_("Zoom in"),GETIMAGE(zoom_in_button_24),wxNullBitmap,wxITEM_NORMAL,_("Zoom video in")); - Toolbar->AddTool(Menu_Video_Zoom_Out,_("Zoom out"),GETIMAGE(zoom_out_button_24),wxNullBitmap,wxITEM_NORMAL,_("Zoom video out")); wxArrayString choices; for (int i=1;i<=24;i++) { wxString toAdd = wxString::Format(_T("%i"),int(i*12.5)); @@ -242,73 +266,18 @@ void FrameMain::InitToolbar () { toAdd += _T("%"); choices.Add(toAdd); } - ZoomBox = new wxComboBox(Toolbar,Toolbar_Zoom_Dropdown,_T("75%"),wxDefaultPosition,wxDefaultSize,choices,wxCB_DROPDOWN); + ZoomBox = new wxComboBox(Toolbar,ID_TOOLBAR_ZOOM_DROPDOWN,_T("75%"),wxDefaultPosition,wxDefaultSize,choices,wxCB_DROPDOWN); Toolbar->AddControl(ZoomBox); Toolbar->AddSeparator(); - // More video buttons - Toolbar->AddTool(Menu_Subs_Snap_Video_To_Start,_("Jump video to start"),GETIMAGE(video_to_substart_24),_("Jumps the video to the start frame of current subtitle")); - Toolbar->AddTool(Menu_Subs_Snap_Video_To_End,_("Jump video to end"),GETIMAGE(video_to_subend_24),_("Jumps the video to the end frame of current subtitle")); - Toolbar->AddTool(Menu_Subs_Snap_Start_To_Video,_("Snap start to video"),GETIMAGE(substart_to_video_24),_("Set start of selected subtitles to current video frame")); - Toolbar->AddTool(Menu_Subs_Snap_End_To_Video,_("Snap end to video"),GETIMAGE(subend_to_video_24),_("Set end of selected subtitles to current video frame")); - Toolbar->AddTool(Menu_Video_Select_Visible,_("Select visible"),GETIMAGE(select_visible_button_24),_("Selects all lines that are currently visible on video frame")); - Toolbar->AddTool(Menu_Video_Snap_To_Scene,_("Snap subtitles to scene"),GETIMAGE(snap_subs_to_scene_24),_("Snap selected subtitles so they match current scene start/end")); - Toolbar->AddTool(Menu_Video_Shift_To_Frame,_("Shift subtitles to frame"),GETIMAGE(shift_to_frame_24),_("Shift selected subtitles so first selected starts at this frame")); - Toolbar->AddSeparator(); - - // Property stuff - Toolbar->AddTool(Menu_Tools_Styles_Manager,_("Styles Manager"),GETIMAGE(style_toolbutton_24),_("Open Styles Manager")); - Toolbar->AddTool(Menu_Tools_Properties,_("Properties"),GETIMAGE(properties_toolbutton_24),_("Open Properties")); - Toolbar->AddTool(Menu_Tools_Attachments,_("Attachments"),GETIMAGE(attach_button_24),_("Open Attachment List")); - Toolbar->AddTool(Menu_Tools_Fonts_Collector,_("Fonts Collector"),GETIMAGE(font_collector_button_24),_("Open Fonts Collector")); - Toolbar->AddSeparator(); - - // Automation -#ifdef WITH_AUTOMATION - Toolbar->AddTool(Menu_Tools_Automation,_("Automation"),GETIMAGE(automation_toolbutton_24),_("Open Automation manager")); - Toolbar->AddSeparator(); -#endif - - // Tools - if (HasASSDraw()) { - Toolbar->AddTool(Menu_Tools_ASSDraw,_T("ASSDraw3"),GETIMAGE(assdraw_24),_("Launches ai-chan's \"ASSDraw3\" tool for vector drawing.")); - Toolbar->AddSeparator(); - } - Toolbar->AddTool(Menu_Edit_Shift,_("Shift Times"),GETIMAGE(shift_times_toolbutton_24),_("Open Shift Times Dialogue")); - Toolbar->AddTool(Menu_Tools_Styling,_("Styling Assistant"),GETIMAGE(styling_toolbutton_24),_("Open Styling Assistant")); - Toolbar->AddTool(Menu_Tools_Translation,_("Translation Assistant"),GETIMAGE(translation_toolbutton_24),_("Open Translation Assistant")); - Toolbar->AddTool(Menu_Tools_Resample,_("Resample"),GETIMAGE(resample_toolbutton_24),_("Resample Script Resolution")); - Toolbar->AddTool(Menu_Tools_Timing_Processor,_("Timing Post-Processor"),GETIMAGE(timing_processor_toolbutton_24),_("Open Timing Post-processor dialog")); - Toolbar->AddTool(Menu_Tools_Kanji_Timer,_("Kanji Timer"),GETIMAGE(kara_timing_copier_24),_("Open Kanji Timer dialog")); - Toolbar->AddTool(Menu_Tools_SpellCheck,_("Spell Checker"),GETIMAGE(spellcheck_toolbutton_24),_("Open Spell checker")); - Toolbar->AddSeparator(); - - // Options - Toolbar->AddTool(Menu_Tools_Options,_("Options"),GETIMAGE(options_button_24),_("Configure Aegisub")); - Toolbar->AddTool(Grid_Toggle_Tags,_("Cycle Tag Hidding Mode"),GETIMAGE(toggle_tag_hiding_24),_("Cycle through tag-hiding modes")); - // Update Toolbar->Realize(); } -/// @brief DOCME -/// @param item_text -/// @param hotkey_name -/// @return -wxString MakeHotkeyText(const wxString &item_text, const wxString &hotkey_name) { - return item_text + wxString(_T("\t")) + Hotkeys.GetText(hotkey_name); - } - - /// @brief Initialize menu bar void FrameMain::InitMenu() { - // Deinit menu if needed - if (menuCreated) { - SetMenuBar(NULL); - MenuBar->Destroy(); - } - + #ifdef __WXMAC__ // Make sure special menu items are placed correctly on Mac wxApp::s_macAboutMenuItemId = Menu_Help_About; @@ -317,250 +286,14 @@ void FrameMain::InitMenu() { wxApp::s_macHelpMenuTitleName = _("&Help"); #endif - // Generate menubar - MenuBar = new wxMenuBar(); - - // Create recent subs submenus - RecentSubs = new wxMenu(); - RecentVids = new wxMenu(); - RecentAuds = new wxMenu(); - RecentTimecodes = new wxMenu(); - RecentKeyframes = new wxMenu(); - - // Create file menu - fileMenu = new wxMenu(); - AppendBitmapMenuItem(fileMenu,Menu_File_New_Subtitles, MakeHotkeyText(_("&New Subtitles"), _T("New Subtitles")), _("New subtitles"),GETIMAGE(new_toolbutton_16)); - AppendBitmapMenuItem(fileMenu,Menu_File_Open_Subtitles, MakeHotkeyText(_("&Open Subtitles..."), _T("Open Subtitles")), _("Opens a subtitles file"),GETIMAGE(open_toolbutton_16)); - AppendBitmapMenuItem(fileMenu,Menu_File_Open_Subtitles_Charset, _("&Open Subtitles with Charset..."), _("Opens a subtitles file with a specific charset"),GETIMAGE(open_with_toolbutton_16)); - fileMenu->Append(Menu_File_Open_Subtitles_From_Video, _("Open Subtitles from &Video"), _("Opens the subtitles from the current video file")); - AppendBitmapMenuItem(fileMenu,Menu_File_Save_Subtitles, MakeHotkeyText(_("&Save Subtitles"), _T("Save Subtitles")), _("Saves subtitles"),GETIMAGE(save_toolbutton_16)); - AppendBitmapMenuItem(fileMenu,Menu_File_Save_Subtitles_As, _("Save Subtitles as..."), _("Saves subtitles with another name"), GETIMAGE(save_as_toolbutton_16)); - AppendBitmapMenuItem(fileMenu,Menu_File_Export_Subtitles, _("Export Subtitles..."), _("Saves a copy of subtitles with processing applied to it."), GETIMAGE(export_menu_16)); - wxMenuItem *RecentParent = new wxMenuItem(fileMenu, Menu_File_Recent_Subs_Parent, _("Recent"), _T(""), wxITEM_NORMAL, RecentSubs); -#ifndef __APPLE__ - RecentParent->SetBitmap(GETIMAGE(blank_button_16)); -#endif - fileMenu->Append(RecentParent); - fileMenu->AppendSeparator(); - AppendBitmapMenuItem (fileMenu,Menu_Tools_Properties, _("&Properties..."), _("Open script properties window"),GETIMAGE(properties_toolbutton_16)); - AppendBitmapMenuItem (fileMenu,Menu_Tools_Attachments, _("&Attachments..."), _("Open the attachment list"), GETIMAGE(attach_button_16)); - AppendBitmapMenuItem (fileMenu,Menu_Tools_Fonts_Collector, _("&Fonts Collector..."),_("Open fonts collector"), GETIMAGE(font_collector_button_16)); - fileMenu->AppendSeparator(); -#ifndef __APPLE__ - // Doesn't work on Mac, only one instance is ever allowed there from OS side - AppendBitmapMenuItem(fileMenu,Menu_File_New_Window, _("New Window"), _("Open a new application window"),GETIMAGE(new_window_menu_16)); -#endif - AppendBitmapMenuItem(fileMenu,Menu_File_Exit, MakeHotkeyText(_("E&xit"), _T("Exit")), _("Exit the application"),GETIMAGE(exit_button_16)); - MenuBar->Append(fileMenu, _("&File")); - - // Create Edit menu - // NOTE: Undo and Redo are actually controlled in frame_main_events, OnMenuOpen(). They will always be the first two items. - editMenu = new wxMenu(); - AppendBitmapMenuItem(editMenu,Menu_Edit_Undo, MakeHotkeyText(_("&Undo"), _T("Undo")), _("Undoes last action"),GETIMAGE(undo_button_16)); - AppendBitmapMenuItem(editMenu,Menu_Edit_Redo, MakeHotkeyText(_("&Redo"), _T("Redo")), _("Redoes last action"),GETIMAGE(redo_button_16)); - editMenu->AppendSeparator(); - AppendBitmapMenuItem(editMenu,Menu_Edit_Cut, MakeHotkeyText(_("Cut Lines"), _T("Cut")), _("Cut subtitles"), GETIMAGE(cut_button_16)); - AppendBitmapMenuItem(editMenu,Menu_Edit_Copy, MakeHotkeyText(_("Copy Lines"), _T("Copy")), _("Copy subtitles"), GETIMAGE(copy_button_16)); - AppendBitmapMenuItem(editMenu,Menu_Edit_Paste, MakeHotkeyText(_("Paste Lines"), _T("Paste")), _("Paste subtitles"), GETIMAGE(paste_button_16)); - AppendBitmapMenuItem(editMenu,Menu_Edit_Paste_Over, MakeHotkeyText(_("Paste Lines Over..."), _T("Paste Over")) , _("Paste subtitles over others"),GETIMAGE(paste_over_button_16)); - editMenu->AppendSeparator(); - AppendBitmapMenuItem(editMenu,Menu_Edit_Find, MakeHotkeyText(_("&Find..."), _T("Find")), _("Find words in subtitles"),GETIMAGE(find_button_16)); - AppendBitmapMenuItem(editMenu,Menu_Edit_Find_Next, MakeHotkeyText(_("Find Next"), _T("Find Next")), _("Find next match of last word"),GETIMAGE(find_next_menu_16)); - AppendBitmapMenuItem(editMenu,Menu_Edit_Replace, MakeHotkeyText(_("Search and &Replace..."), _T("Replace")) , _("Find and replace words in subtitles"),GETIMAGE(find_replace_menu_16)); - MenuBar->Append(editMenu, _("&Edit")); - - // Create subtitles menu - subtitlesMenu = new wxMenu(); - wxMenu *InsertMenu = new wxMenu; - wxMenuItem *InsertParent = new wxMenuItem(subtitlesMenu,Menu_Subtitles_Insert,_("&Insert Lines"),_T(""),wxITEM_NORMAL,InsertMenu); -#ifndef __APPLE__ - InsertParent->SetBitmap(GETIMAGE(blank_button_16)); -#endif - AppendBitmapMenuItem (subtitlesMenu,Menu_Tools_Styles_Manager, _("&Styles Manager..."), _("Open styles manager"), GETIMAGE(style_toolbutton_16)); - AppendBitmapMenuItem (subtitlesMenu,Menu_Tools_Styling, _("St&yling Assistant..."), _("Open styling assistant"), GETIMAGE(styling_toolbutton_16)); - AppendBitmapMenuItem (subtitlesMenu,Menu_Tools_Translation, _("&Translation Assistant..."),_("Open translation assistant"), GETIMAGE(translation_toolbutton_16)); - AppendBitmapMenuItem (subtitlesMenu,Menu_Tools_Resample,_("Resample Resolution..."), _("Changes resolution and modifies subtitles to conform to change"), GETIMAGE(resample_toolbutton_16)); - AppendBitmapMenuItem (subtitlesMenu,Menu_Tools_SpellCheck, _("Spe&ll Checker..."),_("Open spell checker"), GETIMAGE(spellcheck_toolbutton_16)); - if (HasASSDraw()) { - subtitlesMenu->AppendSeparator(); - AppendBitmapMenuItem (subtitlesMenu,Menu_Tools_ASSDraw,_T("ASSDraw3..."),_("Launches ai-chan's \"ASSDraw3\" tool for vector drawing."), GETIMAGE(assdraw_16)); - } - subtitlesMenu->AppendSeparator(); - AppendBitmapMenuItem(InsertMenu,MENU_INSERT_BEFORE,_("&Before Current"),_("Inserts a line before current"),GETIMAGE(blank_button_16)); - AppendBitmapMenuItem(InsertMenu,MENU_INSERT_AFTER,_("&After Current"),_("Inserts a line after current"),GETIMAGE(blank_button_16)); - AppendBitmapMenuItem(InsertMenu,MENU_INSERT_BEFORE_VIDEO,_("Before Current, at Video Time"),_("Inserts a line before current, starting at video time"),GETIMAGE(blank_button_16)); - AppendBitmapMenuItem(InsertMenu,MENU_INSERT_AFTER_VIDEO,_("After Current, at Video Time"),_("Inserts a line after current, starting at video time"),GETIMAGE(blank_button_16)); - subtitlesMenu->Append(InsertParent); - AppendBitmapMenuItem(subtitlesMenu,MENU_DUPLICATE,MakeHotkeyText(_("&Duplicate Lines"), _T("Grid duplicate rows")),_("Duplicate the selected lines"),GETIMAGE(blank_button_16)); - AppendBitmapMenuItem(subtitlesMenu,MENU_DUPLICATE_NEXT_FRAME,MakeHotkeyText(_("&Duplicate and Shift by 1 Frame"), _T("Grid duplicate and shift one frame")),_("Duplicate lines and shift by one frame"),GETIMAGE(blank_button_16)); - AppendBitmapMenuItem(subtitlesMenu,MENU_DELETE,MakeHotkeyText(_("Delete Lines"), _T("Grid delete rows")),_("Delete currently selected lines"),GETIMAGE(delete_button_16)); - subtitlesMenu->AppendSeparator(); - wxMenu *JoinMenu = new wxMenu; - wxMenuItem *JoinParent = new wxMenuItem(subtitlesMenu,Menu_Subtitles_Join,_("Join Lines"),_T(""),wxITEM_NORMAL,JoinMenu); -#ifndef __APPLE__ - JoinParent->SetBitmap(GETIMAGE(blank_button_16)); -#endif - AppendBitmapMenuItem(JoinMenu,MENU_JOIN_CONCAT,_("&Concatenate"),_("Joins selected lines in a single one, concatenating text together"),GETIMAGE(blank_button_16)); - AppendBitmapMenuItem(JoinMenu,MENU_JOIN_REPLACE,_("Keep &First"),_("Joins selected lines in a single one, keeping text of first and discarding remaining"),GETIMAGE(blank_button_16)); - AppendBitmapMenuItem(JoinMenu,MENU_JOIN_AS_KARAOKE,_("As &Karaoke"),_("Joins selected lines in a single one, as karaoke"),GETIMAGE(blank_button_16)); - subtitlesMenu->Append(JoinParent); - AppendBitmapMenuItem(subtitlesMenu,MENU_RECOMBINE,_("Recombine Lines"),_("Recombine subtitles when they have been split and merged"),GETIMAGE(blank_button_16)); - AppendBitmapMenuItem(subtitlesMenu,MENU_SPLIT_BY_KARAOKE,_("Split Lines (by karaoke)"),_("Uses karaoke timing to split line into multiple smaller lines"),GETIMAGE(blank_button_16)); - subtitlesMenu->AppendSeparator(); - wxMenu *SortMenu = new wxMenu; - wxMenuItem *SortParent = new wxMenuItem(subtitlesMenu,Menu_Subtitles_Sort_Start,_("Sort Lines"),_T(""),wxITEM_NORMAL,SortMenu); -#ifndef __APPLE__ - SortParent->SetBitmap(GETIMAGE(sort_times_button_16)); -#endif - AppendBitmapMenuItem(SortMenu,Menu_Subtitles_Sort_Start,_("&Start Time"),_("Sort all subtitles by their start times"),GETIMAGE(blank_button_16)); - AppendBitmapMenuItem(SortMenu,Menu_Subtitles_Sort_End,_("&End Time"),_("Sort all subtitles by their end times"),GETIMAGE(blank_button_16)); - AppendBitmapMenuItem(SortMenu,Menu_Subtitles_Sort_Style,_("St&yle Name"),_("Sort all subtitles by their style names"),GETIMAGE(blank_button_16)); - subtitlesMenu->Append(SortParent); - AppendBitmapMenuItem(subtitlesMenu,MENU_SWAP,_("Swap Lines"),_("Swaps the two selected lines"),GETIMAGE(arrow_sort_16)); - AppendBitmapMenuItem (subtitlesMenu,Menu_Edit_Select, MakeHotkeyText(_("Select Lines..."), _T("Select lines")), _("Selects lines based on defined criterea"),GETIMAGE(select_lines_button_16)); - MenuBar->Append(subtitlesMenu, _("&Subtitles")); - - // Create timing menu - timingMenu = new wxMenu(); - AppendBitmapMenuItem(timingMenu,Menu_Edit_Shift, MakeHotkeyText(_("S&hift Times..."), _T("Shift times")), _("Shift subtitles by time or frames"),GETIMAGE(shift_times_toolbutton_16)); - AppendBitmapMenuItem(timingMenu,Menu_Tools_Timing_Processor,_("Timing Post-Processor..."), _("Runs a post-processor for timing to deal with lead-ins, lead-outs, scene timing and etc."), GETIMAGE(timing_processor_toolbutton_16)); - AppendBitmapMenuItem (timingMenu,Menu_Tools_Kanji_Timer,_("Kanji Timer..."),_("Open Kanji timer"),GETIMAGE(kara_timing_copier_16)); - timingMenu->AppendSeparator(); - AppendBitmapMenuItem(timingMenu,Menu_Subs_Snap_Start_To_Video, MakeHotkeyText(_("Snap Start to Video"), _T("Set Start To Video")), _("Set start of selected subtitles to current video frame"), GETIMAGE(substart_to_video_16)); - AppendBitmapMenuItem(timingMenu,Menu_Subs_Snap_End_To_Video, MakeHotkeyText(_("Snap End to Video"), _T("Set End to Video")), _("Set end of selected subtitles to current video frame"), GETIMAGE(subend_to_video_16)); - AppendBitmapMenuItem(timingMenu,Menu_Video_Snap_To_Scene, MakeHotkeyText(_("Snap to Scene"), _T("Snap to Scene")), _("Set start and end of subtitles to the keyframes around current video frame"), GETIMAGE(snap_subs_to_scene_16)); - AppendBitmapMenuItem(timingMenu,Menu_Video_Shift_To_Frame, MakeHotkeyText(_("Shift to Current Frame"), _T("Shift by Current Time")), _("Shift selection so first selected line starts at current frame"), GETIMAGE(shift_to_frame_16)); - timingMenu->AppendSeparator(); - wxMenu *ContinuousMenu = new wxMenu; - wxMenuItem *ContinuousParent = new wxMenuItem(subtitlesMenu,-1,_("Make Times Continuous"),_T(""),wxITEM_NORMAL,ContinuousMenu); -#ifndef __APPLE__ - ContinuousParent->SetBitmap(GETIMAGE(blank_button_16)); -#endif - AppendBitmapMenuItem(ContinuousMenu,MENU_ADJOIN,_("Change &Start"),_("Changes times of subs so start times begin on previous's end time"),GETIMAGE(blank_button_16)); - AppendBitmapMenuItem(ContinuousMenu,MENU_ADJOIN2,_("Change &End"),_("Changes times of subs so end times begin on next's start time"),GETIMAGE(blank_button_16)); - timingMenu->Append(ContinuousParent); - MenuBar->Append(timingMenu, _("&Timing")); - - // Create video menu - videoMenu = new wxMenu(); - AppendBitmapMenuItem(videoMenu, Menu_File_Open_Video, _("&Open Video..."), _("Opens a video file"), GETIMAGE(open_video_menu_16)); - AppendBitmapMenuItem(videoMenu, Menu_File_Close_Video, _("&Close Video"), _("Closes the currently open video file"), GETIMAGE(close_video_menu_16)); - wxMenuItem *RecentVidParent = new wxMenuItem(videoMenu, Menu_File_Recent_Vids_Parent, _("Recent"), _T(""), wxITEM_NORMAL, RecentVids); - videoMenu->Append(RecentVidParent); - AppendBitmapMenuItem(videoMenu, Menu_Video_Dummy, _("Use Dummy Video..."), _("Opens a video clip with solid colour"), GETIMAGE(use_dummy_video_menu_16)); - AppendBitmapMenuItem(videoMenu, Menu_Video_Details, _("Show Video Details..."), _("Shows video details"), GETIMAGE(show_video_details_menu_16)); - videoMenu->AppendSeparator(); - AppendBitmapMenuItem(videoMenu, Menu_File_Open_VFR, _("Open Timecodes File..."), _("Opens a VFR timecodes v1 or v2 file"), GETIMAGE(open_timecodes_menu_16)); - AppendBitmapMenuItem(videoMenu, Menu_File_Save_VFR, _("Save Timecodes File..."), _("Saves a VFR timecodes v2 file"), GETIMAGE(save_timecodes_menu_16)); - AppendBitmapMenuItem(videoMenu, Menu_File_Close_VFR, _("Close Timecodes File"), _("Closes the currently open timecodes file"), GETIMAGE(close_timecodes_menu_16))->Enable(false); - wxMenuItem *RecentTimesParent = new wxMenuItem(videoMenu, Menu_File_Recent_Timecodes_Parent, _("Recent"), _T(""), wxITEM_NORMAL, RecentTimecodes); - videoMenu->Append(RecentTimesParent); - videoMenu->AppendSeparator(); - AppendBitmapMenuItem(videoMenu, Menu_Video_Load_Keyframes, _("Open Keyframes..."), _("Opens a keyframe list file"), GETIMAGE(open_keyframes_menu_16)); - AppendBitmapMenuItem(videoMenu, Menu_Video_Save_Keyframes, _("Save Keyframes..."), _("Saves the current keyframe list"), GETIMAGE(save_keyframes_menu_16))->Enable(false); - AppendBitmapMenuItem(videoMenu, Menu_Video_Close_Keyframes, _("Close Keyframes"), _("Closes the currently open keyframes list"), GETIMAGE(close_keyframes_menu_16))->Enable(false); - wxMenuItem *RecentKeyframesParent = new wxMenuItem(videoMenu, Menu_File_Recent_Keyframes_Parent, _("Recent"), _T(""), wxITEM_NORMAL, RecentKeyframes); - videoMenu->Append(RecentKeyframesParent); - videoMenu->AppendSeparator(); - AppendBitmapMenuItem(videoMenu, Menu_Video_Detach, _("Detach Video"), _("Detach video, displaying it in a separate Window."), GETIMAGE(detach_video_menu_16)); - wxMenu *ZoomMenu = new wxMenu; - wxMenuItem *ZoomParent = new wxMenuItem(subtitlesMenu,Menu_View_Zoom,_("Set Zoom"),_T(""),wxITEM_NORMAL,ZoomMenu); -#ifndef __APPLE__ - ZoomParent->SetBitmap(GETIMAGE(set_zoom_menu_16)); -#endif - ZoomMenu->Append(Menu_View_Zoom_50, MakeHotkeyText(_T("&50%"), _T("Zoom 50%")), _("Set zoom to 50%")); - ZoomMenu->Append(Menu_View_Zoom_100, MakeHotkeyText(_T("&100%"), _T("Zoom 100%")), _("Set zoom to 100%")); - ZoomMenu->Append(Menu_View_Zoom_200, MakeHotkeyText(_T("&200%"), _T("Zoom 200%")), _("Set zoom to 200%")); - videoMenu->Append(ZoomParent); - wxMenu *AspectMenu = new wxMenu; - wxMenuItem *AspectParent = new wxMenuItem(subtitlesMenu,Menu_Video_AR,_("Override Aspect Ratio"),_T(""),wxITEM_NORMAL,AspectMenu); -#ifndef __APPLE__ - AspectParent->SetBitmap(GETIMAGE(override_aspect_menu_16)); -#endif - AspectMenu->AppendCheckItem(Menu_Video_AR_Default, _("&Default"), _("Leave video on original aspect ratio")); - AspectMenu->AppendCheckItem(Menu_Video_AR_Full, _("&Fullscreen (4:3)"), _("Forces video to 4:3 aspect ratio")); - AspectMenu->AppendCheckItem(Menu_Video_AR_Wide, _("&Widescreen (16:9)"), _("Forces video to 16:9 aspect ratio")); - AspectMenu->AppendCheckItem(Menu_Video_AR_235, _("&Cinematic (2.35)"), _("Forces video to 2.35 aspect ratio")); - AspectMenu->AppendCheckItem(Menu_Video_AR_Custom, _("Custom..."), _("Forces video to a custom aspect ratio")); - videoMenu->Append(AspectParent); - videoMenu->AppendCheckItem(Menu_Video_Overscan, _("Show Overscan Mask"), _("Show a mask over the video, indicating areas that might get cropped off by overscan on televisions.")); -// This is broken as you can't use Check() on a menu item that has a bitmap. -// AppendBitmapMenuItem(videoMenu, Menu_Video_Overscan, _("Show Overscan Mask"), _("Show a mask over the video, indicating areas that might get cropped off by overscan on televisions."), GETIMAGE(show_overscan_menu_checked_16)); - videoMenu->AppendSeparator(); - AppendBitmapMenuItem(videoMenu,Menu_Video_JumpTo, MakeHotkeyText(_("&Jump to..."), _T("Video Jump")), _("Jump to frame or time"), GETIMAGE(jumpto_button_16)); - AppendBitmapMenuItem(videoMenu,Menu_Subs_Snap_Video_To_Start, MakeHotkeyText(_("Jump Video to Start"), _T("Jump Video To Start")), _("Jumps the video to the start frame of current subtitle"), GETIMAGE(video_to_substart_16)); - AppendBitmapMenuItem(videoMenu,Menu_Subs_Snap_Video_To_End, MakeHotkeyText(_("Jump Video to End"), _T("Jump Video To End")), _("Jumps the video to the end frame of current subtitle"), GETIMAGE(video_to_subend_16)); - MenuBar->Append(videoMenu, _("&Video")); - - // Create audio menu - audioMenu = new wxMenu(); - AppendBitmapMenuItem(audioMenu, Menu_Audio_Open_File, _("&Open Audio File..."), _("Opens an audio file"), GETIMAGE(open_audio_menu_16)); - AppendBitmapMenuItem(audioMenu, Menu_Audio_Open_From_Video, _("Open Audio from &Video"), _("Opens the audio from the current video file"), GETIMAGE(open_audio_from_video_menu_16)); - AppendBitmapMenuItem(audioMenu, Menu_Audio_Close, _("&Close Audio"), _("Closes the currently open audio file"), GETIMAGE(close_audio_menu_16)); - wxMenuItem *RecentAudParent = new wxMenuItem(audioMenu, Menu_File_Recent_Auds_Parent, _("Recent"), _T(""), wxITEM_NORMAL, RecentAuds); - audioMenu->Append(RecentAudParent); - audioMenu->AppendSeparator(); - audioMenu->Append(Menu_Audio_Spectrum, _("Spectrum display"), _("Display audio as a frequency-power spectrogrph"), wxITEM_RADIO); - audioMenu->Append(Menu_Audio_Waveform, _("Waveform display"), _("Display audio as a linear amplitude graph"), wxITEM_RADIO); -#ifdef _DEBUG - audioMenu->AppendSeparator(); - audioMenu->Append(Menu_Audio_Open_Dummy, _T("Open 2h30 Blank Audio"), _T("Open a 150 minutes blank audio clip, for debugging")); - audioMenu->Append(Menu_Audio_Open_Dummy_Noise, _T("Open 2h30 Noise Audio"), _T("Open a 150 minutes noise-filled audio clip, for debugging")); -#endif - MenuBar->Append(audioMenu, _("&Audio")); - - // Create Automation menu -#ifdef WITH_AUTOMATION - automationMenu = new wxMenu(); - AppendBitmapMenuItem (automationMenu,Menu_Tools_Automation, _("&Automation..."),_("Open automation manager"), GETIMAGE(automation_toolbutton_16)); - automationMenu->AppendSeparator(); - MenuBar->Append(automationMenu, _("&Automation")); -#endif - - // Create view menu - viewMenu = new wxMenu(); - AppendBitmapMenuItem(viewMenu,Menu_View_Language, _T("&Language..."), _("Select Aegisub interface language"), GETIMAGE(languages_menu_16)); - AppendBitmapMenuItem(viewMenu,Menu_Tools_Options, MakeHotkeyText(_("&Options..."), _T("Options")), _("Configure Aegisub"), GETIMAGE(options_button_16)); - viewMenu->AppendSeparator(); - viewMenu->AppendRadioItem(Menu_View_Subs, _("Subs Only View"), _("Display subtitles only")); - viewMenu->AppendRadioItem(Menu_View_Video, _("Video+Subs View"), _("Display video and subtitles only")); - viewMenu->AppendRadioItem(Menu_View_Audio, _("Audio+Subs View"), _("Display audio and subtitles only")); - viewMenu->AppendRadioItem(Menu_View_Standard, _("Full view"), _("Display audio, video and subtitles")); - viewMenu->AppendSeparator(); - viewMenu->AppendRadioItem(Menu_View_FullTags, _("Show Tags"), _("Show full override tags in the subtitle grid")); - viewMenu->AppendRadioItem(Menu_View_ShortTags, _("Simplify Tags"), _("Replace override tags in the subtitle grid with a simplified placeholder")); - viewMenu->AppendRadioItem(Menu_View_NoTags, _("Hide Tags"), _("Hide override tags in the subtitle grid")); - MenuBar->Append(viewMenu, _("Vie&w")); - - // Create help menu - helpMenu = new wxMenu(); - AppendBitmapMenuItem (helpMenu,Menu_Help_Contents, MakeHotkeyText(_("&Contents..."), _T("Help")), _("Help topics"), GETIMAGE(contents_button_16)); -#ifdef __WXMAC__ - AppendBitmapMenuItem (helpMenu,Menu_Help_Files, MakeHotkeyText(_("&All Files") + _T("..."), _T("Help")), _("Help topics"), GETIMAGE(contents_button_16)); -#endif - helpMenu->AppendSeparator(); - AppendBitmapMenuItem(helpMenu,Menu_Help_Website, _("&Website..."), _("Visit Aegisub's official website"),GETIMAGE(website_button_16)); - AppendBitmapMenuItem(helpMenu,Menu_Help_Forums, _("&Forums..."), _("Visit Aegisub's forums"),GETIMAGE(forums_button_16)); - AppendBitmapMenuItem(helpMenu,Menu_Help_BugTracker, _("&Bug Tracker..."), _("Visit Aegisub's bug tracker to report bugs and request new features"),GETIMAGE(bugtracker_button_16)); - AppendBitmapMenuItem (helpMenu,Menu_Help_IRCChannel, _("&IRC Channel..."), _("Visit Aegisub's official IRC channel"), GETIMAGE(irc_button_16)); -#ifndef __WXMAC__ - helpMenu->AppendSeparator(); -#endif - AppendBitmapMenuItem(helpMenu,Menu_Help_Check_Updates, _("&Check for Updates..."), _("Check to see if there is a new version of Aegisub available"),GETIMAGE(blank_button_16)); - AppendBitmapMenuItem(helpMenu,Menu_Help_About, _("&About..."), _("About Aegisub"),GETIMAGE(about_menu_16)); - AppendBitmapMenuItem(helpMenu,Menu_Help_Log, _("&Log window..."), _("Aegisub event log"),GETIMAGE(about_menu_16)); - MenuBar->Append(helpMenu, _("&Help")); - - // Set the bar as this frame's - SetMenuBar(MenuBar); - - // Set menu created flag - menuCreated = true; + SetMenuBar(menu::menu->GetMainMenu()); } + /// @brief Initialize contents void FrameMain::InitContents() { AssFile::top = ass = new AssFile; + temp_context.ass = ass; ass->AddCommitListener(&FrameMain::OnSubtitlesFileChanged, this); // Set a background panel @@ -570,6 +303,7 @@ void FrameMain::InitContents() { // Video area; StartupLog(_T("Create video box")); videoBox = new VideoBox(Panel, false, ZoomBox, ass); + temp_context.videoBox = videoBox; VideoContext::Get()->audio = audioController; wxBoxSizer *videoSizer = new wxBoxSizer(wxVERTICAL); videoSizer->Add(videoBox, 0, wxEXPAND); @@ -578,19 +312,21 @@ void FrameMain::InitContents() { // Subtitles area StartupLog(_T("Create subtitles grid")); SubsGrid = new SubtitlesGrid(this,Panel,-1,ass,wxDefaultPosition,wxSize(600,100),wxWANTS_CHARS | wxSUNKEN_BORDER,_T("Subs grid")); + temp_context.SubsGrid = SubsGrid; videoBox->videoSlider->grid = SubsGrid; VideoContext::Get()->grid = SubsGrid; Search.grid = SubsGrid; // Tools area StartupLog(_T("Create tool area splitter window")); - audioSash = new wxSashWindow(Panel, Main_AudioSash, wxDefaultPosition, wxDefaultSize, wxSW_3D|wxCLIP_CHILDREN); + audioSash = new wxSashWindow(Panel, ID_SASH_MAIN_AUDIO, wxDefaultPosition, wxDefaultSize, wxSW_3D|wxCLIP_CHILDREN); wxBoxSizer *audioSashSizer = new wxBoxSizer(wxHORIZONTAL); audioSash->SetSashVisible(wxSASH_BOTTOM, true); // Audio area StartupLog(_T("Create audio box")); audioBox = new AudioBox(audioSash, audioController, SubsGrid, ass); + temp_context.audioBox = audioBox; audioBox->frameMain = this; audioSashSizer->Add(audioBox, 1, wxEXPAND); audioSash->SetSizer(audioSashSizer); @@ -600,6 +336,7 @@ void FrameMain::InitContents() { // Editing area StartupLog(_T("Create subtitle editing box")); EditBox = new SubsEditBox(Panel,SubsGrid); + temp_context.EditBox = EditBox; // Set sizers/hints StartupLog(_T("Arrange main sizers")); @@ -647,17 +384,20 @@ void FrameMain::UpdateToolbar() { // Update wxToolBar* toolbar = GetToolBar(); - toolbar->FindById(Menu_Video_JumpTo)->Enable(isVideo); - toolbar->FindById(Menu_Video_Zoom_In)->Enable(isVideo && !detachedVideo); - toolbar->FindById(Menu_Video_Zoom_Out)->Enable(isVideo && !detachedVideo); + toolbar->FindById(cmd::id("video/jump"))->Enable(isVideo); + toolbar->FindById(cmd::id("video/zoom/in"))->Enable(isVideo && !detachedVideo); + toolbar->FindById(cmd::id("video/zoom/out"))->Enable(isVideo && !detachedVideo); ZoomBox->Enable(isVideo && !detachedVideo); - toolbar->FindById(Menu_Subs_Snap_Start_To_Video)->Enable(isVideo && selRows > 0); - toolbar->FindById(Menu_Subs_Snap_End_To_Video)->Enable(isVideo && selRows > 0); - toolbar->FindById(Menu_Subs_Snap_Video_To_Start)->Enable(isVideo && selRows == 1); - toolbar->FindById(Menu_Subs_Snap_Video_To_End)->Enable(isVideo && selRows == 1); - toolbar->FindById(Menu_Video_Select_Visible)->Enable(isVideo); - toolbar->FindById(Menu_Video_Snap_To_Scene)->Enable(isVideo && selRows > 0); - toolbar->FindById(Menu_Video_Shift_To_Frame)->Enable(isVideo && selRows > 0); + + toolbar->FindById(cmd::id("video/jump/start"))->Enable(isVideo && selRows > 0); + toolbar->FindById(cmd::id("video/jump/end"))->Enable(isVideo && selRows > 0); + + toolbar->FindById(cmd::id("time/snap/start_video"))->Enable(isVideo && selRows == 1); + toolbar->FindById(cmd::id("time/snap/end_video"))->Enable(isVideo && selRows == 1); + + toolbar->FindById(cmd::id("subtitle/select/visible"))->Enable(isVideo); + toolbar->FindById(cmd::id("time/snap/scene"))->Enable(isVideo && selRows > 0); + toolbar->FindById(cmd::id("time/snap/frame"))->Enable(isVideo && selRows > 0); toolbar->Realize(); } @@ -1160,6 +900,7 @@ void FrameMain::DetachVideo(bool detach) { if (detach) { if (!detachedVideo) { detachedVideo = new DialogDetachedVideo(this, videoBox->videoDisplay->GetClientSize()); + temp_context.detachedVideo = detachedVideo; detachedVideo->Show(); } } @@ -1176,46 +917,10 @@ void FrameMain::DetachVideo(bool detach) { /// @param ms void FrameMain::StatusTimeout(wxString text,int ms) { SetStatusText(text,1); - StatusClear.SetOwner(this,StatusClear_Timer); + StatusClear.SetOwner(this, ID_APP_TIMER_STATUSCLEAR); StatusClear.Start(ms,true); } -/// @brief Setup accelerator table -void FrameMain::SetAccelerators() { - std::vector entry; - entry.reserve(32); - - // Standard - entry.push_back(Hotkeys.GetAccelerator(_T("Video global prev frame"),Video_Prev_Frame)); - entry.push_back(Hotkeys.GetAccelerator(_T("Video global next frame"),Video_Next_Frame)); - entry.push_back(Hotkeys.GetAccelerator(_T("Video global focus seek"),Video_Focus_Seek)); - entry.push_back(Hotkeys.GetAccelerator(_T("Grid global prev line"),Grid_Prev_Line)); - entry.push_back(Hotkeys.GetAccelerator(_T("Grid global next line"),Grid_Next_Line)); - entry.push_back(Hotkeys.GetAccelerator(_T("Save Subtitles Alt"),Menu_File_Save_Subtitles)); - entry.push_back(Hotkeys.GetAccelerator(_T("Video global zoom in"),Menu_Video_Zoom_In)); - entry.push_back(Hotkeys.GetAccelerator(_T("Video global zoom out"),Menu_Video_Zoom_Out)); - entry.push_back(Hotkeys.GetAccelerator(_T("Video global play"),Video_Frame_Play)); - - // Medusa - bool medusaPlay = OPT_GET("Audio/Medusa Timing Hotkeys")->GetBool(); - if (medusaPlay && audioController->IsAudioOpen()) { - entry.push_back(Hotkeys.GetAccelerator(_T("Audio Medusa Play"),Medusa_Play)); - entry.push_back(Hotkeys.GetAccelerator(_T("Audio Medusa Stop"),Medusa_Stop)); - entry.push_back(Hotkeys.GetAccelerator(_T("Audio Medusa Play Before"),Medusa_Play_Before)); - entry.push_back(Hotkeys.GetAccelerator(_T("Audio Medusa Play After"),Medusa_Play_After)); - entry.push_back(Hotkeys.GetAccelerator(_T("Audio Medusa Next"),Medusa_Next)); - entry.push_back(Hotkeys.GetAccelerator(_T("Audio Medusa Previous"),Medusa_Prev)); - entry.push_back(Hotkeys.GetAccelerator(_T("Audio Medusa Shift Start Forward"),Medusa_Shift_Start_Forward)); - entry.push_back(Hotkeys.GetAccelerator(_T("Audio Medusa Shift Start Back"),Medusa_Shift_Start_Back)); - entry.push_back(Hotkeys.GetAccelerator(_T("Audio Medusa Shift End Forward"),Medusa_Shift_End_Forward)); - entry.push_back(Hotkeys.GetAccelerator(_T("Audio Medusa Shift End Back"),Medusa_Shift_End_Back)); - entry.push_back(Hotkeys.GetAccelerator(_T("Audio Medusa Enter"),Medusa_Enter)); - } - - // Set table - wxAcceleratorTable table(entry.size(),&entry[0]); - SetAcceleratorTable(table); -} /// @brief Load list of files /// @param list @@ -1304,6 +1009,7 @@ bool FrameMain::LoadList(wxArrayString list) { /// @brief Sets the descriptions for undo/redo void FrameMain::SetUndoRedoDesc() { + wxMenu *editMenu = menu::menu->GetMenu("main/edit"); editMenu->SetHelpString(0,_T("Undo ")+ass->GetUndoDescription()); editMenu->SetHelpString(1,_T("Redo ")+ass->GetRedoDescription()); } @@ -1327,3 +1033,433 @@ static void autosave_timer_changed(wxTimer *timer, const agi::OptionValue &opt) timer->Start(freq * 1000); } } +BEGIN_EVENT_TABLE(FrameMain, wxFrame) + EVT_TIMER(ID_APP_TIMER_AUTOSAVE, FrameMain::OnAutoSave) + EVT_TIMER(ID_APP_TIMER_STATUSCLEAR, FrameMain::OnStatusClear) + + EVT_CLOSE(FrameMain::OnCloseWindow) + + EVT_SASH_DRAGGED(ID_SASH_MAIN_AUDIO, FrameMain::OnAudioBoxResize) + + EVT_MENU_OPEN(FrameMain::OnMenuOpen) + EVT_KEY_DOWN(FrameMain::OnKeyDown) +// EVT_MENU(cmd::id("subtitle/new"), FrameMain::cmd_call) +// EVT_MENU(cmd::id("subtitle/open"), FrameMain::cmd_call) +// EVT_MENU(cmd::id("subtitle/save"), FrameMain::cmd_call) + +// EVT_MENU_RANGE(MENU_GRID_START+1,MENU_GRID_END-1,FrameMain::OnGridEvent) +// EVT_COMBOBOX(Toolbar_Zoom_Dropdown, FrameMain::OnSetZoom) +// EVT_TEXT_ENTER(Toolbar_Zoom_Dropdown, FrameMain::OnSetZoom) + +#ifdef __WXMAC__ + EVT_MENU(wxID_ABOUT, FrameMain::OnAbout) + EVT_MENU(wxID_EXIT, FrameMain::OnExit) +#endif +END_EVENT_TABLE() + + +/// @brief Redirect grid events to grid +/// @param event +void FrameMain::OnGridEvent (wxCommandEvent &event) { + SubsGrid->GetEventHandler()->ProcessEvent(event); +} + +/// @brief Rebuild recent list +/// @param listName +/// @param menu +/// @param startID +void FrameMain::RebuildRecentList(wxString listName,wxMenu *menu,int startID) { + // Wipe previous list + int count = (int)menu->GetMenuItemCount(); + for (int i=count;--i>=0;) { + menu->Destroy(menu->FindItemByPosition(i)); + } + + // Rebuild + int added = 0; + wxString n; + wxArrayString entries = lagi_MRU_wxAS(listName); + for (size_t i=0;iAppend(startID+i,n + _T(" ") + filename); + added++; + } + + // Nothing added, add an empty placeholder + if (added == 0) menu->Append(startID,_("Empty"))->Enable(false); +} + +/// @brief Menu is being opened +/// @param event +void FrameMain::OnMenuOpen (wxMenuEvent &event) { + // Get menu + wxMenuBar *MenuBar = menu::menu->GetMainMenu(); + + MenuBar->Freeze(); + wxMenu *curMenu = event.GetMenu(); + + // File menu + if (curMenu == menu::menu->GetMenu("main/file")) { + // Rebuild recent + RebuildRecentList(_T("Subtitle"),menu::menu->GetMenu("recent/subtitle"), cmd::id("recent/subtitle")); + + MenuBar->Enable(cmd::id("subtitle/open/video"),VideoContext::Get()->HasSubtitles()); + } + + // View menu + else if (curMenu == menu::menu->GetMenu("main/view")) { + // Flags + bool aud = audioController->IsAudioOpen(); + bool vid = VideoContext::Get()->IsLoaded() && !detachedVideo; + + // Set states + MenuBar->Enable(cmd::id("app/display/audio_subs"),aud); + MenuBar->Enable(cmd::id("app/display/video_subs"),vid); + MenuBar->Enable(cmd::id("app/display/full"),aud && vid); + + // Select option + if (!showVideo && !showAudio) MenuBar->Check(cmd::id("app/display/subs"),true); + else if (showVideo && !showAudio) MenuBar->Check(cmd::id("app/display/video_subs"),true); + else if (showAudio && showVideo) MenuBar->Check(cmd::id("app/display/full"),true); + else MenuBar->Check(cmd::id("app/display/audio_subs"),true); + + int sub_grid = OPT_GET("Subtitle/Grid/Hide Overrides")->GetInt(); + if (sub_grid == 1) MenuBar->Check(cmd::id("grid/tags/show"), true); + if (sub_grid == 2) MenuBar->Check(cmd::id("grid/tags/simplify"), true); + if (sub_grid == 3) MenuBar->Check(cmd::id("grid/tags/hide"), true); + + + } + + // Video menu + else if (curMenu == menu::menu->GetMenu("main/video")) { + bool state = VideoContext::Get()->IsLoaded(); + bool attached = state && !detachedVideo; + + // Set states + MenuBar->Enable(cmd::id("video/jump"),state); + MenuBar->Enable(cmd::id("video/jump/start"),state); + MenuBar->Enable(cmd::id("video/jump/end"),state); + MenuBar->Enable(cmd::id("main/video/set zoom"), attached); + MenuBar->Enable(cmd::id("video/zoom/50"),attached); + MenuBar->Enable(cmd::id("video/zoom/100"),attached); + MenuBar->Enable(cmd::id("video/zoom/200"),attached); + MenuBar->Enable(cmd::id("video/close"),state); + MenuBar->Enable(cmd::id("main/video/override ar"),attached); + MenuBar->Enable(cmd::id("video/aspect/default"),attached); + MenuBar->Enable(cmd::id("video/aspect/full"),attached); + MenuBar->Enable(cmd::id("video/aspect/wide"),attached); + MenuBar->Enable(cmd::id("video/aspect/cinematic"),attached); + MenuBar->Enable(cmd::id("video/aspect/custom"),attached); + MenuBar->Enable(cmd::id("video/detach"),state); + MenuBar->Enable(cmd::id("timecode/save"),VideoContext::Get()->TimecodesLoaded()); + MenuBar->Enable(cmd::id("timecode/close"),VideoContext::Get()->OverTimecodesLoaded()); + MenuBar->Enable(cmd::id("keyframe/close"),VideoContext::Get()->OverKeyFramesLoaded()); + MenuBar->Enable(cmd::id("keyframe/save"),VideoContext::Get()->KeyFramesLoaded()); + MenuBar->Enable(cmd::id("video/detach"),state); + MenuBar->Enable(cmd::id("video/show_overscan"),state); + + // Set AR radio + int arType = VideoContext::Get()->GetAspectRatioType(); + MenuBar->Check(cmd::id("video/aspect/default"),false); + MenuBar->Check(cmd::id("video/aspect/full"),false); + MenuBar->Check(cmd::id("video/aspect/wide"),false); + MenuBar->Check(cmd::id("video/aspect/cinematic"),false); + MenuBar->Check(cmd::id("video/aspect/custom"),false); + switch (arType) { + case 0: MenuBar->Check(cmd::id("video/aspect/default"),true); break; + case 1: MenuBar->Check(cmd::id("video/aspect/full"),true); break; + case 2: MenuBar->Check(cmd::id("video/aspect/wide"),true); break; + case 3: MenuBar->Check(cmd::id("video/aspect/cinematic"),true); break; + case 4: MenuBar->Check(cmd::id("video/aspect/custom"),true); break; + } + + // Set overscan mask + MenuBar->Check(cmd::id("video/show_overscan"),OPT_GET("Video/Overscan Mask")->GetBool()); + + // Rebuild recent lists + RebuildRecentList(_T("Video"),menu::menu->GetMenu("recent/video"), cmd::id("recent/video")); + RebuildRecentList(_T("Timecodes"),menu::menu->GetMenu("recent/timecode"), cmd::id("recent/timecode")); + RebuildRecentList(_T("Keyframes"),menu::menu->GetMenu("recent/keyframe"), cmd::id("recent/keyframe")); + } + + // Audio menu + else if (curMenu == menu::menu->GetMenu("main/audio")) { + bool state = audioController->IsAudioOpen(); + bool vidstate = VideoContext::Get()->IsLoaded(); + + MenuBar->Enable(cmd::id("audio/open/video"),vidstate); + MenuBar->Enable(cmd::id("audio/close"),state); + + // Rebuild recent + RebuildRecentList(_T("Audio"),menu::menu->GetMenu("recent/audio"), cmd::id("recent/audio")); + } + + // Subtitles menu + else if (curMenu == menu::menu->GetMenu("main/subtitle")) { + // Variables + bool continuous; + wxArrayInt sels = SubsGrid->GetSelection(&continuous); + int count = sels.Count(); + bool state,state2; + + // Entries + state = count > 0; + MenuBar->Enable(cmd::id("subtitle/insert/before"),state); + MenuBar->Enable(cmd::id("subtitle/insert/after"),state); + MenuBar->Enable(cmd::id("edit/line/split/by_karaoke"),state); + MenuBar->Enable(cmd::id("edit/line/delete"),state); + state2 = count > 0 && VideoContext::Get()->IsLoaded(); + MenuBar->Enable(cmd::id("subtitle/insert/before/videotime"),state2); + MenuBar->Enable(cmd::id("subtitle/insert/after/videotime"),state2); + MenuBar->Enable(cmd::id("main/subtitle/insert lines"),state); + state = count > 0 && continuous; + MenuBar->Enable(cmd::id("edit/line/duplicate"),state); + state = count > 0 && continuous && VideoContext::Get()->TimecodesLoaded(); + MenuBar->Enable(cmd::id("edit/line/duplicate/shift"),state); + state = count == 2; + MenuBar->Enable(cmd::id("edit/line/swap"),state); + state = count >= 2 && continuous; + MenuBar->Enable(cmd::id("edit/line/join/concatenate"),state); + MenuBar->Enable(cmd::id("edit/line/join/keep_first"),state); + MenuBar->Enable(cmd::id("edit/line/join/as_karaoke"),state); + MenuBar->Enable(cmd::id("main/subtitle/join lines"),state); + state = (count == 2 || count == 3) && continuous; + MenuBar->Enable(cmd::id("edit/line/recombine"),state); + } + + // Timing menu + else if (curMenu == menu::menu->GetMenu("main/timing")) { + // Variables + bool continuous; + wxArrayInt sels = SubsGrid->GetSelection(&continuous); + int count = sels.Count(); + + // Video related + bool state = VideoContext::Get()->IsLoaded(); + MenuBar->Enable(cmd::id("time/snap/start_video"),state); + MenuBar->Enable(cmd::id("time/snap/end_video"),state); + MenuBar->Enable(cmd::id("time/snap/scene"),state); + MenuBar->Enable(cmd::id("time/frame/current"),state); + + // Other + state = count >= 2 && continuous; + MenuBar->Enable(cmd::id("time/continous/start"),state); + MenuBar->Enable(cmd::id("time/continous/end"),state); + } + + // Edit menu + else if (curMenu == menu::menu->GetMenu("main/edit")) { + wxMenu *editMenu = menu::menu->GetMenu("main/edit"); + + // Undo state + wxMenuItem *item; +//H wxString undo_text = _("&Undo") + wxString(_T(" ")) + ass->GetUndoDescription() + wxString(_T("\t")) + Hotkeys.GetText(_T("Undo")); +// The bottom line needs to be fixed for the new hotkey system + wxString undo_text = _("&Undo") + wxString(_T(" ")) + ass->GetUndoDescription() + wxString(_T("\t")) + _T("Undo"); + item = editMenu->FindItem(cmd::id("edit/undo")); + item->SetItemLabel(undo_text); + item->Enable(!ass->IsUndoStackEmpty()); + + // Redo state +//H wxString redo_text = _("&Redo") + wxString(_T(" ")) + ass->GetRedoDescription() + wxString(_T("\t")) + Hotkeys.GetText(_T("Redo")); +// Same as above. + wxString redo_text = _("&Redo") + wxString(_T(" ")) + ass->GetRedoDescription() + wxString(_T("\t")) + _T("Redo"); + item = editMenu->FindItem(cmd::id("edit/redo")); + item->SetItemLabel(redo_text); + item->Enable(!ass->IsRedoStackEmpty()); + + // Copy/cut/paste + wxArrayInt sels = SubsGrid->GetSelection(); + bool can_copy = (sels.Count() > 0); + + bool can_paste = true; + if (wxTheClipboard->Open()) { + can_paste = wxTheClipboard->IsSupported(wxDF_TEXT); + wxTheClipboard->Close(); + } + + MenuBar->Enable(cmd::id("edit/line/cut"),can_copy); + MenuBar->Enable(cmd::id("edit/line/copy"),can_copy); + MenuBar->Enable(cmd::id("edit/line/paste"),can_paste); + MenuBar->Enable(cmd::id("edit/line/paste/over"),can_copy&&can_paste); + } + + // Automation menu +#ifdef WITH_AUTOMATION + else if (curMenu == menu::menu->GetMenu("main/automation")) { + wxMenu *automationMenu = menu::menu->GetMenu("main/automation"); + + // Remove old macro items + for (unsigned int i = 0; i < activeMacroItems.size(); i++) { + wxMenu *p = 0; + wxMenuItem *it = MenuBar->FindItem(ID_MENU_AUTOMATION_MACRO + i, &p); + if (it) + p->Delete(it); + } + activeMacroItems.clear(); + + // Add new ones + int added = 0; + added += AddMacroMenuItems(automationMenu, wxGetApp().global_scripts->GetMacros()); + added += AddMacroMenuItems(automationMenu, local_scripts->GetMacros()); + + // If none were added, show a ghosted notice + if (added == 0) { + automationMenu->Append(ID_MENU_AUTOMATION_MACRO, _("No Automation macros loaded"))->Enable(false); + activeMacroItems.push_back(0); + } + } +#endif + + MenuBar->Thaw(); +} + +/// @brief Macro menu creation helper +/// @param menu +/// @param macros +/// @return +int FrameMain::AddMacroMenuItems(wxMenu *menu, const std::vector ¯os) { +#ifdef WITH_AUTOMATION + if (macros.empty()) { + return 0; + } + + int id = activeMacroItems.size();; + for (std::vector::const_iterator i = macros.begin(); i != macros.end(); ++i) { + wxMenuItem * m = menu->Append(ID_MENU_AUTOMATION_MACRO + id, (*i)->GetName(), (*i)->GetDescription()); + m->Enable((*i)->Validate(SubsGrid->ass, SubsGrid->GetAbsoluteSelection(), SubsGrid->GetFirstSelRow())); + activeMacroItems.push_back(*i); + id++; + } + + return macros.size(); +#else + return 0; +#endif +} + +/// @brief General handler for all Automation-generated menu items +/// @param event +void FrameMain::OnAutomationMacro (wxCommandEvent &event) { +#ifdef WITH_AUTOMATION + SubsGrid->BeginBatch(); + // First get selection data + std::vector selected_lines = SubsGrid->GetAbsoluteSelection(); + int first_sel = SubsGrid->GetFirstSelRow(); + // Run the macro... + activeMacroItems[event.GetId()-ID_MENU_AUTOMATION_MACRO]->Process(SubsGrid->ass, selected_lines, first_sel, this); + SubsGrid->SetSelectionFromAbsolute(selected_lines); + SubsGrid->EndBatch(); +#endif +} + + +/// @brief Window is attempted to be closed +/// @param event +void FrameMain::OnCloseWindow (wxCloseEvent &event) { + // Stop audio and video + VideoContext::Get()->Stop(); + audioController->Stop(); + + // Ask user if he wants to save first + bool canVeto = event.CanVeto(); + int result = TryToCloseSubs(canVeto); + + // Store maximization state + OPT_SET("App/Maximized")->SetBool(IsMaximized()); + + // Abort/destroy + if (canVeto) { + if (result == wxCANCEL) event.Veto(); + else Destroy(); + } + else Destroy(); +} + +/// @brief Autosave the currently open file, if any +void FrameMain::OnAutoSave(wxTimerEvent &) { + try { + if (ass->loaded && ass->IsModified()) { + // Set path + wxFileName origfile(ass->filename); + wxString path = lagi_wxString(OPT_GET("Path/Auto/Save")->GetString()); + if (path.IsEmpty()) path = origfile.GetPath(); + wxFileName dstpath(path); + if (!dstpath.IsAbsolute()) path = StandardPaths::DecodePathMaybeRelative(path, _T("?user/")); + dstpath.AssignDir(path); + if (!dstpath.DirExists()) wxMkdir(path); + + wxString name = origfile.GetName(); + if (name.IsEmpty()) { + dstpath.SetFullName("Untitled.AUTOSAVE.ass"); + } + else { + dstpath.SetFullName(name + L".AUTOSAVE.ass"); + } + + ass->Save(dstpath.GetFullPath(),false,false); + + // Set status bar + StatusTimeout(_("File backup saved as \"") + dstpath.GetFullPath() + _T("\".")); + } + } + catch (const agi::Exception& err) { + StatusTimeout(lagi_wxString("Exception when attempting to autosave file: " + err.GetMessage())); + } + catch (wxString err) { + StatusTimeout(_T("Exception when attempting to autosave file: ") + err); + } + catch (const wchar_t *err) { + StatusTimeout(_T("Exception when attempting to autosave file: ") + wxString(err)); + } + catch (...) { + StatusTimeout(_T("Unhandled exception when attempting to autosave file.")); + } +} + +/// @brief Clear statusbar +void FrameMain::OnStatusClear(wxTimerEvent &) { + SetStatusText(_T(""),1); +} + +void FrameMain::OnAudioBoxResize(wxSashEvent &event) +{ + if (event.GetDragStatus() == wxSASH_STATUS_OUT_OF_RANGE) + return; + + wxRect rect = event.GetDragRect(); + + if (rect.GetHeight() < audioSash->GetMinimumSizeY()) + rect.SetHeight(audioSash->GetMinimumSizeY()); + + audioBox->SetMinSize(wxSize(-1, rect.GetHeight())); + Panel->Layout(); + Refresh(); +} + +void FrameMain::OnAudioOpen(AudioProvider *provider) +{ + SetDisplayMode(-1, 1); +} + +void FrameMain::OnAudioClose() +{ + SetDisplayMode(-1, 0); +} + +void FrameMain::OnSubtitlesFileChanged() { + if (OPT_GET("App/Auto/Save on Every Change")->GetBool()) { + if (ass->IsModified() && !ass->filename.empty()) SaveSubtitles(false); + } + + UpdateTitle(); +} + +void FrameMain::OnKeyDown(wxKeyEvent &event) { + hotkey::check("Main Frame", event.GetKeyCode(), event.GetUnicodeKey(), event.GetModifiers()); +} + diff --git a/aegisub/src/frame_main.h b/aegisub/src/frame_main.h index daed37ff5..42ff4f3cc 100644 --- a/aegisub/src/frame_main.h +++ b/aegisub/src/frame_main.h @@ -47,6 +47,9 @@ #include #endif +#include "aegisub/context.h" + + class AssFile; class VideoDisplay; class VideoSlider; @@ -64,6 +67,13 @@ class AudioProvider; namespace Automation4 { class FeatureMacro; class ScriptManager; } +enum SubMenuID { + ID_TOOLBAR_ZOOM_DROPDOWN = 11001, + ID_APP_TIMER_AUTOSAVE = 12001, + ID_APP_TIMER_STATUSCLEAR = 12002, + ID_MENU_AUTOMATION_MACRO = 13006, + ID_SASH_MAIN_AUDIO = 14001 +}; /// DOCME /// @class FrameMain @@ -75,7 +85,21 @@ class FrameMain: public wxFrame { friend class AegisubApp; friend class SubtitlesGrid; +public: + void StatusTimeout(wxString text,int ms=10000); + void SetDisplayMode(int showVid,int showAudio); + void LoadSubtitles(wxString filename,wxString charset=_T("")); + bool SaveSubtitles(bool saveas=false,bool withCharset=false); + void LoadVideo(wxString filename,bool autoload=false); + void DetachVideo(bool detach=true); + void LoadVFR(wxString filename); + private: + + agi::Context temp_context; + + void cmd_call(wxCommandEvent& event); + AssFile *ass; /// DOCME @@ -103,57 +127,6 @@ private: /// DOCME wxPanel *Panel; - - /// DOCME - wxMenuBar *MenuBar; - - /// DOCME - wxMenu *fileMenu; - - /// DOCME - wxMenu *editMenu; - - /// DOCME - wxMenu *videoMenu; - - /// DOCME - wxMenu *timingMenu; - - /// DOCME - wxMenu *subtitlesMenu; - - /// DOCME - wxMenu *helpMenu; - - /// DOCME - wxMenu *audioMenu; - - /// DOCME - wxMenu *viewMenu; - - /// DOCME - wxMenu *automationMenu; - - /// DOCME - wxMenu *kanjiTimingMenu; - - - /// DOCME - wxMenu *RecentSubs; - - /// DOCME - wxMenu *RecentVids; - - /// DOCME - wxMenu *RecentAuds; - - /// DOCME - wxMenu *RecentTimecodes; - - /// DOCME - wxMenu *RecentKeyframes; - - /// DOCME wxToolBar *Toolbar; @@ -179,146 +152,17 @@ private: void InitContents(); void DeInitContents(); - void OnAutoSave(wxTimerEvent &event); - void OnStatusClear(wxTimerEvent &event); - void OnVideoPlay(wxCommandEvent &event); + void OnKeyDown(wxKeyEvent &event); + void OnGridEvent (wxCommandEvent &event); + void OnMenuOpen (wxMenuEvent &event); void OnAudioBoxResize(wxSashEvent &event); - - void OnOpenRecentSubs (wxCommandEvent &event); - void OnOpenRecentVideo (wxCommandEvent &event); - void OnOpenRecentAudio (wxCommandEvent &event); - void OnOpenRecentTimecodes (wxCommandEvent &event); - void OnOpenRecentKeyframes (wxCommandEvent &event); - - void OnNewWindow (wxCommandEvent &event); + void OnAutoSave(wxTimerEvent &event); + void OnStatusClear(wxTimerEvent &event); void OnCloseWindow (wxCloseEvent &event); - void OnMenuOpen (wxMenuEvent &event); - void OnExit(wxCommandEvent &WXUNUSED(event)); - void OnAbout (wxCommandEvent &event); - void OnLog (wxCommandEvent &event); - void OnCheckUpdates (wxCommandEvent &event); - void OnContents (wxCommandEvent &event); - void OnFiles (wxCommandEvent &event); - void OnWebsite (wxCommandEvent &event); - void OnForums (wxCommandEvent &event); - void OnBugTracker (wxCommandEvent &event); - void OnIRCChannel (wxCommandEvent &event); - - void OnNewSubtitles (wxCommandEvent &event); - void OnOpenSubtitles (wxCommandEvent &event); - void OnOpenSubtitlesCharset (wxCommandEvent &event); - void OnOpenSubtitlesVideo (wxCommandEvent &event); - void OnSaveSubtitles (wxCommandEvent &event); - void OnSaveSubtitlesAs (wxCommandEvent &event); - void OnSaveSubtitlesCharset (wxCommandEvent &event); - void OnExportSubtitles (wxCommandEvent &event); - void OnOpenVideo (wxCommandEvent &event); - void OnCloseVideo (wxCommandEvent &event); - void OnOpenVFR (wxCommandEvent &event); - void OnSaveVFR (wxCommandEvent &event); - void OnCloseVFR (wxCommandEvent &event); - void OnOpenKeyframes (wxCommandEvent &event); - void OnCloseKeyframes (wxCommandEvent &event); - void OnSaveKeyframes (wxCommandEvent &event); - - void OnZoomIn (wxCommandEvent &event); - void OnZoomOut (wxCommandEvent &event); - void OnSetZoom50 (wxCommandEvent &event); - void OnSetZoom100 (wxCommandEvent &event); - void OnSetZoom200 (wxCommandEvent &event); - void OnSetZoom (wxCommandEvent &event); - void OnSetARDefault (wxCommandEvent &event); - void OnSetARWide (wxCommandEvent &event); - void OnSetARFull (wxCommandEvent &event); - void OnSetAR235 (wxCommandEvent &event); - void OnSetARCustom (wxCommandEvent &event); - void OnDetachVideo (wxCommandEvent &event); - void OnDummyVideo (wxCommandEvent &event); - void OnOverscan (wxCommandEvent &event); - - void OnOpenAudio (wxCommandEvent &event); - void OnOpenAudioFromVideo (wxCommandEvent &event); - void OnCloseAudio (wxCommandEvent &event); - void OnAudioDisplayMode (wxCommandEvent &event); -#ifdef _DEBUG - void OnOpenDummyAudio(wxCommandEvent &event); - void OnOpenDummyNoiseAudio(wxCommandEvent &event); -#endif - - void OnChooseLanguage (wxCommandEvent &event); - void OnViewStandard (wxCommandEvent &event); - void OnViewVideo (wxCommandEvent &event); - void OnViewAudio (wxCommandEvent &event); - void OnViewSubs (wxCommandEvent &event); - void OnSetTags (wxCommandEvent &event); - - void OnUndo (wxCommandEvent &event); - void OnRedo (wxCommandEvent &event); - void OnCut (wxCommandEvent &event); - void OnCopy (wxCommandEvent &event); - void OnPaste (wxCommandEvent &event); - void OnPasteOver (wxCommandEvent &event); - void OnDelete (wxCommandEvent &event); - void OnFind (wxCommandEvent &event); - void OnFindNext (wxCommandEvent &event); - void OnReplace (wxCommandEvent &event); - void OnJumpTo (wxCommandEvent &event); - void OnShift (wxCommandEvent &event); - void OnSortStart (wxCommandEvent &event); - void OnSortEnd (wxCommandEvent &event); - void OnSortStyle (wxCommandEvent &event); - void OnOpenProperties (wxCommandEvent &event); - void OnOpenStylesManager (wxCommandEvent &event); - void OnOpenAttachments (wxCommandEvent &event); - void OnOpenTranslation (wxCommandEvent &event); - void OnOpenSpellCheck (wxCommandEvent &event); - void OnOpenFontsCollector (wxCommandEvent &event); - void OnSnapSubsStartToVid (wxCommandEvent &event); - void OnSnapSubsEndToVid (wxCommandEvent &event); - void OnSnapVidToSubsStart (wxCommandEvent &event); - void OnSnapVidToSubsEnd (wxCommandEvent &event); - void OnSnapToScene (wxCommandEvent &event); - void OnShiftToFrame (wxCommandEvent &event); - void OnSelectVisible (wxCommandEvent &event); - void OnSelect (wxCommandEvent &event); - void OnOpenStylingAssistant (wxCommandEvent &event); - void OnOpenResample (wxCommandEvent &event); - void OnOpenTimingProcessor (wxCommandEvent &event); - void OnOpenKanjiTimer (wxCommandEvent &event); - void OnOpenVideoDetails (wxCommandEvent &event); - void OnOpenASSDraw (wxCommandEvent &event); - - void OnOpenPreferences (wxCommandEvent &event); - void OnGridEvent (wxCommandEvent &event); - - void OnOpenAutomation (wxCommandEvent &event); void OnAutomationMacro(wxCommandEvent &event); - void OnNextFrame(wxCommandEvent &event); - void OnPrevFrame(wxCommandEvent &event); - void OnFocusSeek(wxCommandEvent &event); - void OnNextLine(wxCommandEvent &event); - void OnPrevLine(wxCommandEvent &event); - void OnToggleTags(wxCommandEvent &event); - - void OnMedusaPlay(wxCommandEvent &event); - void OnMedusaStop(wxCommandEvent &event); - void OnMedusaShiftStartForward(wxCommandEvent &event); - void OnMedusaShiftStartBack(wxCommandEvent &event); - void OnMedusaShiftEndForward(wxCommandEvent &event); - void OnMedusaShiftEndBack(wxCommandEvent &event); - void OnMedusaPlayBefore(wxCommandEvent &event); - void OnMedusaPlayAfter(wxCommandEvent &event); - void OnMedusaEnter(wxCommandEvent &event); - void OnMedusaNext(wxCommandEvent &event); - void OnMedusaPrev(wxCommandEvent &event); - - void LoadVideo(wxString filename,bool autoload=false); - void LoadVFR(wxString filename); - void LoadSubtitles(wxString filename,wxString charset=_T("")); - bool SaveSubtitles(bool saveas=false,bool withCharset=false); int TryToCloseSubs(bool enableCancel=true); void RebuildRecentList(wxString listName,wxMenu *menu,int startID); @@ -375,180 +219,13 @@ public: bool LoadList(wxArrayString list); static void OpenHelp(wxString page=_T("")); void UpdateTitle(); - void StatusTimeout(wxString text,int ms=10000); - void DetachVideo(bool detach=true); - void SetAccelerators(); void InitMenu(); void UpdateToolbar(); - void SetDisplayMode(int showVid,int showAudio); - + void SetUndoRedoDesc(); bool HasASSDraw(); DECLARE_EVENT_TABLE() }; - -/// Menu entry event ids -enum { - Menu_File_New = 200, - Menu_File_Open, - Menu_File_Save, - Menu_File_SaveAs, - Menu_File_Close, - Menu_File_Open_Video, - Menu_File_Close_Video, - Menu_File_Open_Subtitles, - Menu_File_Open_Subtitles_Charset, - Menu_File_Open_Subtitles_From_Video, - Menu_File_New_Subtitles, - Menu_File_Save_Subtitles, - Menu_File_Save_Subtitles_As, - Menu_File_Save_Subtitles_With_Charset, - Menu_File_Export_Subtitles, - Menu_File_Open_VFR, - Menu_File_Save_VFR, - Menu_File_Close_VFR, - Menu_File_New_Window, - Menu_File_Exit, - - Menu_File_Recent_Subs_Parent, - Menu_File_Recent_Vids_Parent, - Menu_File_Recent_Auds_Parent, - Menu_File_Recent_Timecodes_Parent, - Menu_File_Recent_Keyframes_Parent, - - Menu_Video_JumpTo, - Menu_View_Zoom, - Menu_View_Zoom_50, - Menu_View_Zoom_100, - Menu_View_Zoom_200, - Menu_Video_Zoom_In, - Menu_Video_Zoom_Out, - Menu_Video_Load_Keyframes, - Menu_Video_Save_Keyframes, - Menu_Video_Close_Keyframes, - Toolbar_Zoom_Dropdown, - Menu_Video_AR, - Menu_Video_AR_Default, - Menu_Video_AR_Full, - Menu_Video_AR_Wide, - Menu_Video_AR_235, - Menu_Video_AR_Custom, - Menu_Video_Select_Visible, - Menu_Video_Play, - Menu_Video_Detach, - Menu_Video_Dummy, - Menu_Video_Overscan, - Menu_Video_Details, - - Menu_Audio_Open_File, - Menu_Audio_Open_From_Video, - Menu_Audio_Close, - - Menu_Audio_Spectrum, - Menu_Audio_Waveform, -#ifdef _DEBUG - Menu_Audio_Open_Dummy, - Menu_Audio_Open_Dummy_Noise, -#endif - - Menu_Edit_Select, - Menu_Edit_Undo, - Menu_Edit_Redo, - Menu_Edit_Find, - Menu_Edit_Find_Next, - Menu_Edit_Replace, - Menu_Edit_Shift, - Menu_Edit_Cut, - Menu_Edit_Copy, - Menu_Edit_Paste, - Menu_Edit_Paste_Over, - Menu_Edit_Delete, - - Menu_View_Language, - Menu_View_Standard, - Menu_View_Audio, - Menu_View_Video, - Menu_View_Subs, - Menu_View_FullTags, - Menu_View_ShortTags, - Menu_View_NoTags, - - Menu_Subtitles_Join, - Menu_Subtitles_Recombine, - Menu_Subtitles_Insert, - - Menu_Subtitles_Sort_Start, - Menu_Subtitles_Sort_End, - Menu_Subtitles_Sort_Style, - Menu_Tools_Properties, - Menu_Tools_Styles_Manager, - Menu_Tools_Attachments, - Menu_Tools_Translation, - Menu_Tools_SpellCheck, - Menu_Tools_Fonts_Collector, - Menu_Tools_Automation, - Menu_Tools_Styling, - Menu_Tools_Resample, - Menu_Tools_Timing_Processor, - Menu_Tools_Kanji_Timer, - Menu_Tools_Options, - Menu_Tools_ASSDraw, - - Menu_Help_Contents, - Menu_Help_Files, - Menu_Help_IRCChannel, - Menu_Help_Website, - Menu_Help_Forums, - Menu_Help_BugTracker, - Menu_Help_Check_Updates, - Menu_Help_About, - - Menu_Help_Log, - Menu_Subs_Snap_Start_To_Video, - Menu_Subs_Snap_End_To_Video, - Menu_Subs_Snap_Video_To_Start, - Menu_Subs_Snap_Video_To_End, - Menu_Video_Snap_To_Scene, - Menu_Video_Shift_To_Frame, - - AutoSave_Timer, - StatusClear_Timer, - - - /// Id for the audio box resizing sash - Main_AudioSash, - - - /// DOCME - Video_Next_Frame, - Video_Prev_Frame, - Video_Focus_Seek, - Grid_Next_Line, - Grid_Prev_Line, - Grid_Toggle_Tags, - - - Video_Frame_Play, - - Medusa_Play, - Medusa_Stop, - Medusa_Shift_Start_Forward, - Medusa_Shift_Start_Back, - Medusa_Shift_End_Forward, - Medusa_Shift_End_Back, - Medusa_Play_Before, - Medusa_Play_After, - Medusa_Next, - Medusa_Prev, - Medusa_Enter, - - Menu_File_Recent = 2000, - Menu_Video_Recent = 2200, - Menu_Audio_Recent = 2400, - Menu_Timecodes_Recent = 2500, - Menu_Keyframes_Recent = 2600, - Menu_Automation_Macro = 2700 -}; diff --git a/aegisub/src/frame_main_events.cpp b/aegisub/src/frame_main_events.cpp deleted file mode 100644 index d1e260cc6..000000000 --- a/aegisub/src/frame_main_events.cpp +++ /dev/null @@ -1,1632 +0,0 @@ -// Copyright (c) 2005, Rodrigo Braz Monteiro -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of the Aegisub Group nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Aegisub Project http://www.aegisub.org/ -// -// $Id$ - -/// @file frame_main_events.cpp -/// @brief Event handlers for controls in main window -/// @ingroup main_ui - - -#include "config.h" - -#ifndef AGI_PRE -#include -#include -#include -#include -#include -#include -#include -#endif - -#include "ass_dialogue.h" -#include "ass_file.h" -#include "selection_controller.h" -#include "audio_controller.h" -#include "audio_box.h" -#include "audio_display.h" -#ifdef WITH_AUTOMATION -#include "auto4_base.h" -#endif -#include "compat.h" -#include "dialog_about.h" -#include "dialog_attachments.h" -#include "dialog_automation.h" -#include "dialog_dummy_video.h" -#include "dialog_export.h" -#include "dialog_fonts_collector.h" -#include "dialog_jumpto.h" -#include "dialog_kara_timing_copy.h" -#include "dialog_log.h" -#include "dialog_progress.h" -#include "dialog_properties.h" -#include "dialog_resample.h" -#include "dialog_search_replace.h" -#include "dialog_selection.h" -#include "dialog_shift_times.h" -#include "dialog_spellchecker.h" -#include "dialog_style_manager.h" -#include "dialog_styling_assistant.h" -#include "dialog_timing_processor.h" -#include "dialog_translation.h" -#include "dialog_version_check.h" -#include "dialog_video_details.h" -#include "frame_main.h" -#include "hotkeys.h" -#include "include/aegisub/audio_player.h" -#include "libaegisub/charset_conv.h" -#include "libresrc/libresrc.h" -#include "main.h" -#include "preferences.h" -#include "standard_paths.h" -#include "selection_controller.h" -#include "subs_edit_box.h" -#include "subs_edit_ctrl.h" -#include "subs_grid.h" -#include "toggle_bitmap.h" -#include "utils.h" -#include "video_box.h" -#include "video_context.h" -#include "video_display.h" -#include "video_slider.h" - -#ifdef __APPLE__ -#include -#endif - -BEGIN_EVENT_TABLE(FrameMain, wxFrame) - EVT_TIMER(AutoSave_Timer, FrameMain::OnAutoSave) - EVT_TIMER(StatusClear_Timer, FrameMain::OnStatusClear) - - EVT_CLOSE(FrameMain::OnCloseWindow) - - EVT_SASH_DRAGGED(Main_AudioSash, FrameMain::OnAudioBoxResize) - - EVT_MENU_OPEN(FrameMain::OnMenuOpen) - EVT_MENU_RANGE(Menu_File_Recent,Menu_File_Recent+99, FrameMain::OnOpenRecentSubs) - EVT_MENU_RANGE(Menu_Video_Recent,Menu_Video_Recent+99, FrameMain::OnOpenRecentVideo) - EVT_MENU_RANGE(Menu_Audio_Recent,Menu_Audio_Recent+99, FrameMain::OnOpenRecentAudio) - EVT_MENU_RANGE(Menu_Timecodes_Recent,Menu_Timecodes_Recent+99, FrameMain::OnOpenRecentTimecodes) - EVT_MENU_RANGE(Menu_Keyframes_Recent,Menu_Keyframes_Recent+99, FrameMain::OnOpenRecentKeyframes) - EVT_MENU_RANGE(Menu_Automation_Macro,Menu_Automation_Macro+99, FrameMain::OnAutomationMacro) - - EVT_MENU_RANGE(MENU_GRID_START+1,MENU_GRID_END-1,FrameMain::OnGridEvent) - EVT_MENU(Menu_File_New_Window, FrameMain::OnNewWindow) - EVT_MENU(Menu_File_Exit, FrameMain::OnExit) - EVT_MENU(Menu_File_Open_Video, FrameMain::OnOpenVideo) - EVT_MENU(Menu_File_Close_Video, FrameMain::OnCloseVideo) - EVT_MENU(Menu_File_Open_Subtitles, FrameMain::OnOpenSubtitles) - EVT_MENU(Menu_File_Open_Subtitles_Charset, FrameMain::OnOpenSubtitlesCharset) - EVT_MENU(Menu_File_Open_Subtitles_From_Video, FrameMain::OnOpenSubtitlesVideo) - EVT_MENU(Menu_File_New_Subtitles, FrameMain::OnNewSubtitles) - EVT_MENU(Menu_File_Save_Subtitles, FrameMain::OnSaveSubtitles) - EVT_MENU(Menu_File_Save_Subtitles_As, FrameMain::OnSaveSubtitlesAs) - EVT_MENU(Menu_File_Save_Subtitles_With_Charset, FrameMain::OnSaveSubtitlesCharset) - EVT_MENU(Menu_File_Export_Subtitles, FrameMain::OnExportSubtitles) - EVT_MENU(Menu_File_Open_VFR, FrameMain::OnOpenVFR) - EVT_MENU(Menu_File_Save_VFR, FrameMain::OnSaveVFR) - EVT_MENU(Menu_File_Close_VFR, FrameMain::OnCloseVFR) - EVT_MENU(Menu_Video_Load_Keyframes, FrameMain::OnOpenKeyframes) - EVT_MENU(Menu_Video_Save_Keyframes, FrameMain::OnSaveKeyframes) - EVT_MENU(Menu_Video_Close_Keyframes, FrameMain::OnCloseKeyframes) - - EVT_MENU(Menu_View_Zoom_50, FrameMain::OnSetZoom50) - EVT_MENU(Menu_View_Zoom_100, FrameMain::OnSetZoom100) - EVT_MENU(Menu_View_Zoom_200, FrameMain::OnSetZoom200) - EVT_COMBOBOX(Toolbar_Zoom_Dropdown, FrameMain::OnSetZoom) - EVT_TEXT_ENTER(Toolbar_Zoom_Dropdown, FrameMain::OnSetZoom) - EVT_MENU(Video_Frame_Play, FrameMain::OnVideoPlay) - EVT_MENU(Menu_Video_Zoom_In, FrameMain::OnZoomIn) - EVT_MENU(Menu_Video_Zoom_Out, FrameMain::OnZoomOut) - EVT_MENU(Menu_Video_AR_Default, FrameMain::OnSetARDefault) - EVT_MENU(Menu_Video_AR_Full, FrameMain::OnSetARFull) - EVT_MENU(Menu_Video_AR_Wide, FrameMain::OnSetARWide) - EVT_MENU(Menu_Video_AR_235, FrameMain::OnSetAR235) - EVT_MENU(Menu_Video_AR_Custom, FrameMain::OnSetARCustom) - EVT_MENU(Menu_Video_JumpTo, FrameMain::OnJumpTo) - EVT_MENU(Menu_Video_Select_Visible, FrameMain::OnSelectVisible) - EVT_MENU(Menu_Video_Detach, FrameMain::OnDetachVideo) - EVT_MENU(Menu_Video_Dummy, FrameMain::OnDummyVideo) - EVT_MENU(Menu_Video_Overscan, FrameMain::OnOverscan) - EVT_MENU(Menu_Video_Details, FrameMain::OnOpenVideoDetails) - - EVT_MENU(Menu_Audio_Open_File, FrameMain::OnOpenAudio) - EVT_MENU(Menu_Audio_Open_From_Video, FrameMain::OnOpenAudioFromVideo) - EVT_MENU(Menu_Audio_Close, FrameMain::OnCloseAudio) - EVT_MENU(Menu_Audio_Spectrum, FrameMain::OnAudioDisplayMode) - EVT_MENU(Menu_Audio_Waveform, FrameMain::OnAudioDisplayMode) -#ifdef _DEBUG - EVT_MENU(Menu_Audio_Open_Dummy, FrameMain::OnOpenDummyAudio) - EVT_MENU(Menu_Audio_Open_Dummy_Noise, FrameMain::OnOpenDummyNoiseAudio) -#endif - - EVT_MENU(Menu_Edit_Undo, FrameMain::OnUndo) - EVT_MENU(Menu_Edit_Redo, FrameMain::OnRedo) - EVT_MENU(Menu_Edit_Cut, FrameMain::OnCut) - EVT_MENU(Menu_Edit_Copy, FrameMain::OnCopy) - EVT_MENU(Menu_Edit_Paste, FrameMain::OnPaste) - EVT_MENU(Menu_Edit_Paste_Over, FrameMain::OnPasteOver) - EVT_MENU(Menu_Edit_Find, FrameMain::OnFind) - EVT_MENU(Menu_Edit_Find_Next, FrameMain::OnFindNext) - EVT_MENU(Menu_Edit_Replace, FrameMain::OnReplace) - EVT_MENU(Menu_Edit_Shift, FrameMain::OnShift) - EVT_MENU(Menu_Edit_Select, FrameMain::OnSelect) - - EVT_MENU(Menu_Subtitles_Sort_Start, FrameMain::OnSortStart) - EVT_MENU(Menu_Subtitles_Sort_End, FrameMain::OnSortEnd) - EVT_MENU(Menu_Subtitles_Sort_Style, FrameMain::OnSortStyle) - - EVT_MENU(Menu_Tools_Properties, FrameMain::OnOpenProperties) - EVT_MENU(Menu_Tools_Styles_Manager, FrameMain::OnOpenStylesManager) - EVT_MENU(Menu_Tools_Attachments, FrameMain::OnOpenAttachments) - EVT_MENU(Menu_Tools_Translation, FrameMain::OnOpenTranslation) - EVT_MENU(Menu_Tools_SpellCheck, FrameMain::OnOpenSpellCheck) - EVT_MENU(Menu_Tools_Fonts_Collector, FrameMain::OnOpenFontsCollector) - EVT_MENU(Menu_Tools_Automation, FrameMain::OnOpenAutomation) - EVT_MENU(Menu_Tools_Styling, FrameMain::OnOpenStylingAssistant) - EVT_MENU(Menu_Tools_Resample, FrameMain::OnOpenResample) - EVT_MENU(Menu_Tools_Timing_Processor, FrameMain::OnOpenTimingProcessor) - EVT_MENU(Menu_Tools_Kanji_Timer, FrameMain::OnOpenKanjiTimer) - EVT_MENU(Menu_Tools_Options, FrameMain::OnOpenPreferences) - EVT_MENU(Menu_Tools_ASSDraw, FrameMain::OnOpenASSDraw) - - EVT_MENU(Menu_Subs_Snap_Start_To_Video, FrameMain::OnSnapSubsStartToVid) - EVT_MENU(Menu_Subs_Snap_End_To_Video, FrameMain::OnSnapSubsEndToVid) - EVT_MENU(Menu_Subs_Snap_Video_To_Start, FrameMain::OnSnapVidToSubsStart) - EVT_MENU(Menu_Subs_Snap_Video_To_End, FrameMain::OnSnapVidToSubsEnd) - EVT_MENU(Menu_Video_Snap_To_Scene, FrameMain::OnSnapToScene) - EVT_MENU(Menu_Video_Shift_To_Frame, FrameMain::OnShiftToFrame) - - EVT_MENU(Menu_Help_Contents, FrameMain::OnContents) - EVT_MENU(Menu_Help_Files, FrameMain::OnFiles) - EVT_MENU(Menu_Help_Website, FrameMain::OnWebsite) - EVT_MENU(Menu_Help_Forums, FrameMain::OnForums) - EVT_MENU(Menu_Help_BugTracker, FrameMain::OnBugTracker) - EVT_MENU(Menu_Help_IRCChannel, FrameMain::OnIRCChannel) - EVT_MENU(Menu_Help_Check_Updates, FrameMain::OnCheckUpdates) - EVT_MENU(Menu_Help_About, FrameMain::OnAbout) - EVT_MENU(Menu_Help_Log, FrameMain::OnLog) - - EVT_MENU(Menu_View_Language, FrameMain::OnChooseLanguage) - EVT_MENU(Menu_View_Standard, FrameMain::OnViewStandard) - EVT_MENU(Menu_View_Audio, FrameMain::OnViewAudio) - EVT_MENU(Menu_View_Video, FrameMain::OnViewVideo) - EVT_MENU(Menu_View_Subs, FrameMain::OnViewSubs) - EVT_MENU(Menu_View_FullTags, FrameMain::OnSetTags) - EVT_MENU(Menu_View_ShortTags, FrameMain::OnSetTags) - EVT_MENU(Menu_View_NoTags, FrameMain::OnSetTags) - - EVT_MENU(Video_Prev_Frame,FrameMain::OnPrevFrame) - EVT_MENU(Video_Next_Frame,FrameMain::OnNextFrame) - EVT_MENU(Video_Focus_Seek,FrameMain::OnFocusSeek) - EVT_MENU(Grid_Next_Line,FrameMain::OnNextLine) - EVT_MENU(Grid_Prev_Line,FrameMain::OnPrevLine) - EVT_MENU(Grid_Toggle_Tags,FrameMain::OnToggleTags) - - EVT_MENU(Medusa_Play, FrameMain::OnMedusaPlay) - EVT_MENU(Medusa_Stop, FrameMain::OnMedusaStop) - EVT_MENU(Medusa_Play_After, FrameMain::OnMedusaPlayAfter) - EVT_MENU(Medusa_Play_Before, FrameMain::OnMedusaPlayBefore) - EVT_MENU(Medusa_Next, FrameMain::OnMedusaNext) - EVT_MENU(Medusa_Prev, FrameMain::OnMedusaPrev) - EVT_MENU(Medusa_Shift_Start_Forward, FrameMain::OnMedusaShiftStartForward) - EVT_MENU(Medusa_Shift_Start_Back, FrameMain::OnMedusaShiftStartBack) - EVT_MENU(Medusa_Shift_End_Forward, FrameMain::OnMedusaShiftEndForward) - EVT_MENU(Medusa_Shift_End_Back, FrameMain::OnMedusaShiftEndBack) - EVT_MENU(Medusa_Enter, FrameMain::OnMedusaEnter) - -#ifdef __WXMAC__ - EVT_MENU(wxID_ABOUT, FrameMain::OnAbout) - EVT_MENU(wxID_EXIT, FrameMain::OnExit) -#endif -END_EVENT_TABLE() - - -/// @brief Redirect grid events to grid -/// @param event -void FrameMain::OnGridEvent (wxCommandEvent &event) { - SubsGrid->GetEventHandler()->ProcessEvent(event); -} - -/// @brief Rebuild recent list -/// @param listName -/// @param menu -/// @param startID -void FrameMain::RebuildRecentList(wxString listName,wxMenu *menu,int startID) { - // Wipe previous list - int count = (int)menu->GetMenuItemCount(); - for (int i=count;--i>=0;) { - menu->Destroy(menu->FindItemByPosition(i)); - } - - // Rebuild - int added = 0; - wxString n; - wxArrayString entries = lagi_MRU_wxAS(listName); - for (size_t i=0;iAppend(startID+i,n + _T(" ") + filename); - added++; - } - - // Nothing added, add an empty placeholder - if (added == 0) menu->Append(startID,_("Empty"))->Enable(false); -} - -/// @brief Menu is being opened -/// @param event -void FrameMain::OnMenuOpen (wxMenuEvent &event) { - // Get menu - MenuBar->Freeze(); - wxMenu *curMenu = event.GetMenu(); - - // File menu - if (curMenu == fileMenu) { - // Rebuild recent - RebuildRecentList(_T("Subtitle"),RecentSubs,Menu_File_Recent); - - MenuBar->Enable(Menu_File_Open_Subtitles_From_Video,VideoContext::Get()->HasSubtitles()); - } - - // View menu - else if (curMenu == viewMenu) { - // Flags - bool aud = audioController->IsAudioOpen(); - bool vid = VideoContext::Get()->IsLoaded() && !detachedVideo; - - // Set states - MenuBar->Enable(Menu_View_Audio,aud); - MenuBar->Enable(Menu_View_Video,vid); - MenuBar->Enable(Menu_View_Standard,aud && vid); - - // Select option - if (!showVideo && !showAudio) MenuBar->Check(Menu_View_Subs,true); - else if (showVideo && !showAudio) MenuBar->Check(Menu_View_Video,true); - else if (showAudio && showVideo) MenuBar->Check(Menu_View_Standard,true); - else MenuBar->Check(Menu_View_Audio,true); - - MenuBar->Check(OPT_GET("Subtitle/Grid/Hide Overrides")->GetInt() + Menu_View_FullTags, true); - } - - // Video menu - else if (curMenu == videoMenu) { - bool state = VideoContext::Get()->IsLoaded(); - bool attached = state && !detachedVideo; - - // Set states - MenuBar->Enable(Menu_Video_JumpTo,state); - MenuBar->Enable(Menu_Subs_Snap_Video_To_Start,state); - MenuBar->Enable(Menu_Subs_Snap_Video_To_End,state); - MenuBar->Enable(Menu_View_Zoom,attached); - MenuBar->Enable(Menu_View_Zoom_50,attached); - MenuBar->Enable(Menu_View_Zoom_100,attached); - MenuBar->Enable(Menu_View_Zoom_200,attached); - MenuBar->Enable(Menu_File_Close_Video,state); - MenuBar->Enable(Menu_Video_AR,attached); - MenuBar->Enable(Menu_Video_AR_Default,attached); - MenuBar->Enable(Menu_Video_AR_Full,attached); - MenuBar->Enable(Menu_Video_AR_Wide,attached); - MenuBar->Enable(Menu_Video_AR_235,attached); - MenuBar->Enable(Menu_Video_AR_Custom,attached); - MenuBar->Enable(Menu_Video_Detach,state); - MenuBar->Enable(Menu_File_Save_VFR,VideoContext::Get()->TimecodesLoaded()); - MenuBar->Enable(Menu_File_Close_VFR,VideoContext::Get()->OverTimecodesLoaded()); - MenuBar->Enable(Menu_Video_Close_Keyframes,VideoContext::Get()->OverKeyFramesLoaded()); - MenuBar->Enable(Menu_Video_Save_Keyframes,VideoContext::Get()->KeyFramesLoaded()); - MenuBar->Enable(Menu_Video_Details,state); - MenuBar->Enable(Menu_Video_Overscan,state); - - // Set AR radio - int arType = VideoContext::Get()->GetAspectRatioType(); - MenuBar->Check(Menu_Video_AR_Default,false); - MenuBar->Check(Menu_Video_AR_Full,false); - MenuBar->Check(Menu_Video_AR_Wide,false); - MenuBar->Check(Menu_Video_AR_235,false); - MenuBar->Check(Menu_Video_AR_Custom,false); - switch (arType) { - case 0: MenuBar->Check(Menu_Video_AR_Default,true); break; - case 1: MenuBar->Check(Menu_Video_AR_Full,true); break; - case 2: MenuBar->Check(Menu_Video_AR_Wide,true); break; - case 3: MenuBar->Check(Menu_Video_AR_235,true); break; - case 4: MenuBar->Check(Menu_Video_AR_Custom,true); break; - } - - // Set overscan mask - MenuBar->Check(Menu_Video_Overscan,OPT_GET("Video/Overscan Mask")->GetBool()); - - // Rebuild recent lists - RebuildRecentList(_T("Video"),RecentVids,Menu_Video_Recent); - RebuildRecentList(_T("Timecodes"),RecentTimecodes,Menu_Timecodes_Recent); - RebuildRecentList(_T("Keyframes"),RecentKeyframes,Menu_Keyframes_Recent); - } - - // Audio menu - else if (curMenu == audioMenu) { - bool state = audioController->IsAudioOpen(); - bool vidstate = VideoContext::Get()->IsLoaded(); - - MenuBar->Enable(Menu_Audio_Open_From_Video,vidstate); - MenuBar->Enable(Menu_Audio_Close,state); - - bool spectrum_enabled = OPT_GET("Audio/Spectrum")->GetBool(); - MenuBar->Check(Menu_Audio_Spectrum, spectrum_enabled); - MenuBar->Check(Menu_Audio_Waveform, !spectrum_enabled); - - // Rebuild recent - RebuildRecentList(_T("Audio"),RecentAuds,Menu_Audio_Recent); - } - - // Subtitles menu - else if (curMenu == subtitlesMenu) { - // Variables - bool continuous; - wxArrayInt sels = SubsGrid->GetSelection(&continuous); - int count = sels.Count(); - bool state,state2; - - // Entries - state = count > 0; - MenuBar->Enable(MENU_INSERT_BEFORE,state); - MenuBar->Enable(MENU_INSERT_AFTER,state); - MenuBar->Enable(MENU_SPLIT_BY_KARAOKE,state); - MenuBar->Enable(MENU_DELETE,state); - state2 = count > 0 && VideoContext::Get()->IsLoaded(); - MenuBar->Enable(MENU_INSERT_BEFORE_VIDEO,state2); - MenuBar->Enable(MENU_INSERT_AFTER_VIDEO,state2); - MenuBar->Enable(Menu_Subtitles_Insert,state); - state = count > 0 && continuous; - MenuBar->Enable(MENU_DUPLICATE,state); - state = count > 0 && continuous && VideoContext::Get()->TimecodesLoaded(); - MenuBar->Enable(MENU_DUPLICATE_NEXT_FRAME,state); - state = count == 2; - MenuBar->Enable(MENU_SWAP,state); - state = count >= 2 && continuous; - MenuBar->Enable(MENU_JOIN_CONCAT,state); - MenuBar->Enable(MENU_JOIN_REPLACE,state); - MenuBar->Enable(MENU_JOIN_AS_KARAOKE,state); - MenuBar->Enable(Menu_Subtitles_Join,state); - state = (count == 2 || count == 3) && continuous; - MenuBar->Enable(MENU_RECOMBINE,state); - } - - // Timing menu - else if (curMenu == timingMenu) { - // Variables - bool continuous; - wxArrayInt sels = SubsGrid->GetSelection(&continuous); - int count = sels.Count(); - - // Video related - bool state = VideoContext::Get()->IsLoaded(); - MenuBar->Enable(Menu_Subs_Snap_Start_To_Video,state); - MenuBar->Enable(Menu_Subs_Snap_End_To_Video,state); - MenuBar->Enable(Menu_Video_Snap_To_Scene,state); - MenuBar->Enable(Menu_Video_Shift_To_Frame,state); - - // Other - state = count >= 2 && continuous; - MenuBar->Enable(MENU_ADJOIN,state); - MenuBar->Enable(MENU_ADJOIN2,state); - } - - // Edit menu - else if (curMenu == editMenu) { - // Undo state - wxMenuItem *item; - wxString undo_text = _("&Undo") + wxString(_T(" ")) + ass->GetUndoDescription() + wxString(_T("\t")) + Hotkeys.GetText(_T("Undo")); - item = editMenu->FindItem(Menu_Edit_Undo); - item->SetItemLabel(undo_text); - item->Enable(!ass->IsUndoStackEmpty()); - - // Redo state - wxString redo_text = _("&Redo") + wxString(_T(" ")) + ass->GetRedoDescription() + wxString(_T("\t")) + Hotkeys.GetText(_T("Redo")); - item = editMenu->FindItem(Menu_Edit_Redo); - item->SetItemLabel(redo_text); - item->Enable(!ass->IsRedoStackEmpty()); - - // Copy/cut/paste - wxArrayInt sels = SubsGrid->GetSelection(); - bool can_copy = (sels.Count() > 0); - - bool can_paste = true; - if (wxTheClipboard->Open()) { - can_paste = wxTheClipboard->IsSupported(wxDF_TEXT); - wxTheClipboard->Close(); - } - - MenuBar->Enable(Menu_Edit_Cut,can_copy); - MenuBar->Enable(Menu_Edit_Copy,can_copy); - MenuBar->Enable(Menu_Edit_Paste,can_paste); - MenuBar->Enable(Menu_Edit_Paste_Over,can_copy&&can_paste); - } - - // Automation menu -#ifdef WITH_AUTOMATION - else if (curMenu == automationMenu) { - // Remove old macro items - for (unsigned int i = 0; i < activeMacroItems.size(); i++) { - wxMenu *p = 0; - wxMenuItem *it = MenuBar->FindItem(Menu_Automation_Macro + i, &p); - if (it) - p->Delete(it); - } - activeMacroItems.clear(); - - // Add new ones - int added = 0; - added += AddMacroMenuItems(automationMenu, wxGetApp().global_scripts->GetMacros()); - added += AddMacroMenuItems(automationMenu, local_scripts->GetMacros()); - - // If none were added, show a ghosted notice - if (added == 0) { - automationMenu->Append(Menu_Automation_Macro, _("No Automation macros loaded"))->Enable(false); - activeMacroItems.push_back(0); - } - } -#endif - - MenuBar->Thaw(); -} - -/// @brief Macro menu creation helper -/// @param menu -/// @param macros -/// @return -int FrameMain::AddMacroMenuItems(wxMenu *menu, const std::vector ¯os) { -#ifdef WITH_AUTOMATION - if (macros.empty()) { - return 0; - } - - int id = activeMacroItems.size();; - for (std::vector::const_iterator i = macros.begin(); i != macros.end(); ++i) { - wxMenuItem * m = menu->Append(Menu_Automation_Macro + id, (*i)->GetName(), (*i)->GetDescription()); - m->Enable((*i)->Validate(SubsGrid->ass, SubsGrid->GetAbsoluteSelection(), SubsGrid->GetFirstSelRow())); - activeMacroItems.push_back(*i); - id++; - } - - return macros.size(); -#else - return 0; -#endif -} - -/// @brief Open recent subs menu entry -/// @param event -void FrameMain::OnOpenRecentSubs(wxCommandEvent &event) { - int number = event.GetId()-Menu_File_Recent; - LoadSubtitles(lagi_wxString(config::mru->GetEntry("Subtitle", number))); -} - -/// @brief Open recent video menu entry -/// @param event -void FrameMain::OnOpenRecentVideo(wxCommandEvent &event) { - int number = event.GetId()-Menu_Video_Recent; - LoadVideo(lagi_wxString(config::mru->GetEntry("Video", number))); -} - -/// @brief Open recent timecodes entry -/// @param event -void FrameMain::OnOpenRecentTimecodes(wxCommandEvent &event) { - int number = event.GetId()-Menu_Timecodes_Recent; - LoadVFR(lagi_wxString(config::mru->GetEntry("Timecodes", number))); -} - -/// @brief Open recent Keyframes entry -/// @param event -void FrameMain::OnOpenRecentKeyframes(wxCommandEvent &event) { - VideoContext::Get()->LoadKeyframes(lagi_wxString(config::mru->GetEntry("Keyframes", event.GetId()-Menu_Keyframes_Recent))); -} - -/// @brief Open recent audio menu entry -/// @param event -void FrameMain::OnOpenRecentAudio(wxCommandEvent &event) { - audioController->OpenAudio(lagi_wxString(config::mru->GetEntry("Audio", event.GetId()-Menu_Audio_Recent))); -} - -/// @brief Open new Window -void FrameMain::OnNewWindow(wxCommandEvent&) { - RestartAegisub(); -} - -/// @brief Exit -void FrameMain::OnExit(wxCommandEvent&) { - Close(); -} - -/// @brief Open about box -void FrameMain::OnAbout(wxCommandEvent &) { - AboutScreen About(this); - About.ShowModal(); -} - - -/// @brief Open log window -void FrameMain::OnLog(wxCommandEvent &) { - LogWindow *log = new LogWindow(this); - log->Show(1); -} - -/// @brief Open check updates -void FrameMain::OnCheckUpdates(wxCommandEvent &) { - PerformVersionCheck(true); -} - -/// @brief Open help topics -void FrameMain::OnContents(wxCommandEvent&) { - OpenHelp(_T("")); -} - -/// @brief Open help files on OSX. -/// @param event -void FrameMain::OnFiles(wxCommandEvent&) { -#ifdef __WXMAC__ - char *shared_path = agi::util::OSX_GetBundleSharedSupportDirectory(); - wxString help_path = wxString::Format(_T("%s/doc"), wxString(shared_path, wxConvUTF8).c_str()); - agi::util::OSX_OpenLocation(help_path.c_str()); - free(shared_path); -#endif -} - -/// @brief Open website -void FrameMain::OnWebsite(wxCommandEvent&) { - AegisubApp::OpenURL(_T("http://www.aegisub.org/")); -} - -/// @brief Open forums -void FrameMain::OnForums(wxCommandEvent&) { - AegisubApp::OpenURL(_T("http://forum.aegisub.org/")); -} - -/// @brief Open bugtracker -void FrameMain::OnBugTracker(wxCommandEvent&) { - if (wxGetMouseState().CmdDown()) { - if (wxGetMouseState().ShiftDown()) { - wxMessageBox(_T("Now crashing with an access violation...")); - for (char *foo = (char*)0;;) *foo++ = 42; - } - else { - wxMessageBox(_T("Now crashing with an unhandled exception...")); - throw this; - } - } - - AegisubApp::OpenURL(_T("http://devel.aegisub.org/")); -} - -/// @brief Open IRC channel -void FrameMain::OnIRCChannel(wxCommandEvent&) { - AegisubApp::OpenURL(_T("irc://irc.rizon.net/aegisub")); -} - -/// @brief Play video -void FrameMain::OnVideoPlay(wxCommandEvent &) { - VideoContext::Get()->Play(); -} - - -/// @brief Open video -void FrameMain::OnOpenVideo(wxCommandEvent&) { - wxString path = lagi_wxString(OPT_GET("Path/Last/Video")->GetString()); - wxString str = wxString(_("Video Formats")) + _T(" (*.avi,*.mkv,*.mp4,*.avs,*.d2v,*.ogm,*.mpeg,*.mpg,*.vob,*.mov)|*.avi;*.avs;*.d2v;*.mkv;*.ogm;*.mp4;*.mpeg;*.mpg;*.vob;*.mov|") - + _("All Files") + _T(" (*.*)|*.*"); - wxString filename = wxFileSelector(_("Open video file"),path,_T(""),_T(""),str,wxFD_OPEN | wxFD_FILE_MUST_EXIST); - if (!filename.empty()) { - LoadVideo(filename); - OPT_SET("Path/Last/Video")->SetString(STD_STR(filename)); - } -} - -/// @brief Close video -void FrameMain::OnCloseVideo(wxCommandEvent&) { - LoadVideo(_T("")); -} - -/// @brief Open Audio -void FrameMain::OnOpenAudio (wxCommandEvent&) { - wxString path = lagi_wxString(OPT_GET("Path/Last/Audio")->GetString()); - wxString str = wxString(_("Audio Formats")) + _T(" (*.wav,*.mp3,*.ogg,*.flac,*.mp4,*.ac3,*.aac,*.mka,*.m4a,*.w64)|*.wav;*.mp3;*.ogg;*.flac;*.mp4;*.ac3;*.aac;*.mka;*.m4a;*.w64|") - + _("Video Formats") + _T(" (*.avi,*.mkv,*.ogm,*.mpg,*.mpeg)|*.avi;*.mkv;*.ogm;*.mp4;*.mpeg;*.mpg|") - + _("All files") + _T(" (*.*)|*.*"); - wxString filename = wxFileSelector(_("Open audio file"),path,_T(""),_T(""),str,wxFD_OPEN | wxFD_FILE_MUST_EXIST); - if (!filename.empty()) { - audioController->OpenAudio(filename); - OPT_SET("Path/Last/Audio")->SetString(STD_STR(filename)); - } -} - -/// @brief DOCME -void FrameMain::OnOpenAudioFromVideo (wxCommandEvent&) { - audioController->OpenAudio(_T("audio-video:cache")); -} - -/// @brief DOCME -void FrameMain::OnCloseAudio (wxCommandEvent&) { - audioController->CloseAudio(); -} - - -/// @brief Event handler for audio display renderer selection menu options -/// @param event wxWidgets event object -void FrameMain::OnAudioDisplayMode (wxCommandEvent &event) { - OPT_SET("Audio/Spectrum")->SetBool(event.GetId() == Menu_Audio_Spectrum); -} - -#ifdef _DEBUG - -/// @brief DOCME -void FrameMain::OnOpenDummyAudio (wxCommandEvent&) { - audioController->OpenAudio(_T("dummy-audio:silence?sr=44100&bd=16&ch=1&ln=396900000")); -} - -/// @brief DOCME -void FrameMain::OnOpenDummyNoiseAudio (wxCommandEvent&) { - audioController->OpenAudio(_T("dummy-audio:noise?sr=44100&bd=16&ch=1&ln=396900000")); -} -#endif - - - -/// @brief Open subtitles -void FrameMain::OnOpenSubtitles(wxCommandEvent&) { - wxString path = lagi_wxString(OPT_GET("Path/Last/Subtitles")->GetString()); - wxString filename = wxFileSelector(_("Open subtitles file"),path,_T(""),_T(""),AssFile::GetWildcardList(0),wxFD_OPEN | wxFD_FILE_MUST_EXIST); - if (!filename.empty()) { - LoadSubtitles(filename); - wxFileName filepath(filename); - OPT_SET("Path/Last/Subtitles")->SetString(STD_STR(filepath.GetPath())); - } -} - -/// @brief Open subtitles with specific charset -void FrameMain::OnOpenSubtitlesCharset(wxCommandEvent&) { - // Initialize charsets - wxString path = lagi_wxString(OPT_GET("Path/Last/Subtitles")->GetString()); - - // Get options and load - wxString filename = wxFileSelector(_("Open subtitles file"),path,_T(""),_T(""),AssFile::GetWildcardList(0),wxFD_OPEN | wxFD_FILE_MUST_EXIST); - if (!filename.empty()) { - wxString charset = wxGetSingleChoice(_("Choose charset code:"), _("Charset"),agi::charset::GetEncodingsList(),this,-1, -1,true,250,200); - if (!charset.empty()) { - LoadSubtitles(filename,charset); - } - OPT_SET("Path/Last/Subtitles")->SetString(STD_STR(filename)); - } -} - -/// @brief Open subtitles from the currently open video file -void FrameMain::OnOpenSubtitlesVideo(wxCommandEvent&) { - LoadSubtitles(VideoContext::Get()->videoName, "binary"); -} - -/// @brief Save subtitles as -void FrameMain::OnSaveSubtitlesAs(wxCommandEvent&) { - SaveSubtitles(true); -} - -/// @brief Save subtitles -void FrameMain::OnSaveSubtitles(wxCommandEvent&) { - SaveSubtitles(false); -} - -/// @brief Save subtitles with specific charset -void FrameMain::OnSaveSubtitlesCharset(wxCommandEvent&) { - SaveSubtitles(true,true); -} - -/// @brief Close subtitles -void FrameMain::OnNewSubtitles(wxCommandEvent&) { - LoadSubtitles(_T("")); -} - -/// @brief Export subtitles -void FrameMain::OnExportSubtitles(wxCommandEvent &) { -#ifdef WITH_AUTOMATION - int autoreload = OPT_GET("Automation/Autoreload Mode")->GetInt(); - if (autoreload & 1) { - // Local scripts - const std::vector scripts = local_scripts->GetScripts(); - for (size_t i = 0; i < scripts.size(); ++i) { - try { - scripts[i]->Reload(); - } - catch (const wchar_t *e) { - wxLogError(_T("Error while reloading Automation scripts before export: %s"), e); - } - catch (...) { - wxLogError(_T("An unknown error occurred reloading Automation script '%s'."), scripts[i]->GetName().c_str()); - } - } - } - if (autoreload & 2) { - // Global scripts - wxGetApp().global_scripts->Reload(); - } -#endif - - DialogExport exporter(this, ass); - exporter.ShowModal(); -} - -/// @brief Open VFR tags -void FrameMain::OnOpenVFR(wxCommandEvent &) { - wxString path = lagi_wxString(OPT_GET("Path/Last/Timecodes")->GetString()); - wxString str = wxString(_("All Supported Types")) + _T("(*.txt)|*.txt|") - + _("All Files") + _T(" (*.*)|*.*"); - wxString filename = wxFileSelector(_("Open timecodes file"),path,_T(""),_T(""),str,wxFD_OPEN | wxFD_FILE_MUST_EXIST); - if (!filename.empty()) { - LoadVFR(filename); - OPT_SET("Path/Last/Timecodes")->SetString(STD_STR(filename)); - } -} - -/// @brief Save VFR tags -void FrameMain::OnSaveVFR(wxCommandEvent &) { - wxString path = lagi_wxString(OPT_GET("Path/Last/Timecodes")->GetString()); - wxString str = wxString(_("All Supported Types")) + _T("(*.txt)|*.txt|") - + _("All Files") + _T(" (*.*)|*.*"); - wxString filename = wxFileSelector(_("Save timecodes file"),path,_T(""),_T(""),str,wxFD_SAVE | wxFD_OVERWRITE_PROMPT); - if (!filename.empty()) { - VideoContext::Get()->SaveTimecodes(filename); - OPT_SET("Path/Last/Timecodes")->SetString(STD_STR(filename)); - } -} - - -/// @brief Close VFR tags -void FrameMain::OnCloseVFR(wxCommandEvent &) { - LoadVFR(""); -} - -/// @brief Open keyframes -void FrameMain::OnOpenKeyframes (wxCommandEvent &) { - // Pick file - wxString path = lagi_wxString(OPT_GET("Path/Last/Keyframes")->GetString()); - wxString filename = wxFileSelector( - _T("Select the keyframes file to open"), - path, - _T("") - ,_T(".txt"), - _T("All supported formats (*.txt, *.pass, *.stats, *.log)|*.txt;*.pass;*.stats;*.log|All files (*.*)|*.*"), - wxFD_FILE_MUST_EXIST | wxFD_OPEN); - - if (filename.empty()) return; - OPT_SET("Path/Last/Keyframes")->SetString(STD_STR(filename)); - - // Load - VideoContext::Get()->LoadKeyframes(filename); -} - -/// @brief Close keyframes -void FrameMain::OnCloseKeyframes (wxCommandEvent &) { - VideoContext::Get()->CloseKeyframes(); -} - -/// @brief Save keyframes -void FrameMain::OnSaveKeyframes (wxCommandEvent &) { - // Pick file - wxString path = lagi_wxString(OPT_GET("Path/Last/Keyframes")->GetString()); - wxString filename = wxFileSelector(_T("Select the Keyframes file to open"),path,_T(""),_T("*.key.txt"),_T("Text files (*.txt)|*.txt"),wxFD_OVERWRITE_PROMPT | wxFD_SAVE); - if (filename.IsEmpty()) return; - OPT_SET("Path/Last/Keyframes")->SetString(STD_STR(filename)); - - VideoContext::Get()->SaveKeyframes(filename); -} - -/// @brief Zoom levels -void FrameMain::OnSetZoom50(wxCommandEvent&) { - VideoContext::Get()->Stop(); - videoBox->videoDisplay->SetZoom(.5); -} - - -/// @brief DOCME -void FrameMain::OnSetZoom100(wxCommandEvent&) { - VideoContext::Get()->Stop(); - videoBox->videoDisplay->SetZoom(1.); -} - - -/// @brief DOCME -void FrameMain::OnSetZoom200(wxCommandEvent&) { - VideoContext::Get()->Stop(); - videoBox->videoDisplay->SetZoom(2.); -} - - -/// @brief DOCME -void FrameMain::OnZoomIn (wxCommandEvent &) { - VideoContext::Get()->Stop(); - videoBox->videoDisplay->SetZoom(videoBox->videoDisplay->GetZoom() + .125); -} - - -/// @brief DOCME -void FrameMain::OnZoomOut (wxCommandEvent &) { - VideoContext::Get()->Stop(); - videoBox->videoDisplay->SetZoom(videoBox->videoDisplay->GetZoom() - .125); -} - - -/// @brief DOCME -void FrameMain::OnSetZoom(wxCommandEvent &) { - videoBox->videoDisplay->SetZoomFromBox(); -} - -/// @brief Detach video -void FrameMain::OnDetachVideo(wxCommandEvent &) { - DetachVideo(!detachedVideo); -} - -/// @brief Use dummy video -void FrameMain::OnDummyVideo (wxCommandEvent &) { - wxString fn; - if (DialogDummyVideo::CreateDummyVideo(this, fn)) { - LoadVideo(fn); - } -} - -/// @brief Overscan toggle -void FrameMain::OnOverscan (wxCommandEvent &event) { - OPT_SET("Video/Overscan Mask")->SetBool(event.IsChecked()); - VideoContext::Get()->Stop(); - videoBox->videoDisplay->Render(); -} - -/// @brief Show video details -void FrameMain::OnOpenVideoDetails (wxCommandEvent &) { - VideoContext::Get()->Stop(); - DialogVideoDetails videodetails(this); - videodetails.ShowModal(); -} - -/// @brief Open jump to dialog -void FrameMain::OnJumpTo(wxCommandEvent&) { - VideoContext::Get()->Stop(); - if (VideoContext::Get()->IsLoaded()) { - DialogJumpTo JumpTo(this); - JumpTo.ShowModal(); - videoBox->videoSlider->SetFocus(); - } -} - -/// @brief Open shift dialog -void FrameMain::OnShift(wxCommandEvent&) { - VideoContext::Get()->Stop(); - DialogShiftTimes Shift(this,SubsGrid); - Shift.ShowModal(); -} - -/// @brief Open properties -void FrameMain::OnOpenProperties (wxCommandEvent &) { - VideoContext::Get()->Stop(); - DialogProperties Properties(this, ass); - Properties.ShowModal(); -} - -/// @brief Open styles manager -void FrameMain::OnOpenStylesManager(wxCommandEvent&) { - VideoContext::Get()->Stop(); - DialogStyleManager StyleManager(this,SubsGrid); - StyleManager.ShowModal(); -} - -/// @brief Open attachments -void FrameMain::OnOpenAttachments(wxCommandEvent&) { - VideoContext::Get()->Stop(); - DialogAttachments attachments(this, ass); - attachments.ShowModal(); -} - -/// @brief Open translation assistant -void FrameMain::OnOpenTranslation(wxCommandEvent&) { - VideoContext::Get()->Stop(); - int start = SubsGrid->GetFirstSelRow(); - if (start == -1) start = 0; - DialogTranslation Trans(this,ass,SubsGrid,start,true); - Trans.ShowModal(); -} - -/// @brief Open Spell Checker -void FrameMain::OnOpenSpellCheck (wxCommandEvent &) { - VideoContext::Get()->Stop(); - new DialogSpellChecker(this); -} - -/// @brief Open Fonts Collector -void FrameMain::OnOpenFontsCollector (wxCommandEvent &) { - VideoContext::Get()->Stop(); - DialogFontsCollector Collector(this, ass); - Collector.ShowModal(); -} - -/// @brief Open Resolution Resampler -void FrameMain::OnOpenResample (wxCommandEvent &) { - VideoContext::Get()->Stop(); - DialogResample diag(this, SubsGrid); - diag.ShowModal(); -} - -/// @brief Open Timing post-processor dialog -void FrameMain::OnOpenTimingProcessor (wxCommandEvent &) { - DialogTimingProcessor timing(this,SubsGrid); - timing.ShowModal(); -} - -/// @brief Open Kanji Timer dialog -void FrameMain::OnOpenKanjiTimer (wxCommandEvent &) { - DialogKanjiTimer kanjitimer(this,SubsGrid); - kanjitimer.ShowModal(); -} - -/// @brief Open Options dialog -void FrameMain::OnOpenPreferences (wxCommandEvent &) { - try { - Preferences pref(this); - pref.ShowModal(); - - } catch (agi::Exception& e) { - LOG_E("dialog/preferences") << "Caught exception: " << e.GetName() << " -> " << e.GetMessage(); - } -} - -/// @brief Launch ASSDraw -void FrameMain::OnOpenASSDraw (wxCommandEvent &) { - wxExecute(_T("\"") + StandardPaths::DecodePath(_T("?data/ASSDraw3.exe")) + _T("\"")); -} - -/// @brief Open Automation -void FrameMain::OnOpenAutomation (wxCommandEvent &) { -#ifdef WITH_AUTOMATION -#ifdef __APPLE__ - if (wxGetMouseState().CmdDown()) { -#else - if (wxGetMouseState().ControlDown()) { -#endif - wxGetApp().global_scripts->Reload(); - if (wxGetMouseState().ShiftDown()) { - const std::vector scripts = local_scripts->GetScripts(); - for (size_t i = 0; i < scripts.size(); ++i) { - try { - scripts[i]->Reload(); - } - catch (const wchar_t *e) { - wxLogError(e); - } - catch (...) { - wxLogError(_T("An unknown error occurred reloading Automation script '%s'."), scripts[i]->GetName().c_str()); - } - } - - StatusTimeout(_("Reloaded all Automation scripts")); - } - else { - StatusTimeout(_("Reloaded autoload Automation scripts")); - } - } - else { - VideoContext::Get()->Stop(); - DialogAutomation dlg(this, local_scripts); - dlg.ShowModal(); - } -#endif -} - -/// @brief General handler for all Automation-generated menu items -/// @param event -void FrameMain::OnAutomationMacro (wxCommandEvent &event) { -#ifdef WITH_AUTOMATION - SubsGrid->BeginBatch(); - // First get selection data - std::vector selected_lines = SubsGrid->GetAbsoluteSelection(); - int first_sel = SubsGrid->GetFirstSelRow(); - // Run the macro... - activeMacroItems[event.GetId()-Menu_Automation_Macro]->Process(SubsGrid->ass, selected_lines, first_sel, this); - SubsGrid->SetSelectionFromAbsolute(selected_lines); - SubsGrid->EndBatch(); -#endif -} - -/// @brief Snap subs to video -void FrameMain::OnSnapSubsStartToVid (wxCommandEvent &) { - SubsGrid->SetSubsToVideo(true); -} - -/// @brief DOCME -void FrameMain::OnSnapSubsEndToVid (wxCommandEvent &) { - SubsGrid->SetSubsToVideo(false); -} - -/// @brief Jump video to subs -void FrameMain::OnSnapVidToSubsStart (wxCommandEvent &) { - SubsGrid->SetVideoToSubs(true); -} - - -/// @brief DOCME -void FrameMain::OnSnapVidToSubsEnd (wxCommandEvent &) { - SubsGrid->SetVideoToSubs(false); -} - -/// @brief Snap to scene -void FrameMain::OnSnapToScene (wxCommandEvent &) { - VideoContext *con = VideoContext::Get(); - if (!con->IsLoaded() || !con->KeyFramesLoaded()) return; - - // Get frames - wxArrayInt sel = SubsGrid->GetSelection(); - int curFrame = con->GetFrameN(); - int prev = 0; - int next = 0; - - const std::vector &keyframes = con->GetKeyFrames(); - if (curFrame < keyframes.front()) { - next = keyframes.front(); - } - else if (curFrame >= keyframes.back()) { - prev = keyframes.back(); - next = con->GetLength(); - } - else { - std::vector::const_iterator kf = std::lower_bound(keyframes.begin(), keyframes.end(), curFrame); - if (*kf == curFrame) { - prev = *kf; - next = *(kf + 1); - } - else { - prev = *(kf - 1); - next = *kf; - } - } - - // Get times - int start_ms = con->TimeAtFrame(prev,agi::vfr::START); - int end_ms = con->TimeAtFrame(next-1,agi::vfr::END); - AssDialogue *cur; - - // Update rows - for (size_t i=0;iGetDialogue(sel[i]); - cur->Start.SetMS(start_ms); - cur->End.SetMS(end_ms); - } - - // Commit - SubsGrid->ass->Commit(_("snap to scene"), AssFile::COMMIT_TIMES); -} - -/// @brief Shift to frame -void FrameMain::OnShiftToFrame (wxCommandEvent &) { - if (!VideoContext::Get()->IsLoaded()) return; - - wxArrayInt sels = SubsGrid->GetSelection(); - size_t n=sels.Count(); - if (n == 0) return; - - // Get shifting in ms - AssDialogue *cur = SubsGrid->GetDialogue(sels[0]); - if (!cur) return; - int shiftBy = VideoContext::Get()->TimeAtFrame(VideoContext::Get()->GetFrameN(),agi::vfr::START) - cur->Start.GetMS(); - - // Update - for (size_t i=0;iGetDialogue(sels[i]); - if (cur) { - cur->Start.SetMS(cur->Start.GetMS()+shiftBy); - cur->End.SetMS(cur->End.GetMS()+shiftBy); - } - } - - // Commit - SubsGrid->ass->Commit(_("shift to frame"), AssFile::COMMIT_TIMES); -} - -/// @brief Undo -void FrameMain::OnUndo(wxCommandEvent&) { - VideoContext::Get()->Stop(); - ass->Undo(); -} - -/// @brief Redo -void FrameMain::OnRedo(wxCommandEvent&) { - VideoContext::Get()->Stop(); - ass->Redo(); -} - -/// @brief Find -void FrameMain::OnFind(wxCommandEvent &) { - VideoContext::Get()->Stop(); - Search.OpenDialog(false); -} - -/// @brief Find next -void FrameMain::OnFindNext(wxCommandEvent &) { - VideoContext::Get()->Stop(); - Search.FindNext(); -} - -/// @brief Find & replace -void FrameMain::OnReplace(wxCommandEvent &) { - VideoContext::Get()->Stop(); - Search.OpenDialog(true); -} - -/// @brief Change aspect ratio to default -void FrameMain::OnSetARDefault (wxCommandEvent &) { - VideoContext::Get()->Stop(); - VideoContext::Get()->SetAspectRatio(0); - SetDisplayMode(1,-1); -} - -/// @brief Change aspect ratio to fullscreen -void FrameMain::OnSetARFull (wxCommandEvent &) { - VideoContext::Get()->Stop(); - VideoContext::Get()->SetAspectRatio(1); - SetDisplayMode(1,-1); -} - -/// @brief Change aspect ratio to widescreen -void FrameMain::OnSetARWide (wxCommandEvent &) { - VideoContext::Get()->Stop(); - VideoContext::Get()->SetAspectRatio(2); - SetDisplayMode(1,-1); -} - -/// @brief Change aspect ratio to 2:35 -void FrameMain::OnSetAR235 (wxCommandEvent &) { - VideoContext::Get()->Stop(); - VideoContext::Get()->SetAspectRatio(3); - SetDisplayMode(1,-1); -} - -/// @brief Change aspect ratio to a custom value -void FrameMain::OnSetARCustom (wxCommandEvent &) { - VideoContext::Get()->Stop(); - - wxString value = wxGetTextFromUser(_("Enter aspect ratio in either:\n decimal (e.g. 2.35)\n fractional (e.g. 16:9)\n specific resolution (e.g. 853x480)"),_("Enter aspect ratio"),AegiFloatToString(VideoContext::Get()->GetAspectRatioValue())); - if (value.IsEmpty()) return; - - value.MakeLower(); - - // Process text - double numval; - if (value.ToDouble(&numval)) { - //Nothing to see here, move along - } - else { - double a,b; - int pos=0; - bool scale=false; - - //Why bloat using Contains when we can just check the output of Find? - pos = value.Find(':'); - if (pos==wxNOT_FOUND) pos = value.Find('/'); - if (pos==wxNOT_FOUND&&value.Contains(_T('x'))) { - pos = value.Find('x'); - scale=true; - } - - if (pos>0) { - wxString num = value.Left(pos); - wxString denum = value.Mid(pos+1); - if (num.ToDouble(&a) && denum.ToDouble(&b) && b!=0) { - numval = a/b; - if (scale) videoBox->videoDisplay->SetZoom(b / VideoContext::Get()->GetHeight()); - } - } - else numval = 0.0; - } - - // Sanity check - if (numval < 0.5 || numval > 5.0) wxMessageBox(_("Invalid value! Aspect ratio must be between 0.5 and 5.0."),_("Invalid Aspect Ratio"),wxICON_ERROR|wxOK); - - // Set value - else { - VideoContext::Get()->SetAspectRatio(4,numval); - SetDisplayMode(1,-1); - } -} - -/// @brief Window is attempted to be closed -/// @param event -void FrameMain::OnCloseWindow (wxCloseEvent &event) { - // Stop audio and video - VideoContext::Get()->Stop(); - audioController->Stop(); - - // Ask user if he wants to save first - bool canVeto = event.CanVeto(); - int result = TryToCloseSubs(canVeto); - - // Store maximization state - OPT_SET("App/Maximized")->SetBool(IsMaximized()); - - // Abort/destroy - if (canVeto) { - if (result == wxCANCEL) event.Veto(); - else Destroy(); - } - else Destroy(); -} - -/// @brief Cut/copy/paste -void FrameMain::OnCut (wxCommandEvent &) { - if (FindFocus() == EditBox->TextEdit) { - EditBox->TextEdit->Cut(); - return; - } - SubsGrid->CutLines(SubsGrid->GetSelection()); -} - - -/// @brief DOCME -void FrameMain::OnCopy (wxCommandEvent &) { - if (FindFocus() == EditBox->TextEdit) { - EditBox->TextEdit->Copy(); - return; - } - SubsGrid->CopyLines(SubsGrid->GetSelection()); -} - - -/// @brief DOCME -void FrameMain::OnPaste (wxCommandEvent &) { - if (FindFocus() == EditBox->TextEdit) { - EditBox->TextEdit->Paste(); - return; - } - SubsGrid->PasteLines(SubsGrid->GetFirstSelRow()); -} - -/// @brief Paste over -void FrameMain::OnPasteOver (wxCommandEvent &) { - SubsGrid->PasteLines(SubsGrid->GetFirstSelRow(),true); -} - -/// @brief Select visible lines -void FrameMain::OnSelectVisible (wxCommandEvent &) { - VideoContext::Get()->Stop(); - SubsGrid->SelectVisible(); -} - -/// @brief Open select dialog -void FrameMain::OnSelect (wxCommandEvent &) { - VideoContext::Get()->Stop(); - DialogSelection select(this, SubsGrid); - select.ShowModal(); -} - -/// @brief Sort subtitles by start time -void FrameMain::OnSortStart (wxCommandEvent &) { - ass->Sort(); - ass->Commit(_("sort")); -} -/// @brief Sort subtitles by end time -void FrameMain::OnSortEnd (wxCommandEvent &) { - ass->Sort(AssFile::CompEnd); - ass->Commit(_("sort")); -} -/// @brief Sort subtitles by style name -void FrameMain::OnSortStyle (wxCommandEvent &) { - ass->Sort(AssFile::CompStyle); - ass->Commit(_("sort")); -} - -/// @brief Open styling assistant -void FrameMain::OnOpenStylingAssistant (wxCommandEvent &) { - VideoContext::Get()->Stop(); - if (!stylingAssistant) stylingAssistant = new DialogStyling(this,SubsGrid); - stylingAssistant->Show(true); -} - -/// @brief Autosave the currently open file, if any -void FrameMain::OnAutoSave(wxTimerEvent &) { - try { - if (ass->loaded && ass->IsModified()) { - // Set path - wxFileName origfile(ass->filename); - wxString path = lagi_wxString(OPT_GET("Path/Auto/Save")->GetString()); - if (path.IsEmpty()) path = origfile.GetPath(); - wxFileName dstpath(path); - if (!dstpath.IsAbsolute()) path = StandardPaths::DecodePathMaybeRelative(path, _T("?user/")); - dstpath.AssignDir(path); - if (!dstpath.DirExists()) wxMkdir(path); - - wxString name = origfile.GetName(); - if (name.IsEmpty()) { - dstpath.SetFullName("Untitled.AUTOSAVE.ass"); - } - else { - dstpath.SetFullName(name + L".AUTOSAVE.ass"); - } - - ass->Save(dstpath.GetFullPath(),false,false); - - // Set status bar - StatusTimeout(_("File backup saved as \"") + dstpath.GetFullPath() + _T("\".")); - } - } - catch (const agi::Exception& err) { - StatusTimeout(lagi_wxString("Exception when attempting to autosave file: " + err.GetMessage())); - } - catch (wxString err) { - StatusTimeout(_T("Exception when attempting to autosave file: ") + err); - } - catch (const wchar_t *err) { - StatusTimeout(_T("Exception when attempting to autosave file: ") + wxString(err)); - } - catch (...) { - StatusTimeout(_T("Unhandled exception when attempting to autosave file.")); - } -} - -/// @brief Clear statusbar -void FrameMain::OnStatusClear(wxTimerEvent &) { - SetStatusText(_T(""),1); -} - -/// @brief Next frame hotkey -void FrameMain::OnNextFrame(wxCommandEvent &) { - videoBox->videoSlider->NextFrame(); -} - -/// @brief Previous frame hotkey -void FrameMain::OnPrevFrame(wxCommandEvent &) { - videoBox->videoSlider->PrevFrame(); -} - -/// @brief Toggle focus between seek bar and whatever else -void FrameMain::OnFocusSeek(wxCommandEvent &) { - wxWindow *curFocus = wxWindow::FindFocus(); - if (curFocus == videoBox->videoSlider) { - if (PreviousFocus) PreviousFocus->SetFocus(); - } - else { - PreviousFocus = curFocus; - videoBox->videoSlider->SetFocus(); - } -} - -/// @brief Previous line hotkey -void FrameMain::OnPrevLine(wxCommandEvent &) { - SubsGrid->PrevLine(); -} - -/// @brief Next line hotkey -void FrameMain::OnNextLine(wxCommandEvent &) { - SubsGrid->NextLine(); -} - -/// @brief Cycle through tag hiding modes -void FrameMain::OnToggleTags(wxCommandEvent &) { - int tagMode = OPT_GET("Subtitle/Grid/Hide Overrides")->GetInt(); - - // Cycle to next - tagMode = (tagMode+1)%3; - - // Show on status bar - wxString message = _("ASS Override Tag mode set to "); - if (tagMode == 0) message += _("show full tags."); - if (tagMode == 1) message += _("simplify tags."); - if (tagMode == 2) message += _("hide tags."); - StatusTimeout(message,10000); - - // Set option - OPT_SET("Subtitle/Grid/Hide Overrides")->SetInt(tagMode); - - // Refresh grid - SubsGrid->Refresh(false); -} -void FrameMain::OnSetTags(wxCommandEvent &event) { - OPT_SET("Subtitle/Grid/Hide Overrides")->SetInt(event.GetId() - Menu_View_FullTags); - SubsGrid->Refresh(false); -} - -/// @brief Choose a different language -void FrameMain::OnChooseLanguage (wxCommandEvent &) { - // Get language - AegisubApp *app = (AegisubApp*) wxTheApp; - int old = app->locale.curCode; - int newCode = app->locale.PickLanguage(); - - // Is OK? - if (newCode != -1) { - // Set code - OPT_SET("App/Locale")->SetInt(newCode); - - // Language actually changed? - if (newCode != old) { - // Ask to restart program - int result = wxMessageBox(_T("Aegisub needs to be restarted so that the new language can be applied. Restart now?"),_T("Restart Aegisub?"),wxICON_QUESTION | wxYES_NO); - if (result == wxYES) { - // Restart Aegisub - if (Close()) { - RestartAegisub(); - //wxStandardPaths stand; - //wxExecute(_T("\"") + stand.GetExecutablePath() + _T("\"")); - } - } - } - } -} - -/// @brief View standard -void FrameMain::OnViewStandard (wxCommandEvent &) { - if (!audioController->IsAudioOpen() || !VideoContext::Get()->IsLoaded()) return; - SetDisplayMode(1,1); -} - -/// @brief View video -void FrameMain::OnViewVideo (wxCommandEvent &) { - SetDisplayMode(1,0); -} - -/// @brief View audio -void FrameMain::OnViewAudio (wxCommandEvent &) { - if (!audioController->IsAudioOpen()) return; - SetDisplayMode(0,1); -} - -/// @brief View subs -void FrameMain::OnViewSubs (wxCommandEvent &) { - SetDisplayMode(0,0); -} - -/// @brief Medusa shortcuts -void FrameMain::OnMedusaPlay(wxCommandEvent &) { - audioController->PlayPrimaryRange(); -} - -/// @brief DOCME -void FrameMain::OnMedusaStop(wxCommandEvent &) { - // Playing, stop - if (audioController->IsPlaying()) { - audioController->Stop(); - } - - // Otherwise, play the last 500 ms - else { - SampleRange sel(audioController->GetPrimaryPlaybackRange()); - audioController->PlayRange(SampleRange( - sel.end() - audioController->SamplesFromMilliseconds(500), - sel.end()));; - } -} - -/// @brief DOCME -void FrameMain::OnMedusaShiftStartForward(wxCommandEvent &) { - SampleRange newsel( - audioController->GetPrimaryPlaybackRange(), - audioController->SamplesFromMilliseconds(10), - 0); - /// @todo Make this use the timing controller instead - //audioController->SetSelection(newsel); -} - -/// @brief DOCME -void FrameMain::OnMedusaShiftStartBack(wxCommandEvent &) { - SampleRange newsel( - audioController->GetPrimaryPlaybackRange(), - -audioController->SamplesFromMilliseconds(10), - 0); - /// @todo Make this use the timing controller instead - //audioController->SetSelection(newsel); -} - -/// @brief DOCME -void FrameMain::OnMedusaShiftEndForward(wxCommandEvent &) { - SampleRange newsel( - audioController->GetPrimaryPlaybackRange(), - 0, - audioController->SamplesFromMilliseconds(10)); - /// @todo Make this use the timing controller instead - //audioController->SetSelection(newsel); -} - -/// @brief DOCME -void FrameMain::OnMedusaShiftEndBack(wxCommandEvent &) { - SampleRange newsel( - audioController->GetPrimaryPlaybackRange(), - 0, - -audioController->SamplesFromMilliseconds(10)); - /// @todo Make this use the timing controller instead - //audioController->SetSelection(newsel); -} - -/// @brief DOCME -void FrameMain::OnMedusaPlayBefore(wxCommandEvent &) { - SampleRange sel(audioController->GetPrimaryPlaybackRange()); - audioController->PlayRange(SampleRange( - sel.begin() - audioController->SamplesFromMilliseconds(500), - sel.begin()));; -} - -/// @brief DOCME -void FrameMain::OnMedusaPlayAfter(wxCommandEvent &) { - SampleRange sel(audioController->GetPrimaryPlaybackRange()); - audioController->PlayRange(SampleRange( - sel.end(), - sel.end() + audioController->SamplesFromMilliseconds(500)));; -} - -/// @brief DOCME -void FrameMain::OnMedusaNext(wxCommandEvent &) { - /// @todo Figure out how to handle this in the audio controller - //audioBox->audioDisplay->Next(false); -} - -/// @brief DOCME -void FrameMain::OnMedusaPrev(wxCommandEvent &) { - /// @todo Figure out how to handle this in the audio controller - //audioBox->audioDisplay->Prev(false); -} - -/// @brief DOCME -void FrameMain::OnMedusaEnter(wxCommandEvent &) { - /// @todo Figure out how to handle this in the audio controller - //audioBox->audioDisplay->CommitChanges(true); -} - -void FrameMain::OnAudioBoxResize(wxSashEvent &event) -{ - if (event.GetDragStatus() == wxSASH_STATUS_OUT_OF_RANGE) - return; - - wxRect rect = event.GetDragRect(); - - if (rect.GetHeight() < audioSash->GetMinimumSizeY()) - rect.SetHeight(audioSash->GetMinimumSizeY()); - - audioBox->SetMinSize(wxSize(-1, rect.GetHeight())); - Panel->Layout(); - Refresh(); -} - -void FrameMain::OnAudioOpen(AudioProvider *provider) -{ - SetDisplayMode(-1, 1); -} - -void FrameMain::OnAudioClose() -{ - SetDisplayMode(-1, 0); -} - -void FrameMain::OnSubtitlesFileChanged() { - if (OPT_GET("App/Auto/Save on Every Change")->GetBool()) { - if (ass->IsModified() && !ass->filename.empty()) SaveSubtitles(false); - } - - UpdateTitle(); -} diff --git a/aegisub/src/hotkey.cpp b/aegisub/src/hotkey.cpp new file mode 100644 index 000000000..7b4fc52ea --- /dev/null +++ b/aegisub/src/hotkey.cpp @@ -0,0 +1,176 @@ +// Copyright (c) 2010, Amar Takhar +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// $Id$ + +/// @file hotkey.cpp +/// @brief Hotkey handler +/// @ingroup hotkey menu event window + +#include "config.h" + +#ifndef AGI_PRE +#include + +#include +#endif + +#include +#include +#include +#include + +#include "aegisub/hotkey.h" + +#include "aegisub/toolbar.h" +#include "libresrc/libresrc.h" +#include "command/command.h" + + +namespace hotkey { + +typedef std::pair KCNamePair; + +KCNameMap kc_name_map; + + +void check(std::string context, int key_code, wchar_t key_char, int modifier) { + std::string combo; + if ((modifier != wxMOD_NONE)) { + if ((modifier & wxMOD_CMD) != 0) combo.append("Ctrl-"); + if ((modifier & wxMOD_ALT) != 0) combo.append("Alt-"); + if ((modifier & wxMOD_SHIFT) != 0) combo.append("Shift-"); + } + + if ((key_char != 0) + && (key_code != WXK_BACK) + && (key_code != WXK_RETURN) + && (key_code != WXK_ESCAPE) + && (key_code != WXK_SPACE) + && (key_code != WXK_DELETE)) { + combo.append(wxString::Format("%c", key_char)); + } else if (keycode_name(key_code, combo) == 1) { + std::stringstream ss; + ss << key_code; + combo.append(ss.str()); + } + + std::string command; + if (agi::hotkey::hotkey->Scan(context, combo, command) == 0) { + } + +} + + +bool keycode_name(const int &code, std::string &combo) { + KCNameMap::iterator index; + + if ((index = kc_name_map.find(code)) != kc_name_map.end()) { + combo.append(index->second); + return 0; + } + return 1; +} + + +void keycode_name_map_init() { + kc_name_map.insert(KCNamePair(WXK_TAB, "Tab")); + kc_name_map.insert(KCNamePair(WXK_RETURN, "Return")); + kc_name_map.insert(KCNamePair(WXK_ESCAPE, "Escape")); + kc_name_map.insert(KCNamePair(WXK_SPACE, "Space")); + kc_name_map.insert(KCNamePair(WXK_DELETE, "Delete")); + kc_name_map.insert(KCNamePair(WXK_SHIFT, "Shift")); + kc_name_map.insert(KCNamePair(WXK_ALT, "Alt")); + kc_name_map.insert(KCNamePair(WXK_CONTROL, "Control")); + kc_name_map.insert(KCNamePair(WXK_PAUSE, "Pause")); + kc_name_map.insert(KCNamePair(WXK_END, "End")); + kc_name_map.insert(KCNamePair(WXK_HOME, "Home")); + kc_name_map.insert(KCNamePair(WXK_LEFT, "Left")); + kc_name_map.insert(KCNamePair(WXK_UP, "Up")); + kc_name_map.insert(KCNamePair(WXK_RIGHT, "Right")); + kc_name_map.insert(KCNamePair(WXK_DOWN, "Down")); + kc_name_map.insert(KCNamePair(WXK_PRINT, "Print")); + kc_name_map.insert(KCNamePair(WXK_INSERT, "Insert")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD0, "KP_0")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD1, "KP_1")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD2, "KP_2")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD3, "KP_3")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD4, "KP_4")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD5, "KP_5")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD6, "KP_6")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD7, "KP_7")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD8, "KP_8")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD9, "KP_9")); + kc_name_map.insert(KCNamePair(WXK_MULTIPLY, "Astrisk")); + kc_name_map.insert(KCNamePair(WXK_ADD, "Plus")); + kc_name_map.insert(KCNamePair(WXK_SUBTRACT, "Hyphen")); + kc_name_map.insert(KCNamePair(WXK_DECIMAL, "Period")); + kc_name_map.insert(KCNamePair(WXK_DIVIDE, "Slash")); + kc_name_map.insert(KCNamePair(WXK_F1, "F1")); + kc_name_map.insert(KCNamePair(WXK_F2, "F2")); + kc_name_map.insert(KCNamePair(WXK_F3, "F3")); + kc_name_map.insert(KCNamePair(WXK_F4, "F4")); + kc_name_map.insert(KCNamePair(WXK_F5, "F5")); + kc_name_map.insert(KCNamePair(WXK_F6, "F6")); + kc_name_map.insert(KCNamePair(WXK_F7, "F7")); + kc_name_map.insert(KCNamePair(WXK_F8, "F8")); + kc_name_map.insert(KCNamePair(WXK_F9, "F9")); + kc_name_map.insert(KCNamePair(WXK_F10, "F10")); + kc_name_map.insert(KCNamePair(WXK_F11, "F11")); + kc_name_map.insert(KCNamePair(WXK_F12, "F12")); + kc_name_map.insert(KCNamePair(WXK_F13, "F13")); + kc_name_map.insert(KCNamePair(WXK_F14, "F14")); + kc_name_map.insert(KCNamePair(WXK_F15, "F15")); + kc_name_map.insert(KCNamePair(WXK_F16, "F16")); + kc_name_map.insert(KCNamePair(WXK_F17, "F17")); + kc_name_map.insert(KCNamePair(WXK_F18, "F18")); + kc_name_map.insert(KCNamePair(WXK_F19, "F19")); + kc_name_map.insert(KCNamePair(WXK_F20, "F20")); + kc_name_map.insert(KCNamePair(WXK_F21, "F21")); + kc_name_map.insert(KCNamePair(WXK_F22, "F22")); + kc_name_map.insert(KCNamePair(WXK_F23, "F23")); + kc_name_map.insert(KCNamePair(WXK_F24, "F24")); + kc_name_map.insert(KCNamePair(WXK_NUMLOCK, "Num_Lock")); + kc_name_map.insert(KCNamePair(WXK_SCROLL, "Scroll_Lock")); + kc_name_map.insert(KCNamePair(WXK_PAGEUP, "PageUp")); + kc_name_map.insert(KCNamePair(WXK_PAGEDOWN, "PageDown")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_SPACE, "KP_Space")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_TAB, "KP_Tab")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_ENTER, "KP_Return")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_F1, "KP_F1")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_F2, "KP_F2")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_F3, "KP_F3")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_F4, "KP_F4")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_HOME, "KP_Home")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_LEFT, "KP_Left")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_UP, "KP_Up")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_RIGHT, "KP_Right")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_DOWN, "KP_Down")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_PAGEUP, "KP_PageUp")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_PAGEDOWN, "KP_PageDown")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_END, "KP_End")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_BEGIN, "KP_Begin")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_INSERT, "KP_insert")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_DELETE, "KP_Delete")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_EQUAL, "KP_Equal")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_MULTIPLY, "KP_Multiply")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_ADD, "KP_Add")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_SUBTRACT, "KP_Subtract")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_DECIMAL, "KP_Decimal")); + kc_name_map.insert(KCNamePair(WXK_NUMPAD_DIVIDE, "KP_Divide")); + +} + +} // namespace toolbar + diff --git a/aegisub/src/hotkeys.cpp b/aegisub/src/hotkeys.cpp deleted file mode 100644 index 32ea12a34..000000000 --- a/aegisub/src/hotkeys.cpp +++ /dev/null @@ -1,571 +0,0 @@ -// Copyright (c) 2005, Rodrigo Braz Monteiro -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of the Aegisub Group nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Aegisub Project http://www.aegisub.org/ -// -// $Id$ - -/// @file hotkeys.cpp -/// @brief Keep hotkey configuration and handle hotkey presses -/// @ingroup main_ui -/// - -#include "config.h" - -#ifndef AGI_PRE -#include - -#include -#include -#endif - -#include "hotkeys.h" -#include "text_file_reader.h" -#include "text_file_writer.h" - -/// @brief Constructors HotkeyType ////////////////////////////////// -/// -HotkeyType::HotkeyType() { - flags = 0; - keycode = 0; -} - -/// @brief DOCME -/// @param text -/// @param name -/// -HotkeyType::HotkeyType(wxString text,wxString name) { - Parse(text); - origName = name; -} - -/// @brief Get string of hotkey -/// @return -/// -wxString HotkeyType::GetText() const { - wxString text; - - // Modifiers - if (flags & wxACCEL_CTRL) text += _T("Ctrl-"); - if (flags & wxACCEL_ALT) text += _T("Alt-"); - if (flags & wxACCEL_SHIFT) text += _T("Shift-"); - - // Key name - text += GetKeyName(keycode); - - return text; -} - -/// @brief Parse text into hotkey -/// @param text -/// -void HotkeyType::Parse(wxString text) { - // Reset - flags = 0; - keycode = 0; - wxString work = text.Lower(); - - // Parse modifiers - while (true) { - // Ctrl - if (work.Left(5) == _T("ctrl-")) { - flags |= wxACCEL_CTRL; - work = work.Mid(5); - continue; - } - - // Alt - if (work.Left(4) == _T("alt-")) { - flags |= wxACCEL_ALT; - work = work.Mid(4); - continue; - } - - // Shift - if (work.Left(6) == _T("shift-")) { - flags |= wxACCEL_SHIFT; - work = work.Mid(6); - continue; - } - - break; - } - - // Get key name - FillMap(); - bool got = false; - std::map::iterator cur; - for (cur = keyName.begin();cur != keyName.end();cur++) { - if (cur->second.Lower() == work) { - keycode = cur->first; - got = true; - break; - } - } - - // Didn't find, check if it's a raw code - if (!got) { - if (work.Left(1) == _T("[") && work.Right(1) == _T("]")) { - work = work.Mid(1,work.Length()-2); - if (work.IsNumber()) { - long temp; - work.ToLong(&temp); - keycode = temp; - } - } - } -} - -/// DOCME -std::map HotkeyType::keyName; - -/// @brief DOCME -/// @param keycode -/// @return -/// -wxString HotkeyType::GetKeyName(int keycode) { - // Fill map - FillMap(); - - // Blank key - if (keycode == 0) return _T(""); - - // Get key name - std::map::iterator cur = keyName.find(keycode); - if (cur != keyName.end()) return cur->second; - else return wxString::Format(_T("[%i]"),keycode); -} - -/// @brief Fill map -/// @return -/// -void HotkeyType::FillMap() { - if (keyName.empty()) { - keyName[WXK_BACK] = _T("Backspace"); - keyName[WXK_SPACE] = _T("Space"); - keyName[WXK_RETURN] = _T("Enter"); - keyName[WXK_TAB] = _T("Tab"); - keyName[WXK_PAUSE] = _T("Pause"); - - keyName[WXK_LEFT] = _T("Left"); - keyName[WXK_RIGHT] = _T("Right"); - keyName[WXK_UP] = _T("Up"); - keyName[WXK_DOWN] = _T("Down"); - - keyName[WXK_INSERT] = _T("Insert"); - keyName[WXK_DELETE] = _T("Delete"); - keyName[WXK_HOME] = _T("Home"); - keyName[WXK_END] = _T("End"); - keyName[WXK_PAGEUP] = _T("PgUp"); - keyName[WXK_PAGEDOWN] = _T("PgDn"); - - keyName[WXK_NUMPAD0] = _T("KP_0"); - keyName[WXK_NUMPAD1] = _T("KP_1"); - keyName[WXK_NUMPAD2] = _T("KP_2"); - keyName[WXK_NUMPAD3] = _T("KP_3"); - keyName[WXK_NUMPAD4] = _T("KP_4"); - keyName[WXK_NUMPAD5] = _T("KP_5"); - keyName[WXK_NUMPAD6] = _T("KP_6"); - keyName[WXK_NUMPAD7] = _T("KP_7"); - keyName[WXK_NUMPAD8] = _T("KP_8"); - keyName[WXK_NUMPAD9] = _T("KP_9"); - keyName[WXK_NUMPAD_ADD] = _T("KP_Add"); - keyName[WXK_NUMPAD_SUBTRACT] = _T("KP_Subtract"); - keyName[WXK_NUMPAD_SUBTRACT] = _T("KP_Subtract"); - keyName[WXK_NUMPAD_MULTIPLY] = _T("KP_Multiply"); - keyName[WXK_NUMPAD_DIVIDE] = _T("KP_Divide"); - keyName[WXK_NUMPAD_DECIMAL] = _T("KP_Decimal"); - keyName[WXK_NUMPAD_ENTER] = _T("KP_Enter"); - - keyName[WXK_F1] = _T("F1"); - keyName[WXK_F2] = _T("F2"); - keyName[WXK_F3] = _T("F3"); - keyName[WXK_F4] = _T("F4"); - keyName[WXK_F5] = _T("F5"); - keyName[WXK_F6] = _T("F6"); - keyName[WXK_F7] = _T("F7"); - keyName[WXK_F8] = _T("F8"); - keyName[WXK_F9] = _T("F9"); - keyName[WXK_F10] = _T("F10"); - keyName[WXK_F11] = _T("F11"); - keyName[WXK_F12] = _T("F12"); - - for (char i='!';i<='`';i++) { - keyName[i] = wchar_t(i); - } - } -} - -/// DOCME -HotkeyManager Hotkeys; - -/// @brief Constructor -/// -HotkeyManager::HotkeyManager() { - modified = false; -} - -/// @brief Destructor -/// -HotkeyManager::~HotkeyManager() { - key.clear(); -} - -/// @brief Save -/// @return -/// -void HotkeyManager::Save() { - // Check if it's actually modified - if (!modified) return; - - // Open file - using namespace std; - TextFileWriter file(filename,_T("UTF-8")); - file.WriteLineToFile(_T("[Hotkeys]")); - - // Put variables in it - for (map::iterator cur=key.begin();cur!=key.end();cur++) { - file.WriteLineToFile((*cur).first + _T("=") + (*cur).second.GetText()); - } - - // Close - modified = false; -} - -/// @brief Load -/// @return -/// -void HotkeyManager::Load() { - // Load defaults - LoadDefaults(); - - // Check if file exists (create if it doesn't) - wxFileName path(filename); - if (!path.FileExists()) { - modified = true; - Save(); - return; - } - - // Open file - using namespace std; - TextFileReader file(filename); - wxString header; - try { - header = file.ReadLineFromFile(); - } - catch (...) { - } - - // if (header != _T("[Hotkeys]")) { - if (!header.EndsWith(_T("[Hotkeys]"))) { // Workaround for OSX, will be useless when Hotkeys are redone. - wxFileName backupfn(filename); - backupfn.SetFullName(_T("hotkeys.bak")); - wxCopyFile(filename, backupfn.GetFullPath()); - modified = true; - Save(); - wxLogWarning(_T("Hotkeys file corrupted, defaults restored.\nA backup of the corrupted file was made.")); - return; - } - - // Get variables - wxString curLine; - map::iterator cur; - while (file.HasMoreLines()) { - // Parse line - try { - curLine = file.ReadLineFromFile(); - } - catch (wxString e) { - wxFileName backupfn(filename); - backupfn.SetFullName(_T("hotkeys.bak")); - wxCopyFile(filename, backupfn.GetFullPath()); - modified = true; - Save(); - wxLogWarning(_T("Hotkeys file corrupted, defaults restored.\nA backup of the corrupted file was made.")); - return; - } - if (curLine.IsEmpty()) continue; - size_t pos = curLine.Find(_T("=")); - if (pos == wxString::npos) continue; - wxString func = curLine.Left(pos); - wxString value = curLine.Mid(pos+1); - - // Find it - cur = key.find(func); - if (cur != key.end()) { - (*cur).second.Parse(value); - } - - // Commented out so it discards anything that isn't listed: - //else SetHotkey(func,value); - } - - // Close - Save(); -} - -/// @brief Set all hotkeys to the default values -/// -void HotkeyManager::LoadDefaults() { - modified = true; - - /// @note () is used here instead of _T(). This is done so the strings can be extracted. - /// However, since this function is called before locale is set, it won't ever be translated. - /// Keep this in mind: THESE CANNOT BE TRANSLATED HERE! - /// As a safeguard, _() is undefined here - #undef _ - - /// DOCME - #define _(a) _T(a) - - SetHotkey(_("New subtitles"),_T("Ctrl-N")); - SetHotkey(_("Open subtitles"),_T("Ctrl-O")); - SetHotkey(_("Save subtitles"),_T("Ctrl-S")); -#ifdef __APPLE__ - SetHotkey(_("Exit"),_T("Ctrl-Q")); - SetHotkey(_("Help"),_T("Ctrl-?")); - SetHotkey(_("Options"),_T("Ctrl-,")); -#else - SetHotkey(_("Exit"),_T("Alt-F4")); - SetHotkey(_("Help"),_T("F1")); - SetHotkey(_("Options"),_T("Alt-O")); -#endif - - SetHotkey(_("Edit Box Commit"),_T("Ctrl-Enter")); - SetHotkey(_("Undo"),_T("Ctrl-Z")); -#ifdef __APPLE__ - SetHotkey(_("Redo"),_T("Ctrl-Shift-Z")); -#else - SetHotkey(_("Redo"),_T("Ctrl-Y")); -#endif - SetHotkey(_("Shift Times"),_T("Ctrl-I")); - SetHotkey(_("Find"),_T("Ctrl-F")); -#ifdef __APPLE__ - SetHotkey(_("Find Next"),_T("Ctrl-G")); - SetHotkey(_("Replace"),_T("Ctrl-Shift-F")); // non-standard? -#else - SetHotkey(_("Find Next"),_T("F3")); - SetHotkey(_("Replace"),_T("Ctrl-H")); -#endif - SetHotkey(_("Select Lines"),_T("")); - SetHotkey(_("Copy"),_T("Ctrl-C")); - SetHotkey(_("Cut"),_T("Ctrl-X")); - SetHotkey(_("Paste"),_T("Ctrl-V")); - SetHotkey(_("Paste Over"),_T("Ctrl-Shift-V")); - -#ifdef __APPLE__ - SetHotkey(_("Video Jump"),_T("Ctrl-J")); -#else - SetHotkey(_("Video Jump"),_T("Ctrl-G")); -#endif - SetHotkey(_("Jump Video to Start"),_T("Ctrl-1")); - SetHotkey(_("Jump Video to End"),_T("Ctrl-2")); - SetHotkey(_("Set Start to Video"),_T("Ctrl-3")); - SetHotkey(_("Set End to Video"),_T("Ctrl-4")); - SetHotkey(_("Snap to Scene"),_T("Ctrl-5")); - SetHotkey(_("Shift by Current Time"),_T("Ctrl-6")); - SetHotkey(_("Zoom 50%"),_T("")); - SetHotkey(_("Zoom 100%"),_T("")); - SetHotkey(_("Zoom 200%"),_T("")); - - SetHotkey(_("Video global prev frame"),_T("Ctrl-KP_4")); - SetHotkey(_("Video global next frame"),_T("Ctrl-KP_6")); - SetHotkey(_("Video global focus seek"),_T("Ctrl-Space")); - SetHotkey(_("Video global play"),_T("Ctrl-P")); - SetHotkey(_("Grid global prev line"),_T("Ctrl-KP_8")); - SetHotkey(_("Grid global next line"),_T("Ctrl-KP_2")); - SetHotkey(_("Save Subtitles Alt"),_T("F2")); - SetHotkey(_("Video global zoom in"),_T("Ctrl-KP_Add")); - SetHotkey(_("Video global zoom out"),_T("Ctrl-KP_Subtract")); - - SetHotkey(_("Grid move row down"),_T("Alt-Down")); - SetHotkey(_("Grid move row up"),_T("Alt-Up")); -#ifdef __APPLE__ - SetHotkey(_("Grid delete rows"),_T("Ctrl-Backspace")); -#else - SetHotkey(_("Grid delete rows"),_T("Ctrl-Delete")); -#endif - SetHotkey(_("Grid duplicate rows"),_T("")); - SetHotkey(_("Grid duplicate and shift one frame"),_T("Ctrl-D")); - - SetHotkey(_("Audio Commit Alt"),_T("G")); - SetHotkey(_("Audio Commit"),_T("Enter")); - SetHotkey(_("Audio Commit (Stay)"),_T("F8")); - SetHotkey(_("Audio Prev Line"),_T("Left")); - SetHotkey(_("Audio Prev Line Alt"),_T("Z")); - SetHotkey(_("Audio Next Line"),_T("Right")); - SetHotkey(_("Audio Next Line Alt"),_T("X")); - SetHotkey(_("Audio Play"),_T("Space")); - SetHotkey(_("Audio Play Alt"),_T("S")); - SetHotkey(_("Audio Play or Stop"),_T("B")); - SetHotkey(_("Audio Stop"),_T("H")); - SetHotkey(_("Audio Karaoke Increase Len"),_T("KP_Add")); - SetHotkey(_("Audio Karaoke Decrease Len"),_T("KP_Subtract")); - SetHotkey(_("Audio Karaoke Increase Len Shift"),_T("Shift-KP_Add")); - SetHotkey(_("Audio Karaoke Decrease Len Shift"),_T("Shift-KP_Subtract")); - SetHotkey(_("Audio Scroll Left"),_T("A")); - SetHotkey(_("Audio Scroll Right"),_T("F")); - SetHotkey(_("Audio Play First 500ms"),_T("E")); - SetHotkey(_("Audio Play Last 500ms"),_T("D")); - SetHotkey(_("Audio Play 500ms Before"),_T("Q")); - SetHotkey(_("Audio Play 500ms After"),_T("W")); - SetHotkey(_("Audio Play To End"),_T("T")); - SetHotkey(_("Audio Play Original Line"),_T("R")); - SetHotkey(_("Audio Add Lead In"),_T("C")); - SetHotkey(_("Audio Add Lead Out"),_T("V")); - - SetHotkey(_("Audio Medusa Toggle"),_T("Ctrl-KP_Multiply")); - SetHotkey(_("Audio Medusa Play"),_T("KP_5")); - SetHotkey(_("Audio Medusa Stop"),_T("KP_8")); - SetHotkey(_("Audio Medusa Shift Start Back"),_T("KP_4")); - SetHotkey(_("Audio Medusa Shift Start Forward"),_T("KP_6")); - SetHotkey(_("Audio Medusa Shift End Back"),_T("KP_7")); - SetHotkey(_("Audio Medusa Shift End Forward"),_T("KP_9")); - SetHotkey(_("Audio Medusa Play Before"),_T("KP_1")); - SetHotkey(_("Audio Medusa Play After"),_T("KP_3")); - SetHotkey(_("Audio Medusa Next"),_T("KP_2")); - SetHotkey(_("Audio Medusa Previous"),_T("KP_0")); - SetHotkey(_("Audio Medusa Enter"),_T("KP_Enter")); - - SetHotkey(_("Translation Assistant Play Audio"),_T("End")); - SetHotkey(_("Translation Assistant Play Video"),_T("Home")); - SetHotkey(_("Translation Assistant Next"),_T("PgDn")); - SetHotkey(_("Translation Assistant Prev"),_T("PgUp")); - SetHotkey(_("Translation Assistant Accept"),_T("Enter")); - SetHotkey(_("Translation Assistant Preview"),_T("F8")); - SetHotkey(_("Translation Assistant Insert Original"),_T("Insert")); - - SetHotkey(_("Styling Assistant Play Audio"),_T("End")); - SetHotkey(_("Styling Assistant Play Video"),_T("Home")); - SetHotkey(_("Styling Assistant Next"),_T("PgDn")); - SetHotkey(_("Styling Assistant Prev"),_T("PgUp")); - SetHotkey(_("Styling Assistant Accept"),_T("Enter")); - SetHotkey(_("Styling Assistant Preview"),_T("F8")); - - SetHotkey(_("Visual Tool Default"), _T("A")); - SetHotkey(_("Visual Tool Drag"), _T("S")); - SetHotkey(_("Visual Tool Rotate Z"), _T("D")); - SetHotkey(_("Visual Tool Rotate X/Y"), _T("F")); - SetHotkey(_("Visual Tool Scale"), _T("G")); - SetHotkey(_("Visual Tool Rectangular Clip"), _T("H")); - SetHotkey(_("Visual Tool Vector Clip"), _T("J")); -} - -/// @brief Set hotkey -/// @param function -/// @param hotkey -/// -void HotkeyManager::SetHotkey(wxString function,HotkeyType hotkey) { - key[function.Lower()] = hotkey; - modified = true; -} - -/// @brief DOCME -/// @param function -/// @param hotkey -/// -void HotkeyManager::SetHotkey(wxString function,wxString hotkey) { - key[function.Lower()] = HotkeyType(hotkey,function); - modified = true; -} - -/// @brief Set file -/// @param file -/// -void HotkeyManager::SetFile(wxString file) { - filename = file; -} - -/// @brief Get hotkey as text -/// @param function -/// @return -/// -const wxString HotkeyManager::GetText(wxString function) const { - std::map::const_iterator cur = key.find(function.Lower()); - if (cur != key.end()) { - return cur->second.GetText(); - } - else throw _T("Hotkey not defined"); -} - -/// @brief Get hotkey as accelerator entry -/// @param function -/// @param id -/// @return -/// -wxAcceleratorEntry HotkeyManager::GetAccelerator(wxString function,int id) const { - std::map::const_iterator cur = key.find(function.Lower()); - if (cur != key.end()) { - const HotkeyType *hotkey = &(*cur).second; - wxAcceleratorEntry entry; - entry.Set(hotkey->flags,hotkey->keycode,id); - return entry; - } - else throw _T("Hotkey not defined"); -} - -/// @brief Set last key pressed -/// @param keypress -/// @param ctrl -/// @param alt -/// @param shift -/// -void HotkeyManager::SetPressed(int keypress,bool ctrl,bool alt,bool shift) { - lastKey = keypress; - lastMod = 0; - if (ctrl) lastMod |= wxACCEL_CTRL; - if (alt) lastMod |= wxACCEL_ALT; - if (shift) lastMod |= wxACCEL_SHIFT; -} - -/// @brief Is pressed? -/// @param function -/// @return -/// -bool HotkeyManager::IsPressed(wxString function) const { - std::map::const_iterator cur = key.find(function.Lower()); - if (cur != key.end()) { - const HotkeyType *hotkey = &(*cur).second; - return (hotkey->keycode == lastKey && hotkey->flags == lastMod); - } - else throw _T("Hotkey not defined"); -} - -/// @brief Search for a hotkey -/// @param keycode -/// @param mod -/// -HotkeyType *HotkeyManager::Find(int keycode,int mod) { - for (std::map::iterator cur = key.begin();cur != key.end();cur++) { - if (cur->second.keycode == keycode && cur->second.flags == mod) { - return &(cur->second); - } - } - - return NULL; -} diff --git a/aegisub/src/include/aegisub/context.h b/aegisub/src/include/aegisub/context.h new file mode 100644 index 000000000..86636a0bc --- /dev/null +++ b/aegisub/src/include/aegisub/context.h @@ -0,0 +1,33 @@ +#pragma once // sigh. + +#include + +#include "ass_file.h" +#include "subs_grid.h" +#include "audio_box.h" +#include "video_box.h" +#include "dialog_detached_video.h" +#include "auto4_base.h" +#include "dialog_styling_assistant.h" +#include "audio_controller.h" + +namespace agi { + +struct Context { + // Frames + wxWindow *parent; + + DialogStyling *stylingAssistant; + + AudioBox *audioBox; + AudioController *audioController; + DialogDetachedVideo *detachedVideo; + AssFile *ass; + Automation4::ScriptManager *local_scripts; + wxWindow *PreviousFocus; + SubsEditBox *EditBox; + SubtitlesGrid *SubsGrid; + VideoBox *videoBox; +}; + +} diff --git a/aegisub/src/include/aegisub/hotkey.h b/aegisub/src/include/aegisub/hotkey.h new file mode 100644 index 000000000..e58e74e61 --- /dev/null +++ b/aegisub/src/include/aegisub/hotkey.h @@ -0,0 +1,42 @@ +// Copyright (c) 2010, Amar Takhar +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// $Id$ + +/// @file hotkey.h +/// @brief Hotkey handler +/// @ingroup hotkey menu event window + +#include "config.h" + +#ifndef AGI_PRE +#include + +#include +#endif + +#include + + +namespace hotkey { + + +typedef std::map KCNameMap; + +extern KCNameMap kc_name_map; +void keycode_name_map_init(); +bool keycode_name(const int &code, std::string &combo); +void check(std::string context, int key_code, wchar_t key_char, int modifier); + +} // namespace hotkey diff --git a/aegisub/src/include/aegisub/menu.h b/aegisub/src/include/aegisub/menu.h new file mode 100644 index 000000000..04ebea720 --- /dev/null +++ b/aegisub/src/include/aegisub/menu.h @@ -0,0 +1,72 @@ +// Copyright (c) 2010, Amar Takhar +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// $Id$ + +/// @file menu.h +/// @brief Dynamic menu and toolbar generator. +/// @ingroup menu toolbar + +#include "config.h" + +#ifndef AGI_PRE +#include + +#include +#endif + +#include +#include + +#pragma once + +namespace menu { +DEFINE_BASE_EXCEPTION_NOINNER(MenuError, agi::Exception) +DEFINE_SIMPLE_EXCEPTION_NOINNER(MenuJsonValueArray, MenuError, "menu/value/array") +DEFINE_SIMPLE_EXCEPTION_NOINNER(MenuJsonValueSingle, MenuError, "menu/value") +DEFINE_SIMPLE_EXCEPTION_NOINNER(MenuJsonValueNull, MenuError, "menu/value") +DEFINE_SIMPLE_EXCEPTION_NOINNER(MenuInvalidName, MenuError, "menu/invalid") + +class Menu; +extern Menu *menu; + +class Menu { +public: + Menu(); + ~Menu(); + wxMenuBar* GetMainMenu() { return main_menu; } + wxMenu* GetMenu(std::string name); + +private: + + typedef std::map MTMap; + typedef std::pair MTPair; + + enum MenuTypes { + Option = 1, + Check = 2, + Radio = 3, + Submenu = 4, + Recent = 5, + Spacer = 100 + }; + + wxMenuBar *main_menu; + MTMap map; + + wxMenu* BuildMenu(std::string name, const json::Array& array, int submenu=0); + +}; + +} // namespace menu diff --git a/aegisub/src/include/aegisub/toolbar.h b/aegisub/src/include/aegisub/toolbar.h new file mode 100644 index 000000000..f46116f3f --- /dev/null +++ b/aegisub/src/include/aegisub/toolbar.h @@ -0,0 +1,62 @@ +// Copyright (c) 2010, Amar Takhar +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// $Id$ + +/// @file toolbar.h +/// @brief Dynamic toolbar generator. +/// @ingroup menu toolbar + +#include "config.h" + +#ifndef AGI_PRE +#include + +#include +#endif + +#include +#include + +#pragma once + +namespace toolbar { +DEFINE_BASE_EXCEPTION_NOINNER(ToolbarError, agi::Exception) +DEFINE_SIMPLE_EXCEPTION_NOINNER(ToolbarJsonValueArray, ToolbarError, "toolbar/value/array") +DEFINE_SIMPLE_EXCEPTION_NOINNER(ToolbarInvalidName, ToolbarError, "toolbar/invalid") + +class Toolbar; +extern Toolbar *toolbar; + +class Toolbar { +public: + Toolbar(); + ~Toolbar(); + void GetToolbar(std::string name, wxToolBar *toolbar); + +private: + typedef std::map TbMap; + typedef std::pair TbPair; + + TbMap map; + + enum ToolbarTypes { + Standard = 1, + }; + + void BuildToolbar(wxToolBar *toolbar, const json::Array& array); + +}; + +} // namespace toolbar diff --git a/aegisub/src/libresrc/Makefile b/aegisub/src/libresrc/Makefile index 0c52d88f2..510f526bf 100644 --- a/aegisub/src/libresrc/Makefile +++ b/aegisub/src/libresrc/Makefile @@ -20,9 +20,12 @@ bitmap.cpp: ../../tools/common-respack default_config.cpp: ../../tools/common-respack *.json ../../tools/common-respack \ default_config.cpp \ - ./default_mru.json \ ./default_config.json \ - ./default_path.json + ./default_hotkey.json \ + ./default_menu.json \ + ./default_mru.json \ + ./default_path.json \ + ./default_toolbar.json EXTRA_DIST = *.json diff --git a/aegisub/src/libresrc/OLD_METHOD_TO_NEW_COMMAND_MAP.txt b/aegisub/src/libresrc/OLD_METHOD_TO_NEW_COMMAND_MAP.txt new file mode 100644 index 000000000..635844081 --- /dev/null +++ b/aegisub/src/libresrc/OLD_METHOD_TO_NEW_COMMAND_MAP.txt @@ -0,0 +1,108 @@ +am/manager Menu_Tools_Automation FrameMain::OnOpenAutomation +app/about Menu_Help_About FrameMain::OnAbout +app/display/audio_subs Menu_View_Audio FrameMain::OnViewAudio +app/display/full Menu_View_Standard FrameMain::OnViewStandard +app/display/subs Menu_View_Subs FrameMain::OnViewSubs +app/display/video_subs Menu_View_Video FrameMain::OnViewVideo +app/exit Menu_File_Exit FrameMain::OnExit +app/language Menu_View_Language FrameMain::OnChooseLanguage +app/log Menu_Help_Log FrameMain::OnLog +app/new_window Menu_File_New_Window FrameMain::OnNewWindow +app/options Menu_Tools_Options FrameMain::OnOpenPreferences +app/updates Menu_Help_Check_Updates FrameMain::OnCheckUpdates +audio/close Menu_Audio_Close FrameMain::OnCloseAudio +audio/open Menu_Audio_Open_File FrameMain::OnOpenAudio +audio/open/blank Menu_Audio_Open_Dummy FrameMain::OnOpenDummyAudio +audio/open/noise Menu_Audio_Open_Dummy_Noise FrameMain::OnOpenDummyNoiseAudio +audio/open/video Menu_Audio_Open_From_Video FrameMain::OnOpenAudioFromVideo +edit/line/copy Menu_Edit_Copy FrameMain::OnCopy +edit/line/cut Menu_Edit_Cut FrameMain::OnCut +edit/line/paste Menu_Edit_Paste FrameMain::OnPaste +edit/line/paste/over Menu_Edit_Paste_Over FrameMain::OnPasteOver +edit/redo Menu_Edit_Redo FrameMain::OnRedo +edit/search_replace Menu_Edit_Replace FrameMain::OnReplace +edit/undo Menu_Edit_Undo FrameMain::OnUndo +grid/line/next Grid_Next_Line FrameMain::OnNextLine +grid/line/prev Grid_Prev_Line FrameMain::OnPrevLine +grid/tag/cycle_hiding Grid_Toggle_Tags FrameMain::OnToggleTags +grid/tags/hide Menu_View_NoTags FrameMain::OnSetTags +grid/tags/show Menu_View_FullTags FrameMain::OnSetTags +grid/tags/simplify Menu_View_ShortTags FrameMain::OnSetTags + +help/bugs Menu_Help_BugTracker FrameMain::OnBugTracker +help/contents Menu_Help_Contents FrameMain::OnContents +help/files Menu_Help_Files FrameMain::OnFiles +help/forums Menu_Help_Forums FrameMain::OnForums +help/irc Menu_Help_IRCChannel FrameMain::OnIRCChannel +help/website Menu_Help_Website FrameMain::OnWebsite + +keyframe/close Menu_Video_Close_Keyframes FrameMain::OnCloseKeyframes +keyframe/open Menu_Video_Load_Keyframes FrameMain::OnOpenKeyframes +keyframe/save Menu_Video_Save_Keyframes FrameMain::OnSaveKeyframes +medusa/enter Medusa_Enter FrameMain::OnMedusaEnter +medusa/next Medusa_Next FrameMain::OnMedusaNext +medusa/play Medusa_Play FrameMain::OnMedusaPlay +medusa/play/after Medusa_Play_After FrameMain::OnMedusaPlayAfter +medusa/play/before Medusa_Play_Before FrameMain::OnMedusaPlayBefore +medusa/previous Medusa_Prev FrameMain::OnMedusaPrev +medusa/shift/end/back Medusa_Shift_End_Back FrameMain::OnMedusaShiftEndBack +medusa/shift/end/forward Medusa_Shift_End_Forward FrameMain::OnMedusaShiftEndForward +medusa/shift/start/back Medusa_Shift_Start_Back FrameMain::OnMedusaShiftStartBack +medusa/shift/start/forward Medusa_Shift_Start_Forward FrameMain::OnMedusaShiftStartForward +medusa/stop Medusa_Stop FrameMain::OnMedusaStop +subtitle/attachment Menu_Tools_Attachments FrameMain::OnOpenAttachments +subtitle/find Menu_Edit_Find FrameMain::OnFind +subtitle/find/next Menu_Edit_Find_Next FrameMain::OnFindNext +subtitle/new Menu_File_New_Subtitles FrameMain::OnNewSubtitles +subtitle/open Menu_File_Open_Subtitles FrameMain::OnOpenSubtitles +subtitle/open/charset Menu_File_Open_Subtitles_Charset FrameMain::OnOpenSubtitlesCharset +subtitle/open/video Menu_File_Open_Subtitles_From_Video FrameMain::OnOpenSubtitlesVideo +subtitle/properties Menu_Tools_Properties FrameMain::OnOpenProperties +subtitle/save Menu_File_Save_Subtitles FrameMain::OnSaveSubtitles +subtitle/save/as Menu_File_Save_Subtitles_As FrameMain::OnSaveSubtitlesAs +subtitle/select/visible Menu_Video_Select_Visible FrameMain::OnSelectVisible +subtitle/spellcheck Menu_Tools_SpellCheck FrameMain::OnOpenSpellCheck +time/frame/current Menu_Video_Shift_To_Frame FrameMain::OnShiftToFrame +time/shift Menu_Edit_Shift FrameMain::OnShift +time/snap/end_video Menu_Subs_Snap_End_To_Video FrameMain::OnSnapSubsEndToVid +time/snap/scene Menu_Video_Snap_To_Scene FrameMain::OnSnapToScene +time/snap/start_video Menu_Subs_Snap_Start_To_Video FrameMain::OnSnapSubsStartToVid +time/sort/end Menu_Subtitles_Sort_End FrameMain::OnSortEnd +time/sort/start Menu_Subtitles_Sort_Start FrameMain::OnSortStart +time/sort/style Menu_Subtitles_Sort_Style FrameMain::OnSortStyle +timecode/close Menu_File_Close_VFR FrameMain::OnCloseVFR +timecode/open Menu_File_Open_VFR FrameMain::OnOpenVFR +timecode/save Menu_File_Save_VFR FrameMain::OnSaveVFR +tool/assdraw Menu_Tools_ASSDraw FrameMain::OnOpenASSDraw +tool/export Menu_File_Export_Subtitles FrameMain::OnExportSubtitles +tool/font_collector Menu_Tools_Fonts_Collector FrameMain::OnOpenFontsCollector +tool/line/select Menu_Edit_Select FrameMain::OnSelect +tool/resampleres Menu_Tools_Resample FrameMain::OnOpenResample +tool/style/assistant Menu_Tools_Styling FrameMain::OnOpenStylingAssistant +tool/style/manager Menu_Tools_Styles_Manager FrameMain::OnOpenStylesManager +tool/time/kanji Menu_Tools_Kanji_Timer FrameMain::OnOpenKanjiTimer +tool/time/postprocess Menu_Tools_Timing_Processor FrameMain::OnOpenTimingProcessor +tool/translation_assistant Menu_Tools_Translation FrameMain::OnOpenTranslation +video/aspect/cinematic Menu_Video_AR_235 FrameMain::OnSetAR235 +video/aspect/custom Menu_Video_AR_Custom FrameMain::OnSetARCustom +video/aspect/default Menu_Video_AR_Default FrameMain::OnSetARDefault +video/aspect/full Menu_Video_AR_Full FrameMain::OnSetARFull +video/aspect/wide Menu_Video_AR_Wide FrameMain::OnSetARWide +video/close Menu_File_Close_Video FrameMain::OnCloseVideo +video/detach Menu_Video_Detach FrameMain::OnDetachVideo +video/details Menu_Video_Details FrameMain::OnOpenVideoDetails +video/focus_seek Video_Focus_Seek FrameMain::OnFocusSeek +video/frame/next Video_Next_Frame FrameMain::OnNextFrame +video/frame/play Video_Frame_Play FrameMain::OnVideoPlay +video/frame/prev Video_Prev_Frame FrameMain::OnPrevFrame +video/jump Menu_Video_JumpTo FrameMain::OnJumpTo +video/jump/end Menu_Subs_Snap_Video_To_End FrameMain::OnSnapVidToSubsEnd +video/jump/start Menu_Subs_Snap_Video_To_Start FrameMain::OnSnapVidToSubsStart +video/open Menu_File_Open_Video FrameMain::OnOpenVideo +video/open/dummy Menu_Video_Dummy FrameMain::OnDummyVideo +video/show_overscan Menu_Video_Overscan FrameMain::OnOverscan +video/zoom/100 Menu_View_Zoom_100 FrameMain::OnSetZoom100 +video/zoom/200 Menu_View_Zoom_200 FrameMain::OnSetZoom200 +video/zoom/50 Menu_View_Zoom_50 FrameMain::OnSetZoom50 +video/zoom/in Menu_Video_Zoom_In FrameMain::OnZoomIn +video/zoom/out Menu_Video_Zoom_Out FrameMain::OnZoomOut diff --git a/aegisub/src/libresrc/default_hotkey.json b/aegisub/src/libresrc/default_hotkey.json new file mode 100644 index 000000000..7d36ac4e3 --- /dev/null +++ b/aegisub/src/libresrc/default_hotkey.json @@ -0,0 +1,767 @@ +{ + "Always" : { + "audio play" : [ + { + "modifiers" : [], + "key" : "KP_5", + "enable" : false + } + ], + "audio stop" : [ + { + "modifiers" : [], + "key" : "KP_8", + "enable" : false + } + ], + "timing shift start backward" : [ + { + "modifiers" : [], + "key" : "KP_4", + "enable" : false + } + ], + "timing shift start forward" : [ + { + "modifiers" : [], + "key" : "KP_6", + "enable" : false + } + ], + "timing shift end backward" : [ + { + "modifiers" : [], + "key" : "KP_7", + "enable" : false + } + ], + "timing shift end forward" : [ + { + "modifiers" : [], + "key" : "KP_9", + "enable" : false + } + ], + "audio play before selection begin" : [ + { + "modifiers" : [], + "key" : "KP_1", + "enable" : false + } + ], + "audio play after selection end" : [ + { + "modifiers" : [], + "key" : "KP_3", + "enable" : false + } + ], + "timing move to prev item" : [ + { + "modifiers" : [], + "key" : "KP_0", + "enable" : false + } + ], + "timing move to next item" : [ + { + "modifiers" : [], + "key" : "KP_2", + "enable" : false + } + ], + "timing commit" : [ + { + "modifiers" : [], + "key" : "KP_Enter", + "enable" : false + } + ] + }, + + + "Default" : { + "app/exit" : [ + { + "modifiers" : [ "C" ], + "key" : "Q", + "enable" : true + } + ], + "app/options" : [ + { + "modifiers" : [ "Alt" ], + "key" : "O", + "enable" : true + } + ], + "audio play" : [ + { + "modifiers" : [], + "key" : "Space", + "enable" : true + }, + { + "modifiers" : [], + "key" : "S", + "enable" : true + } + ], + "audio play after selection end" : [ + { + "modifiers" : [], + "key" : "W", + "enable" : true + } + ], + "audio play before selection begin" : [ + { + "modifiers" : [], + "key" : "Q", + "enable" : true + } + ], + "audio play toggle" : [ + { + "modifiers" : [], + "key" : "B", + "enable" : true + } + ], + "audio play selection begin" : [ + { + "modifiers" : [], + "key" : "E", + "enable" : true + } + ], + "audio play selection end" : [ + { + "modifiers" : [], + "key" : "D", + "enable" : true + } + ], + "audio play to end" : [ + { + "modifiers" : [], + "key" : "T", + "enable" : true + } + ], + "audio scroll left" : [ + { + "modifiers" : [], + "key" : "A", + "enable" : true + } + ], + "audio scroll right" : [ + { + "modifiers" : [], + "key" : "F", + "enable" : true + } + ], + "audio stop" : [ + { + "modifiers" : [], + "key" : "H", + "enable" : true + } + ], + "commit" : [ + { + "modifiers" : [], + "key" : "Enter", + "enable" : true + }, + { + "modifiers" : [], + "key" : "G", + "enable" : true + } + ], + "commit and stay" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "Enter", + "enable" : true + }, + { + "modifiers" : [], + "key" : "F8", + "enable" : true + } + ], + "edit/copy" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "C", + "enable" : true + } + ], + "edit/cut" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "X", + "enable" : true + } + ], + "edit/find_replace" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "H", + "enable" : true + } + ], + "edit/line/delete" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "Delete", + "enable" : true + } + ], + "edit/line/duplicate/shift" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "D", + "enable" : true + } + ], + "edit/paste" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "V", + "enable" : true + } + ], + "edit/paste/over" : [ + { + "modifiers" : [ "Ctrl", "Shift" ], + "key" : "V", + "enable" : true + } + ], + "edit/redo" : [ + { + "modifiers" : [ "Ctrl", "Shift" ], + "key" : "V", + "enable" : true + } + ], + "edit/undo" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "Y", + "enable" : true + } + ], + "grid/line/next" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "KP_8", + "enable" : true + } + ], + "grid/line/prev" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "KP_2", + "enable" : true + } + ], + "grid/swap/down" : [ + { + "modifiers" : [ "Alt" ], + "key" : "Down", + "enable" : true + } + ], + "grid/swap/up" : [ + { + "modifiers" : [ "Alt" ], + "key" : "Up", + "enable" : true + } + ], + "help/contents" : [ + { + "modifiers" : [], + "key" : "F1", + "enable" : true + } + ], + "subtitle/find" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "F", + "enable" : true + } + ], + "subtitle/find/next" : [ + { + "modifiers" : [], + "key" : "F3", + "enable" : true + } + ], + "subtitle/new" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "N", + "enable" : true + } + ], + "subtitle/open" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "O", + "enable" : true + } + ], + "subtitle/save" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "S", + "enable" : true + }, + { + "modifiers" : [], + "key" : "F2", + "enable" : true + } + ], + "time/frame/current" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "6", + "enable" : true + } + ], + "time/shift" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "I", + "enable" : true + } + ], + "time/snap/end_video" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "4", + "enable" : true + } + ], + "time/snap/scene" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "5", + "enable" : true + } + ], + "time/snap/start_video" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "3", + "enable" : true + } + ], + "timing add lead in" : [ + { + "modifiers" : [], + "key" : "C", + "enable" : true + } + ], + "timing add lead out" : [ + { + "modifiers" : [], + "key" : "V", + "enable" : true + } + ], + "timing karaoke decrease length" : [ + { + "modifiers" : [], + "key" : "KP_Subtract", + "enable" : true + } + ], + "timing karaoke decrease length and shift following" : [ + { + "modifiers" : [ "Shift" ], + "key" : "KP_Subtract", + "enable" : true + } + ], + "timing karaoke increase length" : [ + { + "modifiers" : [], + "key" : "KP_Add", + "enable" : true + } + ], + "timing karaoke increase length and shift following" : [ + { + "modifiers" : [ "Shift" ], + "key" : "KP_Add", + "enable" : true + } + ], + "timing move to next item" : [ + { + "modifiers" : [], + "key" : "X", + "enable" : true + } + ], + "timing move to prev item" : [ + { + "modifiers" : [], + "key" : "Z", + "enable" : true + } + ], + "toggle global timing mode" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "KP_Multiply", + "enable" : true + } + ], + "video/focus_seek" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "Space", + "enable" : true + } + ], + "video/frame/next" : [ + { + "modifiers" : [], + "key" : "Right", + "enable" : true + }, + { + "modifiers" : [ "Ctrl" ], + "key" : "KP_6", + "enable" : true + } + ], + "video/frame/play" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "P", + "enable" : true + } + ], + "video/frame/prev" : [ + { + "modifiers" : [], + "key" : "Left", + "enable" : true + }, + { + "modifiers" : [ "Ctrl" ], + "key" : "KP_4", + "enable" : true + } + ], + "video/jump" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "J", + "enable" : true + } + ], + "video/jump/end" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "2", + "enable" : true + } + ], + "video/jump/start" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "1", + "enable" : true + } + ], + "video/zoom/in" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "KP_Add", + "enable" : true + } + ], + "video/zoom/out" : [ + { + "modifiers" : [ "Ctrl" ], + "key" : "KP_Subtract", + "enable" : true + } + ] + }, + + "Audio" : { + "timing move to next item" : [ + { + "modifiers" : [], + "key" : "Right", + "enable" : true + } + ], + "timing move to prev item" : [ + { + "modifiers" : [], + "key" : "Left", + "enable" : true + } + ] + }, + + "Video" : { + "video/frame/next" : [ + { + "modifiers" : [], + "key" : "Right", + "enable" : true + } + ], + "video/frame/prev" : [ + { + "modifiers" : [], + "key" : "Left", + "enable" : true + } + ], + "visual typesetting set tool crosshair" : [ + { + "modifiers" : [], + "key" : "A", + "enable" : true + } + ], + "visual typesetting set tool drag" : [ + { + "modifiers" : [], + "key" : "S", + "enable" : true + } + ], + "visual typesetting set tool rectangle clip" : [ + { + "modifiers" : [], + "key" : "H", + "enable" : true + } + ], + "visual typesetting set tool rotate xy" : [ + { + "modifiers" : [], + "key" : "F", + "enable" : true + } + ], + "visual typesetting set tool rotate z" : [ + { + "modifiers" : [], + "key" : "D", + "enable" : true + } + ], + "visual typesetting set tool scale" : [ + { + "modifiers" : [], + "key" : "G", + "enable" : true + } + ], + "visual typesetting set tool vector clip" : [ + { + "modifiers" : [], + "key" : "J", + "enable" : true + } + ] + }, + + "Styling Assistant" : { + "audio play" : [ + { + "modifiers" : [], + "key" : "End", + "enable" : true + } + ], + "styling assistant commit" : [ + { + "modifiers" : [], + "key" : "Enter", + "enable" : true + } + ], + "styling assistant next item" : [ + { + "modifiers" : [], + "key" : "PageDown", + "enable" : true + } + ], + "styling assistant prev item" : [ + { + "modifiers" : [], + "key" : "PageUp", + "enable" : true + } + ], + "styling assistant preview" : [ + { + "modifiers" : [], + "key" : "F8", + "enable" : true + } + ], + "video play" : [ + { + "modifiers" : [], + "key" : "Home", + "enable" : true + } + ] + }, + + "Timing Mode" : { + "audio play" : [ + { + "modifiers" : [], + "key" : "KP_5", + "enable" : true + } + ], + "audio play after selection end" : [ + { + "modifiers" : [], + "key" : "KP_3", + "enable" : true + } + ], + "audio play before selection begin" : [ + { + "modifiers" : [], + "key" : "KP_1", + "enable" : true + } + ], + "audio stop" : [ + { + "modifiers" : [], + "key" : "KP_8", + "enable" : true + } + ], + "timing commit" : [ + { + "modifiers" : [], + "key" : "KP_Enter", + "enable" : true + } + ], + "timing move to next item" : [ + { + "modifiers" : [], + "key" : "KP_2", + "enable" : true + } + ], + "timing move to prev item" : [ + { + "modifiers" : [], + "key" : "KP_0", + "enable" : true + } + ], + "timing shift end backward" : [ + { + "modifiers" : [], + "key" : "KP_7", + "enable" : true + } + ], + "timing shift end forward" : [ + { + "modifiers" : [], + "key" : "KP_9", + "enable" : true + } + ], + "timing shift start backward" : [ + { + "modifiers" : [], + "key" : "KP_4", + "enable" : true + } + ], + "timing shift start forward" : [ + { + "modifiers" : [], + "key" : "KP_6", + "enable" : true + } + ] + }, + + "Translation Assistant" : { + "audio play" : [ + { + "modifiers" : [], + "key" : "End", + "enable" : true + } + ], + "translation assiatant prev item" : [ + { + "modifiers" : [], + "key" : "PageUp", + "enable" : true + } + ], + "translation assistant commit" : [ + { + "modifiers" : [], + "key" : "Enter", + "enable" : true + } + ], + "translation assistant insert original" : [ + { + "modifiers" : [], + "key" : "Insert", + "enable" : true + } + ], + "translation assistant next item" : [ + { + "modifiers" : [], + "key" : "PageDown", + "enable" : true + } + ], + "translation assistant preview" : [ + { + "modifiers" : [], + "key" : "F8", + "enable" : true + } + ], + "video play" : [ + { + "modifiers" : [], + "key" : "Home", + "enable" : true + } + ] + } +} diff --git a/aegisub/src/libresrc/default_menu.json b/aegisub/src/libresrc/default_menu.json index 2ddcd6958..adf3f5a27 100644 --- a/aegisub/src/libresrc/default_menu.json +++ b/aegisub/src/libresrc/default_menu.json @@ -1,364 +1,291 @@ { - "Main" : [ + "main" : [ { "type" : 4, - "display" : "&File", - "description" : "Operations on subtitles.", - "command" : "submenu/file", + "command" : "file", "contents" : [ { "type" : 1, - "display" : "&New Subtitles", - "description" : "New subtitles.", - "command" : "" + "command" : "subtitle/new" }, { "type" : 1, - "display" : "&Open Subtitles..", - "description" : "Opens a subtitles file.", - "command" : "" + "command" : "subtitle/open" }, { "type" : 1, - "display" : "&Open Subtitles with Charset..", - "description" : "Opens a subtitles file with a specific charset.", - "command" : "" + "command" : "subtitle/open/charset" }, { "type" : 1, - "display" : "&Save Subtitles", - "description" : "Saves subtitles.", - "command" : "" + "command" : "subtitle/open/video" }, { "type" : 1, - "display" : "Save Subtitles as..", - "description" : "Saves subtitles with another name.", - "command" : "" + "command" : "subtitle/save" }, { "type" : 1, - "display" : "Export Subtitles..", - "description" : "Saves a copy of subtitles with processing applied to it.", - "command" : "" + "command" : "subtitle/save/as" }, { "type" : 1, - "display" : "Recent", - "description" : ".", - "command" : "" + "command" : "tool/export" + }, + { + "type" : 5, + "command" : "recent/subtitle" + }, + { + "type" : 100 }, { "type" : 1, - "display" : "&Properties..", - "description" : "Open script properties window.", - "command" : "" + "command" : "subtitle/properties" }, { "type" : 1, - "display" : "&Attachments..", - "description" : "Open the attachment list.", - "command" : "" + "command" : "subtitle/attachment" }, { "type" : 1, - "display" : "&Fonts Collector..", - "description" : "Open fonts collector.", - "command" : "" + "command" : "tool/font_collector" + }, + { + "type" : 100 }, { "type" : 1, - "display" : "New Window", - "description" : "Open a new application window.", - "command" : "" + "command" : "app/new_window" }, { "type" : 1, - "display" : "E&xit", - "description" : "Exit the application.", - "command" : "" + "command" : "app/exit" } ] }, { "type" : 4, - "display" : "&Edit", - "description" : "Editing operations.", - "command" : "submenu/edit", + "command" : "edit", "contents" : [ { "type" : 1, - "display" : "&Undo", - "description" : "Undoes last action.", - "command" : "" + "command" : "edit/undo" }, { "type" : 1, - "display" : "&Redo", - "description" : "Redoes last action.", - "command" : "" + "command" : "edit/redo" + }, + { + "type" : 100 }, { "type" : 1, - "display" : "Cut Lines", - "description" : "Cut subtitles.", - "command" : "" + "command" : "edit/line/cut" }, { "type" : 1, - "display" : "Copy Lines", - "description" : "Copy subtitles.", - "command" : "" + "command" : "edit/line/copy" }, { "type" : 1, - "display" : "Paste Lines", - "description" : "Paste subtitles.", - "command" : "" + "command" : "edit/line/paste" }, { "type" : 1, - "display" : "Paste Lines Over..", - "description" : "Paste subtitles over others.", - "command" : "" + "command" : "edit/line/paste/over" + }, + { + "type" : 100 }, { "type" : 1, - "display" : "&Find..", - "description" : "Find words in subtitles.", - "command" : "" + "command" : "subtitle/find" }, { "type" : 1, - "display" : "Find Next", - "description" : "Find next match of last word.", - "command" : "" + "command" : "subtitle/find/next" }, { "type" : 1, - "display" : "Search and &Replace..", - "description" : "Find and replace words in subtitles.", - "command" : "" - }, - - { - "type" : 4, - "display" : "&Subtitle", - "description" : "Subtitle manipulation.", - "command" : "submenu/subtitle", - "contents" : [ - { - "type" : 1, - "display" : "&Styles Manager..", - "description" : "Open styles manager.", - "command" : "" - }, - { - "type" : 1, - "display" : "St&yling Assistant..", - "description" : "Open styling assistant.", - "command" : "" - }, - { - "type" : 1, - "display" : "&Translation Assistant..", - "description" : "Open translation assistant.", - "command" : "" - }, - { - "type" : 1, - "display" : "Resample Resolution..", - "description" : "Changes resolution and modifies subtitles to conform to change.", - "command" : "" - }, - { - "type" : 1, - "display" : "Spe&ll Checker..", - "description" : "Open spell checker.", - "command" : "" - }, - - { - "type" : 4, - "display" : "&Insert Lines", - "description" : "Insert lines into currently active subtitle file.", - "command" : "submenu/subtitle/insert lines", - "contents" : [ - { - "type" : 1, - "display" : "&Before Current", - "description" : "Inserts a line before current.", - "command" : "" - }, - { - "type" : 1, - "display" : "&After Current", - "description" : "Inserts a line after current.", - "command" : "" - }, - { - "type" : 1, - "display" : "Before Current, at Video Time", - "description" : "Inserts a line before current, starting at video time.", - "command" : "" - }, - { - "type" : 1, - "display" : "After Current, at Video Time", - "description" : "Inserts a line after current, starting at video time.", - "command" : "" - } - ] - }, - { - "type" : 1, - "display" : "&Duplicate Lines", - "description" : "Duplicate the selected lines.", - "command" : "" - }, - { - "type" : 1, - "display" : "&Duplicate and Shift by 1 Frame", - "description" : "Duplicate lines and shift by one frame.", - "command" : "" - }, - { - "type" : 1, - "display" : "Delete Lines", - "description" : "Delete currently selected lines.", - "command" : "" - }, - - - { - "type" : 4, - "display" : "Join Lines", - "description" : "Merge 2 or more lines together.", - "command" : "submenu/timing/join lines", - "contents" : [ - { - "type" : 1, - "display" : "&Concatenate", - "description" : "Joins selected lines in a single one, concatenating text together.", - "command" : "" - }, - { - "type" : 1, - "display" : "Keep &First", - "description" : "Joins selected lines in a single one, keeping text of first and discarding remaining.", - "command" : "" - }, - { - "type" : 1, - "display" : "As &Karaoke", - "description" : "Joins selected lines in a single one, as karaoke.", - "command" : "" - } - ] - }, - { - "type" : 1, - "display" : "Recombine Lines", - "description" : "Recombine subtitles when they have been split and merged.", - "command" : "" - }, - { - "type" : 1, - "display" : "Split Lines (by karaoke)", - "description" : "Uses karaoke timing to split line into multiple smaller lines.", - "command" : "" - }, - { - "type" : 1, - "display" : "Swap Lines", - "description" : "Swaps the two selected lines.", - "command" : "" - }, - { - "type" : 1, - "display" : "Select Lines..", - "description" : "Selects lines based on defined criterea.", - "command" : "" + "command" : "edit/search_replace" } ] }, { "type" : 4, - "display" : "&Timing", - "description" : "Time manipulation.", - "command" : "submenu/timing", + "command" : "subtitle", "contents" : [ { "type" : 1, - "display" : "S&hift Times..", - "description" : "Shift subtitles by time or frames.", - "command" : "" + "command" : "tool/style/manager" }, { "type" : 1, - "display" : "Sort by Time", - "description" : "Sort all subtitles by their start times.", - "command" : "" + "command" : "tool/style/assistant" }, { "type" : 1, - "display" : "Timing Post-Processor..", - "description" : "Runs a post-processor for timing to deal with lead-ins, lead-outs, scene timing and etc.", - "command" : "" + "command" : "tool/translation_assistant" }, { "type" : 1, - "display" : "Kanji Timer..", - "description" : "Open Kanji timer.", - "command" : "" + "command" : "tool/resampleres" }, { "type" : 1, - "display" : "Snap Start to Video", - "description" : "Set start of selected subtitles to current video frame.", - "command" : "" + "command" : "subtitle/spellcheck" + }, + { + "type" : 100 }, { "type" : 1, - "display" : "Snap End to Video", - "description" : "Set end of selected subtitles to current video frame.", - "command" : "" - }, - { - "type" : 1, - "display" : "Snap to Scene", - "description" : "Set start and end of subtitles to the keyframes around current video frame.", - "command" : "" - }, - { - "type" : 1, - "display" : "Shift to Current Frame", - "description" : "Shift selection so first selected line starts at current frame.", - "command" : "" + "command" : "tool/assdraw" }, { "type" : 4, - "display" : "Make Times Continous", - "description" : "Make time continous.", - "command" : "submenu/timing/make times continous", + "command" : "insert lines", "contents" : [ { "type" : 1, - "display" : "Make Times Continuous", - "description" : ".", - "command" : "" - }, - { - "type" : 1, - "display" : "Change &Start", - "description" : "Changes times of subs so start times begin on previous's end time.", - "command" : "" + "command" : "subtitle/insert/before" }, { "type" : 1, - "display" : "Change &End", - "description" : "Changes times of subs so end times begin on next's start time.", - "command" : "" + "command" : "subtitle/insert/after" + }, + { + "type" : 1, + "command" : "subtitle/insert/before/videotime" + }, + { + "type" : 1, + "command" : "subtitle/insert/after/videotime" + } + ] + }, + { + "type" : 1, + "command" : "edit/line/duplicate" + }, + { + "type" : 1, + "command" : "edit/line/duplicate/shift" + }, + { + "type" : 1, + "command" : "edit/line/delete" + }, + { + "type" : 100 + }, + { + "type" : 4, + "command" : "join lines", + "contents" : [ + { + "type" : 1, + "command" : "edit/line/join/concatenate" + }, + { + "type" : 1, + "command" : "edit/line/join/keep_first" + }, + { + "type" : 1, + "command" : "edit/line/join/as_karaoke" + } + ] + }, + { + "type" : 1, + "command" : "edit/line/recombine" + }, + { + "type" : 1, + "command" : "edit/line/split/by_karaoke" + }, + { + "type" : 100 + }, + { + "type" : 4, + "command" : "sort lines", + "contents" : [ + { + "type" : 1, + "command" : "time/sort/start" + }, + { + "type" : 1, + "command" : "time/sort/end" + }, + { + "type" : 1, + "command" : "time/sort/style" + } + ] + }, + { + "type" : 1, + "command" : "edit/line/swap" + }, + { + "type" : 1, + "command" : "tool/line/select" + } + ] + }, + { + "type" : 4, + "command" : "timing", + "contents" : [ + { + "type" : 1, + "command" : "time/shift" + }, + { + "type" : 1, + "command" : "tool/time/postprocess" + }, + { + "type" : 1, + "command" : "tool/time/kanji" + }, + { + "type" : 100 + }, + { + "type" : 1, + "command" : "time/snap/start_video" + }, + { + "type" : 1, + "command" : "time/snap/end_video" + }, + { + "type" : 1, + "command" : "time/snap/scene" + }, + { + "type" : 1, + "command" : "time/frame/current" + }, + { + "type" : 100 + }, + { + "type" : 4, + "command" : "make times continous", + "contents" : [ + { + "type" : 1, + "command" : "time/continous/start" + }, + { + "type" : 1, + "command" : "time/continous/end" } ] } @@ -367,376 +294,287 @@ { "type" : 4, - "display" : "&Video", - "description" : "Video operations.", - "command" : "submenu/video", + "command" : "video", "contents" : [ { "type" : 1, - "display" : "&Open Video..", - "description" : "Opens a video file.", - "command" : "" + "command" : "video/open" }, { "type" : 1, - "display" : "&Close Video", - "description" : "Closes the currently open video file.", - "command" : "" + "command" : "video/close" + }, + { + "type" : 5, + "command" : "recent/video" }, { "type" : 1, - "display" : "Recent", - "description" : ".", - "command" : "" + "command" : "video/open/dummy" }, { "type" : 1, - "display" : "Use Dummy Video..", - "description" : "Opens a video clip with solid colour.", - "command" : "" + "command" : "video/details" + }, + { + "type" : 100 }, { "type" : 1, - "display" : "Show Video Details..", - "description" : "Shows video details.", - "command" : "" + "command" : "timecode/open" }, { "type" : 1, - "display" : "Open Timecodes File..", - "description" : "Opens a VFR timecodes v1 or v2 file.", - "command" : "" + "command" : "timecode/save" }, { "type" : 1, - "display" : "Save Timecodes File..", - "description" : "Saves a VFR timecodes v2 file.", - "command" : "" + "command" : "timecode/close" + }, + { + "type" : 5, + "command" : "recent/timecode" + }, + { + "type" : 100 }, { "type" : 1, - "display" : "Close Timecodes File", - "description" : "Closes the currently open timecodes file.", - "command" : "" + "command" : "keyframe/open" }, { "type" : 1, - "display" : "Recent", - "description" : ".", - "command" : "" + "command" : "keyframe/save" }, { "type" : 1, - "display" : "Open Keyframes..", - "description" : "Opens a keyframe list file.", - "command" : "" + "command" : "keyframe/close" + }, + { + "type" : 5, + "command" : "recent/keyframe" + }, + { + "type" : 100 }, { "type" : 1, - "display" : "Save Keyframes..", - "description" : "Saves the current keyframe list.", - "command" : "" + "command" : "video/detach" + }, + { + "type" : 4, + "command" : "set zoom", + "contents" : [ + { + "type" : 1, + "command" : "video/zoom/50" + }, + { + "type" : 1, + "command" : "video/zoom/100" + }, + { + "type" : 1, + "command" : "video/zoom/200" + } + ] + }, + { + "type" : 4, + "command" : "override ar", + "contents" : [ + { + "type" : 2, + "command" : "video/aspect/default" + }, + { + "type" : 2, + "command" : "video/aspect/full" + }, + { + "type" : 2, + "command" : "video/aspect/wide" + }, + { + "type" : 2, + "command" : "video/aspect/cinematic" + }, + { + "type" : 2, + "command" : "video/aspect/custom" + } + ] + }, + { + "type" : 2, + "command" : "video/show_overscan" + }, + { + "type" : 100 }, { "type" : 1, - "display" : "Close Keyframes", - "description" : "Closes the currently open keyframes list.", - "command" : "" + "command" : "video/jump" }, { "type" : 1, - "display" : "Recent", - "description" : ".", - "command" : "" + "command" : "video/jump/start" }, { - "type" : 1, - "display" : "Detach Video", - "description" : "Detach video, displaying it in a separate Window.", - "command" : "" - }, - - + "type" : 1, + "command" : "video/jump/end" + } + ] + }, { "type" : 4, - "display" : "", - "description" : "", - "command" : "submenu/", + "command" : "audio", "contents" : [ { "type" : 1, - "display" : "Set Zoom", - "description" : ".", - "command" : "" + "command" : "audio/open" }, { "type" : 1, - "display" : "Set zoom to 50%", - "description" : ".", - "command" : "" + "command" : "audio/open/video" }, { "type" : 1, - "display" : "Set zoom to 100%", - "description" : ".", - "command" : "" + "command" : "audio/close" + }, + { + "type" : 5, + "command" : "recent/audio" + }, + { + "type" : 100 }, { "type" : 1, - "display" : "Set zoom to 200%", - "description" : ".", - "command" : "" + "command" : "audio/view/spectrum" }, - - + { + "type" : 1, + "command" : "audio/view/waveform" + }, + { + "type" : 1, + "command" : "audio/open/blank" + }, + { + "type" : 1, + "command" : "audio/open/noise" + } + ] + }, { "type" : 4, - "display" : "", - "description" : "", - "command" : "submenu/", + "command" : "automation", "contents" : [ { "type" : 1, - "display" : "Override Aspect Ratio", - "description" : ".", - "command" : "" + "command" : "am/manager" }, { - "type" : 1, - "display" : "&Default", - "description" : "Leave video on original aspect ratio.", - "command" : "" - }, - { - "type" : 1, - "display" : "&Fullscreen (4:3)", - "description" : "Forces video to 4:3 aspect ratio.", - "command" : "" - }, - { - "type" : 1, - "display" : "&Widescreen (16:9)", - "description" : "Forces video to 16:9 aspect ratio.", - "command" : "" - }, - { - "type" : 1, - "display" : "&Cinematic (2.35)", - "description" : "Forces video to 2.35 aspect ratio.", - "command" : "" - }, - { - "type" : 1, - "display" : "Custom..", - "description" : "Forces video to a custom aspect ratio.", - "command" : "" - }, - { - "type" : 1, - "display" : "Show Overscan Mask", - "description" : "Show a mask over the video, indicating areas that might get cropped off by overscan on televisions.", - "command" : "" - }, - { - "type" : 1, - "display" : "&Jump to..", - "description" : "Jump to frame or time.", - "command" : "" - }, - { - "type" : 1, - "display" : "Jump Video to Start", - "description" : "Jumps the video to the start frame of current subtitle.", - "command" : "" - }, - { - "type" : 1, - "display" : "Jump Video to End", - "description" : "Jumps the video to the end frame of current subtitle.", - "command" : "" - }, - { - "type" : 1, - "display" : "", - "description" : ".", - "command" : "" - }, - { - "type" : 1, - "display" : "", - "description" : ".", - "command" : "" - }, - - - + "type" : 100 + } + ] + }, { "type" : 4, - "display" : "", - "description" : "", - "command" : "submenu/", + "command" : "view", "contents" : [ { "type" : 1, - "display" : "&Open Audio File..", - "description" : "Opens an audio file.", - "command" : "" + "command" : "app/language" }, { "type" : 1, - "display" : "Open Audio from &Video", - "description" : "Opens the audio from the current video file.", - "command" : "" + "command" : "app/options" }, { - "type" : 1, - "display" : "&Close Audio", - "description" : "Closes the currently open audio file.", - "command" : "" + "type" : 100 }, { - "type" : 1, - "display" : "Recent", - "description" : ".", - "command" : "" + "type" : 3, + "command" : "app/display/subs" }, { - "type" : 1, - "display" : "", - "description" : ".", - "command" : "" + "type" : 3, + "command" : "app/display/video_subs" }, - + { + "type" : 3, + "command" : "app/display/audio_subs" + }, + { + "type" : 3, + "command" : "app/display/full" + }, + { + "type" : 100 + }, + { + "type" : 3, + "command" : "grid/tags/show" + }, + { + "type" : 3, + "command" : "grid/tags/simplify" + }, + { + "type" : 3, + "command" : "grid/tags/hide" + } + ] + }, { "type" : 4, - "display" : "", - "description" : "", - "command" : "submenu/", + "command" : "help", "contents" : [ { "type" : 1, - "display" : "&Automation..", - "description" : "Open automation manager.", - "command" : "" + "command" : "help/contents" + }, + { + "type" : 100 }, { "type" : 1, - "display" : "&Scripts", - "description" : "Available automation scripts.", - "command" : "" - }, - - - { - "type" : 4, - "display" : "", - "description" : "", - "command" : "submenu/", - "contents" : [ - { - "type" : 1, - "display" : "", - "description" : ".", - "command" : "" + "command" : "help/files" }, { "type" : 1, - "display" : "Select Aegisub interface language", - "description" : ".", - "command" : "" + "command" : "help/website" }, { "type" : 1, - "display" : "&Options..", - "description" : "Configure Aegisub.", - "command" : "" + "command" : "help/forums" }, { "type" : 1, - "display" : "Subs Only View", - "description" : "Display subtitles only.", - "command" : "" + "command" : "help/bugs" + }, + { + "type" : 100 }, { "type" : 1, - "display" : "Video+Subs View", - "description" : "Display video and subtitles only.", - "command" : "" + "command" : "help/irc" }, { "type" : 1, - "display" : "Audio+Subs View", - "description" : "Display audio and subtitles only.", - "command" : "" + "command" : "app/updates" }, { "type" : 1, - "display" : "Full view", - "description" : "Display audio, video and subtitles.", - "command" : "" + "command" : "app/about" }, { "type" : 1, - "display" : "", - "description" : ".", - "command" : "" - }, - - - { - "type" : 4, - "display" : "", - "description" : "", - "command" : "submenu/", - "contents" : [ - { - "type" : 1, - "display" : "&Contents..", - "description" : "Help topics.", - "command" : "" - }, - { - "type" : 1, - "display" : "&All Files", - "description" : "Help topics.", - "command" : "" - }, - { - "type" : 1, - "display" : "&Website..", - "description" : "Visit Aegisub's official website.", - "command" : "" - }, - { - "type" : 1, - "display" : "&Forums..", - "description" : "Visit Aegisub's forums.", - "command" : "" - }, - { - "type" : 1, - "display" : "&Bug Tracker..", - "description" : "Visit Aegisub's bug tracker to report bugs and request new features.", - "command" : "" - }, - { - "type" : 1, - "display" : "&IRC Channel..", - "description" : "Visit Aegisub's official IRC channel.", - "command" : "" - }, - { - "type" : 1, - "display" : "&Check for Updates..", - "description" : "Check to see if there is a new version of Aegisub available.", - "command" : "" - }, - { - "type" : 1, - "display" : "&About..", - "description" : "About Aegisub.", - "command" : "" - }, - + "command" : "app/log" + } + ] + } ] } diff --git a/aegisub/src/libresrc/default_toolbar.json b/aegisub/src/libresrc/default_toolbar.json new file mode 100644 index 000000000..d192125a4 --- /dev/null +++ b/aegisub/src/libresrc/default_toolbar.json @@ -0,0 +1,116 @@ +{ + "main" : [ + { + "type" : 1, + "command" : "subtitle/new" + }, + { + "type" : 1, + "command" : "subtitle/open" + }, + { + "type" : 1, + "command" : "subtitle/save" + }, + { + "type" : 1, + "command" : "video/jump" + }, + { + "type" : 1, + "command" : "video/zoom/in" + }, + { + "type" : 1, + "command" : "video/zoom/out" + }, + { + "type" : 1, + "command" : "video/jump/start" + }, + { + "type" : 1, + "command" : "video/jump/end" + }, + { + "type" : 1, + "command" : "time/snap/start_video" + }, + { + "type" : 1, + "command" : "time/snap/end_video" + }, + { + "type" : 1, + "command" : "subtitle/select/visible" + }, + { + "type" : 1, + "command" : "time/snap/scene" + }, + { + "type" : 1, + "command" : "time/snap/frame" + }, + { + "type" : 1, + "command" : "tool/style/manager" + }, + { + "type" : 1, + "command" : "subtitle/properties" + }, + { + "type" : 1, + "command" : "subtitle/attachment" + }, + { + "type" : 1, + "command" : "tool/font_collector" + }, + { + "type" : 1, + "command" : "am/manager" + }, + { + "type" : 1, + "command" : "tool/assdraw" + }, + { + "type" : 1, + "command" : "time/shift" + }, + { + "type" : 1, + "command" : "tool/style/assistant" + }, + { + "type" : 1, + "command" : "tool/translation_assistant" + }, + { + "type" : 1, + "command" : "tool/resampleres" + }, + { + "type" : 1, + "command" : "tool/time/postprocess" + }, + { + "type" : 1, + "command" : "tool/time/kanji" + }, + { + "type" : 1, + "command" : "subtitle/spellcheck" + }, + { + "type" : 1, + "command" : "app/options" + }, + { + "type" : 1, + "command" : "grid/tag/cycle_hiding" + } + ] +} diff --git a/aegisub/src/main.cpp b/aegisub/src/main.cpp index ed066efba..a512d06b6 100644 --- a/aegisub/src/main.cpp +++ b/aegisub/src/main.cpp @@ -50,6 +50,12 @@ #include #endif +#include "aegisub/menu.h" +#include "command/command.h" +#include "command/icon.h" +#include "aegisub/toolbar.h" +#include "aegisub/hotkey.h" + #include "ass_dialogue.h" #include "ass_export_filter.h" #include "ass_file.h" @@ -63,7 +69,6 @@ #include "compat.h" #include "export_framerate.h" #include "frame_main.h" -#include "hotkeys.h" #include "main.h" #include "libresrc/libresrc.h" #include "plugin_manager.h" @@ -75,6 +80,9 @@ #include #include #include +#include + + namespace config { agi::Options *opt; @@ -153,11 +161,40 @@ static void wxAssertHandler(const wxString &file, int line, const wxString &func /// @brief Gets called when application starts. /// @return bool bool AegisubApp::OnInit() { + + // logging. + const std::string path_log(StandardPaths::DecodePath(_T("?user/log/"))); + wxFileName::Mkdir(path_log, 0777, wxPATH_MKDIR_FULL); + agi::log::log = new agi::log::LogSink(path_log); + + #ifdef _DEBUG emit_stdout = new agi::log::EmitSTDOUT(); emit_stdout->Enable(); #endif + // Init command manager + cmd::cm = new cmd::CommandManager(); + + // Init commands. + cmd::init_command(cmd::cm); + + // Init hotkey keycode->name map. + hotkey::keycode_name_map_init(); + + // Init hotkeys. + const std::string conf_user_hotkey(StandardPaths::DecodePath(_T("?user/hotkey.json"))); + agi::hotkey::hotkey = new agi::hotkey::Hotkey(conf_user_hotkey, GET_DEFAULT_CONFIG(default_hotkey)); + + // Init icons. + icon::icon_init(); + + // Generate menus. + menu::menu = new menu::Menu(); + + // Generate toolbars. + toolbar::toolbar = new toolbar::Toolbar(); + // Install assertion handler // wxSetAssertHandler(wxAssertHandler); @@ -231,11 +268,6 @@ bool AegisubApp::OnInit() { OPT_SET("Version/Last Version")->SetInt(GetSVNRevision()); AssTime::UseMSPrecision = OPT_GET("App/Nonstandard Milisecond Times")->GetBool(); - // Set hotkeys file - StartupLog(_T("Load hotkeys")); - Hotkeys.SetFile(StandardPaths::DecodePath(_T("?user/hotkeys.dat"))); - Hotkeys.Load(); - StartupLog(_T("Initialize final locale")); // Set locale @@ -302,12 +334,18 @@ int AegisubApp::OnExit() { delete plugins; delete config::opt; delete config::mru; + delete agi::hotkey::hotkey; + #ifdef WITH_AUTOMATION delete global_scripts; #endif #ifdef _DEBUG delete emit_stdout; #endif + + // Keep this last! + delete agi::log::log; + return wxApp::OnExit(); } @@ -562,14 +600,14 @@ void AegisubApp::OnMouseWheel(wxMouseEvent &event) { -/// @brief Key pressed -/// @param event -/// +/// @brief Key pressed +/// @param event wxEvent +/// Noone has any idea what this does anymore. void AegisubApp::OnKey(wxKeyEvent &event) { //frame->audioBox->audioDisplay->AddPendingEvent(event); - if (!event.GetSkipped()) { - event.Skip(); - } +// if (!event.GetSkipped()) { +// event.Skip(); +// } } diff --git a/aegisub/src/menu.cpp b/aegisub/src/menu.cpp new file mode 100644 index 000000000..616227a97 --- /dev/null +++ b/aegisub/src/menu.cpp @@ -0,0 +1,164 @@ +// Copyright (c) 2010, Amar Takhar +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// $Id$ + +/// @file menu.cpp +/// @brief Dynamic menu and toolbar generator. +/// @ingroup menu + +#include "config.h" + +#ifndef AGI_PRE +#include + +#include + +#include +#endif + +#include +#include +#include + +#include "aegisub/menu.h" +#include "command/command.h" +#include "libresrc/libresrc.h" +#include "main.h" + +namespace menu { + +menu::Menu *menu; + +Menu::Menu() { + + main_menu = new wxMenuBar(); + + std::istringstream *stream = new std::istringstream(GET_DEFAULT_CONFIG(default_menu)); + json::UnknownElement menu_root = agi::json_util::parse(stream); + + LOG_D("menu/init") << "Generating Menus"; + json::Object object = menu_root; + + for (json::Object::const_iterator index(object.Begin()); index != object.End(); index++) { + const json::Object::Member& member = *index; +// const json::UnknownElement& element = member.element; + + const json::Array& array = member.element; + BuildMenu(member.name, array); + + } +} + +Menu::~Menu() {} + + +wxMenu* Menu::GetMenu(std::string name) { + + MTMap::iterator index; + + if ((index = map.find(name)) != map.end()) { + return index->second; + } + + LOG_E("menu/invalid") << "Invalid index name: " << name; + throw MenuInvalidName("Unknown index"); +} + + + + +wxMenu* Menu::BuildMenu(std::string name, const json::Array& array, int submenu) { + wxMenu *menu = new wxMenu(); + + + for (json::Array::const_iterator index(array.Begin()); index != array.End(); index++) { + std::string name_sub = name; + + const json::Object& obj = *index; + const json::Number& type_number = obj["type"]; + int type = type_number.Value(); + + if (type == Menu::Spacer) { + menu->AppendSeparator(); + continue; + } + + + const json::String& command = obj["command"]; + std::string name_submenu = name_sub + "/" + command.Value(); + + + cmd::Command *cmd; + if (type == Menu::Submenu) { + cmd = cmd::get(name_submenu); + } else { + cmd = cmd::get(command.Value()); + } + + wxString display = cmd->StrMenu(); + wxString descr = cmd->StrHelp(); + + + + + switch (type) { + case Menu::Option: { + wxMenuItem *menu_item = new wxMenuItem(menu, cmd::id(command.Value()), wxString(display), wxString(descr), wxITEM_NORMAL); + menu->Append(menu_item); + } + break; + + case Menu::Check: { + menu->AppendCheckItem(cmd::id(command.Value()), wxString(display), wxString(descr)); + } + break; + + case Menu::Radio: { + menu->AppendRadioItem(cmd::id(command.Value()), wxString(display), wxString(descr)); + } + break; + + case Menu::Recent: { + wxMenu *menu_new = new wxMenu(); + wxMenuItem *menu_item = new wxMenuItem(menu, cmd::id(command.Value()), wxString(display), wxString(descr), wxITEM_NORMAL, menu_new); + menu->Append(menu_item); + map.insert(MTPair(command.Value(), menu_new)); + + } + break; + + case Menu::Submenu: { + + const json::Array& arr = obj["contents"]; + + wxMenu *menu_new = BuildMenu(name_sub.append("/").append(command), arr, 1); + map.insert(MTPair(name_submenu, menu_new)); + + if (submenu) { + wxMenuItem *menu_item = new wxMenuItem(menu, cmd::id(name_sub), wxString(display), wxString(descr), wxITEM_NORMAL, menu_new); + menu->Append(menu_item); + } else { + main_menu->Append(menu_new, wxString(display)); + } + } + break; + } + + } // for index + + return menu; +} + +} // namespace menu diff --git a/aegisub/src/run.sh b/aegisub/src/run.sh new file mode 100755 index 000000000..286f0b93f --- /dev/null +++ b/aegisub/src/run.sh @@ -0,0 +1,17 @@ +#!/bin/sh +BIN="aegisub-3.0" + +if ! test -x ${BIN}; then + echo "${BIN} does not exist"; + exit 1; +fi + +case "$1" in + "gdb") + LD_LIBRARY_PATH="../libaegisub" exec gdb ./${BIN} + ;; + *) + LD_LIBRARY_PATH="../libaegisub" exec ./${BIN} + ;; +esac + diff --git a/aegisub/src/standard_paths.cpp b/aegisub/src/standard_paths.cpp index 4514452c8..ff747c61f 100644 --- a/aegisub/src/standard_paths.cpp +++ b/aegisub/src/standard_paths.cpp @@ -77,7 +77,7 @@ StandardPaths::StandardPaths() { wxString userDir = paths.GetUserDataDir() + _T("-") + _T(AEGISUB_VERSION_DATA); #else wxString dataDir = paths.GetDataDir() + _T("/") + _T(AEGISUB_VERSION_DATA); - wxString userDir = paths.GetUserDataDir() + _T("-") + _T(AEGISUB_VERSION_DATA); + wxString userDir = paths.GetUserConfigDir() + _T("/.aegisub-") + _T(AEGISUB_VERSION_DATA); #endif wxString tempDir = paths.GetTempDir(); diff --git a/aegisub/src/subs_edit_box.cpp b/aegisub/src/subs_edit_box.cpp index c99d58628..e905191bf 100644 --- a/aegisub/src/subs_edit_box.cpp +++ b/aegisub/src/subs_edit_box.cpp @@ -54,6 +54,8 @@ #include #endif +#include "aegisub/hotkey.h" + #include "ass_dialogue.h" #include "ass_file.h" #include "ass_override.h" @@ -424,6 +426,10 @@ void SubsEditBox::UpdateFrameTiming(agi::vfr::Framerate const& fps) { } void SubsEditBox::OnKeyDown(wxKeyEvent &event) { + + hotkey::check("Subtitle Edit Box", event.GetKeyCode(), event.GetUnicodeKey(), event.GetModifiers()); + event.StopPropagation(); + int key = event.GetKeyCode(); if (line && (key == WXK_RETURN || key == WXK_NUMPAD_ENTER)) { NextLine(); diff --git a/aegisub/src/subs_grid.cpp b/aegisub/src/subs_grid.cpp index c31daf417..1922f95f7 100644 --- a/aegisub/src/subs_grid.cpp +++ b/aegisub/src/subs_grid.cpp @@ -46,7 +46,9 @@ #include #endif +#include "aegisub/hotkey.h" #include "include/aegisub/audio_provider.h" + #include "ass_file.h" #include "ass_karaoke.h" #include "ass_override.h" @@ -58,7 +60,6 @@ #include "charset_conv.h" #include "dialog_paste_over.h" #include "frame_main.h" -#include "hotkeys.h" #include "main.h" #include "subs_edit_box.h" #include "subs_grid.h" @@ -246,6 +247,12 @@ void SubtitlesGrid::OnShowColMenu(wxCommandEvent &event) { /// @brief Process keyboard events /// @param event void SubtitlesGrid::OnKeyDown(wxKeyEvent &event) { + + hotkey::check("Subtitle Grid", event.GetKeyCode(), event.GetUnicodeKey(), event.GetModifiers()); + event.StopPropagation(); + +//H Fix below. +/* // Get key #ifdef __APPLE__ Hotkeys.SetPressed(event.GetKeyCode(),event.m_metaDown,event.m_altDown,event.m_shiftDown); @@ -330,6 +337,7 @@ void SubtitlesGrid::OnKeyDown(wxKeyEvent &event) { } event.Skip(); +*/ } void SubtitlesGrid::OnDuplicate (wxCommandEvent &) { diff --git a/aegisub/src/subs_grid.h b/aegisub/src/subs_grid.h index f5225a466..a19a83fdb 100644 --- a/aegisub/src/subs_grid.h +++ b/aegisub/src/subs_grid.h @@ -34,6 +34,8 @@ /// @ingroup main_ui /// +#pragma once + #ifndef AGI_PRE #include #include diff --git a/aegisub/src/toolbar.cpp b/aegisub/src/toolbar.cpp new file mode 100644 index 000000000..9b1ccc0fa --- /dev/null +++ b/aegisub/src/toolbar.cpp @@ -0,0 +1,97 @@ +// Copyright (c) 2010, Amar Takhar +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +// $Id$ + +/// @file menutool.cpp +/// @brief Dynamic menu toolbar generator. +/// @ingroup toolbar menu + +#include "config.h" + +#ifndef AGI_PRE +#include + +#include +#endif + +#include +#include +#include + +#include "aegisub/toolbar.h" +#include "libresrc/libresrc.h" +#include "command/command.h" + + +namespace toolbar { + +Toolbar *toolbar; + +Toolbar::Toolbar() {} + +Toolbar::~Toolbar() {} + + +void Toolbar::GetToolbar(std::string name, wxToolBar *toolbar) { + +// TbMap::iterator index; + +// if ((index = map.find(name)) != map.end()) { +// return index->second; +// } + +// throw ToolbarInvalidName("Unknown index"); + + LOG_D("toolbar/init") << "Generating " << name << " toolbar."; + + std::istringstream *stream = new std::istringstream(GET_DEFAULT_CONFIG(default_toolbar)); + json::UnknownElement toolbar_root = agi::json_util::parse(stream); + + const json::Array& arr = toolbar_root[name]; + + BuildToolbar(toolbar, arr); +// map.insert(TbPair(name, toolbar)); +} + + +void Toolbar::BuildToolbar(wxToolBar *toolbar, const json::Array& array) { + + for (json::Array::const_iterator index(array.Begin()); index != array.End(); index++) { + + const json::Object& obj = *index; + const json::Number& type_number = obj["type"]; + int type = type_number.Value(); + + const json::String& command = obj["command"]; + cmd::Command *cmd = cmd::get(command.Value()); + + // this is dumb. + wxBitmap *bitmap = cmd->Icon(24); + wxBitmap icon = bitmap->GetSubBitmap(wxRect(0, 0, bitmap->GetWidth(), bitmap->GetHeight())); + + switch (type) { + case Toolbar::Standard: { + toolbar->AddTool(cmd::id(command.Value()), cmd->StrMenu(), icon, cmd->StrHelp(), wxITEM_NORMAL); + } + break; + } + + } // for index + +} + +} // namespace toolbar + + diff --git a/aegisub/src/tooltip_manager.cpp b/aegisub/src/tooltip_manager.cpp index c14784e0a..9f47f190f 100644 --- a/aegisub/src/tooltip_manager.cpp +++ b/aegisub/src/tooltip_manager.cpp @@ -39,7 +39,6 @@ // Headers #include "config.h" -#include "hotkeys.h" #include "tooltip_manager.h" @@ -113,7 +112,7 @@ void ToolTipBinding::Update() { wxString finalTip = toolTip; wxArrayString hotkeysLeft = hotkeys; while (hotkeysLeft.Count()) { - finalTip.Replace(_T("%KEY%"),Hotkeys.GetText(hotkeysLeft[0]),false); +//H finalTip.Replace(_T("%KEY%"),Hotkeys.GetText(hotkeysLeft[0]),false); hotkeysLeft.RemoveAt(0); } window->SetToolTip(finalTip); diff --git a/aegisub/src/utils.cpp b/aegisub/src/utils.cpp index 69001e9a8..bdaa1f438 100644 --- a/aegisub/src/utils.cpp +++ b/aegisub/src/utils.cpp @@ -47,7 +47,6 @@ #include #include #include -#include #include #endif @@ -175,26 +174,6 @@ wxString PrettySize(int bytes) { -/// @brief Append a menu item with bitmap -/// @param parentMenu -/// @param id -/// @param text -/// @param help -/// @param bmp -/// @param pos -/// @return -/// -wxMenuItem* AppendBitmapMenuItem (wxMenu* parentMenu,int id,wxString text,wxString help,wxBitmap bmp,int pos) { - wxMenuItem *cur = new wxMenuItem(parentMenu,id,text,help); - // Mac software does not use icons in menus so we shouldn't either - cur->SetBitmap(bmp); - if (pos == -1) parentMenu->Append(cur); - else parentMenu->Insert(pos,cur); - return cur; -} - - - /// @brief Code from http://bob.allegronetwork.com/prog/tricks.html Get the smallest power of two that is greater or equal to x /// @param x /// @return diff --git a/aegisub/src/video_box.h b/aegisub/src/video_box.h index 1bc72c9a5..df8c802da 100644 --- a/aegisub/src/video_box.h +++ b/aegisub/src/video_box.h @@ -34,6 +34,8 @@ /// @ingroup main_ui video /// +#pragma once + #ifndef AGI_PRE #include #include diff --git a/aegisub/src/video_display.cpp b/aegisub/src/video_display.cpp index aae95a357..2c70f9b29 100644 --- a/aegisub/src/video_display.cpp +++ b/aegisub/src/video_display.cpp @@ -56,12 +56,13 @@ #include #endif +#include "aegisub/hotkey.h" + #include "video_display.h" #include "selection_controller.h" #include "ass_dialogue.h" #include "ass_file.h" -#include "hotkeys.h" #include "main.h" #include "subs_grid.h" #include "threaded_frame_source.h" @@ -94,7 +95,7 @@ enum { BEGIN_EVENT_TABLE(VideoDisplay, wxGLCanvas) EVT_MOUSE_EVENTS(VideoDisplay::OnMouseEvent) - EVT_KEY_DOWN(VideoDisplay::OnKey) + EVT_KEY_DOWN(VideoDisplay::OnKeyDown) EVT_PAINT(VideoDisplay::OnPaint) EVT_SIZE(VideoDisplay::OnSizeEvent) EVT_ERASE_BACKGROUND(VideoDisplay::OnEraseBackground) @@ -498,7 +499,11 @@ void VideoDisplay::OnMouseEvent(wxMouseEvent& event) { tool->OnMouseEvent(event); ShowCursor(activeMode != Video_Mode_Standard); } -void VideoDisplay::OnKey(wxKeyEvent &event) { +void VideoDisplay::OnKeyDown(wxKeyEvent &event) { + hotkey::check("Video Display", event.GetKeyCode(), event.GetUnicodeKey(), event.GetModifiers()); + event.StopPropagation(); + +/* int key = event.GetKeyCode(); #ifdef __APPLE__ Hotkeys.SetPressed(key, event.m_metaDown, event.m_altDown, event.m_shiftDown); @@ -514,8 +519,10 @@ void VideoDisplay::OnKey(wxKeyEvent &event) { else if (Hotkeys.IsPressed(L"Visual Tool Rectangular Clip")) SetMode(Video_Mode_Clip); else if (Hotkeys.IsPressed(L"Visual Tool Vector Clip")) SetMode(Video_Mode_Vector_Clip); event.Skip(); +*/ } + void VideoDisplay::SetZoom(double value) { zoomValue = std::max(value, .125); if (zoomBox) zoomBox->SetValue(wxString::Format("%g%%", zoomValue * 100.)); diff --git a/aegisub/src/video_display.h b/aegisub/src/video_display.h index c7a22cd3a..2fea0916a 100644 --- a/aegisub/src/video_display.h +++ b/aegisub/src/video_display.h @@ -110,7 +110,7 @@ class VideoDisplay : public wxGLCanvas { void OnPaint(wxPaintEvent& event); /// @brief Key event handler /// @param event - void OnKey(wxKeyEvent &event); + void OnKeyDown(wxKeyEvent &event); /// @brief Mouse event handler /// @param event void OnMouseEvent(wxMouseEvent& event);