diff --git a/build/Aegisub/Aegisub.vcxproj b/build/Aegisub/Aegisub.vcxproj
index 9491799c9..7c2e91466 100644
--- a/build/Aegisub/Aegisub.vcxproj
+++ b/build/Aegisub/Aegisub.vcxproj
@@ -129,7 +129,6 @@
-
@@ -195,7 +194,6 @@
-
@@ -389,7 +387,6 @@
-
@@ -416,6 +413,7 @@
+
diff --git a/build/Aegisub/Aegisub.vcxproj.filters b/build/Aegisub/Aegisub.vcxproj.filters
index 9b0ce6d9d..b9a07eebd 100644
--- a/build/Aegisub/Aegisub.vcxproj.filters
+++ b/build/Aegisub/Aegisub.vcxproj.filters
@@ -210,9 +210,6 @@
Commands
-
- Config
-
Audio\Players
@@ -591,9 +588,6 @@
ASS
-
- Main UI\Edit box
-
Utilities\UI utilities
@@ -1148,9 +1142,6 @@
ASS
-
- Main UI\Edit box
-
Audio\Providers
@@ -1187,6 +1178,9 @@
Main UI
+
+ Main UI\Edit box
+
diff --git a/src/Makefile b/src/Makefile
index 8dc66b7ac..25a1e001c 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -208,7 +208,6 @@ SRC += \
preferences_base.cpp \
resolution_resampler.cpp \
scintilla_text_ctrl.cpp \
- scintilla_text_selection_controller.cpp \
search_replace_engine.cpp \
selection_controller.cpp \
spellchecker.cpp \
@@ -232,6 +231,7 @@ SRC += \
subtitles_provider.cpp \
text_file_reader.cpp \
text_file_writer.cpp \
+ text_selection_controller.cpp \
thesaurus.cpp \
threaded_frame_source.cpp \
timeedit_ctrl.cpp \
diff --git a/src/context.cpp b/src/context.cpp
index 2e89d56eb..b7725de68 100644
--- a/src/context.cpp
+++ b/src/context.cpp
@@ -24,6 +24,7 @@
#include "search_replace_engine.h"
#include "selection_controller.h"
#include "subs_controller.h"
+#include "text_selection_controller.h"
#include "video_context.h"
#include
@@ -31,6 +32,7 @@
namespace agi {
Context::Context()
: ass(util::make_unique())
+, textSelectionController(util::make_unique())
, subsController(util::make_unique(this))
, local_scripts(util::make_unique(this))
, videoController(util::make_unique(this))
diff --git a/src/include/aegisub/context.h b/src/include/aegisub/context.h
index f3186240a..23c3b405c 100644
--- a/src/include/aegisub/context.h
+++ b/src/include/aegisub/context.h
@@ -40,13 +40,13 @@ struct Context {
// Note: order here matters quite a bit, as things need to be set up and
// torn down in the correct order
std::unique_ptr ass;
+ std::unique_ptr textSelectionController;
std::unique_ptr subsController;
std::unique_ptr local_scripts;
std::unique_ptr videoController;
std::unique_ptr audioController;
std::unique_ptr selectionController;
std::unique_ptr initialLineState;
- TextSelectionController *textSelectionController;
std::unique_ptr search;
// Things that should probably be in some sort of UI-context-model
diff --git a/src/scintilla_text_ctrl.cpp b/src/scintilla_text_ctrl.cpp
index 4e5892a09..0c52eb097 100644
--- a/src/scintilla_text_ctrl.cpp
+++ b/src/scintilla_text_ctrl.cpp
@@ -64,15 +64,9 @@ void ScintillaTextCtrl::SetUnicodeStyling(int start,int length,int style) {
// Get the real length
int len = text.Mid(start, length).utf8_str().length();
- // Set styling
SetStyling(len,style);
}
-/// @brief Set selection, unicode-aware
-void ScintillaTextCtrl::SetSelectionU(int start, int end) {
- SetSelection(GetUnicodePosition(start),GetUnicodePosition(end));
-}
-
void ScintillaTextCtrl::OnMouseWheel(wxMouseEvent& evt) {
if (ForwardMouseWheelEvent(this, evt)) {
// Skip the event so that wxSTC's default mouse wheel handler is hit
diff --git a/src/scintilla_text_ctrl.h b/src/scintilla_text_ctrl.h
index 171aee242..220b1496b 100644
--- a/src/scintilla_text_ctrl.h
+++ b/src/scintilla_text_ctrl.h
@@ -46,7 +46,6 @@ public:
void StartUnicodeStyling(int start,int mask=31);
void SetUnicodeStyling(int start,int length,int style);
- void SetSelectionU(int start,int end);
ScintillaTextCtrl(wxWindow* parent, wxWindowID id, const wxString& value = wxString(), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0);
};
diff --git a/src/scintilla_text_selection_controller.cpp b/src/scintilla_text_selection_controller.cpp
deleted file mode 100644
index f54e68418..000000000
--- a/src/scintilla_text_selection_controller.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2012, Thomas Goyne
-//
-// Permission to use, copy, modify, and distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-//
-// Aegisub Project http://www.aegisub.org/
-
-#include "scintilla_text_selection_controller.h"
-
-#include "scintilla_text_ctrl.h"
-
-ScintillaTextSelectionController::ScintillaTextSelectionController(ScintillaTextCtrl *ctrl)
-: ctrl(ctrl)
-{
-}
-
-void ScintillaTextSelectionController::SetInsertionPoint(int position) {
- ctrl->SetInsertionPoint(position);
-}
-
-int ScintillaTextSelectionController::GetInsertionPoint() const {
- return ctrl->GetInsertionPoint();
-}
-
-void ScintillaTextSelectionController::SetSelection(int start, int end) {
- ctrl->SetSelection(start, end);
-}
-
-int ScintillaTextSelectionController::GetSelectionStart() const {
- return ctrl->GetSelectionStart();
-}
-
-int ScintillaTextSelectionController::GetSelectionEnd() const {
- return ctrl->GetSelectionEnd();
-}
diff --git a/src/scintilla_text_selection_controller.h b/src/scintilla_text_selection_controller.h
deleted file mode 100644
index d481dd014..000000000
--- a/src/scintilla_text_selection_controller.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2012, Thomas Goyne
-//
-// Permission to use, copy, modify, and distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-//
-// Aegisub Project http://www.aegisub.org/
-
-#include "text_selection_controller.h"
-
-class ScintillaTextCtrl;
-
-class ScintillaTextSelectionController final : public TextSelectionController {
- ScintillaTextCtrl *ctrl;
-
-public:
- void SetSelection(int start, int end) override;
- void SetInsertionPoint(int point) override;
-
- int GetSelectionStart() const override;
- int GetSelectionEnd() const override;
- int GetInsertionPoint() const override;
-
- ScintillaTextSelectionController(ScintillaTextCtrl *ctrl);
-};
diff --git a/src/subs_controller.cpp b/src/subs_controller.cpp
index 0b81147d0..4f3aae793 100644
--- a/src/subs_controller.cpp
+++ b/src/subs_controller.cpp
@@ -30,6 +30,7 @@
#include "selection_controller.h"
#include "subtitle_format.h"
#include "text_file_reader.h"
+#include "text_selection_controller.h"
#include "utils.h"
#include "video_context.h"
@@ -62,6 +63,7 @@ struct SubsController::UndoInfo {
mutable std::vector selection;
int active_line_id = 0;
+ int pos = 0, sel_start = 0, sel_end = 0;
UndoInfo(const agi::Context *c, wxString const& d, int commit_id)
: undo_description(d)
@@ -80,6 +82,7 @@ struct SubsController::UndoInfo {
UpdateActiveLine(c);
UpdateSelection(c);
+ UpdateTextSelection(c);
}
void Apply(agi::Context *c) const {
@@ -108,6 +111,9 @@ struct SubsController::UndoInfo {
c->ass->Commit("", AssFile::COMMIT_NEW);
c->selectionController->SetSelectionAndActive(std::move(new_sel), active_line);
+
+ c->textSelectionController->SetInsertionPoint(pos);
+ c->textSelectionController->SetSelection(sel_start, sel_end);
}
void UpdateActiveLine(const agi::Context *c) {
@@ -123,11 +129,18 @@ struct SubsController::UndoInfo {
for (const auto diag : sel)
selection.push_back(diag->Id);
}
+
+ void UpdateTextSelection(const agi::Context *c) {
+ pos = c->textSelectionController->GetInsertionPoint();
+ sel_start = c->textSelectionController->GetSelectionStart();
+ sel_end = c->textSelectionController->GetSelectionEnd();
+ }
};
SubsController::SubsController(agi::Context *context)
: context(context)
, undo_connection(context->ass->AddUndoManager(&SubsController::OnCommit, this))
+, text_selection_connection(context->textSelectionController->AddSelectionListener(&SubsController::OnTextSelectionChanged, this))
{
autosave_timer_changed(&autosave_timer);
OPT_SUB("App/Auto/Save", [=] { autosave_timer_changed(&autosave_timer); });
@@ -379,12 +392,20 @@ void SubsController::OnSelectionChanged() {
undo_stack.back().UpdateSelection(context);
}
+void SubsController::OnTextSelectionChanged() {
+ if (!undo_stack.empty())
+ undo_stack.back().UpdateTextSelection(context);
+}
+
void SubsController::Undo() {
if (undo_stack.size() <= 1) return;
redo_stack.splice(redo_stack.end(), undo_stack, std::prev(undo_stack.end()));
commit_id = undo_stack.back().commit_id;
+
+ text_selection_connection.Block();
undo_stack.back().Apply(context);
+ text_selection_connection.Unblock();
}
void SubsController::Redo() {
@@ -392,7 +413,10 @@ void SubsController::Redo() {
undo_stack.splice(undo_stack.end(), redo_stack, std::prev(redo_stack.end()));
commit_id = undo_stack.back().commit_id;
+
+ text_selection_connection.Block();
undo_stack.back().Apply(context);
+ text_selection_connection.Unblock();
}
wxString SubsController::GetUndoDescription() const {
diff --git a/src/subs_controller.h b/src/subs_controller.h
index fb03f61ae..843054551 100644
--- a/src/subs_controller.h
+++ b/src/subs_controller.h
@@ -34,6 +34,7 @@ class SubsController {
agi::signal::Connection undo_connection;
agi::signal::Connection active_line_connection;
agi::signal::Connection selection_connection;
+ agi::signal::Connection text_selection_connection;
struct UndoInfo;
boost::container::list undo_stack;
@@ -66,6 +67,7 @@ class SubsController {
void OnCommit(AssFileCommit c);
void OnActiveLineChanged();
void OnSelectionChanged();
+ void OnTextSelectionChanged();
public:
SubsController(agi::Context *context);
diff --git a/src/subs_edit_box.cpp b/src/subs_edit_box.cpp
index ad05bdd34..69e82f566 100644
--- a/src/subs_edit_box.cpp
+++ b/src/subs_edit_box.cpp
@@ -45,9 +45,9 @@
#include "libresrc/libresrc.h"
#include "options.h"
#include "placeholder_ctrl.h"
-#include "scintilla_text_selection_controller.h"
#include "selection_controller.h"
#include "subs_edit_ctrl.h"
+#include "text_selection_controller.h"
#include "timeedit_ctrl.h"
#include "tooltip_manager.h"
#include "utils.h"
@@ -213,12 +213,12 @@ SubsEditBox::SubsEditBox(wxWindow *parent, agi::Context *context)
connections.push_back(context->selectionController->AddSelectionListener(&SubsEditBox::OnSelectedSetChanged, this));
connections.push_back(context->initialLineState->AddChangeListener(&SubsEditBox::OnLineInitialTextChanged, this));
- textSelectionController = agi::util::make_unique(edit_ctrl);
- context->textSelectionController = textSelectionController.get();
+ context->textSelectionController->SetControl(edit_ctrl);
edit_ctrl->SetFocus();
}
SubsEditBox::~SubsEditBox() {
+ c->textSelectionController->SetControl(nullptr);
}
wxTextCtrl *SubsEditBox::MakeMarginCtrl(wxString const& tooltip, int margin, wxString const& commit_msg) {
@@ -293,11 +293,8 @@ void SubsEditBox::OnCommit(int type) {
}
if (type == AssFile::COMMIT_NEW) {
- /// @todo maybe preserve selection over undo?
PopulateList(effect_box, &AssDialogue::Effect);
PopulateList(actor_box, &AssDialogue::Actor);
-
- edit_ctrl->SetSelection(0,0);
return;
}
else if (type & AssFile::COMMIT_STYLES)
@@ -315,7 +312,7 @@ void SubsEditBox::OnCommit(int type) {
}
if (type & AssFile::COMMIT_DIAG_TEXT) {
- edit_ctrl->SetTextTo(to_wx(line->Text));
+ edit_ctrl->SetTextTo(line->Text);
UpdateCharacterCount(line->Text);
}
@@ -333,7 +330,7 @@ void SubsEditBox::OnCommit(int type) {
PopulateList(actor_box, &AssDialogue::Actor);
actor_box->ChangeValue(to_wx(line->Actor));
actor_box->SetStringSelection(to_wx(line->Actor));
- edit_ctrl->SetTextTo(to_wx(line->Text));
+ edit_ctrl->SetTextTo(line->Text);
}
}
diff --git a/src/subs_edit_box.h b/src/subs_edit_box.h
index cbb344107..afa38ebad 100644
--- a/src/subs_edit_box.h
+++ b/src/subs_edit_box.h
@@ -50,7 +50,6 @@ namespace agi { struct Context; }
class AssDialogue;
class AssTime;
class SubsTextEditCtrl;
-class TextSelectionController;
class TimeEdit;
class wxButton;
class wxCheckBox;
@@ -199,7 +198,6 @@ class SubsEditBox final : public wxPanel {
SubsTextEditCtrl *edit_ctrl;
wxTextCtrl *secondary_editor;
- std::unique_ptr textSelectionController;
public:
/// @brief Constructor
diff --git a/src/subs_edit_ctrl.cpp b/src/subs_edit_ctrl.cpp
index afe8e81b1..ac5ffead7 100644
--- a/src/subs_edit_ctrl.cpp
+++ b/src/subs_edit_ctrl.cpp
@@ -276,17 +276,13 @@ void SubsTextEditCtrl::UpdateCallTip() {
CallTipSetHighlight(new_calltip.highlight_start, new_calltip.highlight_end);
}
-void SubsTextEditCtrl::SetTextTo(wxString const& text) {
+void SubsTextEditCtrl::SetTextTo(std::string const& text) {
SetEvtHandlerEnabled(false);
Freeze();
- int from = GetReverseUnicodePosition(GetSelectionStart());
- int to = GetReverseUnicodePosition(GetSelectionEnd());
-
line_text.clear();
- SetText(text);
-
- SetSelectionU(from, to);
+ SetTextRaw(text.c_str());
+ SetSelection(0, 0);
SetEvtHandlerEnabled(true);
Thaw();
diff --git a/src/subs_edit_ctrl.h b/src/subs_edit_ctrl.h
index 4ce1734a0..24f7ceac0 100644
--- a/src/subs_edit_ctrl.h
+++ b/src/subs_edit_ctrl.h
@@ -122,7 +122,7 @@ public:
SubsTextEditCtrl(wxWindow* parent, wxSize size, long style, agi::Context *context);
~SubsTextEditCtrl();
- void SetTextTo(wxString const& text);
+ void SetTextTo(std::string const& text);
void Paste() override;
std::pair GetBoundsOfWordAtPosition(int pos);
diff --git a/src/text_selection_controller.cpp b/src/text_selection_controller.cpp
new file mode 100644
index 000000000..deefa6573
--- /dev/null
+++ b/src/text_selection_controller.cpp
@@ -0,0 +1,75 @@
+// Copyright (c) 2014, Thomas Goyne
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+// Aegisub Project http://www.aegisub.org/
+
+#include "text_selection_controller.h"
+
+#include
+
+void TextSelectionController::SetControl(wxStyledTextCtrl *ctrl) {
+ this->ctrl = ctrl;
+ if (ctrl)
+ ctrl->Bind(wxEVT_STC_UPDATEUI, &TextSelectionController::UpdateUI, this);
+}
+
+TextSelectionController::~TextSelectionController() {
+ if (ctrl) ctrl->Unbind(wxEVT_STC_UPDATEUI, &TextSelectionController::UpdateUI, this);
+}
+
+#define GET(var, new_value) do { \
+ int tmp = new_value; \
+ if (tmp != var) { \
+ var = tmp; \
+ changed = true; \
+ } \
+} while(false)
+
+#define SET(var, new_value, Setter) do { \
+ if (var != new_value) { \
+ var = new_value; \
+ if (ctrl) ctrl->Setter(var); \
+ } \
+} while (false)
+
+void TextSelectionController::UpdateUI(wxStyledTextEvent &evt) {
+ if (changing) return;
+
+ bool changed = false;
+ GET(insertion_point, ctrl->GetInsertionPoint());
+ if (evt.GetUpdated() & wxSTC_UPDATE_SELECTION) {
+ GET(selection_start, ctrl->GetSelectionStart());
+ GET(selection_end, ctrl->GetSelectionEnd());
+ }
+ else {
+ GET(selection_start, insertion_point);
+ GET(selection_end, insertion_point);
+ }
+ if (changed) AnnounceSelectionChanged();
+}
+
+void TextSelectionController::SetInsertionPoint(int position) {
+ changing = true;
+ SET(insertion_point, position, SetInsertionPoint);
+ changing = false;
+ AnnounceSelectionChanged();
+}
+
+void TextSelectionController::SetSelection(int start, int end) {
+ changing = true;
+ SET(selection_start, start, SetSelectionStart);
+ SET(selection_end, end, SetSelectionEnd);
+ changing = false;
+ AnnounceSelectionChanged();
+}
diff --git a/src/text_selection_controller.h b/src/text_selection_controller.h
index cc24c61c7..be6949ef4 100644
--- a/src/text_selection_controller.h
+++ b/src/text_selection_controller.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012, Thomas Goyne
+// Copyright (c) 2014, Thomas Goyne
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -14,16 +14,33 @@
//
// Aegisub Project http://www.aegisub.org/
-#pragma once
+#include
+
+class wxStyledTextCtrl;
+class wxStyledTextEvent;
class TextSelectionController {
+ int selection_start = 0;
+ int selection_end = 0;
+ int insertion_point = 0;
+ bool changing = false;
+
+ wxStyledTextCtrl *ctrl = nullptr;
+
+ void UpdateUI(wxStyledTextEvent &evt);
+
+ agi::signal::Signal<> AnnounceSelectionChanged;
+
public:
- virtual ~TextSelectionController() { }
+ void SetSelection(int start, int end);
+ void SetInsertionPoint(int point);
- virtual void SetSelection(int start, int end) = 0;
- virtual void SetInsertionPoint(int point) = 0;
+ int GetSelectionStart() const { return selection_start; }
+ int GetSelectionEnd() const { return selection_end; }
+ int GetInsertionPoint() const { return insertion_point; }
- virtual int GetSelectionStart() const = 0;
- virtual int GetSelectionEnd() const = 0;
- virtual int GetInsertionPoint() const = 0;
+ void SetControl(wxStyledTextCtrl *ctrl);
+ ~TextSelectionController();
+
+ DEFINE_SIGNAL_ADDERS(AnnounceSelectionChanged, AddSelectionListener)
};