fix: Fixes for breakpoints (#1923)
WARNING: this PR won't compile unless [PR 132 from pattern language repository](https://github.com/WerWolv/PatternLanguage/pull/132) is merged first. Some changes here are shared by at least another PR to this repository but there should not be any conflicts as the shared changes are identical. ### Problem description fix: Editing patterns with breakpoints sets behaves unexpectedly. As a simple example, set a breakpoint and insert a blank line somewhere before the breakpoint location. The breakpoint will appear to move but in reality it hasn't. To see this set another breakpoint elsewhere in the file and the old one will be displayed where it is really located at. The reason for this and many other problems with breakpoints is that currently ImHex keeps two set of breakpoints in text editor and in evaluator that are independent of each other, ie, changes to one don't affect the other. This PR aims at synchronizing the two sets through the per provider breakpoints that exist in view pattern editor. ### Implementation description It accomplishes this by making the text editor version of breakpoints the principal source of vectors and the ones in evaluator the effective version. The first allows one to modify the text around and at the breakpoint and notify others that the changes have induced changes in the breakpoint locations. The effective breakpoints allow the insertion and deletion of breakpoints. View pattern editor is where breakpoints are updated. It receives notifications from text editor about changes and then makes sure the version in evaluator is updated with those changes. View pattern editor also manages breakpoint addition and deletion so before making changes it gets a copy of the current ones from text editor, sets the ones in evaluator, uses the evaluator functions to add or delete breakpoints and finally sets the text editor version with the new version.
This commit is contained in:
parent
7e0f60615b
commit
382a62343d
@ -133,7 +133,7 @@ public:
|
||||
using Keywords = std::unordered_set<std::string> ;
|
||||
using ErrorMarkers = std::map<Coordinates, std::pair<uint32_t ,std::string>>;
|
||||
using ErrorHoverBoxes = std::map<Coordinates, std::pair<ImVec2,ImVec2>>;
|
||||
using Breakpoints = std::unordered_set<int32_t>;
|
||||
using Breakpoints = std::unordered_set<uint32_t>;
|
||||
using Palette = std::array<ImU32, (uint32_t)PaletteIndex::Max>;
|
||||
using Char = uint8_t ;
|
||||
|
||||
@ -229,6 +229,8 @@ public:
|
||||
bool IsReadOnly() const { return mReadOnly; }
|
||||
bool IsTextChanged() const { return mTextChanged; }
|
||||
bool IsCursorPositionChanged() const { return mCursorPositionChanged; }
|
||||
bool IsBreakpointsChanged() const { return mBreakPointsChanged; }
|
||||
void ClearBreakpointsChanged() { mBreakPointsChanged = false; }
|
||||
|
||||
void SetShowCursor(bool aValue) { mShowCursor = aValue; }
|
||||
void SetShowLineNumbers(bool aValue) { mShowLineNumbers = aValue; }
|
||||
@ -468,6 +470,7 @@ private:
|
||||
float mTextStart; // position (in pixels) where a code line starts relative to the left of the TextEditor.
|
||||
int mLeftMargin;
|
||||
bool mCursorPositionChanged;
|
||||
bool mBreakPointsChanged;
|
||||
int mColorRangeMin, mColorRangeMax;
|
||||
SelectionMode mSelectionMode;
|
||||
bool mHandleKeyboardInputs;
|
||||
|
@ -592,12 +592,17 @@ void TextEditor::RemoveLine(int aStart, int aEnd) {
|
||||
mErrorMarkers = std::move(etmp);
|
||||
|
||||
Breakpoints btmp;
|
||||
for (auto i : mBreakpoints) {
|
||||
if (i >= aStart && i <= aEnd)
|
||||
continue;
|
||||
btmp.insert(i >= aStart ? i - 1 : i);
|
||||
for (auto breakpoint : mBreakpoints) {
|
||||
if (breakpoint <= aStart || breakpoint >= aEnd) {
|
||||
if (breakpoint >= aEnd) {
|
||||
btmp.insert(breakpoint - 1);
|
||||
mBreakPointsChanged = true;
|
||||
} else
|
||||
btmp.insert(breakpoint);
|
||||
}
|
||||
}
|
||||
mBreakpoints = std::move(btmp);
|
||||
if (mBreakPointsChanged)
|
||||
mBreakpoints = std::move(btmp);
|
||||
if (aStart == 0 && aEnd == (int32_t)mLines.size() - 1)
|
||||
mLines.erase(mLines.begin() + aStart, mLines.end());
|
||||
else
|
||||
@ -620,12 +625,15 @@ void TextEditor::RemoveLine(int aIndex) {
|
||||
mErrorMarkers = std::move(etmp);
|
||||
|
||||
Breakpoints btmp;
|
||||
for (auto i : mBreakpoints) {
|
||||
if (i == aIndex)
|
||||
continue;
|
||||
btmp.insert(i >= aIndex ? i - 1 : i);
|
||||
for (auto breakpoint : mBreakpoints) {
|
||||
if (breakpoint > aIndex) {
|
||||
btmp.insert(breakpoint - 1);
|
||||
mBreakPointsChanged = true;
|
||||
}else
|
||||
btmp.insert(breakpoint);
|
||||
}
|
||||
mBreakpoints = std::move(btmp);
|
||||
if (mBreakPointsChanged)
|
||||
mBreakpoints = std::move(btmp);
|
||||
|
||||
mLines.erase(mLines.begin() + aIndex);
|
||||
assert(!mLines.empty());
|
||||
@ -642,9 +650,15 @@ TextEditor::Line &TextEditor::InsertLine(int aIndex) {
|
||||
mErrorMarkers = std::move(etmp);
|
||||
|
||||
Breakpoints btmp;
|
||||
for (auto i : mBreakpoints)
|
||||
btmp.insert(i >= aIndex ? i + 1 : i);
|
||||
mBreakpoints = std::move(btmp);
|
||||
for (auto breakpoint : mBreakpoints) {
|
||||
if (breakpoint >= aIndex) {
|
||||
btmp.insert(breakpoint + 1);
|
||||
mBreakPointsChanged = true;
|
||||
} else
|
||||
btmp.insert(breakpoint);
|
||||
}
|
||||
if (mBreakPointsChanged)
|
||||
mBreakpoints = std::move(btmp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -251,6 +251,7 @@ namespace hex::plugin::builtin {
|
||||
std::mutex m_logMutex;
|
||||
|
||||
PerProvider<TextEditor::Coordinates> m_cursorPosition;
|
||||
|
||||
PerProvider<TextEditor::Coordinates> m_consoleCursorPosition;
|
||||
PerProvider<TextEditor::Selection> m_selection;
|
||||
PerProvider<TextEditor::Selection> m_consoleSelection;
|
||||
|
@ -562,6 +562,16 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}
|
||||
|
||||
if (m_textEditor.IsBreakpointsChanged()) {
|
||||
m_breakpoints = m_textEditor.GetBreakpoints();
|
||||
m_textEditor.ClearBreakpointsChanged();
|
||||
const auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||
auto &evaluator = runtime.getInternals().evaluator;
|
||||
if (evaluator) {
|
||||
evaluator->setBreakpoints(m_breakpoints);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_textEditor.IsTextChanged()) {
|
||||
m_hasUnevaluatedChanges = true;
|
||||
m_lastEditorChangeTime = std::chrono::steady_clock::now();
|
||||
@ -1249,23 +1259,23 @@ namespace hex::plugin::builtin {
|
||||
|
||||
if (ImGui::BeginChild("##debugger", size, true)) {
|
||||
auto &evaluator = runtime.getInternals().evaluator;
|
||||
const auto &breakpoints = evaluator->getBreakpoints();
|
||||
m_breakpoints = m_textEditor.GetBreakpoints();
|
||||
evaluator->setBreakpoints(m_breakpoints);
|
||||
const auto line = m_textEditor.GetCursorPosition().mLine + 1;
|
||||
|
||||
if (!breakpoints.contains(line)) {
|
||||
if (!m_breakpoints->contains(line)) {
|
||||
if (ImGuiExt::IconButton(ICON_VS_DEBUG_BREAKPOINT, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarRed))) {
|
||||
evaluator->addBreakpoint(line);
|
||||
m_textEditor.SetBreakpoints(breakpoints);
|
||||
}
|
||||
ImGuiExt::InfoTooltip("hex.builtin.view.pattern_editor.debugger.add_tooltip"_lang);
|
||||
} else {
|
||||
if (ImGuiExt::IconButton(ICON_VS_DEBUG_BREAKPOINT_UNVERIFIED, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarRed))) {
|
||||
evaluator->removeBreakpoint(line);
|
||||
m_textEditor.SetBreakpoints(breakpoints);
|
||||
}
|
||||
ImGuiExt::InfoTooltip("hex.builtin.view.pattern_editor.debugger.remove_tooltip"_lang);
|
||||
}
|
||||
|
||||
m_breakpoints = evaluator->getBreakpoints();
|
||||
m_textEditor.SetBreakpoints(m_breakpoints);
|
||||
ImGui::SameLine();
|
||||
|
||||
if (*m_breakpointHit) {
|
||||
@ -2397,15 +2407,16 @@ namespace hex::plugin::builtin {
|
||||
const auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||
|
||||
auto &evaluator = runtime.getInternals().evaluator;
|
||||
auto &breakpoints = evaluator->getBreakpoints();
|
||||
m_breakpoints = m_textEditor.GetBreakpoints();
|
||||
evaluator->setBreakpoints(m_breakpoints);
|
||||
|
||||
if (breakpoints.contains(line)) {
|
||||
if (m_breakpoints->contains(line)) {
|
||||
evaluator->removeBreakpoint(line);
|
||||
} else {
|
||||
evaluator->addBreakpoint(line);
|
||||
}
|
||||
|
||||
m_textEditor.SetBreakpoints(breakpoints);
|
||||
m_breakpoints = evaluator->getBreakpoints();
|
||||
m_textEditor.SetBreakpoints(m_breakpoints);
|
||||
});
|
||||
|
||||
/* Trigger evaluation */
|
||||
|
Loading…
x
Reference in New Issue
Block a user