Coverage Report

Created: 2025-10-10 06:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wt/src/Wt/WLineEdit.h
Line
Count
Source
1
// This may look like C code, but it's really -*- C++ -*-
2
/*
3
 * Copyright (C) 2008 Emweb bv, Herent, Belgium.
4
 *
5
 * See the LICENSE file for terms of use.
6
 */
7
#ifndef WLINEEDIT_H_
8
#define WLINEEDIT_H_
9
10
#include <Wt/WFormWidget.h>
11
12
namespace Wt {
13
14
/*! \brief Enumeration that describes how the contents is displayed.
15
 *
16
 * \sa setEchoMode(EchoMode)
17
 */
18
enum class EchoMode {
19
  Normal,   //!< Characters are shown.
20
  Password  //!< Hide the contents as for a password.
21
};
22
23
/*! \brief Enumeration that describes options for input masks.
24
 *
25
 * \sa setInputMask()
26
 */
27
enum class InputMaskFlag {
28
  KeepMaskWhileBlurred = 0x1 //!< Keep the input mask when blurred
29
};
30
31
/*! \brief Enumeration that describes different autocomplete modes.
32
 *
33
 * The autocomplete mode tells the browser what type of information is
34
 * required by the field. This helps the browser to complete the field
35
 * for the user.
36
 *
37
 * \sa setAutoComplete(AutoCompleteMode)
38
 */
39
enum class AutoCompleteMode {
40
  Off, //!< Forbid the browser to automatically enter or select values. \note In most modern browsers, this will not stop password manager to do it.
41
  On, //!< The browser will "guess" what type of data is required.
42
  NewPassword, //!< A new password. This should be used with field for entering a new password or confirming the new password.
43
  CurrentPassword, //!< The current password of the user.
44
  Username //!< An accout name or username.
45
};
46
47
/*! \brief Enumeration that describes different input modes.
48
 *
49
 * The input mode tells the browser what layout should be used for a
50
 * virtual keybord when editing this field. This mainly impacts phone
51
 * users.
52
 *
53
 * \sa setInputMode(InputMode)
54
 */
55
enum class InputMode {
56
  Off, //!< Does not specify any input mode to the browser
57
  None, //!< No virtual keyboard should be displayed.
58
  Text, //!< The locale-specific standard virtual keyboard.
59
  Tel, //!< A numeric virtual keyboard wich also have "#"" and "*".
60
  Url, //!< Ensure that the virtual keyboard has "/"
61
  Email, //!< Ensure that the virtual keyboard has "@"
62
  Numeric, //!< Ensure that the virtual keyboard has the digit from 0 to 9. Does usually show only the numbers with maybe also "-" .
63
  Decimal, //!< Like Numeric + ensure that the virtual keyboard has the decimal separator.
64
  Search //!< A virtual keyboard convenient for search
65
};
66
67
/*! \class WLineEdit Wt/WLineEdit.h Wt/WLineEdit.h
68
 *  \brief A widget that provides a single line edit.
69
 *
70
 * To act upon text changes, connect a slot to the changed()
71
 * signal. This signal is emitted when the user changed the content,
72
 * and subsequently removes the focus from the line edit.
73
 *
74
 * To act upon editing, connect a slot to the keyWentUp() signal because the
75
 * keyPressed() signal is fired before the line edit has interpreted the
76
 * keypress to change its text.
77
 *
78
 * At all times, the current content may be accessed with the text()
79
 * method.
80
 *
81
 * You may specify a maximum length for the input using
82
 * setMaxLength(). If you wish to provide more detailed input
83
 * validation, you may set a validator using the
84
 * setValidator(const std::shared_ptr<WValidator> &) method. Validators provide, in general,
85
 * both client-side validation (as visual feed-back only) and
86
 * server-side validation when calling validate().
87
 *
88
 * \if cpp
89
 * Usage example:
90
 * \code
91
 * auto w = std::make_unique<Wt::WContainerWidget>();
92
 * Wt::WLabel *label = w->addWidget(std::make_unique<Wt::WLabel>("Age:"));
93
 * Wt::WLineEdit *edit = w->addWidget(std::make_unique<Wt::WLineEdit>("13"));
94
 * edit->setValidator(std::make_shared<Wt::WIntValidator>(0, 200));
95
 * label->setBuddy(edit);
96
 * \endcode
97
 * \endif
98
 *
99
 * The widget corresponds to the HTML <tt>&lt;input type="text"&gt;</tt> or
100
 * <tt>&lt;input type="password"&gt;</tt> tag.
101
 *
102
 * %WLineEdit is an \link WWidget::setInline(bool) inline \endlink widget.
103
 *
104
 * <h3>CSS</h3>
105
 *
106
 * The emptyText style can be configured via .Wt-edit-emptyText,
107
 * other styling can be done using inline or external CSS as appropriate.
108
 *
109
 * \sa WTextArea
110
 */
111
class WT_API WLineEdit : public WFormWidget
112
{
113
public:
114
  /*! \brief Creates a line edit with empty content.
115
   */
116
  WLineEdit();
117
118
  /*! \brief Creates a line edit with given content.
119
   */
120
  WLineEdit(const WT_USTRING& content);
121
122
  /*! \brief Specifies the width of the line edit in number of characters.
123
   *
124
   * This specifies the width of the line edit that is roughly
125
   * equivalent with \p chars characters. This does not limit the
126
   * maximum length of a string that may be entered, which may be set
127
   * using setMaxLength(int).
128
   *
129
   * The default value is 10.
130
   */
131
  void setTextSize(int chars);
132
133
  /*! \brief Returns the current width of the line edit in number of characters.
134
   *
135
   * \sa setTextSize(int)
136
   */
137
0
  int textSize() const { return textSize_; }
138
139
  /*! \brief Sets the content of the line edit.
140
   *
141
   * The default value is "".
142
   *
143
   * \sa text()
144
   */
145
  virtual void setText(const WT_USTRING& text);
146
147
  /*! \brief Returns the current content.
148
   *
149
   * \sa setText()
150
   */
151
0
  const WT_USTRING& text() const { return content_; }
152
153
  /*! \brief Returns the displayed text.
154
   *
155
   * If echoMode() is set to Normal, and no input mask is defined, this returns the same as
156
   * text().
157
   *
158
   * If an input mask is defined, then the text is returned including space characters.
159
   *
160
   * If echoMode() is set to Password, then a string of asterisks is returned equal to the length
161
   * of the text.
162
   *
163
   * \sa setText()
164
   */
165
  WT_USTRING displayText() const;
166
167
  /*! \brief Specifies the maximum length of text that can be entered.
168
   *
169
   * A value <= 0 indicates that there is no limit.
170
   *
171
   * The default value is -1.
172
   */
173
  virtual void setMaxLength(int length);
174
175
  /*! \brief Returns the maximum length of text that can be entered.
176
   *
177
   * \sa setMaxLength(int)
178
   */
179
0
  int maxLength() const { return maxLength_; }
180
181
  /*! \brief Sets the echo mode.
182
   *
183
   * The default echo mode is Normal.
184
   *
185
   * \deprecated For EchoMode::Password, use WPasswordEdit instead.
186
   */
187
  WT_DEPRECATED("For EchoMode::Password, use WPasswordEdit instead.")
188
  void setEchoMode(EchoMode echoMode);
189
190
  /*! \brief Returns the echo mode.
191
   *
192
   * \deprecated For EchoMode::Password, use WPasswordEdit instead.
193
   *
194
   * \sa setEchoMode(EchoMode)
195
   */
196
  WT_DEPRECATED("For EchoMode::Password, use WPasswordEdit instead.")
197
0
  EchoMode echoMode() const { return echoMode_; }
198
199
  /*! \brief Sets (built-in browser) autocomplete support.
200
   *
201
   * Depending on the user agent, this may assist the user in filling in
202
   * text for common input fields (e.g. address information) based on
203
   * some heuristics.
204
   *
205
   * The default value is \c true.
206
   */
207
  void setAutoComplete(bool enabled);
208
209
  /*! \brief Sets (built-in browser) autocomplete support.
210
   *
211
   * Depending on the user agent, this may assist the user in filling in
212
   * text for common input fields (e.g. address information) based on
213
   * some heuristics.
214
   *
215
   * The default value is AutoCompleteMode::On.
216
   */
217
  void setAutoComplete(AutoCompleteMode token);
218
219
  /*! \brief Returns if auto-completion support is not off.
220
   *
221
   * \sa setAutoComplete()
222
   */
223
0
  bool autoComplete() const { return autoComplete_ != AutoCompleteMode::Off; }
224
225
  /*! \brief Returns auto-completion support.
226
   *
227
   * \sa setAutoComplete()
228
   */
229
0
  AutoCompleteMode autoCompleteToken() const { return autoComplete_; }
230
231
  /*! \brief Sets (built-in browser) input mode support.
232
   *
233
   * The input mode suggest what type of virtual keyboard should
234
   * be used when applicable (mainly for phone users).
235
   *
236
   * When InputMode::Off is used, the inputmode field is not specified.
237
   * Not to be confused with InputMode::None, which suggest the browser to
238
   * not use any virtual keybord.
239
   *
240
   * The default value is InputMode::Off.
241
   */
242
  void setInputMode(InputMode mode);
243
244
  /*! \brief Returns inputMode support.
245
   *
246
   * \sa setInputMode()
247
   */
248
0
  InputMode inputMode() const { return inputMode_; }
249
250
  /*! \brief Returns the current selection start.
251
   *
252
   * Returns -1 if there is no selected text.
253
   *
254
   * \sa hasSelectedText(), selectedText()
255
   */
256
  int selectionStart() const;
257
258
  /*! \brief Returns the currently selected text.
259
   *
260
   * Returns an empty string if there is currently no selected text.
261
   *
262
   * \sa hasSelectedText()
263
   */
264
  WT_USTRING selectedText() const;
265
266
  /*! \brief Returns whether there is selected text.
267
   *
268
   * \sa selectedtext()
269
   */
270
  bool hasSelectedText() const;
271
272
  /*! \brief Selects length characters starting from the start position
273
   *
274
   * \sa selectedtext()
275
   */
276
  void setSelection(int start, int length);
277
278
  /*! \brief Returns the current cursor position.
279
   *
280
   * Returns -1 if the widget does not have the focus.
281
   */
282
  int cursorPosition() const;
283
284
  /*! \brief Returns the current value.
285
   *
286
   * Returns text().
287
   */
288
  virtual WT_USTRING valueText() const override;
289
290
  /*! \brief Sets the current value.
291
   *
292
   * Calls setText().
293
   */
294
  virtual void setValueText(const WT_USTRING& value) override;
295
296
  /*! \brief Returns the input mask.
297
   *
298
   * \sa setInputMask()
299
   */
300
  WT_USTRING inputMask() const;
301
302
  /*! \brief Sets the input mask.
303
   *
304
   * If no input mask is supplied, or the given input mask
305
   * is empty, no input mask is applied.
306
   *
307
   * The following characters can be used in the input mask:
308
   * <table>
309
   *  <tr><th>Character</th>  <th>Description</th></tr>
310
   *  <tr><td>A</td>
311
   *      <td>ASCII alphabetic character: A-Z, a-z (required)</td></tr>
312
   *  <tr><td>a</td>
313
   *      <td>ASCII alphabetic character: A-Z, a-z (optional)</td></tr>
314
   *  <tr><td>N</td>
315
   *      <td>ASCII alphanumeric character: A-Z, a-z, 0-9 (required)</td></tr>
316
   *  <tr><td>n</td>
317
   *      <td>ASCII alphanumeric character: A-Z, a-z, 0-9 (optional)</td></tr>
318
   *  <tr><td>X</td><td>Any character (required)</td></tr>
319
   *  <tr><td>x</td><td>Any character (optional)</td></tr>
320
   *  <tr><td>9</td><td>Digit: 0-9 (required)</td></tr>
321
   *  <tr><td>0</td><td>Digit: 0-9 (optional)</td></tr>
322
   *  <tr><td>D</td><td>Nonzero digit: 1-9 (required)</td></tr>
323
   *  <tr><td>d</td><td>Nonzero digit: 1-9 (optional)</td></tr>
324
   *  <tr><td>#</td><td>Digit or sign: 0-9, -, + (required)</td></tr>
325
   *  <tr><td>H</td>
326
   *      <td>Hexadecimal character: A-F, a-f, 0-9 (required)</td></tr>
327
   *  <tr><td>h</td>
328
   *      <td>Hexadecimal character: A-F, a-f, 0-9 (optional)</td></tr>
329
   *  <tr><td>B</td><td>Binary digit: 0-1 (required)</td></tr>
330
   *  <tr><td>b</td><td>Binary digit: 0-1 (optional)</td></tr>
331
   * </table>
332
   * The distinction between required and optional characters won't be
333
   * apparent on the client side, but will affect the result of validate().
334
   *
335
   * There are also a few special characters, that won't be checked against,
336
   * but modify the value in some way:
337
   * <table>
338
   *  <tr><th>Character</th><th>Description</th></tr>
339
   *  <tr><td>&gt;</td><td>The following characters are uppercased</td></tr>
340
   *  <tr><td>&lt;</td><td>The following characters are lowercased</td></tr>
341
   *  <tr><td>!</td>
342
   *      <td>The casing of the following characters remains the same</td></tr>
343
   * </table>
344
   * A backslash ('\\') can be used to escape any of the mask characters
345
   * or modifiers, so that they can be used verbatim in the input mask.
346
   *
347
   * If the mask ends with a semicolon (';') followed by a character,
348
   * this character will be used on the client side to display spaces.
349
   * This defaults to the space (' ') character. The space character will be
350
   * removed from the value of this %WLineEdit.
351
   *
352
   * Examples:
353
   * <table>
354
   *  <tr><th>Input mask</th><th>Notes</th></tr>
355
   *  <tr><td><pre>009.009.009.009;_</pre></td>
356
   *      <td>IP address. Spaces are denoted by '_'. Will validate if there
357
   *          is at least one digit per segment.</td></tr>
358
   *  <tr><td><pre>9999-99-99</pre></td>
359
   *      <td>Date, in yyyy-MM-dd notation. Spaces are denoted by ' '.
360
   *          Will validate if all digits are filled in.</td></tr>
361
   *  <tr><td><pre>>HH:HH:HH:HH:HH:HH;_</pre></td>
362
   *      <td>MAC address. Spaces are denoted by '_'. Will validate if all
363
   *          hexadecimal characters are filled in. All characters will be
364
   *          formatted in uppercase.</td></tr>
365
   * </table>
366
   *
367
   * Input masks are enforced by JavaScript on the client side.
368
   * Without JavaScript or using setText(), however, non-compliant
369
   * strings can be entered. This does not result in an error: any
370
   * non-compliant characters will be removed from the input and this
371
   * action will be logged.
372
   */
373
  void setInputMask(const WT_USTRING &mask = "",
374
                    WFlags<InputMaskFlag> flags = None);
375
376
  virtual ValidationState validate() override;
377
378
  /*! \brief Event signal emitted when the text in the input field changed.
379
   *
380
   * This signal is emitted whenever the text contents has
381
   * changed. Unlike the changed() signal, the signal is fired on
382
   * every change, not only when the focus is lost. Unlike the
383
   * keyPressed() signal, this signal is fired also for other events
384
   * that change the text, such as paste actions.
385
   *
386
   * \sa keyPressed(), changed()
387
   */
388
  EventSignal<>& textInput();
389
390
private:
391
  static const char *INPUT_SIGNAL;
392
393
  WT_USTRING        content_;
394
  WT_USTRING        displayContent_;
395
  int               textSize_;
396
  int               maxLength_;
397
  EchoMode          echoMode_;
398
  AutoCompleteMode autoComplete_;
399
  InputMode         inputMode_;
400
401
  static const int BIT_CONTENT_CHANGED        = 0;
402
  static const int BIT_TEXT_SIZE_CHANGED      = 1;
403
  static const int BIT_MAX_LENGTH_CHANGED     = 2;
404
  static const int BIT_ECHO_MODE_CHANGED      = 3;
405
  static const int BIT_AUTOCOMPLETE_CHANGED   = 4;
406
  static const int BIT_INPUT_MODE_CHANGED     = 5;
407
408
  std::bitset<6> flags_;
409
410
  static const std::string SKIPPABLE_MASK_CHARS;
411
412
  bool maskChanged_;
413
  std::string  mask_;
414
#if !defined(WT_TARGET_JAVA)
415
  std::u32string inputMask_;
416
  std::u32string raw_;
417
  char32_t spaceChar_;
418
#else
419
  std::string inputMask_;
420
  std::string raw_;
421
  char spaceChar_;
422
#endif
423
  WFlags<InputMaskFlag> inputMaskFlags_;
424
  std::string  case_;
425
  bool javaScriptDefined_;
426
427
  WT_USTRING removeSpaces(const WT_USTRING& text) const;
428
  WT_USTRING inputText(const WT_USTRING& text) const;
429
  void processInputMask();
430
#if !defined(WT_TARGET_JAVA)
431
  bool acceptChar(char32_t chr, size_t position) const;
432
#else
433
  bool acceptChar(char chr, size_t position) const;
434
#endif
435
  void defineJavaScript();
436
  void connectJavaScript(Wt::EventSignalBase&s, const std::string& methodName);
437
  bool validateInputMask() const;
438
439
protected:
440
  virtual void           updateDom(DomElement& element, bool all) override;
441
  virtual DomElementType domElementType() const override;
442
  virtual void           propagateRenderOk(bool deep) override;
443
  virtual void           getDomChanges(std::vector<DomElement *>& result,
444
                                       WApplication *app) override;
445
  virtual void setFormData(const FormData& formData) override;
446
447
  virtual int boxPadding(Orientation orientation) const override;
448
  virtual int boxBorder(Orientation orientation) const override;
449
450
  virtual void render(WFlags<RenderFlag> flags) override;
451
  /*! \internal
452
   * \brief Returns the value of the type attribute for the <input> element
453
   *
454
   * For WLineEdit this is normally "text" or "password", but this can be overridden by
455
   * derived classes, e.g. for a native WTimeEdit this would be "time".
456
   */
457
  WT_NODISCARD virtual std::string type() const noexcept;
458
};
459
460
}
461
462
#endif // WLINEEDIT_H_