001/*
002 * #%L
003 * GwtBootstrap3
004 * %%
005 * Copyright (C) 2015 GwtBootstrap3
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.base.error;
021
022import com.google.gwt.editor.client.EditorError;
023import com.google.gwt.user.client.ui.HasWidgets;
024import com.google.gwt.user.client.ui.Widget;
025import gwt.material.design.client.base.HasError;
026import gwt.material.design.client.ui.MaterialHelpBlock;
027
028import java.util.List;
029
030/**
031 * This is the default {@link ErrorHandler} implementation.
032 * If there is a {@link MaterialHelpBlock} that is a child then error messages
033 * will be displayed in the {@link MaterialHelpBlock}.
034 * <p>
035 * Example:
036 * <p>
037 * <pre>{@code
038 * <m:MaterialRow>
039 *     <m:TextBox m:id="username" ui:field="username" />
040 *     <m:MaterialHelpBlock iconType="EXCLAMATION" />
041 * </m:MaterialRow>
042 * }</pre>
043 *
044 * @author Steven Jardine
045 * @author Ben Dol
046 */
047public class DefaultErrorHandler implements ErrorHandler {
048
049    private boolean initialized = false;
050
051    private final Widget inputWidget;
052
053    private MaterialHelpBlock helpBlock = null;
054
055    /**
056     * Default error handler.
057     *
058     * @param widget the parent of this error handler.
059     */
060    public DefaultErrorHandler(Widget widget) {
061        super();
062        assert widget != null;
063        this.inputWidget = widget;
064        this.inputWidget.addAttachHandler(event -> {
065            if (event.isAttached()) {
066                init();
067            }
068        });
069    }
070
071    @Override
072    public void cleanup() {
073    }
074
075    @Override
076    public void clearErrors() {
077        if (inputWidget instanceof HasError) {
078            ((HasError) inputWidget).clearErrorOrSuccess();
079        }
080        if (helpBlock != null) {
081            helpBlock.removeStyleName("field-error-label");
082            helpBlock.removeStyleName("field-success-label");
083            helpBlock.clear();
084        }
085    }
086
087    /**
088     * Find the sibling {@link MaterialHelpBlock}.
089     *
090     * @param widget the {@link Widget} to search.
091     * @return the found {@link MaterialHelpBlock} of null if not found.
092     */
093    protected MaterialHelpBlock findHelpBlock(Widget widget) {
094        if (widget != null) {
095            if (widget instanceof MaterialHelpBlock) {
096                return (MaterialHelpBlock) widget;
097            }
098            // Try and find the MaterialHelpBlock in the children of the given widget.
099            if (widget instanceof HasWidgets) {
100                for (Widget w : (HasWidgets) widget) {
101                    if (w instanceof MaterialHelpBlock) {
102                        return (MaterialHelpBlock) w;
103                    }
104                }
105            }
106            // Try and find the MaterialHelpBlock in the parent of widget.
107            return findHelpBlock(widget.getParent());
108        }
109        return null;
110    }
111
112    /**
113     * Initialize the instance.
114     */
115    public void init() {
116        if (initialized) {
117            return;
118        }
119        Widget parent = inputWidget.getParent();
120        while (parent != null && !parent.getClass().getName().equals("com.google.gwt.user.client.ui.Widget")) {
121            helpBlock = findHelpBlock(inputWidget);
122            if (helpBlock != null) {
123                break;
124            } else {
125                parent = parent.getParent();
126            }
127        }
128        initialized = true;
129    }
130
131    @Override
132    public void showErrors(List<EditorError> errors) {
133        init();
134        String errorMsg = "";
135        for (int index = 0; index < errors.size(); index++) {
136            errorMsg = errors.get(0).getMessage();
137            if (index + 1 < errors.size()) {
138                errorMsg += "; ";
139            }
140        }
141
142        if (inputWidget instanceof HasError) {
143            ((HasError) inputWidget).setError(errorMsg);
144        }
145
146        if (helpBlock != null) {
147            helpBlock.addStyleName("field-error-label");
148            helpBlock.removeStyleName("field-success-label");
149            helpBlock.setText(errorMsg);
150        }
151    }
152}