Add additional class names and style to components and error indicators to distinguish different error levels. Vaadin 8 implementation of #9816. Cherry picked changes and added compatibility package component changes and tests. Resolves #3139tags/8.2.0.alpha2
@@ -106,6 +106,8 @@ | |||
<li><tt>DataCommunicator</tt> method <tt>getDataProviderSize</tt> is now <tt>public</tt>, not <tt>protected</tt>.</li> | |||
<li><tt>Binder</tt> method <tt>getBindings</tt> now returns a Collection, not a Set.</li> | |||
<li><tt>BindingBuilder</tt> now works like a proper builder. Adding a converter will not mark Binding as <tt>bound</tt> allowing chaining to the same object.</li> | |||
<li><tt>ErrorLevel</tt> is removed from <tt>ErrorMessage</tt> and now <tt>com.vaadin.shared.ui.ErrorLevel</tt> should be used.</li> | |||
<li>Error indicators are now <tt><span class="v-errorindicator"></span></tt> elements.</li> | |||
<h2>For incompatible or behaviour-altering changes in 8.1, please see <a href="https://vaadin.com/download/release/8.1/8.1.0/release-notes.html#incompatible">8.1 release notes</a></h2> | |||
@@ -44,4 +44,9 @@ public class StyleConstants { | |||
public static final String REQUIRED_EXT = "-required"; | |||
public static final String ERROR_EXT = "-error"; | |||
/** | |||
* Style name and style name prefix for the error indicator element. | |||
*/ | |||
public static final String STYLE_NAME_ERROR_INDICATOR = "v-errorindicator"; | |||
} |
@@ -16,8 +16,13 @@ | |||
package com.vaadin.client; | |||
import com.vaadin.shared.ui.ContentMode; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
import com.vaadin.shared.util.SharedUtil; | |||
/** | |||
* An object that contains information about a tooltip, such as the tooltip's | |||
* title, error message, error level and an ID. | |||
*/ | |||
public class TooltipInfo { | |||
private String title; | |||
@@ -26,14 +31,25 @@ public class TooltipInfo { | |||
private String errorMessageHtml; | |||
private ErrorLevel errorLevel; | |||
// Contains the tooltip's identifier. If a tooltip's contents and this | |||
// identifier haven't changed, the tooltip won't be updated in subsequent | |||
// events. | |||
private Object identifier; | |||
/** | |||
* Constructs a new tooltip info instance. | |||
*/ | |||
public TooltipInfo() { | |||
} | |||
/** | |||
* Constructs a new tooltip info instance. | |||
* | |||
* @param tooltip | |||
* tooltip title | |||
*/ | |||
public TooltipInfo(String tooltip) { | |||
this(tooltip, ContentMode.PREFORMATTED); | |||
} | |||
@@ -41,12 +57,12 @@ public class TooltipInfo { | |||
/** | |||
* Constructs a new instance using the {@code tooltip} for the title and | |||
* {@code errorMessage} as a description. | |||
* | |||
* | |||
* @param tooltip | |||
* tooltip title | |||
* @param errorMessage | |||
* error description | |||
* | |||
* | |||
* @deprecated use {@link #TooltipInfo(String, ContentMode, String)} instead | |||
*/ | |||
@Deprecated | |||
@@ -57,13 +73,14 @@ public class TooltipInfo { | |||
/** | |||
* Constructs a new instance using the {@code tooltip} for the title, | |||
* {@code errorMessage} as a description and {@code identifier} as its id. | |||
* | |||
* | |||
* @param tooltip | |||
* tooltip title | |||
* @param errorMessage | |||
* error description | |||
* @param identifier | |||
* | |||
* the tooltip's identifier | |||
* | |||
* @deprecated use {@link #TooltipInfo(String, ContentMode, String, Object)} | |||
* instead | |||
*/ | |||
@@ -72,55 +89,194 @@ public class TooltipInfo { | |||
this(tooltip, ContentMode.HTML, errorMessage, identifier); | |||
} | |||
/** | |||
* Constructs a new instance using the {@code tooltip} for the title, | |||
* {@code errorMessage} as a description, {@code identifier} as its id and | |||
* {@code errorLevel} as the error level. | |||
* | |||
* @param tooltip | |||
* tooltip title | |||
* @param errorMessage | |||
* error description | |||
* @param identifier | |||
* the tooltip's identifier | |||
* @param errorLevel | |||
* error level | |||
* | |||
* @deprecated use {@link #TooltipInfo(String, ContentMode, String, Object, | |||
* ErrorLevel)} instead | |||
* @since 8.2 | |||
*/ | |||
@Deprecated | |||
public TooltipInfo(String tooltip, String errorMessage, Object identifier, | |||
ErrorLevel errorLevel) { | |||
this(tooltip, ContentMode.HTML, errorMessage, identifier, errorLevel); | |||
} | |||
/** | |||
* Constructs a new tooltip info instance. | |||
* | |||
* @param tooltip | |||
* tooltip title | |||
* @param mode | |||
* content mode | |||
*/ | |||
public TooltipInfo(String tooltip, ContentMode mode) { | |||
setTitle(tooltip); | |||
setContentMode(mode); | |||
} | |||
/** | |||
* Constructs a new tooltip info instance. | |||
* | |||
* @param tooltip | |||
* tooltip title | |||
* @param mode | |||
* content mode | |||
* @param errorMessage | |||
* error message | |||
*/ | |||
public TooltipInfo(String tooltip, ContentMode mode, String errorMessage) { | |||
this(tooltip, mode, errorMessage, null); | |||
} | |||
/** | |||
* Constructs a new tooltip info instance. | |||
* | |||
* @param tooltip | |||
* tooltip title | |||
* @param mode | |||
* content mode | |||
* @param errorMessage | |||
* error message | |||
* @param identifier | |||
* the tooltip's identifier | |||
*/ | |||
public TooltipInfo(String tooltip, ContentMode mode, String errorMessage, | |||
Object identifier) { | |||
this(tooltip, mode, errorMessage, identifier, null); | |||
} | |||
/** | |||
* Constructs a new tooltip info instance. | |||
* | |||
* @param tooltip | |||
* tooltip title | |||
* @param mode | |||
* content mode | |||
* @param errorMessage | |||
* error message | |||
* @param identifier | |||
* the tooltip's identifier | |||
* @param errorLevel | |||
* error level | |||
*/ | |||
public TooltipInfo(String tooltip, ContentMode mode, String errorMessage, | |||
Object identifier, ErrorLevel errorLevel) { | |||
setIdentifier(identifier); | |||
setTitle(tooltip); | |||
setContentMode(mode); | |||
setErrorMessage(errorMessage); | |||
setErrorLevel(errorLevel); | |||
} | |||
/** | |||
* Sets the tooltip's identifier. | |||
* | |||
* @param identifier | |||
* the identifier to set | |||
*/ | |||
public void setIdentifier(Object identifier) { | |||
this.identifier = identifier; | |||
} | |||
/** | |||
* Gets the tooltip's identifier. | |||
* | |||
* @return the identifier | |||
*/ | |||
public Object getIdentifier() { | |||
return identifier; | |||
} | |||
/** | |||
* Gets the tooltip title. | |||
* | |||
* @return the title | |||
*/ | |||
public String getTitle() { | |||
return title; | |||
} | |||
/** | |||
* Sets the tooltip title. | |||
* | |||
* @param title | |||
* the title to set | |||
*/ | |||
public void setTitle(String title) { | |||
this.title = title; | |||
} | |||
/** | |||
* Gets the error message. | |||
* | |||
* @return the error message | |||
*/ | |||
public String getErrorMessage() { | |||
return errorMessageHtml; | |||
} | |||
/** | |||
* Sets the error message. | |||
* | |||
* @param errorMessage | |||
* the error message to set | |||
*/ | |||
public void setErrorMessage(String errorMessage) { | |||
errorMessageHtml = errorMessage; | |||
} | |||
/** | |||
* Gets the tooltip title's content mode. | |||
* | |||
* @return the content mode | |||
*/ | |||
public ContentMode getContentMode() { | |||
return contentMode; | |||
} | |||
/** | |||
* Sets the tooltip title's content mode. | |||
* | |||
* @param contentMode | |||
* the content mode to set | |||
*/ | |||
public void setContentMode(ContentMode contentMode) { | |||
this.contentMode = contentMode; | |||
} | |||
/** | |||
* Gets the error level. | |||
* | |||
* @return the error level | |||
* @since | |||
*/ | |||
public ErrorLevel getErrorLevel() { | |||
return errorLevel; | |||
} | |||
/** | |||
* Sets the error level. | |||
* | |||
* @param errorLevel | |||
* the error level to set | |||
* @since | |||
*/ | |||
public void setErrorLevel(ErrorLevel errorLevel) { | |||
this.errorLevel = errorLevel; | |||
} | |||
/** | |||
* Checks is a message has been defined for the tooltip. | |||
* | |||
@@ -132,9 +288,19 @@ public class TooltipInfo { | |||
|| (errorMessageHtml != null && !errorMessageHtml.isEmpty()); | |||
} | |||
/** | |||
* Indicates whether another tooltip info instance is equal to this one. Two | |||
* instances are equal if their title, error message, error level and | |||
* identifier are equal. | |||
* | |||
* @param other | |||
* the reference tooltip info instance with which to compare | |||
* @return {@code true} if the instances are equal, {@code false} otherwise | |||
*/ | |||
public boolean equals(TooltipInfo other) { | |||
return (other != null && SharedUtil.equals(other.title, title) | |||
&& SharedUtil.equals(other.errorMessageHtml, errorMessageHtml) | |||
&& SharedUtil.equals(other.errorLevel, errorLevel) | |||
&& other.identifier == identifier); | |||
} | |||
} |
@@ -25,8 +25,10 @@ import com.google.gwt.user.client.DOM; | |||
import com.google.gwt.user.client.Event; | |||
import com.google.gwt.user.client.ui.HTML; | |||
import com.google.gwt.user.client.ui.HasHTML; | |||
import com.vaadin.client.WidgetUtil.ErrorUtil; | |||
import com.vaadin.client.communication.StateChangeEvent; | |||
import com.vaadin.client.ui.HasErrorIndicator; | |||
import com.vaadin.client.ui.HasErrorIndicatorElement; | |||
import com.vaadin.client.ui.HasRequiredIndicator; | |||
import com.vaadin.client.ui.Icon; | |||
import com.vaadin.client.ui.ImageIcon; | |||
@@ -34,8 +36,9 @@ import com.vaadin.client.ui.aria.AriaHelper; | |||
import com.vaadin.shared.AbstractComponentState; | |||
import com.vaadin.shared.ComponentConstants; | |||
import com.vaadin.shared.ui.ComponentStateUtil; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
public class VCaption extends HTML { | |||
public class VCaption extends HTML implements HasErrorIndicatorElement { | |||
public static final String CLASSNAME = "v-caption"; | |||
@@ -259,23 +262,17 @@ public class VCaption extends HTML { | |||
AriaHelper.handleInputInvalid(owner.getWidget(), showError); | |||
if (showError) { | |||
if (errorIndicatorElement == null) { | |||
errorIndicatorElement = DOM.createDiv(); | |||
DOM.setInnerHTML(errorIndicatorElement, " "); | |||
DOM.setElementProperty(errorIndicatorElement, "className", | |||
"v-errorindicator"); | |||
setErrorIndicatorElementVisible(true); | |||
DOM.insertChild(getElement(), errorIndicatorElement, | |||
getInsertPosition(InsertPosition.ERROR)); | |||
// Hide error indicator from assistive devices | |||
Roles.getTextboxRole() | |||
.setAriaHiddenState(errorIndicatorElement, true); | |||
// Hide error indicator from assistive devices | |||
Roles.getTextboxRole().setAriaHiddenState(errorIndicatorElement, | |||
true); | |||
} | |||
} else if (errorIndicatorElement != null) { | |||
// Remove existing | |||
getElement().removeChild(errorIndicatorElement); | |||
errorIndicatorElement = null; | |||
ErrorUtil.setErrorLevelStyle(errorIndicatorElement, | |||
StyleConstants.STYLE_NAME_ERROR_INDICATOR, | |||
owner.getState().errorLevel); | |||
} else { | |||
setErrorIndicatorElementVisible(false); | |||
} | |||
return (wasPlacedAfterComponent != placedAfterComponent); | |||
@@ -322,6 +319,14 @@ public class VCaption extends HTML { | |||
public boolean updateCaptionWithoutOwner(String caption, boolean disabled, | |||
boolean hasDescription, boolean hasError, String iconURL, | |||
String iconAltText) { | |||
return updateCaptionWithoutOwner(caption, disabled, hasDescription, | |||
hasError, null, iconURL, iconAltText); | |||
} | |||
@Deprecated | |||
public boolean updateCaptionWithoutOwner(String caption, boolean disabled, | |||
boolean hasDescription, boolean hasError, ErrorLevel errorLevel, | |||
String iconURL, String iconAltText) { | |||
boolean wasPlacedAfterComponent = placedAfterComponent; | |||
// Caption is placed after component unless there is some part which | |||
@@ -401,19 +406,11 @@ public class VCaption extends HTML { | |||
} | |||
if (hasError) { | |||
if (errorIndicatorElement == null) { | |||
errorIndicatorElement = DOM.createDiv(); | |||
DOM.setInnerHTML(errorIndicatorElement, " "); | |||
DOM.setElementProperty(errorIndicatorElement, "className", | |||
"v-errorindicator"); | |||
DOM.insertChild(getElement(), errorIndicatorElement, | |||
getInsertPosition(InsertPosition.ERROR)); | |||
} | |||
} else if (errorIndicatorElement != null) { | |||
// Remove existing | |||
getElement().removeChild(errorIndicatorElement); | |||
errorIndicatorElement = null; | |||
setErrorIndicatorElementVisible(true); | |||
ErrorUtil.setErrorLevelStyle(errorIndicatorElement, | |||
StyleConstants.STYLE_NAME_ERROR_INDICATOR, errorLevel); | |||
} else { | |||
setErrorIndicatorElementVisible(false); | |||
} | |||
return (wasPlacedAfterComponent != placedAfterComponent); | |||
@@ -775,4 +772,23 @@ public class VCaption extends HTML { | |||
private static Logger getLogger() { | |||
return Logger.getLogger(VCaption.class.getName()); | |||
} | |||
@Override | |||
public Element getErrorIndicatorElement() { | |||
return errorIndicatorElement; | |||
} | |||
@Override | |||
public void setErrorIndicatorElementVisible(boolean visible) { | |||
if (visible) { | |||
if (errorIndicatorElement == null) { | |||
errorIndicatorElement = ErrorUtil.createErrorIndicatorElement(); | |||
DOM.insertChild(getElement(), errorIndicatorElement, | |||
getInsertPosition(InsertPosition.ERROR)); | |||
} | |||
} else if (errorIndicatorElement != null) { | |||
getElement().removeChild(errorIndicatorElement); | |||
errorIndicatorElement = null; | |||
} | |||
} | |||
} |
@@ -22,6 +22,8 @@ import com.google.gwt.user.client.ui.FlowPanel; | |||
import com.google.gwt.user.client.ui.HTML; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.vaadin.client.ui.VOverlay; | |||
import com.vaadin.client.WidgetUtil.ErrorUtil; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
public class VErrorMessage extends FlowPanel { | |||
public static final String CLASSNAME = "v-errormessage"; | |||
@@ -57,6 +59,18 @@ public class VErrorMessage extends FlowPanel { | |||
} | |||
} | |||
/** | |||
* Sets the correct error level style name for the error message and removes | |||
* all previous style names. | |||
* | |||
* @param errorLevel | |||
* error level | |||
* @since | |||
*/ | |||
public void updateErrorLevel(ErrorLevel errorLevel) { | |||
ErrorUtil.setErrorLevelStyle(getStyleElement(), CLASSNAME, errorLevel); | |||
} | |||
/** | |||
* Shows this error message next to given element. | |||
* |
@@ -138,6 +138,7 @@ public class VTooltip extends VOverlay { | |||
&& !info.getErrorMessage().isEmpty()) { | |||
em.setVisible(true); | |||
em.updateMessage(info.getErrorMessage()); | |||
em.updateErrorLevel(info.getErrorLevel()); | |||
} else { | |||
em.setVisible(false); | |||
} | |||
@@ -459,6 +460,7 @@ public class VTooltip extends VOverlay { | |||
@Override | |||
public void hide() { | |||
em.updateMessage(""); | |||
em.updateErrorLevel(null); | |||
description.setHTML(""); | |||
updatePosition(null, true); |
@@ -44,6 +44,7 @@ import com.google.gwt.user.client.EventListener; | |||
import com.google.gwt.user.client.Window; | |||
import com.google.gwt.user.client.ui.RootPanel; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
import com.vaadin.shared.util.SharedUtil; | |||
/** | |||
@@ -790,7 +791,7 @@ public class WidgetUtil { | |||
com.google.gwt.dom.client.Element el, String p) | |||
/*-{ | |||
try { | |||
if (el.currentStyle) { | |||
// IE | |||
return el.currentStyle[p]; | |||
@@ -805,7 +806,7 @@ public class WidgetUtil { | |||
} catch (e) { | |||
return ""; | |||
} | |||
}-*/; | |||
/** | |||
@@ -819,7 +820,7 @@ public class WidgetUtil { | |||
try { | |||
el.focus(); | |||
} catch (e) { | |||
} | |||
}-*/; | |||
@@ -1172,7 +1173,7 @@ public class WidgetUtil { | |||
if ($wnd.document.activeElement) { | |||
return $wnd.document.activeElement; | |||
} | |||
return null; | |||
}-*/; | |||
@@ -1243,11 +1244,11 @@ public class WidgetUtil { | |||
/*-{ | |||
var top = elem.offsetTop; | |||
var height = elem.offsetHeight; | |||
if (elem.parentNode != elem.offsetParent) { | |||
top -= elem.parentNode.offsetTop; | |||
} | |||
var cur = elem.parentNode; | |||
while (cur && (cur.nodeType == 1)) { | |||
if (top < cur.scrollTop) { | |||
@@ -1256,12 +1257,12 @@ public class WidgetUtil { | |||
if (top + height > cur.scrollTop + cur.clientHeight) { | |||
cur.scrollTop = (top + height) - cur.clientHeight; | |||
} | |||
var offsetTop = cur.offsetTop; | |||
if (cur.parentNode != cur.offsetParent) { | |||
offsetTop -= cur.parentNode.offsetTop; | |||
} | |||
top += offsetTop - cur.scrollTop; | |||
cur = cur.parentNode; | |||
} | |||
@@ -1710,7 +1711,7 @@ public class WidgetUtil { | |||
} | |||
var heightWithoutBorder = cloneElement.offsetHeight; | |||
parentElement.removeChild(cloneElement); | |||
return heightWithBorder - heightWithoutBorder; | |||
} | |||
}-*/; | |||
@@ -1866,4 +1867,48 @@ public class WidgetUtil { | |||
int relativeTop = element.getAbsoluteTop() - Window.getScrollTop(); | |||
return WidgetUtil.getTouchOrMouseClientY(event) - relativeTop; | |||
} | |||
/** | |||
* Utility methods for displaying error message on components. | |||
* | |||
* @since 8.2 | |||
*/ | |||
public static class ErrorUtil { | |||
/** | |||
* Sets the error level style name for the given element and removes all | |||
* previously applied error level style names. The style name has the | |||
* {@code prefix-errorLevel} format. | |||
* | |||
* @param element | |||
* element to apply the style name to | |||
* @param prefix | |||
* part of the style name before the error level string | |||
* @param errorLevel | |||
* error level for which the style will be applied | |||
*/ | |||
public static void setErrorLevelStyle(Element element, String prefix, | |||
ErrorLevel errorLevel) { | |||
for (ErrorLevel errorLevelValue : ErrorLevel.values()) { | |||
String className = | |||
prefix + "-" + errorLevelValue.toString().toLowerCase(); | |||
if (errorLevel == errorLevelValue) { | |||
element.addClassName(className); | |||
} else { | |||
element.removeClassName(className); | |||
} | |||
} | |||
} | |||
/** | |||
* Creates an element to use by widgets as an error indicator. | |||
* | |||
* @return the error indicator element | |||
*/ | |||
public static Element createErrorIndicatorElement() { | |||
Element indicator = DOM.createSpan(); | |||
indicator.setClassName(StyleConstants.STYLE_NAME_ERROR_INDICATOR); | |||
return indicator; | |||
} | |||
} | |||
} |
@@ -46,6 +46,7 @@ import com.vaadin.client.UIDL; | |||
import com.vaadin.client.Util; | |||
import com.vaadin.client.VConsole; | |||
import com.vaadin.client.WidgetUtil; | |||
import com.vaadin.client.WidgetUtil.ErrorUtil; | |||
import com.vaadin.client.annotations.OnStateChange; | |||
import com.vaadin.client.communication.StateChangeEvent; | |||
import com.vaadin.client.extensions.DragSourceExtensionConnector; | |||
@@ -489,6 +490,27 @@ public abstract class AbstractComponentConnector extends AbstractConnector | |||
Profiler.leave("AbstractComponentConnector.onStateChanged"); | |||
} | |||
@OnStateChange({"errorMessage", "errorLevel"}) | |||
private void setErrorLevel() { | |||
// Add or remove the widget's error level style name | |||
ErrorUtil.setErrorLevelStyle(getWidget().getElement(), | |||
getWidget().getStylePrimaryName() + StyleConstants.ERROR_EXT, | |||
getState().errorLevel); | |||
// Add or remove error indicator element | |||
if (getWidget() instanceof HasErrorIndicatorElement) { | |||
HasErrorIndicatorElement widget = (HasErrorIndicatorElement) getWidget(); | |||
if (getState().errorMessage != null) { | |||
widget.setErrorIndicatorElementVisible(true); | |||
ErrorUtil.setErrorLevelStyle(widget.getErrorIndicatorElement(), | |||
StyleConstants.STYLE_NAME_ERROR_INDICATOR, | |||
getState().errorLevel); | |||
} else { | |||
widget.setErrorIndicatorElementVisible(false); | |||
} | |||
} | |||
} | |||
@Override | |||
public void setWidgetEnabled(boolean widgetEnabled) { | |||
// add or remove v-disabled style name from the widget | |||
@@ -764,7 +786,8 @@ public abstract class AbstractComponentConnector extends AbstractConnector | |||
@Override | |||
public TooltipInfo getTooltipInfo(Element element) { | |||
return new TooltipInfo(getState().description, | |||
getState().descriptionContentMode, getState().errorMessage); | |||
getState().descriptionContentMode, getState().errorMessage, | |||
null, getState().errorLevel); | |||
} | |||
@Override |
@@ -0,0 +1,42 @@ | |||
/* | |||
* Copyright 2000-2016 Vaadin Ltd. | |||
* | |||
* 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. | |||
*/ | |||
package com.vaadin.client.ui; | |||
import com.google.gwt.dom.client.Element; | |||
/** | |||
* Implemented by widgets supporting an error indicator. | |||
* | |||
* @since 8.2 | |||
*/ | |||
public interface HasErrorIndicatorElement { | |||
/** | |||
* Gets the error indicator element. | |||
* | |||
* @return the error indicator element | |||
*/ | |||
Element getErrorIndicatorElement(); | |||
/** | |||
* Sets the visibility of the error indicator element. | |||
* | |||
* @param visible | |||
* {@code true} to show the error indicator element, {@code false} | |||
* to hide it | |||
*/ | |||
void setErrorIndicatorElementVisible(boolean visible); | |||
} |
@@ -364,8 +364,10 @@ public class VAccordion extends VTabsheetBase { | |||
caption.updateCaptionWithoutOwner(tabState.caption, | |||
!tabState.enabled, hasAttribute(tabState.description), | |||
hasAttribute(tabState.componentError), | |||
tabState.componentErrorLevel, | |||
connector.getResourceUrl( | |||
ComponentConstants.ICON_RESOURCE + tabState.key)); | |||
ComponentConstants.ICON_RESOURCE + tabState.key), | |||
tabState.iconAltText); | |||
} | |||
private boolean hasAttribute(String string) { |
@@ -30,8 +30,10 @@ import com.vaadin.client.ApplicationConnection; | |||
import com.vaadin.client.BrowserInfo; | |||
import com.vaadin.client.Util; | |||
import com.vaadin.client.WidgetUtil; | |||
import com.vaadin.client.WidgetUtil.ErrorUtil; | |||
public class VButton extends FocusWidget implements ClickHandler { | |||
public class VButton extends FocusWidget implements ClickHandler, | |||
HasErrorIndicatorElement { | |||
public static final String CLASSNAME = "v-button"; | |||
private static final String CLASSNAME_PRESSED = "v-pressed"; | |||
@@ -48,7 +50,7 @@ public class VButton extends FocusWidget implements ClickHandler { | |||
public final Element wrapper = DOM.createSpan(); | |||
/** For internal use only. May be removed or replaced in the future. */ | |||
public Element errorIndicatorElement; | |||
private Element errorIndicatorElement; | |||
/** For internal use only. May be removed or replaced in the future. */ | |||
public final Element captionElement = DOM.createSpan(); | |||
@@ -481,4 +483,21 @@ public class VButton extends FocusWidget implements ClickHandler { | |||
return ret; | |||
}-*/; | |||
@Override | |||
public Element getErrorIndicatorElement() { | |||
return errorIndicatorElement; | |||
} | |||
@Override | |||
public void setErrorIndicatorElementVisible(boolean visible) { | |||
if (visible) { | |||
if (errorIndicatorElement == null) { | |||
errorIndicatorElement = ErrorUtil.createErrorIndicatorElement(); | |||
wrapper.insertFirst(errorIndicatorElement); | |||
} | |||
} else if (errorIndicatorElement != null) { | |||
wrapper.removeChild(errorIndicatorElement); | |||
errorIndicatorElement = null; | |||
} | |||
} | |||
} |
@@ -25,12 +25,14 @@ import com.vaadin.client.ApplicationConnection; | |||
import com.vaadin.client.BrowserInfo; | |||
import com.vaadin.client.Util; | |||
import com.vaadin.client.VTooltip; | |||
import com.vaadin.client.WidgetUtil.ErrorUtil; | |||
import com.vaadin.client.ui.aria.AriaHelper; | |||
import com.vaadin.client.ui.aria.HandlesAriaInvalid; | |||
import com.vaadin.client.ui.aria.HandlesAriaRequired; | |||
public class VCheckBox extends com.google.gwt.user.client.ui.CheckBox | |||
implements Field, HandlesAriaInvalid, HandlesAriaRequired { | |||
implements Field, HandlesAriaInvalid, HandlesAriaRequired, | |||
HasErrorIndicatorElement { | |||
public static final String CLASSNAME = "v-checkbox"; | |||
@@ -41,7 +43,7 @@ public class VCheckBox extends com.google.gwt.user.client.ui.CheckBox | |||
public ApplicationConnection client; | |||
/** For internal use only. May be removed or replaced in the future. */ | |||
public Element errorIndicatorElement; | |||
private Element errorIndicatorElement; | |||
/** For internal use only. May be removed or replaced in the future. */ | |||
public Icon icon; | |||
@@ -101,4 +103,24 @@ public class VCheckBox extends com.google.gwt.user.client.ui.CheckBox | |||
public void setAriaInvalid(boolean invalid) { | |||
AriaHelper.handleInputInvalid(getCheckBoxElement(), invalid); | |||
} | |||
@Override | |||
public Element getErrorIndicatorElement() { | |||
return errorIndicatorElement; | |||
} | |||
@Override | |||
public void setErrorIndicatorElementVisible(boolean visible) { | |||
if (visible) { | |||
if (errorIndicatorElement == null) { | |||
errorIndicatorElement = ErrorUtil.createErrorIndicatorElement(); | |||
getElement().appendChild(errorIndicatorElement); | |||
DOM.sinkEvents(errorIndicatorElement, | |||
VTooltip.TOOLTIP_EVENTS | Event.ONCLICK); | |||
} | |||
} else if (errorIndicatorElement != null) { | |||
getElement().removeChild(errorIndicatorElement); | |||
errorIndicatorElement = null; | |||
} | |||
} | |||
} |
@@ -34,10 +34,12 @@ import com.vaadin.client.ComponentConnector; | |||
import com.vaadin.client.Focusable; | |||
import com.vaadin.client.StyleConstants; | |||
import com.vaadin.client.VTooltip; | |||
import com.vaadin.client.WidgetUtil.ErrorUtil; | |||
import com.vaadin.client.ui.aria.AriaHelper; | |||
import com.vaadin.shared.AbstractComponentState; | |||
import com.vaadin.shared.ComponentConstants; | |||
import com.vaadin.shared.ui.ComponentStateUtil; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
import com.vaadin.shared.ui.MarginInfo; | |||
/** | |||
@@ -201,10 +203,10 @@ public class VFormLayout extends SimplePanel { | |||
} | |||
public void updateError(Widget widget, String errorMessage, | |||
boolean hideErrors) { | |||
ErrorLevel errorLevel, boolean hideErrors) { | |||
final ErrorFlag e = widgetToError.get(widget); | |||
if (e != null) { | |||
e.updateError(errorMessage, hideErrors); | |||
e.updateError(errorMessage, errorLevel, hideErrors); | |||
} | |||
} | |||
@@ -340,7 +342,7 @@ public class VFormLayout extends SimplePanel { | |||
} | |||
/** For internal use only. May be removed or replaced in the future. */ | |||
public class ErrorFlag extends HTML { | |||
public class ErrorFlag extends HTML implements HasErrorIndicatorElement { | |||
private static final String CLASSNAME = VFormLayout.CLASSNAME | |||
+ "-error-indicator"; | |||
Element errorIndicatorElement; | |||
@@ -361,7 +363,8 @@ public class VFormLayout extends SimplePanel { | |||
return owner; | |||
} | |||
public void updateError(String errorMessage, boolean hideErrors) { | |||
public void updateError(String errorMessage, ErrorLevel errorLevel, | |||
boolean hideErrors) { | |||
boolean showError = null != errorMessage; | |||
if (hideErrors) { | |||
showError = false; | |||
@@ -370,24 +373,37 @@ public class VFormLayout extends SimplePanel { | |||
AriaHelper.handleInputInvalid(owner.getWidget(), showError); | |||
if (showError) { | |||
if (errorIndicatorElement == null) { | |||
errorIndicatorElement = DOM.createDiv(); | |||
DOM.setInnerHTML(errorIndicatorElement, " "); | |||
DOM.setElementProperty(errorIndicatorElement, "className", | |||
"v-errorindicator"); | |||
DOM.appendChild(getElement(), errorIndicatorElement); | |||
setErrorIndicatorElementVisible(true); | |||
// Hide the error indicator from screen reader, as this | |||
// information is set directly at the input field | |||
Roles.getFormRole() | |||
.setAriaHiddenState(errorIndicatorElement, true); | |||
} | |||
// Hide the error indicator from screen reader, as this | |||
// information is set directly at the input field | |||
Roles.getFormRole() | |||
.setAriaHiddenState(errorIndicatorElement, true); | |||
ErrorUtil.setErrorLevelStyle(errorIndicatorElement, | |||
StyleConstants.STYLE_NAME_ERROR_INDICATOR, errorLevel); | |||
} else { | |||
setErrorIndicatorElementVisible(false); | |||
} | |||
} | |||
@Override | |||
public Element getErrorIndicatorElement() { | |||
return errorIndicatorElement; | |||
} | |||
@Override | |||
public void setErrorIndicatorElementVisible(boolean visible) { | |||
if (visible) { | |||
if (errorIndicatorElement == null) { | |||
errorIndicatorElement = ErrorUtil | |||
.createErrorIndicatorElement(); | |||
getElement().appendChild(errorIndicatorElement); | |||
} | |||
} else if (errorIndicatorElement != null) { | |||
DOM.removeChild(getElement(), errorIndicatorElement); | |||
getElement().removeChild(errorIndicatorElement); | |||
errorIndicatorElement = null; | |||
} | |||
} | |||
} | |||
} |
@@ -25,9 +25,11 @@ import com.google.gwt.user.client.Window; | |||
import com.google.gwt.user.client.ui.HTML; | |||
import com.google.gwt.user.client.ui.HasEnabled; | |||
import com.vaadin.client.Util; | |||
import com.vaadin.client.WidgetUtil.ErrorUtil; | |||
import com.vaadin.shared.ui.BorderStyle; | |||
public class VLink extends HTML implements ClickHandler, HasEnabled { | |||
public class VLink extends HTML implements ClickHandler, HasEnabled, | |||
HasErrorIndicatorElement { | |||
public static final String CLASSNAME = "v-link"; | |||
@@ -59,7 +61,7 @@ public class VLink extends HTML implements ClickHandler, HasEnabled { | |||
public int targetHeight; | |||
/** For internal use only. May be removed or replaced in the future. */ | |||
public Element errorIndicatorElement; | |||
private Element errorIndicatorElement; | |||
/** For internal use only. May be removed or replaced in the future. */ | |||
public final Element anchor = DOM.createAnchor(); | |||
@@ -145,4 +147,21 @@ public class VLink extends HTML implements ClickHandler, HasEnabled { | |||
this.enabled = enabled; | |||
} | |||
@Override | |||
public Element getErrorIndicatorElement() { | |||
return errorIndicatorElement; | |||
} | |||
@Override | |||
public void setErrorIndicatorElementVisible(boolean visible) { | |||
if (visible) { | |||
if (errorIndicatorElement == null) { | |||
errorIndicatorElement = ErrorUtil.createErrorIndicatorElement(); | |||
getElement().insertFirst(errorIndicatorElement); | |||
} | |||
} else if (errorIndicatorElement != null) { | |||
getElement().removeChild(errorIndicatorElement); | |||
errorIndicatorElement = null; | |||
} | |||
} | |||
} |
@@ -27,10 +27,12 @@ import com.vaadin.client.BrowserInfo; | |||
import com.vaadin.client.MouseEventDetailsBuilder; | |||
import com.vaadin.client.StyleConstants; | |||
import com.vaadin.client.Util; | |||
import com.vaadin.client.WidgetUtil.ErrorUtil; | |||
import com.vaadin.shared.MouseEventDetails; | |||
import com.vaadin.shared.ui.button.ButtonServerRpc; | |||
public class VNativeButton extends Button implements ClickHandler { | |||
public class VNativeButton extends Button implements ClickHandler, | |||
HasErrorIndicatorElement { | |||
public static final String CLASSNAME = "v-nativebutton"; | |||
@@ -44,7 +46,7 @@ public class VNativeButton extends Button implements ClickHandler { | |||
public ButtonServerRpc buttonRpcProxy; | |||
/** For internal use only. May be removed or replaced in the future. */ | |||
public Element errorIndicatorElement; | |||
private Element errorIndicatorElement; | |||
/** For internal use only. May be removed or replaced in the future. */ | |||
public final Element captionElement = DOM.createSpan(); | |||
@@ -159,4 +161,22 @@ public class VNativeButton extends Button implements ClickHandler { | |||
clickPending = false; | |||
} | |||
@Override | |||
public Element getErrorIndicatorElement() { | |||
return errorIndicatorElement; | |||
} | |||
@Override | |||
public void setErrorIndicatorElementVisible(boolean visible) { | |||
if (visible) { | |||
if (errorIndicatorElement == null) { | |||
errorIndicatorElement = ErrorUtil.createErrorIndicatorElement(); | |||
getElement() | |||
.insertBefore(errorIndicatorElement, captionElement); | |||
} | |||
} else if (errorIndicatorElement != null) { | |||
getElement().removeChild(errorIndicatorElement); | |||
errorIndicatorElement = null; | |||
} | |||
} | |||
} |
@@ -24,11 +24,12 @@ import com.google.gwt.user.client.Event; | |||
import com.google.gwt.user.client.ui.SimplePanel; | |||
import com.vaadin.client.ApplicationConnection; | |||
import com.vaadin.client.Focusable; | |||
import com.vaadin.client.WidgetUtil.ErrorUtil; | |||
import com.vaadin.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner; | |||
import com.vaadin.client.ui.TouchScrollDelegate.TouchScrollHandler; | |||
public class VPanel extends SimplePanel | |||
implements ShortcutActionHandlerOwner, Focusable { | |||
public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner, | |||
Focusable, HasErrorIndicatorElement { | |||
public static final String CLASSNAME = "v-panel"; | |||
@@ -133,23 +134,6 @@ public class VPanel extends SimplePanel | |||
DOM.setInnerHTML(captionText, text); | |||
} | |||
/** For internal use only. May be removed or replaced in the future. */ | |||
public void setErrorIndicatorVisible(boolean showError) { | |||
if (showError) { | |||
if (errorIndicatorElement == null) { | |||
errorIndicatorElement = DOM.createSpan(); | |||
DOM.setElementProperty(errorIndicatorElement, "className", | |||
"v-errorindicator"); | |||
DOM.sinkEvents(errorIndicatorElement, Event.MOUSEEVENTS); | |||
sinkEvents(Event.MOUSEEVENTS); | |||
} | |||
DOM.insertBefore(captionNode, errorIndicatorElement, captionText); | |||
} else if (errorIndicatorElement != null) { | |||
DOM.removeChild(captionNode, errorIndicatorElement); | |||
errorIndicatorElement = null; | |||
} | |||
} | |||
/** For internal use only. May be removed or replaced in the future. */ | |||
public void setIconUri(String iconUri, ApplicationConnection client) { | |||
if (icon != null) { | |||
@@ -201,4 +185,24 @@ public class VPanel extends SimplePanel | |||
} | |||
touchScrollHandler.addElement(contentNode); | |||
} | |||
@Override | |||
public Element getErrorIndicatorElement() { | |||
return errorIndicatorElement; | |||
} | |||
@Override | |||
public void setErrorIndicatorElementVisible(boolean visible) { | |||
if (visible) { | |||
if (errorIndicatorElement == null) { | |||
errorIndicatorElement = ErrorUtil.createErrorIndicatorElement(); | |||
DOM.sinkEvents(errorIndicatorElement, Event.MOUSEEVENTS); | |||
sinkEvents(Event.MOUSEEVENTS); | |||
captionNode.insertBefore(errorIndicatorElement, captionText); | |||
} | |||
} else if (errorIndicatorElement != null){ | |||
captionNode.removeChild(errorIndicatorElement); | |||
errorIndicatorElement = null; | |||
} | |||
} | |||
} |
@@ -340,7 +340,8 @@ public class VTabsheet extends VTabsheetBase | |||
|| tabState.componentError != null) { | |||
setTooltipInfo(new TooltipInfo(tabState.description, | |||
tabState.descriptionContentMode, | |||
tabState.componentError, this)); | |||
tabState.componentError, this, | |||
tabState.componentErrorLevel)); | |||
} else { | |||
setTooltipInfo(null); | |||
} | |||
@@ -352,6 +353,7 @@ public class VTabsheet extends VTabsheetBase | |||
boolean ret = updateCaptionWithoutOwner(captionString, | |||
!tabState.enabled, hasAttribute(tabState.description), | |||
hasAttribute(tabState.componentError), | |||
tabState.componentErrorLevel, | |||
tab.getTabsheet().connector.getResourceUrl( | |||
ComponentConstants.ICON_RESOURCE + tabState.key), | |||
tabState.iconAltText); |
@@ -20,7 +20,9 @@ import com.google.gwt.event.dom.client.ClickEvent; | |||
import com.google.gwt.event.dom.client.ClickHandler; | |||
import com.google.gwt.user.client.DOM; | |||
import com.vaadin.client.MouseEventDetailsBuilder; | |||
import com.vaadin.client.StyleConstants; | |||
import com.vaadin.client.VCaption; | |||
import com.vaadin.client.WidgetUtil.ErrorUtil; | |||
import com.vaadin.client.annotations.OnStateChange; | |||
import com.vaadin.client.ui.AbstractComponentConnector; | |||
import com.vaadin.client.ui.ConnectorFocusAndBlurHandler; | |||
@@ -50,22 +52,6 @@ public class ButtonConnector extends AbstractComponentConnector | |||
ConnectorFocusAndBlurHandler.addHandlers(this); | |||
} | |||
@OnStateChange("errorMessage") | |||
void setErrorMessage() { | |||
if (null != getState().errorMessage) { | |||
if (getWidget().errorIndicatorElement == null) { | |||
getWidget().errorIndicatorElement = DOM.createSpan(); | |||
getWidget().errorIndicatorElement | |||
.setClassName("v-errorindicator"); | |||
} | |||
getWidget().wrapper.insertFirst(getWidget().errorIndicatorElement); | |||
} else if (getWidget().errorIndicatorElement != null) { | |||
getWidget().wrapper.removeChild(getWidget().errorIndicatorElement); | |||
getWidget().errorIndicatorElement = null; | |||
} | |||
} | |||
@OnStateChange("resources") | |||
void onResourceChange() { | |||
if (getWidget().icon != null) { |
@@ -21,8 +21,10 @@ import com.google.gwt.event.dom.client.ClickHandler; | |||
import com.google.gwt.user.client.DOM; | |||
import com.google.gwt.user.client.Event; | |||
import com.vaadin.client.MouseEventDetailsBuilder; | |||
import com.vaadin.client.StyleConstants; | |||
import com.vaadin.client.VCaption; | |||
import com.vaadin.client.VTooltip; | |||
import com.vaadin.client.WidgetUtil.ErrorUtil; | |||
import com.vaadin.client.annotations.OnStateChange; | |||
import com.vaadin.client.communication.StateChangeEvent; | |||
import com.vaadin.client.ui.AbstractFieldConnector; | |||
@@ -66,27 +68,7 @@ public class CheckBoxConnector extends AbstractFieldConnector | |||
public void onStateChanged(StateChangeEvent stateChangeEvent) { | |||
super.onStateChanged(stateChangeEvent); | |||
if (null != getState().errorMessage) { | |||
getWidget().setAriaInvalid(true); | |||
if (getWidget().errorIndicatorElement == null) { | |||
getWidget().errorIndicatorElement = DOM.createSpan(); | |||
getWidget().errorIndicatorElement.setInnerHTML(" "); | |||
DOM.setElementProperty(getWidget().errorIndicatorElement, | |||
"className", "v-errorindicator"); | |||
DOM.appendChild(getWidget().getElement(), | |||
getWidget().errorIndicatorElement); | |||
DOM.sinkEvents(getWidget().errorIndicatorElement, | |||
VTooltip.TOOLTIP_EVENTS | Event.ONCLICK); | |||
} else { | |||
getWidget().errorIndicatorElement.getStyle().clearDisplay(); | |||
} | |||
} else if (getWidget().errorIndicatorElement != null) { | |||
getWidget().errorIndicatorElement.getStyle() | |||
.setDisplay(Display.NONE); | |||
getWidget().setAriaInvalid(false); | |||
} | |||
getWidget().setAriaInvalid(getState().errorMessage != null); | |||
getWidget().setAriaRequired(isRequiredIndicatorVisible()); | |||
if (isReadOnly()) { |
@@ -254,7 +254,8 @@ public class FormLayoutConnector extends AbstractLayoutConnector | |||
} | |||
getWidget().table.updateError(component.getWidget(), | |||
component.getState().errorMessage, hideErrors); | |||
component.getState().errorMessage, | |||
component.getState().errorLevel, hideErrors); | |||
} | |||
@Override |
@@ -18,7 +18,9 @@ package com.vaadin.client.ui.link; | |||
import com.google.gwt.dom.client.Style.Display; | |||
import com.google.gwt.user.client.DOM; | |||
import com.vaadin.client.StyleConstants; | |||
import com.vaadin.client.VCaption; | |||
import com.vaadin.client.WidgetUtil.ErrorUtil; | |||
import com.vaadin.client.communication.StateChangeEvent; | |||
import com.vaadin.client.ui.AbstractComponentConnector; | |||
import com.vaadin.client.ui.Icon; | |||
@@ -70,20 +72,6 @@ public class LinkConnector extends AbstractComponentConnector { | |||
// Set link caption | |||
VCaption.setCaptionText(getWidget().captionElement, getState()); | |||
// handle error | |||
if (null != getState().errorMessage) { | |||
if (getWidget().errorIndicatorElement == null) { | |||
getWidget().errorIndicatorElement = DOM.createDiv(); | |||
DOM.setElementProperty(getWidget().errorIndicatorElement, | |||
"className", "v-errorindicator"); | |||
} | |||
DOM.insertChild(getWidget().getElement(), | |||
getWidget().errorIndicatorElement, 0); | |||
} else if (getWidget().errorIndicatorElement != null) { | |||
getWidget().errorIndicatorElement.getStyle() | |||
.setDisplay(Display.NONE); | |||
} | |||
if (getWidget().icon != null) { | |||
getWidget().anchor.removeChild(getWidget().icon.getElement()); | |||
getWidget().icon = null; |
@@ -16,7 +16,9 @@ | |||
package com.vaadin.client.ui.nativebutton; | |||
import com.google.gwt.user.client.DOM; | |||
import com.vaadin.client.StyleConstants; | |||
import com.vaadin.client.VCaption; | |||
import com.vaadin.client.WidgetUtil.ErrorUtil; | |||
import com.vaadin.client.communication.StateChangeEvent; | |||
import com.vaadin.client.ui.AbstractComponentConnector; | |||
import com.vaadin.client.ui.ConnectorFocusAndBlurHandler; | |||
@@ -55,23 +57,6 @@ public class NativeButtonConnector extends AbstractComponentConnector { | |||
// Set text | |||
VCaption.setCaptionText(getWidget(), getState()); | |||
// handle error | |||
if (null != getState().errorMessage) { | |||
if (getWidget().errorIndicatorElement == null) { | |||
getWidget().errorIndicatorElement = DOM.createSpan(); | |||
getWidget().errorIndicatorElement | |||
.setClassName("v-errorindicator"); | |||
} | |||
getWidget().getElement().insertBefore( | |||
getWidget().errorIndicatorElement, | |||
getWidget().captionElement); | |||
} else if (getWidget().errorIndicatorElement != null) { | |||
getWidget().getElement() | |||
.removeChild(getWidget().errorIndicatorElement); | |||
getWidget().errorIndicatorElement = null; | |||
} | |||
if (getWidget().icon != null) { | |||
getWidget().getElement().removeChild(getWidget().icon.getElement()); | |||
getWidget().icon = null; |
@@ -275,8 +275,9 @@ public abstract class AbstractOrderedLayoutConnector | |||
slot.setCaptionResizeListener(null); | |||
} | |||
slot.setCaption(caption, icon, styles, error, showError, required, | |||
enabled, child.getState().captionAsHtml); | |||
slot.setCaption(caption, icon, styles, error, | |||
child.getState().errorLevel, showError, required, enabled, | |||
child.getState().captionAsHtml); | |||
AriaHelper.handleInputRequired(child.getWidget(), required); | |||
AriaHelper.handleInputInvalid(child.getWidget(), showError); |
@@ -30,16 +30,19 @@ import com.google.gwt.user.client.ui.Widget; | |||
import com.vaadin.client.LayoutManager; | |||
import com.vaadin.client.StyleConstants; | |||
import com.vaadin.client.WidgetUtil; | |||
import com.vaadin.client.WidgetUtil.ErrorUtil; | |||
import com.vaadin.client.ui.FontIcon; | |||
import com.vaadin.client.ui.HasErrorIndicatorElement; | |||
import com.vaadin.client.ui.Icon; | |||
import com.vaadin.client.ui.ImageIcon; | |||
import com.vaadin.client.ui.layout.ElementResizeListener; | |||
import com.vaadin.shared.ui.AlignmentInfo; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
/** | |||
* Represents a slot which contains the actual widget in the layout. | |||
*/ | |||
public class Slot extends SimplePanel { | |||
public class Slot extends SimplePanel implements HasErrorIndicatorElement { | |||
private static final String ALIGN_CLASS_PREFIX = "v-align-"; | |||
@@ -493,6 +496,37 @@ public class Slot extends SimplePanel { | |||
public void setCaption(String captionText, Icon icon, List<String> styles, | |||
String error, boolean showError, boolean required, boolean enabled, | |||
boolean captionAsHtml) { | |||
setCaption(captionText, icon, styles, error, null, showError, required, | |||
enabled, captionAsHtml); | |||
} | |||
/** | |||
* Set the caption of the slot | |||
* | |||
* @param captionText | |||
* The text of the caption | |||
* @param icon | |||
* The icon | |||
* @param styles | |||
* The style names | |||
* @param error | |||
* The error message | |||
* @param errorLevel | |||
* The error level | |||
* @param showError | |||
* Should the error message be shown | |||
* @param required | |||
* Is the (field) required | |||
* @param enabled | |||
* Is the component enabled | |||
* @param captionAsHtml | |||
* true if the caption should be rendered as HTML, false | |||
* otherwise | |||
* @since 8.2 | |||
*/ | |||
public void setCaption(String captionText, Icon icon, List<String> styles, | |||
String error, ErrorLevel errorLevel, boolean showError, | |||
boolean required, boolean enabled, boolean captionAsHtml) { | |||
// TODO place for optimization: check if any of these have changed | |||
// since last time, and only run those changes | |||
@@ -583,14 +617,11 @@ public class Slot extends SimplePanel { | |||
// Error | |||
if (error != null && showError) { | |||
if (errorIcon == null) { | |||
errorIcon = DOM.createSpan(); | |||
errorIcon.setClassName("v-errorindicator"); | |||
} | |||
caption.appendChild(errorIcon); | |||
} else if (errorIcon != null) { | |||
errorIcon.removeFromParent(); | |||
errorIcon = null; | |||
setErrorIndicatorElementVisible(true); | |||
ErrorUtil.setErrorLevelStyle(getErrorIndicatorElement(), | |||
StyleConstants.STYLE_NAME_ERROR_INDICATOR, errorLevel); | |||
} else { | |||
setErrorIndicatorElementVisible(false); | |||
} | |||
if (caption != null) { | |||
@@ -799,4 +830,22 @@ public class Slot extends SimplePanel { | |||
return hasRelativeWidth(); | |||
} | |||
} | |||
@Override | |||
public Element getErrorIndicatorElement() { | |||
return errorIcon; | |||
} | |||
@Override | |||
public void setErrorIndicatorElementVisible(boolean visible) { | |||
if (visible) { | |||
if (errorIcon == null) { | |||
errorIcon = ErrorUtil.createErrorIndicatorElement(); | |||
} | |||
caption.appendChild(errorIcon); | |||
} else if (errorIcon != null) { | |||
errorIcon.removeFromParent(); | |||
errorIcon = null; | |||
} | |||
} | |||
} |
@@ -143,8 +143,6 @@ public class PanelConnector extends AbstractSingleComponentContainerConnector | |||
getWidget().setIconUri(null, client); | |||
} | |||
getWidget().setErrorIndicatorVisible(isErrorIndicatorVisible()); | |||
// We may have actions attached to this panel | |||
if (uidl.getChildCount() > 0) { | |||
final int cnt = uidl.getChildCount(); |
@@ -21,8 +21,10 @@ import com.google.gwt.event.dom.client.ClickHandler; | |||
import com.google.gwt.user.client.DOM; | |||
import com.google.gwt.user.client.Event; | |||
import com.vaadin.client.MouseEventDetailsBuilder; | |||
import com.vaadin.client.StyleConstants; | |||
import com.vaadin.client.VCaption; | |||
import com.vaadin.client.VTooltip; | |||
import com.vaadin.client.WidgetUtil.ErrorUtil; | |||
import com.vaadin.client.annotations.OnStateChange; | |||
import com.vaadin.client.communication.StateChangeEvent; | |||
import com.vaadin.client.ui.ConnectorFocusAndBlurHandler; | |||
@@ -67,7 +69,7 @@ public class CheckBoxConnector extends AbstractFieldConnector | |||
getWidget().errorIndicatorElement = DOM.createSpan(); | |||
getWidget().errorIndicatorElement.setInnerHTML(" "); | |||
DOM.setElementProperty(getWidget().errorIndicatorElement, | |||
"className", "v-errorindicator"); | |||
"className", StyleConstants.STYLE_NAME_ERROR_INDICATOR); | |||
DOM.appendChild(getWidget().getElement(), | |||
getWidget().errorIndicatorElement); | |||
DOM.sinkEvents(getWidget().errorIndicatorElement, | |||
@@ -75,6 +77,11 @@ public class CheckBoxConnector extends AbstractFieldConnector | |||
} else { | |||
getWidget().errorIndicatorElement.getStyle().clearDisplay(); | |||
} | |||
ErrorUtil.setErrorLevelStyle(getWidget().errorIndicatorElement, | |||
StyleConstants.STYLE_NAME_ERROR_INDICATOR, | |||
getState().errorLevel); | |||
} else if (getWidget().errorIndicatorElement != null) { | |||
getWidget().errorIndicatorElement.getStyle() | |||
.setDisplay(Display.NONE); |
@@ -126,6 +126,7 @@ public class FormConnector extends AbstractComponentContainerConnector | |||
if (null != getState().errorMessage) { | |||
getWidget().errorMessage.updateMessage(getState().errorMessage); | |||
getWidget().errorMessage.updateErrorLevel(getState().errorLevel); | |||
getWidget().errorMessage.setVisible(true); | |||
} else { | |||
getWidget().errorMessage.setVisible(false); |
@@ -21,9 +21,9 @@ import java.io.Serializable; | |||
import com.vaadin.data.Binder; | |||
import com.vaadin.server.AbstractErrorMessage; | |||
import com.vaadin.server.ErrorMessage; | |||
import com.vaadin.server.ErrorMessage.ErrorLevel; | |||
import com.vaadin.server.ErrorMessageProducer; | |||
import com.vaadin.server.UserError; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
import com.vaadin.v7.data.Validator.InvalidValueException; | |||
/** |
@@ -22,10 +22,10 @@ import com.vaadin.data.Binder; | |||
import com.vaadin.server.AbstractErrorMessage; | |||
import com.vaadin.server.AbstractErrorMessage.ContentMode; | |||
import com.vaadin.server.ErrorMessage; | |||
import com.vaadin.server.ErrorMessage.ErrorLevel; | |||
import com.vaadin.server.ErrorMessageProducer; | |||
import com.vaadin.server.UserError; | |||
import com.vaadin.server.VaadinServlet; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
/** | |||
* Interface that implements a method for validating if an {@link Object} is |
@@ -58,6 +58,7 @@ import com.vaadin.server.VaadinSession; | |||
import com.vaadin.shared.MouseEventDetails; | |||
import com.vaadin.shared.Registration; | |||
import com.vaadin.shared.data.sort.SortDirection; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
import com.vaadin.shared.util.SharedUtil; | |||
import com.vaadin.ui.AbstractComponent; | |||
import com.vaadin.ui.Component; |
@@ -29,12 +29,12 @@ import org.jsoup.parser.Tag; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import com.vaadin.server.ErrorMessage.ErrorLevel; | |||
import com.vaadin.server.ExternalResource; | |||
import com.vaadin.server.FileResource; | |||
import com.vaadin.server.Responsive; | |||
import com.vaadin.server.ThemeResource; | |||
import com.vaadin.server.UserError; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
import com.vaadin.tests.design.DeclarativeTestBase; | |||
import com.vaadin.ui.AbstractComponent; | |||
import com.vaadin.ui.Label; |
@@ -21,6 +21,8 @@ import java.io.StringWriter; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
/** | |||
* Base class for component error messages. | |||
* |
@@ -19,6 +19,8 @@ package com.vaadin.server; | |||
import java.util.Collection; | |||
import java.util.Iterator; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
/** | |||
* Class for combining multiple error messages together. | |||
* | |||
@@ -37,7 +39,7 @@ public class CompositeErrorMessage extends AbstractErrorMessage { | |||
*/ | |||
public CompositeErrorMessage(ErrorMessage... errorMessages) { | |||
super(null); | |||
setErrorLevel(ErrorLevel.INFORMATION); | |||
setErrorLevel(ErrorLevel.INFO); | |||
for (ErrorMessage errorMessage : errorMessages) { | |||
addErrorMessage(errorMessage); | |||
@@ -60,7 +62,7 @@ public class CompositeErrorMessage extends AbstractErrorMessage { | |||
public CompositeErrorMessage( | |||
Collection<? extends ErrorMessage> errorMessages) { | |||
super(null); | |||
setErrorLevel(ErrorLevel.INFORMATION); | |||
setErrorLevel(ErrorLevel.INFO); | |||
for (ErrorMessage errorMessage : errorMessages) { | |||
addErrorMessage(errorMessage); |
@@ -18,6 +18,8 @@ package com.vaadin.server; | |||
import java.io.Serializable; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
/** | |||
* Interface for rendering error messages to terminal. All the visible errors | |||
* shown to user must implement this interface. | |||
@@ -27,66 +29,11 @@ import java.io.Serializable; | |||
*/ | |||
public interface ErrorMessage extends Serializable { | |||
public enum ErrorLevel { | |||
/** | |||
* Error code for informational messages. | |||
*/ | |||
INFORMATION("info", 0), | |||
/** | |||
* Error code for warning messages. | |||
*/ | |||
WARNING("warning", 1), | |||
/** | |||
* Error code for regular error messages. | |||
*/ | |||
ERROR("error", 2), | |||
/** | |||
* Error code for critical error messages. | |||
*/ | |||
CRITICAL("critical", 3), | |||
/** | |||
* Error code for system errors and bugs. | |||
*/ | |||
SYSTEMERROR("system", 4); | |||
String text; | |||
int errorLevel; | |||
private ErrorLevel(String text, int errorLevel) { | |||
this.text = text; | |||
this.errorLevel = errorLevel; | |||
} | |||
/** | |||
* Textual representation for server-client communication of level | |||
* | |||
* @return String for error severity | |||
*/ | |||
public String getText() { | |||
return text; | |||
} | |||
/** | |||
* Integer representation of error severity for comparison | |||
* | |||
* @return integer for error severity | |||
*/ | |||
public int intValue() { | |||
return errorLevel; | |||
} | |||
@Override | |||
public String toString() { | |||
return text; | |||
} | |||
} | |||
/** | |||
* @deprecated As of 7.0, use {@link ErrorLevel#SYSTEMERROR} instead | |||
* @deprecated As of 7.0, use {@link ErrorLevel#SYSTEM} instead | |||
*/ | |||
@Deprecated | |||
public static final ErrorLevel SYSTEMERROR = ErrorLevel.SYSTEMERROR; | |||
public static final ErrorLevel SYSTEMERROR = ErrorLevel.SYSTEM; | |||
/** | |||
* @deprecated As of 7.0, use {@link ErrorLevel#CRITICAL} instead | |||
@@ -108,10 +55,10 @@ public interface ErrorMessage extends Serializable { | |||
public static final ErrorLevel WARNING = ErrorLevel.WARNING; | |||
/** | |||
* @deprecated As of 7.0, use {@link ErrorLevel#INFORMATION} instead | |||
* @deprecated As of 7.0, use {@link ErrorLevel#INFO} instead | |||
*/ | |||
@Deprecated | |||
public static final ErrorLevel INFORMATION = ErrorLevel.INFORMATION; | |||
public static final ErrorLevel INFORMATION = ErrorLevel.INFO; | |||
/** | |||
* Gets the errors level. |
@@ -16,6 +16,8 @@ | |||
package com.vaadin.server; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
/** | |||
* <code>SystemError</code> is an error message for a problem caused by error in | |||
* system, not the user application code. The system error can contain technical | |||
@@ -39,7 +41,7 @@ public class SystemError extends AbstractErrorMessage { | |||
*/ | |||
public SystemError(String message) { | |||
super(message); | |||
setErrorLevel(ErrorLevel.SYSTEMERROR); | |||
setErrorLevel(ErrorLevel.SYSTEM); | |||
setMode(ContentMode.HTML); | |||
setMessage(getHtmlMessage()); | |||
} |
@@ -16,6 +16,8 @@ | |||
package com.vaadin.server; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
/** | |||
* <code>UserError</code> is a controlled error occurred in application. User | |||
* errors are occur in normal usage of the application and guide the user. |
@@ -45,7 +45,6 @@ import com.vaadin.server.AbstractClientConnector; | |||
import com.vaadin.server.ClientConnector; | |||
import com.vaadin.server.ComponentSizeValidator; | |||
import com.vaadin.server.ErrorMessage; | |||
import com.vaadin.server.ErrorMessage.ErrorLevel; | |||
import com.vaadin.server.Extension; | |||
import com.vaadin.server.Resource; | |||
import com.vaadin.server.Responsive; | |||
@@ -62,6 +61,7 @@ import com.vaadin.shared.MouseEventDetails; | |||
import com.vaadin.shared.Registration; | |||
import com.vaadin.shared.ui.ComponentStateUtil; | |||
import com.vaadin.shared.ui.ContentMode; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
import com.vaadin.shared.util.SharedUtil; | |||
import com.vaadin.ui.declarative.DesignAttributeHandler; | |||
import com.vaadin.ui.declarative.DesignContext; | |||
@@ -723,8 +723,10 @@ public abstract class AbstractComponent extends AbstractClientConnector | |||
ErrorMessage error = getErrorMessage(); | |||
if (null != error) { | |||
getState().errorMessage = error.getFormattedHtmlMessage(); | |||
getState().errorLevel = error.getErrorLevel(); | |||
} else { | |||
getState().errorMessage = null; | |||
getState().errorLevel = null; | |||
} | |||
} | |||
@@ -1314,9 +1314,15 @@ public class TabSheet extends AbstractComponentContainer | |||
public void setComponentError(ErrorMessage componentError) { | |||
this.componentError = componentError; | |||
String formattedHtmlMessage = componentError != null | |||
? componentError.getFormattedHtmlMessage() : null; | |||
tabState.componentError = formattedHtmlMessage; | |||
if (componentError != null) { | |||
tabState.componentError = componentError | |||
.getFormattedHtmlMessage(); | |||
tabState.componentErrorLevel = componentError.getErrorLevel(); | |||
} else { | |||
tabState.componentError = null; | |||
tabState.componentErrorLevel = null; | |||
} | |||
markAsDirty(); | |||
} |
@@ -28,13 +28,13 @@ import org.jsoup.parser.Tag; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import com.vaadin.server.ErrorMessage.ErrorLevel; | |||
import com.vaadin.shared.ui.ContentMode; | |||
import com.vaadin.server.ExternalResource; | |||
import com.vaadin.server.FileResource; | |||
import com.vaadin.server.Responsive; | |||
import com.vaadin.server.ThemeResource; | |||
import com.vaadin.server.UserError; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
import com.vaadin.tests.design.DeclarativeTestBase; | |||
import com.vaadin.ui.AbstractComponent; | |||
import com.vaadin.ui.Button; |
@@ -24,11 +24,11 @@ import java.util.Locale; | |||
import org.junit.Test; | |||
import com.vaadin.server.ErrorMessage.ErrorLevel; | |||
import com.vaadin.server.ExternalResource; | |||
import com.vaadin.server.FileResource; | |||
import com.vaadin.server.ThemeResource; | |||
import com.vaadin.server.UserError; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
import com.vaadin.tests.design.DeclarativeTestBase; | |||
import com.vaadin.ui.AbstractComponent; | |||
import com.vaadin.ui.declarative.DesignContext; |
@@ -21,6 +21,7 @@ import java.util.List; | |||
import com.vaadin.shared.annotations.NoLayout; | |||
import com.vaadin.shared.communication.SharedState; | |||
import com.vaadin.shared.ui.ContentMode; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
/** | |||
* Default shared state implementation for AbstractComponent. | |||
@@ -43,9 +44,15 @@ public class AbstractComponentState extends SharedState { | |||
public String id = null; | |||
public String primaryStyleName = null; | |||
// HTML formatted error message for the component | |||
// TODO this could be an object with more information, but currently the UI | |||
// only uses the message | |||
/** HTML formatted error message for the component */ | |||
public String errorMessage = null; | |||
/** | |||
* Level of error | |||
* | |||
* @since 8.2 | |||
*/ | |||
public ErrorLevel errorLevel = null; | |||
public boolean captionAsHtml = false; | |||
} |
@@ -0,0 +1,58 @@ | |||
/* | |||
* Copyright 2000-2016 Vaadin Ltd. | |||
* | |||
* 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. | |||
*/ | |||
package com.vaadin.shared.ui; | |||
/** | |||
* Represents the error levels displayed on components. | |||
* @author Vaadin Ltd | |||
* @since | |||
*/ | |||
public enum ErrorLevel { | |||
/** | |||
* Error level for informational messages. | |||
*/ | |||
INFO, | |||
/** | |||
* Error level for warning messages. | |||
*/ | |||
WARNING, | |||
/** | |||
* Error level for regular messages. | |||
*/ | |||
ERROR, | |||
/** | |||
* Error level for critical messages. | |||
*/ | |||
CRITICAL, | |||
/** | |||
* Error level for system errors and bugs. | |||
*/ | |||
SYSTEM; | |||
/** | |||
* Integer representation of error severity for comparison | |||
* | |||
* @return integer for error severity | |||
*/ | |||
public int intValue() { | |||
return ordinal(); | |||
} | |||
} |
@@ -19,6 +19,8 @@ import java.io.Serializable; | |||
import com.vaadin.shared.ui.ContentMode; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
/** | |||
* Shared state of a single tab in a Tabsheet or an Accordion. | |||
* | |||
@@ -36,6 +38,13 @@ public class TabState implements Serializable { | |||
public String styleName; | |||
public String key; | |||
public String componentError; | |||
/** | |||
* Represents the level of error on a tab. | |||
* | |||
* @since 8.2 | |||
*/ | |||
public ErrorLevel componentErrorLevel; | |||
public String id; | |||
public String iconAltText; | |||
@@ -1 +1 @@ | |||
Subproject commit 3a4a26065d36ac5fb706c159f1dd757fb52bf8eb | |||
Subproject commit 37f67cd836df7d34469f55298bb167696338f2a5 |
@@ -35,6 +35,61 @@ | |||
} | |||
} | |||
.#{$primary-stylename}-error-info { | |||
.#{$primary-stylename}-input { | |||
@include valo-textfield-error-level-info-style; | |||
} | |||
.#{$primary-stylename}-button { | |||
color: $v-error-indicator-level-info-color; | |||
border-color: $v-error-indicator-level-info-color; | |||
} | |||
} | |||
.#{$primary-stylename}-error-warning { | |||
.#{$primary-stylename}-input { | |||
@include valo-textfield-error-level-warning-style; | |||
} | |||
.#{$primary-stylename}-button { | |||
color: $v-error-indicator-level-warning-color; | |||
border-color: $v-error-indicator-level-warning-color; | |||
} | |||
} | |||
.#{$primary-stylename}-error-error { | |||
.#{$primary-stylename}-input { | |||
@include valo-textfield-error-level-error-style; | |||
} | |||
.#{$primary-stylename}-button { | |||
color: $v-error-indicator-level-error-color; | |||
border-color: $v-error-indicator-level-error-color; | |||
} | |||
} | |||
.#{$primary-stylename}-error-critical { | |||
.#{$primary-stylename}-input { | |||
@include valo-textfield-error-level-critical-style; | |||
} | |||
.#{$primary-stylename}-button { | |||
color: $v-error-indicator-level-critical-color; | |||
border-color: $v-error-indicator-level-critical-color; | |||
} | |||
} | |||
.#{$primary-stylename}-error-system { | |||
.#{$primary-stylename}-input { | |||
@include valo-textfield-error-level-system-style; | |||
} | |||
.#{$primary-stylename}-button { | |||
color: $v-error-indicator-level-system-color; | |||
border-color: $v-error-indicator-level-system-color; | |||
} | |||
} | |||
.#{$primary-stylename}-suggestpopup { | |||
@include valo-combobox-popup-style; | |||
} |
@@ -25,6 +25,61 @@ | |||
} | |||
} | |||
.#{$primary-stylename}-error-info { | |||
.#{$primary-stylename}-textfield { | |||
@include valo-textfield-error-level-info-style; | |||
} | |||
.#{$primary-stylename}-button { | |||
color: $v-error-indicator-level-info-color; | |||
border-color: $v-error-indicator-level-info-color; | |||
} | |||
} | |||
.#{$primary-stylename}-error-warning { | |||
.#{$primary-stylename}-textfield { | |||
@include valo-textfield-error-level-warning-style; | |||
} | |||
.#{$primary-stylename}-button { | |||
color: $v-error-indicator-level-warning-color; | |||
border-color: $v-error-indicator-level-warning-color; | |||
} | |||
} | |||
.#{$primary-stylename}-error-error { | |||
.#{$primary-stylename}-textfield { | |||
@include valo-textfield-error-level-error-style; | |||
} | |||
.#{$primary-stylename}-button { | |||
color: $v-error-indicator-level-error-color; | |||
border-color: $v-error-indicator-level-error-color; | |||
} | |||
} | |||
.#{$primary-stylename}-error-critical { | |||
.#{$primary-stylename}-textfield { | |||
@include valo-textfield-error-level-critical-style; | |||
} | |||
.#{$primary-stylename}-button { | |||
color: $v-error-indicator-level-critical-color; | |||
border-color: $v-error-indicator-level-critical-color; | |||
} | |||
} | |||
.#{$primary-stylename}-error-system { | |||
.#{$primary-stylename}-textfield { | |||
@include valo-textfield-error-level-system-style; | |||
} | |||
.#{$primary-stylename}-button { | |||
color: $v-error-indicator-level-system-color; | |||
border-color: $v-error-indicator-level-system-color; | |||
} | |||
} | |||
// Different widths for different resolutions | |||
.#{$primary-stylename}-full { | |||
width: round($v-font-size * 15); |
@@ -70,6 +70,25 @@ $v-textfield-disabled-opacity: $v-disabled-opacity !default; | |||
@include valo-textfield-error-style; | |||
} | |||
.#{$primary-stylename}-error-info { | |||
@include valo-textfield-error-level-info-style; | |||
} | |||
.#{$primary-stylename}-error-warning { | |||
@include valo-textfield-error-level-warning-style; | |||
} | |||
.#{$primary-stylename}-error-error { | |||
@include valo-textfield-error-level-error-style; | |||
} | |||
.#{$primary-stylename}-error-critical { | |||
@include valo-textfield-error-level-critical-style; | |||
} | |||
.#{$primary-stylename}-error-system { | |||
@include valo-textfield-error-level-system-style; | |||
} | |||
@if $include-additional-styles { | |||
.#{$primary-stylename}-borderless { | |||
@@ -319,13 +338,58 @@ $v-textfield-disabled-opacity: $v-disabled-opacity !default; | |||
* | |||
* @group textfield | |||
*/ | |||
@mixin valo-textfield-error-style { | |||
border-color: $v-error-indicator-color !important; | |||
$bg: scale-color($v-error-indicator-color, $lightness: 98%); | |||
@mixin valo-textfield-error-style($indicator-color: $v-error-indicator-color) { | |||
border-color: $indicator-color !important; | |||
$bg: scale-color($indicator-color, $lightness: 98%); | |||
background: $bg; | |||
color: valo-font-color($bg); | |||
} | |||
/** | |||
* Outputs the styles for a text field error state with error level 'info'. | |||
* | |||
* @group textfield | |||
*/ | |||
@mixin valo-textfield-error-level-info-style { | |||
@include valo-textfield-error-style($v-error-indicator-level-info-color); | |||
} | |||
/** | |||
* Outputs the styles for a text field error state with error level 'warning'. | |||
* | |||
* @group textfield | |||
*/ | |||
@mixin valo-textfield-error-level-warning-style { | |||
@include valo-textfield-error-style($v-error-indicator-level-warning-color); | |||
} | |||
/** | |||
* Outputs the styles for a text field error state with error level 'error'. | |||
* | |||
* @group textfield | |||
*/ | |||
@mixin valo-textfield-error-level-error-style { | |||
@include valo-textfield-error-style($v-error-indicator-level-error-color); | |||
} | |||
/** | |||
* Outputs the styles for a text field error state with error level 'critical'. | |||
* | |||
* @group textfield | |||
*/ | |||
@mixin valo-textfield-error-level-critical-style { | |||
@include valo-textfield-error-style($v-error-indicator-level-critical-color); | |||
} | |||
/** | |||
* Outputs the styles for a text field error state with error level 'system'. | |||
* | |||
* @group textfield | |||
*/ | |||
@mixin valo-textfield-error-level-system-style { | |||
@include valo-textfield-error-style($v-error-indicator-level-system-color); | |||
} | |||
/** | |||
* Outputs the selectors and styles for an inline-icon style for a text field. Included indipendently (i.e. not enclosed with a parent text field selector). |
@@ -85,6 +85,40 @@ | |||
} | |||
} | |||
.#{$primary-stylename}-error-info { | |||
.#{$primary-stylename}-options, | |||
.#{$primary-stylename}-selections { | |||
@include valo-textfield-error-level-info-style; | |||
} | |||
} | |||
.#{$primary-stylename}-error-warning { | |||
.#{$primary-stylename}-options, | |||
.#{$primary-stylename}-selections { | |||
@include valo-textfield-error-level-warning-style; | |||
} | |||
} | |||
.#{$primary-stylename}-error-error { | |||
.#{$primary-stylename}-options, | |||
.#{$primary-stylename}-selections { | |||
@include valo-textfield-error-level-error-style; | |||
} | |||
} | |||
.#{$primary-stylename}-error-critical { | |||
.#{$primary-stylename}-options, | |||
.#{$primary-stylename}-selections { | |||
@include valo-textfield-error-level-critical-style; | |||
} | |||
} | |||
.#{$primary-stylename}-error-system { | |||
.#{$primary-stylename}-options, | |||
.#{$primary-stylename}-selections { | |||
@include valo-textfield-error-level-system-style; | |||
} | |||
} | |||
} | |||
@@ -313,6 +313,26 @@ $valo-shared-pathPrefix: null; | |||
@include valo-error-indicator-style; | |||
} | |||
.v-errorindicator-info { | |||
@include valo-error-indicator-style($indicator-color: $v-error-indicator-level-info-color); | |||
} | |||
.v-errorindicator-warning { | |||
@include valo-error-indicator-style($indicator-color: $v-error-indicator-level-warning-color); | |||
} | |||
.v-errorindicator-error { | |||
@include valo-error-indicator-style($indicator-color: $v-error-indicator-level-error-color); | |||
} | |||
.v-errorindicator-critical { | |||
@include valo-error-indicator-style($indicator-color: $v-error-indicator-level-critical-color); | |||
} | |||
.v-errorindicator-system { | |||
@include valo-error-indicator-style($indicator-color: $v-error-indicator-level-system-color); | |||
} | |||
.v-required-field-indicator { | |||
color: $v-required-field-indicator-color; | |||
padding: 0 .2em; | |||
@@ -366,8 +386,8 @@ $valo-shared-pathPrefix: null; | |||
* | |||
* @requires {mixin} valo-error-indicator-icon-style by default | |||
*/ | |||
@mixin valo-error-indicator-style ($is-pseudo-element: false) { | |||
color: $v-error-indicator-color; | |||
@mixin valo-error-indicator-style ($is-pseudo-element: false, $indicator-color: $v-error-indicator-color) { | |||
color: $indicator-color; | |||
font-weight: 600; | |||
width: ceil($v-unit-size/2); | |||
text-align: center; |
@@ -62,6 +62,46 @@ $v-tooltip-error-message-background-color: #fff !default; | |||
*/ | |||
$v-tooltip-error-message-font-color: $v-error-indicator-color !default; | |||
/** | |||
* The font color for error tooltips for level 'info'. | |||
* | |||
* @type color | |||
* @group tooltip | |||
*/ | |||
$v-tooltip-error-message-level-info-font-color: $v-error-indicator-level-info-color !default; | |||
/** | |||
* The font color for error tooltips for level 'warning'. | |||
* | |||
* @type color | |||
* @group tooltip | |||
*/ | |||
$v-tooltip-error-message-level-warning-font-color: $v-error-indicator-level-warning-color !default; | |||
/** | |||
* The font color for error tooltips for level 'error'. | |||
* | |||
* @type color | |||
* @group tooltip | |||
*/ | |||
$v-tooltip-error-message-level-error-font-color: $v-error-indicator-level-error-color !default; | |||
/** | |||
* The font color for error tooltips for level 'critical'. | |||
* | |||
* @type color | |||
* @group tooltip | |||
*/ | |||
$v-tooltip-error-message-level-critical-font-color: $v-error-indicator-level-critical-color !default; | |||
/** | |||
* The font color for error tooltips for level 'system'. | |||
* | |||
* @type color | |||
* @group tooltip | |||
*/ | |||
$v-tooltip-error-message-level-system-font-color: $v-error-indicator-level-system-color !default; | |||
/** | |||
* The corner radius for tooltips. | |||
* | |||
@@ -100,6 +140,26 @@ $v-tooltip-border-radius: $v-border-radius - 1px !default; | |||
} | |||
} | |||
.v-errormessage-info { | |||
color: $v-tooltip-error-message-level-info-font-color; | |||
} | |||
.v-errormessage-warning { | |||
color: $v-tooltip-error-message-level-warning-font-color; | |||
} | |||
.v-errormessage-error { | |||
color: $v-tooltip-error-message-level-error-font-color; | |||
} | |||
.v-errormessage-critical { | |||
color: $v-tooltip-error-message-level-critical-font-color; | |||
} | |||
.v-errormessage-system { | |||
color: $v-tooltip-error-message-level-system-font-color; | |||
} | |||
.v-tooltip-text { | |||
max-height: 10em; | |||
overflow: auto; |
@@ -206,6 +206,46 @@ $v-disabled-opacity: 0.5 !default; | |||
*/ | |||
$v-selection-color: $v-focus-color !default; | |||
/** | |||
* Color of the component error indication for 'info' error level. | |||
* @group color | |||
* @type color | |||
*/ | |||
$v-error-indicator-level-info-color: #00a7f5 !default; | |||
/** | |||
* Color of the component error indication for 'warning' error level. | |||
* @group color | |||
* @type color | |||
*/ | |||
$v-error-indicator-level-warning-color: #fc9c00 !default; | |||
/** | |||
* Color of the component error indication for 'error' error level. | |||
* @group color | |||
* @type color | |||
*/ | |||
$v-error-indicator-level-error-color: #ed473b !default; | |||
/** | |||
* Color of the component error indication for 'critical' error level. | |||
* @group color | |||
* @type color | |||
*/ | |||
$v-error-indicator-level-critical-color: #fa007d !default; | |||
/** | |||
* Color of the component error indication for 'system' error level. | |||
* @group color | |||
* @type color | |||
*/ | |||
$v-error-indicator-level-system-color: #bb00ff !default; | |||
/** | |||
* Color of the component error indicator and other error indications, such as the | |||
* error style notification. | |||
@@ -213,7 +253,7 @@ $v-selection-color: $v-focus-color !default; | |||
* @group color | |||
* @type color | |||
*/ | |||
$v-error-indicator-color: #ed473b !default; | |||
$v-error-indicator-color: $v-error-indicator-level-error-color !default; | |||
/** | |||
* Color of the required indicator in field components. |
@@ -0,0 +1,210 @@ | |||
package com.vaadin.tests.components; | |||
import java.util.Arrays; | |||
import com.vaadin.annotations.Theme; | |||
import com.vaadin.server.AbstractErrorMessage; | |||
import com.vaadin.server.ErrorMessage; | |||
import com.vaadin.server.ExternalResource; | |||
import com.vaadin.server.UserError; | |||
import com.vaadin.server.VaadinRequest; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
import com.vaadin.ui.Accordion; | |||
import com.vaadin.ui.Button; | |||
import com.vaadin.ui.CheckBox; | |||
import com.vaadin.ui.ComboBox; | |||
import com.vaadin.ui.DateField; | |||
import com.vaadin.ui.FormLayout; | |||
import com.vaadin.ui.HorizontalLayout; | |||
import com.vaadin.ui.Label; | |||
import com.vaadin.ui.Link; | |||
import com.vaadin.ui.NativeButton; | |||
import com.vaadin.ui.Panel; | |||
import com.vaadin.ui.TabSheet; | |||
import com.vaadin.ui.TextField; | |||
import com.vaadin.ui.TwinColSelect; | |||
import com.vaadin.ui.themes.ValoTheme; | |||
@Theme("valo") | |||
public class ErrorLevels extends AbstractTestUI { | |||
private ComboBox<ErrorLevel> errorLevels; | |||
private Button button; | |||
private Button borderlessButton; | |||
private Link link; | |||
private ComboBox<String> comboBox; | |||
private TextField textField; | |||
private TextField textFieldBorderless; | |||
private TabSheet tabSheet; | |||
private Accordion accordion; | |||
private CheckBox checkBox; | |||
private NativeButton nativeButton; | |||
private FormLayout formLayout; | |||
private TextField formLayoutTextField; | |||
private Panel panel; | |||
private DateField dateField; | |||
private TwinColSelect twinColSelect; | |||
private com.vaadin.v7.ui.ComboBox comboBoxCompat; | |||
private com.vaadin.v7.ui.TextField textFieldCompat; | |||
private com.vaadin.v7.ui.CheckBox checkBoxCompat; | |||
private com.vaadin.v7.ui.DateField dateFieldCompat; | |||
private com.vaadin.v7.ui.TwinColSelect twinColSelectCompat; | |||
@Override | |||
protected void setup(VaadinRequest request) { | |||
errorLevels = new ComboBox<>("Error level", | |||
Arrays.asList(ErrorLevel.values())); | |||
errorLevels.setEmptySelectionAllowed(false); | |||
errorLevels.setValue(ErrorLevel.ERROR); | |||
errorLevels.addValueChangeListener(event -> setErrorMessages()); | |||
addComponent(errorLevels); | |||
Label subtitle = new Label("Components"); | |||
subtitle.setStyleName(ValoTheme.LABEL_H3); | |||
addComponent(subtitle); | |||
// Button | |||
button = new Button("Button"); | |||
borderlessButton = new Button("Borderless button"); | |||
borderlessButton.setStyleName(ValoTheme.BUTTON_BORDERLESS); | |||
addComponent(new HorizontalLayout(button, borderlessButton)); | |||
// Native button | |||
nativeButton = new NativeButton("Native button"); | |||
addComponent(nativeButton); | |||
// Link | |||
link = new Link("Link", new ExternalResource("#")); | |||
addComponent(link); | |||
// Combo box | |||
comboBox = new ComboBox<>("Combo box"); | |||
addComponent(comboBox); | |||
// Text field | |||
textField = new TextField("Text field"); | |||
textField.setValue("text"); | |||
textFieldBorderless = new TextField("Borderless text field"); | |||
textFieldBorderless.setStyleName(ValoTheme.TEXTFIELD_BORDERLESS); | |||
textFieldBorderless.setValue("text"); | |||
addComponent(new HorizontalLayout(textField, textFieldBorderless)); | |||
// Date field | |||
dateField = new DateField("Date field"); | |||
addComponent(dateField); | |||
// Check box | |||
checkBox = new CheckBox("Check box"); | |||
addComponent(checkBox); | |||
// Tab sheet | |||
tabSheet = new TabSheet(); | |||
tabSheet.addTab(new Label("Label1"), "Tab1"); | |||
tabSheet.addTab(new Label("Label2"), "Tab2"); | |||
tabSheet.setWidth("400px"); | |||
addComponent(tabSheet); | |||
// Accordion | |||
accordion = new Accordion(); | |||
accordion.addTab(new Label("Label1"), "Tab1"); | |||
accordion.addTab(new Label("Label2"), "Tab2"); | |||
accordion.setWidth("400px"); | |||
addComponent(accordion); | |||
// Form layout | |||
formLayout = new FormLayout(); | |||
formLayout.setWidth("400px"); | |||
formLayoutTextField = new TextField("Form layout text field"); | |||
formLayout.addComponent(formLayoutTextField); | |||
addComponent(formLayout); | |||
// Panel | |||
panel = new Panel(); | |||
panel.setContent(new Label("Panel")); | |||
panel.setWidth("400px"); | |||
addComponent(panel); | |||
// TwinColSelect | |||
twinColSelect = new TwinColSelect("Twin col select"); | |||
addComponent(twinColSelect); | |||
Label subtitleCompat = new Label("Compatibility components"); | |||
subtitleCompat.setStyleName(ValoTheme.LABEL_H3); | |||
addComponent(subtitleCompat); | |||
// Compatibility combo box | |||
comboBoxCompat = new com.vaadin.v7.ui.ComboBox( | |||
"Compatibility combo box"); | |||
addComponent(comboBoxCompat); | |||
// Compatibility text field | |||
textFieldCompat = new com.vaadin.v7.ui.TextField( | |||
"Compatibility text field"); | |||
textFieldCompat.setValue("text"); | |||
// Compatibility check box | |||
checkBoxCompat = new com.vaadin.v7.ui.CheckBox("Check box"); | |||
addComponent(checkBoxCompat); | |||
// Compatibility date field | |||
dateFieldCompat = new com.vaadin.v7.ui.DateField("Date field"); | |||
addComponent(dateFieldCompat); | |||
// Compatibility twin col select | |||
twinColSelectCompat = new com.vaadin.v7.ui.TwinColSelect( | |||
"Twin col select"); | |||
addComponent(twinColSelectCompat); | |||
setErrorMessages(); | |||
getLayout().setSpacing(true); | |||
} | |||
private void setErrorMessages() { | |||
button.setComponentError(createErrorMessage("Button error")); | |||
borderlessButton.setComponentError( | |||
createErrorMessage("Borderless button error")); | |||
link.setComponentError(createErrorMessage("Link error")); | |||
comboBox.setComponentError(createErrorMessage("ComboBox error")); | |||
textField.setComponentError(createErrorMessage("Text field error")); | |||
textFieldBorderless.setComponentError( | |||
createErrorMessage("Borderless text field error")); | |||
tabSheet.setComponentError(createErrorMessage("Tab sheet error")); | |||
tabSheet.getTab(0).setComponentError(createErrorMessage("Tab error")); | |||
accordion.setComponentError(createErrorMessage("Accordion error")); | |||
accordion.getTab(0).setComponentError(createErrorMessage("Tab error")); | |||
checkBox.setComponentError(createErrorMessage("Check box error")); | |||
nativeButton | |||
.setComponentError(createErrorMessage("Native button error")); | |||
formLayout.setComponentError(createErrorMessage("Form layout error")); | |||
formLayoutTextField.setComponentError( | |||
createErrorMessage("Form layout text field error")); | |||
panel.setComponentError(createErrorMessage("Panel error")); | |||
dateField.setComponentError(createErrorMessage("Date field error")); | |||
twinColSelect | |||
.setComponentError(createErrorMessage("Twin col select error")); | |||
comboBoxCompat.setComponentError( | |||
createErrorMessage("Compatibility combo box error")); | |||
textFieldCompat.setComponentError( | |||
createErrorMessage("Compatibility text field error")); | |||
checkBoxCompat.setComponentError( | |||
createErrorMessage("Compatibility check box error")); | |||
dateFieldCompat.setComponentError( | |||
createErrorMessage("Compatibility date field error")); | |||
twinColSelectCompat.setComponentError( | |||
createErrorMessage("Compatibility twin col select error")); | |||
} | |||
private ErrorMessage createErrorMessage(String text) { | |||
return new UserError(text, AbstractErrorMessage.ContentMode.TEXT, | |||
errorLevels.getValue()); | |||
} | |||
} |
@@ -20,11 +20,11 @@ import com.vaadin.icons.VaadinIcons; | |||
import com.vaadin.navigator.View; | |||
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; | |||
import com.vaadin.server.AbstractErrorMessage; | |||
import com.vaadin.server.ErrorMessage.ErrorLevel; | |||
import com.vaadin.server.Page; | |||
import com.vaadin.server.UserError; | |||
import com.vaadin.shared.Position; | |||
import com.vaadin.shared.ui.ContentMode; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
import com.vaadin.ui.Alignment; | |||
import com.vaadin.ui.Button; | |||
import com.vaadin.ui.Button.ClickEvent; |
@@ -0,0 +1,160 @@ | |||
package com.vaadin.tests.components; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import org.junit.Assert; | |||
import org.junit.Test; | |||
import org.openqa.selenium.Keys; | |||
import org.openqa.selenium.WebElement; | |||
import com.vaadin.client.StyleConstants; | |||
import com.vaadin.shared.ui.ErrorLevel; | |||
import com.vaadin.testbench.By; | |||
import com.vaadin.testbench.elements.AccordionElement; | |||
import com.vaadin.testbench.elements.ButtonElement; | |||
import com.vaadin.testbench.elements.CheckBoxElement; | |||
import com.vaadin.testbench.elements.ComboBoxElement; | |||
import com.vaadin.testbench.elements.DateFieldElement; | |||
import com.vaadin.testbench.elements.FormLayoutElement; | |||
import com.vaadin.testbench.elements.LinkElement; | |||
import com.vaadin.testbench.elements.NativeButtonElement; | |||
import com.vaadin.testbench.elements.PanelElement; | |||
import com.vaadin.testbench.elements.TabSheetElement; | |||
import com.vaadin.testbench.elements.TwinColSelectElement; | |||
import com.vaadin.testbench.parallel.BrowserUtil; | |||
import com.vaadin.tests.tb3.SingleBrowserTest; | |||
public class ErrorLevelsTest extends SingleBrowserTest { | |||
private ComboBoxElement errorLevelSelector; | |||
@Override | |||
public void setup() throws Exception { | |||
super.setup(); | |||
openTestURL(); | |||
errorLevelSelector = $(ComboBoxElement.class).first(); | |||
} | |||
@Test | |||
public void testErrorIndicatorsClassName() { | |||
ErrorLevel errorLevel = ErrorLevel.WARNING; | |||
selectErrorLevel(errorLevel); | |||
List<WebElement> errorIndicators = findElements( | |||
By.className(StyleConstants.STYLE_NAME_ERROR_INDICATOR)); | |||
for (WebElement errorIndicator : errorIndicators) { | |||
assertHasRightClassNames(errorIndicator, | |||
StyleConstants.STYLE_NAME_ERROR_INDICATOR, errorLevel); | |||
} | |||
} | |||
@Test | |||
public void testComponentsClassName() { | |||
ErrorLevel errorLevel = ErrorLevel.WARNING; | |||
selectErrorLevel(errorLevel); | |||
// Button | |||
ButtonElement buttonElement = $(ButtonElement.class).first(); | |||
assertHasRightClassNames(buttonElement, "v-button-error", errorLevel); | |||
// Native button | |||
NativeButtonElement nativeButtonElement = $(NativeButtonElement.class) | |||
.first(); | |||
assertHasRightClassNames(nativeButtonElement, "v-nativebutton-error", | |||
errorLevel); | |||
// Link | |||
LinkElement linkElement = $(LinkElement.class).first(); | |||
assertHasRightClassNames(linkElement, "v-link-error", errorLevel); | |||
// Combo box | |||
ComboBoxElement comboBoxElement = $(ComboBoxElement.class).get(1); | |||
assertHasRightClassNames(comboBoxElement, "v-filterselect-error", | |||
errorLevel); | |||
// Date field | |||
DateFieldElement dateFieldElement = $(DateFieldElement.class).first(); | |||
assertHasRightClassNames(dateFieldElement, "v-datefield-error", | |||
errorLevel); | |||
// Checkbox | |||
CheckBoxElement checkBoxElement = $(CheckBoxElement.class).first(); | |||
assertHasRightClassNames(checkBoxElement, "v-checkbox-error", | |||
errorLevel); | |||
// Tab sheet | |||
TabSheetElement tabSheetElement = $(TabSheetElement.class).first(); | |||
assertHasRightClassNames(tabSheetElement, "v-tabsheet-error", | |||
errorLevel); | |||
// Accordion | |||
AccordionElement accordionElement = $(AccordionElement.class).first(); | |||
assertHasRightClassNames(accordionElement, "v-accordion-error", | |||
errorLevel); | |||
// Form layout | |||
FormLayoutElement formLayoutElement = $(FormLayoutElement.class) | |||
.first(); | |||
assertHasRightClassNames(formLayoutElement, "v-formlayout-error", | |||
errorLevel); | |||
// Panel | |||
PanelElement panelElement = $(PanelElement.class).first(); | |||
assertHasRightClassNames(panelElement, "v-panel-error", errorLevel); | |||
// Twin col select | |||
TwinColSelectElement twinColSelectElement = $( | |||
TwinColSelectElement.class).first(); | |||
assertHasRightClassNames(twinColSelectElement, "v-select-twincol-error", | |||
errorLevel); | |||
} | |||
private void assertHasRightClassNames(WebElement element, String prefix, | |||
ErrorLevel errorLevel) { | |||
Assert.assertTrue("Element must have only one error level class name", | |||
containsCorrectErrorLevelClassNameOnly(element, prefix, | |||
errorLevel)); | |||
} | |||
private boolean containsCorrectErrorLevelClassNameOnly(WebElement element, | |||
String prefix, ErrorLevel errorLevel) { | |||
List<String> classNames = new ArrayList<String>( | |||
Arrays.asList(element.getAttribute("class").split(" "))); | |||
classNames.retainAll(getErrorLevelClassNames(prefix, | |||
Arrays.asList(ErrorLevel.values()))); | |||
return classNames.size() == 1 && classNames | |||
.contains(getErrorLevelClassName(prefix, errorLevel)); | |||
} | |||
private String getErrorLevelClassName(String prefix, | |||
ErrorLevel errorLevel) { | |||
return prefix + "-" + errorLevel.toString().toLowerCase(); | |||
} | |||
private List<String> getErrorLevelClassNames(String prefix, | |||
Collection<ErrorLevel> errorLevels) { | |||
List<String> classNames = new ArrayList<String>(errorLevels.size()); | |||
for (ErrorLevel errorLevel : errorLevels) { | |||
classNames.add(getErrorLevelClassName(prefix, errorLevel)); | |||
} | |||
return classNames; | |||
} | |||
private void selectErrorLevel(ErrorLevel errorLevel) { | |||
errorLevelSelector.clear(); | |||
errorLevelSelector.sendKeys(errorLevel.toString().toLowerCase()); | |||
errorLevelSelector.sendKeys(getReturn()); | |||
} | |||
private Keys getReturn() { | |||
if (BrowserUtil.isPhantomJS(getDesiredCapabilities())) { | |||
return Keys.ENTER; | |||
} else { | |||
return Keys.RETURN; | |||
} | |||
} | |||
} |
@@ -84,8 +84,8 @@ public class TabSheetErrorTooltipTest extends MultiBrowserTest { | |||
} | |||
private WebElement getCurrentErrorMessage() { | |||
return getDriver() | |||
.findElement(By.xpath("//div[@class='v-errormessage']")); | |||
return getDriver().findElement( | |||
By.xpath("//div[contains(@class, 'v-errormessage')]")); | |||
} | |||
private void assertTooltip(String tooltip) { |