1/*
2 * LegacyClonk
3 *
4 * Copyright (c) RedWolf Design
5 * Copyright (c) 2001, Sven2
6 * Copyright (c) 2017-2023, The LegacyClonk Team and contributors
7 *
8 * Distributed under the terms of the ISC license; see accompanying file
9 * "COPYING" for details.
10 *
11 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12 * See accompanying file "TRADEMARK" for details.
13 *
14 * To redistribute this file separately, substitute the full license texts
15 * for the above references.
16 */
17
18#pragma once
19
20#include "C4Gui.h"
21
22namespace C4GUI
23{
24// an edit control to type text in
25class Edit : public Control
26{
27public:
28 Edit(const C4Rect &rtBounds, bool fFocusEdit = false);
29 ~Edit();
30
31private:
32 enum CursorOperation { COP_BACK, COP_DELETE, COP_LEFT, COP_RIGHT, COP_HOME, COP_END, };
33
34 bool KeyCursorOp(C4KeyCodeEx key, CursorOperation op);
35 bool KeyEnter();
36 bool KeyCopy() { Copy(); return true; }
37 bool KeyPaste() { Paste(); return true; }
38 bool KeyCut() { Cut(); return true; }
39 bool KeySelectAll() { SelectAll(); return true; }
40
41 class C4KeyBinding *RegisterCursorOp(CursorOperation op, C4KeyCode key, const char *szName, C4CustomKey::Priority eKeyPrio);
42
43 class C4KeyBinding *pKeyCursorBack, *pKeyCursorDel, *pKeyCursorLeft, *pKeyCursorRight, *pKeyCursorHome, *pKeyCursorEnd,
44 *pKeyEnter, *pKeyCopy, *pKeyPaste, *pKeyCut, *pKeySelAll;
45
46protected:
47 // context callbacks
48 ContextMenu *OnContext(C4GUI::Element *pListItem, int32_t iX, int32_t iY);
49 void OnCtxCopy(C4GUI::Element *pThis) { Copy(); }
50 void OnCtxPaste(C4GUI::Element *pThis) { Paste(); }
51 void OnCtxCut(C4GUI::Element *pThis) { Cut(); }
52 void OnCtxClear(C4GUI::Element *pThis) { DeleteSelection(); }
53 void OnCtxSelAll(C4GUI::Element *pThis) { SelectAll(); }
54
55private:
56 void Deselect(); // clear selection range
57
58public:
59 bool InsertText(C4NullableStringView text, bool fUser); // insert text at cursor pos (returns whether all text could be inserted)
60 void ClearText(); // remove all the text
61 void DeleteSelection(); // deletes the selected text. Adjust cursor position if necessary
62 bool SetText(const C4NullableStringView text, bool fUser) { ClearText(); return InsertText(text, fUser); }
63 void SetPasswordMask(char cNewPasswordMask) { cPasswordMask = cNewPasswordMask; } // mask edit box contents using the given character
64
65private:
66 int32_t GetCharPos(int32_t iControlXPos); // get character index of pixel position; always resides within current text length
67 void EnsureBufferSize(int32_t iMinBufferSize); // ensure buffer has desired size
68 void ScrollCursorInView(); // ensure cursor pos is visible in edit control
69 bool DoFinishInput(bool fPasting, bool fPastingMore); // do OnFinishInput callback and process result - returns whether pasting operation should be continued
70
71 bool Copy(); bool Cut(); bool Paste(); // clipboard operations
72
73protected:
74 CStdFont *pFont; // font for edit
75 char *Text; // edit text
76 uint32_t dwBGClr, dwFontClr, dwBorderColor; // drawing colors for edit box
77 int32_t iBufferSize; // size of current buffer
78 int32_t iCursorPos; // cursor position: char, before which the cursor is located
79 int32_t iSelectionStart, iSelectionEnd; // selection range (start may be larger than end)
80 int32_t iMaxTextLength; // maximum number of characters to be input here
81 uint32_t dwLastInputTime; // time of last input (for cursor flashing)
82 int32_t iXScroll; // horizontal scrolling
83 char cPasswordMask; // character to be used for masking the contents. 0 for none.
84
85 bool fLeftBtnDown; // flag whether left mouse button is down or not
86
87 virtual bool CharIn(const char *c) override; // input: character key pressed - should return false for none-character-inputs
88 virtual void MouseInput(CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, uint32_t dwKeyParam) override; // input: mouse movement or buttons
89 virtual void DoDragging(CMouse &rMouse, int32_t iX, int32_t iY, uint32_t dwKeyParam) override; // dragging: allow text selection outside the component
90 virtual bool IsFocusOnClick() override { return true; } // edit fields do get focus on click
91 virtual void OnGetFocus(bool fByMouse) override; // edit control gets focus
92 virtual void OnLooseFocus() override; // edit control looses focus
93
94 virtual void DrawElement(C4FacetEx &cgo) override; // draw edit control
95
96 // called when user presses enter in single-line edit control - closes the current dialog
97 virtual InputResult OnFinishInput(bool fPasting, bool fPastingMore) { return IR_CloseDlg; }
98 virtual void OnAbortInput() {}
99 virtual void OnTextChange() {}
100
101 // get margins from bounds to client rect
102 virtual int32_t GetMarginTop() override { return 2; }
103 virtual int32_t GetMarginLeft() override { return 4; }
104 virtual int32_t GetMarginRight() override { return 4; }
105 virtual int32_t GetMarginBottom() override { return 2; }
106
107public:
108 const char *GetText() { return Text; }
109 void SelectAll(); // select all the text
110
111 static int32_t GetDefaultEditHeight();
112 static int32_t GetCustomEditHeight(CStdFont *pUseFont);
113
114 bool GetCurrentWord(char *szTargetBuf, int32_t iMaxTargetBufLen); // get word before cursor pos (for nick completion)
115
116 // layout
117 void SetFont(CStdFont *pToFont) { pFont = pToFont; ScrollCursorInView(); }
118
119 void SetColors(uint32_t dwNewBGClr, uint32_t dwNewFontClr, uint32_t dwNewBorderColor)
120 {
121 dwBGClr = dwNewBGClr; dwFontClr = dwNewFontClr; dwBorderColor = dwNewBorderColor;
122 }
123
124 void SetMaxText(int32_t iTo) { iMaxTextLength = iTo; }
125};
126
127// an edit doing some callback
128template <class CallbackCtrl> class CallbackEdit : public Edit
129{
130private:
131 CallbackCtrl *pCBCtrl;
132
133protected:
134 typedef InputResult(CallbackCtrl::*CBFunc)(Edit *, bool, bool);
135 typedef void (CallbackCtrl::*CBAbortFunc)();
136 CBFunc pCBFunc; CBAbortFunc pCBAbortFunc;
137
138 virtual InputResult OnFinishInput(bool fPasting, bool fPastingMore) override
139 {
140 if (pCBFunc && pCBCtrl) return (pCBCtrl->*pCBFunc)(this, fPasting, fPastingMore); else return IR_CloseDlg;
141 }
142
143 virtual void OnAbortInput() override
144 {
145 if (pCBAbortFunc && pCBCtrl)(pCBCtrl->*pCBAbortFunc)();
146 }
147
148public:
149 CallbackEdit(const C4Rect &rtBounds, CallbackCtrl *pCBCtrl, CBFunc pCBFunc, CBAbortFunc pCBAbortFunc = nullptr)
150 : Edit(rtBounds), pCBCtrl(pCBCtrl), pCBFunc(pCBFunc), pCBAbortFunc(pCBAbortFunc) {}
151};
152
153// an edit control that renames a label - some less decoration; abort on Escape and focus loss
154class RenameEdit : public Edit
155{
156private:
157 C4KeyBinding *pKeyAbort; // key bindings
158 bool fFinishing; // set during deletion process
159 Label *pForLabel; // label that is being renamed
160 Control *pPrevFocusCtrl; // previous focus element to be restored after rename
161
162public:
163 RenameEdit(Label *pLabel); // construct for label; add element; set focus
164 virtual ~RenameEdit();
165
166 void Abort();
167
168private:
169 void FinishRename(); // renaming aborted or finished - remove this element and restore label
170
171protected:
172 bool KeyAbort() { Abort(); return true; }
173 virtual InputResult OnFinishInput(bool fPasting, bool fPastingMore) override; // forward last input to OnOKRename
174 virtual void OnLooseFocus() override; // callback when control looses focus: OK input
175
176 virtual void OnCancelRename() {} // renaming was aborted
177 virtual RenameResult OnOKRename(const char *szNewName) = 0; // rename performed - return whether name was accepted
178};
179
180template <class CallbackDlg, class ParType> class CallbackRenameEdit : public RenameEdit
181{
182protected:
183 typedef void (CallbackDlg::*CBCancelFunc)(ParType);
184 typedef RenameResult(CallbackDlg::*CBOKFunc)(ParType, const char *);
185
186 CBCancelFunc pCBCancelFunc; CBOKFunc pCBOKFunc;
187 CallbackDlg *pDlg; ParType par;
188
189 virtual void OnCancelRename() override { if (pDlg && pCBCancelFunc)(pDlg->*pCBCancelFunc)(par); }
190 virtual RenameResult OnOKRename(const char *szNewName) override { return (pDlg && pCBOKFunc) ? (pDlg->*pCBOKFunc)(par, szNewName) : RR_Accepted; }
191
192public:
193 CallbackRenameEdit(Label *pForLabel, CallbackDlg *pDlg, const ParType &par, CBOKFunc pCBOKFunc, CBCancelFunc pCBCancelFunc)
194 : RenameEdit(pForLabel), pDlg(pDlg), par(par), pCBOKFunc(pCBOKFunc), pCBCancelFunc(pCBCancelFunc) {}
195};
196
197// editbox below descriptive label sharing one window for common tooltip
198class LabeledEdit : public C4GUI::Window
199{
200public:
201 LabeledEdit(const C4Rect &rcBounds, const char *szName, bool fMultiline, const char *szPrefText = nullptr, CStdFont *pUseFont = nullptr, uint32_t dwTextClr = C4GUI_CaptionFontClr);
202
203private:
204 C4GUI::Edit *pEdit;
205
206public:
207 const char *GetText() const { return pEdit->GetText(); }
208 C4GUI::Edit *GetEdit() const { return pEdit; }
209 static bool GetControlSize(int *piWdt, int *piHgt, const char *szForText, CStdFont *pForFont, bool fMultiline);
210};
211}
212