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)).
This commit is contained in:
Thomas Goyne 2012-12-06 10:01:47 -08:00
parent 1b15a753a1
commit 422cfb153f
7 changed files with 73 additions and 0 deletions

View file

@ -349,6 +349,7 @@
},
"Subtitle" : {
"Character Limit" : 40,
"Default Resolution" : {
"Auto" : true,
"Height" : 720,

View file

@ -349,6 +349,7 @@
},
"Subtitle" : {
"Character Limit" : 40,
"Default Resolution" : {
"Auto" : true,
"Height" : 720,

View file

@ -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");

View file

@ -41,6 +41,7 @@
#include <wx/checkbox.h>
#include <wx/combobox.h>
#include <wx/radiobut.h>
#include <wx/settings.h>
#include <wx/sizer.h>
#include <wx/spinctrl.h>
@ -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));
}

View file

@ -103,6 +103,7 @@ class SubsEditBox : public wxPanel {
Placeholder<wxComboBox> *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);

View file

@ -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 *) { }

View file

@ -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