diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java index 1e3754dce85..5ae9841fbe7 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java @@ -347,6 +347,42 @@ public Registration addItemRemovedListener( return addListener(DashboardItemRemovedEvent.class, listener); } + /** + * Adds an item selected change listener to this dashboard. + * + * @param listener + * the listener to add, not null + * @return a handle that can be used for removing the listener + */ + public Registration addItemSelectedChangedListener( + ComponentEventListener listener) { + return addListener(DashboardItemSelectedChangedEvent.class, listener); + } + + /** + * Adds an item move mode change listener to this dashboard. + * + * @param listener + * the listener to add, not null + * @return a handle that can be used for removing the listener + */ + public Registration addItemMoveModeChangedListener( + ComponentEventListener listener) { + return addListener(DashboardItemMoveModeChangedEvent.class, listener); + } + + /** + * Adds an item resize mode change listener to this dashboard. + * + * @param listener + * the listener to add, not null + * @return a handle that can be used for removing the listener + */ + public Registration addItemResizeModeChangedListener( + ComponentEventListener listener) { + return addListener(DashboardItemResizeModeChangedEvent.class, listener); + } + /** * Gets the internationalization object previously set for this component. *

@@ -406,6 +442,21 @@ protected void onAttach(AttachEvent attachEvent) { doUpdateClient(); } + Component getItem(int nodeId) { + return getChildren().map(item -> { + if (nodeId == item.getElement().getNode().getId()) { + return item; + } + if (item instanceof DashboardSection section) { + return section.getWidgets().stream() + .filter(sectionItem -> nodeId == sectionItem + .getElement().getNode().getId()) + .findAny().orElse(null); + } + return null; + }).filter(Objects::nonNull).findAny().orElseThrow(); + } + void updateClient() { if (pendingUpdate) { return; @@ -616,27 +667,12 @@ private void initItemRemovedClientEventListener() { private void handleItemRemovedClientEvent(DomEvent e, String nodeIdKey) { int nodeId = (int) e.getEventData().getNumber(nodeIdKey); - Component removedItem = getRemovedItem(nodeId); + Component removedItem = getItem(nodeId); removedItem.removeFromParent(); fireEvent(new DashboardItemRemovedEvent(this, true, removedItem, getChildren().toList())); } - private Component getRemovedItem(int nodeId) { - return getChildren().map(item -> { - if (nodeId == item.getElement().getNode().getId()) { - return item; - } - if (item instanceof DashboardSection section) { - return section.getWidgets().stream() - .filter(sectionItem -> nodeId == sectionItem - .getElement().getNode().getId()) - .findAny().orElse(null); - } - return null; - }).filter(Objects::nonNull).findAny().orElseThrow(); - } - private void customizeItemMovedEvent() { getElement().executeJs( """ diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemMoveModeChangedEvent.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemMoveModeChangedEvent.java new file mode 100644 index 00000000000..0eed879c23d --- /dev/null +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemMoveModeChangedEvent.java @@ -0,0 +1,72 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.dashboard; + +import com.vaadin.flow.component.Component; +import com.vaadin.flow.component.ComponentEvent; +import com.vaadin.flow.component.ComponentEventListener; +import com.vaadin.flow.component.DomEvent; +import com.vaadin.flow.component.EventData; + +/** + * Widget or section move mode state changed event of {@link Dashboard}. + * + * @author Vaadin Ltd. + * @see Dashboard#addItemMoveModeChangedListener(ComponentEventListener) + */ +@DomEvent("dashboard-item-move-mode-changed") +public class DashboardItemMoveModeChangedEvent + extends ComponentEvent { + + private final Component item; + + private final boolean moveMode; + + /** + * Creates a dashboard item move mode changed event. + * + * @param source + * Dashboard that contains the item of which the move mode state + * has changed + * @param fromClient + * {@code true} if the event originated from the client side, + * {@code false} otherwise + * @param itemNodeId + * The node ID of the item of which the move mode state has + * changed + * @param moveMode + * Whether the item is in move mode + */ + public DashboardItemMoveModeChangedEvent(Dashboard source, + boolean fromClient, + @EventData("event.detail.item.nodeid") int itemNodeId, + @EventData("event.detail.value") boolean moveMode) { + super(source, fromClient); + this.item = source.getItem(itemNodeId); + this.moveMode = moveMode; + } + + /** + * Returns the item of which the move mode state has changed + * + * @return the item of which the move mode state has changed + */ + public Component getItem() { + return item; + } + + /** + * Returns whether the item is in move mode + * + * @return whether the item is in move mode + */ + public boolean isMoveMode() { + return moveMode; + } +} diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizeModeChangedEvent.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizeModeChangedEvent.java new file mode 100644 index 00000000000..1fedfe8bf46 --- /dev/null +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemResizeModeChangedEvent.java @@ -0,0 +1,74 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.dashboard; + +import com.vaadin.flow.component.Component; +import com.vaadin.flow.component.ComponentEvent; +import com.vaadin.flow.component.ComponentEventListener; +import com.vaadin.flow.component.DomEvent; +import com.vaadin.flow.component.EventData; + +/** + * Widget resize mode state changed event of {@link Dashboard}. + * + * @author Vaadin Ltd. + * @see Dashboard#addItemResizeModeChangedListener(ComponentEventListener) + */ +@DomEvent("dashboard-item-resize-mode-changed") +public class DashboardItemResizeModeChangedEvent + extends ComponentEvent { + + private final Component item; + + private final boolean resizeMode; + + /** + * Creates a dashboard item resize mode changed event. + * + * @param source + * Dashboard that contains the item of which the resize mode + * state has changed + * @param fromClient + * {@code true} if the event originated from the client side, + * {@code false} otherwise + * @param itemNodeId + * The node ID of the item of which the resize mode state has + * changed + * @param resizeMode + * Whether the item is in resize mode + */ + public DashboardItemResizeModeChangedEvent(Dashboard source, + boolean fromClient, + @EventData("event.detail.item.nodeid") int itemNodeId, + @EventData("event.detail.value") boolean resizeMode) { + super(source, fromClient); + this.item = source.getWidgets().stream().filter( + widget -> itemNodeId == widget.getElement().getNode().getId()) + .findAny().orElseThrow(); + this.resizeMode = resizeMode; + } + + /** + * Returns the item of which the resize mode state has changed; + * + * @return the item of which the resize mode state has changed + */ + public Component getItem() { + return item; + } + + /** + * Returns whether the item is in resize mode + * + * @return whether the item is in resize mode + */ + public boolean isResizeMode() { + return resizeMode; + } +} diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemSelectedChangedEvent.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemSelectedChangedEvent.java new file mode 100644 index 00000000000..1d1c419f98d --- /dev/null +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardItemSelectedChangedEvent.java @@ -0,0 +1,72 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.dashboard; + +import com.vaadin.flow.component.Component; +import com.vaadin.flow.component.ComponentEvent; +import com.vaadin.flow.component.ComponentEventListener; +import com.vaadin.flow.component.DomEvent; +import com.vaadin.flow.component.EventData; + +/** + * Widget or section selected state changed event of {@link Dashboard}. + * + * @author Vaadin Ltd. + * @see Dashboard#addItemSelectedChangedListener(ComponentEventListener) + */ +@DomEvent("dashboard-item-selected-changed") +public class DashboardItemSelectedChangedEvent + extends ComponentEvent { + + private final Component item; + + private final boolean selected; + + /** + * Creates a dashboard item selected changed event. + * + * @param source + * Dashboard that contains the item of which the selected state + * has changed + * @param fromClient + * {@code true} if the event originated from the client side, + * {@code false} otherwise + * @param itemNodeId + * The node ID of the item of which the selected state has + * changed + * @param selected + * Whether the item is selected + */ + public DashboardItemSelectedChangedEvent(Dashboard source, + boolean fromClient, + @EventData("event.detail.item.nodeid") int itemNodeId, + @EventData("event.detail.value") boolean selected) { + super(source, fromClient); + this.item = source.getItem(itemNodeId); + this.selected = selected; + } + + /** + * Returns the item of which the selected state has changed + * + * @return the item of which the selected state has changed + */ + public Component getItem() { + return item; + } + + /** + * Returns whether the item is selected + * + * @return whether the item is selected + */ + public boolean isSelected() { + return selected; + } +} diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderTest.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardItemMoveTest.java similarity index 62% rename from vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderTest.java rename to vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardItemMoveTest.java index 35f036a0641..bb0519dba18 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragReorderTest.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardItemMoveTest.java @@ -23,14 +23,12 @@ import com.vaadin.flow.component.dashboard.Dashboard; import com.vaadin.flow.component.dashboard.DashboardSection; import com.vaadin.flow.component.dashboard.DashboardWidget; -import com.vaadin.flow.dom.DomEvent; -import com.vaadin.flow.internal.nodefeature.ElementListenerMap; import elemental.json.Json; import elemental.json.JsonArray; import elemental.json.JsonObject; -public class DashboardDragReorderTest extends DashboardTestBase { +public class DashboardItemMoveTest extends DashboardTestBase { private Dashboard dashboard; private JsonArray itemsArray; @@ -50,43 +48,44 @@ public void setup() { } @Test - public void reorderWidget_orderIsUpdated() { - assertRootLevelItemReorder(0, 1); + public void moveWidget_orderIsUpdated() { + assertRootLevelItemMoved(0, 1); } @Test - public void reorderWidgetToSamePosition_orderIsNotUpdated() { - assertRootLevelItemReorder(0, 0); + public void moveWidgetToSamePosition_orderIsNotUpdated() { + assertRootLevelItemMoved(0, 0); } @Test - public void reorderSection_orderIsUpdated() { - assertRootLevelItemReorder(2, 1); + public void moveSection_orderIsUpdated() { + assertRootLevelItemMoved(2, 1); } @Test - public void reorderWidgetInSection_orderIsUpdated() { - assertSectionWidgetReorder(2, 0, 1); + public void moveWidgetInSection_orderIsUpdated() { + assertSectionWidgetMoved(2, 0, 1); } @Test - public void reorderWidgetInSectionToSamePosition_orderIsNotUpdated() { - assertSectionWidgetReorder(2, 0, 0); + public void moveWidgetInSectionToSamePosition_orderIsNotUpdated() { + assertSectionWidgetMoved(2, 0, 0); } @Test - public void setDashboardNotEditable_reorderWidget_orderIsNotUpdated() { + public void setDashboardNotEditable_moveWidget_orderIsNotUpdated() { dashboard.setEditable(false); int movedWidgetNodeId = dashboard.getChildren().toList().get(0) .getElement().getNode().getId(); List expectedRootLevelNodeIds = getRootLevelNodeIds(); - reorderRootLevelItem(0, 1); - fireItemMovedEvent(movedWidgetNodeId); + moveRootLevelItem(0, 1); + DashboardTestHelper.fireItemMovedEvent(dashboard, movedWidgetNodeId, + itemsArray, null); Assert.assertEquals(expectedRootLevelNodeIds, getRootLevelNodeIds()); } @Test - public void reorderWidget_eventCorrectlyFired() { + public void moveWidget_eventCorrectlyFired() { int initialIndex = 0; int finalIndex = 1; Component movedItem = dashboard.getChildren().toList() @@ -96,15 +95,16 @@ public void reorderWidget_eventCorrectlyFired() { .collect(Collectors.toCollection(ArrayList::new)); expectedItems.add(finalIndex, expectedItems.remove(initialIndex)); Runnable itemMoveAction = () -> { - reorderRootLevelItem(initialIndex, finalIndex); - fireItemMovedEvent(movedItemNodeId); + moveRootLevelItem(initialIndex, finalIndex); + DashboardTestHelper.fireItemMovedEvent(dashboard, movedItemNodeId, + itemsArray, null); }; - assertEventCorrectlyFired(itemMoveAction, 1, movedItem, expectedItems, - null); + assertItemMovedEventCorrectlyFired(itemMoveAction, 1, movedItem, + expectedItems, null); } @Test - public void reorderSection_eventCorrectlyFired() { + public void moveSection_eventCorrectlyFired() { int initialIndex = 2; int finalIndex = 1; Component movedItem = dashboard.getChildren().toList() @@ -114,15 +114,16 @@ public void reorderSection_eventCorrectlyFired() { .collect(Collectors.toCollection(ArrayList::new)); expectedItems.add(finalIndex, expectedItems.remove(initialIndex)); Runnable itemMoveAction = () -> { - reorderRootLevelItem(initialIndex, finalIndex); - fireItemMovedEvent(movedItemNodeId); + moveRootLevelItem(initialIndex, finalIndex); + DashboardTestHelper.fireItemMovedEvent(dashboard, movedItemNodeId, + itemsArray, null); }; - assertEventCorrectlyFired(itemMoveAction, 1, movedItem, expectedItems, - null); + assertItemMovedEventCorrectlyFired(itemMoveAction, 1, movedItem, + expectedItems, null); } @Test - public void reorderWidgetInSection_eventCorrectlyFired() { + public void moveWidgetInSection_eventCorrectlyFired() { int sectionIndex = 2; int initialIndex = 0; int finalIndex = 1; @@ -133,15 +134,16 @@ public void reorderWidgetInSection_eventCorrectlyFired() { Component movedItem = section.getWidgets().get(initialIndex); int movedItemNodeId = movedItem.getElement().getNode().getId(); Runnable itemMoveAction = () -> { - reorderSectionWidget(sectionIndex, initialIndex, finalIndex); - fireItemMovedEvent(movedItemNodeId, sectionNodeId); + moveSectionWidget(sectionIndex, initialIndex, finalIndex); + DashboardTestHelper.fireItemMovedEvent(dashboard, movedItemNodeId, + itemsArray, sectionNodeId); }; - assertEventCorrectlyFired(itemMoveAction, 1, movedItem, expectedItems, - section); + assertItemMovedEventCorrectlyFired(itemMoveAction, 1, movedItem, + expectedItems, section); } @Test - public void setDashboardNotEditable_reorderWidget_eventNotFired() { + public void setDashboardNotEditable_moveWidget_eventNotFired() { dashboard.setEditable(false); int initialIndex = 0; int finalIndex = 1; @@ -149,13 +151,55 @@ public void setDashboardNotEditable_reorderWidget_eventNotFired() { .get(initialIndex); int movedItemNodeId = movedItem.getElement().getNode().getId(); Runnable itemMoveAction = () -> { - reorderRootLevelItem(initialIndex, finalIndex); - fireItemMovedEvent(movedItemNodeId); + moveRootLevelItem(initialIndex, finalIndex); + DashboardTestHelper.fireItemMovedEvent(dashboard, movedItemNodeId, + itemsArray, null); }; - assertEventCorrectlyFired(itemMoveAction, 0, null, null, null); + assertItemMovedEventCorrectlyFired(itemMoveAction, 0, null, null, null); } - private void assertEventCorrectlyFired(Runnable itemMoveAction, + @Test + public void changeWidgetMoveMode_eventCorrectlyFired() { + Component movedItem = dashboard.getChildren().toList().get(0); + assertItemMoveModeChangedEventCorrectlyFired(movedItem, true); + assertItemMoveModeChangedEventCorrectlyFired(movedItem, false); + } + + @Test + public void changeSectionMoveMode_eventCorrectlyFired() { + Component movedItem = dashboard.getChildren().toList().get(2); + assertItemMoveModeChangedEventCorrectlyFired(movedItem, true); + assertItemMoveModeChangedEventCorrectlyFired(movedItem, false); + } + + @Test + public void changeWidgetInSectionMoveMode_eventCorrectlyFired() { + DashboardSection section = (DashboardSection) dashboard.getChildren() + .toList().get(2); + Component movedItem = section.getWidgets().get(0); + assertItemMoveModeChangedEventCorrectlyFired(movedItem, true); + assertItemMoveModeChangedEventCorrectlyFired(movedItem, false); + } + + private void assertItemMoveModeChangedEventCorrectlyFired(Component item, + boolean moveMode) { + AtomicInteger listenerInvokedCount = new AtomicInteger(0); + AtomicReference eventItem = new AtomicReference<>(); + AtomicReference eventIsMoveMode = new AtomicReference<>(); + dashboard.addItemMoveModeChangedListener(e -> { + listenerInvokedCount.incrementAndGet(); + eventItem.set(e.getItem()); + eventIsMoveMode.set(e.isMoveMode()); + e.unregisterListener(); + }); + DashboardTestHelper.fireItemMoveModeChangedEvent(dashboard, + item.getElement().getNode().getId(), moveMode); + Assert.assertEquals(1, listenerInvokedCount.get()); + Assert.assertEquals(item, eventItem.get()); + Assert.assertEquals(moveMode, eventIsMoveMode.get()); + } + + private void assertItemMovedEventCorrectlyFired(Runnable itemMoveAction, int expectedListenerInvokedCount, Component expectedItem, List expectedItems, DashboardSection expectedSection) { AtomicInteger listenerInvokedCount = new AtomicInteger(0); @@ -180,23 +224,6 @@ private void assertEventCorrectlyFired(Runnable itemMoveAction, } } - private void fireItemMovedEvent(int itemNodeId) { - fireItemMovedEvent(itemNodeId, null); - } - - private void fireItemMovedEvent(int itemNodeId, Integer sectionNodeId) { - JsonObject eventData = Json.createObject(); - eventData.put("event.detail.item", itemNodeId); - eventData.put("event.detail.items", itemsArray); - if (sectionNodeId != null) { - eventData.put("event.detail.section", sectionNodeId); - } - DomEvent itemMovedDomEvent = new DomEvent(dashboard.getElement(), - "dashboard-item-moved-flow", eventData); - dashboard.getElement().getNode().getFeature(ElementListenerMap.class) - .fireEvent(itemMovedDomEvent); - } - private List getSectionWidgetNodeIds(int sectionIndex) { DashboardSection section = (DashboardSection) dashboard.getChildren() .toList().get(sectionIndex); @@ -230,45 +257,46 @@ private List getExpectedRootLevelItemNodeIds(int initialIndex, return expectedRootLevelNodeIds; } - private void reorderSectionWidget(int sectionIndex, int initialIndex, + private void moveSectionWidget(int sectionIndex, int initialIndex, int finalIndex) { JsonObject sectionItem = itemsArray.get(sectionIndex); JsonArray sectionItems = sectionItem.getArray("items"); sectionItem.put("items", - reorderItemInJsonArray(initialIndex, finalIndex, sectionItems)); + moveItemInJsonArray(initialIndex, finalIndex, sectionItems)); } - private void reorderRootLevelItem(int initialIndex, int finalIndex) { - itemsArray = reorderItemInJsonArray(initialIndex, finalIndex, - itemsArray); + private void moveRootLevelItem(int initialIndex, int finalIndex) { + itemsArray = moveItemInJsonArray(initialIndex, finalIndex, itemsArray); } - private void assertSectionWidgetReorder(int sectionIndex, int initialIndex, + private void assertSectionWidgetMoved(int sectionIndex, int initialIndex, int finalIndex) { DashboardSection section = (DashboardSection) dashboard.getChildren() .toList().get(sectionIndex); int sectionNodeId = section.getElement().getNode().getId(); int movedWidgetNodeId = section.getWidgets().get(initialIndex) .getElement().getNode().getId(); - reorderSectionWidget(sectionIndex, initialIndex, finalIndex); + moveSectionWidget(sectionIndex, initialIndex, finalIndex); List expectedSectionWidgetNodeIds = getExpectedSectionWidgetNodeIds( sectionIndex, initialIndex, finalIndex); - fireItemMovedEvent(movedWidgetNodeId, sectionNodeId); + DashboardTestHelper.fireItemMovedEvent(dashboard, movedWidgetNodeId, + itemsArray, sectionNodeId); Assert.assertEquals(expectedSectionWidgetNodeIds, getSectionWidgetNodeIds(sectionIndex)); } - private void assertRootLevelItemReorder(int initialIndex, int finalIndex) { + private void assertRootLevelItemMoved(int initialIndex, int finalIndex) { int movedItemNodeId = dashboard.getChildren().toList().get(initialIndex) .getElement().getNode().getId(); - reorderRootLevelItem(initialIndex, finalIndex); + moveRootLevelItem(initialIndex, finalIndex); List expectedRootLevelNodeIds = getExpectedRootLevelItemNodeIds( initialIndex, finalIndex); - fireItemMovedEvent(movedItemNodeId); + DashboardTestHelper.fireItemMovedEvent(dashboard, movedItemNodeId, + itemsArray, null); Assert.assertEquals(expectedRootLevelNodeIds, getRootLevelNodeIds()); } - private static JsonArray reorderItemInJsonArray(int initialIndex, + private static JsonArray moveItemInJsonArray(int initialIndex, int finalIndex, JsonArray initialArray) { JsonObject itemToMove = initialArray.get(initialIndex); initialArray.remove(initialIndex); diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragResizeTest.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardItemResizeTest.java similarity index 63% rename from vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragResizeTest.java rename to vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardItemResizeTest.java index 7a396a7e4bb..057214541a1 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardDragResizeTest.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardItemResizeTest.java @@ -20,13 +20,8 @@ import com.vaadin.flow.component.dashboard.Dashboard; import com.vaadin.flow.component.dashboard.DashboardSection; import com.vaadin.flow.component.dashboard.DashboardWidget; -import com.vaadin.flow.dom.DomEvent; -import com.vaadin.flow.internal.nodefeature.ElementListenerMap; -import elemental.json.Json; -import elemental.json.JsonObject; - -public class DashboardDragResizeTest extends DashboardTestBase { +public class DashboardItemResizeTest extends DashboardTestBase { private Dashboard dashboard; @Before @@ -76,7 +71,8 @@ public void resizeWidgetInSectionBothHorizontallyAndVertically_sizeIsUpdated() { public void setDashboardNotEditable_resizeWidget_sizeIsNotUpdated() { dashboard.setEditable(false); DashboardWidget widgetToResize = dashboard.getWidgets().get(0); - fireItemResizedEvent(widgetToResize, 2, 2); + DashboardTestHelper.fireItemResizedEvent(dashboard, widgetToResize, 2, + 2); Assert.assertEquals(1, widgetToResize.getColspan()); Assert.assertEquals(1, widgetToResize.getRowspan()); } @@ -85,7 +81,7 @@ public void setDashboardNotEditable_resizeWidget_sizeIsNotUpdated() { public void resizeWidget_eventCorrectlyFired() { DashboardWidget resizedWidget = (DashboardWidget) dashboard .getChildren().toList().get(0); - assertEventCorrectlyFired(resizedWidget, 1, resizedWidget, + assertItemResizedEventCorrectlyFired(resizedWidget, 1, resizedWidget, dashboard.getChildren().toList()); } @@ -94,7 +90,7 @@ public void resizeWidgetInSection_eventCorrectlyFired() { DashboardSection section = (DashboardSection) dashboard.getChildren() .toList().get(1); DashboardWidget resizedWidget = section.getWidgets().get(0); - assertEventCorrectlyFired(resizedWidget, 1, resizedWidget, + assertItemResizedEventCorrectlyFired(resizedWidget, 1, resizedWidget, dashboard.getChildren().toList()); } @@ -103,12 +99,28 @@ public void setDashboardNotEditable_resizeWidget_eventNotFired() { dashboard.setEditable(false); DashboardWidget resizedWidget = (DashboardWidget) dashboard .getChildren().toList().get(0); - assertEventCorrectlyFired(resizedWidget, 0, null, null); + assertItemResizedEventCorrectlyFired(resizedWidget, 0, null, null); + } + + @Test + public void changeWidgetResizeMode_eventCorrectlyFired() { + Component resizedItem = dashboard.getChildren().toList().get(0); + assertItemResizeModeChangedEventCorrectlyFired(resizedItem, true); + assertItemResizeModeChangedEventCorrectlyFired(resizedItem, false); + } + + @Test + public void changeWidgetInSectionResizeMode_eventCorrectlyFired() { + DashboardSection section = (DashboardSection) dashboard.getChildren() + .toList().get(1); + Component resizedItem = section.getWidgets().get(0); + assertItemResizeModeChangedEventCorrectlyFired(resizedItem, true); + assertItemResizeModeChangedEventCorrectlyFired(resizedItem, false); } - private void assertEventCorrectlyFired(DashboardWidget widgetToResize, - int expectedListenerInvokedCount, Component expectedResizedWidget, - List expectedItems) { + private void assertItemResizedEventCorrectlyFired( + DashboardWidget widgetToResize, int expectedListenerInvokedCount, + Component expectedResizedWidget, List expectedItems) { AtomicInteger listenerInvokedCount = new AtomicInteger(0); AtomicReference eventResizedWidget = new AtomicReference<>(); AtomicReference> eventItems = new AtomicReference<>(); @@ -118,7 +130,8 @@ private void assertEventCorrectlyFired(DashboardWidget widgetToResize, eventItems.set(e.getItems()); e.unregisterListener(); }); - fireItemResizedEvent(widgetToResize, 2, 2); + DashboardTestHelper.fireItemResizedEvent(dashboard, widgetToResize, 2, + 2); Assert.assertEquals(expectedListenerInvokedCount, listenerInvokedCount.get()); if (expectedListenerInvokedCount > 0) { @@ -128,30 +141,37 @@ private void assertEventCorrectlyFired(DashboardWidget widgetToResize, } } + private void assertItemResizeModeChangedEventCorrectlyFired(Component item, + boolean resizeMode) { + AtomicInteger listenerInvokedCount = new AtomicInteger(0); + AtomicReference eventItem = new AtomicReference<>(); + AtomicReference eventIsResizeMode = new AtomicReference<>(); + dashboard.addItemResizeModeChangedListener(e -> { + listenerInvokedCount.incrementAndGet(); + eventItem.set(e.getItem()); + eventIsResizeMode.set(e.isResizeMode()); + e.unregisterListener(); + }); + DashboardTestHelper.fireItemResizeModeChangedEvent(dashboard, + item.getElement().getNode().getId(), resizeMode); + Assert.assertEquals(1, listenerInvokedCount.get()); + Assert.assertEquals(item, eventItem.get()); + Assert.assertEquals(resizeMode, eventIsResizeMode.get()); + } + private void assertWidgetResized(int widgetIndexToResize, int targetColspan, int targetRowspan) { DashboardWidget widgetToResize = dashboard.getWidgets() .get(widgetIndexToResize); // Assert widget is enlarged - fireItemResizedEvent(widgetToResize, targetColspan, targetRowspan); + DashboardTestHelper.fireItemResizedEvent(dashboard, widgetToResize, + targetColspan, targetRowspan); Assert.assertEquals(targetColspan, widgetToResize.getColspan()); Assert.assertEquals(targetRowspan, widgetToResize.getRowspan()); // Assert widget is shrunk - fireItemResizedEvent(widgetToResize, 1, 1); + DashboardTestHelper.fireItemResizedEvent(dashboard, widgetToResize, 1, + 1); Assert.assertEquals(1, widgetToResize.getColspan()); Assert.assertEquals(1, widgetToResize.getRowspan()); } - - private void fireItemResizedEvent(DashboardWidget widget, int targetColspan, - int targetRowspan) { - JsonObject eventData = Json.createObject(); - eventData.put("event.detail.item.nodeid", - widget.getElement().getNode().getId()); - eventData.put("event.detail.item.rowspan", targetRowspan); - eventData.put("event.detail.item.colspan", targetColspan); - DomEvent itemResizedDomEvent = new DomEvent(dashboard.getElement(), - "dashboard-item-resized", eventData); - dashboard.getElement().getNode().getFeature(ElementListenerMap.class) - .fireEvent(itemResizedDomEvent); - } } diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardTest.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardTest.java index 8c73e5eabd5..5e3624bb1fe 100644 --- a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardTest.java +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardTest.java @@ -24,11 +24,6 @@ import com.vaadin.flow.component.dashboard.DashboardSection; import com.vaadin.flow.component.dashboard.DashboardWidget; import com.vaadin.flow.component.html.Div; -import com.vaadin.flow.dom.DomEvent; -import com.vaadin.flow.internal.nodefeature.ElementListenerMap; - -import elemental.json.Json; -import elemental.json.JsonObject; public class DashboardTest extends DashboardTestBase { private Dashboard dashboard; @@ -836,7 +831,7 @@ public void dashboardNotEditable_removeWidget_widgetIsNotRemoved() { fakeClientCommunication(); int expectedWidgetCount = dashboard.getWidgets().size(); int expectedNodeId = widgetToRemove.getElement().getNode().getId(); - fireItemRemovedEvent(expectedNodeId); + DashboardTestHelper.fireItemRemovedEvent(dashboard, expectedNodeId); Assert.assertEquals(expectedWidgetCount, dashboard.getWidgets().size()); Set actualNodeIds = dashboard.getWidgets().stream() .map(widget -> widget.getElement().getNode().getId()) @@ -852,7 +847,7 @@ public void setDashboardEditable_removeWidget_widgetIsRemoved() { fakeClientCommunication(); int expectedWidgetCount = dashboard.getWidgets().size() - 1; int nodeIdToBeRemoved = widgetToRemove.getElement().getNode().getId(); - fireItemRemovedEvent(nodeIdToBeRemoved); + DashboardTestHelper.fireItemRemovedEvent(dashboard, nodeIdToBeRemoved); Assert.assertEquals(expectedWidgetCount, dashboard.getWidgets().size()); Set actualNodeIds = dashboard.getWidgets().stream() .map(widget -> widget.getElement().getNode().getId()) @@ -860,6 +855,7 @@ public void setDashboardEditable_removeWidget_widgetIsRemoved() { Assert.assertFalse(actualNodeIds.contains(nodeIdToBeRemoved)); } + @Test public void setDashboardEditable_removeWidget_eventCorrectlyFired() { dashboard.setEditable(true); DashboardWidget widget = new DashboardWidget(); @@ -938,6 +934,48 @@ public void getSectionVisibility_returnsTrue() { Assert.assertTrue(section.isVisible()); } + @Test + public void changeWidgetSelectedState_eventCorrectlyFired() { + DashboardWidget widget = new DashboardWidget(); + dashboard.add(widget); + assertItemSelectedChangedEventCorrectlyFired(widget, true); + assertItemSelectedChangedEventCorrectlyFired(widget, false); + } + + @Test + public void changeSectionSelectedState_eventCorrectlyFired() { + DashboardSection section = dashboard.addSection(); + assertItemSelectedChangedEventCorrectlyFired(section, true); + assertItemSelectedChangedEventCorrectlyFired(section, false); + } + + @Test + public void changeWidgetInSectionSelectedState_eventCorrectlyFired() { + DashboardSection section = dashboard.addSection(); + DashboardWidget widget = new DashboardWidget(); + section.add(widget); + assertItemSelectedChangedEventCorrectlyFired(widget, true); + assertItemSelectedChangedEventCorrectlyFired(widget, false); + } + + private void assertItemSelectedChangedEventCorrectlyFired(Component item, + boolean selected) { + AtomicInteger listenerInvokedCount = new AtomicInteger(0); + AtomicReference eventItem = new AtomicReference<>(); + AtomicReference eventIsSelected = new AtomicReference<>(); + dashboard.addItemSelectedChangedListener(e -> { + listenerInvokedCount.incrementAndGet(); + eventItem.set(e.getItem()); + eventIsSelected.set(e.isSelected()); + e.unregisterListener(); + }); + DashboardTestHelper.fireItemSelectedChangedEvent(dashboard, + item.getElement().getNode().getId(), selected); + Assert.assertEquals(1, listenerInvokedCount.get()); + Assert.assertEquals(item, eventItem.get()); + Assert.assertEquals(selected, eventIsSelected.get()); + } + private void assertItemRemoveEventCorrectlyFired(int nodeIdToRemove, int expectedListenerInvokedCount, Component expectedRemovedItem, List expectedItems) { @@ -950,7 +988,7 @@ private void assertItemRemoveEventCorrectlyFired(int nodeIdToRemove, eventItems.set(e.getItems()); e.unregisterListener(); }); - fireItemRemovedEvent(nodeIdToRemove); + DashboardTestHelper.fireItemRemovedEvent(dashboard, nodeIdToRemove); Assert.assertEquals(expectedListenerInvokedCount, listenerInvokedCount.get()); if (expectedListenerInvokedCount > 0) { @@ -958,13 +996,4 @@ private void assertItemRemoveEventCorrectlyFired(int nodeIdToRemove, Assert.assertEquals(expectedItems, eventItems.get()); } } - - private void fireItemRemovedEvent(int nodeId) { - JsonObject eventData = Json.createObject(); - eventData.put("event.detail.item.nodeid", nodeId); - DomEvent itemRemovedDomEvent = new DomEvent(dashboard.getElement(), - "dashboard-item-removed", eventData); - dashboard.getElement().getNode().getFeature(ElementListenerMap.class) - .fireEvent(itemRemovedDomEvent); - } } diff --git a/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardTestHelper.java b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardTestHelper.java new file mode 100644 index 00000000000..9b21f6c173d --- /dev/null +++ b/vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/test/java/com/vaadin/flow/component/dashboard/tests/DashboardTestHelper.java @@ -0,0 +1,81 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.dashboard.tests; + +import com.vaadin.flow.component.dashboard.Dashboard; +import com.vaadin.flow.component.dashboard.DashboardWidget; +import com.vaadin.flow.dom.DomEvent; +import com.vaadin.flow.internal.nodefeature.ElementListenerMap; + +import elemental.json.Json; +import elemental.json.JsonArray; +import elemental.json.JsonObject; + +public class DashboardTestHelper { + + static void fireItemResizeModeChangedEvent(Dashboard dashboard, + int itemNodeId, boolean resizeMode) { + JsonObject eventData = Json.createObject(); + eventData.put("event.detail.item.nodeid", itemNodeId); + eventData.put("event.detail.value", resizeMode); + fireDomEvent(dashboard, "dashboard-item-resize-mode-changed", + eventData); + } + + static void fireItemResizedEvent(Dashboard dashboard, + DashboardWidget widget, int targetColspan, int targetRowspan) { + JsonObject eventData = Json.createObject(); + eventData.put("event.detail.item.nodeid", + widget.getElement().getNode().getId()); + eventData.put("event.detail.item.rowspan", targetRowspan); + eventData.put("event.detail.item.colspan", targetColspan); + fireDomEvent(dashboard, "dashboard-item-resized", eventData); + } + + static void fireItemMovedEvent(Dashboard dashboard, int itemNodeId, + JsonArray itemsArray, Integer sectionNodeId) { + JsonObject eventData = Json.createObject(); + eventData.put("event.detail.item", itemNodeId); + eventData.put("event.detail.items", itemsArray); + if (sectionNodeId != null) { + eventData.put("event.detail.section", sectionNodeId); + } + fireDomEvent(dashboard, "dashboard-item-moved-flow", eventData); + } + + static void fireItemMoveModeChangedEvent(Dashboard dashboard, + int itemNodeId, boolean moveMode) { + JsonObject eventData = Json.createObject(); + eventData.put("event.detail.item.nodeid", itemNodeId); + eventData.put("event.detail.value", moveMode); + fireDomEvent(dashboard, "dashboard-item-move-mode-changed", eventData); + } + + static void fireItemRemovedEvent(Dashboard dashboard, int nodeId) { + JsonObject eventData = Json.createObject(); + eventData.put("event.detail.item.nodeid", nodeId); + fireDomEvent(dashboard, "dashboard-item-removed", eventData); + } + + static void fireItemSelectedChangedEvent(Dashboard dashboard, + int itemNodeId, boolean selected) { + JsonObject eventData = Json.createObject(); + eventData.put("event.detail.item.nodeid", itemNodeId); + eventData.put("event.detail.value", selected); + fireDomEvent(dashboard, "dashboard-item-selected-changed", eventData); + } + + private static void fireDomEvent(Dashboard dashboard, String eventType, + JsonObject eventData) { + DomEvent domEvent = new DomEvent(dashboard.getElement(), eventType, + eventData); + dashboard.getElement().getNode().getFeature(ElementListenerMap.class) + .fireEvent(domEvent); + } +}