001/*
002 * #%L
003 * GwtMaterial
004 * %%
005 * Copyright (C) 2015 - 2017 GwtMaterialDesign
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 * 
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 * 
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package gwt.material.design.client.ui;
021
022import com.google.gwt.core.client.Scheduler;
023import com.google.gwt.dom.client.Element;
024import com.google.gwt.user.client.ui.TextArea;
025import gwt.material.design.client.constants.CssName;
026import gwt.material.design.client.constants.InputType;
027
028import static gwt.material.design.client.js.JsMaterialElement.$;
029
030//@formatter:off
031
032/**
033 * Material Text Area represents a multiple line text box where users can define comment, detail and etc.
034 * <h3>UiBinder Usage:</h3>
035 * <pre>
036 * {@code <m:MaterialTextArea placeholder="Your Comment" /> }
037 * </pre>
038 *
039 * @author kevzlou7979
040 * @author Ben Dol
041 * @author paulux84
042 * @see <a href="http://gwtmaterialdesign.github.io/gwt-material-demo/#textfields">Material TextArea</a>
043 * @see <a href="https://material.io/guidelines/components/text-fields.html#">Material Design Specification</a>
044 */
045//@formatter:on
046public class MaterialTextArea extends MaterialValueBox<String> {
047
048    public enum ResizeRule {
049        NONE, AUTO, FOCUS
050    }
051
052    private ResizeRule resizeRule = ResizeRule.NONE;
053    private Integer originalHeight;
054
055    public MaterialTextArea() {
056        super(new TextArea());
057        setType(InputType.TEXT);
058        valueBoxBase.setStyleName(CssName.MATERIALIZE_TEXTAREA);
059    }
060
061    public MaterialTextArea(String placeholder) {
062        this();
063        setPlaceholder(placeholder);
064    }
065
066    public MaterialTextArea(String placeholder, int length) {
067        this(placeholder);
068        setLength(length);
069    }
070
071    @Override
072    protected void onLoad() {
073        super.onLoad();
074
075        setResizeRule(resizeRule);
076    }
077
078    public void triggerAutoResize() {
079        if (!valueBoxBase.isAttached()) {
080            registerHandler(valueBoxBase.addAttachHandler(event -> {
081                if (event.isAttached()) {
082                    triggerAutoResize(valueBoxBase.getElement());
083                }
084            }));
085        } else {
086            triggerAutoResize(valueBoxBase.getElement());
087        }
088    }
089
090    protected void triggerAutoResize(Element element) {
091        Scheduler.get().scheduleDeferred(() -> $(element).trigger("autoresize", null));
092    }
093
094    @Override
095    public void setText(String text) {
096        super.setText(text);
097
098        if (resizeRule.equals(ResizeRule.AUTO)) {
099            triggerAutoResize();
100        }
101    }
102
103    public void setResizeRule(ResizeRule resizeRule) {
104        this.resizeRule = resizeRule;
105
106        switch (resizeRule) {
107            case AUTO:
108                registerHandler(valueBoxBase.addValueChangeHandler(event -> triggerAutoResize()));
109                break;
110            case FOCUS:
111                registerHandler(addFocusHandler(event -> {
112                    if (originalHeight == null) {
113                        originalHeight = valueBoxBase.getElement().getClientHeight();
114                    }
115                    triggerAutoResize();
116                }));
117
118
119                registerHandler(addBlurHandler(event -> {
120                    if (originalHeight != null) {
121                        valueBoxBase.setHeight(originalHeight + "px");
122                    }
123                }));
124                break;
125        }
126    }
127
128    public ResizeRule getResizeRule() {
129        return resizeRule;
130    }
131}