From fde4a7815d4c13911bf15f9aa5d4a25ee09d7b3f Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 20 Jul 2010 03:11:11 +0000 Subject: [PATCH] Make the subtitle edit box auto-commit all changes This happens to fix most of the undo issues, as it's now much harder to have uncommitted changes to the file. Closes #355 and #586. Originally committed to SVN as r4699. --- .../aegisub_vs2008/aegisub_vs2008.vcproj | 16 - aegisub/libaegisub/common/vfr.cpp | 2 + aegisub/src/agi_pre.h | 13 +- aegisub/src/ass_dialogue.h | 2 + aegisub/src/ass_file.cpp | 23 +- aegisub/src/ass_time.cpp | 7 + aegisub/src/ass_time.h | 7 +- aegisub/src/audio_display.cpp | 7 +- aegisub/src/base_grid.cpp | 11 +- aegisub/src/dialog_resample.cpp | 2 - aegisub/src/dialog_search_replace.cpp | 2 +- aegisub/src/dialog_shift_times.cpp | 2 - aegisub/src/dialog_spellchecker.cpp | 1 + aegisub/src/dialog_translation.cpp | 1 + aegisub/src/dialog_translation.h | 29 +- aegisub/src/frame_main.cpp | 8 +- aegisub/src/frame_main.h | 2 - aegisub/src/frame_main_events.cpp | 35 +- aegisub/src/hilimod_textctrl.cpp | 127 -- aegisub/src/hilimod_textctrl.h | 87 - aegisub/src/idle_field_event.cpp | 181 -- aegisub/src/idle_field_event.h | 95 - aegisub/src/scintilla_text_ctrl.h | 13 - aegisub/src/subs_edit_box.cpp | 1780 ++++++----------- aegisub/src/subs_edit_box.h | 378 +--- aegisub/src/subs_edit_ctrl.cpp | 521 ++--- aegisub/src/subs_edit_ctrl.h | 95 +- aegisub/src/subs_grid.cpp | 329 +-- aegisub/src/subs_grid.h | 116 +- aegisub/src/timeedit_ctrl.cpp | 83 +- aegisub/src/timeedit_ctrl.h | 33 +- aegisub/src/video_context.cpp | 21 +- aegisub/src/video_context.h | 6 +- aegisub/src/visual_tool.cpp | 11 +- aegisub/src/visual_tool.h | 1 + aegisub/src/visual_tool_clip.cpp | 1 - aegisub/src/visual_tool_cross.cpp | 1 - aegisub/src/visual_tool_drag.cpp | 1 - aegisub/src/visual_tool_rotatexy.cpp | 1 - aegisub/src/visual_tool_rotatez.cpp | 1 - aegisub/src/visual_tool_scale.cpp | 1 - 41 files changed, 1120 insertions(+), 2933 deletions(-) delete mode 100644 aegisub/src/hilimod_textctrl.cpp delete mode 100644 aegisub/src/hilimod_textctrl.h delete mode 100644 aegisub/src/idle_field_event.cpp delete mode 100644 aegisub/src/idle_field_event.h diff --git a/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj b/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj index 12868ea65..ec62f4f53 100644 --- a/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj +++ b/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj @@ -671,14 +671,6 @@ RelativePath="..\..\src\help_button.h" > - - - - @@ -819,14 +811,6 @@ RelativePath="..\..\src\font_file_lister_freetype.h" > - - - - diff --git a/aegisub/libaegisub/common/vfr.cpp b/aegisub/libaegisub/common/vfr.cpp index b7fb117a6..43edb5408 100644 --- a/aegisub/libaegisub/common/vfr.cpp +++ b/aegisub/libaegisub/common/vfr.cpp @@ -22,8 +22,10 @@ #ifndef LAGI_PRE #include +#include #include #include +#include #include #endif diff --git a/aegisub/src/agi_pre.h b/aegisub/src/agi_pre.h index 175b349e4..1475ce476 100644 --- a/aegisub/src/agi_pre.h +++ b/aegisub/src/agi_pre.h @@ -72,17 +72,20 @@ #include #include #include -#ifdef _WIN32 -#include -#else -#include -#endif #include #include #include #include #include +#ifdef _WIN32 +#include +#include +#else +#include +#include +#endif + #include "boost/shared_ptr.hpp" // General headers diff --git a/aegisub/src/ass_dialogue.h b/aegisub/src/ass_dialogue.h index 4ed3abe79..24dc69336 100644 --- a/aegisub/src/ass_dialogue.h +++ b/aegisub/src/ass_dialogue.h @@ -221,6 +221,8 @@ public: /// Do nothing void SetEntryData(wxString) { } + template + void SetMarginString(const wxString value) { SetMarginString(value, which);} /// @brief Set a margin /// @param value New value of the margin /// @param which 0 = left, 1 = right, 2 = vertical/top, 3 = bottom diff --git a/aegisub/src/ass_file.cpp b/aegisub/src/ass_file.cpp index a6fe1bba5..c048e43ae 100644 --- a/aegisub/src/ass_file.cpp +++ b/aegisub/src/ass_file.cpp @@ -73,11 +73,12 @@ AssFile::AssFile () { } -/// @brief AssFile destructor +/// @brief AssFile destructor AssFile::~AssFile() { delete_clear(Line); } +/// @brief Load generic subs void AssFile::Load (const wxString &_filename,wxString charset,bool addToRecent) { bool ok = false; Clear(); @@ -447,11 +448,11 @@ void AssFile::LoadDefault (bool defline) { AddLine(_T("PlayResX: 640"),_T("[Script Info]"),version); AddLine(_T("PlayResY: 480"),_T("[Script Info]"),version); AddLine(_T("ScaledBorderAndShadow: yes"),_T("[Script Info]"),version); - AddLine(_T(""),_T("[Script Info]"),version); + AddLine("",_T("[Script Info]"),version); AddLine(_T("[V4+ Styles]"),_T("[V4+ Styles]"),version); AddLine(_T("Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding"),_T("[V4+ Styles]"),version); AddLine(defstyle.GetEntryData(),_T("[V4+ Styles]"),version); - AddLine(_T(""),_T("[V4+ Styles]"),version); + AddLine("",_T("[V4+ Styles]"),version); AddLine(_T("[Events]"),_T("[Events]"),version); AddLine(_T("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"),_T("[Events]"),version); @@ -506,7 +507,7 @@ void AssFile::InsertStyle (AssStyle *style) { // No styles found, add them if (lastStyle == Line.end()) { // Add space - curEntry = new AssEntry(_T("")); + curEntry = new AssEntry(""); curEntry->group = lastGroup; Line.push_back(curEntry); @@ -559,10 +560,10 @@ void AssFile::InsertAttachment (AssAttachment *attach) { // Otherwise, create the [Fonts] group and insert else { int version=1; - AddLine(_T(""),Line.back()->group,version); + AddLine("",Line.back()->group,version); AddLine(attach->group,attach->group,version); Line.push_back(attach); - AddLine(_T(""),attach->group,version); + AddLine("",attach->group,version); } } @@ -640,7 +641,7 @@ void AssFile::SetScriptInfo(const wxString _key,const wxString value) { // Found if (curText.StartsWith(key)) { // Set value - if (value != _T("")) { + if (value != "") { wxString result = _key; result += _T(": "); result += value; @@ -660,7 +661,7 @@ void AssFile::SetScriptInfo(const wxString _key,const wxString value) { // Add else if (GotIn) { - if (value != _T("")) { + if (value != "") { wxString result = _key; result += _T(": "); result += value; @@ -762,7 +763,7 @@ wxString AssFile::GetWildcardList(int mode) { if (mode == 0) return SubtitleFormat::GetWildcards(0); else if (mode == 1) return _T("Advanced Substation Alpha (*.ass)|*.ass"); else if (mode == 2) return SubtitleFormat::GetWildcards(1); - else return _T(""); + else return ""; } int AssFile::Commit(wxString desc, int amendId) { @@ -844,9 +845,7 @@ void AssFile::Sort(std::list &lst, CompFunc comp) { entryIter end = begin; while (end != lst.end() && dynamic_cast(*end)) ++end; - // std::list::sort doesn't support sorting only part of the list, but - // splice is constant-time, so just sort a temp list with only the part we - // want sorted + // used instead of std::list::sort for partial list sorting std::list tmp; tmp.splice(tmp.begin(), lst, begin, end); tmp.sort(compE); diff --git a/aegisub/src/ass_time.cpp b/aegisub/src/ass_time.cpp index 8ca809c45..78ac0bc8a 100644 --- a/aegisub/src/ass_time.cpp +++ b/aegisub/src/ass_time.cpp @@ -322,6 +322,13 @@ bool operator != (const AssTime &t1, const AssTime &t2) { return (t1.GetMS() != t2.GetMS()); } +AssTime operator + (const AssTime &t1, const AssTime &t2) { + return AssTime(t1.GetMS() + t2.GetMS()); +} + +AssTime operator - (const AssTime &t1, const AssTime &t2) { + return AssTime(t1.GetMS() - t2.GetMS()); +} /// DOCME diff --git a/aegisub/src/ass_time.h b/aegisub/src/ass_time.h index b6dbe5d1c..3071b32b7 100644 --- a/aegisub/src/ass_time.h +++ b/aegisub/src/ass_time.h @@ -72,8 +72,8 @@ public: int GetTimeMiliseconds(); int GetTimeCentiseconds(); - int GetMS() const; // Returns miliseconds - void SetMS(int ms); // Sets values to miliseconds + int GetMS() const; // Returns milliseconds + void SetMS(int ms); // Sets values to milliseconds void ParseASS(const wxString text); // Sets value to text-form time, in ASS format void ParseSRT(const wxString text); // Sets value to text-form time, in SRT format wxString GetASSFormated(bool ms=false) const; // Returns the ASS representation of time @@ -87,6 +87,9 @@ bool operator < (const AssTime &t1, const AssTime &t2); bool operator > (const AssTime &t1, const AssTime &t2); bool operator <= (const AssTime &t1, const AssTime &t2); bool operator >= (const AssTime &t1, const AssTime &t2); +// Arithmetic operators +AssTime operator + (const AssTime &t1, const AssTime &t2); +AssTime operator - (const AssTime &t1, const AssTime &t2); diff --git a/aegisub/src/audio_display.cpp b/aegisub/src/audio_display.cpp index 7c841564d..23bded046 100644 --- a/aegisub/src/audio_display.cpp +++ b/aegisub/src/audio_display.cpp @@ -61,6 +61,7 @@ #include "main.h" #include "standard_paths.h" #include "subs_edit_box.h" +#include "subs_edit_ctrl.h" #include "subs_grid.h" #include "timeedit_ctrl.h" #include "utils.h" @@ -2320,8 +2321,8 @@ void AudioDisplay::OnLoseFocus(wxFocusEvent &event) { /// @brief Update time edit controls void AudioDisplay::UpdateTimeEditCtrls() { - grid->editBox->StartTime->SetTime(curStartMS,true); - grid->editBox->EndTime->SetTime(curEndMS,true); - grid->editBox->Duration->SetTime(curEndMS-curStartMS,true); + grid->editBox->StartTime->SetTime(curStartMS); + grid->editBox->EndTime->SetTime(curEndMS); + grid->editBox->Duration->SetTime(curEndMS-curStartMS); } diff --git a/aegisub/src/base_grid.cpp b/aegisub/src/base_grid.cpp index 862d4a341..448aaeb34 100644 --- a/aegisub/src/base_grid.cpp +++ b/aegisub/src/base_grid.cpp @@ -42,11 +42,12 @@ #include #endif +#include "base_grid.h" + #include "ass_dialogue.h" #include "ass_file.h" #include "ass_style.h" #include "audio_display.h" -#include "base_grid.h" #include "compat.h" #include "frame_main.h" #include "main.h" @@ -1112,10 +1113,10 @@ int BaseGrid::GetDialogueIndex(AssDialogue *diag) const { bool BaseGrid::IsDisplayed(AssDialogue *line) { VideoContext* con = VideoContext::Get(); if (!con->IsLoaded()) return false; - int f1 = con->FrameAtTime(line->Start.GetMS(),agi::vfr::START); - int f2 = con->FrameAtTime(line->End.GetMS(),agi::vfr::END); - if (f1 <= con->GetFrameN() && f2 >= con->GetFrameN()) return true; - return false; + int frame = con->GetFrameN(); + return + con->FrameAtTime(line->Start.GetMS(),agi::vfr::START) <= frame && + con->FrameAtTime(line->End.GetMS(),agi::vfr::END) >= frame; } /// @brief Key press diff --git a/aegisub/src/dialog_resample.cpp b/aegisub/src/dialog_resample.cpp index 46b6d2052..4ab842757 100644 --- a/aegisub/src/dialog_resample.cpp +++ b/aegisub/src/dialog_resample.cpp @@ -46,7 +46,6 @@ #include "dialog_resample.h" #include "help_button.h" #include "libresrc/libresrc.h" -#include "subs_edit_box.h" #include "subs_grid.h" #include "utils.h" #include "validators.h" @@ -323,7 +322,6 @@ void DialogResample::OnResample (wxCommandEvent &event) { // Flag as modified subs->Commit(_("resolution resampling")); grid->CommitChanges(); - grid->editBox->Update(); EndModal(0); } diff --git a/aegisub/src/dialog_search_replace.cpp b/aegisub/src/dialog_search_replace.cpp index 204ac6ec9..604fe5681 100644 --- a/aegisub/src/dialog_search_replace.cpp +++ b/aegisub/src/dialog_search_replace.cpp @@ -51,6 +51,7 @@ #include "frame_main.h" #include "main.h" #include "subs_edit_box.h" +#include "subs_edit_ctrl.h" #include "subs_grid.h" #include "video_display.h" @@ -545,7 +546,6 @@ void SearchReplaceEngine::ReplaceAll() { if (count > 0) { grid->ass->Commit(_("replace")); grid->CommitChanges(); - grid->editBox->Update(); wxMessageBox(wxString::Format(_("%i matches were replaced."),count)); } diff --git a/aegisub/src/dialog_shift_times.cpp b/aegisub/src/dialog_shift_times.cpp index b36892198..ffc1480df 100644 --- a/aegisub/src/dialog_shift_times.cpp +++ b/aegisub/src/dialog_shift_times.cpp @@ -57,7 +57,6 @@ #include "libresrc/libresrc.h" #include "main.h" #include "standard_paths.h" -#include "subs_edit_box.h" #include "subs_grid.h" #include "utils.h" #include "video_context.h" @@ -312,7 +311,6 @@ void DialogShiftTimes::OnOK(wxCommandEvent &event) { // End dialog grid->ass->Commit(_("shifting")); grid->CommitChanges(); - grid->editBox->Update(); EndModal(0); } diff --git a/aegisub/src/dialog_spellchecker.cpp b/aegisub/src/dialog_spellchecker.cpp index 265cedc6d..7de4e624c 100644 --- a/aegisub/src/dialog_spellchecker.cpp +++ b/aegisub/src/dialog_spellchecker.cpp @@ -52,6 +52,7 @@ #include "main.h" #include "spellchecker_manager.h" #include "subs_edit_box.h" +#include "subs_edit_ctrl.h" #include "subs_grid.h" #include "utils.h" diff --git a/aegisub/src/dialog_translation.cpp b/aegisub/src/dialog_translation.cpp index e8a0adde7..bbb7b4a05 100644 --- a/aegisub/src/dialog_translation.cpp +++ b/aegisub/src/dialog_translation.cpp @@ -52,6 +52,7 @@ #include "hotkeys.h" #include "libresrc/libresrc.h" #include "subs_edit_box.h" +#include "subs_edit_ctrl.h" #include "subs_grid.h" #include "utils.h" #include "video_context.h" diff --git a/aegisub/src/dialog_translation.h b/aegisub/src/dialog_translation.h index 4872ca77c..75b7b569f 100644 --- a/aegisub/src/dialog_translation.h +++ b/aegisub/src/dialog_translation.h @@ -33,26 +33,17 @@ /// @see dialog_translation.cpp /// @ingroup tools_ui/// - - - -/////////// -// Headers #ifndef AGI_PRE #include #include #include #endif -#include "scintilla_text_ctrl.h" - - -////////////// -// Prototypes class AssFile; class AssDialogue; -class SubtitlesGrid; class AudioDisplay; +class ScintillaTextCtrl; +class SubtitlesGrid; class VideoContext; @@ -126,8 +117,6 @@ public: DECLARE_EVENT_TABLE() }; - - /// DOCME /// @class DialogTranslationEvent /// @brief DOCME @@ -147,23 +136,11 @@ public: DECLARE_EVENT_TABLE() }; - -/////// -// IDs +/// Event IDs enum { - - /// DOCME TEXT_ORIGINAL = 1100, - - /// DOCME TEXT_TRANS, - - /// DOCME PREVIEW_CHECK, - - /// DOCME BUTTON_TRANS_PLAY_AUDIO, - - /// DOCME BUTTON_TRANS_PLAY_VIDEO }; diff --git a/aegisub/src/frame_main.cpp b/aegisub/src/frame_main.cpp index 0e9c1e7c6..819208ae3 100644 --- a/aegisub/src/frame_main.cpp +++ b/aegisub/src/frame_main.cpp @@ -73,6 +73,7 @@ #include "main.h" #include "standard_paths.h" #include "subs_edit_box.h" +#include "subs_edit_ctrl.h" #include "subs_grid.h" #include "text_file_reader.h" #include "text_file_writer.h" @@ -604,8 +605,7 @@ void FrameMain::InitContents() { // Top sizer StartupLog(_T("Create subtitle editing box")); - EditBox = new SubsEditBox(Panel,SubsGrid); - EditBox->audio = audioBox->audioDisplay; + EditBox = new SubsEditBox(Panel,SubsGrid, audioBox->audioDisplay); StartupLog(_T("Arrange controls in sizers")); ToolSizer = new wxBoxSizer(wxVERTICAL); ToolSizer->Add(audioBox,0,wxEXPAND | wxBOTTOM,5); @@ -863,7 +863,6 @@ void FrameMain::SetDisplayMode(int video, int audio) { // Update UpdateToolbar(); - EditBox->SetSplitLineMode(); MainSizer->CalcMin(); MainSizer->RecalcSizes(); MainSizer->Layout(); @@ -1138,7 +1137,7 @@ void FrameMain::LoadVideo(wxString file,bool autoload) { } } - SubsGrid->CommitChanges(true); + SubsGrid->CommitChanges(); SetDisplayMode(1,-1); EditBox->UpdateFrameTiming(); @@ -1229,7 +1228,6 @@ void FrameMain::SetAccelerators() { 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)); - entry.push_back(Hotkeys.GetAccelerator(_T("Edit box commit"),Edit_Box_Commit)); // Medusa bool medusaPlay = OPT_GET("Audio/Medusa Timing Hotkeys")->GetBool(); diff --git a/aegisub/src/frame_main.h b/aegisub/src/frame_main.h index 893694411..ebb9b411a 100644 --- a/aegisub/src/frame_main.h +++ b/aegisub/src/frame_main.h @@ -266,7 +266,6 @@ private: void OnSortStart (wxCommandEvent &event); void OnSortEnd (wxCommandEvent &event); void OnSortStyle (wxCommandEvent &event); - void OnEditBoxCommit (wxCommandEvent &event); void OnOpenProperties (wxCommandEvent &event); void OnOpenStylesManager (wxCommandEvent &event); void OnOpenAttachments (wxCommandEvent &event); @@ -508,7 +507,6 @@ enum { Grid_Prev_Line, Grid_Toggle_Tags, - Edit_Box_Commit, Video_Frame_Play, diff --git a/aegisub/src/frame_main_events.cpp b/aegisub/src/frame_main_events.cpp index 2f4e70623..a10c29d84 100644 --- a/aegisub/src/frame_main_events.cpp +++ b/aegisub/src/frame_main_events.cpp @@ -85,6 +85,7 @@ #include "preferences.h" #include "standard_paths.h" #include "subs_edit_box.h" +#include "subs_edit_ctrl.h" #include "subs_grid.h" #include "toggle_bitmap.h" #include "utils.h" @@ -223,7 +224,6 @@ BEGIN_EVENT_TABLE(FrameMain, wxFrame) EVT_MENU(Grid_Next_Line,FrameMain::OnNextLine) EVT_MENU(Grid_Prev_Line,FrameMain::OnPrevLine) EVT_MENU(Grid_Toggle_Tags,FrameMain::OnToggleTags) - EVT_MENU(Edit_Box_Commit,FrameMain::OnEditBoxCommit) EVT_MENU(Medusa_Play, FrameMain::OnMedusaPlay) EVT_MENU(Medusa_Stop, FrameMain::OnMedusaStop) @@ -574,7 +574,6 @@ void FrameMain::OnLog(wxCommandEvent &) { log->Show(1); } - /// @brief Open check updates void FrameMain::OnCheckUpdates(wxCommandEvent &) { PerformVersionCheck(true); @@ -1056,7 +1055,7 @@ void FrameMain::OnAutomationMacro (wxCommandEvent &event) { // Have the grid update its maps, this properly refreshes it to reflect the changed subs SubsGrid->UpdateMaps(); SubsGrid->SetSelectionFromAbsolute(selected_lines); - SubsGrid->CommitChanges(true, false); + SubsGrid->CommitChanges(); SubsGrid->EndBatch(); #endif } @@ -1155,8 +1154,8 @@ void FrameMain::OnShiftToFrame (wxCommandEvent &) { // Commit SubsGrid->ass->Commit(_("shift to frame")); - SubsGrid->CommitChanges(); - SubsGrid->editBox->Update(true,false); + SubsGrid->CommitChanges(false); + SubsGrid->editBox->Update(true); } /// @brief Undo @@ -1474,32 +1473,6 @@ void FrameMain::OnSetTags(wxCommandEvent &event) { SubsGrid->Refresh(false); } -/// @brief Commit Edit Box's changes -/// @param event -void FrameMain::OnEditBoxCommit(wxCommandEvent &event) { - // Find focus - wxWindow *focus = FindFocus(); - if (!focus) return; - - // Is the text edit - if (focus == EditBox->TextEdit) { - EditBox->Commit(true); - EditBox->Update(true); - } - - // Other window - else { - //wxKeyEvent keyevent; - //keyevent.m_keyCode = WXK_RETURN; - //keyevent.m_controlDown = true; - //keyevent.SetEventType(wxEVT_KEY_DOWN); - wxCommandEvent keyevent(wxEVT_COMMAND_TEXT_ENTER,focus->GetId()); - focus->GetEventHandler()->AddPendingEvent(keyevent); - } -} - - - /// @brief Choose a different language void FrameMain::OnChooseLanguage (wxCommandEvent &) { // Get language diff --git a/aegisub/src/hilimod_textctrl.cpp b/aegisub/src/hilimod_textctrl.cpp deleted file mode 100644 index 8cbf2d3a1..000000000 --- a/aegisub/src/hilimod_textctrl.cpp +++ /dev/null @@ -1,127 +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 hilimod_textctrl.cpp -/// @brief Edit control that changes colour when its contents are modified -/// @ingroup custom_control -/// - - -//////////// -// Includes -#include "config.h" - -#include "compat.h" -#include "hilimod_textctrl.h" -#include "main.h" - - -/// @brief Constructor -/// @param parent -/// @param id -/// @param value -/// @param pos -/// @param size -/// @param style -/// @param validator -/// @param name -/// -HiliModTextCtrl::HiliModTextCtrl(wxWindow* parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name) : -wxTextCtrl(parent,id,value,pos,size,style,validator,name) -{ - UpdateLocked = false; - isModified = false; - orig = GetValue(); - - Connect(wxEVT_COMMAND_TEXT_UPDATED,wxCommandEventHandler(HiliModTextCtrl::OnModified)); -} - - - -/// @brief Modified event -/// @param event -/// @return -/// -void HiliModTextCtrl::OnModified(wxCommandEvent &event) { - if (UpdateLocked) return; - Modified(); - event.Skip(); -} - - - -/// @brief Commited event -/// -void HiliModTextCtrl::Commited() { - if (isModified) { - orig = GetValue(); - SetBackgroundColour(wxNullColour); - Refresh(false); - isModified = false; - } -} - - - -/// @brief Set value -/// @param value -/// -void HiliModTextCtrl::SetValue(const wxString& value) { - UpdateLocked = true; - orig = value; - wxTextCtrl::SetValue(value); - Commited(); - UpdateLocked = false; -} - - - -/// @brief Was modified -/// -void HiliModTextCtrl::Modified() { - bool match = GetValue() == orig; - - // Different from original - if (!isModified && !match) { - isModified = true; - SetBackgroundColour(lagi_wxColour(OPT_GET("Colour/Background/Modified")->GetColour())); - Refresh(false); - } - - // Same as original - if (isModified && match) { - SetBackgroundColour(wxNullColour); - Refresh(false); - isModified = false; - } -} - - diff --git a/aegisub/src/hilimod_textctrl.h b/aegisub/src/hilimod_textctrl.h deleted file mode 100644 index 8ea7dec84..000000000 --- a/aegisub/src/hilimod_textctrl.h +++ /dev/null @@ -1,87 +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 hilimod_textctrl.h -/// @see hilimod_textctrl.cpp -/// @ingroup custom_control -/// - - -#ifndef HILIMOD_TEXTCTRL - -/// DOCME -#define HILIMOD_TEXTCTRL - - -//////////// -// Includes -#ifndef AGI_PRE -#include -#endif - - -/// DOCME -/// @class HiliModTextCtrl -/// @brief DOCME -/// -/// DOCME -class HiliModTextCtrl : public wxTextCtrl { -private: - - /// DOCME - bool UpdateLocked; - - /// DOCME - bool isModified; - - - /// DOCME - wxString orig; - - void OnModified(wxCommandEvent &event); - void OnKey(wxKeyEvent &event); - -public: - HiliModTextCtrl(wxWindow* parent, wxWindowID id, const wxString& value = _T(""), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxValidator& validator = wxDefaultValidator, const wxString& name = wxTextCtrlNameStr); - - void Modified(); - void Commited(); - void SetValue(const wxString& value); - - /// @brief DOCME - /// - bool HasBeenModified() { return isModified; } -}; - - -#endif - - diff --git a/aegisub/src/idle_field_event.cpp b/aegisub/src/idle_field_event.cpp deleted file mode 100644 index 5f865fd98..000000000 --- a/aegisub/src/idle_field_event.cpp +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2006, 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 idle_field_event.cpp -/// @brief Unused event, intended to be used for automatic update of other controls after some idle time from the user -/// @ingroup custom_control -/// - - -/////////// -// Headers -#include "config.h" - -#ifndef AGI_PRE -#include -#include -#endif - -#include "idle_field_event.h" - - -/// @brief Constructor -/// @param _control -/// @param _name -/// -IdleFieldHandler::IdleFieldHandler(wxWindow *_control,wxString _name) { - control = _control; - name = _name; - overriden = false; - locked = false; - text = NULL; - box = NULL; - - // Set colours - original = control->GetForegroundColour(); - grey = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); - wxColour bg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); - grey = wxColour((grey.Red() + bg.Red()) / 2,(grey.Green() + bg.Green()) / 2,(grey.Blue() + bg.Blue()) / 2); - - // wxTextCtrl - if (control->IsKindOf(CLASSINFO(wxTextCtrl))) { - text = (wxTextCtrl*) control; - Connect(text->GetId(),wxEVT_COMMAND_TEXT_UPDATED,wxCommandEventHandler(IdleFieldHandler::OnChange)); - } - - // wxComboBox - else if (control->IsKindOf(CLASSINFO(wxComboBox))) { - box = (wxComboBox*) control; - Connect(box->GetId(),wxEVT_COMMAND_TEXT_UPDATED,wxCommandEventHandler(IdleFieldHandler::OnChange)); - Connect(box->GetId(),wxEVT_COMMAND_COMBOBOX_SELECTED,wxCommandEventHandler(IdleFieldHandler::OnChange)); - } - - KillFocus(); -} - - -/////////////// -// Event table -BEGIN_EVENT_TABLE(IdleFieldHandler,wxEvtHandler) - EVT_SET_FOCUS(IdleFieldHandler::OnSetFocus) - EVT_KILL_FOCUS(IdleFieldHandler::OnKillFocus) -END_EVENT_TABLE() - - - -/// @brief Get Focus event -/// @param event -/// -void IdleFieldHandler::OnSetFocus(wxFocusEvent &event) { - SetFocus(); - event.Skip(); -} - - - -/// @brief Lose Focus event -/// @param event -/// -void IdleFieldHandler::OnKillFocus(wxFocusEvent &event) { - KillFocus(); - event.Skip(); -} - - - -/// @brief Get focus -/// -void IdleFieldHandler::SetFocus() { - if (overriden) { - // Prepare - locked = true; - control->Freeze(); - control->SetForegroundColour(original); - - // Text - if (text) text->SetValue(_T("")); - - // Box - if (box) box->SetValue(_T("")); - - // Finish - overriden = false; - locked = false; - control->Thaw(); - } -} - - - -/// @brief Lose Focus -/// -void IdleFieldHandler::KillFocus() { - bool modify = false; - if ((text && text->GetValue().IsEmpty()) || (box && box->GetValue().IsEmpty())) modify = true; - - if (modify) { - // Prepare - locked = true; - control->Freeze(); - control->SetForegroundColour(grey); - - // Text - if (text) text->SetValue(name); - - // Box - if (box) box->SetValue(name); - - // Finish - overriden = true; - locked = false; - control->Thaw(); - } -} - - - -/// @brief Parent control changed -/// @param event -/// -void IdleFieldHandler::OnChange(wxCommandEvent &event) { - if (locked) return; - - overriden = false; - control->SetForegroundColour(original); - if (wxWindow::FindFocus() != control) { - wxFocusEvent focus(wxEVT_KILL_FOCUS,control->GetId()); - focus.SetEventObject(control); - AddPendingEvent(focus); - } - event.Skip(); -} - - diff --git a/aegisub/src/idle_field_event.h b/aegisub/src/idle_field_event.h deleted file mode 100644 index 8b2697b76..000000000 --- a/aegisub/src/idle_field_event.h +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) 2006, 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 idle_field_event.h -/// @see idle_field_event.cpp -/// @ingroup custom_control -/// - - - - -/////////// -// Headers -#ifndef AGI_PRE -#include -#include -#include -#endif - - -/// DOCME -/// @class IdleFieldHandler -/// @brief DOCME -/// -/// DOCME -class IdleFieldHandler : public wxEvtHandler { -private: - - /// DOCME - wxComboBox *box; - - /// DOCME - wxTextCtrl *text; - - /// DOCME - bool overriden; - - /// DOCME - bool locked; - - /// DOCME - wxColour grey; - - /// DOCME - wxColour original; - - - /// DOCME - wxWindow *control; - - /// DOCME - wxString name; - - void SetFocus(); - void KillFocus(); - - void OnSetFocus(wxFocusEvent &event); - void OnKillFocus(wxFocusEvent &event); - void OnChange(wxCommandEvent &event); - -public: - IdleFieldHandler(wxWindow *control,wxString name); - - DECLARE_EVENT_TABLE() -}; - - diff --git a/aegisub/src/scintilla_text_ctrl.h b/aegisub/src/scintilla_text_ctrl.h index 5e656a0b2..dabc5fbb9 100644 --- a/aegisub/src/scintilla_text_ctrl.h +++ b/aegisub/src/scintilla_text_ctrl.h @@ -34,17 +34,10 @@ /// @ingroup custom_control /// - -#pragma once - - -//////////// -// Includes #ifndef AGI_PRE #include #endif - /// DOCME /// @class ScintillaTextCtrl /// @brief DOCME @@ -57,10 +50,6 @@ public: int GetUnicodePosition(int pos); int GetReverseUnicodePosition(int pos); - /// @brief DOCME - /// - wxString GetValue() { return GetText(); } - void StartUnicodeStyling(int start,int mask=31); void SetUnicodeStyling(int start,int length,int style); void SetSelectionU(int start,int end); @@ -68,5 +57,3 @@ public: ScintillaTextCtrl(wxWindow* parent, wxWindowID id, const wxString& value = _T(""), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxValidator& validator = wxDefaultValidator, const wxString& name = wxTextCtrlNameStr); virtual ~ScintillaTextCtrl(); }; - - diff --git a/aegisub/src/subs_edit_box.cpp b/aegisub/src/subs_edit_box.cpp index ca8c7176c..36e08375e 100644 --- a/aegisub/src/subs_edit_box.cpp +++ b/aegisub/src/subs_edit_box.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2005, Rodrigo Braz Monteiro +// Copyright (c) 2010, Thomas Goyne // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -32,16 +33,25 @@ /// @file subs_edit_box.cpp /// @brief Main subtitle editing area, including toolbars around the text control /// @ingroup main_ui -/// - -//////////// -// Includes #include "config.h" #ifndef AGI_PRE +#ifdef _WIN32 +#include +#else +#include +#endif + +#include +#include #include +#include +#include +#include #include +#include +#include #endif #include "ass_dialogue.h" @@ -52,11 +62,10 @@ #include "dialog_colorpicker.h" #include "dialog_search_replace.h" #include "frame_main.h" -#include "hilimod_textctrl.h" -#include "idle_field_event.h" #include "libresrc/libresrc.h" #include "main.h" #include "subs_edit_box.h" +#include "subs_edit_ctrl.h" #include "subs_grid.h" #include "timeedit_ctrl.h" #include "tooltip_manager.h" @@ -65,83 +74,157 @@ #include "video_context.h" #include "video_display.h" +enum { + BUTTON_BOLD = 1300, + BUTTON_ITALICS, + BUTTON_UNDERLINE, + BUTTON_STRIKEOUT, + BUTTON_FONT_NAME, + BUTTON_COLOR1, + BUTTON_COLOR2, + BUTTON_COLOR3, + BUTTON_COLOR4, + BUTTON_COMMIT, + BUTTON_LAST +}; +enum { + BUTTON_FIRST = BUTTON_BOLD +}; -/// @brief Constructor -/// @param parent -/// @param gridp -/// -SubsEditBox::SubsEditBox (wxWindow *parent,SubtitlesGrid *gridp) : wxPanel(parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxRAISED_BORDER, _T("SubsEditBox")) +template +struct field_setter : public std::binary_function { + T AssDialogue::*field; + field_setter(T AssDialogue::*field) : field(field) { } + void operator()(AssDialogue* obj, T value) { + obj->*field = value; + } +}; + +/// @brief Get the selection from a text edit +/// @param[out] start Beginning of selection +/// @param[out] end End of selection +void get_selection(SubsTextEditCtrl *TextEdit, int &start, int &end) { + TextEdit->GetSelection(&start, &end); + int len = TextEdit->GetText().size(); + start = MID(0,TextEdit->GetReverseUnicodePosition(start),len); + end = MID(0,TextEdit->GetReverseUnicodePosition(end),len); +} + +/// @brief Get the value of a tag at a specified position in a line +/// @param line Line to get the value from +/// @param blockn Block number in the line +/// @param initial Value from style to use if the tag does not exist +/// @param tag Tag to get the value of +/// @param alt Alternate name of the tag, if any +template +static T get_value(AssDialogue const& line, int blockn, T initial, wxString tag, wxString alt = "") { + for (int i = blockn; i >= 0; i--) { + AssDialogueBlockOverride *ovr = dynamic_cast(line.Blocks[i]); + if (ovr) { + for (int j = (int)ovr->Tags.size() - 1; j >= 0; j--) { + if (ovr->Tags[j]->Name == tag || ovr->Tags[j]->Name == alt) { + return ovr->Tags[j]->Params[0]->Get(); + } + } + } + } + return initial; +} + +template +struct FocusHandler : std::unary_function { + wxString value; + wxString alt; + wxColor color; + Control *control; + void operator()(wxFocusEvent &event) const { + event.Skip(); + + if (control->GetValue() == alt) { + control->Freeze(); + control->ChangeValue(value); + control->SetForegroundColour(color); + control->Thaw(); + } + } +}; + +template +void bind_focus_handler(T *control, Event event, wxString value, wxString alt, wxColor color) { + FocusHandler handler; + handler.value = value; + handler.alt = alt; + handler.color = color; + handler.control = control; + control->Bind(event, handler); +} + +SubsEditBox::SubsEditBox (wxWindow *parent, SubtitlesGrid *grid, AudioDisplay *audio) +: wxPanel(parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxRAISED_BORDER, "SubsEditBox") +, line(NULL) +, splitLineMode(false) +, controlState(true) +, audio(audio) +, grid(grid) { - // Setup - audio = NULL; - grid = gridp; grid->editBox = this; - enabled = false; - textEditReady = true; - controlState = true; - setupDone = false; // Top controls wxArrayString styles; styles.Add(_T("Default")); - CommentBox = new wxCheckBox(this,COMMENT_CHECKBOX,_("Comment")); - CommentBox->SetToolTip(_("Comment this line out. Commented lines don't show up on screen.")); - StyleBox = new wxComboBox(this,STYLE_COMBOBOX,_T("Default"),wxDefaultPosition,wxSize(110,-1),styles,wxCB_READONLY | wxTE_PROCESS_ENTER); - StyleBox->SetToolTip(_("Style for this line.")); - ActorBox = new wxComboBox(this,ACTOR_COMBOBOX,_T("Actor"),wxDefaultPosition,wxSize(110,-1),styles,wxCB_DROPDOWN | wxTE_PROCESS_ENTER); - ActorBox->SetToolTip(_("Actor name for this speech. This is only for reference, and is mainly useless.")); - ActorBox->PushEventHandler(new IdleFieldHandler(ActorBox,_("Actor"))); - Effect = new HiliModTextCtrl(this,EFFECT_BOX,_T(""),wxDefaultPosition,wxSize(80,-1),wxTE_PROCESS_ENTER); - Effect->SetToolTip(_("Effect for this line. This can be used to store extra information for karaoke scripts, or for the effects supported by the renderer.")); - Effect->PushEventHandler(new IdleFieldHandler(Effect,_("Effect"))); + CommentBox = new wxCheckBox(this,wxID_ANY,_("Comment")); + StyleBox = new wxComboBox(this,wxID_ANY,_T("Default"),wxDefaultPosition,wxSize(110,-1),styles,wxCB_READONLY | wxTE_PROCESS_ENTER); + ActorBox = new wxComboBox(this,wxID_ANY,_T("Actor"),wxDefaultPosition,wxSize(110,-1),styles,wxCB_DROPDOWN | wxTE_PROCESS_ENTER); + Effect = new wxTextCtrl(this,wxID_ANY,"",wxDefaultPosition,wxSize(80,-1),wxTE_PROCESS_ENTER); // Middle controls - Layer = new wxSpinCtrl(this,LAYER_BOX,_T(""),wxDefaultPosition,wxSize(50,-1),wxSP_ARROW_KEYS,0,0x7FFFFFFF,0); - Layer->SetToolTip(_("Layer number")); - StartTime = new TimeEdit(this,STARTTIME_BOX,_T(""),wxDefaultPosition,wxSize(75,-1),wxTE_PROCESS_ENTER); - StartTime->SetToolTip(_("Start time")); - StartTime->showModified = true; - EndTime = new TimeEdit(this,ENDTIME_BOX,_T(""),wxDefaultPosition,wxSize(75,-1),wxTE_PROCESS_ENTER); - EndTime->SetToolTip(_("End time")); + Layer = new wxSpinCtrl(this,wxID_ANY,"",wxDefaultPosition,wxSize(50,-1),wxSP_ARROW_KEYS,0,0x7FFFFFFF,0); + StartTime = new TimeEdit(this,wxID_ANY,"",wxDefaultPosition,wxSize(75,-1),wxTE_PROCESS_ENTER); + EndTime = new TimeEdit(this,wxID_ANY,"",wxDefaultPosition,wxSize(75,-1),wxTE_PROCESS_ENTER); EndTime->isEnd = true; - EndTime->showModified = true; - Duration = new TimeEdit(this,DURATION_BOX,_T(""),wxDefaultPosition,wxSize(75,-1),wxTE_PROCESS_ENTER); - Duration->SetToolTip(_("Line duration")); - Duration->showModified = true; - MarginL = new HiliModTextCtrl(this,MARGINL_BOX,_T(""),wxDefaultPosition,wxSize(40,-1),wxTE_CENTRE | wxTE_PROCESS_ENTER,NumValidator()); - MarginL->SetToolTip(_("Left Margin (0 = default)")); + Duration = new TimeEdit(this,wxID_ANY,"",wxDefaultPosition,wxSize(75,-1),wxTE_PROCESS_ENTER); + MarginL = new wxTextCtrl(this,wxID_ANY,"",wxDefaultPosition,wxSize(40,-1),wxTE_CENTRE | wxTE_PROCESS_ENTER,NumValidator()); MarginL->SetMaxLength(4); - MarginR = new HiliModTextCtrl(this,MARGINR_BOX,_T(""),wxDefaultPosition,wxSize(40,-1),wxTE_CENTRE | wxTE_PROCESS_ENTER,NumValidator()); - MarginR->SetToolTip(_("Right Margin (0 = default)")); + MarginR = new wxTextCtrl(this,wxID_ANY,"",wxDefaultPosition,wxSize(40,-1),wxTE_CENTRE | wxTE_PROCESS_ENTER,NumValidator()); MarginR->SetMaxLength(4); - MarginV = new HiliModTextCtrl(this,MARGINV_BOX,_T(""),wxDefaultPosition,wxSize(40,-1),wxTE_CENTRE | wxTE_PROCESS_ENTER,NumValidator()); - MarginV->SetToolTip(_("Vertical Margin (0 = default)")); + MarginV = new wxTextCtrl(this,wxID_ANY,"",wxDefaultPosition,wxSize(40,-1),wxTE_CENTRE | wxTE_PROCESS_ENTER,NumValidator()); MarginV->SetMaxLength(4); // Middle-bottom controls - Bold = new wxBitmapButton(this,BUTTON_BOLD,GETIMAGE(button_bold_16),wxDefaultPosition,wxDefaultSize); - Bold->SetToolTip(_("Bold")); - Italics = new wxBitmapButton(this,BUTTON_ITALICS,GETIMAGE(button_italics_16),wxDefaultPosition,wxDefaultSize); - Italics->SetToolTip(_("Italics")); - Underline = new wxBitmapButton(this,BUTTON_UNDERLINE,GETIMAGE(button_underline_16),wxDefaultPosition,wxDefaultSize); - Underline->SetToolTip(_("Underline")); - Strikeout = new wxBitmapButton(this,BUTTON_STRIKEOUT,GETIMAGE(button_strikeout_16),wxDefaultPosition,wxDefaultSize); - Strikeout->SetToolTip(_("Strikeout")); - FontName = new wxBitmapButton(this,BUTTON_FONT_NAME,GETIMAGE(button_fontname_16),wxDefaultPosition,wxDefaultSize); - FontName->SetToolTip(_("Font Face Name")); - Color1 = new wxBitmapButton(this,BUTTON_COLOR1,GETIMAGE(button_color_one_16),wxDefaultPosition,wxDefaultSize); - Color1->SetToolTip(_("Primary color")); - Color2 = new wxBitmapButton(this,BUTTON_COLOR2,GETIMAGE(button_color_two_16),wxDefaultPosition,wxDefaultSize); - Color2->SetToolTip(_("Secondary color")); - Color3 = new wxBitmapButton(this,BUTTON_COLOR3,GETIMAGE(button_color_three_16),wxDefaultPosition,wxDefaultSize); - Color3->SetToolTip(_("Outline color")); - Color4 = new wxBitmapButton(this,BUTTON_COLOR4,GETIMAGE(button_color_four_16),wxDefaultPosition,wxDefaultSize); - Color4->SetToolTip(_("Shadow color")); - CommitButton = new wxBitmapButton(this,BUTTON_COMMIT,GETIMAGE(button_audio_commit_16),wxDefaultPosition,wxDefaultSize); - ToolTipManager::Bind(CommitButton,_("Commits the text (Enter). Hold Ctrl to stay in line (%KEY%)."),_T("Edit Box Commit")); - ByTime = new wxRadioButton(this,RADIO_TIME_BY_TIME,_("Time"),wxDefaultPosition,wxDefaultSize,wxRB_GROUP); + ToggableButtons.reserve(10); + int id = BUTTON_FIRST; +#define MAKE_BUTTON(img, tooltip) \ + ToggableButtons.push_back(new wxBitmapButton(this, id++, GETIMAGE(img))); \ + ToggableButtons.back()->SetToolTip(tooltip); + + MAKE_BUTTON(button_bold_16, _("Bold")); + MAKE_BUTTON(button_italics_16, _("Italics")); + MAKE_BUTTON(button_underline_16, _("Underline")); + MAKE_BUTTON(button_strikeout_16, _("Strikeout")); + MAKE_BUTTON(button_fontname_16, _("Font Face Name")); + MAKE_BUTTON(button_color_one_16, _("Primary color")); + MAKE_BUTTON(button_color_two_16, _("Secondary color")); + MAKE_BUTTON(button_color_three_16, _("Outline color")); + MAKE_BUTTON(button_color_four_16, _("Shadow color")); + MAKE_BUTTON(button_audio_commit_16, _("Commits the text (Enter). Hold Ctrl to stay in line (%KEY%).")); +#undef MAKE_BUTTON + + ByTime = new wxRadioButton(this,wxID_ANY,_("Time"),wxDefaultPosition,wxDefaultSize,wxRB_GROUP); + ByFrame = new wxRadioButton(this,wxID_ANY,_("Frame")); + + // Tooltips + CommentBox->SetToolTip(_("Comment this line out. Commented lines don't show up on screen.")); + StyleBox->SetToolTip(_("Style for this line.")); + ActorBox->SetToolTip(_("Actor name for this speech. This is only for reference, and is mainly useless.")); + Effect->SetToolTip(_("Effect for this line. This can be used to store extra information for karaoke scripts, or for the effects supported by the renderer.")); + Layer->SetToolTip(_("Layer number")); + StartTime->SetToolTip(_("Start time")); + EndTime->SetToolTip(_("End time")); + Duration->SetToolTip(_("Line duration")); + MarginL->SetToolTip(_("Left Margin (0 = default)")); + MarginR->SetToolTip(_("Right Margin (0 = default)")); + MarginV->SetToolTip(_("Vertical Margin (0 = default)")); ByTime->SetToolTip(_("Time by h:mm:ss.cs")); - ByFrame = new wxRadioButton(this,RADIO_TIME_BY_FRAME,_("Frame")); ByFrame->SetToolTip(_("Time by frame number")); // Top sizer @@ -165,27 +248,19 @@ SubsEditBox::SubsEditBox (wxWindow *parent,SubtitlesGrid *gridp) : wxPanel(paren // Middle-bottom sizer MiddleBotSizer = new wxBoxSizer(wxHORIZONTAL); - MiddleBotSizer->Add(Bold,0,wxALIGN_CENTER|wxEXPAND,0); - MiddleBotSizer->Add(Italics,0,wxALIGN_CENTER|wxEXPAND,0); - MiddleBotSizer->Add(Underline,0,wxALIGN_CENTER|wxEXPAND,0); - MiddleBotSizer->Add(Strikeout,0,wxALIGN_CENTER|wxEXPAND,0); - MiddleBotSizer->Add(FontName,0,wxALIGN_CENTER|wxEXPAND,0); - MiddleBotSizer->AddSpacer(5); - MiddleBotSizer->Add(Color1,0,wxALIGN_CENTER|wxEXPAND,0); - MiddleBotSizer->Add(Color2,0,wxALIGN_CENTER|wxEXPAND,0); - MiddleBotSizer->Add(Color3,0,wxALIGN_CENTER|wxEXPAND,0); - MiddleBotSizer->Add(Color4,0,wxALIGN_CENTER|wxEXPAND,0); - MiddleBotSizer->AddSpacer(5); - MiddleBotSizer->Add(CommitButton,0,wxALIGN_CENTER,0); + for (size_t i = 0; i < ToggableButtons.size(); ++i) { + MiddleBotSizer->Add(ToggableButtons[i],0,wxALIGN_CENTER|wxEXPAND,0); + if (i == 4 || i == 8) + MiddleBotSizer->AddSpacer(5); + } MiddleBotSizer->AddSpacer(10); MiddleBotSizer->Add(ByTime,0,wxRIGHT | wxALIGN_CENTER | wxEXPAND,5); MiddleBotSizer->Add(ByFrame,0,wxRIGHT | wxALIGN_CENTER | wxEXPAND,5); // Text editor - int textStyle = wxBORDER_SUNKEN; - TextEdit = new SubsTextEditCtrl(this,EDIT_BOX,_T(""),wxDefaultPosition,wxSize(300,50),textStyle); - TextEdit->PushEventHandler(new SubsEditBoxEvent(this)); - TextEdit->control = this; + TextEdit = new SubsTextEditCtrl(this, wxSize(300,50), wxBORDER_SUNKEN, grid); + TextEdit->Bind(wxEVT_KEY_DOWN, &SubsEditBox::OnKeyDown, this); + TextEdit->SetUndoCollection(false); BottomSizer = new wxBoxSizer(wxHORIZONTAL); BottomSizer->Add(TextEdit,1,wxEXPAND,0); @@ -200,132 +275,105 @@ SubsEditBox::SubsEditBox (wxWindow *parent,SubtitlesGrid *gridp) : wxPanel(paren SetSizer(MainSizer); MainSizer->SetSizeHints(this); - // HACK: Fix colour of bg of editbox origBgColour = TextEdit->GetBackgroundColour(); disabledBgColour = GetBackgroundColour(); - // Set split mode - setupDone = true; - SetSplitLineMode(); - Update(); + wxColor text = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); + wxColor grey((text.Red() + origBgColour.Red()) / 2, + (text.Green() + origBgColour.Green()) / 2, + (text.Blue() + origBgColour.Blue()) / 2); + + // Setup placeholders for effect and actor boxes + bind_focus_handler(Effect, wxEVT_SET_FOCUS, "", L"Effect", text); + bind_focus_handler(Effect, wxEVT_KILL_FOCUS, L"Effect", "", grey); + Effect->SetForegroundColour(grey); + + bind_focus_handler(ActorBox, wxEVT_SET_FOCUS, "", L"Actor", text); + bind_focus_handler(ActorBox, wxEVT_KILL_FOCUS, L"Actor", "", grey); + ActorBox->SetForegroundColour(grey); + + TextEdit->Bind(wxEVT_STC_STYLENEEDED, &SubsEditBox::OnNeedStyle, this); + TextEdit->Bind(wxEVT_STC_MODIFIED, &SubsEditBox::OnChange, this); + TextEdit->SetModEventMask(wxSTC_MOD_INSERTTEXT | wxSTC_MOD_DELETETEXT); + + Bind(wxEVT_COMMAND_RADIOBUTTON_SELECTED, &SubsEditBox::OnFrameTimeRadio, this, ByFrame->GetId()); + Bind(wxEVT_COMMAND_RADIOBUTTON_SELECTED, &SubsEditBox::OnFrameTimeRadio, this, ByTime->GetId()); + + Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &SubsEditBox::OnStyleChange, this, StyleBox->GetId()); + Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &SubsEditBox::OnActorChange, this, ActorBox->GetId()); + Bind(wxEVT_COMMAND_TEXT_UPDATED, &SubsEditBox::OnActorChange, this, ActorBox->GetId()); + + Bind(wxEVT_COMMAND_TEXT_UPDATED, &SubsEditBox::OnLayerEnter, this, Layer->GetId()); + Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, &SubsEditBox::OnLayerChange, this, Layer->GetId()); + Bind(wxEVT_COMMAND_TEXT_UPDATED, &SubsEditBox::OnStartTimeChange, this, StartTime->GetId()); + Bind(wxEVT_COMMAND_TEXT_UPDATED, &SubsEditBox::OnEndTimeChange, this, EndTime->GetId()); + Bind(wxEVT_COMMAND_TEXT_UPDATED, &SubsEditBox::OnDurationChange, this, Duration->GetId()); + Bind(wxEVT_COMMAND_TEXT_UPDATED, &SubsEditBox::OnMarginLChange, this, MarginL->GetId()); + Bind(wxEVT_COMMAND_TEXT_UPDATED, &SubsEditBox::OnMarginRChange, this, MarginR->GetId()); + Bind(wxEVT_COMMAND_TEXT_UPDATED, &SubsEditBox::OnMarginVChange, this, MarginV->GetId()); + Bind(wxEVT_COMMAND_TEXT_UPDATED, &SubsEditBox::OnEffectChange, this, Effect->GetId()); + Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &SubsEditBox::OnCommentChange, this, CommentBox->GetId()); + + Bind(wxEVT_SIZE, &SubsEditBox::OnSize, this); + + for (int i = 0; i < 4; i++) { + Bind(wxEVT_COMMAND_BUTTON_CLICKED, &SubsEditBox::OnFlagButton, this, BUTTON_FIRST + i); + } + Bind(wxEVT_COMMAND_BUTTON_CLICKED, &SubsEditBox::OnFontButton, this, BUTTON_FONT_NAME); + for (int i = 5; i < 9; i++) { + Bind(wxEVT_COMMAND_BUTTON_CLICKED, &SubsEditBox::OnColorButton, this, BUTTON_FIRST + i); + } + Bind(wxEVT_COMMAND_BUTTON_CLICKED, &SubsEditBox::OnCommitButton, this, BUTTON_COMMIT); + + wxSizeEvent evt; + OnSize(evt); grid->AddSelectionListener(this); } - - - -/// @brief Destructor -/// SubsEditBox::~SubsEditBox() { grid->RemoveSelectionListener(this); - ActorBox->PopEventHandler(true); - Effect->PopEventHandler(true); - TextEdit->PopEventHandler(true); } - - -/// @brief Set split or single line mode -/// @param newSize -/// -void SubsEditBox::SetSplitLineMode(wxSize newSize) { - // Widths - int topWidth; - if (newSize.GetWidth() == -1) topWidth = TopSizer->GetSize().GetWidth(); - else topWidth = newSize.GetWidth()-GetSize().GetWidth()+GetClientSize().GetWidth(); - int midMin = MiddleSizer->GetMinSize().GetWidth(); - int botMin = MiddleBotSizer->GetMinSize().GetWidth(); - - // Currently split - if (splitLineMode) { - - if (topWidth >= midMin + botMin) { - MainSizer->Detach(MiddleBotSizer); - MiddleSizer->Add(MiddleBotSizer,0,wxALIGN_CENTER_VERTICAL); - Layout(); - splitLineMode = false; - } +void SubsEditBox::Update(bool timeOnly, bool setAudio) { + SetControlsState(!!line); + if (!line) { + return; } - // Currently joined - else { - if (topWidth < midMin) { - MiddleSizer->Detach(MiddleBotSizer); - MainSizer->Insert(2,MiddleBotSizer,0,wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM,3); - Layout(); - splitLineMode = true; - } + SetEvtHandlerEnabled(false); + StartTime->SetTime(line->Start); + EndTime->SetTime(line->End); + Duration->SetTime(line->End-line->Start); + if (!timeOnly) { + TextEdit->SetTextTo(line->Text); + Layer->SetValue(line->Layer); + MarginL->ChangeValue(line->GetMarginString(0,false)); + MarginR->ChangeValue(line->GetMarginString(1,false)); + MarginV->ChangeValue(line->GetMarginString(2,false)); + Effect->ChangeValue(line->Effect.empty() ? L"Effect" : line->Effect); + CommentBox->SetValue(line->Comment); + StyleBox->Select(StyleBox->FindString(line->Style)); + ActorBox->ChangeValue(line->Actor.empty() ? L"Actor" : line->Actor); + ActorBox->SetStringSelection(line->Actor); } + + if (setAudio) audio->SetDialogue(grid,line,grid->GetDialogueIndex(line)); + + SetEvtHandlerEnabled(true); } - - -/// @brief Update function -/// @param timeOnly -/// @param weak -/// -void SubsEditBox::Update (bool timeOnly,bool weak) { - if (enabled) { - AssDialogue *curdiag = grid->GetActiveLine(); - if (curdiag) { - // Controls - SetControlsState(true); - int start = curdiag->Start.GetMS(); - int end = curdiag->End.GetMS(); - StartTime->SetTime(start); - StartTime->Update(); - EndTime->SetTime(end); - EndTime->Update(); - Duration->SetTime(end-start); - Duration->Update(); - if (!timeOnly) { - TextEdit->SetTextTo(curdiag->Text); - Layer->SetValue(curdiag->Layer); - MarginL->SetValue(curdiag->GetMarginString(0,false)); - MarginR->SetValue(curdiag->GetMarginString(1,false)); - MarginV->SetValue(curdiag->GetMarginString(2,false)); - Effect->SetValue(curdiag->Effect); - CommentBox->SetValue(curdiag->Comment); - StyleBox->Select(StyleBox->FindString(curdiag->Style)); - ActorBox->SetValue(curdiag->Actor); - ActorBox->SetStringSelection(curdiag->Actor); - - // Force actor box to update its idle status - wxCommandEvent changeEvent(wxEVT_COMMAND_TEXT_UPDATED,ActorBox->GetId()); - ActorBox->GetEventHandler()->AddPendingEvent(changeEvent); - } - - // Audio - if (!weak) audio->SetDialogue(grid,curdiag,grid->GetDialogueIndex(curdiag)); - - TextEdit->EmptyUndoBuffer(); - } - else enabled = false; - } - - else { - SetControlsState(false); - } -} - - - -/// @brief Update globals -/// -void SubsEditBox::UpdateGlobals () { - // Styles +void SubsEditBox::UpdateGlobals() { + SetEvtHandlerEnabled(false); StyleBox->Clear(); StyleBox->Append(grid->ass->GetStyles()); - // Actors ActorBox->Freeze(); ActorBox->Clear(); int nrows = grid->GetRows(); - wxString actor; for (int i=0;iGetDialogue(i)->Actor; + wxString actor = grid->GetDialogue(i)->Actor; // OSX doesn't like combo boxes that are empty. - if (actor == "") actor = _T("Actor"); + if (actor.empty()) actor = "Actor"; if (ActorBox->FindString(actor) == wxNOT_FOUND) { ActorBox->Append(actor); } @@ -335,162 +383,184 @@ void SubsEditBox::UpdateGlobals () { // Set subs update OnActiveLineChanged(grid->GetActiveLine()); TextEdit->SetSelection(0,0); + SetEvtHandlerEnabled(true); } +void SubsEditBox::OnActiveLineChanged(AssDialogue *new_line) { + SetEvtHandlerEnabled(false); + line = new_line; + Update(); -/////////////// -// Event table -BEGIN_EVENT_TABLE(SubsEditBox, wxPanel) - EVT_STC_MODIFIED(EDIT_BOX,SubsEditBox::OnEditText) - EVT_STC_STYLENEEDED(EDIT_BOX,SubsEditBox::OnNeedStyle) - EVT_STC_KEY(EDIT_BOX,SubsEditBox::OnKeyDown) - EVT_STC_CHARADDED(EDIT_BOX,SubsEditBox::OnCharAdded) - EVT_STC_UPDATEUI(EDIT_BOX,SubsEditBox::OnUpdateUI) + /// @todo VideoContext should be doing this + if (VideoContext::Get()->IsLoaded()) { + bool sync; + if (Search.hasFocus) sync = OPT_GET("Tool/Search Replace/Video Update")->GetBool(); + else sync = OPT_GET("Video/Subtitle Sync")->GetBool(); - EVT_CHECKBOX(SYNTAX_BOX, SubsEditBox::OnSyntaxBox) - EVT_RADIOBUTTON(RADIO_TIME_BY_FRAME, SubsEditBox::OnFrameRadio) - EVT_RADIOBUTTON(RADIO_TIME_BY_TIME, SubsEditBox::OnTimeRadio) - EVT_COMBOBOX(STYLE_COMBOBOX, SubsEditBox::OnStyleChange) - EVT_COMBOBOX(ACTOR_COMBOBOX, SubsEditBox::OnActorChange) - EVT_TEXT_ENTER(ACTOR_COMBOBOX, SubsEditBox::OnActorChange) - EVT_TEXT_ENTER(LAYER_BOX, SubsEditBox::OnLayerEnter) - EVT_SPINCTRL(LAYER_BOX, SubsEditBox::OnLayerChange) - EVT_TEXT_ENTER(STARTTIME_BOX, SubsEditBox::OnStartTimeChange) - EVT_TEXT_ENTER(ENDTIME_BOX, SubsEditBox::OnEndTimeChange) - EVT_TEXT_ENTER(DURATION_BOX, SubsEditBox::OnDurationChange) - EVT_TEXT_ENTER(MARGINL_BOX, SubsEditBox::OnMarginLChange) - EVT_TEXT_ENTER(MARGINR_BOX, SubsEditBox::OnMarginRChange) - EVT_TEXT_ENTER(MARGINV_BOX, SubsEditBox::OnMarginVChange) - EVT_TEXT_ENTER(EFFECT_BOX, SubsEditBox::OnEffectChange) - EVT_CHECKBOX(COMMENT_CHECKBOX, SubsEditBox::OnCommentChange) - - EVT_BUTTON(BUTTON_COLOR1,SubsEditBox::OnButtonColor1) - EVT_BUTTON(BUTTON_COLOR2,SubsEditBox::OnButtonColor2) - EVT_BUTTON(BUTTON_COLOR3,SubsEditBox::OnButtonColor3) - EVT_BUTTON(BUTTON_COLOR4,SubsEditBox::OnButtonColor4) - EVT_BUTTON(BUTTON_FONT_NAME,SubsEditBox::OnButtonFontFace) - EVT_BUTTON(BUTTON_BOLD,SubsEditBox::OnButtonBold) - EVT_BUTTON(BUTTON_ITALICS,SubsEditBox::OnButtonItalics) - EVT_BUTTON(BUTTON_UNDERLINE,SubsEditBox::OnButtonUnderline) - EVT_BUTTON(BUTTON_STRIKEOUT,SubsEditBox::OnButtonStrikeout) - EVT_BUTTON(BUTTON_COMMIT,SubsEditBox::OnButtonCommit) - - EVT_SIZE(SubsEditBox::OnSize) -END_EVENT_TABLE() - - - -/// @brief On size -/// @param event -/// -void SubsEditBox::OnSize(wxSizeEvent &event) { - if (setupDone) SetSplitLineMode(event.GetSize()); - event.Skip(); + if (sync) { + VideoContext::Get()->Stop(); + VideoContext::Get()->JumpToTime(line->Start.GetMS()); + } + } + SetEvtHandlerEnabled(true); +} +void SubsEditBox::OnSelectedSetChanged(const Selection &, const Selection &) { + sel = grid->GetSelectedSet(); } - - -/// @brief Text edited event -/// @param event -/// -void SubsEditBox::OnEditText(wxStyledTextEvent &event) { - int modType = event.GetModificationType(); - if (modType == (wxSTC_MOD_INSERTTEXT | wxSTC_PERFORMED_USER) || modType == (wxSTC_MOD_DELETETEXT | wxSTC_PERFORMED_USER)) { - //TextEdit->UpdateCallTip(); +void SubsEditBox::UpdateFrameTiming () { + if (VideoContext::Get()->TimecodesLoaded()) ByFrame->Enable(true); + else { + ByFrame->Enable(false); + ByTime->SetValue(true); + StartTime->SetByFrame(false); + EndTime->SetByFrame(false); + grid->SetByFrame(false); } } - - -/// @brief User Interface updated -/// @param event -/// -void SubsEditBox::OnUpdateUI(wxStyledTextEvent &event) { - TextEdit->UpdateCallTip(); +void SubsEditBox::OnKeyDown(wxKeyEvent &event) { + int key = event.GetKeyCode(); + if (line && (key == WXK_RETURN || key == WXK_NUMPAD_ENTER)) { +#ifdef __APPLE__ + Commit(event.m_metaDown); +#else + Commit(event.m_controlDown); +#endif + } + else { + event.Skip(); + } } +void SubsEditBox::OnCommitButton(wxCommandEvent &) { +#ifdef __APPLE__ + Commit(wxGetMouseState().CmdDown()); +#else + Commit(wxGetMouseState().ControlDown()); +#endif +} +void SubsEditBox::Commit(bool stay) { + if (stay) { + VideoContext::Get()->Refresh(); + return; + } + int next = grid->GetLastSelRow() + 1; + if (next >= grid->GetRows()) { + AssDialogue *cur = grid->GetDialogue(next-1); + AssDialogue *newline = new AssDialogue; + newline->Start = cur->End; + newline->End = cur->End + OPT_GET("Timing/Default Duration")->GetInt(); + newline->Style = cur->Style; + grid->InsertLine(newline,next-1,true,true); + } + grid->NextLine(); +} + +void SubsEditBox::OnChange(wxStyledTextEvent &event) { + if (line && TextEdit->GetText() != line->Text) { + if (event.GetModificationType() & wxSTC_MOD_INSERTTEXT) { + CommitText(_("insert text")); + } + else { + CommitText(_("delete text")); + } + } +} + +template +void SubsEditBox::SetSelectedRows(setter set, T value, wxString desc, bool amend) { + using namespace std::tr1::placeholders; + static agi::OptionValue* realtime = OPT_GET("Video/Visual Realtime"); + + for_each(sel.begin(), sel.end(), std::tr1::bind(set, _1, value)); + + commitId = grid->ass->Commit(desc, (amend && desc == lastCommitType) ? commitId : -1); + lastCommitType = desc; + grid->CommitChanges(false, realtime->GetBool()); +} + +template +void SubsEditBox::SetSelectedRows(T AssDialogue::*field, T value, wxString desc, bool amend) { + SetSelectedRows(field_setter(field), value, desc, amend); +} + +void SubsEditBox::CommitText(wxString desc) { + SetSelectedRows(&AssDialogue::Text, TextEdit->GetText(), desc, true); + audio->SetDialogue(grid,line,grid->GetDialogueIndex(line)); +} + +void SubsEditBox::CommitTimes(TimeField field) { + Duration->SetTime(EndTime->time - StartTime->time); + + // Update lines + for (Selection::iterator cur = sel.begin(); cur != sel.end(); ++cur) { + switch (field) { + case TIME_START: + (*cur)->Start = StartTime->time; + if ((*cur)->Start > (*cur)->End) (*cur)->End = (*cur)->Start; + break; + case TIME_END: + (*cur)->End = EndTime->time; + if ((*cur)->Start > (*cur)->End) (*cur)->Start = (*cur)->End; + break; + case TIME_DURATION: + (*cur)->End = (*cur)->Start + Duration->time; + break; + } + } + + timeCommitId[field] = grid->ass->Commit(_("modify times"), timeCommitId[field]); + grid->CommitChanges(); + int sel0 = grid->GetFirstSelRow(); + audio->SetDialogue(grid,grid->GetDialogue(sel0),sel0); +} + +void SubsEditBox::OnSize(wxSizeEvent &evt) { + int topWidth = TopSizer->GetSize().GetWidth(); + int midMin = MiddleSizer->GetMinSize().GetWidth(); + int botMin = MiddleBotSizer->GetMinSize().GetWidth(); + + if (splitLineMode) { + if (topWidth >= midMin + botMin) { + MainSizer->Detach(MiddleBotSizer); + MiddleSizer->Add(MiddleBotSizer,0,wxALIGN_CENTER_VERTICAL); + splitLineMode = false; + } + } + else { + if (topWidth < midMin) { + MiddleSizer->Detach(MiddleBotSizer); + MainSizer->Insert(2,MiddleBotSizer,0,wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM,3); + splitLineMode = true; + } + } + + evt.Skip(); +} -/// @brief Need style -/// @param event -/// void SubsEditBox::OnNeedStyle(wxStyledTextEvent &event) { // Check if it needs to fix text wxString text = TextEdit->GetText(); - if (text.Contains(_T("\n")) || text.Contains(_T("\r"))) { - TextEdit->SetTextTo(TextEdit->GetText()); + if (text.Contains("\n") || text.Contains("\r")) { + TextEdit->SetTextTo(text); } - // Just update style else TextEdit->UpdateStyle(); } - - -/// @brief Character added -/// @param event -/// -void SubsEditBox::OnCharAdded(wxStyledTextEvent &event) { - //int character = event.GetKey(); -} - - - -/// @brief Key down -/// @param event -/// -void SubsEditBox::OnKeyDown(wxStyledTextEvent &event) { -} - - - -/// @brief Syntax highlight checkbox -/// @param event -/// -void SubsEditBox::OnSyntaxBox(wxCommandEvent &event) { - TextEdit->UpdateStyle(); - OPT_SET("Subtitle/Highlight/Syntax")->SetBool(SyntaxHighlight->GetValue()); +void SubsEditBox::OnFrameTimeRadio(wxCommandEvent &event) { + bool byFrame = ByFrame->GetValue(); + StartTime->SetByFrame(byFrame); + EndTime->SetByFrame(byFrame); + Duration->SetByFrame(byFrame); + grid->SetByFrame(byFrame); event.Skip(); } - - -/// @brief Time by frame radiobox -/// @param event -/// -void SubsEditBox::OnFrameRadio(wxCommandEvent &event) { - if (ByFrame->GetValue()) { - StartTime->SetByFrame(true); - EndTime->SetByFrame(true); - Duration->SetByFrame(true); - grid->SetByFrame(true); - } - event.Skip(); -} - - - -/// @brief Standard time radiobox -/// @param event -/// -void SubsEditBox::OnTimeRadio(wxCommandEvent &event) { - if (ByTime->GetValue()) { - StartTime->SetByFrame(false); - EndTime->SetByFrame(false); - Duration->SetByFrame(false); - grid->SetByFrame(false); - } - event.Skip(); -} - - - -/// @brief Sets state (enabled/disabled) for all controls -/// @param state -/// @return -/// -void SubsEditBox::SetControlsState (bool state) { +void SubsEditBox::SetControlsState(bool state) { if (state == controlState) return; controlState = state; @@ -512,931 +582,317 @@ void SubsEditBox::SetControlsState (bool state) { StyleBox->Enable(state); ActorBox->Enable(state); ByTime->Enable(state); - //SyntaxHighlight->Enable(state); - Bold->Enable(state); - Italics->Enable(state); - Underline->Enable(state); - Strikeout->Enable(state); - Color1->Enable(state); - Color2->Enable(state); - Color3->Enable(state); - Color4->Enable(state); - FontName->Enable(state); - CommitButton->Enable(state); + for (size_t i = 0; i < ToggableButtons.size(); ++i) + ToggableButtons[i]->Enable(state); UpdateFrameTiming(); - // Clear values if it's false - if (state==false) { - TextEdit->SetTextTo(_T("")); + if (!state) { + SetEvtHandlerEnabled(false); + TextEdit->SetTextTo(""); StartTime->SetTime(0); EndTime->SetTime(0); Duration->SetTime(0); - Layer->SetValue(_T("")); - MarginL->SetValue(_T("")); - MarginR->SetValue(_T("")); - MarginV->SetValue(_T("")); - Effect->SetValue(_T("")); + Layer->SetValue(""); + MarginL->ChangeValue(""); + MarginR->ChangeValue(""); + MarginV->ChangeValue(""); + Effect->ChangeValue(""); CommentBox->SetValue(false); + SetEvtHandlerEnabled(true); } } - -/// @brief Disables or enables frame timing -/// -void SubsEditBox::UpdateFrameTiming () { - if (VideoContext::Get()->TimecodesLoaded()) ByFrame->Enable(enabled); - else { - ByFrame->Enable(false); - ByTime->SetValue(true); - StartTime->SetByFrame(false); - EndTime->SetByFrame(false); - grid->SetByFrame(false); - } +void SubsEditBox::OnStyleChange(wxCommandEvent &) { + SetSelectedRows(&AssDialogue::Style, StyleBox->GetValue(), _("style change")); } - - -/// @brief Style changed -/// @param event -/// -void SubsEditBox::OnStyleChange(wxCommandEvent &event) { - grid->BeginBatch(); - wxArrayInt sel = grid->GetSelection(); - int n = sel.Count(); - AssDialogue *cur; - for (int i=0;iGetDialogue(sel[i]); - if (cur) { - cur->Style = StyleBox->GetValue(); - } - } - grid->ass->Commit(_("style change")); - grid->CommitChanges(); - grid->EndBatch(); -} - - - -/// @brief Style changed -/// @param event -/// -void SubsEditBox::OnActorChange(wxCommandEvent &event) { - grid->BeginBatch(); - wxArrayInt sel = grid->GetSelection(); - AssDialogue *cur; +void SubsEditBox::OnActorChange(wxCommandEvent &) { wxString actor = ActorBox->GetValue(); - - // Update rows - int n = sel.Count(); - for (int i=0;iGetDialogue(sel[i]); - if (cur) { - cur->Actor = actor; - } - } + SetSelectedRows(&AssDialogue::Actor, actor, _("actor change")); // Add actor to list - if (ActorBox->GetString(0).IsEmpty()) ActorBox->Delete(0); + if (!actor.empty() && ActorBox->GetCount() && ActorBox->GetString(0).empty()) { + ActorBox->Delete(0); + } if (ActorBox->FindString(actor) == wxNOT_FOUND) { ActorBox->Append(actor); } - - // Update grid - grid->ass->Commit(_("actor change")); - grid->CommitChanges(); - grid->EndBatch(); } - - -/// @brief Layer changed with spin -/// @param event -/// void SubsEditBox::OnLayerChange(wxSpinEvent &event) { - // Value - long temp = event.GetPosition(); - - // Get selection - wxArrayInt sel = grid->GetSelection(); - - // Update - int n = sel.Count(); - AssDialogue *cur; - for (int i=0;iGetDialogue(sel[i]); - if (cur) { - cur->Layer = temp; - } - } - - // Done - grid->ass->Commit(_("layer change")); - grid->CommitChanges(); + OnLayerEnter(event); } - - -/// @brief Layer changed with enter -/// @param event -/// -void SubsEditBox::OnLayerEnter(wxCommandEvent &event) { - // Value - long temp = Layer->GetValue(); - - // Get selection - wxArrayInt sel = grid->GetSelection(); - - // Update - int n = sel.Count(); - AssDialogue *cur; - for (int i=0;iGetDialogue(sel[i]); - if (cur) { - cur->Layer = temp; - } - } - - // Done - grid->ass->Commit(_("layer change")); - grid->CommitChanges(); +void SubsEditBox::OnLayerEnter(wxCommandEvent &) { + SetSelectedRows(&AssDialogue::Layer, Layer->GetValue(), _("layer change")); } - - -/// @brief Start time changed -/// @param event -/// -void SubsEditBox::OnStartTimeChange(wxCommandEvent &event) { - if (StartTime->time > EndTime->time) StartTime->SetTime(EndTime->time.GetMS()); - bool join = OPT_GET("Subtitle/Edit Box/Link Time Boxes Commit")->GetBool() && EndTime->HasBeenModified(); - StartTime->Update(); - Duration->Update(); - if (join) EndTime->Update(); - CommitTimes(true,join,true); +void SubsEditBox::OnStartTimeChange(wxCommandEvent &) { + if (StartTime->time > EndTime->time) EndTime->SetTime(StartTime->time); + CommitTimes(TIME_START); } - - -/// @brief End time changed -/// @param event -/// -void SubsEditBox::OnEndTimeChange(wxCommandEvent &event) { - if (StartTime->time > EndTime->time) EndTime->SetTime(StartTime->time.GetMS()); - bool join = OPT_GET("Subtitle/Edit Box/Link Time Boxes Commit")->GetBool() && StartTime->HasBeenModified(); - EndTime->Update(); - Duration->Update(); - if (join) StartTime->Update(); - CommitTimes(join,true,false); +void SubsEditBox::OnEndTimeChange(wxCommandEvent &) { + if (StartTime->time > EndTime->time) StartTime->SetTime(EndTime->time); + CommitTimes(TIME_END); } - - -/// @brief Duration changed -/// @param event -/// -void SubsEditBox::OnDurationChange(wxCommandEvent &event) { - EndTime->SetTime(StartTime->time.GetMS() + Duration->time.GetMS()); - StartTime->Update(); - EndTime->Update(); - Duration->Update(); - CommitTimes(false,true,true); +void SubsEditBox::OnDurationChange(wxCommandEvent &) { + EndTime->SetTime(StartTime->time + Duration->time); + CommitTimes(TIME_DURATION); +} +void SubsEditBox::OnMarginLChange(wxCommandEvent &) { + SetSelectedRows(std::mem_fun(&AssDialogue::SetMarginString<0>), MarginL->GetValue(), _("MarginL change")); + AssDialogue *cur = grid->GetDialogue(grid->GetFirstSelRow()); + if (cur) + MarginL->ChangeValue(cur->GetMarginString(0,false)); } - - -/// @brief Commit time changes -/// @param start -/// @param end -/// @param fromStart -/// @param commit -/// @return -/// -void SubsEditBox::CommitTimes(bool start,bool end,bool fromStart,bool commit) { - // Get selection - if (!start && !end) return; - Selection sel; - grid->GetSelectedSet(sel); - if (sel.size() == 0) return; - AssDialogue *cur; - Duration->SetTime(EndTime->time.GetMS() - StartTime->time.GetMS()); - - // Update lines - for (Selection::iterator it = sel.begin(); it != sel.end(); ++it) { - if (sel.find(grid->GetActiveLine()) != sel.end()) cur = *it; - else cur = grid->GetActiveLine(); - if (cur) { - // Set times - if (start) cur->Start = StartTime->time; - if (end) cur->End = EndTime->time; - - // Ensure that they have positive length - if (cur->Start > cur->End) { - if (fromStart) cur->End = cur->Start; - else cur->Start = cur->End; - } - if (sel.find(grid->GetActiveLine()) == sel.end()) break; - } - } - - // Commit - if (commit) { - StartTime->Update(); - EndTime->Update(); - Duration->Update(); - grid->ass->Commit(_("modify times")); - grid->CommitChanges(); - int sel0 = grid->GetFirstSelRow(); - audio->SetDialogue(grid,grid->GetDialogue(sel0),sel0); - VideoContext::Get()->UpdateDisplays(false); - } +void SubsEditBox::OnMarginRChange(wxCommandEvent &) { + SetSelectedRows(std::mem_fun(&AssDialogue::SetMarginString<1>), MarginR->GetValue(), _("MarginR change")); + AssDialogue *cur = grid->GetDialogue(grid->GetFirstSelRow()); + if (cur) + MarginR->ChangeValue(cur->GetMarginString(1,false)); } - - -/// @brief Margin L changed -/// @param event -/// -void SubsEditBox::OnMarginLChange(wxCommandEvent &event) { - MarginL->Commited(); - grid->BeginBatch(); - wxArrayInt sel = grid->GetSelection(); - int n = sel.Count(); - AssDialogue *cur = NULL; - for (int i=0;iGetDialogue(sel[i]); - if (cur) { - cur->SetMarginString(MarginL->GetValue(),0); - } - } - MarginL->SetValue(cur->GetMarginString(0,false)); - grid->ass->Commit(_("MarginL change")); - grid->CommitChanges(); - grid->EndBatch(); +static void set_margin_v(AssDialogue* diag, wxString value) { + diag->SetMarginString(value, 2); + diag->SetMarginString(value, 3); } - - -/// @brief Margin R changed -/// @param event -/// -void SubsEditBox::OnMarginRChange(wxCommandEvent &event) { - MarginR->Commited(); - grid->BeginBatch(); - wxArrayInt sel = grid->GetSelection(); - int n = sel.Count(); - AssDialogue *cur = NULL; - for (int i=0;iGetDialogue(sel[i]); - if (cur) { - cur->SetMarginString(MarginR->GetValue(),1); - } - } - MarginR->SetValue(cur->GetMarginString(1,false)); - grid->ass->Commit(_("MarginR change")); - grid->CommitChanges(); - grid->EndBatch(); +void SubsEditBox::OnMarginVChange(wxCommandEvent &) { + SetSelectedRows(set_margin_v, MarginV->GetValue(), _("MarginV change")); + AssDialogue *cur = grid->GetDialogue(grid->GetFirstSelRow()); + if (cur) + MarginV->ChangeValue(cur->GetMarginString(2,false)); } - - -/// @brief Margin V changed -/// @param event -/// -void SubsEditBox::OnMarginVChange(wxCommandEvent &event) { - MarginV->Commited(); - grid->BeginBatch(); - wxArrayInt sel = grid->GetSelection(); - int n = sel.Count(); - AssDialogue *cur = NULL; - for (int i=0;iGetDialogue(sel[i]); - if (cur) { - cur->SetMarginString(MarginV->GetValue(),2); - cur->SetMarginString(MarginV->GetValue(),3); // also bottom margin for now - } - } - MarginV->SetValue(cur->GetMarginString(2,false)); - grid->ass->Commit(_("MarginV change")); - grid->CommitChanges(); - grid->EndBatch(); +void SubsEditBox::OnEffectChange(wxCommandEvent &) { + SetSelectedRows(&AssDialogue::Effect, Effect->GetValue(), _("effect change")); } - - -/// @brief Effect changed -/// @param event -/// -void SubsEditBox::OnEffectChange(wxCommandEvent &event) { - Effect->Commited(); - grid->BeginBatch(); - wxArrayInt sel = grid->GetSelection(); - int n = sel.Count(); - AssDialogue *cur; - for (int i=0;iGetDialogue(sel[i]); - if (cur) { - cur->Effect = Effect->GetValue(); - } - } - grid->ass->Commit(_("effect change")); - grid->CommitChanges(); - grid->EndBatch(); -} - - - -/// @brief Comment state changed -/// @param event -/// void SubsEditBox::OnCommentChange(wxCommandEvent &event) { - grid->BeginBatch(); - wxArrayInt sel = grid->GetSelection(); - int n = sel.Count(); - AssDialogue *cur; - for (int i=0;iGetDialogue(sel[i]); - if (cur) { - cur->Comment = CommentBox->GetValue(); - } - } - grid->ass->Commit(_("comment change")); - grid->CommitChanges(); - grid->EndBatch(); + SetSelectedRows(&AssDialogue::Comment, CommentBox->GetValue(), _("comment change")); } - - -/// @brief Event handler class -/// @param _control -/// -SubsEditBoxEvent::SubsEditBoxEvent(SubsEditBox *_control) { - control = _control; -} - -BEGIN_EVENT_TABLE(SubsEditBoxEvent, wxEvtHandler) - EVT_KEY_DOWN(SubsEditBoxEvent::OnKeyPress) -END_EVENT_TABLE() - - -/// @brief DOCME -/// @param event -/// -void SubsEditBoxEvent::OnKeyPress(wxKeyEvent &event) { - control->DoKeyPress(event); -} - - - -/// @brief Actual text changed -/// @param event -/// @return -/// -void SubsEditBox::DoKeyPress(wxKeyEvent &event) { - int key = event.GetKeyCode(); - - if (key == WXK_RETURN || key == WXK_NUMPAD_ENTER) { - if (enabled) { -#ifdef __APPLE__ - Commit(event.m_metaDown); -#else - Commit(event.m_controlDown); -#endif - return; - } - } - - event.Skip(); -} - - - -/// @brief Commit -/// @param stay -/// @return -/// -void SubsEditBox::Commit(bool stay) { - // Record pre-commit data - AssDialogue *old_line = grid->GetActiveLine(); - wxString oldText = old_line->Text; - int oldStart = old_line->Start.GetMS(); - int oldEnd = old_line->End.GetMS(); - // Update line - CommitText(); - - // Change text/time if needed for all selected lines - bool textNeedsCommit = old_line->Text != oldText; - bool timeNeedsCommit = old_line->Start.GetMS() != oldStart || old_line->End.GetMS() != oldEnd; - Selection sel; - grid->GetSelectedSet(sel); - if (sel.find(old_line) != sel.end()) { - for (Selection::iterator it = sel.begin(); it != sel.end(); ++it) { - if (textNeedsCommit) { - (*it)->Text = TextEdit->GetText(); - } - if (timeNeedsCommit) { - (*it)->Start.SetMS(StartTime->time.GetMS()); - (*it)->End.SetMS(EndTime->time.GetMS()); - } - } - } - - // Update file - if (textNeedsCommit) { - grid->ass->Commit(_("editing")); - grid->CommitChanges(); - } - else if (StartTime->HasBeenModified() || EndTime->HasBeenModified()) { - CommitTimes(StartTime->HasBeenModified(),EndTime->HasBeenModified(),StartTime->HasBeenModified(),true); - } - - // Get next line if ctrl was not held down - if (!stay) { - int next; - if (sel.find(old_line) == sel.end()) - next = grid->GetDialogueIndex(old_line)+1; - else - next = grid->GetLastSelRow()+1; - AssDialogue *cur = grid->GetDialogue(next-1); - if (next >= grid->GetRows()) { - AssDialogue *newline = new AssDialogue; - newline->Start = cur->End; - newline->End.SetMS(cur->End.GetMS()+OPT_GET("Timing/Default Duration")->GetInt()); - newline->Style = cur->Style; - grid->InsertLine(newline,next-1,true,true); - } - grid->SelectRow(next); - grid->MakeCellVisible(next,0); - grid->SetActiveLine(grid->GetDialogue(next)); - } -} - - - -/// @brief Commit text -/// @param weak -/// -void SubsEditBox::CommitText(bool weak) { - AssDialogue *cur = grid->GetActiveLine(); - - // Update line - if (cur) { - // Update text - cur->Text = TextEdit->GetText(); - - // Update times - if (grid->IsInSelection(grid->GetDialogueIndex(cur))) { - cur->Start = StartTime->time; - cur->End = EndTime->time; - if (cur->Start > cur->End) { - cur->End = cur->Start; - EndTime->SetTime(cur->End.GetMS()); - } - } - - // Update audio - if (!weak) { - grid->Refresh(false); - audio->SetDialogue(grid,cur,grid->GetDialogueIndex(cur)); - } - } -} - - - -/// @brief Gets block number at text position -/// @param pos -/// @return -/// -int SubsEditBox::BlockAtPos(int pos) { - // Prepare +int SubsEditBox::BlockAtPos(int pos) const { int n=0; wxString text = TextEdit->GetText();; int max = text.Length()-1; - // Find block number at pos for (int i=0;i<=pos && i<=max;i++) { - if (i > 0 && text[i] == _T('{')) n++; - if (text[i] == _T('}') && i != max && i != pos && i != pos -1 && (i+1 == max || text[i+1] != _T('{'))) n++; + if (i > 0 && text[i] == '{') n++; + if (text[i] == '}' && i != max && i != pos && i != pos -1 && (i+1 == max || text[i+1] != '{')) n++; } return n; } +void SubsEditBox::SetTag(wxString tag, wxString value, bool atEnd) { + assert(line); + assert(line->Valid); + if (line->Blocks.empty()) + line->ParseASSTags(); - -/// @brief Set override -/// @param tagname -/// @param preValue -/// @param forcePos -/// @param getFocus -/// @return -/// -void SubsEditBox::SetOverride (wxString tagname,wxString preValue,int forcePos,bool getFocus) { - // Selection int selstart, selend; - if (forcePos != -1) { - selstart = forcePos; - selend = forcePos; - } - else TextEdit->GetSelection(&selstart,&selend); - int len = TextEdit->GetText().Length(); - selstart = MID(0,TextEdit->GetReverseUnicodePosition(selstart),len); - selend = MID(0,TextEdit->GetReverseUnicodePosition(selend),len); + get_selection(TextEdit, selstart, selend); + int start = atEnd ? selend : selstart; + int blockn = BlockAtPos(start); - // Current tag name - wxString alttagname = tagname; - wxString removeTag; - if (tagname == _T("\\1c")) tagname = _T("\\c"); - if (tagname == _T("\\fr")) tagname = _T("\\frz"); - if (tagname == _T("\\pos")) removeTag = _T("\\move"); - if (tagname == _T("\\move")) removeTag = _T("\\pos"); - - // Get block at start - size_t blockn = BlockAtPos(selstart); - AssDialogue *line = new AssDialogue(); - line->Text = TextEdit->GetText(); - line->ParseASSTags(); - AssDialogueBlock *block = line->Blocks.at(blockn); - - // Insert variables - wxString insert; - wxString insert2; - int shift = 0; - int nInserted = 1; - - // Default value - wxColour startcolor; - wxFont startfont; - bool isColor = false; - bool isFont = false; - bool isGeneric = false; - bool isFlag = false; - bool state = false; - AssStyle *style = grid->ass->GetStyle(grid->GetActiveLine()->Style); - AssStyle defStyle; - if (style == NULL) style = &defStyle; - if (tagname == _T("\\b")) { - state = style->bold; - isFlag = true; - } - else if (tagname == _T("\\i")) { - state = style->italic; - isFlag = true; - } - else if (tagname == _T("\\u")) { - state = style->underline; - isFlag = true; - } - else if (tagname == _T("\\s")) { - state = style->strikeout; - isFlag = true; - } - else if (tagname == _T("\\fn")) { - startfont.SetFaceName(style->font); - startfont.SetPointSize(int(style->fontsize)); - startfont.SetWeight(style->bold ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL); - startfont.SetStyle(style->italic ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL); - startfont.SetUnderlined(style->underline); - isFont = true; - } - else if (tagname == _T("\\c")) { - startcolor = style->primary.GetWXColor(); - isColor = true; - } - else if (tagname == _T("\\2c")) { - startcolor = style->secondary.GetWXColor(); - isColor = true; - } - else if (tagname == _T("\\3c")) { - startcolor = style->outline.GetWXColor(); - isColor = true; - } - else if (tagname == _T("\\4c")) { - startcolor = style->shadow.GetWXColor(); - isColor = true; - } - else isGeneric = true; - - bool hasEnd = isFlag; - - // Find current value of style - AssDialogueBlockOverride *override; - AssOverrideTag *tag; - if (isFont || isColor || isFlag) { - for (size_t i=0;i<=blockn;i++) { - override = dynamic_cast(line->Blocks.at(i)); - if (override) { - for (size_t j=0;jTags.size();j++) { - tag = override->Tags.at(j); - if (tag->Name == tagname || tag->Name == alttagname || tagname == _T("\\fn")) { - if (isColor) startcolor = tag->Params.at(0)->Get(); - if (isFlag) state = tag->Params.at(0)->Get(); - if (isFont) { - if (tag->Name == _T("\\fn")) startfont.SetFaceName(tag->Params.at(0)->Get()); - if (tag->Name == _T("\\fs")) startfont.SetPointSize(tag->Params.at(0)->Get()); - if (tag->Name == _T("\\b")) startfont.SetWeight((tag->Params.at(0)->Get() > 0) ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL); - if (tag->Name == _T("\\i")) startfont.SetStyle(tag->Params.at(0)->Get() ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL); - if (tag->Name == _T("\\u")) startfont.SetUnderlined(tag->Params.at(0)->Get()); - } - } - } - } - } - } - - // Overrides being inserted - wxArrayString insertTags; - - // Toggle value - if (isFlag) { - state = !state; - int stateval = 0; - if (state) stateval = 1; - - // Generate insert string - insert = tagname + wxString::Format(_T("%i"),stateval); - insert2 = tagname + wxString::Format(_T("%i"),1-stateval); - insertTags.Add(tagname); - } - - // Choose color - if (isColor) { - // Pick from dialog - //wxColour color = wxGetColourFromUser(this,startcolor); - wxColour color = GetColorFromUser(((AegisubApp*)wxTheApp)->frame, startcolor); - if (!color.Ok() || color == startcolor) { - delete line; - return; - } - - // Generate insert string - AssColor asscolor(color); - insert = tagname + asscolor.GetASSFormatted(false); - insertTags.Add(tagname); - } - - // Choose font - if (isFont) { - // Pick from dialog - wxFont font = wxGetFontFromUser(this,startfont); - if (!font.Ok()) { - delete line; - return; - } - - // Generate insert string - nInserted = 0; - if (font.GetFaceName() != startfont.GetFaceName()) { - insert = _T("\\fn") + font.GetFaceName(); - nInserted++; - insertTags.Add(_T("\\fn")); - } - if (font.GetPointSize() != startfont.GetPointSize()) { - insert += _T("\\fs") + wxString::Format(_T("%i"),font.GetPointSize()); - nInserted++; - insertTags.Add(_T("\\fs")); - } - if (font.GetWeight() != startfont.GetWeight()) { - insert += _T("\\b") + wxString::Format(_T("%i"),font.GetWeight() == wxFONTWEIGHT_BOLD ? 1 : 0); - nInserted++; - insertTags.Add(_T("\\b")); - } - if (font.GetStyle() != startfont.GetStyle()) { - insert += _T("\\i") + wxString::Format(_T("%i"),font.GetStyle() == wxFONTSTYLE_ITALIC ? 1 : 0); - nInserted++; - insertTags.Add(_T("\\i")); - } - if (font.GetUnderlined() != startfont.GetUnderlined()) { - insert += _T("\\u") + wxString::Format(_T("%i"),font.GetUnderlined() ? 1 : 0); - nInserted++; - insertTags.Add(_T("\\u")); - } - if (insert.IsEmpty()) { - delete line; - return; - } - } - - // Generic tag - if (isGeneric) { - insert = tagname + preValue; - insertTags.Add(tagname); - } - - // Get current block as plain or override + AssDialogueBlock *block = line->Blocks[blockn]; AssDialogueBlockPlain *plain = dynamic_cast(block); - override = dynamic_cast(block); + AssDialogueBlockOverride *ovr = dynamic_cast(block); - // Plain + // Drawings should always be preceded by an override block (with the \pX) + if (dynamic_cast(block)) { + assert(blockn > 0); + ovr = dynamic_cast(line->Blocks[blockn - 1]); + assert(ovr); + } + + wxString insert = tag + value; + int shift = insert.size(); if (plain) { - // Insert in text - line->Text = line->Text.Left(selstart) + _T("{") + insert + _T("}") + line->Text.Mid(selstart); - shift = 2 + insert.Length(); + line->Text = line->Text.Left(start) + "{" + insert + "}" + line->Text.Mid(start); + shift += 2; line->ParseASSTags(); } - - // Override - else if (override) { - // Insert new tag - override->text += insert; - override->ParseTags(); - shift = insert.Length(); - + else if (ovr) { + wxString alt; + if (tag == L"\\c") alt = L"\\1c"; // Remove old of same - for (size_t i=0;iTags.size()-nInserted;i++) { - //if (insert.Contains(override->Tags.at(i)->Name)) { - wxString name = override->Tags.at(i)->Name; - if (insertTags.Index(name) != wxNOT_FOUND || removeTag == name) { - shift -= ((wxString)*override->Tags.at(i)).Length(); - delete override->Tags.at(i); - override->Tags.erase(override->Tags.begin() + i); - i--; - } - } - - // Update line - line->UpdateText(); - } - - // End - if (hasEnd && selend != selstart) { - // Prepare variables again - int origStart = selstart; - selstart = selend + shift; - insert = insert2; - TextEdit->SetTextTo(line->Text); - blockn = BlockAtPos(selstart); - block = line->Blocks.at(blockn); - plain = dynamic_cast(block); - override = dynamic_cast(block); - - // Plain - if (plain) { - // Insert in text - line->Text = line->Text.Left(selstart) + _T("{") + insert + _T("}") + line->Text.Mid(selstart); - } - - // Override - else if (override) { - // Insert new tag - override->text += insert; - override->ParseTags(); - - // Remove old of same - for (size_t i=0;iTags.size()-nInserted;i++) { - wxString name = override->Tags.at(i)->Name; - if (insert.Contains(name) || removeTag == name) { - shift -= ((wxString)*override->Tags.at(i)).Length(); - override->Tags.erase(override->Tags.begin() + i); + bool found = false; + for (size_t i = 0; i < ovr->Tags.size(); i++) { + wxString name = ovr->Tags[i]->Name; + if (tag == name || alt == name) { + shift -= ((wxString)*ovr->Tags[i]).size(); + if (found) { + delete ovr->Tags[i]; + ovr->Tags.erase(ovr->Tags.begin() + i); i--; } + else { + ovr->Tags[i]->Params[0]->Set(value); + found = true; + } } - - // Update line - line->UpdateText(); + } + if (!found) { + ovr->AddTag(insert); } - // Shift selection - selstart = origStart; - TextEdit->SetSelectionU(origStart+shift,selend+shift); + line->UpdateText(); } - - // Commit changes and shift selection TextEdit->SetTextTo(line->Text); - delete line; - TextEdit->SetSelectionU(selstart+shift,selend+shift); - if (getFocus) TextEdit->SetFocus(); + if (!atEnd) TextEdit->SetSelectionU(selstart+shift,selend+shift); + TextEdit->SetFocus(); } +void SubsEditBox::OnFlagButton(wxCommandEvent &evt) { + int id = evt.GetId(); + assert(id < BUTTON_LAST && id >= BUTTON_FIRST); - - -/// @brief Set primary color -/// @param event -/// -void SubsEditBox::OnButtonColor1(wxCommandEvent &event) { - SetOverride(_T("\\1c")); -} - - - -/// @brief Set secondary color -/// @param event -/// -void SubsEditBox::OnButtonColor2(wxCommandEvent &event) { - SetOverride(_T("\\2c")); -} - - - -/// @brief Set outline color -/// @param event -/// -void SubsEditBox::OnButtonColor3(wxCommandEvent &event) { - SetOverride(_T("\\3c")); -} - - - -/// @brief Set shadow color -/// @param event -/// -void SubsEditBox::OnButtonColor4(wxCommandEvent &event) { - SetOverride(_T("\\4c")); -} - - - -/// @brief Set font face -/// @param event -/// -void SubsEditBox::OnButtonFontFace(wxCommandEvent &event) { - SetOverride(_T("\\fn")); -} - - - -/// @brief Bold -/// @param event -/// -void SubsEditBox::OnButtonBold(wxCommandEvent &event) { - SetOverride(_T("\\b")); -} - - - -/// @brief Italics -/// @param event -/// -void SubsEditBox::OnButtonItalics(wxCommandEvent &event) { - SetOverride(_T("\\i")); -} - - - -/// @brief Underline -/// @param event -/// -void SubsEditBox::OnButtonUnderline(wxCommandEvent &event) { - SetOverride(_T("\\u")); -} - - - -/// @brief Strikeout -/// @param event -/// -void SubsEditBox::OnButtonStrikeout(wxCommandEvent &event) { - SetOverride(_T("\\s")); -} - - - -/// @brief Commit -/// @param event -/// -void SubsEditBox::OnButtonCommit(wxCommandEvent &event) { -#ifdef __APPLE__ - Commit(wxGetMouseState().CmdDown()); -#else - Commit(wxGetMouseState().ControlDown()); -#endif -} - - - -void SubsEditBox::OnActiveLineChanged(AssDialogue *new_line) { - // Set to nothing - enabled = (new_line != 0); - - // Set line - if (enabled) { - StartTime->Update(); - EndTime->Update(); - Duration->Update(); + wxString tagname; + wxString desc; + bool state = false; + AssStyle *style = grid->ass->GetStyle(line->Style); + AssStyle defStyle; + if (!style) style = &defStyle; + if (id == BUTTON_BOLD) { + tagname = L"\\b"; + desc = _("toggle bold"); + state = style->bold; + } + else if (id == BUTTON_ITALICS) { + tagname = L"\\i"; + desc = _("toggle italic"); + state = style->italic; + } + else if (id == BUTTON_UNDERLINE) { + tagname = L"\\u"; + desc = _("toggle underline"); + state = style->underline; + } + else if (id == BUTTON_STRIKEOUT) { + tagname = L"\\s"; + desc = _("toggle strikeout"); + state = style->strikeout; + } + else { + return; } - // Update controls - Update(); + line->ParseASSTags(); + int selstart, selend; + get_selection(TextEdit, selstart, selend); + int blockn = BlockAtPos(selstart); - // Set video - if (VideoContext::Get()->IsLoaded()) { - bool sync; - if (Search.hasFocus) sync = OPT_GET("Tool/Search Replace/Video Update")->GetBool(); - else sync = OPT_GET("Video/Subtitle Sync")->GetBool(); + state = get_value(*line, blockn, state, tagname); - if (sync) { - VideoContext::Get()->Stop(); - if (new_line) VideoContext::Get()->JumpToTime(new_line->Start.GetMS()); - } + SetTag(tagname, wxString::Format("%i", !state)); + if (selend != selstart) { + SetTag(tagname, wxString::Format("%i", state), true); } - TextEdit->EmptyUndoBuffer(); + line->ClearBlocks(); + commitId = -1; + CommitText(desc); } +void SubsEditBox::OnFontButton(wxCommandEvent &) { + int selstart, selend; + get_selection(TextEdit, selstart, selend); + line->ParseASSTags(); + int blockn = BlockAtPos(selstart); + wxFont startfont; + AssStyle *style = grid->ass->GetStyle(line->Style); + AssStyle defStyle; + if (!style) style = &defStyle; -void SubsEditBox::OnSelectedSetChanged(const Selection &lines_added, const Selection &lines_removed) { + startfont.SetFaceName(get_value(*line, blockn, style->font, L"\\fn")); + startfont.SetPointSize(get_value(*line, blockn, (int)style->fontsize, L"\\fs")); + startfont.SetWeight(get_value(*line, blockn, style->bold, L"\\b") ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL); + startfont.SetStyle(get_value(*line, blockn, style->italic, L"\\i") ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL); + startfont.SetUnderlined(get_value(*line, blockn, style->underline, L"\\u")); + + wxFont font = wxGetFontFromUser(this, startfont); + if (!font.Ok() || font == startfont) { + line->ClearBlocks(); + return; + } + + if (font.GetFaceName() != startfont.GetFaceName()) { + SetTag(L"\\fn", font.GetFaceName()); + } + if (font.GetPointSize() != startfont.GetPointSize()) { + SetTag(L"\\fs", wxString::Format("%i", font.GetPointSize())); + } + if (font.GetWeight() != startfont.GetWeight()) { + SetTag(L"\\b", wxString::Format("%i", font.GetWeight() == wxFONTWEIGHT_BOLD)); + } + if (font.GetStyle() != startfont.GetStyle()) { + SetTag(L"\\i", wxString::Format("%i", font.GetStyle() == wxFONTSTYLE_ITALIC)); + } + if (font.GetUnderlined() != startfont.GetUnderlined()) { + SetTag(L"\\i", wxString::Format("%i", font.GetUnderlined())); + } + line->ClearBlocks(); + commitId = -1; + CommitText(_("set font")); } +void SubsEditBox::OnColorButton(wxCommandEvent &evt) { + int id = evt.GetId(); + assert(id < BUTTON_LAST && id >= BUTTON_FIRST); + wxString alt; + wxColor color; + AssStyle *style = grid->ass->GetStyle(line->Style); + AssStyle defStyle; + if (!style) style = &defStyle; + if (id == BUTTON_COLOR1) { + color = style->primary.GetWXColor(); + colorTag = L"\\c"; + alt = L"\\c1"; + } + else if (id == BUTTON_COLOR2) { + color = style->secondary.GetWXColor(); + colorTag = L"\\2c"; + } + else if (id == BUTTON_COLOR3) { + color = style->outline.GetWXColor(); + colorTag = L"\\3c"; + } + else if (id == BUTTON_COLOR4) { + color = style->shadow.GetWXColor(); + colorTag = L"\\4c"; + } + else { + return; + } + + commitId = -1; + + line->ParseASSTags(); + int selstart, selend; + get_selection(TextEdit, selstart, selend); + int blockn = BlockAtPos(selstart); + + color = get_value(*line, blockn, color, colorTag, alt); + wxString initialText = line->Text; + wxColor newColor = GetColorFromUser(((AegisubApp*)wxTheApp)->frame, color, this); + if (newColor == color) { + TextEdit->SetTextTo(initialText); + TextEdit->SetSelectionU(selstart, selend); + } + + line->ClearBlocks(); + CommitText(_("set color")); +} +void SubsEditBox::SetColorCallback(wxColor newColor) { + if (newColor.Ok()) { + SetTag(colorTag, AssColor(newColor).GetASSFormatted(false)); + CommitText(_("set color")); + } +} diff --git a/aegisub/src/subs_edit_box.h b/aegisub/src/subs_edit_box.h index d9811c469..b6bf20edb 100644 --- a/aegisub/src/subs_edit_box.h +++ b/aegisub/src/subs_edit_box.h @@ -34,335 +34,175 @@ /// @ingroup main_ui /// - - - -//////////// -// Includes #ifndef AGI_PRE -#include -#include -#include -#include -#include +#include + #include -#include -#include #endif #include "selection_controller.h" -#include "subs_edit_ctrl.h" - -////////////// -// Prototypes +class AudioDisplay; class AssDialogue; class SubtitlesGrid; +class SubsTextEditCtrl; class TimeEdit; -class SubsEditBox; -class AudioDisplay; -class HiliModTextCtrl; +class wxButton; +class wxCheckBox; +class wxComboBox; +class wxRadioButton; +class wxSizer; +class wxSpinCtrl; class wxStyledTextCtrl; - - +class wxStyleTextEvent; +class wxTextCtrl; /// DOCME /// @class SubsEditBox -/// @brief DOCME +/// @brief Main subtitle edit box /// -/// DOCME +/// Controls the text edit and all surrounding controls class SubsEditBox : public wxPanel, protected SelectionListener { - friend class SubsTextEditHandler; - friend class SubsTextEditCtrl; friend class AudioDisplay; -private: + enum TimeField { + TIME_START = 0, + TIME_END, + TIME_DURATION + }; - /// DOCME + /// Currently active dialogue line + AssDialogue *line; + /// Last seen grid selection + Selection sel; + + /// Are the buttons currently split into two lines? bool splitLineMode; - - /// DOCME - bool setupDone; - - /// DOCME - bool enabled; - - /// DOCME - bool textEditReady; - - /// DOCME + /// Are the controls currently enabled? bool controlState; - /// DOCME + wxColour disabledBgColour; wxColour origBgColour; - /// DOCME - wxColour disabledBgColour; - - - /// DOCME + // Externally supplied controls + AudioDisplay *audio; SubtitlesGrid *grid; - /// DOCME + // Box controls wxCheckBox *CommentBox; - - /// DOCME wxComboBox *StyleBox; - - /// DOCME wxComboBox *ActorBox; - - /// DOCME TimeEdit *StartTime; - - /// DOCME TimeEdit *EndTime; - - /// DOCME TimeEdit *Duration; - - /// DOCME wxSpinCtrl *Layer; - - /// DOCME - HiliModTextCtrl *MarginL; - - /// DOCME - HiliModTextCtrl *MarginR; - - /// DOCME - HiliModTextCtrl *MarginV; - - /// DOCME - HiliModTextCtrl *Effect; - - /// DOCME + wxTextCtrl *MarginL; + wxTextCtrl *MarginR; + wxTextCtrl *MarginV; + wxTextCtrl *Effect; wxRadioButton *ByTime; - - /// DOCME wxRadioButton *ByFrame; - /// DOCME - wxCheckBox *SyntaxHighlight; + /// Buttons which turn on or off with the control + std::vector ToggableButtons; - - /// DOCME - wxButton *Bold; - - /// DOCME - wxButton *Italics; - - /// DOCME - wxButton *Underline; - - /// DOCME - wxButton *Strikeout; - - /// DOCME - wxButton *FontName; - - /// DOCME - wxButton *Color1; - - /// DOCME - wxButton *Color2; - - /// DOCME - wxButton *Color3; - - /// DOCME - wxButton *Color4; - - /// DOCME - wxButton *CommitButton; - - - /// DOCME wxSizer *TopSizer; - - /// DOCME wxSizer *MiddleBotSizer; - - /// DOCME wxSizer *MiddleSizer; - - /// DOCME wxSizer *MainSizer; - - /// DOCME - wxSizer *DummySizer; - - /// DOCME wxSizer *BottomSizer; void SetControlsState(bool state); - void CommitTimes(bool start,bool end,bool fromStart,bool commit=true); + /// @brief Update times of selected lines + /// @param field Field which changed + void CommitTimes(TimeField field); + /// @brief Commits the current edit box contents + /// @param desc Undo description to use + void CommitText(wxString desc); - int BlockAtPos(int pos); + /// Get block number at text position + int BlockAtPos(int pos) const; + + /// @brief Refresh the video display and move to the next line + /// @param stay Only refresh the video + void Commit(bool stay); + + int timeCommitId[3]; + int commitId; + wxString lastCommitType; - void OnEditText(wxStyledTextEvent &event); void OnNeedStyle(wxStyledTextEvent &event); - void OnCharAdded(wxStyledTextEvent &event); - void OnUpdateUI(wxStyledTextEvent &event); + void OnChange(wxStyledTextEvent &event); + void OnKeyDown(wxKeyEvent &event); - void OnButtonColor1(wxCommandEvent &event); - void OnButtonColor2(wxCommandEvent &event); - void OnButtonColor3(wxCommandEvent &event); - void OnButtonColor4(wxCommandEvent &event); - void OnButtonFontFace(wxCommandEvent &event); - void OnButtonBold(wxCommandEvent &event); - void OnButtonItalics(wxCommandEvent &event); - void OnButtonUnderline(wxCommandEvent &event); - void OnButtonStrikeout(wxCommandEvent &event); - void OnButtonCommit(wxCommandEvent &event); + void OnActiveLineChanged(AssDialogue *new_line); + void OnSelectedSetChanged(const Selection &, const Selection &); - void OnSyntaxBox(wxCommandEvent &event); - void OnFrameRadio(wxCommandEvent &event); - void OnTimeRadio(wxCommandEvent &event); - void OnKeyDown(wxStyledTextEvent &event); + void OnFrameTimeRadio(wxCommandEvent &event); void OnStyleChange(wxCommandEvent &event); void OnActorChange(wxCommandEvent &event); void OnLayerEnter(wxCommandEvent &event); void OnLayerChange(wxSpinEvent &event); - void OnStartTimeChange(wxCommandEvent &event); - void OnEndTimeChange(wxCommandEvent &event); - void OnDurationChange(wxCommandEvent &event); - void OnMarginLChange(wxCommandEvent &event); - void OnMarginRChange(wxCommandEvent &event); - void OnMarginVChange(wxCommandEvent &event); - void OnCommentChange(wxCommandEvent &event); - void OnEffectChange(wxCommandEvent &event); + void OnStartTimeChange(wxCommandEvent &); + void OnEndTimeChange(wxCommandEvent &); + void OnDurationChange(wxCommandEvent &); + void OnMarginLChange(wxCommandEvent &); + void OnMarginRChange(wxCommandEvent &); + void OnMarginVChange(wxCommandEvent &); + void OnCommentChange(wxCommandEvent &); + void OnEffectChange(wxCommandEvent &); void OnSize(wxSizeEvent &event); -protected: - // SubtitleSelectionListener implementation - virtual void OnActiveLineChanged(AssDialogue *new_line); - virtual void OnSelectedSetChanged(const Selection &lines_added, const Selection &lines_removed); + void OnFlagButton(wxCommandEvent &event); + void OnColorButton(wxCommandEvent &event); + void OnFontButton(wxCommandEvent &event); + void OnCommitButton(wxCommandEvent &); + /// @brief Set the value of a tag for the currently selected text + /// @param tag Tag to set + /// @param value New value of tag + /// @param atEnd Set the value at the end of the selection rather than beginning + void SetTag(wxString tag, wxString value, bool atEnd = false); + + /// @brief Callback function for the color picker + /// @param newColor New color selected in the picker + void SetColorCallback(wxColor newColor); + + /// Which color is currently being set + wxString colorTag; + + /// @brief Set a field in each selected line to a specified value + /// @param set Callable which does the setting + /// @param value Value to pass to set + /// @param desc Undo description to use + /// @param amend Coalesce sequences of commits of the same type + template + void SetSelectedRows(setter set, T value, wxString desc, bool amend = false); + + /// @brief Set a field in each selected line to a specified value + /// @param field Field to set + /// @param value Value to set the field to + /// @param desc Undo description to use + /// @param amend Coalesce sequences of commits of the same type + template + void SetSelectedRows(T AssDialogue::*field, T value, wxString desc, bool amend = false); public: - - /// DOCME - AudioDisplay *audio; - - /// DOCME SubsTextEditCtrl *TextEdit; - SubsEditBox(wxWindow *parent,SubtitlesGrid *gridp); + /// @brief Constructor + /// @param parent Parent window + /// @param grid Associated grid + /// @param audio Associated audio display + SubsEditBox(wxWindow *parent, SubtitlesGrid *grid, AudioDisplay *audio); ~SubsEditBox(); - void SetOverride (wxString tag,wxString preValue=_T(""),int pos=-1,bool getFocus=true); - void SetStyleFlag (wxString tag,wxString preValue=_T(""),int pos=-1); - - void SetSplitLineMode(wxSize size=wxSize(-1,-1)); - void CommitText(bool weak=false); - void Update(bool timeOnly=false,bool weak=false); + /// @brief Reload the current line from the file + /// @param timeOnly Only reload times + /// @param setAudio Also update the audio display + void Update(bool timeOnly = false, bool setAudio = true); + /// Reload non-line-specific things like styles from the file void UpdateGlobals(); + + /// @brief Enable or disable frame timing mode void UpdateFrameTiming(); - void DoKeyPress(wxKeyEvent &event); - void Commit(bool stay); - - DECLARE_EVENT_TABLE() }; - - - -/// DOCME -/// @class SubsEditBoxEvent -/// @brief DOCME -/// -/// DOCME -class SubsEditBoxEvent : public wxEvtHandler { -private: - - /// DOCME - SubsEditBox *control; - void OnKeyPress(wxKeyEvent &event); - -public: - SubsEditBoxEvent(SubsEditBox *control); - DECLARE_EVENT_TABLE() -}; - - -/////// -// IDs -enum { - - /// DOCME - EDIT_BOX = 1300, - - /// DOCME - SYNTAX_BOX, - - /// DOCME - RADIO_TIME_BY_FRAME, - - /// DOCME - RADIO_TIME_BY_TIME, - - /// DOCME - STYLE_COMBOBOX, - - /// DOCME - ACTOR_COMBOBOX, - - /// DOCME - LAYER_BOX, - - /// DOCME - STARTTIME_BOX, - - /// DOCME - ENDTIME_BOX, - - /// DOCME - DURATION_BOX, - - /// DOCME - MARGINL_BOX, - - /// DOCME - MARGINR_BOX, - - /// DOCME - MARGINV_BOX, - - /// DOCME - EFFECT_BOX, - - /// DOCME - COMMENT_CHECKBOX, - - - /// DOCME - BUTTON_BOLD, - - /// DOCME - BUTTON_ITALICS, - - /// DOCME - BUTTON_UNDERLINE, - - /// DOCME - BUTTON_STRIKEOUT, - - /// DOCME - BUTTON_FONT_NAME, - - /// DOCME - BUTTON_COLOR1, - - /// DOCME - BUTTON_COLOR2, - - /// DOCME - BUTTON_COLOR3, - - /// DOCME - BUTTON_COLOR4, - - /// DOCME - BUTTON_COMMIT -}; - - diff --git a/aegisub/src/subs_edit_ctrl.cpp b/aegisub/src/subs_edit_ctrl.cpp index fd4d1f21e..5282a02eb 100644 --- a/aegisub/src/subs_edit_ctrl.cpp +++ b/aegisub/src/subs_edit_ctrl.cpp @@ -34,22 +34,46 @@ /// @ingroup main_ui /// - -//////////// -// Includes #include "config.h" #ifndef AGI_PRE +#ifdef _WIN32 +#include +#else +#include +#endif #include #endif #include "ass_dialogue.h" #include "compat.h" #include "main.h" +#include "spellchecker_manager.h" #include "subs_edit_box.h" +#include "subs_edit_ctrl.h" #include "subs_grid.h" +#include "thesaurus.h" #include "utils.h" +/// Event ids +enum { + EDIT_MENU_SPLIT_PRESERVE = 1400, + EDIT_MENU_SPLIT_ESTIMATE, + EDIT_MENU_CUT, + EDIT_MENU_COPY, + EDIT_MENU_PASTE, + EDIT_MENU_SELECT_ALL, + EDIT_MENU_ADD_TO_DICT, + EDIT_MENU_SUGGESTION, + EDIT_MENU_SUGGESTIONS, + EDIT_MENU_THESAURUS = 1450, + EDIT_MENU_THESAURUS_SUGS, + EDIT_MENU_DIC_LANGUAGE = 1600, + EDIT_MENU_DIC_LANGS, + EDIT_MENU_THES_LANGUAGE = 1700, + EDIT_MENU_THES_LANGS +}; + /// @brief Edit box constructor /// @param parent @@ -62,8 +86,11 @@ /// @param name /// @return /// -SubsTextEditCtrl::SubsTextEditCtrl(wxWindow* parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& wsize, long style, const wxValidator& validator, const wxString& name) -: ScintillaTextCtrl(parent, id, value, pos, wsize, style, validator, name) +SubsTextEditCtrl::SubsTextEditCtrl(wxWindow* parent, wxSize wsize, long style, SubtitlesGrid *grid) +: ScintillaTextCtrl(parent, wxID_ANY, "", wxDefaultPosition, wsize, style) +, spellchecker(SpellCheckerFactoryManager::GetSpellChecker()) +, thesaurus(Thesaurus::GetThesaurus()) +, grid(grid) { // Set properties SetWrapMode(wxSTC_WRAP_WORD); @@ -83,127 +110,104 @@ SubsTextEditCtrl::SubsTextEditCtrl(wxWindow* parent, wxWindowID id, const wxStri CmdKeyClear('T',wxSTC_SCMOD_CTRL | wxSTC_SCMOD_SHIFT); CmdKeyClear('U',wxSTC_SCMOD_CTRL); - // Set spellchecker - spellchecker = SpellCheckerFactoryManager::GetSpellChecker(); - - // Set thesaurus - thesaurus = Thesaurus::GetThesaurus(); - // Prototypes for call tips tipProtoN = -1; - proto.Add(_T("move(x1,y1,x2,y2)")); - proto.Add(_T("move(x1,y1,x2,y2,startTime,endTime)")); - proto.Add(_T("fn;FontName")); - proto.Add(_T("bord;Width")); - proto.Add(_T("xbord;Width")); - proto.Add(_T("ybord;Width")); - proto.Add(_T("shad;Depth")); - proto.Add(_T("xshad;Depth")); - proto.Add(_T("yshad;Depth")); - proto.Add(_T("be;Strength")); - proto.Add(_T("blur;Strength")); - proto.Add(_T("fscx;Scale")); - proto.Add(_T("fscy;Scale")); - proto.Add(_T("fsp;Spacing")); - proto.Add(_T("fs;FontSize")); - proto.Add(_T("fe;Encoding")); - proto.Add(_T("frx;Angle")); - proto.Add(_T("fry;Angle")); - proto.Add(_T("frz;Angle")); - proto.Add(_T("fr;Angle")); - proto.Add(_T("pbo;Offset")); - proto.Add(_T("clip(command)")); - proto.Add(_T("clip(scale,command)")); - proto.Add(_T("clip(x1,y1,x2,y2)")); - proto.Add(_T("iclip(command)")); - proto.Add(_T("iclip(scale,command)")); - proto.Add(_T("iclip(x1,y1,x2,y2)")); - proto.Add(_T("t(acceleration,tags)")); - proto.Add(_T("t(startTime,endTime,tags)")); - proto.Add(_T("t(startTime,endTime,acceleration,tags)")); - proto.Add(_T("pos(x,y)")); - proto.Add(_T("p;Exponent")); - proto.Add(_T("org(x,y)")); - proto.Add(_T("fade(startAlpha,middleAlpha,endAlpha,startIn,endIn,startOut,endOut)")); - proto.Add(_T("fad(startTime,endTime)")); - proto.Add(_T("c;Colour")); - proto.Add(_T("1c;Colour")); - proto.Add(_T("2c;Colour")); - proto.Add(_T("3c;Colour")); - proto.Add(_T("4c;Colour")); - proto.Add(_T("alpha;Alpha")); - proto.Add(_T("1a;Alpha")); - proto.Add(_T("2a;Alpha")); - proto.Add(_T("3a;Alpha")); - proto.Add(_T("4a;Alpha")); - proto.Add(_T("an;Alignment")); - proto.Add(_T("a;Alignment")); - proto.Add(_T("b;Weight")); - proto.Add(_T("i;1/0")); - proto.Add(_T("u;1/0")); - proto.Add(_T("s;1/0")); - proto.Add(_T("kf;Duration")); - proto.Add(_T("ko;Duration")); - proto.Add(_T("k;Duration")); - proto.Add(_T("K;Duration")); - proto.Add(_T("q;WrapStyle")); - proto.Add(_T("r;Style")); - proto.Add(_T("fax;Factor")); - proto.Add(_T("fay;Factor")); + proto.Add(L"move(x1,y1,x2,y2)"); + proto.Add(L"move(x1,y1,x2,y2,startTime,endTime)"); + proto.Add(L"fn;FontName"); + proto.Add(L"bord;Width"); + proto.Add(L"xbord;Width"); + proto.Add(L"ybord;Width"); + proto.Add(L"shad;Depth"); + proto.Add(L"xshad;Depth"); + proto.Add(L"yshad;Depth"); + proto.Add(L"be;Strength"); + proto.Add(L"blur;Strength"); + proto.Add(L"fscx;Scale"); + proto.Add(L"fscy;Scale"); + proto.Add(L"fsp;Spacing"); + proto.Add(L"fs;FontSize"); + proto.Add(L"fe;Encoding"); + proto.Add(L"frx;Angle"); + proto.Add(L"fry;Angle"); + proto.Add(L"frz;Angle"); + proto.Add(L"fr;Angle"); + proto.Add(L"pbo;Offset"); + proto.Add(L"clip(command)"); + proto.Add(L"clip(scale,command)"); + proto.Add(L"clip(x1,y1,x2,y2)"); + proto.Add(L"iclip(command)"); + proto.Add(L"iclip(scale,command)"); + proto.Add(L"iclip(x1,y1,x2,y2)"); + proto.Add(L"t(acceleration,tags)"); + proto.Add(L"t(startTime,endTime,tags)"); + proto.Add(L"t(startTime,endTime,acceleration,tags)"); + proto.Add(L"pos(x,y)"); + proto.Add(L"p;Exponent"); + proto.Add(L"org(x,y)"); + proto.Add(L"fade(startAlpha,middleAlpha,endAlpha,startIn,endIn,startOut,endOut)"); + proto.Add(L"fad(startTime,endTime)"); + proto.Add(L"c;Colour"); + proto.Add(L"1c;Colour"); + proto.Add(L"2c;Colour"); + proto.Add(L"3c;Colour"); + proto.Add(L"4c;Colour"); + proto.Add(L"alpha;Alpha"); + proto.Add(L"1a;Alpha"); + proto.Add(L"2a;Alpha"); + proto.Add(L"3a;Alpha"); + proto.Add(L"4a;Alpha"); + proto.Add(L"an;Alignment"); + proto.Add(L"a;Alignment"); + proto.Add(L"b;Weight"); + proto.Add(L"i;1/0"); + proto.Add(L"u;1/0"); + proto.Add(L"s;1/0"); + proto.Add(L"kf;Duration"); + proto.Add(L"ko;Duration"); + proto.Add(L"k;Duration"); + proto.Add(L"K;Duration"); + proto.Add(L"q;WrapStyle"); + proto.Add(L"r;Style"); + proto.Add(L"fax;Factor"); + proto.Add(L"fay;Factor"); + + using namespace std::tr1; + + Bind(wxEVT_COMMAND_MENU_SELECTED, function(bind(&SubsTextEditCtrl::Cut, this)), EDIT_MENU_CUT); + Bind(wxEVT_COMMAND_MENU_SELECTED, function(bind(&SubsTextEditCtrl::Copy, this)), EDIT_MENU_COPY); + Bind(wxEVT_COMMAND_MENU_SELECTED, function(bind(&SubsTextEditCtrl::Paste, this)), EDIT_MENU_PASTE); + Bind(wxEVT_COMMAND_MENU_SELECTED, function(bind(&SubsTextEditCtrl::SelectAll, this)), EDIT_MENU_SELECT_ALL); + + Bind(wxEVT_STC_STYLENEEDED, &SubsTextEditCtrl::UpdateCallTip, this); } - - -/// @brief Destructor -/// SubsTextEditCtrl::~SubsTextEditCtrl() { - delete spellchecker; - spellchecker = NULL; - delete thesaurus; - thesaurus = NULL; } - -/////////////////////// -// Control event table BEGIN_EVENT_TABLE(SubsTextEditCtrl,wxStyledTextCtrl) EVT_MOUSE_EVENTS(SubsTextEditCtrl::OnMouseEvent) EVT_KILL_FOCUS(SubsTextEditCtrl::OnLoseFocus) EVT_MENU(EDIT_MENU_SPLIT_PRESERVE,SubsTextEditCtrl::OnSplitLinePreserve) EVT_MENU(EDIT_MENU_SPLIT_ESTIMATE,SubsTextEditCtrl::OnSplitLineEstimate) - EVT_MENU(EDIT_MENU_CUT,SubsTextEditCtrl::OnCut) - EVT_MENU(EDIT_MENU_COPY,SubsTextEditCtrl::OnCopy) - EVT_MENU(EDIT_MENU_PASTE,SubsTextEditCtrl::OnPaste) - EVT_MENU(EDIT_MENU_UNDO,SubsTextEditCtrl::OnUndo) - EVT_MENU(EDIT_MENU_SELECT_ALL,SubsTextEditCtrl::OnSelectAll) EVT_MENU(EDIT_MENU_ADD_TO_DICT,SubsTextEditCtrl::OnAddToDictionary) EVT_MENU_RANGE(EDIT_MENU_SUGGESTIONS,EDIT_MENU_THESAURUS-1,SubsTextEditCtrl::OnUseSuggestion) - EVT_MENU_RANGE(EDIT_MENU_THESAURUS_SUGS,EDIT_MENU_DIC_LANGUAGE-1,SubsTextEditCtrl::OnUseThesaurusSuggestion) + EVT_MENU_RANGE(EDIT_MENU_THESAURUS_SUGS,EDIT_MENU_DIC_LANGUAGE-1,SubsTextEditCtrl::OnUseSuggestion) EVT_MENU_RANGE(EDIT_MENU_DIC_LANGS,EDIT_MENU_THES_LANGUAGE-1,SubsTextEditCtrl::OnSetDicLanguage) EVT_MENU_RANGE(EDIT_MENU_THES_LANGS,EDIT_MENU_THES_LANGS+100,SubsTextEditCtrl::OnSetThesLanguage) END_EVENT_TABLE() - - -/// @brief Lose focus -/// @param event -/// void SubsTextEditCtrl::OnLoseFocus(wxFocusEvent &event) { CallTipCancel(); event.Skip(); } - - -/// @brief Set styles -/// void SubsTextEditCtrl::SetStyles() { - // Styles wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); font.SetEncoding(wxFONTENCODING_DEFAULT); // this solves problems with some fonts not working properly wxString fontname = lagi_wxString(OPT_GET("Subtitle/Edit Box/Font Face")->GetString()); - if (fontname != _T("")) font.SetFaceName(fontname); + if (!fontname.empty()) font.SetFaceName(fontname); int size = OPT_GET("Subtitle/Edit Box/Font Size")->GetInt(); // Normal style @@ -256,19 +260,11 @@ void SubsTextEditCtrl::SetStyles() { IndicatorSetForeground(0,wxColour(255,0,0)); } - - -/// @brief Style a range -/// @param start -/// @param _length -/// @return -/// void SubsTextEditCtrl::UpdateStyle(int start, int _length) { - // Styling enabled? if (OPT_GET("Subtitle/Highlight/Syntax")->GetBool() == 0) return; // Check if it's a template line - AssDialogue *diag = control->grid->GetActiveLine(); + AssDialogue *diag = grid->GetActiveLine(); bool templateLine = diag && diag->Comment && diag->Effect.Lower().StartsWith(_T("template")); //bool templateCodeLine = diag && diag->Comment && diag->Effect.Lower().StartsWith(_T("code")); @@ -320,7 +316,7 @@ void SubsTextEditCtrl::UpdateStyle(int start, int _length) { } // Start override block - if (curChar == _T('{') && depth >= 0) { + if (curChar == '{' && depth >= 0) { SetUnicodeStyling(curPos,ran,curStyle); curPos += ran; ran = 0; @@ -331,7 +327,7 @@ void SubsTextEditCtrl::UpdateStyle(int start, int _length) { } // End override block - else if (curChar == _T('}') && depth <= 1) { + else if (curChar == '}' && depth <= 1) { SetUnicodeStyling(curPos,ran,curStyle); curPos += ran; ran = 0; @@ -342,21 +338,21 @@ void SubsTextEditCtrl::UpdateStyle(int start, int _length) { } // Karaoke template block - else if (templateLine && curChar == _T('!')) { + else if (templateLine && curChar == '!') { // Apply previous style SetUnicodeStyling(curPos,ran,curStyle); curPos += ran; ran = -1; // such that ran++ later on resets it to 0 ! // Eat entire template block int endPos = i+1; - while (endPos < end && text[endPos] != _T('!')) + while (endPos < end && text[endPos] != '!') endPos++; SetUnicodeStyling(curPos,endPos-curPos+1,7); curPos = endPos+1; i = endPos+0; } // Karaoke template variable - else if (templateLine && curChar == _T('$')) { + else if (templateLine && curChar == '$') { // Apply previous style SetUnicodeStyling(curPos,ran,curStyle); curPos += ran; @@ -365,7 +361,7 @@ void SubsTextEditCtrl::UpdateStyle(int start, int _length) { int endPos = i+1; while (endPos < end) { wxChar ch = text[endPos]; - if ((ch >= _T('A') && ch <= _T('Z')) || (ch >= _T('a') && ch <= _T('z')) || ch == _T('_')) + if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '_') endPos++; else break; @@ -381,7 +377,7 @@ void SubsTextEditCtrl::UpdateStyle(int start, int _length) { numMode = false; // Is \n, \N or \h? - if (curChar == _T('\\') && (nextChar == 'n' || nextChar == 'N' || nextChar == 'h')) { + if (curChar == L'\\' && (nextChar == 'n' || nextChar == 'N' || nextChar == 'h')) { SetUnicodeStyling(curPos,ran,curStyle); curPos += ran; ran = 1; @@ -402,7 +398,7 @@ void SubsTextEditCtrl::UpdateStyle(int start, int _length) { // Inside else if (depth == 1) { // Special character - if (curChar == _T('\\') || curChar == _T('(') || curChar == _T(')') || curChar == _T(',')) { + if (curChar == L'\\' || curChar == '(' || curChar == ')' || curChar == ',') { if (curStyle != 2) { SetUnicodeStyling(curPos,ran,curStyle); curPos += ran; @@ -414,7 +410,7 @@ void SubsTextEditCtrl::UpdateStyle(int start, int _length) { else { // Number - if (prevChar != _T('\\') && (numMode || (curChar >= '0' && curChar <= '9') || curChar == '.' || curChar == '&' || curChar == '+' || curChar == '-' || (curChar == 'H' && prevChar == '&'))) { + if (prevChar != L'\\' && (numMode || (curChar >= '0' && curChar <= '9') || curChar == '.' || curChar == '&' || curChar == '+' || curChar == '-' || (curChar == 'H' && prevChar == '&'))) { if (curStyle != 5) { SetUnicodeStyling(curPos,ran,curStyle); curPos += ran; @@ -433,8 +429,8 @@ void SubsTextEditCtrl::UpdateStyle(int start, int _length) { // Set parameter if it's \fn or \r int tagLen = 0; - if (text.Mid(curPos,2) == _T("fn")) tagLen = 2; - else if (text.Mid(curPos,1) == _T("r")) tagLen = 1; + if (text.Mid(curPos,2) == L"fn") tagLen = 2; + else if (text.Mid(curPos,1) == L"r") tagLen = 1; if (tagLen) { numMode = true; ran = tagLen-1; @@ -442,21 +438,21 @@ void SubsTextEditCtrl::UpdateStyle(int start, int _length) { } // Set drawing mode if it's \p - if (text.Mid(curPos,1) == _T("p")) { + if (text.Mid(curPos,1) == L"p") { if (curPos+2 < (signed) text.Length()) { // Disable wxChar nextNext = text[curPos+2]; - if ((nextNext == _T('\\') || nextNext == _T('}')) && nextChar == _T('0')) drawingMode = false; + if ((nextNext == L'\\' || nextNext == '}') && nextChar == '0') drawingMode = false; // Enable - if (nextChar >= _T('1') && nextChar <= _T('9')) { + if (nextChar >= '1' && nextChar <= '9') { for(int testPos = curPos+2;testPos < (signed) text.Length();testPos++) { nextNext = text[testPos]; - if (nextNext == _T('\\') || nextNext == _T('}')) { + if (nextNext == L'\\' || nextNext == '}') { drawingMode = true; break; } - if (nextNext < _T('0') || nextNext > _T('9')) break; + if (nextNext < '0' || nextNext > '9') break; } } } @@ -469,21 +465,15 @@ void SubsTextEditCtrl::UpdateStyle(int start, int _length) { ran++; } SetUnicodeStyling(curPos,ran,curStyle); - - // Spell check StyleSpellCheck(start,_length); - - // Call tip - UpdateCallTip(); + wxStyledTextEvent evt; + UpdateCallTip(evt); } /// @brief Update call tip -/// @return -/// -void SubsTextEditCtrl::UpdateCallTip() { - // Enabled? +void SubsTextEditCtrl::UpdateCallTip(wxStyledTextEvent &) { if (!OPT_GET("App/Call Tips")->GetBool()) return; // Get position and text @@ -503,11 +493,11 @@ void SubsTextEditCtrl::UpdateCallTip() { else curChar = 0; // Change depth - if (curChar == _T('{')) { + if (curChar == '{') { depth++; continue; } - if (curChar == _T('}')) { + if (curChar == '}') { depth--; if (i >= pos && depth == 0) { tagEnd = i-1; @@ -527,13 +517,13 @@ void SubsTextEditCtrl::UpdateCallTip() { if (depth == 1) { // Inner depth if (tagStart != -1) { - if (curChar == _T('(')) inDepth++; - else if (curChar == _T(')')) inDepth--; + if (curChar == '(') inDepth++; + else if (curChar == ')') inDepth--; } // Not inside parenthesis if (inDepth == 0) { - if (prevChar == _T('\\')) { + if (prevChar == L'\\') { // Found start if (i <= pos) tagStart = i; @@ -578,17 +568,17 @@ void SubsTextEditCtrl::UpdateCallTip() { bool isEnd = false; // Commas - if (curChar == _T(',')) { + if (curChar == ',') { tagCommas++; parN++; } // Parenthesis - else if (curChar == _T('(')) { + else if (curChar == '(') { tagParenthesis++; parN++; } - else if (curChar == _T(')')) { + else if (curChar == ')') { tagParenthesis++; parN++; isEnd = true; @@ -603,7 +593,7 @@ void SubsTextEditCtrl::UpdateCallTip() { // Parameter it's on if (i == posInTag) { parPos = parN; - if (curChar == _T(',') || curChar == _T('(') || curChar == _T(')')) { + if (curChar == ',' || curChar == '(' || curChar == ')') { parPos--; } } @@ -628,18 +618,18 @@ void SubsTextEditCtrl::UpdateCallTip() { bool semiProto = false; for (unsigned int i=0;i 0) { - cleanProto.Replace(_T(";"),_T("")); + if (cleanProto.Freq(';') > 0) { + cleanProto.Replace(L";",""); semiProto = true; } @@ -649,7 +639,7 @@ void SubsTextEditCtrl::UpdateCallTip() { else temp = tagName; if (protoName == temp) { // Parameter count match - if (proto[i].Freq(_T(',')) >= tagCommas) { + if (proto[i].Freq(',') >= tagCommas) { // Found useProto = proto[i]; protoN = i; @@ -674,8 +664,8 @@ void SubsTextEditCtrl::UpdateCallTip() { int delta = 0; for (unsigned int i=0;itextEditReady = false; +void SubsTextEditCtrl::SetTextTo(wxString text) { + SetEvtHandlerEnabled(false); Freeze(); - wxString text = _text; - text.Replace(_T("\r\n"),_T("\\N")); - //text.Replace(_T("\n\r"),_T("\\N")); // never a valid linebreak - text.Replace(_T("\r"),_T("\\N")); - text.Replace(_T("\n"),_T("\\N")); - // Prepare + text.Replace(L"\r\n",L"\\N"); + text.Replace(L"\r",L"\\N"); + text.Replace(L"\n",L"\\N"); + int from=0,to=0; GetSelection(&from,&to); Clear(); - // Set text SetText(text); - - // Style UpdateStyle(); // Restore selection SetSelectionU(GetReverseUnicodePosition(from),GetReverseUnicodePosition(to)); - // Finish + SetEvtHandlerEnabled(true); Thaw(); - control->textEditReady = true; } - - -/// @brief Mouse event -/// @param event -/// @return -/// void SubsTextEditCtrl::OnMouseEvent(wxMouseEvent &event) { - // Right click if (event.ButtonUp(wxMOUSE_BTN_RIGHT)) { - if (control->grid->GetActiveLine() != 0) { + if (grid->GetActiveLine() != 0) { int pos = PositionFromPoint(event.GetPosition()); ShowPopupMenu(pos); return; @@ -791,44 +754,30 @@ void SubsTextEditCtrl::OnMouseEvent(wxMouseEvent &event) { GetParent()->GetEventHandler()->ProcessEvent(event); } - - -/// @brief Show popup menu -/// @param activePos -/// void SubsTextEditCtrl::ShowPopupMenu(int activePos) { - // Menu wxMenu menu; - // Position if (activePos == -1) activePos = GetCurrentPos(); activePos = GetReverseUnicodePosition(activePos); - // Get current word under cursor currentWord = GetWordAtPosition(activePos); currentWordPos = activePos; - // Spell check - //int style = GetStyleAt(activePos); - if (spellchecker && currentWord.Length()) { - // Spelled right? + if (spellchecker.get() && currentWord.Length()) { bool rightSpelling = spellchecker->CheckWord(currentWord); - // Set font wxFont font; font.SetWeight(wxFONTWEIGHT_BOLD); - // Get suggestions sugs.Clear(); sugs = spellchecker->GetSuggestions(currentWord); int nSugs = sugs.Count(); - // Spelled wrong if (!rightSpelling) { - // No suggestions - if (!nSugs) menu.Append(EDIT_MENU_SUGGESTION,_("No correction suggestions"))->Enable(false); + if (!nSugs) { + menu.Append(EDIT_MENU_SUGGESTION,_("No correction suggestions"))->Enable(false); + } - // Build menu for (int i=0;iEnable(spellchecker->CanAddWord(currentWord)); } - // Spelled right else { - // No suggestions - if (!nSugs) menu.Append(EDIT_MENU_SUGGESTION,_("No spell checker suggestions"))->Enable(false); - - // Has suggestions + if (!nSugs) { + menu.Append(EDIT_MENU_SUGGESTION,_("No spell checker suggestions"))->Enable(false); + } else { // Build list wxMenu *subMenu = new wxMenu(); for (int i=0;iAppend(EDIT_MENU_SUGGESTIONS+i,sugs[i]); menu.Append(-1,wxString::Format(_("Spell checker suggestions for \"%s\""),currentWord.c_str()), subMenu); } - - // Separator - //if (!thesaurus) menu.AppendSeparator(); } - - // Language list - wxArrayString langs = spellchecker->GetLanguageList(); // This probably should be cached... - // Current language + wxArrayString langs = spellchecker->GetLanguageList(); // This probably should be cached... wxString curLang = lagi_wxString(OPT_GET("Tool/Spell Checker/Language")->GetString()); // Languages @@ -891,7 +832,7 @@ void SubsTextEditCtrl::ShowPopupMenu(int activePos) { } // Thesaurus - if (thesaurus && currentWord.Length()) { + if (thesaurus.get() && currentWord.Length()) { // Get results ThesaurusEntryArray result; thesaurus->Lookup(currentWord,result); @@ -904,9 +845,7 @@ void SubsTextEditCtrl::ShowPopupMenu(int activePos) { } } - // Has suggestions if (result.size()) { - // Set font wxFont font; font.SetStyle(wxFONTSTYLE_ITALIC); @@ -938,18 +877,14 @@ void SubsTextEditCtrl::ShowPopupMenu(int activePos) { // Thesaurus menu wxString thes_suggestion_text(_("Thesaurus suggestions for \"%s\"")); - thes_suggestion_text.Replace(_T("%s"), currentWord); + thes_suggestion_text.Replace(L"%s", currentWord); menu.Append(-1,thes_suggestion_text,thesMenu); } - // No suggestions if (!result.size()) menu.Append(EDIT_MENU_THESAURUS,_("No thesaurus suggestions"))->Enable(false); - // Language list wxArrayString langs = thesaurus->GetLanguageList(); // This probably should be cached... - - // Current language wxString curLang = lagi_wxString(OPT_GET("Tool/Thesaurus/Language")->GetString()); // Languages @@ -977,8 +912,6 @@ void SubsTextEditCtrl::ShowPopupMenu(int activePos) { } // Standard actions - menu.Append(EDIT_MENU_UNDO,_("&Undo"))->Enable(CanUndo()); - menu.AppendSeparator(); menu.Append(EDIT_MENU_CUT,_("Cu&t"))->Enable(GetSelectionStart()-GetSelectionEnd() != 0); menu.Append(EDIT_MENU_COPY,_("&Copy"))->Enable(GetSelectionStart()-GetSelectionEnd() != 0); menu.Append(EDIT_MENU_PASTE,_("&Paste"))->Enable(CanPaste()); @@ -990,139 +923,49 @@ void SubsTextEditCtrl::ShowPopupMenu(int activePos) { menu.Append(EDIT_MENU_SPLIT_PRESERVE,_("Split at cursor (preserve times)")); menu.Append(EDIT_MENU_SPLIT_ESTIMATE,_("Split at cursor (estimate times)")); - // Pop the menu PopupMenu(&menu); } - - -/// @brief Split line preserving times -/// @param event -/// -void SubsTextEditCtrl::OnSplitLinePreserve (wxCommandEvent &event) { +void SubsTextEditCtrl::OnSplitLinePreserve (wxCommandEvent &) { int from,to; GetSelection(&from, &to); from = GetReverseUnicodePosition(from); - to = GetReverseUnicodePosition(to); - // Call SplitLine() with the text currently in the editbox. - // This makes sure we split what the user sees, not the committed line. - control->grid->SplitLine(control->grid->GetDialogueIndex(control->grid->GetActiveLine()),from,0,GetText()); + grid->SplitLine(grid->GetActiveLine(),from,0); } - - -/// @brief Split line estimating times -/// @param event -/// -void SubsTextEditCtrl::OnSplitLineEstimate (wxCommandEvent &event) { +void SubsTextEditCtrl::OnSplitLineEstimate (wxCommandEvent &) { int from,to; GetSelection(&from, &to); from = GetReverseUnicodePosition(from); - to = GetReverseUnicodePosition(to); - // Call SplitLine() with the text currently in the editbox. - // This makes sure we split what the user sees, not the committed line. - control->grid->SplitLine(control->grid->GetDialogueIndex(control->grid->GetActiveLine()),from,1,GetText()); + grid->SplitLine(grid->GetActiveLine(),from,1); } - - -/// @brief Cut -/// @param event -/// -void SubsTextEditCtrl::OnCut(wxCommandEvent &event) { - Cut(); -} - - - -/// @brief Copy -/// @param event -/// -void SubsTextEditCtrl::OnCopy(wxCommandEvent &event) { - Copy(); -} - - - -/// @brief Paste -/// @param event -/// -void SubsTextEditCtrl::OnPaste(wxCommandEvent &event) { - Paste(); -} - - - -/// @brief Undo -/// @param event -/// -void SubsTextEditCtrl::OnUndo(wxCommandEvent &event) { - Undo(); -} - - - -/// @brief Select All -/// @param event -/// -void SubsTextEditCtrl::OnSelectAll(wxCommandEvent &event) { - SelectAll(); -} - - - -/// @brief Add word to dictionary -/// @param event -/// -void SubsTextEditCtrl::OnAddToDictionary(wxCommandEvent &event) { - if (spellchecker) spellchecker->AddWord(currentWord); +void SubsTextEditCtrl::OnAddToDictionary(wxCommandEvent &) { + if (spellchecker.get()) spellchecker->AddWord(currentWord); UpdateStyle(); SetFocus(); } - - -/// @brief Use suggestion -/// @param event -/// void SubsTextEditCtrl::OnUseSuggestion(wxCommandEvent &event) { - // Get suggestion - wxString suggestion = sugs[event.GetId()-EDIT_MENU_SUGGESTIONS]; - - // Get boundaries of text being replaced - int start,end; - GetBoundsOfWordAtPosition(currentWordPos,start,end); - - // Replace - wxString text = GetText(); - SetText(text.Left(MAX(0,start)) + suggestion + text.Mid(end+1)); - - // Set selection - SetSelectionU(start,start+suggestion.Length()); - SetFocus(); -} - - - - -/// @brief Use thesaurus suggestion -/// @param event -/// -void SubsTextEditCtrl::OnUseThesaurusSuggestion(wxCommandEvent &event) { - // Get suggestion - wxString suggestion = thesSugs[event.GetId()-EDIT_MENU_THESAURUS_SUGS]; + wxString suggestion; + int sugIdx = event.GetId() - EDIT_MENU_THESAURUS_SUGS; + if (sugIdx >= 0) { + suggestion = thesSugs[sugIdx]; + } + else { + suggestion = sugs[event.GetId() - EDIT_MENU_SUGGESTIONS]; + } // Stripe suggestion of parenthesis - int pos = suggestion.Find(_T("(")); + int pos = suggestion.Find(L"("); if (pos != wxNOT_FOUND) { suggestion = suggestion.Left(pos-1); } - + // Get boundaries of text being replaced int start,end; GetBoundsOfWordAtPosition(currentWordPos,start,end); - // Replace wxString text = GetText(); SetText(text.Left(MAX(0,start)) + suggestion + text.Mid(end+1)); @@ -1131,13 +974,7 @@ void SubsTextEditCtrl::OnUseThesaurusSuggestion(wxCommandEvent &event) { SetFocus(); } - - -/// @brief Set dictionary language -/// @param event -/// void SubsTextEditCtrl::OnSetDicLanguage(wxCommandEvent &event) { - // Get language list wxArrayString langs = spellchecker->GetLanguageList(); // Set dictionary @@ -1147,17 +984,10 @@ void SubsTextEditCtrl::OnSetDicLanguage(wxCommandEvent &event) { spellchecker->SetLanguage(lang); OPT_SET("Tool/Spell Checker/Language")->SetString(STD_STR(lang)); - // Update styling UpdateStyle(); } - - -/// @brief Set thesaurus language -/// @param event -/// void SubsTextEditCtrl::OnSetThesLanguage(wxCommandEvent &event) { - // Get language list wxArrayString langs = thesaurus->GetLanguageList(); // Set language @@ -1167,8 +997,5 @@ void SubsTextEditCtrl::OnSetThesLanguage(wxCommandEvent &event) { thesaurus->SetLanguage(lang); OPT_SET("Tool/Thesaurus/Language")->SetString(STD_STR(lang)); - // Update styling UpdateStyle(); } - - diff --git a/aegisub/src/subs_edit_ctrl.h b/aegisub/src/subs_edit_ctrl.h index aeab7e260..f8378b110 100644 --- a/aegisub/src/subs_edit_ctrl.h +++ b/aegisub/src/subs_edit_ctrl.h @@ -34,19 +34,16 @@ /// @ingroup main_ui /// +#ifndef AGI_PRE +#include +#endif -//////////// -// Includes #include "scintilla_text_ctrl.h" -#include "spellchecker_manager.h" -#include "thesaurus.h" - -////////////// -// Prototypes +class SpellChecker; class SubsEditBox; - - +class SubtitlesGrid; +class Thesaurus; /// DOCME /// @class SubsTextEditCtrl @@ -54,13 +51,13 @@ class SubsEditBox; /// /// DOCME class SubsTextEditCtrl : public ScintillaTextCtrl { -private: + /// DOCME + std::auto_ptr spellchecker; /// DOCME - SpellChecker *spellchecker; + std::auto_ptr thesaurus; - /// DOCME - Thesaurus *thesaurus; + SubtitlesGrid *grid; /// DOCME @@ -87,87 +84,21 @@ private: void OnMouseEvent(wxMouseEvent &event); void OnSplitLinePreserve(wxCommandEvent &event); void OnSplitLineEstimate(wxCommandEvent &event); - void OnCut(wxCommandEvent &event); - void OnCopy(wxCommandEvent &event); - void OnPaste(wxCommandEvent &event); - void OnUndo(wxCommandEvent &event); - void OnSelectAll(wxCommandEvent &event); void OnAddToDictionary(wxCommandEvent &event); void OnUseSuggestion(wxCommandEvent &event); - void OnUseThesaurusSuggestion(wxCommandEvent &event); void OnSetDicLanguage(wxCommandEvent &event); void OnSetThesLanguage(wxCommandEvent &event); void OnLoseFocus(wxFocusEvent &event); public: - - /// DOCME - SubsEditBox *control; - - SubsTextEditCtrl(wxWindow* parent, wxWindowID id, const wxString& value = _T(""), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxValidator& validator = wxDefaultValidator, const wxString& name = wxTextCtrlNameStr); + SubsTextEditCtrl(wxWindow* parent, wxSize size, long style, SubtitlesGrid *grid); ~SubsTextEditCtrl(); - void SetTextTo(const wxString text); + void SetTextTo(wxString text); void UpdateStyle(int start=0,int length=-1); void StyleSpellCheck(int start=0,int length=-1); - void UpdateCallTip(); + void UpdateCallTip(wxStyledTextEvent &); void SetStyles(); DECLARE_EVENT_TABLE() }; - - -/////// -// IDs -enum { - - /// DOCME - EDIT_MENU_SPLIT_PRESERVE = 1400, - - /// DOCME - EDIT_MENU_SPLIT_ESTIMATE, - - /// DOCME - EDIT_MENU_CUT, - - /// DOCME - EDIT_MENU_COPY, - - /// DOCME - EDIT_MENU_PASTE, - - /// DOCME - EDIT_MENU_UNDO, - - /// DOCME - EDIT_MENU_SELECT_ALL, - - /// DOCME - EDIT_MENU_ADD_TO_DICT, - - /// DOCME - EDIT_MENU_SUGGESTION, - - /// DOCME - EDIT_MENU_SUGGESTIONS, - - /// DOCME - EDIT_MENU_THESAURUS = 1450, - - /// DOCME - EDIT_MENU_THESAURUS_SUGS, - - /// DOCME - EDIT_MENU_DIC_LANGUAGE = 1600, - - /// DOCME - EDIT_MENU_DIC_LANGS, - - /// DOCME - EDIT_MENU_THES_LANGUAGE = 1700, - - /// DOCME - EDIT_MENU_THES_LANGS -}; - - diff --git a/aegisub/src/subs_grid.cpp b/aegisub/src/subs_grid.cpp index 51ac8d2e3..a506b634d 100644 --- a/aegisub/src/subs_grid.cpp +++ b/aegisub/src/subs_grid.cpp @@ -88,8 +88,6 @@ BEGIN_EVENT_TABLE(SubtitlesGrid, BaseGrid) EVT_MENU_RANGE(MENU_SHOW_COL,MENU_SHOW_COL+15,SubtitlesGrid::OnShowColMenu) END_EVENT_TABLE() - - /// @brief Constructor /// @param parentFr /// @param parent @@ -98,31 +96,22 @@ END_EVENT_TABLE() /// @param size /// @param style /// @param name -/// SubtitlesGrid::SubtitlesGrid(FrameMain* parentFr, wxWindow *parent, wxWindowID id, AssFile *subs, const wxPoint& pos, const wxSize& size, long style, const wxString& name) : BaseGrid(parent,id,pos,size,style,name) , ass(subs) { - // Vars byFrame = false; editBox = NULL; parentFrame = parentFr; } - - /// @brief Destructor -/// SubtitlesGrid::~SubtitlesGrid() { ClearMaps(); } - - /// @brief Popup menu /// @param alternate -/// @return -/// void SubtitlesGrid::OnPopupMenu(bool alternate) { // Alternate if (alternate) { @@ -212,11 +201,8 @@ void SubtitlesGrid::OnPopupMenu(bool alternate) { } } - - /// @brief Process a show/hide column event /// @param event -/// void SubtitlesGrid::OnShowColMenu(wxCommandEvent &event) { int item = event.GetId()-MENU_SHOW_COL; showCol[item] = !showCol[item]; @@ -229,12 +215,8 @@ void SubtitlesGrid::OnShowColMenu(wxCommandEvent &event) { Refresh(false); } - - /// @brief Process keyboard events /// @param event -/// @return -/// void SubtitlesGrid::OnKeyDown(wxKeyEvent &event) { // Get key #ifdef __APPLE__ @@ -322,103 +304,70 @@ void SubtitlesGrid::OnKeyDown(wxKeyEvent &event) { event.Skip(); } - -/////////////////////// -// Duplicate selection -void SubtitlesGrid::OnDuplicate (wxCommandEvent &WXUNUSED(&event)) { +void SubtitlesGrid::OnDuplicate (wxCommandEvent &) { BeginBatch(); wxArrayInt sels = GetSelection(); DuplicateLines(sels.front(),sels.back()); EndBatch(); } - -////////////////////////////////////////////// -// Duplicate selection and shift by one frame -void SubtitlesGrid::OnDuplicateNextFrame (wxCommandEvent &WXUNUSED(&event)) { +void SubtitlesGrid::OnDuplicateNextFrame (wxCommandEvent &) { BeginBatch(); wxArrayInt sels = GetSelection(); DuplicateLines(sels.front(),sels.back(),true); EndBatch(); } - - /// @brief Call swap -/// @param event -/// -void SubtitlesGrid::OnSwap (wxCommandEvent &event) { +void SubtitlesGrid::OnSwap (wxCommandEvent &) { BeginBatch(); wxArrayInt sels = GetSelection(); SwapLines(sels.front(),sels.back()); EndBatch(); } - - /// @brief Call join (concatenate) -/// @param event -/// -void SubtitlesGrid::OnJoinConcat (wxCommandEvent &event) { +void SubtitlesGrid::OnJoinConcat (wxCommandEvent &) { BeginBatch(); wxArrayInt sels = GetSelection(); JoinLines(sels.front(),sels.back(),true); EndBatch(); } - - /// @brief Call join (replace) -/// @param event -/// -void SubtitlesGrid::OnJoinReplace (wxCommandEvent &event) { +void SubtitlesGrid::OnJoinReplace (wxCommandEvent &) { BeginBatch(); wxArrayInt sels = GetSelection(); JoinLines(sels.front(),sels.back(),false); EndBatch(); } - - /// @brief Adjoin lines -/// @param event -/// -void SubtitlesGrid::OnAdjoin (wxCommandEvent &event) { +void SubtitlesGrid::OnAdjoin (wxCommandEvent &) { BeginBatch(); wxArrayInt sels = GetSelection(); AdjoinLines(sels.front(),sels.back(),true); EndBatch(); } - /// @brief DOCME -/// @param event -/// -void SubtitlesGrid::OnAdjoin2 (wxCommandEvent &event) { +void SubtitlesGrid::OnAdjoin2 (wxCommandEvent &) { BeginBatch(); wxArrayInt sels = GetSelection(); AdjoinLines(sels.front(),sels.back(),false); EndBatch(); } - - /// @brief Call join as karaoke -/// @param event -/// -void SubtitlesGrid::OnJoinAsKaraoke (wxCommandEvent &event) { +void SubtitlesGrid::OnJoinAsKaraoke (wxCommandEvent &) { BeginBatch(); wxArrayInt sels = GetSelection(); JoinAsKaraoke(sels.front(),sels.back()); EndBatch(); } - - /// @brief Call split by karaoke -/// @param event -/// -void SubtitlesGrid::OnSplitByKaraoke (wxCommandEvent &event) { +void SubtitlesGrid::OnSplitByKaraoke (wxCommandEvent &) { BeginBatch(); wxArrayInt sels = GetSelection(); bool didSplit = false; @@ -432,12 +381,8 @@ void SubtitlesGrid::OnSplitByKaraoke (wxCommandEvent &event) { EndBatch(); } - - /// @brief Call insert before -/// @param event -/// -void SubtitlesGrid::OnInsertBefore (wxCommandEvent &event) { +void SubtitlesGrid::OnInsertBefore (wxCommandEvent &) { BeginBatch(); // Find line int n = GetFirstSelRow(); @@ -466,12 +411,8 @@ void SubtitlesGrid::OnInsertBefore (wxCommandEvent &event) { EndBatch(); } - - /// @brief Call insert after -/// @param event -/// -void SubtitlesGrid::OnInsertAfter (wxCommandEvent &event) { +void SubtitlesGrid::OnInsertAfter (wxCommandEvent &) { BeginBatch(); // Find line int n = GetFirstSelRow(); @@ -498,12 +439,8 @@ void SubtitlesGrid::OnInsertAfter (wxCommandEvent &event) { EndBatch(); } - - /// @brief Call insert before with video -/// @param event -/// -void SubtitlesGrid::OnInsertBeforeVideo (wxCommandEvent &event) { +void SubtitlesGrid::OnInsertBeforeVideo (wxCommandEvent &) { BeginBatch(); // Find line int n = GetFirstSelRow(); @@ -522,12 +459,8 @@ void SubtitlesGrid::OnInsertBeforeVideo (wxCommandEvent &event) { EndBatch(); } - - /// @brief Call insert after with video -/// @param event -/// -void SubtitlesGrid::OnInsertAfterVideo (wxCommandEvent &event) { +void SubtitlesGrid::OnInsertAfterVideo (wxCommandEvent &) { BeginBatch(); // Find line int n = GetFirstSelRow(); @@ -546,75 +479,51 @@ void SubtitlesGrid::OnInsertAfterVideo (wxCommandEvent &event) { EndBatch(); } - -/////////////////////////////// -// Copy selection to clipboard -void SubtitlesGrid::OnCopyLines (wxCommandEvent &WXUNUSED(&event)) { +/// Copy selection to clipboard +void SubtitlesGrid::OnCopyLines (wxCommandEvent &) { CopyLines(GetSelection()); } - -/////////////////////////////// -// Cuts selection to clipboard -void SubtitlesGrid::OnCutLines (wxCommandEvent &WXUNUSED(&event)) { +/// Cuts selection to clipboard +void SubtitlesGrid::OnCutLines (wxCommandEvent &) { CutLines(GetSelection()); } - -//////////////////////// -// Paste from clipboard -void SubtitlesGrid::OnPasteLines (wxCommandEvent &WXUNUSED(&event)) { +/// Paste from clipboard +void SubtitlesGrid::OnPasteLines (wxCommandEvent &) { PasteLines(GetFirstSelRow()); } - -/////////////////////////////// -// Copy selection to clipboard -void SubtitlesGrid::OnDeleteLines (wxCommandEvent &WXUNUSED(&event)) { +/// Copy selection to clipboard +void SubtitlesGrid::OnDeleteLines (wxCommandEvent &) { BeginBatch(); DeleteLines(GetSelection()); EndBatch(); } - - /// @brief Set start to video pos -/// @param event -/// -void SubtitlesGrid::OnSetStartToVideo(wxCommandEvent &event) { +void SubtitlesGrid::OnSetStartToVideo(wxCommandEvent &) { BeginBatch(); SetSubsToVideo(true); EndBatch(); } - - /// @brief Set end to video pos -/// @param event -/// -void SubtitlesGrid::OnSetEndToVideo(wxCommandEvent &event) { +void SubtitlesGrid::OnSetEndToVideo(wxCommandEvent &) { BeginBatch(); SetSubsToVideo(false); EndBatch(); } - - /// @brief Set video pos to start -/// @param event -/// -void SubtitlesGrid::OnSetVideoToStart(wxCommandEvent &event) { +void SubtitlesGrid::OnSetVideoToStart(wxCommandEvent &) { BeginBatch(); SetVideoToSubs(true); EndBatch(); } - - /// @brief Set video pos to end -/// @param event -/// -void SubtitlesGrid::OnSetVideoToEnd(wxCommandEvent &event) { +void SubtitlesGrid::OnSetVideoToEnd(wxCommandEvent &) { BeginBatch(); SetVideoToSubs(false); EndBatch(); @@ -718,14 +627,8 @@ void SubtitlesGrid::OnRecombine(wxCommandEvent &) { SetActiveLine(activeLine); } - - - /// @brief Export audio clip of line -/// @param event -/// @return -/// -void SubtitlesGrid::OnAudioClip(wxCommandEvent &event) { +void SubtitlesGrid::OnAudioClip(wxCommandEvent &) { int64_t num_samples,start=0,end=0,temp; AudioDisplay *audioDisplay = parentFrame->audioBox->audioDisplay; AudioProvider *provider = audioDisplay->provider; @@ -805,7 +708,6 @@ void SubtitlesGrid::OnAudioClip(wxCommandEvent &event) { /// @brief Clears grid and sets it to default /// @param _ass -/// void SubtitlesGrid::LoadDefault () { ass->LoadDefault(); ClearMaps(); @@ -824,13 +726,9 @@ void SubtitlesGrid::UpdateMaps(bool preserve_selected_rows) { } } - - /// @brief Swaps two lines /// @param n1 /// @param n2 -/// @return -/// void SubtitlesGrid::SwapLines(int n1,int n2) { AssDialogue *dlg1 = GetDialogue(n1); AssDialogue *dlg2 = GetDialogue(n2); @@ -842,14 +740,11 @@ void SubtitlesGrid::SwapLines(int n1,int n2) { CommitChanges(); } - - /// @brief Insert a line /// @param line /// @param n /// @param after /// @param update -/// void SubtitlesGrid::InsertLine(AssDialogue *line,int n,bool after,bool update) { AssDialogue *rel_line = GetDialogue(n + (after?1:0)); entryIter pos = std::find(ass->Line.begin(), ass->Line.end(), rel_line); @@ -864,11 +759,6 @@ void SubtitlesGrid::InsertLine(AssDialogue *line,int n,bool after,bool update) { } } - - -/// @brief Copy lines to clipboard -/// @param target -/// void SubtitlesGrid::CopyLines(wxArrayInt target) { // Prepare text wxString data = _T(""); @@ -889,11 +779,6 @@ void SubtitlesGrid::CopyLines(wxArrayInt target) { } } - - -/// @brief Cut to clipboard -/// @param target -/// void SubtitlesGrid::CutLines(wxArrayInt target) { BeginBatch(); CopyLines(target); @@ -901,18 +786,14 @@ void SubtitlesGrid::CutLines(wxArrayInt target) { EndBatch(); } - - -/// @brief Paste lines from clipboard +/// @brief Paste lines from clipboard /// @param n /// @param pasteOver -/// @return -/// void SubtitlesGrid::PasteLines(int n,bool pasteOver) { BeginBatch(); // Prepare text - wxString data = _T(""); + wxString data; // Read from clipboard if (wxTheClipboard->Open()) { @@ -941,7 +822,7 @@ void SubtitlesGrid::PasteLines(int n,bool pasteOver) { curdiag = new AssDialogue(curdata); } catch (...) { - // Line didn't parse correcly, assume it's plain text that + // Line didn't parse correctly, assume it's plain text that // should be pasted in the Text field only curdiag = new AssDialogue(); curdiag->Text = curdata; @@ -972,7 +853,6 @@ void SubtitlesGrid::PasteLines(int n,bool pasteOver) { if (pasteOverOptions[5]) target->Margin[0] = curdiag->Margin[0]; if (pasteOverOptions[6]) target->Margin[1] = curdiag->Margin[1]; if (pasteOverOptions[7]) target->Margin[2] = curdiag->Margin[2]; - //if (pasteOverOptions[8]) target->Margin[3] = curdiag->Margin[3]; if (pasteOverOptions[8]) target->Effect = curdiag->Effect; if (pasteOverOptions[9]) target->Text = curdiag->Text; } @@ -1004,17 +884,9 @@ void SubtitlesGrid::PasteLines(int n,bool pasteOver) { } } } - - // Done EndBatch(); } - - -/// @brief Delete selected lines -/// @param target -/// @param flagModified -/// void SubtitlesGrid::DeleteLines(wxArrayInt target, bool flagModified) { entryIter before_first = std::find_if(ass->Line.begin(), ass->Line.end(), cast()); --before_first; int old_active_line_index = GetDialogueIndex(GetActiveLine()); @@ -1048,18 +920,10 @@ void SubtitlesGrid::DeleteLines(wxArrayInt target, bool flagModified) { } } - - -/// @brief Joins selected lines -/// @param n1 -/// @param n2 -/// @param concat -/// void SubtitlesGrid::JoinLines(int n1,int n2,bool concat) { - // Initialize - int min_ms = 0x0FFFFFFF; - int max_ms = -1; - wxString finalText = _T(""); + int min_ms = INT_MAX; + int max_ms = INT_MIN; + wxString finalText; // Collect data AssDialogue *cur; @@ -1110,14 +974,6 @@ void SubtitlesGrid::JoinLines(int n1,int n2,bool concat) { SelectRow(n1); } - - -/// @brief Adjoins selected lines -/// @param n1 -/// @param n2 -/// @param setStart -/// @return -/// void SubtitlesGrid::AdjoinLines(int n1,int n2,bool setStart) { // Set start if (setStart) { @@ -1143,19 +999,11 @@ void SubtitlesGrid::AdjoinLines(int n1,int n2,bool setStart) { } } - // Commit ass->Commit(_("adjoin")); CommitChanges(); } - - -/// @brief Joins selected lines as karaoke -/// @param n1 -/// @param n2 -/// void SubtitlesGrid::JoinAsKaraoke(int n1,int n2) { - // Initialize wxString finalText = _T(""); // Collect data @@ -1202,13 +1050,6 @@ void SubtitlesGrid::JoinAsKaraoke(int n1,int n2) { SelectRow(n1); } - - -/// @brief Duplicate lines -/// @param n1 -/// @param n2 -/// @param nextFrame -/// void SubtitlesGrid::DuplicateLines(int n1,int n2,bool nextFrame) { AssDialogue *cur; bool update = false; @@ -1239,91 +1080,41 @@ void SubtitlesGrid::DuplicateLines(int n1,int n2,bool nextFrame) { SetActiveLine(GetDialogue(n1+step)); } - - -/// @brief Shifts line by time -/// @param n -/// @param len -/// @param type -/// -/// Where type = -/// - 0: Start + End -/// - 1: Start -/// - 2: End void SubtitlesGrid::ShiftLineByTime(int n,int len,int type) { + assert(type >= 0 && type <= 2); AssDialogue *cur = GetDialogue(n); if (type != 2) cur->Start.SetMS(cur->Start.GetMS() + len); if (type != 1) cur->End.SetMS(cur->End.GetMS() + len); } - - -/// @brief Shifts line by Frame -/// @param n -/// @param len -/// @param type -/// -/// @see ShiftLineByTime() void SubtitlesGrid::ShiftLineByFrames(int n,int len,int type) { + assert(type >= 0 && type <= 2); AssDialogue *cur = GetDialogue(n); if (type != 2) cur->Start.SetMS(context->TimeAtFrame(len + context->FrameAtTime(cur->Start.GetMS(),agi::vfr::START),agi::vfr::START)); if (type != 1) cur->End.SetMS(context->TimeAtFrame(len + context->FrameAtTime(cur->End.GetMS(),agi::vfr::END),agi::vfr::END)); } +void SubtitlesGrid::SplitLine(AssDialogue *n1,int pos,bool estimateTimes) { + AssDialogue *n2 = new AssDialogue(*n1); + InsertLine(n2,GetDialogueIndex(n1),true,false); - -/// @brief Split line -/// @param n -/// @param pos -/// @param mode -/// @param textIn -/// @return -/// -void SubtitlesGrid::SplitLine(int n,int pos,int mode,wxString textIn) { - // Split - AssDialogue *n1,*n2; - // No textIn? Get saved text - if (textIn.IsEmpty()) { - n1 = GetDialogue(n); - n2 = new AssDialogue(n1->GetEntryData()); - } - // Otherwise use textIn - else { - n1 = GetDialogue(n); - n1->Text = textIn; - n2 = new AssDialogue(n1->GetEntryData()); - } - InsertLine(n2,n,true,false); - - // Modify text wxString orig = n1->Text; n1->Text = orig.Left(pos).Trim(true); // Trim off trailing whitespace n2->Text = orig.Mid(pos).Trim(false); // Trim off leading whitespace - // Modify time - if (mode == 1) { + if (estimateTimes) { double splitPos = double(pos)/orig.Length(); int splitTime = (int)((n1->End.GetMS() - n1->Start.GetMS())*splitPos) + n1->Start.GetMS(); n1->End.SetMS(splitTime); n2->Start.SetMS(splitTime); } - // Update editbox and audio - //editBox->SetToLine(n); - - // Commit ass->Commit(_("split")); - CommitChanges(); + CommitChanges(false); } - - -/// @brief Returns true if changes were made. DOES NOT FLAG AS MODIFIED OR COMMIT CHANGES timed as the syllables. Splits the line into as many new lines as there are karaoke syllables, --------------------- Split line by karaoke -/// @param lineNumber -/// @return -/// bool SubtitlesGrid::SplitLineByKaraoke(int lineNumber) { AssDialogue *line = GetDialogue(lineNumber); @@ -1363,29 +1154,20 @@ bool SubtitlesGrid::SplitLineByKaraoke(int lineNumber) { return true; } - - -/// @brief This will save the work .ass and refresh it -------------- Commit changes -/// @param force -/// @param videoOnly -/// -void SubtitlesGrid::CommitChanges(bool force,bool videoOnly) { - if (context->IsLoaded() || force) { - // Check if it's playing +void SubtitlesGrid::CommitChanges(bool ebox, bool video, bool autosave) { + if (video && context->IsLoaded()) { bool playing = false; if (context->IsPlaying()) { playing = true; context->Stop(); } - // Update video - if (context->IsLoaded()) context->Refresh(); + context->Refresh(); - // Resume play if (playing) context->Play(); } - if (!videoOnly) { + if (autosave) { // Autosave if option is enabled if (OPT_GET("App/Auto/Save on Every Change")->GetBool()) { if (ass->IsModified() && !ass->filename.IsEmpty()) parentFrame->SaveSubtitles(false); @@ -1396,12 +1178,11 @@ void SubtitlesGrid::CommitChanges(bool force,bool videoOnly) { SetColumnWidths(); Refresh(false); } + if (ebox) { + editBox->Update(false, false); + } } -/// @brief Set start to video pos -/// @param start -/// @return -/// void SubtitlesGrid::SetSubsToVideo(bool start) { if (!context->IsLoaded()) return; @@ -1410,18 +1191,16 @@ void SubtitlesGrid::SetSubsToVideo(bool start) { // Update selection wxArrayInt sel = GetSelection(); - AssDialogue *cur; - int modified =0; + bool modified = false; for (size_t i=0;iStart.SetMS(ms); else cur->End.SetMS(ms); } } - // Commit if (modified) { ass->Commit(_("timing")); CommitChanges(); @@ -1429,12 +1208,6 @@ void SubtitlesGrid::SetSubsToVideo(bool start) { } } - - -/// @brief Set video pos to start/end -/// @param start -/// @return -/// void SubtitlesGrid::SetVideoToSubs(bool start) { wxArrayInt sel = GetSelection(); if (sel.Count() == 0) return; @@ -1468,8 +1241,6 @@ std::vector SubtitlesGrid::GetAbsoluteSelection() { return result; } - - /// @brief Update list of selected lines from absolute selection /// @param selection /// @@ -1490,5 +1261,3 @@ void SubtitlesGrid::SetSelectionFromAbsolute(std::vector &selection) { SetSelectedSet(newsel); } - - diff --git a/aegisub/src/subs_grid.h b/aegisub/src/subs_grid.h index f37dace4c..5c3b7bd63 100644 --- a/aegisub/src/subs_grid.h +++ b/aegisub/src/subs_grid.h @@ -56,7 +56,6 @@ class SubsEditBox; class FrameMain; class AudioDisplay; -/// DOCME typedef std::list::iterator entryIter; /// DOCME @@ -95,127 +94,120 @@ private: void OnShowColMenu(wxCommandEvent &event); public: - - /// DOCME + /// Currently open file AssFile *ass; SubtitlesGrid(FrameMain* parentFrame,wxWindow *parent, wxWindowID id, AssFile *subs, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxWANTS_CHARS, const wxString& name = wxPanelNameStr); ~SubtitlesGrid(); void LoadDefault(); - void CommitChanges(bool force=false,bool videoOnly=false); + /// @brief Commit changes and update the current file + /// @param ebox Update the edit box + /// @param video Update the video display + /// @param complete Autosave (if enabled) and update other things which care about the file + void CommitChanges(bool ebox = true, bool video = true, bool complete = true); void UpdateMaps(bool preserve_selected_rows = false); + /// @brief Jump to the start/end time of the current subtitle line + /// @param start Start vs. End time void SetVideoToSubs(bool start); + /// @brief Set the start/end time of the current subtitle line to the current frame + /// @param start Start vs. End time void SetSubsToVideo(bool start); + /// @brief Join the selected lines + /// @param n1 First line to join + /// @param n2 Last line to join + /// @param concat Concatenate the lines rather than discarding all past the first void JoinLines(int first,int last,bool concat=true); + /// @brief Join selected lines as karaoke, with their relative times used for syllable lengths + /// @param n1 First line to join + /// @param n2 Last line to join void JoinAsKaraoke(int first,int last); + /// @brief Adjoins selected lines, setting each line's start time to the previous line's end time + /// @param n1 First line to adjoin + /// @param n2 Last line to adjoin + /// @param setStart Set the start times (rather than end times) void AdjoinLines(int first,int last,bool setStart); - void SplitLine(int lineNumber,int splitPosition,int mode,wxString splitText = _T("")); + /// @brief Split line at the given position + /// @param line Line to split + /// @param pos Position in line + /// @param estimateTimes Adjust the times based on the lengths of the halves + void SplitLine(AssDialogue *line,int splitPosition,bool estimateTimes); + /// @brief Split a line into as many new lines as there are karaoke syllables, timed as the syllables + /// @param lineNumber Line to split + /// @return Were changes made? + /// + /// DOES NOT FLAG AS MODIFIED OR COMMIT CHANGES bool SplitLineByKaraoke(int lineNumber); + /// @brief Duplicate lines + /// @param n1 First frame to duplicate + /// @param n2 Last frame to duplicate + /// @param nextFrame Set the new lines to start and end on the next frame void DuplicateLines(int first,int last,bool nextFrame=false); void SwapLines(int line1,int line2); + /// @brief Shift line by time + /// @param n Line to shift + /// @param len ms to shift by + /// @param type 0: Start + End; 1: Start; 2: End void ShiftLineByTime(int lineNumber,int len,int type); + /// @brief Shift line by frames + /// @param n Line to shift + /// @param len frames to shift by + /// @param type 0: Start + End; 1: Start; 2: End void ShiftLineByFrames(int lineNumber,int len,int type); void InsertLine(AssDialogue *line,int position,bool insertAfter,bool update=true); + /// @brief Delete selected lines + /// @param target Lines to delete + /// @param flagModified Commit the file afterwards void DeleteLines(wxArrayInt lines, bool flagModified=true); + /// @brief Copy to clipboard + /// @param target Lines to copy void CopyLines(wxArrayInt lines); + /// @brief Cut to clipboard + /// @param target Lines to cut void CutLines(wxArrayInt lines); void PasteLines(int pos,bool over=false); + /// Retrieve a list of selected lines in the actual ASS file (i.e. not as displayed in the grid but as represented in the file) std::vector GetAbsoluteSelection(); + /// @brief Update list of selected lines from absolute selection + /// @param selection Sorted list of selections void SetSelectionFromAbsolute(std::vector &selection); DECLARE_EVENT_TABLE() }; - -/////// -// IDs +/// Menu event IDs enum { - - /// DOCME MENU_GRID_START = 1200, - - /// DOCME MENU_INSERT_BEFORE, - - /// DOCME MENU_INSERT_AFTER, - - /// DOCME MENU_INSERT_BEFORE_VIDEO, - - /// DOCME MENU_INSERT_AFTER_VIDEO, - - /// DOCME MENU_SWAP, - - /// DOCME MENU_DUPLICATE, - - /// DOCME MENU_DUPLICATE_NEXT_FRAME, - - /// DOCME MENU_SPLIT_BY_KARAOKE, - - /// DOCME MENU_COPY, - - /// DOCME MENU_PASTE, - - /// DOCME MENU_CUT, - - /// DOCME MENU_DELETE, - - /// DOCME MENU_JOIN_CONCAT, - - /// DOCME MENU_JOIN_REPLACE, - - /// DOCME MENU_ADJOIN, - - /// DOCME MENU_ADJOIN2, - - /// DOCME MENU_JOIN_AS_KARAOKE, - - /// DOCME MENU_RECOMBINE, - - /// DOCME MENU_SET_START_TO_VIDEO, - - /// DOCME MENU_SET_END_TO_VIDEO, - - /// DOCME MENU_SET_VIDEO_TO_START, - - /// DOCME MENU_SET_VIDEO_TO_END, - - /// DOCME MENU_GRID_END, - - /// DOCME MENU_AUDIOCLIP, - - /// DOCME MENU_SHOW_COL = 1250 // Don't put anything after this }; - - diff --git a/aegisub/src/timeedit_ctrl.cpp b/aegisub/src/timeedit_ctrl.cpp index f280f028e..9c999d386 100644 --- a/aegisub/src/timeedit_ctrl.cpp +++ b/aegisub/src/timeedit_ctrl.cpp @@ -102,10 +102,8 @@ wxTextCtrl(parent,id,value,pos,size,TimeEditWindowStyle | style,validator,name) ready = true; byFrame = false; isEnd = false; - modified = false; - showModified = false; - Connect(wxEVT_COMMAND_TEXT_UPDATED,wxCommandEventHandler(TimeEdit::OnModified)); - Connect(wxEVT_KILL_FOCUS,wxFocusEventHandler(TimeEdit::OnKillFocus)); + + Bind(wxEVT_COMMAND_TEXT_UPDATED, &TimeEdit::OnModified, this); } BEGIN_EVENT_TABLE(TimeEdit, wxTextCtrl) @@ -119,52 +117,41 @@ END_EVENT_TABLE() /// @param event void TimeEdit::OnModified(wxCommandEvent &event) { event.Skip(); - if (!ready) return; Modified(); } /// @brief Modified function -/// @param byUser -void TimeEdit::Modified(bool byUser) { +void TimeEdit::Modified() { if (!ready) return; ready = false; if (byFrame) Update(); - else UpdateTime(byUser); + else UpdateTime(true); - // Colour - if (showModified && !modified) { - SetBackgroundColour(lagi_wxColour(OPT_GET("Colour/Background/Modified")->GetColour())); - } - modified = true; ready = true; } /// @brief Set time and update stuff /// @param ms /// @param setModified -/// -void TimeEdit::SetTime(int ms,bool setModified) { - int oldMs = time.GetMS(); - time.SetMS(ms); - UpdateText(); - if (setModified && oldMs != ms) Modified(false); +void TimeEdit::SetTime(AssTime newTime) { + if (newTime != time) { + time = newTime; + UpdateText(); + } } /// @brief Toggles between set by frame and time /// @param enable -void TimeEdit::SetByFrame(bool enable) { - if (enable == byFrame) return; +void TimeEdit::SetByFrame(bool enableByFrame) { + if (enableByFrame == byFrame) return; - // By frames - if (enable) { + if (enableByFrame) { if (VideoContext::Get()->IsLoaded()) { byFrame = true; UpdateText(); } } - - // By actual time else { byFrame = false; UpdateText(); @@ -172,44 +159,32 @@ void TimeEdit::SetByFrame(bool enable) { } /// @brief Update text to reflect time value -/// void TimeEdit::UpdateText() { ready = false; if (byFrame) { int frame_n = VideoContext::Get()->FrameAtTime(time.GetMS(),isEnd ? agi::vfr::END : agi::vfr::START); - SetValue(wxString::Format(_T("%i"),frame_n)); + ChangeValue(wxString::Format("%i", frame_n)); } - else SetValue(time.GetASSFormated()); + else ChangeValue(time.GetASSFormated()); ready = true; } /// @brief Update -/// void TimeEdit::Update() { - // Update frame if (byFrame) { long temp; GetValue().ToLong(&temp); - time.SetMS(VideoContext::Get()->TimeAtFrame(temp,isEnd ? agi::vfr::END : agi::vfr::START)); + SetTime(VideoContext::Get()->TimeAtFrame(temp,isEnd ? agi::vfr::END : agi::vfr::START)); } // Update time if not on insertion mode else if (!OPT_GET("Subtitle/Time Edit/Insert Mode")->GetBool()) { UpdateTime(); - SetValue(time.GetASSFormated()); } - - // Update modified status - if (modified && showModified) { - SetBackgroundColour(wxNullColour); - Refresh(); - } - modified = false; } /// @brief Reads value from a text control and update it /// @param byUser -/// void TimeEdit::UpdateTime(bool byUser) { bool insertion = OPT_GET("Subtitle/Time Edit/Insert Mode")->GetBool(); wxString text = GetValue(); @@ -235,14 +210,13 @@ void TimeEdit::UpdateTime(bool byUser) { // Update time time.ParseASS(text); if (insertion) { - SetValue(time.GetASSFormated()); + ChangeValue(time.GetASSFormated()); SetSelection(start,end); } } /// @brief Key pressed /// @param event -/// void TimeEdit::OnKeyDown(wxKeyEvent &event) { // Get key ID int key = event.GetKeyCode(); @@ -281,19 +255,6 @@ void TimeEdit::OnKeyDown(wxKeyEvent &event) { } } -/// @brief Focus lost -/// @param event -/// -void TimeEdit::OnKillFocus(wxFocusEvent &event) { - if (!byFrame && !OPT_GET("Subtitle/Time Edit/Insert Mode")->GetBool()) { - if (time.GetASSFormated() != GetValue()) { - UpdateTime(); - SetValue(time.GetASSFormated()); - } - } - event.Skip(); -} - ///// Mouse/copy/paste events down here ///// /// @brief Mouse event @@ -315,9 +276,7 @@ void TimeEdit::OnMouseEvent(wxMouseEvent &event) { } /// @brief Menu Copy -/// @param event -/// -void TimeEdit::OnCopy(wxCommandEvent &event) { +void TimeEdit::OnCopy(wxCommandEvent &) { SetFocus(); SetSelection(0,GetValue().Length()); CopyTime(); @@ -325,18 +284,14 @@ void TimeEdit::OnCopy(wxCommandEvent &event) { } /// @brief Menu Paste -/// @param event -/// -void TimeEdit::OnPaste(wxCommandEvent &event) { +void TimeEdit::OnPaste(wxCommandEvent &) { SetFocus(); PasteTime(); Refresh(); } /// @brief Copy to clipboard -/// void TimeEdit::CopyTime() { - // Frame if (byFrame) { Copy(); return; @@ -350,9 +305,7 @@ void TimeEdit::CopyTime() { } /// @brief Paste from clipboard -/// void TimeEdit::PasteTime() { - // Frame if (byFrame) { Paste(); return; diff --git a/aegisub/src/timeedit_ctrl.h b/aegisub/src/timeedit_ctrl.h index d11d69d7c..b01927a77 100644 --- a/aegisub/src/timeedit_ctrl.h +++ b/aegisub/src/timeedit_ctrl.h @@ -52,17 +52,12 @@ /// class TimeEdit : public wxTextCtrl { private: - /// DOCME bool byFrame; /// DOCME bool ready; - /// DOCME - bool modified; - - void Modified(bool byUser=true); void UpdateText(); void CopyTime(); void PasteTime(); @@ -70,20 +65,14 @@ private: /// DOCME void UpdateTime(bool byUser=true); -/// DOCME - - /// DOCME void OnModified(wxCommandEvent &event); void OnMouseEvent(wxMouseEvent &event); void OnKeyDown(wxKeyEvent &event); void OnCopy(wxCommandEvent &event); void OnPaste(wxCommandEvent &event); - void OnKillFocus(wxFocusEvent &event); - -/// @brief DOCME -/// + void Modified(); public: /// DOCME @@ -94,34 +83,16 @@ public: /// DOCME - - /// DOCME - bool showModified; TimeEdit(wxWindow* parent, wxWindowID id, const wxString& value = _T(""), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxValidator& validator = wxDefaultValidator, const wxString& name = wxTextCtrlNameStr); void SetByFrame(bool enable); - void SetTime(int ms,bool setModified=false); + void SetTime(AssTime time); void Update(); - /// @brief DOCME - /// @return - /// - bool HasBeenModified() { return modified; } - DECLARE_EVENT_TABLE() }; - -/////// -// IDs enum { - - /// DOCME Time_Edit_Copy = 1320, - - /// DOCME Time_Edit_Paste }; - - - diff --git a/aegisub/src/video_context.cpp b/aegisub/src/video_context.cpp index 992a52c68..bf481ca89 100644 --- a/aegisub/src/video_context.cpp +++ b/aegisub/src/video_context.cpp @@ -60,6 +60,7 @@ #include "ass_time.h" #include "audio_display.h" #include "compat.h" +#include "export_visible_lines.h" #include "keyframe.h" #include #include "main.h" @@ -98,6 +99,7 @@ VideoContext::VideoContext() , arType(0) , hasSubtitles(false) , playAudioOnStep(OPT_GET("Audio/Plays When Stepping Video")) +, singleFrame(false) , grid(NULL) , audio(NULL) , VFR_Input(videoFPS) @@ -245,8 +247,17 @@ void VideoContext::UpdateDisplays(bool full, bool seek) { } } -void VideoContext::Refresh () { +void VideoContext::Refresh(bool full) { if (subsProvider.get()) { + if (full) { + AssLimitToVisibleFilter::SetFrame(-1); + singleFrame = false; + } + else { + AssLimitToVisibleFilter::SetFrame(frame_n); + singleFrame = true; + } + AssExporter exporter(grid->ass); exporter.AddAutoFilters(); try { @@ -267,6 +278,10 @@ void VideoContext::JumpToFrame(int n) { frame_n = n; + if (singleFrame) { + Refresh(true); + } + UpdateDisplays(false, true); static agi::OptionValue* highlight = OPT_GET("Subtitle/Grid/Highlight Subtitles in Frame"); @@ -401,8 +416,8 @@ void VideoContext::PlayLine() { // Set variables isPlaying = true; - startFrame = FrameAtTime(curline->Start.GetMS(),agi::vfr::START); - endFrame = FrameAtTime(curline->End.GetMS(),agi::vfr::END); + startFrame = FrameAtTime(grid->GetActiveLine()->Start.GetMS(),agi::vfr::START); + endFrame = FrameAtTime(grid->GetActiveLine()->End.GetMS(),agi::vfr::END); // Jump to start playNextFrame = startFrame; diff --git a/aegisub/src/video_context.h b/aegisub/src/video_context.h index 8b638f64f..27a348870 100644 --- a/aegisub/src/video_context.h +++ b/aegisub/src/video_context.h @@ -151,6 +151,8 @@ private: agi::vfr::Framerate videoFPS; agi::vfr::Framerate ovrFPS; + bool singleFrame; + public: /// DOCME SubtitlesGrid *grid; @@ -231,7 +233,9 @@ public: void JumpToTime(int ms, agi::vfr::Time end = agi::vfr::START); /// @brief Refresh the subtitle provider - void Refresh(); + /// @param full Send the entire subtitle file to the renderer rather than + /// just the lines visible on the current frame + void Refresh(bool full = false); /// @brief Update the video display /// @param full Recalculate size and slider lengths diff --git a/aegisub/src/visual_tool.cpp b/aegisub/src/visual_tool.cpp index c2d934575..e3ea2bbef 100644 --- a/aegisub/src/visual_tool.cpp +++ b/aegisub/src/visual_tool.cpp @@ -51,7 +51,6 @@ #include "ass_override.h" #include "ass_style.h" #include "ass_time.h" -#include "export_visible_lines.h" #include "main.h" #include "subs_edit_box.h" #include "subs_grid.h" @@ -155,8 +154,6 @@ void VisualTool::OnMouseEvent(wxMouseEvent &event) { } // end drag else { - if (realTime) AssLimitToVisibleFilter::SetFrame(-1); - dragging = false; // mouse didn't move, fiddle with selection @@ -197,8 +194,6 @@ void VisualTool::OnMouseEvent(wxMouseEvent &event) { } // end hold else { - if (realTime) AssLimitToVisibleFilter::SetFrame(-1); - holding = false; CommitHold(); Commit(true); @@ -234,7 +229,6 @@ void VisualTool::OnMouseEvent(wxMouseEvent &event) { dragging = true; parent->CaptureMouse(); - if (realTime) AssLimitToVisibleFilter::SetFrame(frameNumber); } } // start hold @@ -249,7 +243,6 @@ void VisualTool::OnMouseEvent(wxMouseEvent &event) { if (curDiag && InitializeHold()) { holding = true; parent->CaptureMouse(); - if (realTime) AssLimitToVisibleFilter::SetFrame(frameNumber); } } } @@ -267,9 +260,7 @@ void VisualTool::Commit(bool full, wxString message) { } grid->ass->Commit(message); } - grid->CommitChanges(false,!full); - if (full) - grid->editBox->Update(false, true); + grid->CommitChanges(full); externalChange = true; } diff --git a/aegisub/src/visual_tool.h b/aegisub/src/visual_tool.h index 0b322fc4a..f248a67b7 100644 --- a/aegisub/src/visual_tool.h +++ b/aegisub/src/visual_tool.h @@ -47,6 +47,7 @@ #include "base_grid.h" #include "gl_wrap.h" +#include "selection_controller.h" class VideoDisplay; class AssDialogue; diff --git a/aegisub/src/visual_tool_clip.cpp b/aegisub/src/visual_tool_clip.cpp index cb4c546eb..256a798a3 100644 --- a/aegisub/src/visual_tool_clip.cpp +++ b/aegisub/src/visual_tool_clip.cpp @@ -41,7 +41,6 @@ #include "ass_dialogue.h" #include "ass_file.h" -#include "subs_edit_box.h" #include "subs_grid.h" #include "utils.h" #include "video_display.h" diff --git a/aegisub/src/visual_tool_cross.cpp b/aegisub/src/visual_tool_cross.cpp index 8ac04fe31..a7a8f8a01 100644 --- a/aegisub/src/visual_tool_cross.cpp +++ b/aegisub/src/visual_tool_cross.cpp @@ -37,7 +37,6 @@ #include "ass_file.h" #include "gl_text.h" -#include "subs_edit_box.h" #include "subs_grid.h" #include "video_context.h" #include "video_display.h" diff --git a/aegisub/src/visual_tool_drag.cpp b/aegisub/src/visual_tool_drag.cpp index 001919dee..f7ea0d72c 100644 --- a/aegisub/src/visual_tool_drag.cpp +++ b/aegisub/src/visual_tool_drag.cpp @@ -38,7 +38,6 @@ #include "ass_dialogue.h" #include "ass_file.h" #include "libresrc/libresrc.h" -#include "subs_edit_box.h" #include "subs_grid.h" #include "utils.h" #include "video_context.h" diff --git a/aegisub/src/visual_tool_rotatexy.cpp b/aegisub/src/visual_tool_rotatexy.cpp index d9f951e99..58f14bf28 100644 --- a/aegisub/src/visual_tool_rotatexy.cpp +++ b/aegisub/src/visual_tool_rotatexy.cpp @@ -41,7 +41,6 @@ #include "ass_dialogue.h" #include "ass_file.h" -#include "subs_edit_box.h" #include "subs_grid.h" #include "utils.h" #include "video_context.h" diff --git a/aegisub/src/visual_tool_rotatez.cpp b/aegisub/src/visual_tool_rotatez.cpp index 54e207c98..0dfaba195 100644 --- a/aegisub/src/visual_tool_rotatez.cpp +++ b/aegisub/src/visual_tool_rotatez.cpp @@ -41,7 +41,6 @@ #include "ass_dialogue.h" #include "ass_file.h" -#include "subs_edit_box.h" #include "subs_grid.h" #include "utils.h" #include "video_context.h" diff --git a/aegisub/src/visual_tool_scale.cpp b/aegisub/src/visual_tool_scale.cpp index ec1d09548..d95da8f91 100644 --- a/aegisub/src/visual_tool_scale.cpp +++ b/aegisub/src/visual_tool_scale.cpp @@ -41,7 +41,6 @@ #include "ass_dialogue.h" #include "ass_file.h" -#include "subs_edit_box.h" #include "subs_grid.h" #include "utils.h" #include "video_context.h"