This is an automated email from the git hooks/post-receive script. New commit to branch feature/7591_Correction_migration_entites_d_un_parent_a_un_autre in repository observe. See https://gitlab.nuiton.org/codelutin/observe.git commit 88fc833a46226af5cd258ad208fc34869c5bb14a Author: Samuel Maisonneuve <maisonneuve@codelutin.com> Date: Tue Aug 2 16:59:05 2016 +0200 Fix move multiple entities from a parent node to another : an open entity has to be closed Also adding a reloadNodeSubTree method to properly regenerate a node sub tree. The move actions algoritms have been rewritten refs #7591 --- .../shared/MoveActivityLonglinesUIAction.java | 72 +++++----------------- .../actions/shared/MoveActivitySeinesUIAction.java | 64 +++++-------------- .../ui/actions/shared/MoveRoutesUIAction.java | 71 +++++---------------- .../fr/ird/observe/ui/tree/ObserveTreeHelper.java | 29 ++++++--- 4 files changed, 73 insertions(+), 163 deletions(-) diff --git a/observe-application-swing/src/main/java/fr/ird/observe/ui/actions/shared/MoveActivityLonglinesUIAction.java b/observe-application-swing/src/main/java/fr/ird/observe/ui/actions/shared/MoveActivityLonglinesUIAction.java index 8bf426b..da262f6 100644 --- a/observe-application-swing/src/main/java/fr/ird/observe/ui/actions/shared/MoveActivityLonglinesUIAction.java +++ b/observe-application-swing/src/main/java/fr/ird/observe/ui/actions/shared/MoveActivityLonglinesUIAction.java @@ -43,9 +43,9 @@ import org.apache.commons.logging.LogFactory; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; -import javax.swing.tree.TreePath; import java.awt.event.ActionEvent; import java.util.List; +import java.util.Optional; import static org.nuiton.i18n.I18n.n; import static org.nuiton.i18n.I18n.t; @@ -102,7 +102,6 @@ public class MoveActivityLonglinesUIAction extends AbstractUIAction { ObserveTreeHelper treeHelper = getMainUI().getTreeHelper(); ObserveNode oldActivitiesNode = treeHelper.getSelectedNode(); ObserveNode oldTripLonglineNode = oldActivitiesNode.getParent(); - String oldTripLonglineId = oldTripLonglineNode.getId(); // choose the new tripLongline String tripLonglineId = chooseNewTripLongline(ui, oldTripLonglineNode); @@ -115,7 +114,7 @@ public class MoveActivityLonglinesUIAction extends AbstractUIAction { List<Integer> positions = service.moveActivityLonglinesToTripLongline(activityIds, tripLonglineId); // update the tree - updateTree(oldActivitiesNode, oldTripLonglineId, tripLonglineId, activityIds, positions); + updateTree(oldActivitiesNode, tripLonglineId, activityIds); } } @@ -157,10 +156,8 @@ public class MoveActivityLonglinesUIAction extends AbstractUIAction { } protected void updateTree(ObserveNode oldActivitiesNode, - String oldTripLonglineId, String tripLonglineId, - List<String> activityIds, - List<Integer> positions) { + List<String> activityIds) { ObserveSwingApplicationContext applicationContext = ObserveSwingApplicationContext.get(); ObserveOpenDataManager openDataManager = applicationContext.getOpenDataManager(); @@ -173,59 +170,24 @@ public class MoveActivityLonglinesUIAction extends AbstractUIAction { TripLonglineDto.PROPERTY_ACTIVITY_LONGLINE); ObserveNode newActivitiesNode = treeHelper.getChild(newTripLonglineNode, activitiesNodeId); - for (int i = 0, s = positions.size(); i < s; i++) { + // Let's check if we're moving an open activity + Optional<String> openActivity = activityIds + .stream() + .filter(openDataManager::isOpenActivityLongline) + .findFirst(); - String activityId = activityIds.get(i); - ObserveNode activityNode = treeHelper.getChild(oldActivitiesNode, activityId); - boolean wasOpen = activityNode.isOpen(); - treeHelper.removeNode(activityNode); - - if (wasOpen) { - openDataManager.closeTripLongline(oldTripLonglineId); - openDataManager.openTripLongline(programNode.getId(), tripLonglineId); - openDataManager.openActivityLongline(tripLonglineId, activityId); // We need to reopen the activity since closing the trip also close the activity - } - - ObserveNode newRouteNode = treeHelper.getChild(newActivitiesNode, activityId); - - if (newRouteNode == null) { - - // create it - if (log.isInfoEnabled()) { - log.info("Insert activity node: "); - } - treeHelper.insertNode(newActivitiesNode, activityNode, positions.get(i)); - } + // If so, we close it to avoid ending up with an open activity into a closed trip. + if (openActivity.isPresent()) { + openDataManager.closeActivityLongline(openActivity.get()); } - // We need to fully reload the newActivitiesNode, - // triggering the child loadors to recreate the node's children from the database - // (since the change in the database has already been care of) - - // 1. Select the newActivitiesNode : - // only a selected node can be reloaded (@see fr.ird.observe.ui.tree.ObserveTreeBridge.canLoadChild). - // (And also it's better for user experience because it puts the focus on the activities node which receive the activities) - // - // However, the node selection has to be done after that the trip has been opened : - // selecting the newAtivitiesNode opens a list layout which compute a rendering mode associated to the trip state. - // After the mode has been computed, it is injected in the list component which triggers listeners on associated components, such as buttons. - // - // That's why, if we do this before the trip is opened, - // we will end up with an incoherent list view (some buttons will be deactivated while they should be activated for instance) - treeHelper.selectNode(newActivitiesNode); - - // 2. Let's fully reload newActivitiesNode - treeHelper.clearAndPopulateNode(newActivitiesNode); - - // 3. We ensure the path until the newActivitiesNode is expanded - // so that the user can see the activities he moved - TreePath path = new TreePath(newActivitiesNode.getPath()); - treeHelper.getUI().collapsePath(path); // FIXME : sometimes the path don't expand because its state seems to indicate that it's already expanded.. - treeHelper.expandPath(path); - - // Finally, let's refresh the nodes' label of the whole program - treeHelper.reloadNode(programNode, true); + // Let's reload the sub tree of each activities node. + // As the change have already be done in database, we just call the child loaders to regenerate the activities nodes sub trees + treeHelper.reloadNodeSubTree(oldActivitiesNode, true); + treeHelper.reloadNodeSubTree(newActivitiesNode, true); + // Let's put the focus on the activities node which received the activities + treeHelper.selectNode(newActivitiesNode); } } diff --git a/observe-application-swing/src/main/java/fr/ird/observe/ui/actions/shared/MoveActivitySeinesUIAction.java b/observe-application-swing/src/main/java/fr/ird/observe/ui/actions/shared/MoveActivitySeinesUIAction.java index d3024c8..d73fee4 100644 --- a/observe-application-swing/src/main/java/fr/ird/observe/ui/actions/shared/MoveActivitySeinesUIAction.java +++ b/observe-application-swing/src/main/java/fr/ird/observe/ui/actions/shared/MoveActivitySeinesUIAction.java @@ -44,9 +44,9 @@ import org.apache.commons.logging.LogFactory; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; -import javax.swing.tree.TreePath; import java.awt.event.ActionEvent; import java.util.List; +import java.util.Optional; import static org.nuiton.i18n.I18n.n; import static org.nuiton.i18n.I18n.t; @@ -101,7 +101,6 @@ public class MoveActivitySeinesUIAction extends AbstractUIAction { ObserveTreeHelper treeHelper = getMainUI().getTreeHelper(); ObserveNode oldActivitiesNode = treeHelper.getSelectedNode(); ObserveNode oldRouteNode = oldActivitiesNode.getParent(); - String oldRouteId = oldRouteNode.getId(); // choose the new route String routeId = chooseNewRoute(ui, oldRouteNode); @@ -114,7 +113,7 @@ public class MoveActivitySeinesUIAction extends AbstractUIAction { List<Integer> positions = service.moveActivitySeinesToRoute(activityIds, routeId); // update the tree - updateTree(oldActivitiesNode, oldRouteId, routeId, activityIds, positions); + updateTree(oldActivitiesNode, routeId, activityIds); } } @@ -157,10 +156,8 @@ public class MoveActivitySeinesUIAction extends AbstractUIAction { } protected void updateTree(ObserveNode oldActivitiesNode, - String oldRouteId, String routeId, - List<String> activitiyIds, - List<Integer> positions) { + List<String> activityIds) { ObserveSwingApplicationContext applicationContext = ObserveSwingApplicationContext.get(); ObserveOpenDataManager openDataManager = applicationContext.getOpenDataManager(); @@ -174,51 +171,24 @@ public class MoveActivitySeinesUIAction extends AbstractUIAction { RouteDto.PROPERTY_ACTIVITY_SEINE); ObserveNode newActivitiesNode = treeHelper.getChild(newRouteNode, activitiesNodeId); - for (int i = 0, s = positions.size(); i < s; i++) { + // Let's check if we're moving an open activity + Optional<String> openActivity = activityIds + .stream() + .filter(openDataManager::isOpenActivitySeine) + .findFirst(); - String actvityId = activitiyIds.get(i); - ObserveNode activityNode = treeHelper.getChild(oldActivitiesNode, actvityId); - boolean wasOpen = activityNode.isOpen(); - treeHelper.removeNode(activityNode); - - if (wasOpen) { - openDataManager.closeRoute(oldRouteId); - String tripSeineId = tripNode.getId(); - openDataManager.openRoute(tripSeineId, routeId); - - // Closing the road also close the activity - // As the activity was previsously opened, we need to re-opened it. - openDataManager.openActivitySeine(routeId, actvityId); - } + // If so, we close it to avoid ending up with an open activity into a closed route. + if (openActivity.isPresent()) { + openDataManager.closeActivitySeine(openActivity.get()); } - // We need to fully reload the newActivitiesNode, - // triggering the child loadors to recreate the node's children from the database - // (since the change in the database has already been care of) - - // 1. Select the newActivitiesNode : - // only a selected node can be reloaded (@see fr.ird.observe.ui.tree.ObserveTreeBridge.canLoadChild). - // (And also it's better for user experience because it puts the focus on the activities node which receive the activities) - // - // However, the node selection has to be done after that the route has been opened : - // selecting the newAtivitiesNode opens a list layout which compute a rendering mode associated to the route state. - // After the mode has been computed, it is injected in the list component which triggers listeners on associated components, such as buttons. - // - // That's why, if we do this before the route is opened, - // we will end up with an incoherent list view (some buttons will be deactivated while they should be activated for instance) - treeHelper.selectNode(newActivitiesNode); + // Let's reload the sub tree of each activities node. + // As the change have already be done in database, we just call the child loaders to regenerate the activities nodes sub trees + treeHelper.reloadNodeSubTree(oldActivitiesNode, true); + treeHelper.reloadNodeSubTree(newActivitiesNode, true); - // 2. Let's fully reload newActivitiesNode - treeHelper.clearAndPopulateNode(newActivitiesNode); - - // 3. We ensure the path until the newActivitiesNode is expanded - // so that the user can see the activities he moved - TreePath path = new TreePath(newActivitiesNode.getPath()); - treeHelper.getUI().collapsePath(path); // FIXME : sometimes the path don't expand because its state seems to indicate that it's already expanded.. - treeHelper.expandPath(path); - - // Finally, let's refresh the nodes' label of the whole trip - treeHelper.reloadNode(tripNode, true); + // Let's put the focus on the activities node which received the activities + treeHelper.selectNode(newActivitiesNode); } } diff --git a/observe-application-swing/src/main/java/fr/ird/observe/ui/actions/shared/MoveRoutesUIAction.java b/observe-application-swing/src/main/java/fr/ird/observe/ui/actions/shared/MoveRoutesUIAction.java index 2f875c7..cba5bba 100644 --- a/observe-application-swing/src/main/java/fr/ird/observe/ui/actions/shared/MoveRoutesUIAction.java +++ b/observe-application-swing/src/main/java/fr/ird/observe/ui/actions/shared/MoveRoutesUIAction.java @@ -43,9 +43,9 @@ import org.apache.commons.logging.LogFactory; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; -import javax.swing.tree.TreePath; import java.awt.event.ActionEvent; import java.util.List; +import java.util.Optional; import static org.nuiton.i18n.I18n.n; import static org.nuiton.i18n.I18n.t; @@ -102,7 +102,6 @@ public class MoveRoutesUIAction extends AbstractUIAction { ObserveTreeHelper treeHelper = getMainUI().getTreeHelper(); ObserveNode oldRoutesNode = treeHelper.getSelectedNode(); ObserveNode oldTripSeineNode = oldRoutesNode.getParent(); - String oldTripSeineId = oldTripSeineNode.getId(); // choose the new tripseine String tripSeineId = chooseNewTripSeine(theUi, oldTripSeineNode); @@ -115,7 +114,7 @@ public class MoveRoutesUIAction extends AbstractUIAction { List<Integer> positions = service.moveRoutesToTripSeine(routeIds, tripSeineId); // update the tree - updateTree(oldRoutesNode, oldTripSeineId, tripSeineId, routeIds, positions); + updateTree(oldRoutesNode, tripSeineId, routeIds); } } @@ -157,10 +156,8 @@ public class MoveRoutesUIAction extends AbstractUIAction { } protected void updateTree(ObserveNode oldRoutesNode, - String oldTripSeineId, String tripSeineId, - List<String> routeIds, - List<Integer> positions) { + List<String> routeIds) { ObserveSwingApplicationContext applicationContext = ObserveSwingApplicationContext.get(); ObserveOpenDataManager openDataManager = applicationContext.getOpenDataManager(); @@ -173,58 +170,24 @@ public class MoveRoutesUIAction extends AbstractUIAction { TripSeineDto.PROPERTY_ROUTE); ObserveNode newRoutesNode = treeHelper.getChild(newTripSeineNode, routesNodeId); - for (int i = 0, s = positions.size(); i < s; i++) { + // Let's check if we're moving an open route + Optional<String> openRoute = routeIds + .stream() + .filter(openDataManager::isOpenRoute) + .findFirst(); - String routeId = routeIds.get(i); - ObserveNode routeNode = treeHelper.getChild(oldRoutesNode, routeId); - boolean wasOpen = routeNode.isOpen(); - treeHelper.removeNode(routeNode); - - if (wasOpen) { - openDataManager.closeTripSeine(oldTripSeineId); - openDataManager.openTripSeine(programNode.getId(), tripSeineId); - openDataManager.openRoute(tripSeineId, routeNode.getId()); // Need to reopen the route since closing the trip also close the route - } - - ObserveNode newRouteNode = treeHelper.getChild(newRoutesNode, routeId); - - if (newRouteNode == null) { - - // create it - if (log.isInfoEnabled()) { - log.info("Insert route node: "); - } - treeHelper.insertNode(newRoutesNode, routeNode, positions.get(i)); - } + // If so, we close it to avoid ending up with an open route into a closed trip. + if (openRoute.isPresent()) { + openDataManager.closeRoute(openRoute.get()); } - // We need to fully reload the newRoutesNode, - // triggering the child loadors to recreate the node's children from the database - // (since the change in the database has already been care of) - - // 1. Select the newRoutesNode : - // only a selected node can be reloaded (@see fr.ird.observe.ui.tree.ObserveTreeBridge.canLoadChild). - // (And also it's better for user experience because it puts the focus on the routes node which receive the routes) - // - // However, the node selection has to be done after that the trip has been opened : - // selecting the newRoutesNode opens a list layout which compute a rendering mode associated to the trip state. - // After the mode has been computed, it is injected in the list component which triggers listeners on associated components, such as buttons. - // - // That's why, if we do this before the trip is opened, - // we will end up with an incoherent list view (some buttons will be deactivated while they should be activated for instance) - treeHelper.selectNode(newRoutesNode); - - // 2. Let's fully reload newRoutesNode - treeHelper.clearAndPopulateNode(newRoutesNode); + // Let's reload the sub tree of each routes node. + // As the change have already be done in database, we just call the child loaders to regenerate the routes nodes sub trees + treeHelper.reloadNodeSubTree(oldRoutesNode, true); + treeHelper.reloadNodeSubTree(newRoutesNode, true); - // 3. We ensure the path until the newRoutesNode is expanded - // so that the user can see the activities he moved - TreePath path = new TreePath(newRoutesNode.getPath()); - treeHelper.getUI().collapsePath(path); // FIXME : sometimes the path don't expand because its state seems to indicate that it's already expanded.. - treeHelper.expandPath(path); - - // Finally, let's refresh the nodes' label of the whole programme - treeHelper.reloadNode(programNode, true); + // Let's put the focus on the routes node which received the routes + treeHelper.selectNode(newRoutesNode); } diff --git a/observe-application-swing/src/main/java/fr/ird/observe/ui/tree/ObserveTreeHelper.java b/observe-application-swing/src/main/java/fr/ird/observe/ui/tree/ObserveTreeHelper.java index 9622487..28e496f 100644 --- a/observe-application-swing/src/main/java/fr/ird/observe/ui/tree/ObserveTreeHelper.java +++ b/observe-application-swing/src/main/java/fr/ird/observe/ui/tree/ObserveTreeHelper.java @@ -577,17 +577,32 @@ public class ObserveTreeHelper extends NavTreeHelper<ObserveNode> { setDataProvider(provider); } - public void populateNode(ObserveNode node) { - node.populateNode(getBridge(), getDataProvider(), true); - } + public void reloadNodeSubTree(ObserveNode node, boolean expandNode) { + Preconditions.checkNotNull(node, "node is null, we can not reload its structure"); + ObserveTreeBridge bridge = getBridge(); - public void clearAndPopulateNode(ObserveNode node) { - // 1. We delete all children of the node because populating only *add* child, it never refreshes totally + // 1. Let's clear node structure while (node.getChildCount() > 0) { removeNode(node.getFirstChild()); } - // 2. We re-generate node's children - populateNode(node); + // 2. We add the node and its parent to the select path in order to force the call to the child loadors when populating the node. + // see fr.ird.observe.ui.tree.ObserveTreeBridge.canLoadChild + bridge.setPathToSelect(node.getId(), node.getParent().getId()); + + try { + + // 3. Let's re-generate node's children by populating the node : this will call the child loaders. + node.populateNode(bridge, getDataProvider(), true); + + } finally { + // Clean the path to select + bridge.setPathToSelect(); + + } + + if (expandNode) { + expandPath(new TreePath(node.getPath())); + } } } -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.