1 /*
2  * Xournal++
3  *
4  * Text editor gui (for Text Tool)
5  *
6  * @author Xournal++ Team
7  * https://github.com/xournalpp/xournalpp
8  *
9  * @license GNU GPLv2 or later
10  */
11 
12 #pragma once
13 
14 #include <gtk/gtk.h>
15 
16 #include "gui/Redrawable.h"
17 #include "model/Text.h"
18 #include "undo/TextUndoAction.h"
19 #include "undo/UndoAction.h"
20 
21 class XojPageView;
22 
23 class TextEditor {
24 public:
25     TextEditor(XojPageView* gui, GtkWidget* widget, Text* text, bool ownText);
26     virtual ~TextEditor();
27 
28     /** Represents the different kinds of text selection */
29     enum class SelectType { word, paragraph, all };
30 
31     void paint(cairo_t* cr, GdkRectangle* rect, double zoom);
32 
33     bool onKeyPressEvent(GdkEventKey* event);
34     bool onKeyReleaseEvent(GdkEventKey* event);
35 
36     void toggleOverwrite();
37     void selectAtCursor(TextEditor::SelectType ty);
38     void toggleBold();
39     void incSize();
40     void decSize();
41     void moveCursor(GtkMovementStep step, int count, bool extendSelection);
42     void deleteFromCursor(GtkDeleteType type, int count);
43     void backspace();
44     void copyToCliboard();
45     void cutToClipboard();
46     void pasteFromClipboard();
47     string getSelection();
48 
49     Text* getText();
50     void textCopyed();
51 
52     void mousePressed(double x, double y);
53     void mouseMoved(double x, double y);
54     void mouseReleased();
55 
56     UndoAction* getFirstUndoAction();
57 
58     void setText(const string& text);
59     void setFont(XojFont font);
60     UndoAction* setColor(Color color);
61 
62 private:
63     void repaintEditor();
64     void drawCursor(cairo_t* cr, double x, double y, double height, double zoom);
65     void repaintCursor();
66     void resetImContext();
67 
68     int getByteOffset(int charOffset);
69     int getCharOffset(int byteOffset);
70 
71     static void bufferPasteDoneCallback(GtkTextBuffer* buffer, GtkClipboard* clipboard, TextEditor* te);
72 
73     static void iMCommitCallback(GtkIMContext* context, const gchar* str, TextEditor* te);
74     static void iMPreeditChangedCallback(GtkIMContext* context, TextEditor* te);
75     static bool iMRetrieveSurroundingCallback(GtkIMContext* context, TextEditor* te);
76     static bool imDeleteSurroundingCallback(GtkIMContext* context, gint offset, gint n_chars, TextEditor* te);
77 
78     void moveCursor(const GtkTextIter* newLocation, gboolean extendSelection);
79 
80     static gint blinkCallback(TextEditor* te);
81 
82     void calcVirtualCursor();
83     void jumpALine(GtkTextIter* textIter, int count);
84 
85     void findPos(GtkTextIter* iter, double x, double y);
86     void markPos(double x, double y, bool extendSelection);
87 
88     void contentsChanged(bool forceCreateUndoAction = false);
89 
90 private:
91     XojPageView* gui = nullptr;
92     GtkWidget* widget = nullptr;
93     GtkWidget* textWidget = nullptr;
94     GtkIMContext* imContext = nullptr;
95     GtkTextBuffer* buffer = nullptr;
96     PangoLayout* layout = nullptr;
97     Text* text = nullptr;
98 
99     PangoAttrList* preeditAttrList = nullptr;
100     int preeditCursor;
101     string preeditString;
102     string lastText;
103 
104     std::vector<std::reference_wrapper<TextUndoAction>> undoActions;
105 
106     double virtualCursor = 0;
107     double markPosX = 0;
108     double markPosY = 0;
109 
110     bool cursorBlink = true;
111     int cursorBlinkTime = 0;
112     int cursorBlinkTimeout = 0;
113     int blinkTimeout = 0;  // handler id
114 
115     bool ownText = false;
116     bool markPosExtendSelection = false;
117     bool markPosQueue = false;
118     bool needImReset = false;
119     bool mouseDown = false;
120     bool cursorOverwrite = false;
121     bool cursorVisible = false;
122 };
123