com.haulmont.cuba.web.toolkit.ui.client.fieldgrouplayout.CubaFieldGroupLayoutComponentSlot.java Source code

Java tutorial

Introduction

Here is the source code for com.haulmont.cuba.web.toolkit.ui.client.fieldgrouplayout.CubaFieldGroupLayoutComponentSlot.java

Source

/*
 * Copyright (c) 2008-2016 Haulmont.
 *
 * 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.haulmont.cuba.web.toolkit.ui.client.fieldgrouplayout;

import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
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.WidgetUtil;
import com.vaadin.client.ui.HasContextHelpConnector;
import com.vaadin.client.ui.ManagedLayout;
import com.vaadin.client.ui.VCheckBox;
import com.vaadin.shared.AbstractFieldState;
import com.vaadin.shared.communication.SharedState;
import com.vaadin.shared.ui.AlignmentInfo;

/**
 * Component slot with horizontal layout for caption and component
 */
public class CubaFieldGroupLayoutComponentSlot extends CubaGridLayoutSlot implements CaptionHolder, EventListener {

    protected static final String INDICATORS_CLASSNAME = "caption-indicators";

    protected Element requiredElement = null;
    protected Element contextHelpIndicatorElement = null;
    protected Element errorIndicatorElement = null;

    protected Element rightCaption = null;

    protected boolean useInlineCaption = true;

    public CubaFieldGroupLayoutComponentSlot(String baseClassName, ComponentConnector child, ManagedLayout layout) {
        super(baseClassName, child, layout);

        // set line-height 25px for all captions exclude captions for CheckBox and Label
        getWrapperElement().addClassName("c-full-height-widget");
    }

    protected boolean isCaptionInline() {
        return useInlineCaption;
    }

    public void setCaptionInline(boolean useInlineCaption) {
        this.useInlineCaption = useInlineCaption;

        if (useInlineCaption) {
            getWrapperElement().addClassName("inline");
        } else {
            getWrapperElement().removeClassName("inline");
        }
    }

    @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 clearCaptionRight = false;

        boolean captionAboveCompnent;
        if (caption == null) {
            captionAboveCompnent = false;
            style.clearPaddingLeft();

            clearCaptionRight = true;
        } 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 {
                availableWidth -= captionWidth;
                if (availableWidth < 0) {
                    availableWidth = 0;
                }
                style.setPaddingLeft(captionWidth, Style.Unit.PX);
                captionStyle.setLeft(0, Style.Unit.PX);
                captionStyle.clearRight();

                clearCaptionRight = true;
            }
        }

        // Take into account right indicators
        double indicatorsWidth = 0;
        if (rightCaption != null) {
            indicatorsWidth = WidgetUtil.getRequiredWidth(rightCaption);
            availableWidth -= indicatorsWidth;
            if (availableWidth < 0) {
                availableWidth = 0;
            }
            style.setPaddingRight(indicatorsWidth, Style.Unit.PX);
        } else if (clearCaptionRight) {
            style.clearPaddingRight();
        }

        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 += WidgetUtil.getRequiredWidth(rightCaption);
            }
            return widgetWidth;
        } else {
            if (rightCaption != null) {
                widgetWidth += WidgetUtil.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 WidgetUtil.getRequiredWidth(rightCaption);
        } else {
            return 0;
        }
    }

    public void setIndicatorsWidth(String width) {
        if (rightCaption != null) {
            rightCaption.getStyle().setProperty("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 (requiredElement != null) {
            requiredElement.removeFromParent();
            requiredElement = null;
        }

        if (captionWidget.getContextHelpIndicatorElement() != null) {
            captionWidget.getContextHelpIndicatorElement().removeFromParent();
            contextHelpIndicatorElement = captionWidget.getContextHelpIndicatorElement();
            rightCaption.appendChild(contextHelpIndicatorElement);

            DOM.sinkEvents(contextHelpIndicatorElement, Event.ONCLICK);
            DOM.setEventListener(contextHelpIndicatorElement, this);
        } else {
            if (contextHelpIndicatorElement != null) {
                contextHelpIndicatorElement.removeFromParent();
                DOM.setEventListener(contextHelpIndicatorElement, null);
                contextHelpIndicatorElement = null;
            }
        }

        if (captionWidget.getErrorIndicatorElement() != null) {
            captionWidget.getErrorIndicatorElement().removeFromParent();

            if (!(getWidget() instanceof VCheckBox)) {
                errorIndicatorElement = captionWidget.getErrorIndicatorElement();
                rightCaption.appendChild(errorIndicatorElement);
            }
        } else if (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;
    }

    @Override
    public void onBrowserEvent(Event event) {
        if (DOM.eventGetType(event) == Event.ONCLICK) {
            Element target = Element.as(event.getEventTarget());
            ComponentConnector componentConnector = Util.findConnectorFor(getWidget());
            if (target == contextHelpIndicatorElement && componentConnector instanceof HasContextHelpConnector) {
                HasContextHelpConnector connector = (HasContextHelpConnector) componentConnector;
                if (hasContextHelpIconListeners(componentConnector.getState())) {
                    connector.contextHelpIconClick(event);
                }
            }
        }
    }

    protected boolean hasContextHelpIconListeners(SharedState state) {
        return state.registeredEventListeners != null
                && state.registeredEventListeners.contains(AbstractFieldState.CONTEXT_HELP_ICON_CLICK_EVENT);
    }
}