PL-9372 Add margins support to GroupBox component

This commit is contained in:
Gleb Gorelov 2017-09-19 12:49:53 +04:00
parent ed2d479cd6
commit 8c294629a8
13 changed files with 193 additions and 18 deletions

View File

@ -20,6 +20,7 @@ package com.haulmont.cuba.desktop.gui.components;
import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter; import com.haulmont.cuba.desktop.sys.layout.BoxLayoutAdapter;
import com.haulmont.cuba.desktop.sys.vcl.CollapsiblePanel; import com.haulmont.cuba.desktop.sys.vcl.CollapsiblePanel;
import com.haulmont.cuba.gui.components.GroupBoxLayout; import com.haulmont.cuba.gui.components.GroupBoxLayout;
import com.haulmont.cuba.gui.components.MarginInfo;
import com.haulmont.cuba.gui.components.compatibility.ComponentExpandCollapseListenerWrapper; import com.haulmont.cuba.gui.components.compatibility.ComponentExpandCollapseListenerWrapper;
import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.BooleanUtils;
import org.dom4j.Element; import org.dom4j.Element;
@ -39,6 +40,7 @@ public class DesktopGroupBox extends DesktopAbstractBox implements GroupBoxLayou
protected boolean settingsEnabled = true; protected boolean settingsEnabled = true;
protected boolean showAsPanel; protected boolean showAsPanel;
protected MarginInfo outerMarginInfo;
public DesktopGroupBox() { public DesktopGroupBox() {
collapsiblePanel = new CollapsiblePanel(super.getComposition()); collapsiblePanel = new CollapsiblePanel(super.getComposition());
@ -242,4 +244,17 @@ public class DesktopGroupBox extends DesktopAbstractBox implements GroupBoxLayou
public boolean expandsHeight() { public boolean expandsHeight() {
return orientation == Orientation.HORIZONTAL; return orientation == Orientation.HORIZONTAL;
} }
@Override
public void setOuterMargin(MarginInfo marginInfo) {
outerMarginInfo = marginInfo;
}
@Override
public MarginInfo getOuterMargin() {
if (outerMarginInfo == null) {
outerMarginInfo = new MarginInfo(false);
}
return outerMarginInfo;
}
} }

View File

@ -921,6 +921,46 @@ public interface Component {
MarginInfo getMargin(); MarginInfo getMargin();
} }
/**
* A class that implements this interface can have indentation outside the border.
*/
interface OuterMargin {
/**
* Enables or disables margins on all sides simultaneously.
*
* @param enable if true, enables margins on all sides. If false, disables margins on all sides.
*/
default void setOuterMargin(boolean enable) {
setOuterMargin(new MarginInfo(enable, enable, enable, enable));
}
/**
* Sets margins on all sides individually.
*
* @param top enable or disable top margin
* @param right enable or disable right margin
* @param bottom enable or disable bottom margin
* @param left enable or disable left margin
*/
default void setOuterMargin(boolean top, boolean right, boolean bottom, boolean left) {
setOuterMargin(new MarginInfo(top, right, bottom, left));
}
/**
* Sets margins on all sides according to the passed {@link MarginInfo} object.
*
* @param marginInfo the {@link MarginInfo} object that describes the
* margin settings for each side of a Component.
*/
void setOuterMargin(MarginInfo marginInfo);
/**
* @return the {@link MarginInfo} object that describes the
* margin settings for each side of a Component.
*/
MarginInfo getOuterMargin();
}
interface HasInputPrompt { interface HasInputPrompt {
/** /**
* @return current input prompt. * @return current input prompt.

View File

@ -19,7 +19,7 @@ package com.haulmont.cuba.gui.components;
public interface GroupBoxLayout public interface GroupBoxLayout
extends ExpandingLayout, extends ExpandingLayout,
Component.OrderedContainer, Component.OrderedContainer,
Component.HasIcon, Component.HasCaption, Component.HasBorder, Component.Spacing, Component.HasIcon, Component.HasCaption, Component.HasBorder, Component.Spacing, Component.OuterMargin,
Component.Collapsable, Component.BelongToFrame, Component.HasSettings, Component.ShortcutNotifier { Component.Collapsable, Component.BelongToFrame, Component.HasSettings, Component.ShortcutNotifier {
String NAME = "groupBox"; String NAME = "groupBox";

View File

@ -840,6 +840,10 @@
<xs:attribute name="spacing" type="xs:boolean"/> <xs:attribute name="spacing" type="xs:boolean"/>
</xs:attributeGroup> </xs:attributeGroup>
<xs:attributeGroup name="hasOuterMargin">
<xs:attribute name="outerMargin" type="xs:string"/>
</xs:attributeGroup>
<xs:attributeGroup name="hasExpand"> <xs:attributeGroup name="hasExpand">
<xs:attribute name="expand" type="xs:string"/> <xs:attribute name="expand" type="xs:string"/>
</xs:attributeGroup> </xs:attributeGroup>
@ -2461,6 +2465,7 @@
<xs:group ref="layoutOrComponent" minOccurs="0"/> <xs:group ref="layoutOrComponent" minOccurs="0"/>
<xs:attributeGroup ref="hasSpacing"/> <xs:attributeGroup ref="hasSpacing"/>
<xs:attributeGroup ref="hasOuterMargin"/>
<xs:attributeGroup ref="hasSettings"/> <xs:attributeGroup ref="hasSettings"/>
<xs:attributeGroup ref="hasExpand"/> <xs:attributeGroup ref="hasExpand"/>

View File

@ -364,22 +364,27 @@ public abstract class AbstractComponentLoader<T extends Component> implements Co
protected void loadMargin(Component.Margin layout, Element element) { protected void loadMargin(Component.Margin layout, Element element) {
final String margin = element.attributeValue("margin"); final String margin = element.attributeValue("margin");
if (!StringUtils.isEmpty(margin)) { if (!StringUtils.isEmpty(margin)) {
if (margin.contains(";") || margin.contains(",")) { MarginInfo marginInfo = parseMarginInfo(margin);
final String[] margins = margin.split("[;,]"); layout.setMargin(marginInfo);
if (margins.length != 4) { }
throw new GuiDevelopmentException( }
"Margin attribute must contain 1 or 4 boolean values separated by ',' or ';", context.getFullFrameId());
}
layout.setMargin( protected MarginInfo parseMarginInfo(String margin) {
Boolean.parseBoolean(StringUtils.trimToEmpty(margins[0])), if (margin.contains(";") || margin.contains(",")) {
Boolean.parseBoolean(StringUtils.trimToEmpty(margins[1])), final String[] margins = margin.split("[;,]");
Boolean.parseBoolean(StringUtils.trimToEmpty(margins[2])), if (margins.length != 4) {
Boolean.parseBoolean(StringUtils.trimToEmpty(margins[3])) throw new GuiDevelopmentException(
); "Margin attribute must contain 1 or 4 boolean values separated by ',' or ';", context.getFullFrameId());
} else {
layout.setMargin(Boolean.parseBoolean(margin));
} }
return new MarginInfo(
Boolean.parseBoolean(StringUtils.trimToEmpty(margins[0])),
Boolean.parseBoolean(StringUtils.trimToEmpty(margins[1])),
Boolean.parseBoolean(StringUtils.trimToEmpty(margins[2])),
Boolean.parseBoolean(StringUtils.trimToEmpty(margins[3]))
);
} else {
return new MarginInfo(Boolean.parseBoolean(margin));
} }
} }

View File

@ -18,6 +18,7 @@ package com.haulmont.cuba.gui.xml.layout.loaders;
import com.haulmont.cuba.gui.GuiDevelopmentException; import com.haulmont.cuba.gui.GuiDevelopmentException;
import com.haulmont.cuba.gui.components.GroupBoxLayout; import com.haulmont.cuba.gui.components.GroupBoxLayout;
import com.haulmont.cuba.gui.components.MarginInfo;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.dom4j.Element; import org.dom4j.Element;
@ -56,11 +57,20 @@ public class GroupBoxLayoutLoader extends ContainerLoader<GroupBoxLayout> {
loadWidth(resultComponent, element); loadWidth(resultComponent, element);
loadSpacing(resultComponent, element); loadSpacing(resultComponent, element);
loadOuterMargin(resultComponent, element);
loadSubComponentsAndExpand(resultComponent, element); loadSubComponentsAndExpand(resultComponent, element);
loadShowAsPanel(resultComponent, element); loadShowAsPanel(resultComponent, element);
} }
protected void loadOuterMargin(GroupBoxLayout resultComponent, Element element) {
final String margin = element.attributeValue("outerMargin");
if (!StringUtils.isEmpty(margin)) {
MarginInfo marginInfo = parseMarginInfo(margin);
resultComponent.setOuterMargin(marginInfo);
}
}
protected void loadOrientation(GroupBoxLayout component, Element element) { protected void loadOrientation(GroupBoxLayout component, Element element) {
String orientation = element.attributeValue("orientation"); String orientation = element.attributeValue("orientation");
if (orientation == null) { if (orientation == null) {

View File

@ -26,6 +26,7 @@ import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.VPanel; import com.vaadin.client.ui.VPanel;
import com.vaadin.client.ui.panel.PanelConnector; import com.vaadin.client.ui.panel.PanelConnector;
import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.MarginInfo;
@Connect(CubaGroupBox.class) @Connect(CubaGroupBox.class)
public class CubaGroupBoxConnector extends PanelConnector { public class CubaGroupBoxConnector extends PanelConnector {
@ -111,12 +112,27 @@ public class CubaGroupBoxConnector extends PanelConnector {
int bottom = layoutManager.getInnerHeight(panel.bottomDecoration); int bottom = layoutManager.getInnerHeight(panel.bottomDecoration);
Profiler.leave("PanelConnector.layout getHeights"); Profiler.leave("PanelConnector.layout getHeights");
Profiler.enter("PanelConnector.layout modify style");
Style style = panel.getElement().getStyle(); Style style = panel.getElement().getStyle();
int paddingTop = 0;
int paddingBottom = 0;
if (panel.hasAnyOuterMargin()) {
Profiler.enter("PanelConnector.layout get values from styles");
// Clear previously set values
style.clearPaddingTop();
style.clearPaddingBottom();
// Calculate padding from styles
ComputedStyle computedStyle = new ComputedStyle(panel.getElement());
paddingTop = computedStyle.getIntProperty("padding-top");
paddingBottom = computedStyle.getIntProperty("padding-bottom");
Profiler.leave("PanelConnector.layout get values from styles");
}
Profiler.enter("PanelConnector.layout modify style");
panel.captionWrap.getStyle().setMarginTop(-top, Style.Unit.PX); panel.captionWrap.getStyle().setMarginTop(-top, Style.Unit.PX);
panel.bottomDecoration.getStyle().setMarginBottom(-bottom, Style.Unit.PX); panel.bottomDecoration.getStyle().setMarginBottom(-bottom, Style.Unit.PX);
style.setPaddingTop(top, Style.Unit.PX); style.setPaddingTop(top + paddingTop, Style.Unit.PX);
style.setPaddingBottom(bottom, Style.Unit.PX); style.setPaddingBottom(bottom + paddingBottom, Style.Unit.PX);
Profiler.leave("PanelConnector.layout modify style"); Profiler.leave("PanelConnector.layout modify style");
// Update scroll positions // Update scroll positions
@ -153,6 +169,7 @@ public class CubaGroupBoxConnector extends PanelConnector {
widget.setCollapsable(getState().collapsable); widget.setCollapsable(getState().collapsable);
widget.setExpanded(getState().expanded); widget.setExpanded(getState().expanded);
widget.setShowAsPanel(getState().showAsPanel); widget.setShowAsPanel(getState().showAsPanel);
widget.setOuterMargin(new MarginInfo(getState().outerMarginsBitmask));
if (stateChangeEvent.hasPropertyChanged("caption")) { if (stateChangeEvent.hasPropertyChanged("caption")) {
widget.captionNode.getStyle().clearWidth(); widget.captionNode.getStyle().clearWidth();

View File

@ -25,6 +25,7 @@ import com.google.gwt.user.client.ui.HasEnabled;
import com.haulmont.cuba.web.toolkit.ui.client.Tools; import com.haulmont.cuba.web.toolkit.ui.client.Tools;
import com.vaadin.client.ApplicationConnection; import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.ui.VPanel; import com.vaadin.client.ui.VPanel;
import com.vaadin.shared.ui.MarginInfo;
public class CubaGroupBoxWidget extends VPanel implements HasEnabled { public class CubaGroupBoxWidget extends VPanel implements HasEnabled {
@ -37,6 +38,7 @@ public class CubaGroupBoxWidget extends VPanel implements HasEnabled {
protected boolean enabled = true; protected boolean enabled = true;
protected ExpandHandler expandHandler; protected ExpandHandler expandHandler;
protected MarginInfo marginInfo;
public Element captionWrap; public Element captionWrap;
public Element expander = DOM.createSpan(); public Element expander = DOM.createSpan();
@ -188,4 +190,23 @@ public class CubaGroupBoxWidget extends VPanel implements HasEnabled {
DOM.insertChild(captionNode, icon.getElement(), 1); DOM.insertChild(captionNode, icon.getElement(), 1);
} }
} }
public boolean hasAnyOuterMargin() {
return marginInfo != null
&& marginInfo.hashCode() != 0;
}
public MarginInfo getMarginInfo() {
return marginInfo;
}
public void setOuterMargin(MarginInfo marginInfo) {
this.marginInfo = marginInfo;
if (marginInfo != null) {
setStyleName("c-outer-margin-top", marginInfo.hasTop());
setStyleName("c-outer-margin-right", marginInfo.hasRight());
setStyleName("c-outer-margin-bottom", marginInfo.hasBottom());
setStyleName("c-outer-margin-left", marginInfo.hasLeft());
}
}
} }

View File

@ -28,6 +28,7 @@ import com.haulmont.cuba.web.toolkit.ui.CubaHorizontalActionsLayout;
import com.haulmont.cuba.web.toolkit.ui.CubaOrderedActionsLayout; import com.haulmont.cuba.web.toolkit.ui.CubaOrderedActionsLayout;
import com.haulmont.cuba.web.toolkit.ui.CubaVerticalActionsLayout; import com.haulmont.cuba.web.toolkit.ui.CubaVerticalActionsLayout;
import com.vaadin.event.ShortcutListener; import com.vaadin.event.ShortcutListener;
import com.vaadin.shared.ui.MarginInfo;
import com.vaadin.ui.AbstractOrderedLayout; import com.vaadin.ui.AbstractOrderedLayout;
import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
@ -413,4 +414,18 @@ public class WebGroupBox extends WebAbstractComponent<CubaGroupBox> implements G
} }
} }
} }
@Override
public void setOuterMargin(com.haulmont.cuba.gui.components.MarginInfo marginInfo) {
MarginInfo vMargin = new MarginInfo(marginInfo.hasTop(), marginInfo.hasRight(), marginInfo.hasBottom(),
marginInfo.hasLeft());
component.setOuterMargin(vMargin);
}
@Override
public com.haulmont.cuba.gui.components.MarginInfo getOuterMargin() {
MarginInfo vMargin = component.getOuterMargin();
return new com.haulmont.cuba.gui.components.MarginInfo(vMargin.hasTop(), vMargin.hasRight(), vMargin.hasBottom(),
vMargin.hasLeft());
}
} }

View File

@ -19,6 +19,7 @@ package com.haulmont.cuba.web.toolkit.ui;
import com.haulmont.cuba.web.toolkit.ui.client.groupbox.CubaGroupBoxServerRpc; import com.haulmont.cuba.web.toolkit.ui.client.groupbox.CubaGroupBoxServerRpc;
import com.haulmont.cuba.web.toolkit.ui.client.groupbox.CubaGroupBoxState; import com.haulmont.cuba.web.toolkit.ui.client.groupbox.CubaGroupBoxState;
import com.vaadin.shared.ui.MarginInfo;
import com.vaadin.ui.Component; import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer; import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.Layout; import com.vaadin.ui.Layout;
@ -209,4 +210,12 @@ public class CubaGroupBox extends Panel implements ComponentContainer {
public boolean isShowAsPanel() { public boolean isShowAsPanel() {
return getState(false).showAsPanel; return getState(false).showAsPanel;
} }
public MarginInfo getOuterMargin() {
return new MarginInfo(getState(false).outerMarginsBitmask);
}
public void setOuterMargin(MarginInfo marginInfo) {
getState().outerMarginsBitmask = marginInfo.getBitMask();
}
} }

View File

@ -29,4 +29,6 @@ public class CubaGroupBoxState extends PanelState {
public boolean expanded = true; public boolean expanded = true;
public boolean showAsPanel = false; public boolean showAsPanel = false;
public int outerMarginsBitmask = 0;
} }

View File

@ -227,4 +227,22 @@
.v-panel.c-panel-groupbox > .v-panel-content { .v-panel.c-panel-groupbox > .v-panel-content {
padding: $v-layout-margin-top $v-layout-margin-right $v-layout-margin-bottom $v-layout-margin-left; padding: $v-layout-margin-top $v-layout-margin-right $v-layout-margin-bottom $v-layout-margin-left;
} }
.#{$primary-stylename} {
&.c-outer-margin-top {
padding-top: $v-layout-margin-top;
}
&.c-outer-margin-right {
padding-right: $v-layout-margin-right;
}
&.c-outer-margin-bottom {
padding-bottom: $v-layout-margin-bottom;
}
&.c-outer-margin-left {
padding-left: $v-layout-margin-left;
}
}
} }

View File

@ -188,4 +188,22 @@
.#{$primary-stylename}-caption-start-deco > div { .#{$primary-stylename}-caption-start-deco > div {
@include box-defaults; @include box-defaults;
} }
.#{$primary-stylename} {
&.c-outer-margin-top {
padding-top: 5px;
}
&.c-outer-margin-right {
padding-right: 5px;
}
&.c-outer-margin-bottom {
padding-bottom: 5px;
}
&.c-outer-margin-left {
padding-left: 5px;
}
}
} }