Line data Source code
1 : /**
2 : Copyright (c) 2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef XENOLITH_SCENE_INPUT_XLTEXTINPUTMANAGER_H_
25 : #define XENOLITH_SCENE_INPUT_XLTEXTINPUTMANAGER_H_
26 :
27 : #include "XLEventHandler.h"
28 : #include "XLInput.h"
29 :
30 : namespace STAPPLER_VERSIONIZED stappler::xenolith {
31 :
32 : class TextInputManager;
33 :
34 : // TextInputHandler used to capture text input
35 : // - Only one handler can be active for one view, new running handler will displace old one
36 : // - Owner is responsible for handler's existence and callback's correctness when handler
37 : // is active (attached to manager)
38 : // - setString/setCursor has no meaning if handler is not active
39 : // - Whole input string from handler will be transferred to device input manager, so, try to
40 : // keep it small (e.g. when working with paragraphs, send only current paragraph). Large
41 : // strings can significantly reduce performance
42 : struct TextInputHandler {
43 : Function<void(WideStringView, TextCursor, TextCursor)> onText;
44 : Function<void(bool, const Rect &, float)> onKeyboard;
45 : Function<void(bool)> onInput;
46 : //Function<bool(const Vec2 &)> onTouchFilter;
47 : Rc<TextInputManager> manager;
48 :
49 : ~TextInputHandler();
50 :
51 : bool run(TextInputManager *, WideStringView str = WideStringView(), TextCursor cursor = TextCursor(), TextCursor marked = TextCursor::InvalidCursor,
52 : TextInputType = TextInputType::Empty);
53 : void cancel();
54 :
55 : // only if this handler is active
56 : bool setString(WideStringView str, TextCursor cursor = TextCursor(), TextCursor marked = TextCursor::InvalidCursor);
57 : bool setCursor(TextCursor);
58 : bool setMarked(TextCursor);
59 :
60 : WideStringView getString() const;
61 : TextCursor getCursor() const;
62 : TextCursor getMarked() const;
63 :
64 : bool isInputEnabled() const;
65 : bool isActive() const;
66 : };
67 :
68 : class TextInputManager : public Ref {
69 : public:
70 : TextInputManager();
71 :
72 : bool init(TextInputViewInterface *);
73 :
74 : void insertText(WideStringView sInsert, bool compose = false);
75 : void insertText(WideStringView sInsert, TextCursor replacement);
76 : void setMarkedText(WideStringView sInsert, TextCursor replacement, TextCursor marked);
77 : void deleteBackward();
78 : void deleteForward();
79 : void unmarkText();
80 :
81 : bool hasText();
82 : void textChanged(WideStringView text, TextCursor, TextCursor);
83 : void cursorChanged(TextCursor);
84 : void markedChanged(TextCursor);
85 :
86 : void setInputEnabled(bool enabled);
87 :
88 : void onTextChanged();
89 :
90 : // run input capture (or update it with new params)
91 : // propagates all data to device input manager, enables screen keyboard if needed
92 : bool run(TextInputHandler *, WideStringView str, TextCursor cursor, TextCursor marked, TextInputType type);
93 :
94 : // update current buffer string (and/or internal cursor)
95 : // propagates string and cursor to device input manager to enable autocorrections, suggestions, etc...
96 : void setString(WideStringView str, TextCursor cursor = TextCursor(), TextCursor marked = TextCursor::InvalidCursor);
97 : void setCursor(TextCursor);
98 : void setMarked(TextCursor);
99 :
100 : WideStringView getStringByRange(TextCursor);
101 : WideStringView getString() const;
102 : TextCursor getCursor() const;
103 : TextCursor getMarked() const;
104 :
105 : // disable text input, disables keyboard connection and keyboard input event interception
106 : // default manager automatically disabled when app goes background
107 : void cancel();
108 :
109 : bool isRunning() const { return _running; }
110 21 : bool isInputEnabled() const { return _isInputEnabled; }
111 :
112 168 : TextInputHandler *getHandler() const { return _handler; }
113 :
114 : bool canHandleInputEvent(const InputEventData &);
115 : bool handleInputEvent(const InputEventData &);
116 :
117 : protected:
118 : bool doInsertText(WideStringView, bool compose);
119 :
120 : TextInputViewInterface *_view = nullptr;
121 : TextInputHandler *_handler = nullptr;
122 : bool _isInputEnabled = false;
123 : bool _running = false;
124 :
125 : TextInputType _type = TextInputType::Empty;
126 : WideString _string;
127 : TextCursor _cursor;
128 : TextCursor _marked;
129 : InputKeyComposeState _compose = InputKeyComposeState::Nothing;
130 : };
131 :
132 : }
133 :
134 : #endif /* XENOLITH_SCENE_INPUT_XLTEXTINPUTMANAGER_H_ */
|