<commit_before>/*
 * #%L
 * GwtMaterial
 * %%
 * Copyright (C) 2015 - 2017 GwtMaterialDesign
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
package gwt.material.design.client.ui;

import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Style;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.IsEditor;
import com.google.gwt.editor.ui.client.adapters.ValueBoxEditor;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.AutoDirectionHandler;
import com.google.gwt.i18n.shared.DirectionEstimator;
import com.google.gwt.i18n.shared.HasDirectionEstimator;
import com.google.gwt.uibinder.client.UiChild;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.HasName;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.ValueBoxBase;
import com.google.gwt.user.client.ui.ValueBoxBase.TextAlignment;
import gwt.material.design.client.base.*;
import gwt.material.design.client.base.mixin.*;
import gwt.material.design.client.constants.*;
import gwt.material.design.client.events.DragEndEvent;
import gwt.material.design.client.events.DragEnterEvent;
import gwt.material.design.client.events.DragLeaveEvent;
import gwt.material.design.client.events.DragOverEvent;
import gwt.material.design.client.events.DragStartEvent;
import gwt.material.design.client.events.DropEvent;
import gwt.material.design.client.events.*;
import gwt.material.design.client.ui.html.Label;

import static gwt.material.design.jquery.client.api.JQuery.$;

//@formatter:off

/**
 * MaterialValueBox is an input field that accepts any text based string from user.
 * <h3>UiBinder Usage:</h3>
 * <pre>
 * {@code <m:MaterialTextBox placeholder="<NAME>" />}
 * </pre>
 *
 * @author kevzlou7979
 * @author <NAME>
 * @author paulux84
 * @see <a href="http://gwtmaterialdesign.github.io/gwt-material-demo/#textfields">Material TextBox</a>
 * @see <a href="https://material.io/guidelines/components/text-fields.html#">Material Design Specification</a>
 */
//@formatter:on
public class MaterialValueBox<T> extends AbstractValueWidget<T> implements HasChangeHandlers, HasName,
    HasDirectionEstimator, HasText, AutoDirectionHandler.Target, IsEditor<ValueBoxEditor<T>>, HasIcon,
    HasInputType, HasPlaceholder, HasCounter, HasReadOnly, HasActive, HasFieldTypes, HasAutocomplete,
    HasToggleReadOnlyHandler, HasPasteHandlers {


    private boolean returnBlankAsNull;
    private InputType type = InputType.TEXT;
    private ValueBoxEditor<T> editor;
    private Label label = new Label();
    private MaterialLabel errorLabel = new MaterialLabel();
    private MaterialIcon icon = new MaterialIcon();

    @Editor.Ignore
    protected ValueBoxBase<T> valueBoxBase;

    private CounterMixin<MaterialValueBox<T>> counterMixin;
    private StatusTextMixin<AbstractValueWidget, MaterialLabel> statusTextMixin;
    private ReadOnlyMixin<MaterialValueBox, ValueBoxBase> readOnlyMixin;
    private FocusableMixin<MaterialWidget> focusableMixin;
    private ActiveMixin<MaterialValueBox> activeMixin;
    private FieldTypeMixin<MaterialValueBox> fieldTypeMixin;

    public class MaterialValueBoxEditor<V> extends ValueBoxEditor<V> {
        private final ValueBoxBase<V> valueBoxBase;

        private MaterialValueBoxEditor(ValueBoxBase<V> valueBoxBase) {
            super(valueBoxBase);
            this.valueBoxBase = valueBoxBase;
        }

        @Override
        public void setValue(V value) {
            super.setValue(value);
            if (valueBoxBase.getText() != null && !valueBoxBase.getText().isEmpty()) {
                label.addStyleName(CssName.ACTIVE);
            } else {
                label.removeStyleName(CssName.ACTIVE);
            }
        }
    }

    protected MaterialValueBox() {
        super(Document.get().createDivElement(), CssName.INPUT_FIELD);
    }

    public MaterialValueBox(ValueBoxBase<T> tValueBox) {
        this();
        setup(tValueBox);
    }

    public void setup(ValueBoxBase<T> tValueBox) {
        valueBoxBase = tValueBox;
        add(valueBoxBase);
    }

    @Deprecated
    @UiChild(limit = 1)
    public void addValueBox(ValueBoxBase<T> widget) {
        setup(widget);
    }

    @Override
    protected void onLoad() {
        super.onLoad();

        String id = DOM.createUniqueId();
        valueBoxBase.getElement().setId(id);
        label.getElement().setAttribute("for", id);
        loadEvents();
        // Make valueBoxBase the primary focus target
        getFocusableMixin().setUiObject(new MaterialWidget(valueBoxBase.getElement()));
    }

    @Override
    protected void onUnload() {
        super.onUnload();

        unloadEvents();
    }

    @Override
    public void reset() {
        super.reset();

        clear();
    }

    /**
     * Resets the text box by removing its content and resetting visual state.
     */
    public void clear() {
        valueBoxBase.setText("");
        clearStatusText();

        if (getPlaceholder() == null || getPlaceholder().isEmpty()) {
            label.removeStyleName(CssName.ACTIVE);
        }
    }

    public void loadEvents() {
        $("#" + valueBoxBase.getElement().getId()).on("paste", event -> {
            PasteNativeEvent nativeEvent = (PasteNativeEvent) event;
            if (nativeEvent != null && nativeEvent.originalEvent.clipboardData != null) {
                PasteEvent.fire(this, nativeEvent.originalEvent.clipboardData.getData("text/plain"));
            }
            return true;
        });
    }

    public void unloadEvents() {
        if (valueBoxBase != null) {
            $("#" + valueBoxBase.getElement().getId()).off("paste");
        }
    }

    public void removeErrorModifiers() {
        valueBoxBase.getElement().removeClassName(CssName.VALID);
        valueBoxBase.getElement().removeClassName(CssName.INVALID);
    }

    @Override
    public String getText() {
        return valueBoxBase.getText();<commit_msg>Fixed potential NPE - ValueBoxBase<commit_after>/*
 * #%L
 * GwtMaterial
 * %%
 * Copyright (C) 2015 - 2017 GwtMaterialDesign
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
package gwt.material.design.client.ui;

import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Style;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.IsEditor;
import com.google.gwt.editor.ui.client.adapters.ValueBoxEditor;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.AutoDirectionHandler;
import com.google.gwt.i18n.shared.DirectionEstimator;
import com.google.gwt.i18n.shared.HasDirectionEstimator;
import com.google.gwt.uibinder.client.UiChild;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.HasName;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.ValueBoxBase;
import com.google.gwt.user.client.ui.ValueBoxBase.TextAlignment;
import gwt.material.design.client.base.*;
import gwt.material.design.client.base.mixin.*;
import gwt.material.design.client.constants.*;
import gwt.material.design.client.events.DragEndEvent;
import gwt.material.design.client.events.DragEnterEvent;
import gwt.material.design.client.events.DragLeaveEvent;
import gwt.material.design.client.events.DragOverEvent;
import gwt.material.design.client.events.DragStartEvent;
import gwt.material.design.client.events.DropEvent;
import gwt.material.design.client.events.*;
import gwt.material.design.client.ui.html.Label;

import static gwt.material.design.jquery.client.api.JQuery.$;

//@formatter:off

/**
 * MaterialValueBox is an input field that accepts any text based string from user.
 * <h3>UiBinder Usage:</h3>
 * <pre>
 * {@code <m:MaterialTextBox placeholder="<NAME>" />}
 * </pre>
 *
 * @author kevzlou7979
 * @author <NAME>
 * @author paulux84
 * @see <a href="http://gwtmaterialdesign.github.io/gwt-material-demo/#textfields">Material TextBox</a>
 * @see <a href="https://material.io/guidelines/components/text-fields.html#">Material Design Specification</a>
 */
//@formatter:on
public class MaterialValueBox<T> extends AbstractValueWidget<T> implements HasChangeHandlers, HasName,
    HasDirectionEstimator, HasText, AutoDirectionHandler.Target, IsEditor<ValueBoxEditor<T>>, HasIcon,
    HasInputType, HasPlaceholder, HasCounter, HasReadOnly, HasActive, HasFieldTypes, HasAutocomplete,
    HasToggleReadOnlyHandler, HasPasteHandlers {


    private boolean returnBlankAsNull;
    private InputType type = InputType.TEXT;
    private ValueBoxEditor<T> editor;
    private Label label = new Label();
    private MaterialLabel errorLabel = new MaterialLabel();
    private MaterialIcon icon = new MaterialIcon();

    @Editor.Ignore
    protected ValueBoxBase<T> valueBoxBase;

    private CounterMixin<MaterialValueBox<T>> counterMixin;
    private StatusTextMixin<AbstractValueWidget, MaterialLabel> statusTextMixin;
    private ReadOnlyMixin<MaterialValueBox, ValueBoxBase> readOnlyMixin;
    private FocusableMixin<MaterialWidget> focusableMixin;
    private ActiveMixin<MaterialValueBox> activeMixin;
    private FieldTypeMixin<MaterialValueBox> fieldTypeMixin;

    public class MaterialValueBoxEditor<V> extends ValueBoxEditor<V> {
        private final ValueBoxBase<V> valueBoxBase;

        private MaterialValueBoxEditor(ValueBoxBase<V> valueBoxBase) {
            super(valueBoxBase);
            this.valueBoxBase = valueBoxBase;
        }

        @Override
        public void setValue(V value) {
            super.setValue(value);
            if (valueBoxBase.getText() != null && !valueBoxBase.getText().isEmpty()) {
                label.addStyleName(CssName.ACTIVE);
            } else {
                label.removeStyleName(CssName.ACTIVE);
            }
        }
    }

    protected MaterialValueBox() {
        super(Document.get().createDivElement(), CssName.INPUT_FIELD);
    }

    public MaterialValueBox(ValueBoxBase<T> tValueBox) {
        this();
        setup(tValueBox);
    }

    public void setup(ValueBoxBase<T> tValueBox) {
        valueBoxBase = tValueBox;
        add(valueBoxBase);
    }

    @Deprecated
    @UiChild(limit = 1)
    public void addValueBox(ValueBoxBase<T> widget) {
        setup(widget);
    }

    @Override
    protected void onLoad() {
        super.onLoad();

        String id = DOM.createUniqueId();
        valueBoxBase.getElement().setId(id);
        label.getElement().setAttribute("for", id);
        loadEvents();
        // Make valueBoxBase the primary focus target
        getFocusableMixin().setUiObject(new MaterialWidget(valueBoxBase.getElement()));
    }

    @Override
    protected void onUnload() {
        super.onUnload();

        unloadEvents();
    }

    @Override
    public void reset() {
        super.reset();

        clear();
    }

    /**
     * Resets the text box by removing its content and resetting visual state.
     */
    public void clear() {
        valueBoxBase.setText("");
        clearStatusText();

        if (getPlaceholder() == null || getPlaceholder().isEmpty()) {
            label.removeStyleName(CssName.ACTIVE);
        }
    }

    public void loadEvents() {
        if (valueBoxBase != null && valueBoxBase.isAttached()) {
            $("#" + valueBoxBase.getElement().getId()).on("paste", event -> {
                PasteNativeEvent nativeEvent = (PasteNativeEvent) event;
                if (nativeEvent != null && nativeEvent.originalEvent.clipboardData != null) {
                    PasteEvent.fire(this, nativeEvent.originalEvent.clipboardData.getData("text/plain"));
                }
                return true;
            });
        }
    }

    public void unloadEvents() {
        if (valueBoxBase != null) {
            $("#" + valueBoxBase.getElement().getId()).off("paste");
        }
    }

    public void removeErrorModifiers() {
        valueBoxBase.getElement().removeClassName(CssName.VALID);
        valueBoxBase.getElement().removeClassName(CssName.INVALID);
    }

    @Override
    public String getText() {
        return valueBoxBase.getText();
{'fraction_non_alphanumeric': 0.1143154452207522, 'fraction_numerical': 0.004013676230117437, 'mean_word_length': 3.4013738959764477, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 67, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5566242', 'n_tokens_mistral': 3970, 'n_tokens_neox': 3881, 'n_words': 806}