-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTextField.ash
196 lines (174 loc) · 13.2 KB
/
TextField.ash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* TEXT FIELD MODULE - Header *
* by Gunnar Harboe (Snarky), v1.3.0 *
* *
* Copyright (c) 2018, 2019 Gunnar Harboe *
* *
* *
* This module provides a one-line text input field, to replace the built-in AGS *
* TextInput control. Its main benefit is that it allows you to position the text cursor *
* (caret) freely within the input string, using either arrow keys or mouse. It also has *
* a notion of focus, which makes it easier to have GUIs with multiple text fields. *
* Finally, you can customize the appearance and behavior of the text fields somewhat. *
* *
* To use, you have to set up a GUI Button for each text field you want. The position, *
* size, font, and text color of the button will be used to format the text field. Then *
* you have to initialize the text field using TextField.Create(), providing the GUI *
* button as an argument, like so: *
* *
* TextField* myTextField = TextField.Create(myButton); *
* *
* You would typically do this in game_start(), and in any case before the text field is *
* displayed. After you've created the text field, don't set the button properties *
* directly! *
* *
* You also need to hook up the events. Because we lose the TextInput OnActivate event, *
* we have to handle activating the field (typically by pressing Return) a little *
* differently. There are two alternatives: You can handle it yourself in the game's *
* general on_key_press() function: *
* *
* function on_key_press(eKeyCode keycode) *
* { *
* if(keycode == eKeyReturn) *
* { *
* if(TextField.Focused == myTextField) *
* { *
* // Activate *
* } *
* else if(TextField.Focused == myOtherTextField) *
* { *
* // Activate *
* } *
* // ... *
* } *
* else // handle other keys *
* } *
* *
* Or the module can handle it, by setting TextField.HandleReturn = true; but then you *
* have to check textField.Activated() each game cycle to see if it was activated: *
* *
* function repeatedly_execute_always() *
* { *
* if(myTextField.Activated()) *
* { *
* // Activate *
* } *
* } *
* *
* You should also link the button's OnClick() event to a function to handle clicks in *
* the text field. Default behavior (set focus and position the text cursor) is provided, *
* so you can just do: *
* *
* function myButton_OnClick(GUIControl *control, MouseButton button) *
* { *
* myTextField.HandleMouseClick(button); *
* } *
* *
* Or, if you want a common function you can use for all the text fields: *
* *
* function myTextFieldButtons_OnClick(GUIControl *control, MouseButton button) *
* { *
* TextField.HandleMouseClickAny(control, button); *
* } *
* *
* *
* This code is offered under multiple licenses. Choose whichever one you like. *
* *
* You may use it under the MIT license: *
* https://opensource.org/licenses/MIT *
* *
* You may also use it under the Creative Commons Attribution 4.0 International License. *
* https://creativecommons.org/licenses/by/4.0/ *
* *
* You may also use it under the Artistic License 2.0 *
* https://opensource.org/licenses/Artistic-2.0 *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* -- Module housekeeping -- */
#ifndef __TEXTFIELD_MODULE__
#define __TEXTFIELD_MODULE__
#define TEXTFIELD_VERSION "v1.3.0"
#define TEXTFIELD_VERSION_01_03_00
// Comment out next line to disable module
#define ENABLE_TEXTFIELD
#ifdef ENABLE_TEXTFIELD
/* -- The module itself -- */
#define TEXTFIELD_DEFAULT_COUNT 4 // How many text fields are created by default. If you have many, increasing this number may slightly improve startup performance
#define TEXTFIELD_BORDER_WIDTH 1 // How wide the border of the text field is
#define TEXTFIELD_CARET_WIDTH 1 // How wide the text cursor/caret is
#define TEXTFIELD_CARET_OFFSET_X -1 // Used to position the caret correctly between characters (depends on font)
/// A replacement for the built-in TextInput control, allowing users to move the text cursor
managed struct TextField
{
// STATIC METHODS AND PROPERTIES
/// Create a TextField from a button. Only TextFields created by this function are valid
import static TextField* Create(Button* textDisplay, String text=0, int paddingLeft=0, int paddingTop=0); // $AUTOCOMPLETESTATICONLY$
/// Get or set which TextField currently has focus. Null if none.
import static attribute TextField* Focused; // $AUTOCOMPLETESTATICONLY$
/// Get or set the delay between text cursor blinks (default 20 game cycles)
import static attribute int BlinkDelay; // $AUTOCOMPLETESTATICONLY$
/// Get or set whether the TextFields handle the Return key, or pass it along to on_key_press()
import static attribute bool HandlesReturn; // $AUTOCOMPLETESTATICONLY$
/// Passes a mouse click on to the relevant TextField, and performs default behavior (give focus and set cursor position). Returns whether the click was handled.
import static bool HandleMouseClickAny(GUIControl *control, MouseButton button); // $AUTOCOMPLETESTATICONLY$
/// Find the TextField associated with the provided button. Null if none.
import static TextField* FindByDisplayButton(Button* textDisplayButton); // $AUTOCOMPLETESTATICONLY$
/// Find the TextField with the given ID. Null if none.
import static TextField* FindByID(int id); // $AUTOCOMPLETESTATICONLY$
// INSTANCE METHODS AND PROPERTIES
/// Get the ID of this TextField
import readonly attribute int ID;
/// Get the Button that displays this text field
import readonly attribute Button* TextDisplayButton;
/// Get or set the text content of this TextField
import attribute String Text;
/// Get or set the font of this TextField
import attribute FontType Font;
/// Get or set the text color of this TextField (also used for the text cursor and border)
import attribute int TextColor;
/// Get or set the selection color of this TextField
import attribute int SelectionColor;
/// Get or set the max String length of this TextField, 0 for unlimited (content will be truncated to MaxLength)
import attribute int MaxLength;
/// Get or set whether this TextField is currently enabled (can receive focus)
import attribute bool Enabled;
/// Get whether this TextField currently has focus
import readonly attribute bool HasFocus;
/// Get or set the current text cursor position, as a String index.
import attribute int CaretIndex;
/*
/// Get or set the start of the current text selection, as a String index.
import attribute int SelectionStartIndex;
*/
/// Get the index in the text corresponding to the x,y coordinates. (-1 if outside the TextField)
import int TextIndexOfPoint(int x, int y);
/// Set whether this TextField should have focus. Returns whether focus was set.
import bool SetFocus(bool giveFocus=true);
/// Position the text cursor to the x,y coordinates. Returns whether the cursor was positioned.
import bool PositionCaret(int x, int y, bool doSelect=false);
/// Handle a keypress (default behavior: add/delete text input or move text cursor). Returns whether keypress was handled.
import bool HandleKeyPress(eKeyCode keycode);
/// Handle a mouse click (default behavior: give focus and set text cursor position). Returns whether mouse click was handled.
import bool HandleMouseClick(MouseButton button);
/// Whether the control was activated (Return pressed) since the last check. Will only return true once (until activated again).
import bool Activated();
/// The transparency the border is drawn with.
import attribute int BorderTransparency;
// Internal values
protected int _id;
protected int _paddingLeft;
protected int _paddingTop;
protected int _caretIndex;
protected int _caretX;
protected int _caretY;
protected int _selectionColor;
protected int _selectionStartIndex;
protected int _selectionStartX;
protected int _maxLength;
protected bool _enabled;
protected int _borderTransparency;
protected bool _activated;
// Input type as bit field (Numeric, Alphabetic, Alphanumeric, Text)
};
#endif // ENABLE_TEXTFIELD
#endif // __TEXTFIELD_MODULE__