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
build/Aegisub
src
Makefilecontext.cpp
include/aegisub
scintilla_text_ctrl.cppscintilla_text_ctrl.hscintilla_text_selection_controller.cppscintilla_text_selection_controller.hsubs_controller.cppsubs_controller.hsubs_edit_box.cppsubs_edit_box.hsubs_edit_ctrl.cppsubs_edit_ctrl.htext_selection_controller.cpptext_selection_controller.h
|
@ -129,7 +129,6 @@
|
|||
<ClInclude Include="$(SrcDir)colour_button.h" />
|
||||
<ClInclude Include="$(SrcDir)command\command.h" />
|
||||
<ClInclude Include="$(SrcDir)compat.h" />
|
||||
<ClInclude Include="$(SrcDir)config.h" />
|
||||
<ClInclude Include="$(SrcDir)crash_writer.h" />
|
||||
<ClInclude Include="$(SrcDir)dialog_about.h" />
|
||||
<ClInclude Include="$(SrcDir)dialog_attachments.h" />
|
||||
|
@ -195,7 +194,6 @@
|
|||
<ClInclude Include="$(SrcDir)preferences_base.h" />
|
||||
<ClInclude Include="$(SrcDir)resolution_resampler.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)selection_controller.h" />
|
||||
<ClInclude Include="$(SrcDir)spellchecker_hunspell.h" />
|
||||
|
@ -389,7 +387,6 @@
|
|||
<ClCompile Include="$(SrcDir)preferences_base.cpp" />
|
||||
<ClCompile Include="$(SrcDir)resolution_resampler.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)selection_controller.cpp" />
|
||||
<ClCompile Include="$(SrcDir)spellchecker.cpp" />
|
||||
|
@ -416,6 +413,7 @@
|
|||
<ClCompile Include="$(SrcDir)subtitles_provider_libass.cpp" />
|
||||
<ClCompile Include="$(SrcDir)text_file_reader.cpp" />
|
||||
<ClCompile Include="$(SrcDir)text_file_writer.cpp" />
|
||||
<ClCompile Include="$(SrcDir)text_selection_controller.cpp" />
|
||||
<ClCompile Include="$(SrcDir)thesaurus.cpp" />
|
||||
<ClCompile Include="$(SrcDir)threaded_frame_source.cpp" />
|
||||
<ClCompile Include="$(SrcDir)timeedit_ctrl.cpp" />
|
||||
|
|
|
@ -210,9 +210,6 @@
|
|||
<ClInclude Include="$(SrcDir)command\command.h">
|
||||
<Filter>Commands</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)config.h">
|
||||
<Filter>Config</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)audio_player_portaudio.h">
|
||||
<Filter>Audio\Players</Filter>
|
||||
</ClInclude>
|
||||
|
@ -591,9 +588,6 @@
|
|||
<ClInclude Include="$(SrcDir)ass_parser.h">
|
||||
<Filter>ASS</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)scintilla_text_selection_controller.h">
|
||||
<Filter>Main UI\Edit box</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(SrcDir)dialog_manager.h">
|
||||
<Filter>Utilities\UI utilities</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1148,9 +1142,6 @@
|
|||
<ClCompile Include="$(SrcDir)ass_parser.cpp">
|
||||
<Filter>ASS</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)scintilla_text_selection_controller.cpp">
|
||||
<Filter>Main UI\Edit box</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)audio_provider_lock.cpp">
|
||||
<Filter>Audio\Providers</Filter>
|
||||
</ClCompile>
|
||||
|
@ -1187,6 +1178,9 @@
|
|||
<ClCompile Include="$(SrcDir)context.cpp">
|
||||
<Filter>Main UI</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(SrcDir)text_selection_controller.cpp">
|
||||
<Filter>Main UI\Edit box</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="$(SrcDir)res/res.rc">
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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 <libaegisub/util.h>
|
||||
|
@ -31,6 +32,7 @@
|
|||
namespace agi {
|
||||
Context::Context()
|
||||
: ass(util::make_unique<AssFile>())
|
||||
, textSelectionController(util::make_unique<TextSelectionController>())
|
||||
, subsController(util::make_unique<SubsController>(this))
|
||||
, local_scripts(util::make_unique<Automation4::LocalScriptManager>(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
|
||||
// torn down in the correct order
|
||||
std::unique_ptr<AssFile> ass;
|
||||
std::unique_ptr<TextSelectionController> textSelectionController;
|
||||
std::unique_ptr<SubsController> subsController;
|
||||
std::unique_ptr<Automation4::ScriptManager> local_scripts;
|
||||
std::unique_ptr<VideoContext> videoController;
|
||||
std::unique_ptr<AudioController> audioController;
|
||||
std::unique_ptr<SelectionController> selectionController;
|
||||
std::unique_ptr<InitialLineState> initialLineState;
|
||||
TextSelectionController *textSelectionController;
|
||||
std::unique_ptr<SearchReplaceEngine> search;
|
||||
|
||||
// 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
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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 "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<int> 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 {
|
||||
|
|
|
@ -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<UndoInfo> undo_stack;
|
||||
|
@ -66,6 +67,7 @@ class SubsController {
|
|||
void OnCommit(AssFileCommit c);
|
||||
void OnActiveLineChanged();
|
||||
void OnSelectionChanged();
|
||||
void OnTextSelectionChanged();
|
||||
|
||||
public:
|
||||
SubsController(agi::Context *context);
|
||||
|
|
|
@ -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<ScintillaTextSelectionController>(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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> textSelectionController;
|
||||
|
||||
public:
|
||||
/// @brief Constructor
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<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
|
||||
// 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 <libaegisub/signal.h>
|
||||
|
||||
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)
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue