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 */
33class 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