From c1aef3c50b540230958f839cd8eabb635e4f0a73 Mon Sep 17 00:00:00 2001 From: Ilia Motornyi Date: Thu, 13 Jul 2017 10:38:05 +0300 Subject: [PATCH] Delegate properties to Composite's root if possible Fixes #9670 --- .../main/java/com/vaadin/ui/Composite.java | 81 ++++++++++++------- .../com/vaadin/tests/components/TreeTest.java | 39 +++++++-- 2 files changed, 81 insertions(+), 39 deletions(-) diff --git a/server/src/main/java/com/vaadin/ui/Composite.java b/server/src/main/java/com/vaadin/ui/Composite.java index 3c1e9b03cc..755b25b742 100644 --- a/server/src/main/java/com/vaadin/ui/Composite.java +++ b/server/src/main/java/com/vaadin/ui/Composite.java @@ -19,10 +19,10 @@ package com.vaadin.ui; import java.util.Collections; import java.util.Iterator; import java.util.Objects; -import java.util.Optional; import com.vaadin.server.ErrorMessage; import com.vaadin.server.Resource; +import com.vaadin.server.SerializableFunction; import com.vaadin.shared.ui.ContentMode; import com.vaadin.shared.ui.composite.CompositeState; @@ -48,7 +48,6 @@ import com.vaadin.shared.ui.composite.CompositeState; */ public class Composite extends AbstractComponent implements HasComponents { - private static final String COMPOSITE_HAS_NO_DOM_OR_WIDGET = "A composite has no DOM or widget"; /** * The contained component. */ @@ -123,7 +122,7 @@ public class Composite extends AbstractComponent implements HasComponents { if (getCompositionRoot() != null) { return Collections.singletonList(getCompositionRoot()).iterator(); } else { - return Collections. emptyList().iterator(); + return Collections.emptyList().iterator(); } } @@ -148,43 +147,65 @@ public class Composite extends AbstractComponent implements HasComponents { @Override public String getStyleName() { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + Component root = getCompositionRoot(); + return root == null ? "" : root.getStyleName(); } @Override public void setStyleName(String style) { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + getRootOrThrow().setStyleName(style); } @Override public void setStyleName(String style, boolean add) { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + getRootAbstractComponentOrThrow().setStyleName(style, add); } @Override public void addStyleName(String style) { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + getRootOrThrow().addStyleName(style); } @Override public void removeStyleName(String style) { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + getRootOrThrow().removeStyleName(style); } @Override public String getPrimaryStyleName() { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + return getRootAbstractComponentPropertyOrNull(AbstractComponent::getPrimaryStyleName); } @Override public void setPrimaryStyleName(String style) { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + getRootOrThrow().setPrimaryStyleName(style); } private Component getRootOrThrow() { - return Optional.ofNullable(getCompositionRoot()) - .orElseThrow(() -> new IllegalStateException( - "Composition root has not been set")); + Component root = getCompositionRoot(); + if(root == null) throw new IllegalStateException("Composition root has not been set"); + return root; + } + + private AbstractComponent getRootAbstractComponentOrThrow() { + Component root = getRootOrThrow(); + if (!(root instanceof AbstractComponent)) { + throw new IllegalStateException("Composition root is not AbstractComponent"); + } + return (AbstractComponent) root; + } + + private T getRootPropertyOrNull(SerializableFunction getter) { + Component root = getCompositionRoot(); + return root == null ? null : getter.apply(root); + } + + private T getRootAbstractComponentPropertyOrNull(SerializableFunction getter) { + Component root = getCompositionRoot(); + if(root instanceof AbstractComponent) { + return getter.apply((AbstractComponent) root); + } + return null; } @Override @@ -249,84 +270,82 @@ public class Composite extends AbstractComponent implements HasComponents { @Override public void setId(String id) { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + getRootOrThrow().setId(id); } @Override public String getId() { - // Design.read relies on being able to call this - return null; + return getRootPropertyOrNull(Component::getId); } @Override public void setDebugId(String id) { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + getRootAbstractComponentOrThrow().setDebugId(id); } @Override public String getDebugId() { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + return getRootAbstractComponentPropertyOrNull(AbstractComponent::getDebugId); } @Override public String getCaption() { - // Design.read relies on being able to call this - return null; + return getRootPropertyOrNull(Component::getCaption); } @Override public void setCaption(String caption) { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + getRootOrThrow().setCaption(caption); } @Override public void setCaptionAsHtml(boolean captionAsHtml) { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + getRootAbstractComponentOrThrow().setCaptionAsHtml(captionAsHtml); } @Override public boolean isCaptionAsHtml() { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + return getRootAbstractComponentPropertyOrNull(AbstractComponent::isCaptionAsHtml); } @Override public Resource getIcon() { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + return getRootPropertyOrNull(Component::getIcon); } @Override public void setIcon(Resource icon) { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + getRootOrThrow().setIcon(icon); } @Override public String getDescription() { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + return getRootOrThrow().getDescription(); } @Override public void setDescription(String description) { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + getRootAbstractComponentOrThrow().setDescription(description); } @Override public void setDescription(String description, ContentMode mode) { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + getRootAbstractComponentOrThrow().setDescription(description, mode); } @Override public ErrorMessage getErrorMessage() { - return null; + return getRootAbstractComponentPropertyOrNull(AbstractComponent::getErrorMessage); } @Override public ErrorMessage getComponentError() { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + return getRootAbstractComponentPropertyOrNull(AbstractComponent::getComponentError); } @Override public void setComponentError(ErrorMessage componentError) { - throw new UnsupportedOperationException(COMPOSITE_HAS_NO_DOM_OR_WIDGET); + getRootAbstractComponentOrThrow().setComponentError(componentError); } } diff --git a/server/src/test/java/com/vaadin/tests/components/TreeTest.java b/server/src/test/java/com/vaadin/tests/components/TreeTest.java index c4ee9ae3d5..8fc5fc28b6 100644 --- a/server/src/test/java/com/vaadin/tests/components/TreeTest.java +++ b/server/src/test/java/com/vaadin/tests/components/TreeTest.java @@ -1,18 +1,26 @@ package com.vaadin.tests.components; -import org.junit.Assert; -import org.junit.Test; - import com.vaadin.data.TreeData; import com.vaadin.data.provider.TreeDataProvider; import com.vaadin.event.CollapseEvent; import com.vaadin.event.CollapseEvent.CollapseListener; import com.vaadin.event.ExpandEvent; import com.vaadin.event.ExpandEvent.ExpandListener; +import com.vaadin.server.ThemeResource; import com.vaadin.ui.Tree; +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class TreeTest { + public static final String TEST_CAPTION = "test caption"; + public static final String TEST_DESCRIPTION = "test description"; + public static final String TEST_RESOURCE_ID = "nothing.gif"; + private static class TreeCollapseExpandListener implements ExpandListener, CollapseListener { @@ -26,7 +34,7 @@ public class TreeTest { @Override public void itemCollapse(CollapseEvent event) { - Assert.assertEquals("Source component was incorrect", tree, + assertEquals("Source component was incorrect", tree, event.getComponent()); Assert.assertFalse("Multiple collapse events", collapsed); collapsed = true; @@ -34,7 +42,7 @@ public class TreeTest { @Override public void itemExpand(ExpandEvent event) { - Assert.assertEquals("Source component was incorrect", tree, + assertEquals("Source component was incorrect", tree, event.getComponent()); Assert.assertFalse("Multiple expand events", expanded); expanded = true; @@ -65,12 +73,27 @@ public class TreeTest { Assert.assertFalse(listener.isExpanded()); tree.expand("Foo"); - Assert.assertTrue("Item not expanded", tree.isExpanded("Foo")); - Assert.assertTrue("Expand event not fired", listener.isExpanded()); + assertTrue("Item not expanded", tree.isExpanded("Foo")); + assertTrue("Expand event not fired", listener.isExpanded()); Assert.assertFalse(listener.isCollapsed()); tree.collapse("Foo"); Assert.assertFalse("Item not collapsed", tree.isExpanded("Foo")); - Assert.assertTrue("Collapse event not fired", listener.isCollapsed()); + assertTrue("Collapse event not fired", listener.isCollapsed()); } + @Test + public void testComponentProperties() { + Tree tree = new Tree<>(); + tree.setCaption(TEST_CAPTION); + tree.setDescription(TEST_DESCRIPTION); + tree.setIcon(new ThemeResource(TEST_RESOURCE_ID)); + + assertEquals(TEST_CAPTION,tree.getCaption()); + assertEquals(TEST_DESCRIPTION,tree.getDescription()); + assertEquals(TEST_RESOURCE_ID,tree.getIcon().toString()); + + assertFalse(tree.isCaptionAsHtml()); + tree.setCaptionAsHtml(true); + assertTrue(tree.isCaptionAsHtml()); + } } -- 2.39.5