Tooltips in ordered layouts #PL-2665

This commit is contained in:
Yuriy Artamonov 2013-09-18 16:40:08 +00:00
parent bb074fb5fe
commit 05df1ef43f
7 changed files with 558 additions and 491 deletions

View File

@ -60,7 +60,7 @@ def desktopModule = project(':cuba-desktop')
def portalModule = project(':cuba-portal')
def webAuthModule = project(':cuba-web-auth')
def vaadinVersion = '7.1.5.cuba.1'
def vaadinVersion = '7.1.5.cuba.2'
def servletApi = [group: 'org.apache.tomcat', name: 'servlet-api', version: '6.0.20']
def groovyArtifact = [group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.1.6']

View File

@ -135,14 +135,6 @@ public class CubaCaptionWidget extends VCaption {
captionText = null;
}
if (ComponentStateUtil.hasDescription(owner.getState())) {
addStyleDependentName("hasdescription");
enableFieldDescription();
} else {
removeStyleDependentName("hasdescription");
disableFieldDescription();
}
AriaHelper.handleInputRequired(owner.getWidget(), showRequired);
if (showRequired) {
@ -165,6 +157,24 @@ public class CubaCaptionWidget extends VCaption {
requiredFieldIndicator = null;
}
// Description
// Haulmont API
if (ComponentStateUtil.hasDescription(owner.getState())) {
addStyleDependentName("hasdescription");
if (toolTipIndicator == null) {
toolTipIndicator = DOM.createDiv();
toolTipIndicator.setClassName(TOOLTIP_CLASSNAME);
DOM.insertChild(getElement(), toolTipIndicator, getDescriptionInsertPosition());
}
} else {
removeStyleDependentName("hasdescription");
if (toolTipIndicator != null) {
toolTipIndicator.removeFromParent();
toolTipIndicator = null;
}
}
AriaHelper.handleInputInvalid(owner.getWidget(), showError);
if (showError) {
@ -195,22 +205,6 @@ public class CubaCaptionWidget extends VCaption {
return (wasPlacedAfterComponent != placedAfterComponent);
}
protected void enableFieldDescription() {
if (toolTipIndicator == null) {
toolTipIndicator = DOM.createDiv();
toolTipIndicator.setClassName(TOOLTIP_CLASSNAME);
DOM.insertChild(getElement(), toolTipIndicator, getDescriptionInsertPosition());
}
}
protected void disableFieldDescription() {
if (toolTipIndicator != null) {
toolTipIndicator.removeFromParent();
toolTipIndicator = null;
}
}
@Override
public int getRenderedWidth() {
int width = 0;

View File

@ -5,9 +5,18 @@
package com.haulmont.cuba.web.toolkit.ui.client.fieldgrouplayout;
import com.google.gwt.dom.client.Style;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.haulmont.cuba.web.toolkit.ui.client.caption.CaptionHolder;
import com.haulmont.cuba.web.toolkit.ui.client.caption.CubaCaptionWidget;
import com.haulmont.cuba.web.toolkit.ui.client.gridlayout.CubaGridLayoutSlot;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.Util;
import com.vaadin.client.VCaption;
import com.vaadin.client.ui.ManagedLayout;
import com.vaadin.client.ui.VCheckBox;
import com.vaadin.shared.ui.AlignmentInfo;
/**
* Component slot with horizontal layout for caption and component
@ -15,13 +24,354 @@ import com.vaadin.client.ui.ManagedLayout;
* @author artamonov
* @version $Id$
*/
public class CubaFieldGroupLayoutComponentSlot extends CubaGridLayoutSlot {
public class CubaFieldGroupLayoutComponentSlot extends CubaGridLayoutSlot implements CaptionHolder {
protected static final String INDICATORS_CLASSNAME = "caption-indicators";
protected Element requiredElement = null;
protected Element tooltipElement = null;
protected Element errorIndicatorElement = null;
protected Element rightCaption = null;
public CubaFieldGroupLayoutComponentSlot(String baseClassName, ComponentConnector child, ManagedLayout layout) {
super(baseClassName, child, layout);
}
@Override
public void captionUpdated(CubaCaptionWidget captionWidget) {
if (isCaptionInline()) {
moveIndicatorsRight(captionWidget);
}
}
@Override
public void setCaption(VCaption caption) {
if (!isCaptionInline()) {
super.setCaption(caption);
} else {
if (rightCaption != null) {
getLayoutManager().unregisterDependency(getLayout(), rightCaption);
rightCaption.removeFromParent();
rightCaption = null;
}
super.setCaption(caption);
if (caption instanceof CubaCaptionWidget) {
moveIndicatorsRight((CubaCaptionWidget) caption);
((CubaCaptionWidget) caption).setCaptionHolder(this);
}
}
}
@Override
public void positionHorizontally(double currentLocation, double allocatedSpace, double marginRight) {
if (!isCaptionInline()) {
super.positionHorizontally(currentLocation, allocatedSpace, marginRight);
return;
}
// CAUTION copied from VLayoutSlot.positionHorizontally(~)
Style style = wrapper.getStyle();
double availableWidth = allocatedSpace;
VCaption caption = getCaption();
Style captionStyle = caption != null ? caption.getElement().getStyle() : null;
int captionWidth = getCaptionWidth();
boolean captionAboveCompnent;
if (caption == null) {
captionAboveCompnent = false;
if (isCaptionInline()) {
style.clearPaddingLeft();
}
style.clearPaddingRight();
} else {
captionAboveCompnent = !caption.shouldBePlacedAfterComponent();
if (!captionAboveCompnent) {
availableWidth -= captionWidth;
if (availableWidth < 0) {
availableWidth = 0;
}
captionStyle.clearLeft();
captionStyle.setRight(0, Style.Unit.PX);
style.setPaddingRight(captionWidth, Style.Unit.PX);
} else {
if (isCaptionInline()) {
availableWidth -= captionWidth;
if (availableWidth < 0) {
availableWidth = 0;
}
style.setPaddingLeft(captionWidth, Style.Unit.PX);
}
captionStyle.setLeft(0, Style.Unit.PX);
captionStyle.clearRight();
style.clearPaddingRight();
}
}
// Take into account right indicators
double indicatorsWidth = 0;
if (rightCaption != null) {
indicatorsWidth = Util.getRequiredWidth(rightCaption);
availableWidth -= indicatorsWidth;
if (availableWidth < 0) {
availableWidth = 0;
}
style.setPaddingRight(indicatorsWidth, Style.Unit.PX);
}
if (marginRight > 0) {
style.setMarginRight(marginRight, Style.Unit.PX);
} else {
style.clearMarginRight();
}
if (isRelativeWidth()) {
style.setPropertyPx("width", (int) availableWidth);
} else {
style.clearProperty("width");
}
double allocatedContentWidth = 0;
if (isRelativeWidth()) {
String percentWidth = getWidget().getElement().getStyle()
.getWidth();
double percentage = parsePercent(percentWidth);
allocatedContentWidth = availableWidth * (percentage / 100);
reportActualRelativeWidth(Math.round((float) allocatedContentWidth));
}
AlignmentInfo alignment = getAlignment();
if (!alignment.isLeft()) {
double usedWidth;
if (isRelativeWidth()) {
if (isCaptionInline()) {
usedWidth = allocatedContentWidth + indicatorsWidth + captionWidth;
} else {
usedWidth = allocatedContentWidth + indicatorsWidth;
}
} else {
usedWidth = getWidgetWidth() + indicatorsWidth;
}
if (alignment.isHorizontalCenter()) {
currentLocation += (allocatedSpace - usedWidth) / 2d;
if (captionAboveCompnent) {
captionStyle.setLeft(
Math.round(usedWidth - captionWidth) / 2, Style.Unit.PX);
}
} else {
currentLocation += (allocatedSpace - usedWidth);
if (captionAboveCompnent) {
captionStyle.setLeft(Math.round(usedWidth - captionWidth),
Style.Unit.PX);
}
}
} else {
if (captionAboveCompnent) {
captionStyle.setLeft(0, Style.Unit.PX);
}
}
style.setLeft(Math.round(currentLocation), Style.Unit.PX);
}
@Override
public void positionVertically(double currentLocation, double allocatedSpace, double marginBottom) {
if (!isCaptionInline()) {
super.positionVertically(currentLocation, allocatedSpace, marginBottom);
return;
}
// CAUTION copied from VLayoutSlot.positionVertically(~)
Style style = wrapper.getStyle();
double contentHeight = allocatedSpace;
int captionHeight;
VCaption caption = getCaption();
if (caption == null || caption.shouldBePlacedAfterComponent() || isCaptionInline()) {
style.clearPaddingTop();
captionHeight = 0;
} else {
captionHeight = getCaptionHeight();
contentHeight -= captionHeight;
if (contentHeight < 0) {
contentHeight = 0;
}
style.setPaddingTop(captionHeight, Style.Unit.PX);
}
if (marginBottom > 0) {
style.setMarginBottom(marginBottom, Style.Unit.PX);
} else {
style.clearMarginBottom();
}
if (isRelativeHeight()) {
style.setHeight(contentHeight, Style.Unit.PX);
} else {
style.clearHeight();
}
double allocatedContentHeight = 0;
if (isRelativeHeight()) {
String height = getWidget().getElement().getStyle().getHeight();
double percentage = parsePercent(height);
allocatedContentHeight = contentHeight * (percentage / 100);
reportActualRelativeHeight(Math
.round((float) allocatedContentHeight));
}
AlignmentInfo alignment = getAlignment();
if (!alignment.isTop()) {
double usedHeight;
if (isRelativeHeight()) {
if (isCaptionInline()) {
usedHeight = allocatedContentHeight;
} else {
usedHeight = captionHeight + allocatedContentHeight;
}
} else {
usedHeight = getUsedHeight();
}
if (alignment.isVerticalCenter()) {
currentLocation += (allocatedSpace - usedHeight) / 2d;
} else {
currentLocation += (allocatedSpace - usedHeight);
}
}
style.setTop(currentLocation, Style.Unit.PX);
}
@Override
public int getUsedWidth() {
if (!isCaptionInline()) {
return super.getUsedWidth();
}
int widgetWidth = getWidgetWidth();
if (getCaption() == null) {
return widgetWidth;
} else if (getCaption().shouldBePlacedAfterComponent() || isCaptionInline()) {
widgetWidth += getCaptionWidth();
if (rightCaption != null) {
widgetWidth += Util.getRequiredWidth(rightCaption);
}
return widgetWidth;
} else {
if (rightCaption != null) {
widgetWidth += Util.getRequiredWidth(rightCaption);
}
return Math.max(widgetWidth, getCaptionWidth());
}
}
@Override
public int getUsedHeight() {
if (!isCaptionInline()) {
return super.getUsedHeight();
}
int widgetHeight = getWidgetHeight();
if (getCaption() == null) {
return widgetHeight;
} else if (getCaption().shouldBePlacedAfterComponent() || isCaptionInline()) {
return Math.max(widgetHeight, getCaptionHeight());
} else {
return widgetHeight + getCaptionHeight();
}
}
public int getIndicatorsWidth() {
if (rightCaption != null) {
return Util.getRequiredWidth(rightCaption);
} else {
return 0;
}
}
public void setInidcatorsWidth(String width) {
if (rightCaption != null) {
DOM.setStyleAttribute(rightCaption, "width", width);
}
}
public void resetIndicatorsWidth() {
if (rightCaption != null) {
rightCaption.getStyle().clearWidth();
}
}
protected void moveIndicatorsRight(final CubaCaptionWidget captionWidget) {
// Indicators element always present in DOM tree of slot
if (rightCaption == null) {
rightCaption = createRightCaption();
getWrapperElement().insertAfter(rightCaption, getWidget().getElement());
}
// detach all indicators
for (int i = 0; i < rightCaption.getChildCount(); i++) {
rightCaption.getChild(i).removeFromParent();
}
/* now attach only necessary indicators */
if (captionWidget.getRequiredIndicatorElement() != null) {
captionWidget.getRequiredIndicatorElement().removeFromParent();
if (!(getWidget() instanceof VCheckBox)) {
requiredElement = captionWidget.getRequiredIndicatorElement();
rightCaption.appendChild(requiredElement);
}
} else if (captionWidget.getRequiredIndicatorElement() == null && requiredElement != null) {
requiredElement.removeFromParent();
requiredElement = null;
}
if (captionWidget.getTooltipElement() != null) {
captionWidget.getTooltipElement().removeFromParent();
if (!(getWidget() instanceof VCheckBox)) {
tooltipElement = captionWidget.getTooltipElement();
rightCaption.appendChild(tooltipElement);
}
} else if (captionWidget.getTooltipElement() == null && tooltipElement != null) {
tooltipElement.removeFromParent();
tooltipElement = null;
}
if (captionWidget.getErrorIndicatorElement() != null) {
captionWidget.getErrorIndicatorElement().removeFromParent();
if (!(getWidget() instanceof VCheckBox)) {
errorIndicatorElement = captionWidget.getErrorIndicatorElement();
rightCaption.appendChild(errorIndicatorElement);
}
} else if (captionWidget.getErrorIndicatorElement() == null && errorIndicatorElement != null) {
errorIndicatorElement.removeFromParent();
errorIndicatorElement = null;
}
}
protected Element createRightCaption() {
Element rightCaption = DOM.createDiv();
getLayoutManager().registerDependency((ManagedLayout) getChild().getParent(), rightCaption);
rightCaption.setClassName(VCaption.CLASSNAME);
rightCaption.addClassName(INDICATORS_CLASSNAME);
rightCaption.getStyle().setDisplay(Style.Display.INLINE_BLOCK);
rightCaption.getStyle().setPosition(Style.Position.ABSOLUTE);
return rightCaption;
}
protected boolean isCaptionInline() {
// todo artamonov implement vertical/horizontal option for captions
return true;

View File

@ -5,348 +5,17 @@
package com.haulmont.cuba.web.toolkit.ui.client.gridlayout;
import com.google.gwt.dom.client.Style;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.haulmont.cuba.web.toolkit.ui.client.caption.CaptionHolder;
import com.haulmont.cuba.web.toolkit.ui.client.caption.CubaCaptionWidget;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.Util;
import com.vaadin.client.VCaption;
import com.vaadin.client.ui.ManagedLayout;
import com.vaadin.client.ui.VCheckBox;
import com.vaadin.client.ui.layout.ComponentConnectorLayoutSlot;
import com.vaadin.shared.ui.AlignmentInfo;
/**
* @author devyatkin
* @version $Id$
*/
public class CubaGridLayoutSlot extends ComponentConnectorLayoutSlot implements CaptionHolder {
protected static final String INDICATORS_CLASSNAME = "caption-indicators";
protected Element requiredElement = null;
protected Element tooltipElement = null;
protected Element errorIndicatorElement = null;
protected Element rightCaption = null;
public class CubaGridLayoutSlot extends ComponentConnectorLayoutSlot {
public CubaGridLayoutSlot(String baseClassName, ComponentConnector child, ManagedLayout layout) {
super(baseClassName, child, layout);
}
@Override
public void captionUpdated(CubaCaptionWidget captionWidget) {
moveIndicatorsRight(captionWidget);
}
@Override
public void setCaption(VCaption caption) {
if (rightCaption != null) {
getLayoutManager().unregisterDependency(getLayout(), rightCaption);
rightCaption.removeFromParent();
rightCaption = null;
}
super.setCaption(caption);
if (caption instanceof CubaCaptionWidget) {
moveIndicatorsRight((CubaCaptionWidget) caption);
((CubaCaptionWidget) caption).setCaptionHolder(this);
}
}
@Override
public void positionHorizontally(double currentLocation, double allocatedSpace, double marginRight) {
// CAUTION copied from VLayoutSlot.positionHorizontally(~)
Style style = wrapper.getStyle();
double availableWidth = allocatedSpace;
VCaption caption = getCaption();
Style captionStyle = caption != null ? caption.getElement().getStyle() : null;
int captionWidth = getCaptionWidth();
boolean captionAboveCompnent;
if (caption == null) {
captionAboveCompnent = false;
if (isCaptionInline()) {
style.clearPaddingLeft();
}
style.clearPaddingRight();
} else {
captionAboveCompnent = !caption.shouldBePlacedAfterComponent();
if (!captionAboveCompnent) {
availableWidth -= captionWidth;
if (availableWidth < 0) {
availableWidth = 0;
}
captionStyle.clearLeft();
captionStyle.setRight(0, Style.Unit.PX);
style.setPaddingRight(captionWidth, Style.Unit.PX);
} else {
if (isCaptionInline()) {
availableWidth -= captionWidth;
if (availableWidth < 0) {
availableWidth = 0;
}
style.setPaddingLeft(captionWidth, Style.Unit.PX);
}
captionStyle.setLeft(0, Style.Unit.PX);
captionStyle.clearRight();
style.clearPaddingRight();
}
}
// Take into account right indicators
double indicatorsWidth = 0;
if (rightCaption != null) {
indicatorsWidth = Util.getRequiredWidth(rightCaption);
availableWidth -= indicatorsWidth;
if (availableWidth < 0) {
availableWidth = 0;
}
style.setPaddingRight(indicatorsWidth, Style.Unit.PX);
}
if (marginRight > 0) {
style.setMarginRight(marginRight, Style.Unit.PX);
} else {
style.clearMarginRight();
}
if (isRelativeWidth()) {
style.setPropertyPx("width", (int) availableWidth);
} else {
style.clearProperty("width");
}
double allocatedContentWidth = 0;
if (isRelativeWidth()) {
String percentWidth = getWidget().getElement().getStyle()
.getWidth();
double percentage = parsePercent(percentWidth);
allocatedContentWidth = availableWidth * (percentage / 100);
reportActualRelativeWidth(Math.round((float) allocatedContentWidth));
}
AlignmentInfo alignment = getAlignment();
if (!alignment.isLeft()) {
double usedWidth;
if (isRelativeWidth()) {
if (isCaptionInline()) {
usedWidth = allocatedContentWidth + indicatorsWidth + captionWidth ;
} else {
usedWidth = allocatedContentWidth + indicatorsWidth;
}
} else {
usedWidth = getWidgetWidth() + indicatorsWidth;
}
if (alignment.isHorizontalCenter()) {
currentLocation += (allocatedSpace - usedWidth) / 2d;
if (captionAboveCompnent) {
captionStyle.setLeft(
Math.round(usedWidth - captionWidth) / 2, Style.Unit.PX);
}
} else {
currentLocation += (allocatedSpace - usedWidth);
if (captionAboveCompnent) {
captionStyle.setLeft(Math.round(usedWidth - captionWidth),
Style.Unit.PX);
}
}
} else {
if (captionAboveCompnent) {
captionStyle.setLeft(0, Style.Unit.PX);
}
}
style.setLeft(Math.round(currentLocation), Style.Unit.PX);
}
@Override
public void positionVertically(double currentLocation, double allocatedSpace, double marginBottom) {
// CAUTION copied from VLayoutSlot.positionVertically(~)
Style style = wrapper.getStyle();
double contentHeight = allocatedSpace;
int captionHeight;
VCaption caption = getCaption();
if (caption == null || caption.shouldBePlacedAfterComponent() || isCaptionInline()) {
style.clearPaddingTop();
captionHeight = 0;
} else {
captionHeight = getCaptionHeight();
contentHeight -= captionHeight;
if (contentHeight < 0) {
contentHeight = 0;
}
style.setPaddingTop(captionHeight, Style.Unit.PX);
}
if (marginBottom > 0) {
style.setMarginBottom(marginBottom, Style.Unit.PX);
} else {
style.clearMarginBottom();
}
if (isRelativeHeight()) {
style.setHeight(contentHeight, Style.Unit.PX);
} else {
style.clearHeight();
}
double allocatedContentHeight = 0;
if (isRelativeHeight()) {
String height = getWidget().getElement().getStyle().getHeight();
double percentage = parsePercent(height);
allocatedContentHeight = contentHeight * (percentage / 100);
reportActualRelativeHeight(Math
.round((float) allocatedContentHeight));
}
AlignmentInfo alignment = getAlignment();
if (!alignment.isTop()) {
double usedHeight;
if (isRelativeHeight()) {
if (isCaptionInline()) {
usedHeight = allocatedContentHeight;
} else {
usedHeight = captionHeight + allocatedContentHeight;
}
} else {
usedHeight = getUsedHeight();
}
if (alignment.isVerticalCenter()) {
currentLocation += (allocatedSpace - usedHeight) / 2d;
} else {
currentLocation += (allocatedSpace - usedHeight);
}
}
style.setTop(currentLocation, Style.Unit.PX);
}
@Override
public int getUsedWidth() {
int widgetWidth = getWidgetWidth();
if (getCaption() == null) {
return widgetWidth;
} else if (getCaption().shouldBePlacedAfterComponent() || isCaptionInline()) {
widgetWidth += getCaptionWidth();
if (rightCaption != null) {
widgetWidth += Util.getRequiredWidth(rightCaption);
}
return widgetWidth;
} else {
if (rightCaption != null) {
widgetWidth += Util.getRequiredWidth(rightCaption);
}
return Math.max(widgetWidth, getCaptionWidth());
}
}
@Override
public int getUsedHeight() {
int widgetHeight = getWidgetHeight();
if (getCaption() == null) {
return widgetHeight;
} else if (getCaption().shouldBePlacedAfterComponent() || isCaptionInline()) {
return Math.max(widgetHeight, getCaptionHeight());
} else {
return widgetHeight + getCaptionHeight();
}
}
public int getIndicatorsWidth() {
if (rightCaption != null) {
return Util.getRequiredWidth(rightCaption);
} else {
return 0;
}
}
public void setInidcatorsWidth(String width) {
if (rightCaption != null) {
DOM.setStyleAttribute(rightCaption, "width", width);
}
}
public void resetIndicatorsWidth() {
if (rightCaption != null) {
rightCaption.getStyle().clearWidth();
}
}
protected void moveIndicatorsRight(final CubaCaptionWidget captionWidget) {
// Indicators element always present in DOM tree of slot
if (rightCaption == null) {
rightCaption = createRightCaption();
getWrapperElement().insertAfter(rightCaption, getWidget().getElement());
}
// detach all indicators
for (int i = 0; i < rightCaption.getChildCount(); i++) {
rightCaption.getChild(i).removeFromParent();
}
/* now attach only necessary indicators */
if (captionWidget.getRequiredIndicatorElement() != null) {
captionWidget.getRequiredIndicatorElement().removeFromParent();
if (!(getWidget() instanceof VCheckBox)) {
requiredElement = captionWidget.getRequiredIndicatorElement();
rightCaption.appendChild(requiredElement);
}
} else if (captionWidget.getRequiredIndicatorElement() == null && requiredElement != null) {
requiredElement.removeFromParent();
requiredElement = null;
}
if (captionWidget.getTooltipElement() != null) {
captionWidget.getTooltipElement().removeFromParent();
if (!(getWidget() instanceof VCheckBox)) {
tooltipElement = captionWidget.getTooltipElement();
rightCaption.appendChild(tooltipElement);
}
} else if (captionWidget.getTooltipElement() == null && tooltipElement != null) {
tooltipElement.removeFromParent();
tooltipElement = null;
}
if (captionWidget.getErrorIndicatorElement() != null) {
captionWidget.getErrorIndicatorElement().removeFromParent();
if (!(getWidget() instanceof VCheckBox)) {
errorIndicatorElement = captionWidget.getErrorIndicatorElement();
rightCaption.appendChild(errorIndicatorElement);
}
} else if (captionWidget.getErrorIndicatorElement() == null && errorIndicatorElement != null) {
errorIndicatorElement.removeFromParent();
errorIndicatorElement = null;
}
}
protected Element createRightCaption() {
Element rightCaption = DOM.createDiv();
getLayoutManager().registerDependency((ManagedLayout) getChild().getParent(), rightCaption);
rightCaption.setClassName(VCaption.CLASSNAME);
rightCaption.addClassName(INDICATORS_CLASSNAME);
rightCaption.getStyle().setDisplay(Style.Display.INLINE_BLOCK);
rightCaption.getStyle().setPosition(Style.Position.ABSOLUTE);
return rightCaption;
}
protected boolean isCaptionInline() {
return false;
}
}

View File

@ -6,12 +6,20 @@
package com.haulmont.cuba.web.toolkit.ui.client.orderedactionslayout;
import com.haulmont.cuba.web.toolkit.ui.CubaOrderedActionsLayout;
import com.haulmont.cuba.web.toolkit.ui.client.caption.CubaCaptionWidget;
import com.vaadin.client.*;
import com.vaadin.client.ui.AbstractFieldConnector;
import com.vaadin.client.ui.ShortcutActionHandler;
import com.vaadin.client.ui.aria.AriaHelper;
import com.vaadin.client.ui.orderedlayout.AbstractOrderedLayoutConnector;
import com.vaadin.client.ui.orderedlayout.CaptionPosition;
import com.vaadin.shared.AbstractFieldState;
import com.vaadin.shared.ComponentConstants;
import com.vaadin.shared.communication.URLReference;
import com.vaadin.shared.ui.ComponentStateUtil;
import com.vaadin.shared.ui.Connect;
import java.util.List;
/**
* @author devyatkin
* @version $Id$
@ -40,17 +48,50 @@ public class CubaOrderedActionsLayoutConnector extends AbstractOrderedLayoutConn
@Override
protected void updateCaptionInternal(ComponentConnector child) {
// CAUTION copied from superclass
CubaOrderedLayoutSlot slot = (CubaOrderedLayoutSlot) getWidget().getSlot(child.getWidget());
if (VCaption.isNeeded(child.getState())) {
VCaption caption = slot.getCaption();
if (caption == null) {
// use our own caption widget
caption = new CubaCaptionWidget(child, getConnection());
slot.setCaption(caption);
String caption = child.getState().caption;
URLReference iconUrl = child.getState().resources
.get(ComponentConstants.ICON_RESOURCE);
String iconUrlString = iconUrl != null ? iconUrl.getURL() : null;
List<String> styles = child.getState().styles;
String error = child.getState().errorMessage;
boolean showError = error != null;
if (child.getState() instanceof AbstractFieldState) {
AbstractFieldState abstractFieldState = (AbstractFieldState) child
.getState();
showError = showError && !abstractFieldState.hideErrors;
}
boolean required = false;
if (child instanceof AbstractFieldConnector) {
required = ((AbstractFieldConnector) child).isRequired();
}
boolean enabled = child.isEnabled();
String description = null;
if (ComponentStateUtil.hasDescription(child.getState())) {
description = child.getState().description;
}
slot.setCaption(caption, description, iconUrlString, styles, error, showError,
required, enabled);
AriaHelper.handleInputRequired(child.getWidget(), required);
AriaHelper.handleInputInvalid(child.getWidget(), showError);
AriaHelper.bindCaption(child.getWidget(), slot.getCaptionElement());
if (slot.hasCaption()) {
CaptionPosition pos = slot.getCaptionPosition();
getLayoutManager().addElementResizeListener(
slot.getCaptionElement(), slotCaptionResizeListener);
if (child.isRelativeHeight()
&& (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) {
getWidget().updateCaptionOffset(slot.getCaptionElement());
} else if (child.isRelativeWidth()
&& (pos == CaptionPosition.LEFT || pos == CaptionPosition.RIGHT)) {
getWidget().updateCaptionOffset(slot.getCaptionElement());
}
caption.updateCaption();
} else {
slot.setCaption(null);
}
}
}

View File

@ -5,150 +5,162 @@
package com.haulmont.cuba.web.toolkit.ui.client.orderedactionslayout;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Style;
import com.google.gwt.aria.client.Roles;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Widget;
import com.haulmont.cuba.web.toolkit.ui.client.caption.CaptionHolder;
import com.haulmont.cuba.web.toolkit.ui.client.caption.CubaCaptionWidget;
import com.vaadin.client.Util;
import com.vaadin.client.VCaption;
import com.vaadin.client.ui.VCheckBox;
import com.vaadin.client.StyleConstants;
import com.vaadin.client.ui.orderedlayout.CaptionPosition;
import com.vaadin.client.ui.orderedlayout.Slot;
import com.google.gwt.user.client.Element;
import com.vaadin.client.ui.orderedlayout.VAbstractOrderedLayout;
import com.vaadin.shared.ui.AlignmentInfo;
import java.util.List;
/**
* @author devyatkin
* @version $Id$
*/
public class CubaOrderedLayoutSlot extends Slot implements CaptionHolder {
public class CubaOrderedLayoutSlot extends Slot {
protected static final String INDICATORS_CLASSNAME = "caption-indicators";
public static final String TOOLTIP_CLASSNAME = "cuba-tooltip-button";
protected Element requiredElement = null;
protected Element tooltipElement = null;
protected Element errorIndicatorElement = null;
protected Element rightCaption = null;
protected VCaption caption;
protected Element tooltipIcon;
protected String descriptionText;
public CubaOrderedLayoutSlot(VAbstractOrderedLayout layout, Widget widget) {
super(layout, widget);
}
public void setCaption(VCaption caption){
if (this.caption != null) {
this.caption.removeFromParent();
}
this.caption = caption;
if (caption != null) {
// Physical attach.
DOM.insertBefore(DOM.getParent(getWidget().getElement()), caption.getElement(), getWidget().getElement());
Style style = caption.getElement().getStyle();
style.setPosition(Style.Position.RELATIVE);
style.clearTop();
style.clearLeft();
((CubaCaptionWidget) caption).setCaptionHolder(this);
public void setCaption(String captionText, String descriptionText, String iconUrl, List<String> styles, String error,
boolean showError, boolean required, boolean enabled) {
// CAUTION copied from super
// Caption wrappers
Widget widget = getWidget();
if (captionText != null || descriptionText != null || iconUrl != null || error != null || required) {
if (caption == null) {
caption = DOM.createDiv();
captionWrap = DOM.createDiv();
captionWrap.addClassName(StyleConstants.UI_WIDGET);
captionWrap.addClassName("v-has-caption");
getElement().appendChild(captionWrap);
orphan(widget);
captionWrap.appendChild(widget.getElement());
adopt(widget);
}
} else if (caption != null) {
orphan(widget);
getElement().appendChild(widget.getElement());
adopt(widget);
captionWrap.removeFromParent();
caption = null;
captionWrap = null;
}
public VCaption getCaption(){
return caption;
// Caption text
if (captionText != null) {
if (this.captionText == null) {
this.captionText = DOM.createSpan();
this.captionText.addClassName("v-captiontext");
caption.appendChild(this.captionText);
}
@Override
public void captionUpdated(CubaCaptionWidget captionWidget) {
moveIndicatorsRight(captionWidget);
}
protected void moveIndicatorsRight(final CubaCaptionWidget captionWidget) {
// Indicators element always present in DOM tree of slot
if (rightCaption == null) {
rightCaption = createRightCaption();
getWidget().getElement().getParentElement().insertAfter(rightCaption, getWidget().getElement());
}
// detach all indicators
for (int i = 0; i < rightCaption.getChildCount(); i++) {
rightCaption.getChild(i).removeFromParent();
}
/* now attach only necessary indicators */
if (captionWidget.getRequiredIndicatorElement() != null) {
captionWidget.getRequiredIndicatorElement().removeFromParent();
if (!(getWidget() instanceof VCheckBox)) {
requiredElement = captionWidget.getRequiredIndicatorElement();
rightCaption.appendChild(requiredElement);
}
} else if (captionWidget.getRequiredIndicatorElement() == null && requiredElement != null) {
requiredElement.removeFromParent();
requiredElement = null;
}
if (captionWidget.getTooltipElement() != null) {
captionWidget.getTooltipElement().removeFromParent();
if (!(getWidget() instanceof VCheckBox)) {
tooltipElement = captionWidget.getTooltipElement();
rightCaption.appendChild(tooltipElement);
}
} else if (captionWidget.getTooltipElement() == null && tooltipElement != null) {
tooltipElement.removeFromParent();
tooltipElement = null;
}
if (captionWidget.getErrorIndicatorElement() != null) {
captionWidget.getErrorIndicatorElement().removeFromParent();
if (!(getWidget() instanceof VCheckBox)) {
errorIndicatorElement = captionWidget.getErrorIndicatorElement();
rightCaption.appendChild(errorIndicatorElement);
}
} else if (captionWidget.getErrorIndicatorElement() == null && errorIndicatorElement != null) {
errorIndicatorElement.removeFromParent();
errorIndicatorElement = null;
}
if (!(getWidget() instanceof VCheckBox)) {
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
@Override
public void execute() {
allocateSpaceForIndicators();
}
});
}
}
protected void allocateSpaceForIndicators() {
int widgetWidth = getWidget().getOffsetWidth();
int indicatorsWidth = Util.getRequiredWidth(rightCaption);
int captionWidth = getCaption().getElement().getOffsetWidth();
if ((getAlignment().getBitMask() & AlignmentInfo.RIGHT.getBitMask()) == AlignmentInfo.RIGHT.getBitMask()) {
getStyleElement().getStyle().setPaddingRight(indicatorsWidth, Style.Unit.PX);
} else if (captionWidth >= widgetWidth + indicatorsWidth) {
getStyleElement().getStyle().clearPaddingRight();
if (captionText.trim().equals("")) {
this.captionText.setInnerHTML("&nbsp;");
} else {
int requiredHorizontalSpace = indicatorsWidth;
if (captionWidth > widgetWidth) {
requiredHorizontalSpace -= (captionWidth - widgetWidth);
this.captionText.setInnerText(captionText);
}
getStyleElement().getStyle().setPaddingRight(requiredHorizontalSpace, Style.Unit.PX);
} else if (this.captionText != null) {
this.captionText.removeFromParent();
this.captionText = null;
}
// Icon
if (iconUrl != null) {
if (icon == null) {
icon = new Icon();
caption.insertFirst(icon.getElement());
}
icon.setUri(iconUrl);
} else if (icon != null) {
icon.getElement().removeFromParent();
icon = null;
}
// Required
if (required) {
if (requiredIcon == null) {
requiredIcon = DOM.createSpan();
// TODO decide something better (e.g. use CSS to insert the
// character)
requiredIcon.setInnerHTML("*");
requiredIcon.setClassName("v-required-field-indicator");
// The star should not be read by the screen reader, as it is
// purely visual. Required state is set at the element level for
// the screen reader.
Roles.getTextboxRole().setAriaHiddenState(requiredIcon, true);
}
caption.appendChild(requiredIcon);
} else if (requiredIcon != null) {
requiredIcon.removeFromParent();
requiredIcon = null;
}
// Desciption
// Haulmont API
this.descriptionText = descriptionText;
if (descriptionText != null) {
if (tooltipIcon == null) {
tooltipIcon = DOM.createSpan();
// TODO decide something better (e.g. use CSS to insert the
// character)
tooltipIcon.setInnerHTML("?");
tooltipIcon.setClassName(TOOLTIP_CLASSNAME);
// The star should not be read by the screen reader, as it is
// purely visual. Required state is set at the element level for
// the screen reader.
Roles.getTextboxRole().setAriaHiddenState(tooltipIcon, true);
}
caption.appendChild(tooltipIcon);
} else if (this.tooltipIcon != null) {
this.tooltipIcon.removeFromParent();
this.tooltipIcon = null;
}
// 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;
}
if (caption != null) {
// Styles
caption.setClassName("v-caption");
if (styles != null) {
for (String style : styles) {
caption.addClassName("v-caption-" + style);
}
}
protected Element createRightCaption() {
Element rightCaption = DOM.createDiv();
if (enabled) {
caption.removeClassName("v-disabled");
} else {
caption.addClassName("v-disabled");
}
rightCaption.setClassName(VCaption.CLASSNAME);
rightCaption.addClassName(INDICATORS_CLASSNAME);
rightCaption.getStyle().setDisplay(Style.Display.INLINE_BLOCK);
rightCaption.getStyle().setPosition(Style.Position.ABSOLUTE);
return rightCaption;
// Caption position
if (captionText != null || iconUrl != null) {
setCaptionPosition(CaptionPosition.TOP);
} else {
setCaptionPosition(CaptionPosition.RIGHT);
}
}
}
}

View File

@ -20,6 +20,7 @@
.cuba-tooltip-button {
display: inline-block;
color: transparent;
background: transparent no-repeat top right;
background-image: url(sprites/question.png); /** sprite-ref: components; */
width: 16px;