001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.gwt.client.ui.input;
029
030import org.opencms.gwt.client.I_CmsHasInit;
031import org.opencms.gwt.client.ui.I_CmsAutoHider;
032import org.opencms.gwt.client.ui.css.I_CmsInputCss;
033import org.opencms.gwt.client.ui.css.I_CmsInputLayoutBundle;
034import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle;
035import org.opencms.gwt.client.ui.input.form.CmsWidgetFactoryRegistry;
036import org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory;
037import org.opencms.gwt.client.util.CmsDomUtil;
038import org.opencms.gwt.client.util.CmsExtendedValueChangeEvent;
039import org.opencms.util.CmsStringUtil;
040
041import java.util.ArrayList;
042import java.util.List;
043import java.util.Map;
044
045import com.google.common.base.Objects;
046import com.google.common.base.Optional;
047import com.google.gwt.dom.client.Style.Unit;
048import com.google.gwt.event.dom.client.BlurEvent;
049import com.google.gwt.event.dom.client.BlurHandler;
050import com.google.gwt.event.dom.client.ClickEvent;
051import com.google.gwt.event.dom.client.ClickHandler;
052import com.google.gwt.event.dom.client.FocusEvent;
053import com.google.gwt.event.dom.client.FocusHandler;
054import com.google.gwt.event.dom.client.HasBlurHandlers;
055import com.google.gwt.event.dom.client.HasClickHandlers;
056import com.google.gwt.event.dom.client.HasFocusHandlers;
057import com.google.gwt.event.dom.client.HasKeyPressHandlers;
058import com.google.gwt.event.dom.client.KeyCodes;
059import com.google.gwt.event.dom.client.KeyPressEvent;
060import com.google.gwt.event.dom.client.KeyPressHandler;
061import com.google.gwt.event.dom.client.KeyUpEvent;
062import com.google.gwt.event.dom.client.KeyUpHandler;
063import com.google.gwt.event.dom.client.MouseOutEvent;
064import com.google.gwt.event.dom.client.MouseOutHandler;
065import com.google.gwt.event.dom.client.MouseOverEvent;
066import com.google.gwt.event.dom.client.MouseOverHandler;
067import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
068import com.google.gwt.event.logical.shared.ValueChangeEvent;
069import com.google.gwt.event.logical.shared.ValueChangeHandler;
070import com.google.gwt.event.shared.HandlerRegistration;
071import com.google.gwt.user.client.Event;
072import com.google.gwt.user.client.ui.Composite;
073import com.google.gwt.user.client.ui.FlowPanel;
074import com.google.gwt.user.client.ui.TextBox;
075
076/**
077 * Basic text box class for forms.
078 *
079 * @since 8.0.0
080 *
081 */
082public class CmsTextBox extends Composite
083implements I_CmsFormWidget, I_CmsHasInit, HasFocusHandlers, HasBlurHandlers, HasValueChangeHandlers<String>,
084HasKeyPressHandlers, HasClickHandlers, I_CmsHasBlur, I_CmsHasGhostValue {
085
086    /**
087     * Event handler for this text box.<p>
088     */
089    private class TextBoxHandler
090    implements MouseOverHandler, MouseOutHandler, FocusHandler, BlurHandler, ValueChangeHandler<String>, KeyUpHandler {
091
092        /** The current text box value. */
093        private String m_currentValue;
094
095        /** True if the text box is focused. */
096        private boolean m_focus;
097
098        /**
099         * Constructor.<p>
100         *
101         * @param currentValue the current text box value
102         */
103        protected TextBoxHandler(String currentValue) {
104
105            m_currentValue = currentValue;
106            if (m_currentValue == null) {
107                m_currentValue = "";
108            }
109        }
110
111        /**
112         * Gets the value.<p>
113         *
114         * @return the value
115         */
116        public String getValue() {
117
118            return m_currentValue;
119        }
120
121        /**
122         * @see com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event.dom.client.BlurEvent)
123         */
124        public void onBlur(BlurEvent event) {
125
126            m_focus = false;
127            ValueChangeEvent.fire(CmsTextBox.this, m_currentValue); // need this to trigger validation
128            updateGhostStyle();
129        }
130
131        /**
132         * @see com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event.dom.client.FocusEvent)
133         */
134        @SuppressWarnings("synthetic-access")
135        public void onFocus(FocusEvent event) {
136
137            if (CmsStringUtil.isEmpty(m_currentValue) && m_clearOnChangeMode) {
138                m_textbox.setValue("");
139            }
140            m_focus = true;
141            CmsDomUtil.fireFocusEvent(CmsTextBox.this);
142            updateGhostStyle();
143        }
144
145        /**
146         * @see com.google.gwt.event.dom.client.KeyUpHandler#onKeyUp(com.google.gwt.event.dom.client.KeyUpEvent)
147         */
148        public void onKeyUp(KeyUpEvent event) {
149
150            actionChangeTextFieldValue(m_textbox.getValue(), true);
151
152        }
153
154        /**
155         * @see com.google.gwt.event.dom.client.MouseOutHandler#onMouseOut(com.google.gwt.event.dom.client.MouseOutEvent)
156         */
157        public void onMouseOut(MouseOutEvent event) {
158
159            hideError();
160        }
161
162        /**
163         * @see com.google.gwt.event.dom.client.MouseOverHandler#onMouseOver(com.google.gwt.event.dom.client.MouseOverEvent)
164         */
165        public void onMouseOver(MouseOverEvent event) {
166
167            if (!isPreventShowError()) {
168                showError();
169            }
170        }
171
172        /**
173         * @see com.google.gwt.event.logical.shared.ValueChangeHandler#onValueChange(ValueChangeEvent event)
174         */
175        public void onValueChange(ValueChangeEvent<String> event) {
176
177            actionChangeTextFieldValue(event.getValue(), false);
178
179        }
180
181        /**
182         * Sets the current value.<p>
183         *
184         * @param value the current value
185         * @param inhibitValidation true if validation should be inhibited
186         */
187        public void setValue(String value, boolean inhibitValidation) {
188
189            if (value == null) {
190                value = "";
191            }
192            if (!Objects.equal(value, m_currentValue)) {
193                m_currentValue = value;
194                CmsExtendedValueChangeEvent<String> event = new CmsExtendedValueChangeEvent<String>(value);
195                event.setInhibitValidation(inhibitValidation);
196                fireEvent(event);
197            }
198        }
199
200        /**
201         * Updates the ghost style and text box content depending on the real and ghost value.<p>
202         */
203        protected void updateGhostStyle() {
204
205            if (CmsStringUtil.isEmpty(m_currentValue)) {
206                if (CmsStringUtil.isEmpty(m_ghostValue)) {
207                    updateTextBox("");
208                    return;
209                }
210                if (!m_focus) {
211                    setGhostStyleEnabled(true);
212                    updateTextBox(m_ghostValue);
213                } else {
214                    // don't show ghost mode while focused
215                    setGhostStyleEnabled(false);
216                }
217            } else {
218                setGhostStyleEnabled(false);
219                updateTextBox(m_currentValue);
220            }
221
222        }
223
224        /**
225         * This method is called when the value in the text box is changed.<p>
226         *
227         * @param value the new value
228         * @param inhibitValidation true if validation should be inhibited
229         */
230        private void actionChangeTextFieldValue(String value, boolean inhibitValidation) {
231
232            if (m_focus) {
233                setValue(value, inhibitValidation);
234                updateGhostStyle();
235            }
236        }
237
238        /**
239         * Updates the value in the text box.<p>
240         *
241         * @param value the new value
242         */
243        private void updateTextBox(String value) {
244
245            if (!Objects.equal(m_textbox.getValue(), value)) {
246                m_textbox.setValue(value);
247            }
248        }
249    }
250
251    /** The CSS bundle used for this widget. */
252    public static final I_CmsInputCss CSS = I_CmsInputLayoutBundle.INSTANCE.inputCss();
253
254    /** The widget type identifier for this widget. */
255    public static final String WIDGET_TYPE = "string";
256
257    /** Key codes for functional keys. */
258    protected static final int[] NAVIGATION_CODES = {
259        KeyCodes.KEY_ALT,
260        KeyCodes.KEY_CTRL,
261        KeyCodes.KEY_DOWN,
262        KeyCodes.KEY_END,
263        KeyCodes.KEY_ENTER,
264        KeyCodes.KEY_ESCAPE,
265        KeyCodes.KEY_HOME,
266        KeyCodes.KEY_LEFT,
267        KeyCodes.KEY_RIGHT,
268        KeyCodes.KEY_SHIFT,
269        KeyCodes.KEY_TAB,
270        KeyCodes.KEY_UP};
271
272    /** Default pseudo-padding for text boxes. */
273    private static final int DEFAULT_PADDING = 4;
274
275    /** A counter used for giving text box widgets ids. */
276    private static int idCounter;
277
278    /** The ghost value. */
279    protected String m_ghostValue;
280
281    /** The text box used internally by this widget. */
282    protected TextBox m_textbox = new TextBox();
283
284    /** Flag which controls whether validation should be inhibited when value change events are fired as a consequence of key presses. */
285    boolean m_inhibitValidationForKeypresses;
286
287    /** Flag indicating if the text box should be cleared when leaving the ghost mode. */
288    private boolean m_clearOnChangeMode;
289
290    /** A list of the click handler registrations for this text box. */
291    private List<HandlerRegistration> m_clickHandlerRegistrations = new ArrayList<HandlerRegistration>();
292
293    /** A list of the click handlers for this text box. */
294    private List<ClickHandler> m_clickHandlers = new ArrayList<ClickHandler>();
295
296    /** Stores the enable/disable state of the textbox. */
297    private boolean m_enabled;
298
299    /** The error display for this widget. */
300    private CmsErrorWidget m_error = new CmsErrorWidget();
301
302    /** The width of the error message. */
303    private String m_errorMessageWidth;
304
305    /** The text box handler instance. */
306    private TextBoxHandler m_handler;
307
308    /** The container for the textbox container and error widget. */
309    private FlowPanel m_panel = new FlowPanel();
310
311    /** Signals whether the error message will be shown on mouse over. */
312    private boolean m_preventShowError;
313
314    /** The container for the text box. */
315    private CmsPaddedPanel m_textboxContainer = new CmsPaddedPanel(DEFAULT_PADDING);
316
317    /** Flag indicating if the value change event should also be fired after key press events. */
318    private boolean m_triggerChangeOnKeyPress;
319
320    /**
321     * Constructs a new instance of this widget.
322     */
323    public CmsTextBox() {
324
325        this(new TextBox());
326    }
327
328    /**
329     * Creates a new text box based on an underlying GWT text box instance.<p>
330     *
331     * @param textbox the GWT text box instance to wrap
332     */
333    public CmsTextBox(TextBox textbox) {
334
335        m_textbox = textbox;
336        setEnabled(true);
337        m_textbox.setStyleName(CSS.textBox());
338        m_textbox.getElement().setId("CmsTextBox_" + (idCounter++));
339
340        TextBoxHandler handler = new TextBoxHandler("");
341        m_textbox.addMouseOverHandler(handler);
342        m_textbox.addMouseOutHandler(handler);
343        m_textbox.addFocusHandler(handler);
344        m_textbox.addBlurHandler(handler);
345        m_textbox.addValueChangeHandler(handler);
346        //m_textbox.addKeyPressHandler(handler);
347        m_textbox.addKeyUpHandler(handler);
348
349        m_handler = handler;
350
351        m_textboxContainer.setStyleName(CSS.textBoxPanel());
352        m_textboxContainer.addStyleName(I_CmsLayoutBundle.INSTANCE.generalCss().cornerAll());
353        m_textboxContainer.addStyleName(I_CmsLayoutBundle.INSTANCE.generalCss().textMedium());
354        m_panel.add(m_textboxContainer);
355        m_panel.add(m_error);
356        m_textboxContainer.add(m_textbox);
357        m_textboxContainer.setPaddingX(4);
358        sinkEvents(Event.ONPASTE);
359        initWidget(m_panel);
360
361    }
362
363    /**
364     * Initializes this class.<p>
365     */
366    public static void initClass() {
367
368        // registers a factory for creating new instances of this widget
369        CmsWidgetFactoryRegistry.instance().registerFactory(WIDGET_TYPE, new I_CmsFormWidgetFactory() {
370
371            /**
372             * @see org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory#createWidget(java.util.Map, com.google.common.base.Optional)
373             */
374            public I_CmsFormWidget createWidget(Map<String, String> widgetParams, Optional<String> defaultValue) {
375
376                return new CmsTextBox().colorWhite();
377            }
378        });
379    }
380
381    /**
382     * @see com.google.gwt.event.dom.client.HasBlurHandlers#addBlurHandler(com.google.gwt.event.dom.client.BlurHandler)
383     */
384    public HandlerRegistration addBlurHandler(BlurHandler handler) {
385
386        return m_textbox.addBlurHandler(handler);
387    }
388
389    /**
390     * @see com.google.gwt.event.dom.client.HasClickHandlers#addClickHandler(com.google.gwt.event.dom.client.ClickHandler)
391     */
392    public HandlerRegistration addClickHandler(ClickHandler handler) {
393
394        HandlerRegistration registration = addDomHandler(handler, ClickEvent.getType());
395        m_clickHandlerRegistrations.add(registration);
396        m_clickHandlers.add(handler);
397        return registration;
398    }
399
400    /**
401     * @see com.google.gwt.event.dom.client.HasFocusHandlers#addFocusHandler(com.google.gwt.event.dom.client.FocusHandler)
402     */
403    public HandlerRegistration addFocusHandler(FocusHandler handler) {
404
405        return m_textbox.addFocusHandler(handler);
406    }
407
408    /**
409     * @see com.google.gwt.event.dom.client.HasKeyPressHandlers#addKeyPressHandler(com.google.gwt.event.dom.client.KeyPressHandler)
410     */
411    public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
412
413        return addDomHandler(handler, KeyPressEvent.getType());
414    }
415
416    /**
417     * Adds a handler for the keyup event.<p>
418     *
419     * @param handler the handler
420     * @return the handler registration
421     */
422    public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
423
424        return addDomHandler(handler, KeyUpEvent.getType());
425    }
426
427    /**
428     * @see com.google.gwt.event.logical.shared.HasValueChangeHandlers#addValueChangeHandler(com.google.gwt.event.logical.shared.ValueChangeHandler)
429     */
430    public HandlerRegistration addValueChangeHandler(ValueChangeHandler<String> handler) {
431
432        return addHandler(handler, ValueChangeEvent.getType());
433
434    }
435
436    /**
437     * @see org.opencms.gwt.client.ui.input.I_CmsHasBlur#blur()
438     */
439    public void blur() {
440
441        m_textbox.getElement().blur();
442    }
443
444    /**
445     * Sets the background color to white.<p>
446     *
447     * @return this widget
448     */
449    public CmsTextBox colorWhite() {
450
451        getTextBoxContainer().addStyleName(I_CmsInputLayoutBundle.INSTANCE.inputCss().textBoxPanelWhite());
452        return this;
453    }
454
455    /**
456     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getApparentValue()
457     */
458    public String getApparentValue() {
459
460        String result = m_textbox.getValue();
461        if (CmsStringUtil.isEmpty(result)) {
462            result = null;
463        }
464        return result;
465    }
466
467    /**
468     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFieldType()
469     */
470    public FieldType getFieldType() {
471
472        return I_CmsFormWidget.FieldType.STRING;
473    }
474
475    /**
476     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFormValue()
477     */
478    public Object getFormValue() {
479
480        return m_handler.getValue();
481    }
482
483    /**
484     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFormValueAsString()
485     */
486    public String getFormValueAsString() {
487
488        return (String)getFormValue();
489    }
490
491    /**
492     * Returns the HTML id of the internal textbox used by this widget.<p>
493     *
494     * @return the HTML id of the internal textbox used by this widget
495     */
496    public String getId() {
497
498        return m_textbox.getElement().getId();
499    }
500
501    /**
502     * Returns the text in the text box.<p>
503     *
504     * @return the text
505     */
506    public String getText() {
507
508        return m_textbox.getText();
509    }
510
511    /**
512     * Returns the Textbox of this widget.<p>
513     *
514     * @return the CmsTextBox
515     */
516    public TextBox getTextBox() {
517
518        return m_textbox;
519    }
520
521    /**
522     * Returns the Panel of this widget.<p>
523     *
524     * @return the Panel
525     */
526    public CmsPaddedPanel getTextBoxContainer() {
527
528        return m_textboxContainer;
529    }
530
531    /**
532     * Returns <code>true</code> if this textbox has an error set.<p>
533     *
534     * @return <code>true</code> if this textbox has an error set
535     */
536    public boolean hasError() {
537
538        return m_error.hasError();
539    }
540
541    /**
542     * Gets whether this widget is enabled.
543     *
544     * @return <code>true</code> if the widget is enabled
545     */
546    public boolean isEnabled() {
547
548        return m_enabled;
549    }
550
551    /**
552     * Returns the preventShowError.<p>
553     *
554     * @return the preventShowError
555     */
556    public boolean isPreventShowError() {
557
558        return m_preventShowError;
559    }
560
561    /**
562     * Returns the read only flag.<p>
563     *
564     * @return <code>true</code> if this text box is only readable
565     */
566    public boolean isReadOnly() {
567
568        return m_textbox.isReadOnly();
569    }
570
571    /**
572     * Returns if the text box is set to trigger the value changed event on key press and not on blur only.<p>
573     *
574     * @return <code>true</code> if the text box is set to trigger the value changed event on key press
575     */
576    public boolean isTriggerChangeOnKeyPress() {
577
578        return m_triggerChangeOnKeyPress;
579    }
580
581    /**
582     * @see com.google.gwt.user.client.ui.Composite#onBrowserEvent(com.google.gwt.user.client.Event)
583     */
584    @Override
585    public void onBrowserEvent(Event event) {
586
587        super.onBrowserEvent(event);
588        /*
589         * In IE8, the change event is not fired if we switch to another application window after having
590         * pasted some text into the text box, so we need to turn off ghost mode manually
591         */
592        if (event.getTypeInt() == Event.ONPASTE) {
593            setGhostMode(false);
594        }
595    }
596
597    /**
598     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#reset()
599     */
600    public void reset() {
601
602        m_textbox.setText("");
603    }
604
605    /**
606     * Selects text in the text box.<p>
607     */
608    public void selectAll() {
609
610        m_textbox.selectAll();
611    }
612
613    /**
614     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setAutoHideParent(org.opencms.gwt.client.ui.I_CmsAutoHider)
615     */
616    public void setAutoHideParent(I_CmsAutoHider autoHideParent) {
617
618        // nothing to do
619    }
620
621    /**
622     * Sets the changed style on the text box.<p>
623     */
624    public void setChangedStyle() {
625
626        m_textbox.addStyleName(CSS.changed());
627    }
628
629    /**
630     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setEnabled(boolean)
631     */
632    public void setEnabled(boolean enabled) {
633
634        if (!m_enabled && enabled) {
635            // if the state changed to enable then add the stored handlers
636            // copy the stored handlers into a new list to avoid concurred access to the list
637            List<ClickHandler> handlers = new ArrayList<ClickHandler>(m_clickHandlers);
638            m_clickHandlers.clear();
639            for (ClickHandler handler : handlers) {
640                addClickHandler(handler);
641            }
642            m_textboxContainer.removeStyleName(CSS.textBoxPanelDisabled());
643            m_enabled = true;
644        } else if (m_enabled && !enabled) {
645            // if state changed to disable then remove all click handlers
646            for (HandlerRegistration registration : m_clickHandlerRegistrations) {
647                registration.removeHandler();
648            }
649            m_clickHandlerRegistrations.clear();
650            m_textboxContainer.addStyleName(CSS.textBoxPanelDisabled());
651            setErrorMessage(null);
652            m_enabled = false;
653        }
654        m_textbox.setEnabled(m_enabled);
655    }
656
657    /**
658     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setErrorMessage(java.lang.String)
659     */
660    public void setErrorMessage(String errorMessage) {
661
662        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(errorMessage)) {
663            if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_errorMessageWidth)) {
664                m_error.setWidth(m_errorMessageWidth);
665            } else {
666                int width = getOffsetWidth() - 8;
667                width = width > 0 ? width : 100;
668                m_error.setWidth(width + Unit.PX.toString());
669            }
670            m_textboxContainer.removeStyleName(CSS.textBoxPanel());
671            m_textboxContainer.addStyleName(CSS.textBoxPanelError());
672        } else {
673            m_textboxContainer.removeStyleName(CSS.textBoxPanelError());
674            m_textboxContainer.addStyleName(CSS.textBoxPanel());
675        }
676        m_error.setText(errorMessage);
677    }
678
679    /**
680     * Sets the width of the error message for this textbox.<p>
681     *
682     * @param width the object's new width, in CSS units (e.g. "10px", "1em")
683     */
684    public void setErrorMessageWidth(String width) {
685
686        m_errorMessageWidth = width;
687    }
688
689    /**
690     * Sets the focus on the text box.<p>
691     *
692     * @param focused signals if the focus should be set
693     */
694    public void setFocus(boolean focused) {
695
696        m_textbox.setFocus(focused);
697    }
698
699    /**
700     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setFormValueAsString(java.lang.String)
701     */
702    public void setFormValueAsString(String newValue) {
703
704        m_handler.setValue(newValue, false);
705        m_handler.updateGhostStyle();
706    }
707
708    /**
709     * Enables or disables ghost mode.<p>
710     *
711     * @param ghostMode if true, enables ghost mode, else disables it
712     */
713    public void setGhostMode(boolean ghostMode) {
714        // do nothing
715    }
716
717    /**
718     * Sets if the input field should be cleared when leaving the ghost mode.<p>
719     *
720     * @param clearOnChangeMode <code>true</code> to clear on leaving the ghost mode
721     */
722    public void setGhostModeClear(boolean clearOnChangeMode) {
723
724        m_clearOnChangeMode = clearOnChangeMode;
725    }
726
727    /**
728     * Enables or disables the "ghost mode" style.<p>
729     *
730     * This *only* changes the style, not the actual mode.
731     *
732     * @param enabled <code>true</code> if the ghost mode style should be enabled, false if it should be disabled
733     */
734    public void setGhostStyleEnabled(boolean enabled) {
735
736        if (enabled) {
737            m_textbox.addStyleName(CSS.textboxGhostMode());
738        } else {
739            m_textbox.removeStyleName(CSS.textboxGhostMode());
740        }
741    }
742
743    /**
744     * @see org.opencms.gwt.client.ui.input.I_CmsHasGhostValue#setGhostValue(java.lang.String, boolean)
745     */
746    public void setGhostValue(String value, boolean ghostMode) {
747
748        m_ghostValue = value;
749        m_handler.updateGhostStyle();
750    }
751
752    /**
753     * Sets the 'inhibitValidationForKeypresses' flag.<p>
754     *
755     * @param inhibitValidationForKeypresses the new flag value
756     */
757    public void setInhibitValidationForKeypresses(boolean inhibitValidationForKeypresses) {
758
759        m_inhibitValidationForKeypresses = inhibitValidationForKeypresses;
760    }
761
762    /**
763     * Sets the name of the input box.
764     *
765     * @param name of the input box
766     * */
767    public void setName(String name) {
768
769        m_textbox.setName(name);
770    }
771
772    /**
773     * Sets the preventShowError.<p>
774     *
775     * @param preventShowError the preventShowError to set
776     */
777    public void setPreventShowError(boolean preventShowError) {
778
779        m_preventShowError = preventShowError;
780        if (preventShowError) {
781            m_error.setErrorVisible(false);
782        }
783    }
784
785    /**
786     * Enables or disables read-only mode.<p>
787     *
788     * @param readOnly if true, enables read-only mode, else disables it
789     */
790    public void setReadOnly(boolean readOnly) {
791
792        m_textbox.setReadOnly(readOnly);
793        if (readOnly) {
794            addStyleName(CSS.textBoxReadOnly());
795        } else {
796            removeStyleName(CSS.textBoxReadOnly());
797        }
798    }
799
800    /**
801     * Sets if the value changed event should be triggered on key press and not on blur only.<p>
802     *
803     * @param triggerOnKeyPress <code>true</code> if the value changed event should be triggered on key press
804     */
805    public void setTriggerChangeOnKeyPress(boolean triggerOnKeyPress) {
806
807        m_triggerChangeOnKeyPress = triggerOnKeyPress;
808    }
809
810    /**
811     * Updates the layout of the text box.<p>
812     */
813    public void updateLayout() {
814
815        m_textboxContainer.updatePadding();
816
817    }
818
819    /**
820     * Fires a value change event.<p>
821     */
822    protected void fireValueChangedEvent() {
823
824        fireValueChangedEvent(false);
825    }
826
827    /**
828     * Helper method for firing a 'value changed' event.<p>
829     *
830     * @param inhibitValidation if true, some additional information will be added to the event to ask event handlers to not perform any validation directly
831     */
832    protected void fireValueChangedEvent(boolean inhibitValidation) {
833
834        if (!inhibitValidation) {
835            ValueChangeEvent.fire(this, getFormValueAsString());
836        } else {
837            CmsExtendedValueChangeEvent<String> e = new CmsExtendedValueChangeEvent<String>(getFormValueAsString());
838            e.setInhibitValidation(true);
839            fireEvent(e);
840        }
841    }
842
843    /**
844     * Hides the error for this textbox.<p>
845     */
846    protected void hideError() {
847
848        m_error.hideError();
849    }
850
851    /**
852     * Checks if the given key code represents a functional key.<p>
853     *
854     * @param keyCode the key code to check
855     *
856     * @return <code>true</code> if the given key code represents a functional key
857     */
858    protected boolean isNavigationKey(int keyCode) {
859
860        for (int i = 0; i < NAVIGATION_CODES.length; i++) {
861            if (NAVIGATION_CODES[i] == keyCode) {
862                return true;
863            }
864        }
865        return false;
866    }
867
868    /**
869     * Shows the error for this textbox.<p>
870     */
871    protected void showError() {
872
873        m_error.showError();
874    }
875
876}