summaryrefslogtreecommitdiff
path: root/Libraries/LibGUI/GTextDocument.h
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-10-27 16:10:07 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-10-27 16:44:16 +0100
commitf1c6193d6d5b35942be4732f65db65ac944b064a (patch)
treeb0a0f9806e87425d3975f23dce3fb5d91bc75fe7 /Libraries/LibGUI/GTextDocument.h
parent1bcbc3f827ede8e0e701b44b582e830a6a673c9a (diff)
downloadserenity-f1c6193d6d5b35942be4732f65db65ac944b064a.zip
LibGUI: Move GTextDocument out of GTextEditor
The idea here is to decouple the document from the editor widget so you could have multiple editors being views onto the same document. This doesn't work yet, since the document and editor are coupled in various ways still (including a per-line back-pointer to the editor.)
Diffstat (limited to 'Libraries/LibGUI/GTextDocument.h')
-rw-r--r--Libraries/LibGUI/GTextDocument.h83
1 files changed, 83 insertions, 0 deletions
diff --git a/Libraries/LibGUI/GTextDocument.h b/Libraries/LibGUI/GTextDocument.h
new file mode 100644
index 0000000000..b1bd94246d
--- /dev/null
+++ b/Libraries/LibGUI/GTextDocument.h
@@ -0,0 +1,83 @@
+#pragma once
+
+#include <AK/NonnullOwnPtrVector.h>
+#include <AK/NonnullRefPtr.h>
+#include <AK/RefCounted.h>
+#include <LibDraw/Color.h>
+#include <LibDraw/Font.h>
+#include <LibGUI/GTextRange.h>
+
+class GTextEditor;
+class GTextDocumentLine;
+
+struct GTextDocumentSpan {
+ GTextRange range;
+ Color color;
+ const Font* font { nullptr };
+};
+
+class GTextDocument : public RefCounted<GTextDocument> {
+public:
+ static NonnullRefPtr<GTextDocument> create(GTextEditor& editor)
+ {
+ return adopt(*new GTextDocument(editor));
+ }
+
+ int line_count() const { return m_lines.size(); }
+ const GTextDocumentLine& line(int line_index) const { return m_lines[line_index]; }
+ GTextDocumentLine& line(int line_index) { return m_lines[line_index]; }
+
+ void set_spans(const Vector<GTextDocumentSpan>& spans) { m_spans = spans; }
+
+ void set_text(const StringView&);
+
+ const NonnullOwnPtrVector<GTextDocumentLine>& lines() const { return m_lines; }
+ NonnullOwnPtrVector<GTextDocumentLine>& lines() { return m_lines; }
+
+ bool has_spans() const { return !m_spans.is_empty(); }
+ const Vector<GTextDocumentSpan>& spans() const { return m_spans; }
+
+private:
+ explicit GTextDocument(GTextEditor&);
+
+ NonnullOwnPtrVector<GTextDocumentLine> m_lines;
+ Vector<GTextDocumentSpan> m_spans;
+
+ GTextEditor& m_editor;
+};
+
+class GTextDocumentLine {
+ friend class GTextEditor;
+ friend class GTextDocument;
+
+public:
+ explicit GTextDocumentLine(GTextEditor&);
+ GTextDocumentLine(GTextEditor&, const StringView&);
+
+ StringView view() const { return { characters(), length() }; }
+ const char* characters() const { return m_text.data(); }
+ int length() const { return m_text.size() - 1; }
+ void set_text(const StringView&);
+ void append(char);
+ void prepend(char);
+ void insert(int index, char);
+ void remove(int index);
+ void append(const char*, int);
+ void truncate(int length);
+ void clear();
+ void recompute_visual_lines();
+ int visual_line_containing(int column) const;
+ int first_non_whitespace_column() const;
+
+ template<typename Callback>
+ void for_each_visual_line(Callback) const;
+
+private:
+ GTextEditor& m_editor;
+
+ // NOTE: This vector is null terminated.
+ Vector<char> m_text;
+
+ Vector<int, 1> m_visual_line_breaks;
+ Rect m_visual_rect;
+};