From 422cfb153faa96ac1610d60e846d344f11bfb8f3 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Thu, 6 Dec 2012 10:01:47 -0800 Subject: [PATCH] Add a box with the character count of the longest line Character counts are a pretty terrible measure of anything, but it's still the main measure of length used in most subtitling standards (because subtitling standards are written under the assumption that the tools are terrible (which is generally an accurate assumption)). --- aegisub/src/libresrc/default_config.json | 1 + aegisub/src/libresrc/osx/default_config.json | 1 + aegisub/src/preferences.cpp | 1 + aegisub/src/subs_edit_box.cpp | 18 ++++++++ aegisub/src/subs_edit_box.h | 4 ++ aegisub/src/utils.cpp | 45 ++++++++++++++++++++ aegisub/src/utils.h | 3 ++ 7 files changed, 73 insertions(+) diff --git a/aegisub/src/libresrc/default_config.json b/aegisub/src/libresrc/default_config.json index f0238777b..fcda84e47 100644 --- a/aegisub/src/libresrc/default_config.json +++ b/aegisub/src/libresrc/default_config.json @@ -349,6 +349,7 @@ }, "Subtitle" : { + "Character Limit" : 40, "Default Resolution" : { "Auto" : true, "Height" : 720, diff --git a/aegisub/src/libresrc/osx/default_config.json b/aegisub/src/libresrc/osx/default_config.json index 70d2bf383..33c62eb84 100644 --- a/aegisub/src/libresrc/osx/default_config.json +++ b/aegisub/src/libresrc/osx/default_config.json @@ -349,6 +349,7 @@ }, "Subtitle" : { + "Character Limit" : 40, "Default Resolution" : { "Auto" : true, "Height" : 720, diff --git a/aegisub/src/preferences.cpp b/aegisub/src/preferences.cpp index 7e55b0217..3cf62ea99 100644 --- a/aegisub/src/preferences.cpp +++ b/aegisub/src/preferences.cpp @@ -199,6 +199,7 @@ Interface::Interface(wxTreebook *book, Preferences *parent): OptionPage(book, pa OptionAdd(edit_box, _("Enable syntax highlighting"), "Subtitle/Highlight/Syntax"); OptionBrowse(edit_box, _("Dictionaries path"), "Path/Dictionary"); OptionFont(edit_box, "Subtitle/Edit Box/"); + OptionAdd(edit_box, _("Maximum characters per line"), "Subtitle/Character Limit", 0, 1000); wxFlexGridSizer *grid = PageSizer(_("Grid")); OptionAdd(grid, _("Allow grid to take focus"), "Subtitle/Grid/Focus Allow"); diff --git a/aegisub/src/subs_edit_box.cpp b/aegisub/src/subs_edit_box.cpp index 27efa2c67..519ba0834 100644 --- a/aegisub/src/subs_edit_box.cpp +++ b/aegisub/src/subs_edit_box.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,7 @@ #include "ass_dialogue.h" #include "ass_file.h" #include "command/command.h" +#include "compat.h" #include "dialog_search_replace.h" #include "include/aegisub/context.h" #include "include/aegisub/hotkey.h" @@ -120,6 +122,10 @@ SubsEditBox::SubsEditBox(wxWindow *parent, agi::Context *context) Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &SubsEditBox::OnEffectChange, this, Effect->GetId()); TopSizer->Add(Effect, 3, wxALIGN_CENTER, 5); + CharCount = new wxTextCtrl(this, -1, "0", wxDefaultPosition, wxSize(30, -1), wxTE_READONLY | wxTE_CENTER); + CharCount->SetToolTip(_("Number of characters in the longest line of this subtitle.")); + TopSizer->Add(CharCount, 0, wxALIGN_CENTER, 5); + // Middle controls MiddleSizer = new wxBoxSizer(wxHORIZONTAL); @@ -287,6 +293,7 @@ void SubsEditBox::OnCommit(int type) { if (type & AssFile::COMMIT_DIAG_TEXT) { TextEdit->SetTextTo(line->Text); + UpdateCharacterCount(line->Text); } if (type & AssFile::COMMIT_DIAG_META) { @@ -375,6 +382,7 @@ void SubsEditBox::OnChange(wxStyledTextEvent &event) { if (event.GetModificationType() & wxSTC_STARTACTION) commitId = -1; CommitText(_("modify text")); + UpdateCharacterCount(line->Text); } } @@ -514,3 +522,13 @@ void SubsEditBox::CallCommand(const char *cmd_name) { cmd::call(cmd_name, c); TextEdit->SetFocus(); } + +void SubsEditBox::UpdateCharacterCount(wxString const& text) { + size_t length = MaxLineLength(text); + CharCount->SetValue(wxString::Format("%lu", (unsigned long)length)); + size_t limit = (size_t)OPT_GET("Subtitle/Character Limit")->GetInt(); + if (limit && length > limit) + CharCount->SetBackgroundColour(to_wx(OPT_GET("Colour/Subtitle/Syntax/Background/Error")->GetColor())); + else + CharCount->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +} diff --git a/aegisub/src/subs_edit_box.h b/aegisub/src/subs_edit_box.h index 9cc03ec36..ff5efdd0f 100644 --- a/aegisub/src/subs_edit_box.h +++ b/aegisub/src/subs_edit_box.h @@ -103,6 +103,7 @@ class SubsEditBox : public wxPanel { Placeholder *Effect; wxRadioButton *ByTime; wxRadioButton *ByFrame; + wxTextCtrl *CharCount; wxSizer *TopSizer; wxSizer *MiddleBotSizer; @@ -184,6 +185,9 @@ class SubsEditBox : public wxPanel { /// @brief Enable or disable frame timing mode void UpdateFrameTiming(agi::vfr::Framerate const& fps); + /// Update the character count box for the given text + void UpdateCharacterCount(wxString const& text); + /// Call a command the restore focus to the edit box void CallCommand(const char *cmd_name); diff --git a/aegisub/src/utils.cpp b/aegisub/src/utils.cpp index 1ae63d4d6..5cd185cc9 100644 --- a/aegisub/src/utils.cpp +++ b/aegisub/src/utils.cpp @@ -391,6 +391,51 @@ void CleanCache(wxString const& directory, wxString const& file_type, int64_t ma LOG_D("utils/clean_cache") << "thread started successfully"; } +size_t MaxLineLength(wxString const& text) { + size_t max_line_length = 0; + size_t current_line_length = 0; + bool last_was_slash = false; + bool in_ovr = false; + + for (auto const& c : text) { + if (in_ovr) { + in_ovr = c != '}'; + continue; + } + + if (c == '\\') { + current_line_length += last_was_slash; // for the slash before this one + last_was_slash = true; + continue; + } + + if (last_was_slash) { + last_was_slash = false; + if (c == 'h') { + ++current_line_length; + continue; + } + + if (c == 'n' || c == 'N') { + max_line_length = std::max(max_line_length, current_line_length); + current_line_length = 0; + continue; + } + + // Not actually an escape so add the character for the slash and fall through + ++current_line_length; + } + + if (c == '{') + in_ovr = true; + else + ++current_line_length; + } + + current_line_length += last_was_slash; + return std::max(max_line_length, current_line_length); +} + // OS X implementation in osx_utils.mm #ifndef __WXOSX_COCOA__ void AddFullScreenButton(wxWindow *) { } diff --git a/aegisub/src/utils.h b/aegisub/src/utils.h index c22fdd8c0..4330b845c 100644 --- a/aegisub/src/utils.h +++ b/aegisub/src/utils.h @@ -74,6 +74,9 @@ bool StringEmptyOrWhitespace(const wxString &str); int AegiStringToInt(const wxString &str,int start=0,int end=-1); int AegiStringToFix(const wxString &str,size_t decimalPlaces,int start=0,int end=-1); +/// Get the length in characters of the longest line in the given text +size_t MaxLineLength(wxString const& text); + /// @brief Launch a new copy of Aegisub. /// /// Contrary to what the name suggests, this does not close the currently