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 WFORM_WIDGET_H_
8 #define WFORM_WIDGET_H_
9 
10 #include <Wt/WInteractWidget.h>
11 #include <Wt/WValidator.h>
12 
13 namespace Wt {
14 
15 class WLabel;
16 
17 /*! \class WFormWidget Wt/WFormWidget.h Wt/WFormWidget.h
18  *  \brief An abstract widget that corresponds to an HTML form element.
19  *
20  * A %WFormWidget may receive focus (see canReceiveFocus()), can be
21  * disabled, and can have a label that acts as proxy for getting
22  * focus. It provides signals which reflect changes to its value, or
23  * changes to its focus.
24  *
25  * Form widgets also have built-in support for validation, using
26  * setValidator(const std::shared_ptr<WValidator> &). If the validator provide client-side
27  * validation, then an invalid validation state is reflected using the
28  * style class <tt>"Wt-invalid"</tt>. All validators provided by %Wt
29  * implement client-side validation.
30  *
31  * On the server-side, use validate() method to validate the content
32  * using a validator previously set.
33  */
34 class WT_API WFormWidget : public WInteractWidget
35 {
36 public:
37   /*! \brief Creates a %WFormWidget.
38    */
39   WFormWidget();
40 
41   /*! \brief Destructor.
42    */
43   ~WFormWidget();
44 
45   /*! \brief Returns the label associated with this widget.
46    *
47    * Returns the label (if there is one) that acts as a proxy for this
48    * widget.
49    *
50    * \sa WLabel::setBuddy(WFormWidget *)
51    */
label()52   WLabel *label() const { return label_; }
53 
54   /*! \brief Sets the hidden state of this widget.
55    *
56    * If the widget has a label, it is hidden and shown together with
57    * this widget.
58    */
59   virtual void setHidden(bool hidden,
60 			 const WAnimation& animation = WAnimation()) override;
61 
62   /*! \brief Returns the current value.
63    *
64    * This returns the current value as a string.
65    */
66   virtual WT_USTRING valueText() const = 0;
67 
68   /*! \brief Sets the value text.
69    *
70    * This sets the current value from a string value.
71    */
72   virtual void setValueText(const WT_USTRING& value) = 0;
73 
74   /*! \brief Sets a validator for this field.
75    *
76    * The validator is used to validate the current input.
77    *
78    * The default value is \c 0.
79    *
80    * \sa validate()
81    */
82   void setValidator(const std::shared_ptr<WValidator>& validator);
83 
84   /*! \brief Returns the validator.
85    */
validator()86   virtual std::shared_ptr<WValidator> validator() const { return validator_; }
87 
88   /*! \brief Validates the field.
89    *
90    * \sa validated()
91    */
92   virtual ValidationState validate();
93 
94   /*! \brief Sets whether the widget is enabled.
95    *
96    * A widget that is disabled cannot receive focus or user interaction.
97    *
98    * This is the opposite of setDisabled().
99    */
100   void setEnabled(bool enabled);
101 
102   /*! \brief Sets the element read-only.
103    *
104    * A read-only form element cannot be edited, but the contents can
105    * still be selected.
106    *
107    * By default, a form element area is not read-only.
108    *
109    * \sa setEnabled()
110    */
111   virtual void setReadOnly(bool readOnly);
112 
113   /*! \brief Returns whether the form element is read-only.
114    *
115    * \sa setReadOnly()
116    */
117   bool isReadOnly() const;
118 
119   /*! \brief Sets the placeholder text.
120    *
121    * This sets the text that is shown when the field is empty.
122    */
123   virtual void setPlaceholderText(const WString& placeholder);
124 
125   /*! \brief Returns the placeholder text.
126    *
127    * \sa setPlaceholderText()
128    */
placeholderText()129   const WString& placeholderText() const { return emptyText_; }
130 
131   /*! \brief %Signal emitted when the value was changed.
132    *
133    * For a keyboard input, the signal is only emitted when the focus is lost
134    */
135   EventSignal<>& changed();
136 
137   /*! \brief %Signal emitted when the widget is being validated.
138    *
139    * This signal may be useful to react to a changed validation state.
140    *
141    * \sa validate()
142    */
validated()143   Signal<WValidator::Result>& validated() { return validated_; }
144 
145   virtual void refresh() override;
146 
147   virtual void setToolTip(const WString& text,
148 			  TextFormat textFormat = TextFormat::Plain)
149     override;
150 
151   virtual bool canReceiveFocus() const override;
152   virtual int tabIndex() const override;
153 
154 protected:
155   WLabel *label_;
156   std::shared_ptr<WValidator> validator_;
157   std::unique_ptr<JSlot> validateJs_, filterInput_, removeEmptyText_;
158   WString emptyText_;
159 
160   // also used in WAbstractToggleButton
161   static const char *CHANGE_SIGNAL;
162 
163   void applyEmptyText();
164 
165   virtual void enableAjax() override;
166 
167 private:
168   static const int BIT_ENABLED_CHANGED  = 0;
169   static const int BIT_READONLY         = 1;
170   static const int BIT_READONLY_CHANGED = 2;
171   static const int BIT_JS_OBJECT        = 3;
172   static const int BIT_VALIDATION_CHANGED = 4;
173   static const int BIT_PLACEHOLDER_CHANGED = 5;
174 
175   std::bitset<6> flags_;
176   Signal<WValidator::Result> validated_;
177   WString validationToolTip_;
178 
179   void setLabel(WLabel *label);
180 
181   void validatorChanged();
182   void defineJavaScript(bool force = false);
183   void updateEmptyText();
184 
185 protected:
186   virtual void updateDom(DomElement& element, bool all) override;
187   virtual void propagateRenderOk(bool deep) override;
188 
189   virtual void render(WFlags<RenderFlag> flags) override;
190 
191   virtual void propagateSetEnabled(bool enabled) override;
192 
193   virtual std::string formName() const;
194 
195   friend class WLabel;
196   friend class WValidator;
197   friend class WebSession;
198 };
199 
200 }
201 
202 #endif // WFORM_WIDGET_H_
203