[escher/text_area] Improve dirty tracking

This commit is contained in:
Léa Saviot
2019-10-11 09:39:24 +02:00
parent 1f44f80e4a
commit e98b67634d
4 changed files with 40 additions and 21 deletions

View File

@@ -179,13 +179,13 @@ void PythonTextArea::ContentView::drawLine(KDContext * ctx, int line, const char
}
}
KDRect PythonTextArea::ContentView::dirtyRectFromPosition(const char * position, bool lineBreak) const {
KDRect PythonTextArea::ContentView::dirtyRectFromPosition(const char * position, bool includeFollowingLines) const {
/* Mark the whole line as dirty.
* TextArea has a very conservative approach and only dirties the surroundings
* of the current character. That works for plain text, but when doing syntax
* highlighting, you may want to redraw the surroundings as well. For example,
* if editing "def foo" into "df foo", you'll want to redraw "df". */
KDRect baseDirtyRect = TextArea::ContentView::dirtyRectFromPosition(position, lineBreak);
KDRect baseDirtyRect = TextArea::ContentView::dirtyRectFromPosition(position, includeFollowingLines);
return KDRect(
bounds().x(),
baseDirtyRect.y(),

View File

@@ -28,7 +28,7 @@ protected:
void unloadSyntaxHighlighter();
void clearRect(KDContext * ctx, KDRect rect) const override;
void drawLine(KDContext * ctx, int line, const char * text, size_t length, int fromColumn, int toColumn, const char * selectionStart, const char * selectionEnd) const override;
KDRect dirtyRectFromPosition(const char * position, bool lineBreak) const override;
KDRect dirtyRectFromPosition(const char * position, bool includeFollowingLines) const override;
private:
App * m_pythonDelegate;
};

View File

@@ -46,9 +46,10 @@ protected:
const char * m_selectionEnd;
protected:
virtual void layoutSubviews(bool force = false) override;
void reloadRectFromPosition(const char * position, bool lineBreak = false);
void reloadRectFromPosition(const char * position, bool includeFollowingLines = false);
void reloadRectFromAndToPositions(const char * start, const char * end);
virtual KDRect glyphFrameAtPosition(const char * buffer, const char * position) const = 0;
virtual KDRect dirtyRectFromPosition(const char * position, bool lineBreak) const;
virtual KDRect dirtyRectFromPosition(const char * position, bool includeFollowingLines) const;
TextCursorView m_cursorView;
const KDFont * m_font;
const char * m_cursorLocation;

View File

@@ -26,6 +26,11 @@ KDRect TextInput::ContentView::cursorRect() {
}
void TextInput::ContentView::addSelection(const char * left, const char * right) {
if ((left == m_selectionStart && right <= m_selectionEnd)
|| (right == m_selectionEnd && left >= m_selectionStart))
{
return;
}
bool emptySelection = selectionIsEmpty();
if (emptySelection) {
m_selectionStart = left;
@@ -40,11 +45,11 @@ void TextInput::ContentView::addSelection(const char * left, const char * right)
assert(left == m_selectionStart);
m_selectionStart = right;
}
reloadRectFromAndToPositions(left, right);
if (m_selectionStart == m_selectionEnd) {
m_selectionStart = nullptr;
m_selectionEnd = nullptr;
}
reloadRectFromPosition(left, true); //TODO LEA
}
bool TextInput::ContentView::resetSelection() {
@@ -52,9 +57,10 @@ bool TextInput::ContentView::resetSelection() {
if (previousStart == nullptr) {
return false;
}
const char * previousEnd = m_selectionEnd;
m_selectionStart = nullptr;
m_selectionEnd = nullptr;
reloadRectFromPosition(previousStart); //TODO LEA many lines?
reloadRectFromAndToPositions(previousStart, previousEnd);
return true;
}
@@ -68,24 +74,36 @@ void TextInput::ContentView::layoutSubviews(bool force) {
m_cursorView.setFrame(cursorRect(), force);
}
void TextInput::ContentView::reloadRectFromPosition(const char * position, bool lineBreak) {
markRectAsDirty(dirtyRectFromPosition(position, lineBreak));
void TextInput::ContentView::reloadRectFromPosition(const char * position, bool includeFollowingLines) {
markRectAsDirty(dirtyRectFromPosition(position, includeFollowingLines));
}
KDRect TextInput::ContentView::dirtyRectFromPosition(const char * position, bool lineBreak) const {
void TextInput::ContentView::reloadRectFromAndToPositions(const char * start, const char * end) {
KDRect startFrame = glyphFrameAtPosition(text(), start);
KDRect endFrame = glyphFrameAtPosition(text(), end);
bool onSameLine = startFrame.y() == endFrame.y();
markRectAsDirty(KDRect(
onSameLine ? startFrame.x() : 0,
startFrame.y(),
onSameLine ? endFrame.right() - startFrame.left() : bounds().width(),
endFrame.bottom() - startFrame.top() + 1));
}
KDRect TextInput::ContentView::dirtyRectFromPosition(const char * position, bool includeFollowingLines) const {
KDRect glyphRect = glyphFrameAtPosition(text(), position);
KDRect dirtyRect = KDRect(
glyphRect.x(),
glyphRect.y(),
bounds().width() - glyphRect.x(),
glyphRect.height());
if (lineBreak) {
dirtyRect = dirtyRect.unionedWith(
KDRect(0,
glyphRect.bottom() + 1,
bounds().width(),
bounds().height() - glyphRect.bottom() - 1));
if (!includeFollowingLines) {
KDRect dirtyRect = KDRect(
glyphRect.x(),
glyphRect.y(),
bounds().width() - glyphRect.x(),
glyphRect.height());
return dirtyRect;
}
KDRect dirtyRect = KDRect(
0,
glyphRect.y(),
bounds().width(),
bounds().height() - glyphRect.y());
return dirtyRect;
}