Restore the text selection and cursor position on undo
This commit is contained in:
parent
56699e4800
commit
df42fdb2d2
17 changed files with 143 additions and 124 deletions
|
@ -129,7 +129,6 @@
|
||||||
<ClInclude Include="$(SrcDir)colour_button.h" />
|
<ClInclude Include="$(SrcDir)colour_button.h" />
|
||||||
<ClInclude Include="$(SrcDir)command\command.h" />
|
<ClInclude Include="$(SrcDir)command\command.h" />
|
||||||
<ClInclude Include="$(SrcDir)compat.h" />
|
<ClInclude Include="$(SrcDir)compat.h" />
|
||||||
<ClInclude Include="$(SrcDir)config.h" />
|
|
||||||
<ClInclude Include="$(SrcDir)crash_writer.h" />
|
<ClInclude Include="$(SrcDir)crash_writer.h" />
|
||||||
<ClInclude Include="$(SrcDir)dialog_about.h" />
|
<ClInclude Include="$(SrcDir)dialog_about.h" />
|
||||||
<ClInclude Include="$(SrcDir)dialog_attachments.h" />
|
<ClInclude Include="$(SrcDir)dialog_attachments.h" />
|
||||||
|
@ -195,7 +194,6 @@
|
||||||
<ClInclude Include="$(SrcDir)preferences_base.h" />
|
<ClInclude Include="$(SrcDir)preferences_base.h" />
|
||||||
<ClInclude Include="$(SrcDir)resolution_resampler.h" />
|
<ClInclude Include="$(SrcDir)resolution_resampler.h" />
|
||||||
<ClInclude Include="$(SrcDir)scintilla_text_ctrl.h" />
|
<ClInclude Include="$(SrcDir)scintilla_text_ctrl.h" />
|
||||||
<ClInclude Include="$(SrcDir)scintilla_text_selection_controller.h" />
|
|
||||||
<ClInclude Include="$(SrcDir)search_replace_engine.h" />
|
<ClInclude Include="$(SrcDir)search_replace_engine.h" />
|
||||||
<ClInclude Include="$(SrcDir)selection_controller.h" />
|
<ClInclude Include="$(SrcDir)selection_controller.h" />
|
||||||
<ClInclude Include="$(SrcDir)spellchecker_hunspell.h" />
|
<ClInclude Include="$(SrcDir)spellchecker_hunspell.h" />
|
||||||
|
@ -389,7 +387,6 @@
|
||||||
<ClCompile Include="$(SrcDir)preferences_base.cpp" />
|
<ClCompile Include="$(SrcDir)preferences_base.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)resolution_resampler.cpp" />
|
<ClCompile Include="$(SrcDir)resolution_resampler.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)scintilla_text_ctrl.cpp" />
|
<ClCompile Include="$(SrcDir)scintilla_text_ctrl.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)scintilla_text_selection_controller.cpp" />
|
|
||||||
<ClCompile Include="$(SrcDir)search_replace_engine.cpp" />
|
<ClCompile Include="$(SrcDir)search_replace_engine.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)selection_controller.cpp" />
|
<ClCompile Include="$(SrcDir)selection_controller.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)spellchecker.cpp" />
|
<ClCompile Include="$(SrcDir)spellchecker.cpp" />
|
||||||
|
@ -416,6 +413,7 @@
|
||||||
<ClCompile Include="$(SrcDir)subtitles_provider_libass.cpp" />
|
<ClCompile Include="$(SrcDir)subtitles_provider_libass.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)text_file_reader.cpp" />
|
<ClCompile Include="$(SrcDir)text_file_reader.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)text_file_writer.cpp" />
|
<ClCompile Include="$(SrcDir)text_file_writer.cpp" />
|
||||||
|
<ClCompile Include="$(SrcDir)text_selection_controller.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)thesaurus.cpp" />
|
<ClCompile Include="$(SrcDir)thesaurus.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)threaded_frame_source.cpp" />
|
<ClCompile Include="$(SrcDir)threaded_frame_source.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)timeedit_ctrl.cpp" />
|
<ClCompile Include="$(SrcDir)timeedit_ctrl.cpp" />
|
||||||
|
|
|
@ -210,9 +210,6 @@
|
||||||
<ClInclude Include="$(SrcDir)command\command.h">
|
<ClInclude Include="$(SrcDir)command\command.h">
|
||||||
<Filter>Commands</Filter>
|
<Filter>Commands</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="$(SrcDir)config.h">
|
|
||||||
<Filter>Config</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="$(SrcDir)audio_player_portaudio.h">
|
<ClInclude Include="$(SrcDir)audio_player_portaudio.h">
|
||||||
<Filter>Audio\Players</Filter>
|
<Filter>Audio\Players</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -591,9 +588,6 @@
|
||||||
<ClInclude Include="$(SrcDir)ass_parser.h">
|
<ClInclude Include="$(SrcDir)ass_parser.h">
|
||||||
<Filter>ASS</Filter>
|
<Filter>ASS</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="$(SrcDir)scintilla_text_selection_controller.h">
|
|
||||||
<Filter>Main UI\Edit box</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="$(SrcDir)dialog_manager.h">
|
<ClInclude Include="$(SrcDir)dialog_manager.h">
|
||||||
<Filter>Utilities\UI utilities</Filter>
|
<Filter>Utilities\UI utilities</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -1148,9 +1142,6 @@
|
||||||
<ClCompile Include="$(SrcDir)ass_parser.cpp">
|
<ClCompile Include="$(SrcDir)ass_parser.cpp">
|
||||||
<Filter>ASS</Filter>
|
<Filter>ASS</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="$(SrcDir)scintilla_text_selection_controller.cpp">
|
|
||||||
<Filter>Main UI\Edit box</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="$(SrcDir)audio_provider_lock.cpp">
|
<ClCompile Include="$(SrcDir)audio_provider_lock.cpp">
|
||||||
<Filter>Audio\Providers</Filter>
|
<Filter>Audio\Providers</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -1187,6 +1178,9 @@
|
||||||
<ClCompile Include="$(SrcDir)context.cpp">
|
<ClCompile Include="$(SrcDir)context.cpp">
|
||||||
<Filter>Main UI</Filter>
|
<Filter>Main UI</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="$(SrcDir)text_selection_controller.cpp">
|
||||||
|
<Filter>Main UI\Edit box</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="$(SrcDir)res/res.rc">
|
<ResourceCompile Include="$(SrcDir)res/res.rc">
|
||||||
|
|
|
@ -208,7 +208,6 @@ SRC += \
|
||||||
preferences_base.cpp \
|
preferences_base.cpp \
|
||||||
resolution_resampler.cpp \
|
resolution_resampler.cpp \
|
||||||
scintilla_text_ctrl.cpp \
|
scintilla_text_ctrl.cpp \
|
||||||
scintilla_text_selection_controller.cpp \
|
|
||||||
search_replace_engine.cpp \
|
search_replace_engine.cpp \
|
||||||
selection_controller.cpp \
|
selection_controller.cpp \
|
||||||
spellchecker.cpp \
|
spellchecker.cpp \
|
||||||
|
@ -232,6 +231,7 @@ SRC += \
|
||||||
subtitles_provider.cpp \
|
subtitles_provider.cpp \
|
||||||
text_file_reader.cpp \
|
text_file_reader.cpp \
|
||||||
text_file_writer.cpp \
|
text_file_writer.cpp \
|
||||||
|
text_selection_controller.cpp \
|
||||||
thesaurus.cpp \
|
thesaurus.cpp \
|
||||||
threaded_frame_source.cpp \
|
threaded_frame_source.cpp \
|
||||||
timeedit_ctrl.cpp \
|
timeedit_ctrl.cpp \
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "search_replace_engine.h"
|
#include "search_replace_engine.h"
|
||||||
#include "selection_controller.h"
|
#include "selection_controller.h"
|
||||||
#include "subs_controller.h"
|
#include "subs_controller.h"
|
||||||
|
#include "text_selection_controller.h"
|
||||||
#include "video_context.h"
|
#include "video_context.h"
|
||||||
|
|
||||||
#include <libaegisub/util.h>
|
#include <libaegisub/util.h>
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
namespace agi {
|
namespace agi {
|
||||||
Context::Context()
|
Context::Context()
|
||||||
: ass(util::make_unique<AssFile>())
|
: ass(util::make_unique<AssFile>())
|
||||||
|
, textSelectionController(util::make_unique<TextSelectionController>())
|
||||||
, subsController(util::make_unique<SubsController>(this))
|
, subsController(util::make_unique<SubsController>(this))
|
||||||
, local_scripts(util::make_unique<Automation4::LocalScriptManager>(this))
|
, local_scripts(util::make_unique<Automation4::LocalScriptManager>(this))
|
||||||
, videoController(util::make_unique<VideoContext>(this))
|
, videoController(util::make_unique<VideoContext>(this))
|
||||||
|
|
|
@ -40,13 +40,13 @@ struct Context {
|
||||||
// Note: order here matters quite a bit, as things need to be set up and
|
// Note: order here matters quite a bit, as things need to be set up and
|
||||||
// torn down in the correct order
|
// torn down in the correct order
|
||||||
std::unique_ptr<AssFile> ass;
|
std::unique_ptr<AssFile> ass;
|
||||||
|
std::unique_ptr<TextSelectionController> textSelectionController;
|
||||||
std::unique_ptr<SubsController> subsController;
|
std::unique_ptr<SubsController> subsController;
|
||||||
std::unique_ptr<Automation4::ScriptManager> local_scripts;
|
std::unique_ptr<Automation4::ScriptManager> local_scripts;
|
||||||
std::unique_ptr<VideoContext> videoController;
|
std::unique_ptr<VideoContext> videoController;
|
||||||
std::unique_ptr<AudioController> audioController;
|
std::unique_ptr<AudioController> audioController;
|
||||||
std::unique_ptr<SelectionController> selectionController;
|
std::unique_ptr<SelectionController> selectionController;
|
||||||
std::unique_ptr<InitialLineState> initialLineState;
|
std::unique_ptr<InitialLineState> initialLineState;
|
||||||
TextSelectionController *textSelectionController;
|
|
||||||
std::unique_ptr<SearchReplaceEngine> search;
|
std::unique_ptr<SearchReplaceEngine> search;
|
||||||
|
|
||||||
// Things that should probably be in some sort of UI-context-model
|
// Things that should probably be in some sort of UI-context-model
|
||||||
|
|
|
@ -64,15 +64,9 @@ void ScintillaTextCtrl::SetUnicodeStyling(int start,int length,int style) {
|
||||||
// Get the real length
|
// Get the real length
|
||||||
int len = text.Mid(start, length).utf8_str().length();
|
int len = text.Mid(start, length).utf8_str().length();
|
||||||
|
|
||||||
// Set styling
|
|
||||||
SetStyling(len,style);
|
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) {
|
void ScintillaTextCtrl::OnMouseWheel(wxMouseEvent& evt) {
|
||||||
if (ForwardMouseWheelEvent(this, evt)) {
|
if (ForwardMouseWheelEvent(this, evt)) {
|
||||||
// Skip the event so that wxSTC's default mouse wheel handler is hit
|
// Skip the event so that wxSTC's default mouse wheel handler is hit
|
||||||
|
|
|
@ -46,7 +46,6 @@ public:
|
||||||
|
|
||||||
void StartUnicodeStyling(int start,int mask=31);
|
void StartUnicodeStyling(int start,int mask=31);
|
||||||
void SetUnicodeStyling(int start,int length,int style);
|
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);
|
ScintillaTextCtrl(wxWindow* parent, wxWindowID id, const wxString& value = wxString(), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
// Copyright (c) 2012, Thomas Goyne <plorkyeran@aegisub.org>
|
|
||||||
//
|
|
||||||
// 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();
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
// Copyright (c) 2012, Thomas Goyne <plorkyeran@aegisub.org>
|
|
||||||
//
|
|
||||||
// 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);
|
|
||||||
};
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "selection_controller.h"
|
#include "selection_controller.h"
|
||||||
#include "subtitle_format.h"
|
#include "subtitle_format.h"
|
||||||
#include "text_file_reader.h"
|
#include "text_file_reader.h"
|
||||||
|
#include "text_selection_controller.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "video_context.h"
|
#include "video_context.h"
|
||||||
|
|
||||||
|
@ -62,6 +63,7 @@ struct SubsController::UndoInfo {
|
||||||
|
|
||||||
mutable std::vector<int> selection;
|
mutable std::vector<int> selection;
|
||||||
int active_line_id = 0;
|
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)
|
UndoInfo(const agi::Context *c, wxString const& d, int commit_id)
|
||||||
: undo_description(d)
|
: undo_description(d)
|
||||||
|
@ -80,6 +82,7 @@ struct SubsController::UndoInfo {
|
||||||
|
|
||||||
UpdateActiveLine(c);
|
UpdateActiveLine(c);
|
||||||
UpdateSelection(c);
|
UpdateSelection(c);
|
||||||
|
UpdateTextSelection(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Apply(agi::Context *c) const {
|
void Apply(agi::Context *c) const {
|
||||||
|
@ -108,6 +111,9 @@ struct SubsController::UndoInfo {
|
||||||
|
|
||||||
c->ass->Commit("", AssFile::COMMIT_NEW);
|
c->ass->Commit("", AssFile::COMMIT_NEW);
|
||||||
c->selectionController->SetSelectionAndActive(std::move(new_sel), active_line);
|
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) {
|
void UpdateActiveLine(const agi::Context *c) {
|
||||||
|
@ -123,11 +129,18 @@ struct SubsController::UndoInfo {
|
||||||
for (const auto diag : sel)
|
for (const auto diag : sel)
|
||||||
selection.push_back(diag->Id);
|
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)
|
SubsController::SubsController(agi::Context *context)
|
||||||
: context(context)
|
: context(context)
|
||||||
, undo_connection(context->ass->AddUndoManager(&SubsController::OnCommit, this))
|
, undo_connection(context->ass->AddUndoManager(&SubsController::OnCommit, this))
|
||||||
|
, text_selection_connection(context->textSelectionController->AddSelectionListener(&SubsController::OnTextSelectionChanged, this))
|
||||||
{
|
{
|
||||||
autosave_timer_changed(&autosave_timer);
|
autosave_timer_changed(&autosave_timer);
|
||||||
OPT_SUB("App/Auto/Save", [=] { 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);
|
undo_stack.back().UpdateSelection(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SubsController::OnTextSelectionChanged() {
|
||||||
|
if (!undo_stack.empty())
|
||||||
|
undo_stack.back().UpdateTextSelection(context);
|
||||||
|
}
|
||||||
|
|
||||||
void SubsController::Undo() {
|
void SubsController::Undo() {
|
||||||
if (undo_stack.size() <= 1) return;
|
if (undo_stack.size() <= 1) return;
|
||||||
redo_stack.splice(redo_stack.end(), undo_stack, std::prev(undo_stack.end()));
|
redo_stack.splice(redo_stack.end(), undo_stack, std::prev(undo_stack.end()));
|
||||||
|
|
||||||
commit_id = undo_stack.back().commit_id;
|
commit_id = undo_stack.back().commit_id;
|
||||||
|
|
||||||
|
text_selection_connection.Block();
|
||||||
undo_stack.back().Apply(context);
|
undo_stack.back().Apply(context);
|
||||||
|
text_selection_connection.Unblock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubsController::Redo() {
|
void SubsController::Redo() {
|
||||||
|
@ -392,7 +413,10 @@ void SubsController::Redo() {
|
||||||
undo_stack.splice(undo_stack.end(), redo_stack, std::prev(redo_stack.end()));
|
undo_stack.splice(undo_stack.end(), redo_stack, std::prev(redo_stack.end()));
|
||||||
|
|
||||||
commit_id = undo_stack.back().commit_id;
|
commit_id = undo_stack.back().commit_id;
|
||||||
|
|
||||||
|
text_selection_connection.Block();
|
||||||
undo_stack.back().Apply(context);
|
undo_stack.back().Apply(context);
|
||||||
|
text_selection_connection.Unblock();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString SubsController::GetUndoDescription() const {
|
wxString SubsController::GetUndoDescription() const {
|
||||||
|
|
|
@ -34,6 +34,7 @@ class SubsController {
|
||||||
agi::signal::Connection undo_connection;
|
agi::signal::Connection undo_connection;
|
||||||
agi::signal::Connection active_line_connection;
|
agi::signal::Connection active_line_connection;
|
||||||
agi::signal::Connection selection_connection;
|
agi::signal::Connection selection_connection;
|
||||||
|
agi::signal::Connection text_selection_connection;
|
||||||
|
|
||||||
struct UndoInfo;
|
struct UndoInfo;
|
||||||
boost::container::list<UndoInfo> undo_stack;
|
boost::container::list<UndoInfo> undo_stack;
|
||||||
|
@ -66,6 +67,7 @@ class SubsController {
|
||||||
void OnCommit(AssFileCommit c);
|
void OnCommit(AssFileCommit c);
|
||||||
void OnActiveLineChanged();
|
void OnActiveLineChanged();
|
||||||
void OnSelectionChanged();
|
void OnSelectionChanged();
|
||||||
|
void OnTextSelectionChanged();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SubsController(agi::Context *context);
|
SubsController(agi::Context *context);
|
||||||
|
|
|
@ -45,9 +45,9 @@
|
||||||
#include "libresrc/libresrc.h"
|
#include "libresrc/libresrc.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "placeholder_ctrl.h"
|
#include "placeholder_ctrl.h"
|
||||||
#include "scintilla_text_selection_controller.h"
|
|
||||||
#include "selection_controller.h"
|
#include "selection_controller.h"
|
||||||
#include "subs_edit_ctrl.h"
|
#include "subs_edit_ctrl.h"
|
||||||
|
#include "text_selection_controller.h"
|
||||||
#include "timeedit_ctrl.h"
|
#include "timeedit_ctrl.h"
|
||||||
#include "tooltip_manager.h"
|
#include "tooltip_manager.h"
|
||||||
#include "utils.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->selectionController->AddSelectionListener(&SubsEditBox::OnSelectedSetChanged, this));
|
||||||
connections.push_back(context->initialLineState->AddChangeListener(&SubsEditBox::OnLineInitialTextChanged, this));
|
connections.push_back(context->initialLineState->AddChangeListener(&SubsEditBox::OnLineInitialTextChanged, this));
|
||||||
|
|
||||||
textSelectionController = agi::util::make_unique<ScintillaTextSelectionController>(edit_ctrl);
|
context->textSelectionController->SetControl(edit_ctrl);
|
||||||
context->textSelectionController = textSelectionController.get();
|
|
||||||
edit_ctrl->SetFocus();
|
edit_ctrl->SetFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
SubsEditBox::~SubsEditBox() {
|
SubsEditBox::~SubsEditBox() {
|
||||||
|
c->textSelectionController->SetControl(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxTextCtrl *SubsEditBox::MakeMarginCtrl(wxString const& tooltip, int margin, wxString const& commit_msg) {
|
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) {
|
if (type == AssFile::COMMIT_NEW) {
|
||||||
/// @todo maybe preserve selection over undo?
|
|
||||||
PopulateList(effect_box, &AssDialogue::Effect);
|
PopulateList(effect_box, &AssDialogue::Effect);
|
||||||
PopulateList(actor_box, &AssDialogue::Actor);
|
PopulateList(actor_box, &AssDialogue::Actor);
|
||||||
|
|
||||||
edit_ctrl->SetSelection(0,0);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (type & AssFile::COMMIT_STYLES)
|
else if (type & AssFile::COMMIT_STYLES)
|
||||||
|
@ -315,7 +312,7 @@ void SubsEditBox::OnCommit(int type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type & AssFile::COMMIT_DIAG_TEXT) {
|
if (type & AssFile::COMMIT_DIAG_TEXT) {
|
||||||
edit_ctrl->SetTextTo(to_wx(line->Text));
|
edit_ctrl->SetTextTo(line->Text);
|
||||||
UpdateCharacterCount(line->Text);
|
UpdateCharacterCount(line->Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,7 +330,7 @@ void SubsEditBox::OnCommit(int type) {
|
||||||
PopulateList(actor_box, &AssDialogue::Actor);
|
PopulateList(actor_box, &AssDialogue::Actor);
|
||||||
actor_box->ChangeValue(to_wx(line->Actor));
|
actor_box->ChangeValue(to_wx(line->Actor));
|
||||||
actor_box->SetStringSelection(to_wx(line->Actor));
|
actor_box->SetStringSelection(to_wx(line->Actor));
|
||||||
edit_ctrl->SetTextTo(to_wx(line->Text));
|
edit_ctrl->SetTextTo(line->Text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,6 @@ namespace agi { struct Context; }
|
||||||
class AssDialogue;
|
class AssDialogue;
|
||||||
class AssTime;
|
class AssTime;
|
||||||
class SubsTextEditCtrl;
|
class SubsTextEditCtrl;
|
||||||
class TextSelectionController;
|
|
||||||
class TimeEdit;
|
class TimeEdit;
|
||||||
class wxButton;
|
class wxButton;
|
||||||
class wxCheckBox;
|
class wxCheckBox;
|
||||||
|
@ -199,7 +198,6 @@ class SubsEditBox final : public wxPanel {
|
||||||
|
|
||||||
SubsTextEditCtrl *edit_ctrl;
|
SubsTextEditCtrl *edit_ctrl;
|
||||||
wxTextCtrl *secondary_editor;
|
wxTextCtrl *secondary_editor;
|
||||||
std::unique_ptr<TextSelectionController> textSelectionController;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// @brief Constructor
|
/// @brief Constructor
|
||||||
|
|
|
@ -276,17 +276,13 @@ void SubsTextEditCtrl::UpdateCallTip() {
|
||||||
CallTipSetHighlight(new_calltip.highlight_start, new_calltip.highlight_end);
|
CallTipSetHighlight(new_calltip.highlight_start, new_calltip.highlight_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubsTextEditCtrl::SetTextTo(wxString const& text) {
|
void SubsTextEditCtrl::SetTextTo(std::string const& text) {
|
||||||
SetEvtHandlerEnabled(false);
|
SetEvtHandlerEnabled(false);
|
||||||
Freeze();
|
Freeze();
|
||||||
|
|
||||||
int from = GetReverseUnicodePosition(GetSelectionStart());
|
|
||||||
int to = GetReverseUnicodePosition(GetSelectionEnd());
|
|
||||||
|
|
||||||
line_text.clear();
|
line_text.clear();
|
||||||
SetText(text);
|
SetTextRaw(text.c_str());
|
||||||
|
SetSelection(0, 0);
|
||||||
SetSelectionU(from, to);
|
|
||||||
|
|
||||||
SetEvtHandlerEnabled(true);
|
SetEvtHandlerEnabled(true);
|
||||||
Thaw();
|
Thaw();
|
||||||
|
|
|
@ -122,7 +122,7 @@ public:
|
||||||
SubsTextEditCtrl(wxWindow* parent, wxSize size, long style, agi::Context *context);
|
SubsTextEditCtrl(wxWindow* parent, wxSize size, long style, agi::Context *context);
|
||||||
~SubsTextEditCtrl();
|
~SubsTextEditCtrl();
|
||||||
|
|
||||||
void SetTextTo(wxString const& text);
|
void SetTextTo(std::string const& text);
|
||||||
void Paste() override;
|
void Paste() override;
|
||||||
|
|
||||||
std::pair<int, int> GetBoundsOfWordAtPosition(int pos);
|
std::pair<int, int> GetBoundsOfWordAtPosition(int pos);
|
||||||
|
|
75
src/text_selection_controller.cpp
Normal file
75
src/text_selection_controller.cpp
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
|
//
|
||||||
|
// 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 <wx/stc/stc.h>
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2012, Thomas Goyne <plorkyeran@aegisub.org>
|
// Copyright (c) 2014, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
//
|
//
|
||||||
// Permission to use, copy, modify, and distribute this software for any
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -14,16 +14,33 @@
|
||||||
//
|
//
|
||||||
// Aegisub Project http://www.aegisub.org/
|
// Aegisub Project http://www.aegisub.org/
|
||||||
|
|
||||||
#pragma once
|
#include <libaegisub/signal.h>
|
||||||
|
|
||||||
|
class wxStyledTextCtrl;
|
||||||
|
class wxStyledTextEvent;
|
||||||
|
|
||||||
class TextSelectionController {
|
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:
|
public:
|
||||||
virtual ~TextSelectionController() { }
|
void SetSelection(int start, int end);
|
||||||
|
void SetInsertionPoint(int point);
|
||||||
|
|
||||||
virtual void SetSelection(int start, int end) = 0;
|
int GetSelectionStart() const { return selection_start; }
|
||||||
virtual void SetInsertionPoint(int point) = 0;
|
int GetSelectionEnd() const { return selection_end; }
|
||||||
|
int GetInsertionPoint() const { return insertion_point; }
|
||||||
|
|
||||||
virtual int GetSelectionStart() const = 0;
|
void SetControl(wxStyledTextCtrl *ctrl);
|
||||||
virtual int GetSelectionEnd() const = 0;
|
~TextSelectionController();
|
||||||
virtual int GetInsertionPoint() const = 0;
|
|
||||||
|
DEFINE_SIGNAL_ADDERS(AnnounceSelectionChanged, AddSelectionListener)
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue