1 | //============================================================================ |
2 | // |
3 | // SSSS tt lll lll |
4 | // SS SS tt ll ll |
5 | // SS tttttt eeee ll ll aaaa |
6 | // SSSS tt ee ee ll ll aa |
7 | // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" |
8 | // SS SS tt ee ll ll aa aa |
9 | // SSSS ttt eeeee llll llll aaaaa |
10 | // |
11 | // Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony |
12 | // and the Stella Team |
13 | // |
14 | // See the file "License.txt" for information on usage and redistribution of |
15 | // this file, and for a DISCLAIMER OF ALL WARRANTIES. |
16 | //============================================================================ |
17 | |
18 | #ifndef EDITABLE_WIDGET_HXX |
19 | #define EDITABLE_WIDGET_HXX |
20 | |
21 | #include <functional> |
22 | |
23 | #include "Widget.hxx" |
24 | #include "Rect.hxx" |
25 | |
26 | /** |
27 | * Base class for widgets which need to edit text, like ListWidget and |
28 | * EditTextWidget. |
29 | * |
30 | * Widgets wishing to enforce their own editing restrictions are able |
31 | * to use a 'TextFilter' as described below. |
32 | */ |
33 | class EditableWidget : public Widget, public CommandSender |
34 | { |
35 | public: |
36 | /** Function used to test if a specified character can be inserted |
37 | into the internal buffer */ |
38 | using TextFilter = std::function<bool(char)>; |
39 | |
40 | enum { |
41 | kAcceptCmd = 'EDac', |
42 | kCancelCmd = 'EDcl', |
43 | kChangedCmd = 'EDch' |
44 | }; |
45 | |
46 | public: |
47 | EditableWidget(GuiObject* boss, const GUI::Font& font, |
48 | int x, int y, int w, int h, const string& str = "" ); |
49 | virtual ~EditableWidget() = default; |
50 | |
51 | virtual void setText(const string& str, bool changed = false); |
52 | const string& getText() const { return _editString; } |
53 | |
54 | bool isEditable() const { return _editable; } |
55 | virtual void setEditable(bool editable, bool hiliteBG = false); |
56 | |
57 | bool handleText(char text) override; |
58 | bool handleKeyDown(StellaKey key, StellaMod mod) override; |
59 | |
60 | // We only want to focus this widget when we can edit its contents |
61 | bool wantsFocus() const override { return _editable; } |
62 | |
63 | // Set filter used to test whether a character can be inserted |
64 | void setTextFilter(const TextFilter& filter) { _filter = filter; } |
65 | |
66 | protected: |
67 | virtual void startEditMode() { setFlags(Widget::FLAG_WANTS_RAWDATA); } |
68 | virtual void endEditMode() { clearFlags(Widget::FLAG_WANTS_RAWDATA); } |
69 | virtual void abortEditMode() { clearFlags(Widget::FLAG_WANTS_RAWDATA); } |
70 | |
71 | virtual Common::Rect getEditRect() const = 0; |
72 | virtual int getCaretOffset() const; |
73 | void drawCaret(); |
74 | bool setCaretPos(int newPos); |
75 | bool adjustOffset(); |
76 | |
77 | // This method is used internally by child classes wanting to |
78 | // access/edit the internal buffer |
79 | string& editString() { return _editString; } |
80 | |
81 | private: |
82 | // Line editing |
83 | bool specialKeys(StellaKey key); |
84 | bool killChar(int direction); |
85 | bool killLine(int direction); |
86 | bool killLastWord(); |
87 | bool moveWord(int direction); |
88 | |
89 | // Clipboard |
90 | void copySelectedText(); |
91 | void pasteSelectedText(); |
92 | |
93 | // Use the current TextFilter to insert a character into the |
94 | // internal buffer |
95 | bool tryInsertChar(char c, int pos); |
96 | |
97 | private: |
98 | bool _editable; |
99 | string _editString; |
100 | |
101 | bool _caretVisible; |
102 | int _caretTime; |
103 | int _caretPos; |
104 | |
105 | protected: |
106 | bool _caretInverse; |
107 | |
108 | int _editScrollOffset; |
109 | |
110 | static string _clippedText; |
111 | |
112 | private: |
113 | TextFilter _filter; |
114 | |
115 | private: |
116 | // Following constructors and assignment operators not supported |
117 | EditableWidget() = delete; |
118 | EditableWidget(const EditableWidget&) = delete; |
119 | EditableWidget(EditableWidget&&) = delete; |
120 | EditableWidget& operator=(const EditableWidget&) = delete; |
121 | EditableWidget& operator=(EditableWidget&&) = delete; |
122 | }; |
123 | |
124 | #endif |
125 | |