From 51d3d607190dbc646bf8ea7359cb4970161c1983 Mon Sep 17 00:00:00 2001 From: Alois Zoitl Date: Thu, 26 Oct 2023 22:23:09 +0200 Subject: [PATCH] Cleaned Zest Algorithms --- .../eclipse/zest/layouts/LayoutAlgorithm.java | 18 +- .../algorithms/AbstractLayoutAlgorithm.java | 401 ++++++------------ .../DirectedGraphLayoutAlgorithm.java | 7 +- .../layouts/algorithms/HorizontalShift.java | 39 +- .../algorithms/RadialLayoutAlgorithm.java | 47 +- .../algorithms/SpringLayoutAlgorithm.java | 167 ++++---- .../algorithms/TreeLayoutAlgorithm.java | 228 +++++----- .../algorithms/internal/CycleChecker.java | 74 ++-- .../algorithms/internal/DynamicScreen.java | 62 ++- 9 files changed, 437 insertions(+), 606 deletions(-) diff --git a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/LayoutAlgorithm.java b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/LayoutAlgorithm.java index 335b9970c..3c0cfcc53 100644 --- a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/LayoutAlgorithm.java +++ b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/LayoutAlgorithm.java @@ -2,12 +2,12 @@ * Copyright 2005 CHISEL Group, University of Victoria, Victoria, BC, * Canada. * - * This program and the accompanying materials are made available under the + * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * SPDX-License-Identifier: EPL-2.0 - * + * * Contributors: The Chisel Group, University of Victoria *******************************************************************************/ package org.eclipse.zest.layouts; @@ -19,10 +19,10 @@ /** * A simple interface used by all layouts. - * + * * Each layout Algorithm must implement the applyLayoutInternal method which * actually compute the layout - * + * * @author Casey Best * @author Ian Bull */ @@ -31,7 +31,7 @@ public interface LayoutAlgorithm { /** * Apply the layout to the given entities. The entities will be moved and * resized based on the algorithm. - * + * * @param entitiesToLayout Apply the algorithm to these entities * @param relationshipsToConsider Only consider these relationships when * applying the algorithm. @@ -51,7 +51,7 @@ public void applyLayout(LayoutEntity[] entitiesToLayout, LayoutRelationship[] re /** * Returns whether or not the algorithm is currenly running - * + * * @return True if a layout algorithm is currenly running, false otherwise */ public boolean isRunning(); @@ -103,13 +103,13 @@ public void applyLayout(LayoutEntity[] entitiesToLayout, LayoutRelationship[] re /** * Sets the style for this layout algorithm. This will overwrite any other style * set. - * + * * @param style */ public void setStyle(int style); /** - * + * * @return */ public int getStyle(); @@ -122,6 +122,6 @@ public void applyLayout(LayoutEntity[] entitiesToLayout, LayoutRelationship[] re public void removeRelationship(LayoutRelationship relationship); - public void removeRelationships(List relationships); + public void removeRelationships(List relationships); } diff --git a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/AbstractLayoutAlgorithm.java b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/AbstractLayoutAlgorithm.java index db3930f2e..77b2123fd 100644 --- a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/AbstractLayoutAlgorithm.java +++ b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/AbstractLayoutAlgorithm.java @@ -1,14 +1,14 @@ /******************************************************************************* - * Copyright 2005 CHISEL Group, University of Victoria, Victoria, BC, - * Canada. + * Copyright 2005, 2023 CHISEL Group, University of Victoria, Victoria, BC, + * Canada, Johannes Kepler University Linz * - * This program and the accompanying materials are made available under the + * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: The Chisel Group, University of Victoria + * + * Contributors: The Chisel Group, University of Victoria, Alois Zoitl *******************************************************************************/ package org.eclipse.zest.layouts.algorithms; @@ -18,7 +18,6 @@ import java.util.Calendar; import java.util.Collection; import java.util.Comparator; -import java.util.Iterator; import java.util.List; import org.eclipse.zest.layouts.Filter; @@ -42,9 +41,9 @@ /** * Handles common elements in all layout algorithms [irbull] Refactored into a * template pattern. ApplyLayout now delegates the task to ApplyLayoutInternal - * + * * [irbull] Included asynchronous layouts - * + * * @version 1.0 * @author Casey Best * @author Ian Bull @@ -54,21 +53,21 @@ */ public abstract class AbstractLayoutAlgorithm implements LayoutAlgorithm, Stoppable { - public void removeRelationships(Collection collection) { + public void removeRelationships(Collection collection) { } - public final static int MIN_ENTITY_SIZE = 5; - private final static int MIN_TIME_DELAY_BETWEEN_PROGRESS_EVENTS = 1; + public static final int MIN_ENTITY_SIZE = 5; + private static final int MIN_TIME_DELAY_BETWEEN_PROGRESS_EVENTS = 1; private Thread creationThread = null; protected Comparator comparator; protected Filter filter; - private List progressListeners; + private final List progressListeners = new ArrayList<>(); private Calendar lastProgressEventFired; private double widthToHeightRatio; - class InternalComparator implements Comparator { + class InternalComparator implements Comparator { Comparator externalComparator = null; public InternalComparator(Comparator externalComparator) { @@ -76,10 +75,7 @@ public InternalComparator(Comparator externalComparator) { } @Override - public int compare(Object o1, Object o2) { - InternalNode internalNode1 = (InternalNode) o1; - InternalNode internalNode2 = (InternalNode) o2; - + public int compare(InternalNode internalNode1, InternalNode internalNode2) { return this.externalComparator.compare(internalNode1.getLayoutEntity(), internalNode2.getLayoutEntity()); } @@ -103,15 +99,13 @@ public int compare(Object o1, Object o2) { */ /** A list of LayoutEntity objects to be removed from the layout. */ - private List entitiesToRemove; + private final List entitiesToRemove = new ArrayList<>(); /** A list of LayoutRelationship objects to be removed. */ - private List relationshipsToRemove; + private final List relationshipsToRemove = new ArrayList<>(); /** A list of LayoutEntity objects to be added to the layout. */ - private List entitiesToAdd; + private final List entitiesToAdd = new ArrayList<>(); /** A list of LayoutRelationship objects to be added. */ - private List relationshipsToAdd; - - // protected boolean cancelled = false; + private final List relationshipsToAdd = new ArrayList<>(); protected boolean layoutStopped = true; @@ -122,26 +116,21 @@ public int compare(Object o1, Object o2) { /** * Initializes the abstract layout algorithm. - * + * * @see LayoutStyles */ public AbstractLayoutAlgorithm(int styles) { this.creationThread = Thread.currentThread(); - this.progressListeners = new ArrayList(); this.lastProgressEventFired = Calendar.getInstance(); this.widthToHeightRatio = 1.0; - this.entitiesToRemove = new ArrayList(); - this.relationshipsToRemove = new ArrayList(); - this.entitiesToAdd = new ArrayList(); - this.relationshipsToAdd = new ArrayList(); this.layout_styles = styles; } /** * Queues up the given entity (if it isn't in the list) to be added to the * algorithm. - * + * * @param entity */ @Override @@ -154,7 +143,7 @@ public void addEntity(LayoutEntity entity) { /** * Queues up the given relationshp (if it isn't in the list) to be added to the * algorithm. - * + * * @param relationship */ @Override @@ -167,7 +156,7 @@ public void addRelationship(LayoutRelationship relationship) { /** * Queues up the given entity to be removed from the algorithm next time it * runs. - * + * * @param entity The entity to remove */ @Override @@ -180,7 +169,7 @@ public void removeEntity(LayoutEntity entity) { /** * Queues up the given relationship to be removed from the algorithm next time * it runs. - * + * * @param relationship The relationship to remove. */ @Override @@ -192,11 +181,11 @@ public void removeRelationship(LayoutRelationship relationship) { /** * Queues up all the relationships in the list to be removed. - * + * * @param relationships */ @Override - public void removeRelationships(List relationships) { + public void removeRelationships(List relationships) { // note we don't check if the relationshipsToRemove contains // any of the objects in relationships. relationshipsToRemove.addAll(relationships); @@ -205,7 +194,7 @@ public void removeRelationships(List relationships) { /** * Sets the current layout style. This overwrites all other layout styles. Use * getStyle to get the current style. - * + * * @param style */ @Override @@ -215,8 +204,8 @@ public void setStyle(int style) { /** * Gets the current layout style - * - * @return + * + * @return the layout styles for this layout */ @Override public int getStyle() { @@ -227,7 +216,7 @@ public int getStyle() { /** * Determines if the configuration is valid for this layout - * + * * @param asynchronous * @param continuous */ @@ -236,47 +225,42 @@ public int getStyle() { /** * Apply the layout to the given entities. The entities will be moved and * resized based on the algorithm. - * + * * @param entitiesToLayout Apply the algorithm to these entities * @param relationshipsToConsider Only consider these relationships when * applying the algorithm. - * @param x The left side of the bounds in which the + * @param boundsX The left side of the bounds in which the * layout can place the entities. - * @param y The top side of the bounds in which the layout + * @param boundsY The top side of the bounds in which the layout * can place the entities. - * @param width The width of the bounds in which the layout + * @param boundsWidth The width of the bounds in which the layout * can place the entities. - * @param height The height of the bounds in which the layout + * @param boundsHeight The height of the bounds in which the layout * can place the entities. */ - abstract protected void applyLayoutInternal(InternalNode[] entitiesToLayout, + protected abstract void applyLayoutInternal(InternalNode[] entitiesToLayout, InternalRelationship[] relationshipsToConsider, double boundsX, double boundsY, double boundsWidth, double boundsHeight); /** * Updates the given array of entities checking if any need to be removed or * added. - * + * * @param entities the current entities * @return the updated entities array */ protected InternalNode[] updateEntities(InternalNode[] entities) { - if ((entitiesToRemove.size() > 0) || (entitiesToAdd.size() > 0)) { - List internalNodesList = new ArrayList(Arrays.asList(entities)); + if (!entitiesToRemove.isEmpty() || !entitiesToAdd.isEmpty()) { + List internalNodesList = new ArrayList<>(Arrays.asList(entities)); // remove nodes - for (Iterator iter = entitiesToRemove.iterator(); iter.hasNext();) { - LayoutEntity entity = (LayoutEntity) iter.next(); - if (entity.getLayoutInformation() != null) { - internalNodesList.remove(entity.getLayoutInformation()); - } - } + entitiesToRemove.stream().filter(e -> e.getLayoutInformation() != null) + .forEach(e -> internalNodesList.remove(e.getLayoutInformation())); // Also remove from _internalNodes - ArrayList updatedEntities = new ArrayList( + List updatedEntities = new ArrayList<>( internalNodes.length - entitiesToRemove.size() + entitiesToAdd.size()); - for (int i = 0; i < internalNodes.length; i++) { - InternalNode node = internalNodes[i]; + for (InternalNode node : internalNodes) { if (entitiesToRemove.contains(node.getLayoutEntity())) { entitiesToRemove.remove(node.getLayoutEntity()); } else { @@ -287,19 +271,19 @@ protected InternalNode[] updateEntities(InternalNode[] entities) { // Add any new nodes LayoutEntity[] entitiesArray = new LayoutEntity[entitiesToAdd.size()]; - entitiesArray = (LayoutEntity[]) entitiesToAdd.toArray(entitiesArray); + entitiesArray = entitiesToAdd.toArray(entitiesArray); InternalNode[] newNodes = createInternalNodes(entitiesArray); - for (int i = 0; i < newNodes.length; i++) { - internalNodesList.add(newNodes[i]); - updatedEntities.add(newNodes[i]); + for (InternalNode newNode : newNodes) { + internalNodesList.add(newNode); + updatedEntities.add(newNode); } entitiesToAdd.clear(); entities = new InternalNode[internalNodesList.size()]; - entities = (InternalNode[]) internalNodesList.toArray(entities); + entities = internalNodesList.toArray(entities); internalNodes = new InternalNode[updatedEntities.size()]; - internalNodes = (InternalNode[]) updatedEntities.toArray(internalNodes); + internalNodes = updatedEntities.toArray(internalNodes); } return entities; @@ -308,29 +292,22 @@ protected InternalNode[] updateEntities(InternalNode[] entities) { /** * Updates the given array of relationships checking if any need to be removed * or added. Also updates the original array of relationships. - * + * * @param relationships the current relationships * @return the update relationships array */ protected InternalRelationship[] updateRelationships(InternalRelationship[] relationships) { - if ((relationshipsToRemove.size() > 0) || (relationshipsToAdd.size() > 0)) { - List internalRelsList = new ArrayList(Arrays.asList(relationships)); + if (!relationshipsToRemove.isEmpty() || !relationshipsToAdd.isEmpty()) { + List internalRelsList = new ArrayList<>(Arrays.asList(relationships)); // remove relationships - if (relationshipsToRemove.size() > 0) { - for (Iterator iter = relationshipsToRemove.iterator(); iter.hasNext();) { - LayoutRelationship relation = (LayoutRelationship) iter.next(); - if (relation.getLayoutInformation() != null) { - internalRelsList.remove(relation.getLayoutInformation()); - } - } - } + relationshipsToRemove.stream().filter(r -> r.getLayoutInformation() != null) + .forEach(r -> internalRelsList.remove(r.getLayoutInformation())); // Also remove from _internalRelationships - ArrayList updatedRelationships = new ArrayList( + List updatedRelationships = new ArrayList<>( internalRelationships.length - relationshipsToRemove.size() + relationshipsToAdd.size()); - for (int i = 0; i < internalRelationships.length; i++) { - InternalRelationship relation = internalRelationships[i]; + for (InternalRelationship relation : internalRelationships) { if (relationshipsToRemove.contains(relation.getLayoutRelationship())) { relationshipsToRemove.remove(relation.getLayoutRelationship()); } else { @@ -340,44 +317,30 @@ protected InternalRelationship[] updateRelationships(InternalRelationship[] rela relationshipsToRemove.clear(); // add relationships - if (relationshipsToAdd.size() > 0) { + if (!relationshipsToAdd.isEmpty()) { LayoutRelationship[] relsArray = new LayoutRelationship[relationshipsToAdd.size()]; - relsArray = (LayoutRelationship[]) relationshipsToAdd.toArray(relsArray); + relsArray = relationshipsToAdd.toArray(relsArray); InternalRelationship[] newRelationships = createInternalRelationships(relsArray); - for (int i = 0; i < newRelationships.length; i++) { - internalRelsList.add(newRelationships[i]); - updatedRelationships.add(newRelationships[i]); + for (InternalRelationship newRelationship : newRelationships) { + internalRelsList.add(newRelationship); + updatedRelationships.add(newRelationship); } } relationshipsToAdd.clear(); relationships = new InternalRelationship[internalRelsList.size()]; - relationships = (InternalRelationship[]) internalRelsList.toArray(relationships); + relationships = internalRelsList.toArray(relationships); internalRelationships = new InternalRelationship[updatedRelationships.size()]; - internalRelationships = (InternalRelationship[]) updatedRelationships.toArray(internalRelationships); + internalRelationships = updatedRelationships.toArray(internalRelationships); } return relationships; } - /** - * Moves all the entities by the given amount. - * - * @param dx the amount to shift the entities in the x-direction - * @param dy the amount to shift the entities in the y-direction - */ - /* - * public void moveAllEntities(double dx, double dy) { if ((dx != 0) || (dy != - * 0)) { synchronized (_internalNodes) { for (int i = 0; i < - * _internalNodes.length; i++) { InternalNode node = _internalNodes[i]; - * node.setInternalLocation(node.getInternalX()+dx, node.getInternalY()+dy); - * node.setLocation(node.getX()+dx, node.getY()+dy); } } } } - */ - /** * Returns true if the layout algorithm is running - * + * * @return boolean if the layout algorithm is running */ @Override @@ -396,28 +359,6 @@ public synchronized void stop() { fireProgressEnded(getTotalNumberOfLayoutSteps()); } - // /** - // * Sleeps while the algorithm is paused. - // */ - // protected void sleepWhilePaused() { - // // do nothing while the algorithm is paused - // boolean wasPaused = false; - // while (isPaused()) { - // try { - // Thread.sleep(200); - // } catch (InterruptedException e) { - // } - // wasPaused = true; - // } - // // update the node positions (they might have been moved while paused) - // if (wasPaused) { - // for (int i = 0; i < internalNodes.length; i++) { - // InternalNode node = internalNodes[i]; - // node.setInternalLocation(node.getPreferredX(), node.getPreferredY()); - // } - // } - // } - private void setupLayout(LayoutEntity[] entitiesToLayout, LayoutRelationship[] relationshipsToConsider, double x, double y, double width, double height) { internalX = x; @@ -432,7 +373,7 @@ private void setupLayout(LayoutEntity[] entitiesToLayout, LayoutRelationship[] r if (!verifyInput(entitiesToLayout, relationshipsToConsider)) { layoutStopped = true; throw new RuntimeException( - "The relationships in relationshipsToConsider don't contain the entities in entitiesToLayout"); + "The relationships in relationshipsToConsider don't contain the entities in entitiesToLayout"); //$NON-NLS-1$ } // Create the internal nodes and relationship @@ -440,20 +381,6 @@ private void setupLayout(LayoutEntity[] entitiesToLayout, LayoutRelationship[] r internalRelationships = createInternalRelationships(relationshipsToConsider); } - // public synchronized Stoppable getLayoutThread(LayoutEntity[] - // entitiesToLayout, LayoutRelationship[] relationshipsToConsider, double x, - // double y, double width, double height, boolean continuous) { - // //setupLayout( entitiesToLayout, relationshipsToConsider, x, y, width, height - // ); - // this.layoutStopped = false; - // this.runContinuously = continuous; - // setupLayout(entitiesToLayout, relationshipsToConsider, x, y, width, height); - // preLayoutAlgorithm(internalNodes, internalRelationships, internalX, - // internalY, internalWidth, internalHeight); - // fireProgressStarted(getTotalNumberOfLayoutSteps()); - // return this; - // } - /** * Code called before the layout algorithm starts */ @@ -473,8 +400,6 @@ protected abstract void postLayoutAlgorithm(InternalNode[] entitiesToLayout, /** * Gets the current layout step - * - * @return */ protected abstract int getCurrentLayoutStep(); @@ -501,20 +426,15 @@ public synchronized void applyLayout(final LayoutEntity[] entitiesToLayout, lastProgressEventFired = Calendar.getInstance(); if (asynchronous) { - Thread thread = new Thread(new Runnable() { - - @Override - public void run() { - setupLayout(entitiesToLayout, relationshipsToConsider, x, y, width, height); - preLayoutAlgorithm(internalNodes, internalRelationships, internalX, internalY, internalWidth, - internalHeight); - fireProgressStarted(getTotalNumberOfLayoutSteps()); - - applyLayoutInternal(internalNodes, internalRelationships, internalX, internalY, internalWidth, - internalHeight); - stop(); - } + Thread thread = new Thread(() -> { + setupLayout(entitiesToLayout, relationshipsToConsider, x, y, width, height); + preLayoutAlgorithm(internalNodes, internalRelationships, internalX, internalY, internalWidth, + internalHeight); + fireProgressStarted(getTotalNumberOfLayoutSteps()); + applyLayoutInternal(internalNodes, internalRelationships, internalX, internalY, internalWidth, + internalHeight); + stop(); }); thread.setPriority(Thread.MIN_PRIORITY); thread.start(); @@ -537,9 +457,8 @@ public void run() { /** * Clear out all old bend points before doing a layout */ - private void clearBendPoints(LayoutRelationship[] relationships) { - for (int i = 0; i < relationships.length; i++) { - LayoutRelationship rel = relationships[i]; + private static void clearBendPoints(LayoutRelationship[] relationships) { + for (LayoutRelationship rel : relationships) { rel.clearBendPoints(); } } @@ -547,14 +466,13 @@ private void clearBendPoints(LayoutRelationship[] relationships) { /** * Update external bend points from the internal bendpoints list. Save the * source and destination points for later use in scaling and translating - * + * * @param relationshipsToConsider */ protected void updateBendPoints(InternalRelationship[] relationshipsToConsider) { - for (int i = 0; i < relationshipsToConsider.length; i++) { - InternalRelationship relationship = relationshipsToConsider[i]; + for (InternalRelationship relationship : relationshipsToConsider) { List bendPoints = relationship.getBendPoints(); - if (bendPoints.size() > 0) { + if (!bendPoints.isEmpty()) { // We will assume that source/dest coordinates are for center of node BendPoint[] externalBendPoints = new BendPoint[bendPoints.size() + 2]; InternalNode sourceNode = relationship.getSource(); @@ -572,27 +490,12 @@ protected void updateBendPoints(InternalRelationship[] relationshipsToConsider) } } - // public void run() { - // - // if (started == true) { - // throw new RuntimeException("Layout has already run!"); - // } - // started = true; - // //layoutStopped = false; - // isLayoutPaused = false; - // applyLayoutInternal(internalNodes, internalRelationships, internalX, - // internalY, internalWidth, internalHeight); - // stop(); - // layoutStopped = true; - // isLayoutPaused = false; - // } - /** * Creates a list of InternalNode objects from the list of LayoutEntity objects * the user wants layed out. Sets the internal nodes' positions and sizes from * the external entities. */ - private InternalNode[] createInternalNodes(LayoutEntity[] nodes) { + private static InternalNode[] createInternalNodes(LayoutEntity[] nodes) { InternalNode[] internalNodes = new InternalNode[nodes.length]; BasicEntityConstraint basicEntityConstraint = new BasicEntityConstraint(); for (int i = 0; i < nodes.length; i++) { @@ -609,27 +512,23 @@ private InternalNode[] createInternalNodes(LayoutEntity[] nodes) { /** * Creates a list of InternalRelationship objects from the given list of * LayoutRelationship objects. - * + * * @param rels * @return List of internal relationships */ - private InternalRelationship[] createInternalRelationships(LayoutRelationship[] rels) { - ArrayList listOfInternalRelationships = new ArrayList(rels.length); - for (int i = 0; i < rels.length; i++) { - LayoutRelationship relation = rels[i]; + private static InternalRelationship[] createInternalRelationships(LayoutRelationship[] rels) { + List listOfInternalRelationships = new ArrayList<>(rels.length); + for (LayoutRelationship relation : rels) { InternalNode src = (InternalNode) relation.getSourceInLayout().getLayoutInformation(); InternalNode dest = (InternalNode) relation.getDestinationInLayout().getLayoutInformation(); - if ((src != null) && (dest != null)) { - InternalRelationship internalRelationship = new InternalRelationship(relation, src, dest); - listOfInternalRelationships.add(internalRelationship); - } else { - throw new RuntimeException("Error creating internal relationship, one of the nodes is null: src=" + src - + ", dest=" + dest); + if ((src == null) || (dest == null)) { + throw new RuntimeException("Error creating internal relationship, one of the nodes is null: src=" + src //$NON-NLS-1$ + + ", dest=" + dest); //$NON-NLS-1$ } + InternalRelationship internalRelationship = new InternalRelationship(relation, src, dest); + listOfInternalRelationships.add(internalRelationship); } - InternalRelationship[] internalRelationships = new InternalRelationship[listOfInternalRelationships.size()]; - listOfInternalRelationships.toArray(internalRelationships); - return internalRelationships; + return listOfInternalRelationships.toArray(new InternalRelationship[listOfInternalRelationships.size()]); } /** @@ -637,10 +536,9 @@ private InternalRelationship[] createInternalRelationships(LayoutRelationship[] */ private Object[] filterUnwantedObjects(LayoutItem[] objects) { // first remove any entities or relationships that are filtered. - List unfilteredObjsList = new ArrayList(); + List unfilteredObjsList = new ArrayList<>(); if (filter != null) { - for (int i = 0; i < objects.length; i++) { - LayoutItem object = objects[i]; + for (LayoutItem object : objects) { if (!filter.isObjectFiltered(object)) { unfilteredObjsList.add(object); } @@ -678,8 +576,7 @@ public void setComparator(Comparator comparator) { */ public static boolean verifyInput(LayoutEntity[] entitiesToLayout, LayoutRelationship[] relationshipsToConsider) { boolean stillValid = true; - for (int i = 0; i < relationshipsToConsider.length; i++) { - LayoutRelationship relationship = relationshipsToConsider[i]; + for (LayoutRelationship relationship : relationshipsToConsider) { LayoutEntity source = relationship.getSourceInLayout(); LayoutEntity destination = relationship.getDestinationInLayout(); boolean containsSrc = false; @@ -701,7 +598,7 @@ public static boolean verifyInput(LayoutEntity[] entitiesToLayout, LayoutRelatio /** * Gets the location in the layout bounds for this node - * + * * @param x * @param y * @return @@ -763,7 +660,7 @@ protected void defaultFitWithinBounds(InternalNode[] entitiesToLayout, InternalR /** * Calculate the screen bounds, maintaining the - * + * * @param realBounds * @return */ @@ -774,36 +671,34 @@ private DisplayIndependentRectangle calcScreenBounds(DisplayIndependentRectangle // each side return new DisplayIndependentRectangle(realBounds.x + borderWidth / 2.0, realBounds.y + borderWidth / 2.0, realBounds.width - borderWidth, realBounds.height - borderWidth); - } else { // retain layout aspect ratio - double heightAdjustment = realBounds.height / layoutBounds.height; - double widthAdjustment = realBounds.width / layoutBounds.width; - double ratio = Math.min(heightAdjustment, widthAdjustment); - double adjustedHeight = layoutBounds.height * ratio; - double adjustedWidth = layoutBounds.width * ratio; - double adjustedX = realBounds.x + (realBounds.width - adjustedWidth) / 2.0; - double adjustedY = realBounds.y + (realBounds.height - adjustedHeight) / 2.0; - double borderWidth = Math.min(adjustedWidth, adjustedHeight) / 10.0; // use 10% for the border - 5% on each - // side - return new DisplayIndependentRectangle(adjustedX + borderWidth / 2.0, adjustedY + borderWidth / 2.0, - adjustedWidth - borderWidth, adjustedHeight - borderWidth); } + double heightAdjustment = realBounds.height / layoutBounds.height; + double widthAdjustment = realBounds.width / layoutBounds.width; + double ratio = Math.min(heightAdjustment, widthAdjustment); + double adjustedHeight = layoutBounds.height * ratio; + double adjustedWidth = layoutBounds.width * ratio; + double adjustedX = realBounds.x + (realBounds.width - adjustedWidth) / 2.0; + double adjustedY = realBounds.y + (realBounds.height - adjustedHeight) / 2.0; + double borderWidth = Math.min(adjustedWidth, adjustedHeight) / 10.0; // use 10% for the border - 5% on each + // side + return new DisplayIndependentRectangle(adjustedX + borderWidth / 2.0, adjustedY + borderWidth / 2.0, + adjustedWidth - borderWidth, adjustedHeight - borderWidth); } /** * Find and set the node size - shift the nodes to the right and down to make * room for the width and height. - * + * * @param entitiesToLayout * @param relationships */ - private void resizeAndShiftNodes(InternalNode[] entitiesToLayout) { - // get maximum node size as percent of screen dimmensions + private static void resizeAndShiftNodes(InternalNode[] entitiesToLayout) { + // get maximum node size as percent of screen dimensions double nodeSize = getNodeSize(entitiesToLayout); double halfNodeSize = nodeSize / 2; // Resize and shift nodes - for (int i = 0; i < entitiesToLayout.length; i++) { - InternalNode node = entitiesToLayout[i]; + for (InternalNode node : entitiesToLayout) { node.setInternalSize(nodeSize, nodeSize); node.setInternalLocation(node.getInternalX() + halfNodeSize, node.getInternalY() + halfNodeSize); } @@ -812,15 +707,14 @@ private void resizeAndShiftNodes(InternalNode[] entitiesToLayout) { /** * Convert all node positions into a percentage of the screen. If * includeNodeSize is true then this also updates the node's internal size. - * + * * @param entitiesToLayout */ - private void convertPositionsToPercentage(InternalNode[] entitiesToLayout, InternalRelationship[] relationships, - DisplayIndependentRectangle layoutBounds, boolean includeNodeSize) { + private static void convertPositionsToPercentage(InternalNode[] entitiesToLayout, + InternalRelationship[] relationships, DisplayIndependentRectangle layoutBounds, boolean includeNodeSize) { // Adjust node positions and sizes - for (int i = 0; i < entitiesToLayout.length; i++) { - InternalNode node = entitiesToLayout[i]; + for (InternalNode node : entitiesToLayout) { DisplayIndependentPoint location = node.getInternalLocation().convertToPercent(layoutBounds); node.setInternalLocation(location.x, location.y); if (includeNodeSize) { // adjust node sizes @@ -831,10 +725,9 @@ private void convertPositionsToPercentage(InternalNode[] entitiesToLayout, Inter } // Adjust bendpoint positions - for (int i = 0; i < relationships.length; i++) { - InternalRelationship rel = relationships[i]; - for (int j = 0; j < rel.getBendPoints().size(); j++) { - BendPoint bp = (BendPoint) rel.getBendPoints().get(j); + for (InternalRelationship rel : relationships) { + for (Object element : rel.getBendPoints()) { + BendPoint bp = (BendPoint) element; DisplayIndependentPoint toPercent = bp.convertToPercent(layoutBounds); bp.setX(toPercent.x); bp.setY(toPercent.y); @@ -846,7 +739,7 @@ private void convertPositionsToPercentage(InternalNode[] entitiesToLayout, Inter * Convert the positions from a percentage of bounds area to fixed coordinates. * NOTE: ALL OF THE POSITIONS OF NODES UNTIL NOW WERE FOR THE CENTER OF THE NODE * - Convert it to the left top corner. - * + * * @param entitiesToLayout * @param relationships * @param realBounds @@ -855,8 +748,7 @@ private void convertPositionsToCoords(InternalNode[] entitiesToLayout, InternalR DisplayIndependentRectangle screenBounds) { // Adjust node positions and sizes - for (int i = 0; i < entitiesToLayout.length; i++) { - InternalNode node = entitiesToLayout[i]; + for (InternalNode node : entitiesToLayout) { double width = node.getInternalWidth() * screenBounds.width; double height = node.getInternalHeight() * screenBounds.height; DisplayIndependentPoint location = node.getInternalLocation().convertFromPercent(screenBounds); @@ -869,10 +761,9 @@ private void convertPositionsToCoords(InternalNode[] entitiesToLayout, InternalR } // Adjust bendpoint positions and shift based on source node size - for (int i = 0; i < relationships.length; i++) { - InternalRelationship rel = relationships[i]; - for (int j = 0; j < rel.getBendPoints().size(); j++) { - BendPoint bp = (BendPoint) rel.getBendPoints().get(j); + for (InternalRelationship rel : relationships) { + for (Object element : rel.getBendPoints()) { + BendPoint bp = (BendPoint) element; DisplayIndependentPoint fromPercent = bp.convertFromPercent(screenBounds); bp.setX(fromPercent.x); bp.setY(fromPercent.y); @@ -883,7 +774,7 @@ private void convertPositionsToCoords(InternalNode[] entitiesToLayout, InternalR /** * Adjust node size to take advantage of space. Reset position to top left * corner of node. - * + * * @param node * @param height * @param width @@ -910,10 +801,11 @@ private void adjustNodeSizeAndPos(InternalNode node, double height, double width /** * Returns the maximum possible node size as a percentage of the width or height - * in current coord system. + * in current coordinate system. */ - private double getNodeSize(InternalNode[] entitiesToLayout) { - double width, height; + private static double getNodeSize(InternalNode[] entitiesToLayout) { + double width; + double height; if (entitiesToLayout.length == 1) { width = 0.8; height = 0.8; @@ -937,8 +829,7 @@ protected DisplayIndependentRectangle getLayoutBounds(InternalNode[] entitiesToL double bottomSide = Double.MIN_VALUE; double leftSide = Double.MAX_VALUE; double topSide = Double.MAX_VALUE; - for (int i = 0; i < entitiesToLayout.length; i++) { - InternalNode entity = entitiesToLayout[i]; + for (InternalNode entity : entitiesToLayout) { if (entity.hasPreferredLocation()) { continue; } @@ -963,17 +854,17 @@ protected DisplayIndependentRectangle getLayoutBounds(InternalNode[] entitiesToL * become the center points for the two closest nodes, which we wish to make * them as big as possible without overlapping. This will be the maximum of * minDistanceX and minDistanceY minus a bit, lets say 20% - * + * * We make the recommended node size a square for convenience. - * - * + * + * * _______ | | | | | + | | |\ | |___|_\_|_____ | | \ | | | \ | +-|---+ | | | * |_______| - * - * - * + * + * + * */ - private DisplayIndependentDimension getMinimumDistance(InternalNode[] entitiesToLayout) { + private static DisplayIndependentDimension getMinimumDistance(InternalNode[] entitiesToLayout) { DisplayIndependentDimension horAndVertdistance = new DisplayIndependentDimension(Double.MAX_VALUE, Double.MAX_VALUE); double minDistance = Double.MAX_VALUE; // the minimum distance between all the nodes @@ -1045,8 +936,7 @@ public void removeProgressListener(ProgressListener listener) { * locations */ protected void updateLayoutLocations(InternalNode[] nodes) { - for (int i = 0; i < nodes.length; i++) { - InternalNode node = nodes[i]; + for (InternalNode node : nodes) { if (!node.hasPreferredLocation()) { node.setLocation(node.getInternalX(), node.getInternalY()); @@ -1060,46 +950,31 @@ protected void updateLayoutLocations(InternalNode[] nodes) { protected void fireProgressStarted(int totalNumberOfSteps) { ProgressEvent event = new ProgressEvent(0, totalNumberOfSteps); - for (int i = 0; i < progressListeners.size(); i++) { - ProgressListener listener = (ProgressListener) progressListeners.get(i); - - listener.progressStarted(event); - } + progressListeners.forEach(listener -> listener.progressStarted(event)); } protected void fireProgressEnded(int totalNumberOfSteps) { ProgressEvent event = new ProgressEvent(totalNumberOfSteps, totalNumberOfSteps); - for (int i = 0; i < progressListeners.size(); i++) { - ProgressListener listener = (ProgressListener) progressListeners.get(i); - listener.progressEnded(event); - } - + progressListeners.forEach(listener -> listener.progressEnded(event)); } /** * Fires an event to notify all of the registered ProgressListeners that another * step has been completed in the algorithm. - * + * * @param currentStep The current step completed. * @param totalNumberOfSteps The total number of steps in the algorithm. */ protected void fireProgressEvent(int currentStep, int totalNumberOfSteps) { - // Update the layout locations to the external nodes Calendar now = Calendar.getInstance(); now.add(Calendar.MILLISECOND, -MIN_TIME_DELAY_BETWEEN_PROGRESS_EVENTS); if (now.after(lastProgressEventFired) || currentStep == totalNumberOfSteps) { ProgressEvent event = new ProgressEvent(currentStep, totalNumberOfSteps); - - for (int i = 0; i < progressListeners.size(); i++) { - - ProgressListener listener = (ProgressListener) progressListeners.get(i); - listener.progressUpdated(event); - } + progressListeners.forEach(listener -> listener.progressUpdated(event)); lastProgressEventFired = Calendar.getInstance(); } - } protected int getNumberOfProgressListeners() { @@ -1108,7 +983,7 @@ protected int getNumberOfProgressListeners() { private void checkThread() { if (this.creationThread != Thread.currentThread()) { - throw new RuntimeException("Invalid Thread Access."); + throw new RuntimeException("Invalid Thread Access."); //$NON-NLS-1$ } } diff --git a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/DirectedGraphLayoutAlgorithm.java b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/DirectedGraphLayoutAlgorithm.java index 7d98b0592..aa3a82bb5 100644 --- a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/DirectedGraphLayoutAlgorithm.java +++ b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/DirectedGraphLayoutAlgorithm.java @@ -14,6 +14,7 @@ import java.lang.reflect.Field; import java.util.Deque; import java.util.HashMap; +import java.util.Map; import org.eclipse.swt.SWT; @@ -58,7 +59,7 @@ public DirectedGraphLayoutAlgorithm(int styles) { @Override protected void applyLayoutInternal(InternalNode[] entitiesToLayout, InternalRelationship[] relationshipsToConsider, double boundsX, double boundsY, double boundsWidth, double boundsHeight) { - HashMap mapping = new HashMap(entitiesToLayout.length); + Map mapping = new HashMap<>(entitiesToLayout.length); DirectedGraph graph = new DirectedGraph(); for (InternalNode internalNode : entitiesToLayout) { Node node = new Node(internalNode); @@ -67,8 +68,8 @@ protected void applyLayoutInternal(InternalNode[] entitiesToLayout, InternalRela graph.nodes.add(node); } for (InternalRelationship relationship : relationshipsToConsider) { - Node source = (Node) mapping.get(relationship.getSource()); - Node dest = (Node) mapping.get(relationship.getDestination()); + Node source = mapping.get(relationship.getSource()); + Node dest = mapping.get(relationship.getDestination()); Edge edge = new Edge(relationship, source, dest); graph.edges.add(edge); } diff --git a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/HorizontalShift.java b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/HorizontalShift.java index bf8cc3398..0338256ca 100644 --- a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/HorizontalShift.java +++ b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/HorizontalShift.java @@ -1,5 +1,6 @@ /******************************************************************************* - * Copyright 2006, CHISEL Group, University of Victoria, Victoria, BC, Canada. + * Copyright 2006, 2023 CHISEL Group, University of Victoria, Victoria, BC, + * Canada, Johannes Kepler University Linz * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -7,13 +8,12 @@ * * SPDX-License-Identifier: EPL-2.0 * - * Contributors: The Chisel Group, University of Victoria + * Contributors: The Chisel Group, University of Victoria, Alois Zoitl *******************************************************************************/ package org.eclipse.zest.layouts.algorithms; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; import org.eclipse.zest.layouts.LayoutEntity; @@ -38,7 +38,7 @@ public HorizontalShift(int styles) { protected void applyLayoutInternal(InternalNode[] entitiesToLayout, InternalRelationship[] relationshipsToConsider, double boundsX, double boundsY, double boundsWidth, double boundsHeight) { - ArrayList row = new ArrayList(); + List> row = new ArrayList<>(); for (InternalNode element : entitiesToLayout) { addToRowList(element, row); } @@ -46,27 +46,19 @@ protected void applyLayoutInternal(InternalNode[] entitiesToLayout, InternalRela int heightSoFar = 0; Collections.sort(row, (arg0, arg1) -> { - // TODO Auto-generated method stub - List a0 = (List) arg0; - List a1 = (List) arg1; - LayoutEntity node0 = ((InternalNode) a0.get(0)).getLayoutEntity(); - LayoutEntity node1 = ((InternalNode) a1.get(0)).getLayoutEntity(); + LayoutEntity node0 = arg0.get(0).getLayoutEntity(); + LayoutEntity node1 = arg1.get(0).getLayoutEntity(); return (int) (node0.getYInLayout() - (node1.getYInLayout())); }); - Iterator iterator = row.iterator(); - while (iterator.hasNext()) { - List currentRow = (List) iterator.next(); - Collections.sort(currentRow, (arg0, arg1) -> (int) (((InternalNode) arg1).getLayoutEntity().getYInLayout() - - ((InternalNode) arg0).getLayoutEntity().getYInLayout())); - Iterator iterator2 = currentRow.iterator(); + for (List currentRow : row) { + Collections.sort(currentRow, (arg0, + arg1) -> (int) (arg1.getLayoutEntity().getYInLayout() - arg0.getLayoutEntity().getYInLayout())); int i = 0; int width = (int) ((boundsWidth / 2) - currentRow.size() * 75); - heightSoFar += ((InternalNode) currentRow.get(0)).getLayoutEntity().getHeightInLayout() + VSPACING * 8; - while (iterator2.hasNext()) { - InternalNode currentNode = (InternalNode) iterator2.next(); - + heightSoFar += currentRow.get(0).getLayoutEntity().getHeightInLayout() + VSPACING * 8; + for (InternalNode currentNode : currentRow) { i++; double location = width + 10 * i; currentNode.setLocation(location, heightSoFar); @@ -75,12 +67,11 @@ protected void applyLayoutInternal(InternalNode[] entitiesToLayout, InternalRela } } - private void addToRowList(InternalNode node, ArrayList list) { + private static void addToRowList(InternalNode node, List> list) { double layoutY = node.getLayoutEntity().getYInLayout(); - for (Object element : list) { - List currentRow = (List) element; - InternalNode currentRowNode = (InternalNode) currentRow.get(0); + for (List currentRow : list) { + InternalNode currentRowNode = currentRow.get(0); double currentRowY = currentRowNode.getLayoutEntity().getYInLayout(); // double currentRowHeight = // currentRowNode.getLayoutEntity().getHeightInLayout(); @@ -90,7 +81,7 @@ private void addToRowList(InternalNode node, ArrayList list) { return; } } - List newRow = new ArrayList(); + List newRow = new ArrayList<>(); newRow.add(node); list.add(newRow); } diff --git a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/RadialLayoutAlgorithm.java b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/RadialLayoutAlgorithm.java index 21d0b3172..0c608182c 100644 --- a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/RadialLayoutAlgorithm.java +++ b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/RadialLayoutAlgorithm.java @@ -1,18 +1,17 @@ /******************************************************************************* - * Copyright 2005 CHISEL Group, University of Victoria, Victoria, BC, - * Canada. + * Copyright 2005, 2023 CHISEL Group, University of Victoria, Victoria, BC, + * Canada, Johannes Kepler University Linz * - * This program and the accompanying materials are made available under the + * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: The Chisel Group, University of Victoria + * + * Contributors: The Chisel Group, University of Victoria, Alois Zoitl *******************************************************************************/ package org.eclipse.zest.layouts.algorithms; -import java.util.Iterator; import java.util.List; import org.eclipse.zest.layouts.LayoutStyles; @@ -24,7 +23,7 @@ /** * This layout will take the given entities, apply a tree layout to them, and * then display the tree in a circular fashion with the roots in the center. - * + * * @author Casey Best * @auhtor Rob Lintern */ @@ -32,7 +31,7 @@ public class RadialLayoutAlgorithm extends TreeLayoutAlgorithm { private static final double MAX_DEGREES = Math.PI * 2; private double startDegree; private double endDegree; - private TreeLayoutAlgorithm treeLayout; + private final TreeLayoutAlgorithm treeLayout; private List roots; /** @@ -53,19 +52,23 @@ public RadialLayoutAlgorithm(int styles) { @Override public void setLayoutArea(double x, double y, double width, double height) { - throw new RuntimeException("Operation not implemented"); + throw new RuntimeException("Operation not implemented"); //$NON-NLS-1$ } @Override protected boolean isValidConfiguration(boolean asynchronous, boolean continueous) { - if (asynchronous && continueous) + if (asynchronous && continueous) { return false; - else if (asynchronous && !continueous) + } + if (asynchronous && !continueous) { return true; - else if (!asynchronous && continueous) + } + if (!asynchronous && continueous) { return false; - else if (!asynchronous && !continueous) + } + if (!asynchronous && !continueous) { return true; + } return false; } @@ -75,7 +78,6 @@ else if (!asynchronous && !continueous) @Override protected void preLayoutAlgorithm(InternalNode[] entitiesToLayout, InternalRelationship[] relationshipsToConsider, double x, double y, double width, double height) { - // TODO Auto-generated method stub layoutBounds = new DisplayIndependentRectangle(x, y, width, height); super.preLayoutAlgorithm(entitiesToLayout, relationshipsToConsider, x, y, width, height); } @@ -106,13 +108,11 @@ public void setRangeToLayout(double startDegree, double endDegree) { * each entity in terms of its percentage in the tree layout. Then apply that * percentage to the radius and distance from the center. */ - protected void computeRadialPositions(InternalNode[] entities, DisplayIndependentRectangle bounds2) { // TODO TODO - // TODO + protected void computeRadialPositions(InternalNode[] entities, DisplayIndependentRectangle bounds2) { DisplayIndependentRectangle bounds = new DisplayIndependentRectangle(getLayoutBounds(entities, true)); bounds.height = bounds2.height; bounds.y = bounds2.y; - for (int i = 0; i < entities.length; i++) { - InternalNode entity = entities[i]; + for (InternalNode entity : entities) { double percentTheta = (entity.getInternalX() - bounds.x) / bounds.width; double distance = (entity.getInternalY() - bounds.y) / bounds.height; double theta = startDegree + Math.abs(endDegree - startDegree) * percentTheta; @@ -141,18 +141,17 @@ protected DisplayIndependentRectangle getLayoutBounds(InternalNode[] entitiesToL Math.abs(centerPoint.x - layoutBounds.x)); double maxDistanceY = Math.max(Math.abs(layoutBounds.y + layoutBounds.height - centerPoint.y), Math.abs(centerPoint.y - layoutBounds.y)); - layoutBounds = new DisplayIndependentRectangle(centerPoint.x - maxDistanceX, centerPoint.y - maxDistanceY, + return new DisplayIndependentRectangle(centerPoint.x - maxDistanceX, centerPoint.y - maxDistanceY, maxDistanceX * 2, maxDistanceY * 2); - return layoutBounds; } /** * Find the center point between the roots */ - private DisplayIndependentPoint determineCenterPoint(List roots) { - double totalX = 0, totalY = 0; - for (Iterator iterator = roots.iterator(); iterator.hasNext();) { - InternalNode entity = (InternalNode) iterator.next(); + private static DisplayIndependentPoint determineCenterPoint(List roots) { + double totalX = 0; + double totalY = 0; + for (InternalNode entity : roots) { totalX += entity.getInternalX(); totalY += entity.getInternalY(); } diff --git a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/SpringLayoutAlgorithm.java b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/SpringLayoutAlgorithm.java index 6616b7096..af321f6ca 100644 --- a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/SpringLayoutAlgorithm.java +++ b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/SpringLayoutAlgorithm.java @@ -1,14 +1,14 @@ /******************************************************************************* - * Copyright 2005 CHISEL Group, University of Victoria, Victoria, BC, - * Canada. + * Copyright 2005, 2023 CHISEL Group, University of Victoria, Victoria, BC, + * Canada, Johannes Kepler University Linz * - * This program and the accompanying materials are made available under the + * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: The Chisel Group, University of Victoria + * + * Contributors: The Chisel Group, University of Victoria, Alois Zoitl *******************************************************************************/ package org.eclipse.zest.layouts.algorithms; @@ -34,14 +34,14 @@ * 4. Execute {@link #compute compute()};
* 5. Execute {@link #fitWithinBounds fitWithinBounds(...)};
* 6. Query the computed results(node size and node position). - * + * * @version 2.0 * @author Ian Bull * @author Casey Best (version 1.0 by Jingwei Wu/Rob Lintern) */ public class SpringLayoutAlgorithm extends ContinuousLayoutAlgorithm { - private final static boolean DEFAULT_ANCHOR = false; + private static final boolean DEFAULT_ANCHOR = false; /** * The default value for the spring layout number of interations. @@ -145,18 +145,18 @@ public class SpringLayoutAlgorithm extends ContinuousLayoutAlgorithm { * Maps a src and dest object to the number of relations between them. Key is * src.toString() + dest.toString(), value is an Integer */ - private Map srcDestToNumRelsMap; + private Map srcDestToNumRelsMap; /** * Maps a src and dest object to the average weight of the relations between * them. Key is src.toString() + dest.toString(), value is a Double */ - private Map srcDestToRelsAvgWeightMap; + private Map srcDestToRelsAvgWeightMap; /** * Maps a relationship type to a weight. Key is a string, value is a Double */ - private static Map relTypeToWeightMap = new HashMap(); + private static Map relTypeToWeightMap = new HashMap<>(); private int iteration; @@ -183,8 +183,8 @@ public class SpringLayoutAlgorithm extends ContinuousLayoutAlgorithm { */ public SpringLayoutAlgorithm(int styles) { super(styles); - srcDestToNumRelsMap = new HashMap(); - srcDestToRelsAvgWeightMap = new HashMap(); + srcDestToNumRelsMap = new HashMap<>(); + srcDestToRelsAvgWeightMap = new HashMap<>(); date = new Date(); } @@ -203,7 +203,7 @@ public void setLayoutArea(double x, double y, double width, double height) { /** * Sets the spring layout move-control. - * + * * @param move The move-control value. */ public void setSpringMove(double move) { @@ -213,7 +213,7 @@ public void setSpringMove(double move) { /** * Returns the move-control value of this SpringLayoutAlgorithm in double * presion. - * + * * @return The move-control value. */ public double getSpringMove() { @@ -222,7 +222,7 @@ public double getSpringMove() { /** * Sets the spring layout strain-control. - * + * * @param strain The strain-control value. */ public void setSpringStrain(double strain) { @@ -232,7 +232,7 @@ public void setSpringStrain(double strain) { /** * Returns the strain-control value of this SpringLayoutAlgorithm in double * presion. - * + * * @return The strain-control value. */ public double getSpringStrain() { @@ -241,7 +241,7 @@ public double getSpringStrain() { /** * Sets the spring layout length-control. - * + * * @param length The length-control value. */ public void setSpringLength(double length) { @@ -250,7 +250,7 @@ public void setSpringLength(double length) { /** * Gets the max time this algorithm will run for - * + * * @return */ public long getSpringTimeout() { @@ -259,7 +259,7 @@ public long getSpringTimeout() { /** * Sets the spring timeout - * + * * @param timeout */ public void setSpringTimeout(long timeout) { @@ -269,7 +269,7 @@ public void setSpringTimeout(long timeout) { /** * Returns the length-control value of this SpringLayoutAlgorithm in double * presion. - * + * * @return The length-control value. */ public double getSpringLength() { @@ -278,7 +278,7 @@ public double getSpringLength() { /** * Sets the spring layout gravitation-control. - * + * * @param gravitation The gravitation-control value. */ public void setSpringGravitation(double gravitation) { @@ -288,7 +288,7 @@ public void setSpringGravitation(double gravitation) { /** * Returns the gravitation-control value of this SpringLayoutAlgorithm in double * presion. - * + * * @return The gravitation-control value. */ public double getSpringGravitation() { @@ -297,7 +297,7 @@ public double getSpringGravitation() { /** * Sets the number of iterations to be used. - * + * * @param gravitation The number of iterations. */ public void setIterations(int iterations) { @@ -306,7 +306,7 @@ public void setIterations(int iterations) { /** * Returns the number of iterations to be used. - * + * * @return The number of iterations. */ public int getIterations() { @@ -316,7 +316,7 @@ public int getIterations() { /** * Sets whether or not this SpringLayoutAlgorithm will layout the nodes randomly * before beginning iterations. - * + * * @param random The random placement value. */ public void setRandom(boolean random) { @@ -336,7 +336,7 @@ public void setWeight(String relType, double weight) { } public double getWeight(String relType) { - Double weight = (Double) relTypeToWeightMap.get(relType); + Double weight = relTypeToWeightMap.get(relType); return (weight == null) ? 1 : weight.doubleValue(); } @@ -353,7 +353,7 @@ public void setDefaultConditions() { /** * Clean up after done - * + * * @param entitiesToLayout */ private void reset(InternalNode[] entitiesToLayout) { @@ -363,9 +363,9 @@ private void reset(InternalNode[] entitiesToLayout) { forcesY = null; anchors = null; setDefaultConditions(); - srcDestToNumRelsMap = new HashMap(); - srcDestToRelsAvgWeightMap = new HashMap(); - relTypeToWeightMap = new HashMap(); + srcDestToNumRelsMap = new HashMap<>(); + srcDestToRelsAvgWeightMap = new HashMap<>(); + relTypeToWeightMap = new HashMap<>(); } private long startTime = 0; @@ -388,8 +388,7 @@ protected void preLayoutAlgorithm(InternalNode[] entitiesToLayout, InternalRelat for (int i = 0; i < entitiesToLayout.length; i++) { anchors[i] = DEFAULT_ANCHOR; } - for (int i = 0; i < relationshipsToConsider.length; i++) { - InternalRelationship layoutRelationship = relationshipsToConsider[i]; + for (InternalRelationship layoutRelationship : relationshipsToConsider) { addRelation(layoutRelationship); } @@ -406,36 +405,34 @@ protected void postLayoutAlgorithm(InternalNode[] entitiesToLayout, /** * Adds a simple relation between two nodes to the relation repository. - * + * * @param layoutRelationship The simple relation to be added * @throws java.lang.NullPointerExcetption If sr is null * @see SimpleRelation */ private void addRelation(InternalRelationship layoutRelationship) { if (layoutRelationship == null) { - throw new IllegalArgumentException("The arguments can not be null!"); - } else { - double weight = layoutRelationship.getWeight(); - weight = (weight <= 0 ? 0.1 : weight); - String key1 = layoutRelationship.getSource().toString() + layoutRelationship.getDestination().toString(); - String key2 = layoutRelationship.getDestination().toString() + layoutRelationship.getSource().toString(); - String[] keys = { key1, key2 }; - for (int i = 0; i < keys.length; i++) { - String key = keys[i]; - Integer count = (Integer) srcDestToNumRelsMap.get(key); - Double avgWeight = (Double) srcDestToRelsAvgWeightMap.get(key); - if (count == null) { - count = Integer.valueOf(1); - avgWeight = Double.valueOf(weight); - } else { - int newCount = count.intValue() + 1; - double newAverage = (avgWeight.doubleValue() * count.doubleValue() + weight) / newCount; - avgWeight = Double.valueOf(newAverage); - count = Integer.valueOf(newCount); - } - srcDestToNumRelsMap.put(key, count); - srcDestToRelsAvgWeightMap.put(key, avgWeight); + throw new IllegalArgumentException("The arguments can not be null!"); //$NON-NLS-1$ + } + double weight = layoutRelationship.getWeight(); + weight = (weight <= 0 ? 0.1 : weight); + String key1 = layoutRelationship.getSource().toString() + layoutRelationship.getDestination().toString(); + String key2 = layoutRelationship.getDestination().toString() + layoutRelationship.getSource().toString(); + String[] keys = { key1, key2 }; + for (String key : keys) { + Integer count = srcDestToNumRelsMap.get(key); + Double avgWeight = srcDestToRelsAvgWeightMap.get(key); + if (count == null) { + count = Integer.valueOf(1); + avgWeight = Double.valueOf(weight); + } else { + int newCount = count.intValue() + 1; + double newAverage = (avgWeight.doubleValue() * count.doubleValue() + weight) / newCount; + avgWeight = Double.valueOf(newAverage); + count = Integer.valueOf(newCount); } + srcDestToNumRelsMap.put(key, count); + srcDestToRelsAvgWeightMap.put(key, avgWeight); } } @@ -455,10 +452,11 @@ private void preCompute(InternalNode[] entitiesToLayout) { } } - if (sprRandom) + if (sprRandom) { placeRandomly(entitiesToLayout); // put vertices in random places - else + } else { convertToUnitCoordinates(entitiesToLayout); + } iteration = 1; largestMovement = Double.MAX_VALUE; @@ -488,15 +486,19 @@ protected void convertNodePositionsBack(int i, InternalNode entityToConvert, dou double screenWidth, double screenHeight, DisplayIndependentRectangle layoutBounds) { // If the node selected is outside the screen, map it to the boarder - if (px > screenWidth) + if (px > screenWidth) { px = screenWidth; - if (py > screenHeight) + } + if (py > screenHeight) { py = screenHeight; + } - if (px < 0) + if (px < 0) { px = 1; - if (py < 0) + } + if (py < 0) { py = 1; + } double x = (px / screenWidth) * layoutBounds.width + layoutBounds.x; double y = (py / screenHeight) * layoutBounds.height + layoutBounds.y; @@ -532,11 +534,12 @@ private void checkPreferredLocation(InternalNode[] entitiesToLayout, DisplayInde * running for. You can set the MaxTime in maxTimeMS! */ private void setSprIterationsBasedOnTime() { - if (maxTimeMS <= 0) + if (maxTimeMS <= 0) { return; + } long currentTime = date.getTime(); - double fractionComplete = (double) ((double) (currentTime - startTime) / ((double) maxTimeMS)); + double fractionComplete = (double) (currentTime - startTime) / ((double) maxTimeMS); int currentIteration = (int) (fractionComplete * sprIterations); if (currentIteration > iteration) { iteration = currentIteration; @@ -547,10 +550,10 @@ private void setSprIterationsBasedOnTime() { @Override protected boolean performAnotherNonContinuousIteration() { setSprIterationsBasedOnTime(); - if (iteration <= sprIterations && largestMovement >= sprMove) + if (iteration <= sprIterations && largestMovement >= sprMove) { return true; - else - return false; + } + return false; } @Override @@ -566,8 +569,9 @@ protected int getTotalNumberOfLayoutSteps() { @Override protected void computeOneIteration(InternalNode[] entitiesToLayout, InternalRelationship[] relationshipsToConsider, double x, double y, double width, double height) { - if (bounds == null) + if (bounds == null) { bounds = new DisplayIndependentRectangle(x, y, width, height); + } checkPreferredLocation(entitiesToLayout, bounds); computeForces(entitiesToLayout); largestMovement = Double.MAX_VALUE; @@ -740,8 +744,7 @@ protected void convertToUnitCoordinates(InternalNode[] entitiesToLayout) { double maxX = Double.MIN_VALUE; double minY = Double.MAX_VALUE; double maxY = Double.MIN_VALUE; - for (int i = 0; i < entitiesToLayout.length; i++) { - InternalNode layoutEntity = entitiesToLayout[i]; + for (InternalNode layoutEntity : entitiesToLayout) { minX = Math.min(minX, layoutEntity.getInternalX()); minY = Math.min(minY, layoutEntity.getInternalY()); maxX = Math.max(maxX, layoutEntity.getInternalX()); @@ -769,42 +772,44 @@ protected void convertToUnitCoordinates(InternalNode[] entitiesToLayout) { * Examines the number of specified relation between the src and * the dest that exist in this SpringLayoutAlgorithm's relation * repository. - * + * * @param src The source part of the relaton to be examined. * @param dest The destination part of the relation to be examined. * @return The number of relations between src and dest. */ private int numRelations(Object src, Object dest) { String key = src.toString() + dest.toString(); - Integer count = (Integer) srcDestToNumRelsMap.get(key); - int intCount = (count == null) ? 0 : count.intValue(); - return intCount; + Integer count = srcDestToNumRelsMap.get(key); + return (count == null) ? 0 : count.intValue(); } /** * Returns the average weight between a src and dest object. - * + * * @param src * @param dest * @return The average weight between the given src and dest nodes */ private double avgWeight(Object src, Object dest) { String key = src.toString() + dest.toString(); - Double avgWeight = (Double) srcDestToRelsAvgWeightMap.get(key); - double doubleWeight = (avgWeight == null) ? 1 : avgWeight.doubleValue(); - return doubleWeight; + Double avgWeight = srcDestToRelsAvgWeightMap.get(key); + return (avgWeight == null) ? 1 : avgWeight.doubleValue(); } @Override protected boolean isValidConfiguration(boolean asynchronous, boolean continueous) { - if (asynchronous && continueous) + if (asynchronous && continueous) { return true; - else if (asynchronous && !continueous) + } + if (asynchronous && !continueous) { return true; - else if (!asynchronous && continueous) + } + if (!asynchronous && continueous) { return false; - else if (!asynchronous && !continueous) + } + if (!asynchronous && !continueous) { return true; + } return false; } diff --git a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/TreeLayoutAlgorithm.java b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/TreeLayoutAlgorithm.java index 0852831fc..b658e4581 100644 --- a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/TreeLayoutAlgorithm.java +++ b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/TreeLayoutAlgorithm.java @@ -1,14 +1,14 @@ /******************************************************************************* - * Copyright 2005 CHISEL Group, University of Victoria, Victoria, BC, - * Canada. + * Copyright 2005, 2023 CHISEL Group, University of Victoria, Victoria, BC, + * Canada, Johannes Kepler University Linz * - * This program and the accompanying materials are made available under the + * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: The Chisel Group, University of Victoria + * + * Contributors: The Chisel Group, University of Victoria, Alois Zoitl *******************************************************************************/ package org.eclipse.zest.layouts.algorithms; @@ -16,9 +16,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Set; @@ -31,7 +29,7 @@ /** * The TreeLayoutAlgorithm class implements a simple algorithm to arrange graph * nodes in a layered vertical tree-like layout. - * + * * This is by no means an efficiently coded algorithm. * * @version 2.0 @@ -39,16 +37,16 @@ */ public class TreeLayoutAlgorithm extends AbstractLayoutAlgorithm { - private final static double DEFAULT_WEIGHT = 0; - private final static boolean DEFAULT_MARKED = false; + private static final double DEFAULT_WEIGHT = 0; + private static final boolean DEFAULT_MARKED = false; - private final static boolean AS_DESTINATION = false; - private final static boolean AS_SOURCE = true; + private static final boolean AS_DESTINATION = false; + private static final boolean AS_SOURCE = true; - private final static int NUM_DESCENDENTS_INDEX = 0; - private final static int NUM_LEVELS_INDEX = 1; + private static final int NUM_DESCENDENTS_INDEX = 0; + private static final int NUM_LEVELS_INDEX = 1; - private ArrayList treeRoots; + private List treeRoots; private double boundsX; private double boundsY; @@ -56,8 +54,8 @@ public class TreeLayoutAlgorithm extends AbstractLayoutAlgorithm { private double boundsHeight; private DisplayIndependentRectangle layoutBounds = null; - private List[] parentLists; - private List[] childrenLists; + private List[] parentLists; + private List[] childrenLists; private double[] weights; private boolean[] markedArr; @@ -91,7 +89,6 @@ public void setLayoutArea(double x, double y, double width, double height) { @Override protected int getCurrentLayoutStep() { - // TODO Auto-generated method stub return 0; } @@ -104,17 +101,17 @@ protected int getTotalNumberOfLayoutSteps() { * Executes this TreeLayoutAlgorithm layout algorithm by referencing the data * stored in the repository system. Once done, the result will be saved to the * data repository. - * + * * @param entitiesToLayout Apply the algorithm to these entities * @param relationshipsToConsider Only consider these relationships when * applying the algorithm. - * @param boundsX The left side of the bounds in which the + * @param x The left side of the bounds in which the * layout can place the entities. - * @param boundsY The top side of the bounds in which the layout + * @param y The top side of the bounds in which the layout * can place the entities. - * @param boundsWidth The width of the bounds in which the layout + * @param Width The width of the bounds in which the layout * can place the entities. - * @param boundsHeight The height of the bounds in which the layout + * @param height The height of the bounds in which the layout * can place the entities. * @throws RuntimeException Thrown if entitiesToLayout doesn't contain all of * the endpoints for each relationship in @@ -132,8 +129,8 @@ protected void preLayoutAlgorithm(InternalNode[] entitiesToLayout, InternalRelat weights = new double[entitiesToLayout.length]; markedArr = new boolean[entitiesToLayout.length]; for (int i = 0; i < entitiesToLayout.length; i++) { - parentLists[i] = new ArrayList(); - childrenLists[i] = new ArrayList(); + parentLists[i] = new ArrayList<>(); + childrenLists[i] = new ArrayList<>(); weights[i] = DEFAULT_WEIGHT; markedArr[i] = DEFAULT_MARKED; } @@ -154,8 +151,7 @@ protected void applyLayoutInternal(InternalNode[] entitiesToLayout, InternalRela int totalProgress = 4; fireProgressEvent(1, totalProgress); - // List roots = new ArrayList(); - treeRoots = new ArrayList(); + treeRoots = new ArrayList<>(); buildForest(treeRoots, entitiesToLayout, relationshipsToConsider); fireProgressEvent(2, totalProgress); computePositions(treeRoots, entitiesToLayout); @@ -182,17 +178,16 @@ public List getRoots() { /** * Finds all the relationships in which the node obj * plays the specified role. - * + * * @param entity The node that concerns the relations to be found. * @param role The role played by the obj. Its type must be of * ACTOR_ROLE or ACTEE_ROLE. * @see SimpleRelationship */ - private Collection findRelationships(Object entity, boolean objectAsSource, + private static Collection findRelationships(Object entity, boolean objectAsSource, InternalRelationship[] relationshipsToConsider) { - Collection foundRels = new ArrayList(); - for (int i = 0; i < relationshipsToConsider.length; i++) { - InternalRelationship rel = relationshipsToConsider[i]; + Collection foundRels = new ArrayList<>(); + for (InternalRelationship rel : relationshipsToConsider) { if (objectAsSource && rel.getSource().equals(entity)) { foundRels.add(rel); } else if (!objectAsSource && rel.getDestination().equals(entity)) { @@ -206,7 +201,7 @@ private Collection findRelationships(Object entity, boolean objectAsSource, * Finds the relation that has the lowest index in the relation repository in * which the node obj plays the specified * role. - * + * * @param obj The node that concerns the relations to be found. * @param role The role played by the obj. Its type must be of * ACTOR_ROLE or ACTEE_ROLE. @@ -214,7 +209,7 @@ private Collection findRelationships(Object entity, boolean objectAsSource, * @see SimpleRelationship#ACTOR_ROLE * @see SimpleRelationship#ACTEE_ROLE */ - private InternalRelationship findRelationship(Object entity, boolean objectAsSource, + private static InternalRelationship findRelationship(Object entity, boolean objectAsSource, InternalRelationship[] relationshipsToConsider) { InternalRelationship relationship = null; for (int i = 0; i < relationshipsToConsider.length && relationship == null; i++) { @@ -236,8 +231,8 @@ private InternalRelationship findRelationship(Object entity, boolean objectAsSou * Builds the tree forest that is used to calculate positions for each node in * this TreeLayoutAlgorithm. */ - private void buildForest(List roots, InternalNode[] entities, InternalRelationship[] relationships) { - List unplacedEntities = new ArrayList(Arrays.asList(entities)); + private void buildForest(List roots, InternalNode[] entities, InternalRelationship[] relationships) { + List unplacedEntities = new ArrayList<>(Arrays.asList(entities)); buildForestRecursively(roots, unplacedEntities, entities, relationships); } @@ -245,24 +240,23 @@ private void buildForest(List roots, InternalNode[] entities, InternalRelationsh * Builds the forest recursively. All entities will be placed somewhere in the * forest. */ - private void buildForestRecursively(List roots, List unplacedEntities, InternalNode[] entities, - InternalRelationship[] relationships) { - if (unplacedEntities.size() == 0) { + private void buildForestRecursively(List roots, List unplacedEntities, + InternalNode[] entities, InternalRelationship[] relationships) { + if (!unplacedEntities.isEmpty()) { return; // no more entities to place } // get the first entity in the list of unplaced entities, find its root, and // build this root's tree - InternalNode layoutEntity = (InternalNode) unplacedEntities.get(0); - InternalNode rootEntity = findRootObjectRecursive(layoutEntity, new HashSet(), relationships); + InternalNode layoutEntity = unplacedEntities.get(0); + InternalNode rootEntity = findRootObjectRecursive(layoutEntity, new HashSet<>(), relationships); int rootEntityIndex = indexOfInternalNode(entities, rootEntity); buildTreeRecursively(rootEntity, rootEntityIndex, 0, entities, relationships); roots.add(rootEntity); // now see which nodes are left to be placed in a tree somewhere - List unmarkedCopy = new ArrayList(unplacedEntities); - for (Iterator iter = unmarkedCopy.iterator(); iter.hasNext();) { - InternalNode tmpEntity = (InternalNode) iter.next(); + List unmarkedCopy = new ArrayList<>(unplacedEntities); + for (InternalNode tmpEntity : unmarkedCopy) { int tmpEntityIndex = indexOfInternalNode(entities, tmpEntity); boolean isMarked = markedArr[tmpEntityIndex]; if (isMarked) { @@ -276,7 +270,7 @@ private void buildForestRecursively(List roots, List unplacedEntities, InternalN * Finds the root node that can be treated as the root of a tree. The found root * node should be one of the unmarked nodes. */ - private InternalNode findRootObjectRecursive(InternalNode currentEntity, Set seenAlready, + private InternalNode findRootObjectRecursive(InternalNode currentEntity, Set seenAlready, InternalRelationship[] relationshipsToConsider) { InternalNode rootEntity = null; InternalRelationship rel = findRelationship(currentEntity, AS_DESTINATION, relationshipsToConsider); @@ -308,7 +302,7 @@ private void buildTreeRecursively(InternalNode layoutEntity, int i, double weigh // A marked entity means that it has been added to the // forest, and its weight value needs to be modified. if (markedArr[i]) { - modifyWeightRecursively(layoutEntity, i, weight, new HashSet(), entities, relationships); + modifyWeightRecursively(layoutEntity, i, weight, new HashSet<>(), entities, relationships); return; // No need to do further computation. } @@ -317,10 +311,9 @@ private void buildTreeRecursively(InternalNode layoutEntity, int i, double weigh weights[i] = weight; // collect the children of this entity and put them in order - Collection rels = findRelationships(layoutEntity, AS_SOURCE, relationships); - List children = new ArrayList(); - for (Iterator iter = rels.iterator(); iter.hasNext();) { - InternalRelationship layoutRel = (InternalRelationship) iter.next(); + Collection rels = findRelationships(layoutEntity, AS_SOURCE, relationships); + List children = new ArrayList<>(); + for (InternalRelationship layoutRel : rels) { InternalNode childEntity = layoutRel.getDestination(); children.add(childEntity); } @@ -331,39 +324,33 @@ private void buildTreeRecursively(InternalNode layoutEntity, int i, double weigh // sort the children by level, then by number of descendents, then by number of // children // TODO: SLOW - Collections.sort(children, new Comparator() { - @Override - public int compare(Object o1, Object o2) { - InternalNode node1 = (InternalNode) o1; - InternalNode node2 = (InternalNode) o2; - int[] numDescendentsAndLevel1 = new int[2]; - int[] numDescendentsAndLevel2 = new int[2]; - int level1 = numDescendentsAndLevel1[NUM_LEVELS_INDEX]; - int level2 = numDescendentsAndLevel2[NUM_LEVELS_INDEX]; - if (level1 == level2) { - getNumDescendentsAndLevel(node1, relationships, numDescendentsAndLevel1); - getNumDescendentsAndLevel(node2, relationships, numDescendentsAndLevel2); - int numDescendents1 = numDescendentsAndLevel1[NUM_DESCENDENTS_INDEX]; - int numDescendents2 = numDescendentsAndLevel2[NUM_DESCENDENTS_INDEX]; - if (numDescendents1 == numDescendents2) { - int numChildren1 = getNumChildren(node1, relationships); - int numChildren2 = getNumChildren(node1, relationships); - return numChildren2 - numChildren1; - } else { - return numDescendents2 - numDescendents1; - } - } else { - return level2 - level1; - } - // return getNumChildren(node2, relationships) - getNumChildren(node1, - // relationships); + Collections.sort(children, (o1, o2) -> { + InternalNode node1 = o1; + InternalNode node2 = o2; + int[] numDescendentsAndLevel1 = new int[2]; + int[] numDescendentsAndLevel2 = new int[2]; + int level1 = numDescendentsAndLevel1[NUM_LEVELS_INDEX]; + int level2 = numDescendentsAndLevel2[NUM_LEVELS_INDEX]; + if (level1 != level2) { + return level2 - level1; + } + // return getNumChildren(node2, relationships) - getNumChildren(node1, + // relationships); + getNumDescendentsAndLevel(node1, relationships, numDescendentsAndLevel1); + getNumDescendentsAndLevel(node2, relationships, numDescendentsAndLevel2); + int numDescendents1 = numDescendentsAndLevel1[NUM_DESCENDENTS_INDEX]; + int numDescendents2 = numDescendentsAndLevel2[NUM_DESCENDENTS_INDEX]; + if (numDescendents1 == numDescendents2) { + int numChildren1 = getNumChildren(node1, relationships); + int numChildren2 = getNumChildren(node1, relationships); + return numChildren2 - numChildren1; } + return numDescendents2 - numDescendents1; }); } // map children to this parent, and vice versa - for (Iterator iter = children.iterator(); iter.hasNext();) { - InternalNode childEntity = (InternalNode) iter.next(); + for (InternalNode childEntity : children) { int childEntityIndex = indexOfInternalNode(entities, childEntity); if (!childrenLists[i].contains(childEntity)) { childrenLists[i].add(childEntity); @@ -373,32 +360,30 @@ public int compare(Object o1, Object o2) { } } - for (Iterator iter = children.iterator(); iter.hasNext();) { - InternalNode childEntity = (InternalNode) iter.next(); + for (InternalNode childEntity : children) { int childEntityIndex = indexOfInternalNode(entities, childEntity); buildTreeRecursively(childEntity, childEntityIndex, weight + 1, entities, relationships); } } - private int getNumChildren(InternalNode layoutEntity, InternalRelationship[] relationships) { + private static int getNumChildren(InternalNode layoutEntity, InternalRelationship[] relationships) { return findRelationships(layoutEntity, AS_SOURCE, relationships).size(); } private void getNumDescendentsAndLevel(InternalNode layoutEntity, InternalRelationship[] relationships, int[] numDescendentsAndLevel) { - getNumDescendentsAndLevelRecursive(layoutEntity, relationships, new HashSet(), numDescendentsAndLevel, 0); + getNumDescendentsAndLevelRecursive(layoutEntity, relationships, new HashSet<>(), numDescendentsAndLevel, 0); } private void getNumDescendentsAndLevelRecursive(InternalNode layoutEntity, InternalRelationship[] relationships, - Set seenAlready, int[] numDescendentsAndLevel, int currentLevel) { + Set seenAlready, int[] numDescendentsAndLevel, int currentLevel) { if (seenAlready.contains(layoutEntity)) { return; } seenAlready.add(layoutEntity); numDescendentsAndLevel[NUM_LEVELS_INDEX] = Math.max(numDescendentsAndLevel[NUM_LEVELS_INDEX], currentLevel); - Collection rels = findRelationships(layoutEntity, AS_SOURCE, relationships); - for (Iterator iter = rels.iterator(); iter.hasNext();) { - InternalRelationship layoutRel = (InternalRelationship) iter.next(); + Collection rels = findRelationships(layoutEntity, AS_SOURCE, relationships); + for (InternalRelationship layoutRel : rels) { InternalNode childEntity = layoutRel.getDestination(); numDescendentsAndLevel[NUM_DESCENDENTS_INDEX]++; getNumDescendentsAndLevelRecursive(childEntity, relationships, seenAlready, numDescendentsAndLevel, @@ -410,8 +395,8 @@ private void getNumDescendentsAndLevelRecursive(InternalNode layoutEntity, Inter /** * Modifies the weight value of the marked node recursively. */ - private void modifyWeightRecursively(InternalNode layoutEntity, int i, double weight, Set descendentsSeenSoFar, - InternalNode[] entities, InternalRelationship[] relationships) { + private void modifyWeightRecursively(InternalNode layoutEntity, int i, double weight, + Set descendentsSeenSoFar, InternalNode[] entities, InternalRelationship[] relationships) { // No need to do further computation! if (layoutEntity == null) { return; @@ -428,10 +413,9 @@ private void modifyWeightRecursively(InternalNode layoutEntity, int i, double we } weights[i] = weight; - Collection rels = findRelationships(layoutEntity, AS_SOURCE, relationships); + Collection rels = findRelationships(layoutEntity, AS_SOURCE, relationships); - for (Iterator iter = rels.iterator(); iter.hasNext();) { - InternalRelationship tmpRel = (InternalRelationship) iter.next(); + for (InternalRelationship tmpRel : rels) { InternalNode tmpEntity = tmpRel.getDestination(); int tmpEntityIndex = indexOfInternalNode(entities, tmpEntity); modifyWeightRecursively(tmpEntity, tmpEntityIndex, weight + 1, descendentsSeenSoFar, entities, @@ -442,20 +426,19 @@ private void modifyWeightRecursively(InternalNode layoutEntity, int i, double we /** * Gets the maxium weight of a tree in the forest of this TreeLayoutAlgorithm. */ - private double getMaxiumWeightRecursive(InternalNode layoutEntity, int i, Set seenAlready, + private double getMaxiumWeightRecursive(InternalNode layoutEntity, int i, Set seenAlready, InternalNode[] entities) { double result = 0; if (seenAlready.contains(layoutEntity)) { return result; } seenAlready.add(layoutEntity); - List children = childrenLists[i]; + List children = childrenLists[i]; if (children.isEmpty()) { result = weights[i]; } else { // TODO: SLOW - for (Iterator iter = children.iterator(); iter.hasNext();) { - InternalNode childEntity = (InternalNode) iter.next(); + for (InternalNode childEntity : children) { int childEntityIndex = indexOfInternalNode(entities, childEntity); result = Math.max(result, getMaxiumWeightRecursive(childEntity, childEntityIndex, seenAlready, entities)); @@ -468,20 +451,19 @@ private double getMaxiumWeightRecursive(InternalNode layoutEntity, int i, Set se * Computes positions for each node in this TreeLayoutAlgorithm by referencing * the forest that holds those nodes. */ - private void computePositions(List roots, InternalNode[] entities) { + private void computePositions(List roots, InternalNode[] entities) { // No need to do further computation! - if (roots.size() == 0) { + if (!roots.isEmpty()) { return; } int totalLeafCount = 0; double maxWeight = 0; - for (int i = 0; i < roots.size(); i++) { - InternalNode rootEntity = (InternalNode) roots.get(i); + for (InternalNode rootEntity : roots) { int rootEntityIndex = indexOfInternalNode(entities, rootEntity); totalLeafCount = totalLeafCount + getNumberOfLeaves(rootEntity, rootEntityIndex, entities); maxWeight = Math.max(maxWeight, - getMaxiumWeightRecursive(rootEntity, rootEntityIndex, new HashSet(), entities) + 1.0); + getMaxiumWeightRecursive(rootEntity, rootEntityIndex, new HashSet<>(), entities) + 1.0); } double width = 1.0 / totalLeafCount; @@ -490,10 +472,9 @@ private void computePositions(List roots, InternalNode[] entities) { int leafCountSoFar = 0; // TODO: SLOW! - for (int i = 0; i < roots.size(); i++) { - InternalNode rootEntity = (InternalNode) roots.get(i); + for (InternalNode rootEntity : roots) { int rootEntityIndex = indexOfInternalNode(entities, rootEntity); - computePositionRecursively(rootEntity, rootEntityIndex, leafCountSoFar, width, height, new HashSet(), + computePositionRecursively(rootEntity, rootEntityIndex, leafCountSoFar, width, height, new HashSet<>(), entities); leafCountSoFar = leafCountSoFar + getNumberOfLeaves(rootEntity, rootEntityIndex, entities); } @@ -503,7 +484,7 @@ private void computePositions(List roots, InternalNode[] entities) { * Computes positions recursively until the leaf nodes are reached. */ private void computePositionRecursively(InternalNode layoutEntity, int i, int relativePosition, double width, - double height, Set seenAlready, InternalNode[] entities) { + double height, Set seenAlready, InternalNode[] entities) { if (seenAlready.contains(layoutEntity)) { return; } @@ -520,10 +501,8 @@ private void computePositionRecursively(InternalNode layoutEntity, int i, int re layoutEntity.setInternalLocation(posx, posy); int relativeCount = 0; - List children = childrenLists[i]; // TODO: Slow - for (Iterator iter = children.iterator(); iter.hasNext();) { - InternalNode childEntity = (InternalNode) iter.next(); + for (InternalNode childEntity : childrenLists[i]) { int childEntityIndex = indexOfInternalNode(entities, childEntity); computePositionRecursively(childEntity, childEntityIndex, relativePosition + relativeCount, width, height, seenAlready, entities); @@ -532,18 +511,18 @@ private void computePositionRecursively(InternalNode layoutEntity, int i, int re } private int getNumberOfLeaves(InternalNode layoutEntity, int i, InternalNode[] entities) { - return getNumberOfLeavesRecursive(layoutEntity, i, new HashSet(), entities); + return getNumberOfLeavesRecursive(layoutEntity, i, new HashSet<>(), entities); } - private int getNumberOfLeavesRecursive(InternalNode layoutEntity, int i, Set seen, InternalNode[] entities) { + private int getNumberOfLeavesRecursive(InternalNode layoutEntity, int i, Set seen, + InternalNode[] entities) { int numLeaves = 0; - List children = childrenLists[i]; - if (children.size() == 0) { + List children = childrenLists[i]; + if (!children.isEmpty()) { numLeaves = 1; } else { // TODO: SLOW! - for (Iterator iter = children.iterator(); iter.hasNext();) { - InternalNode childEntity = (InternalNode) iter.next(); + for (InternalNode childEntity : children) { if (!seen.contains(childEntity)) { seen.add(childEntity); int childEntityIndex = indexOfInternalNode(entities, childEntity); @@ -557,18 +536,16 @@ private int getNumberOfLeavesRecursive(InternalNode layoutEntity, int i, Set see } private int getLevel(InternalNode layoutEntity, int i, InternalNode[] entities) { - return getLevelRecursive(layoutEntity, i, new HashSet(), entities); + return getLevelRecursive(layoutEntity, i, new HashSet<>(), entities); } - private int getLevelRecursive(InternalNode layoutEntity, int i, Set seen, InternalNode[] entities) { + private int getLevelRecursive(InternalNode layoutEntity, int i, Set seen, InternalNode[] entities) { if (seen.contains(layoutEntity)) { return 0; } seen.add(layoutEntity); - List parents = parentLists[i]; int maxParentLevel = 0; - for (Iterator iter = parents.iterator(); iter.hasNext();) { - InternalNode parentEntity = (InternalNode) iter.next(); + for (InternalNode parentEntity : parentLists[i]) { int parentEntityIndex = indexOfInternalNode(entities, parentEntity); int parentLevel = getLevelRecursive(parentEntity, parentEntityIndex, seen, entities) + 1; maxParentLevel = Math.max(maxParentLevel, parentLevel); @@ -578,30 +555,33 @@ private int getLevelRecursive(InternalNode layoutEntity, int i, Set seen, Intern /** * Note: Use this as little as possible! TODO limit the use of this method - * + * * @param nodes * @param nodeToFind * @return */ - private int indexOfInternalNode(InternalNode[] nodes, InternalNode nodeToFind) { + private static int indexOfInternalNode(InternalNode[] nodes, InternalNode nodeToFind) { for (int i = 0; i < nodes.length; i++) { InternalNode node = nodes[i]; if (node.equals(nodeToFind)) { return i; } } - throw new RuntimeException("Couldn't find index of internal node: " + nodeToFind); + throw new RuntimeException("Couldn't find index of internal node: " + nodeToFind); //$NON-NLS-1$ } @Override protected boolean isValidConfiguration(boolean asynchronous, boolean continueous) { if (asynchronous && continueous) { return false; - } else if (asynchronous && !continueous) { + } + if (asynchronous && !continueous) { return true; - } else if (!asynchronous && continueous) { + } + if (!asynchronous && continueous) { return false; - } else if (!asynchronous && !continueous) { + } + if (!asynchronous && !continueous) { return true; } diff --git a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/internal/CycleChecker.java b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/internal/CycleChecker.java index 1ad60423f..795b6142d 100644 --- a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/internal/CycleChecker.java +++ b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/internal/CycleChecker.java @@ -1,39 +1,38 @@ /******************************************************************************* - * Copyright 2005 CHISEL Group, University of Victoria, Victoria, BC, - * Canada. + * Copyright 2005, 2023 CHISEL Group, University of Victoria, Victoria, BC, + * Canada, Johannes Kepler University Linz * - * This program and the accompanying materials are made available under the + * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: The Chisel Group, University of Victoria + * + * Contributors: The Chisel Group, University of Victoria, Alois Zoitl *******************************************************************************/ package org.eclipse.zest.layouts.algorithms.internal; import java.util.ArrayList; import java.util.Arrays; -import java.util.Hashtable; -import java.util.Iterator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.eclipse.zest.layouts.LayoutEntity; import org.eclipse.zest.layouts.LayoutRelationship; import org.eclipse.zest.layouts.algorithms.AbstractLayoutAlgorithm; -import org.eclipse.zest.layouts.exampleStructures.SimpleRelationship; /** * Checks for cycles in the given graph. - * + * * @author Casey Best */ public class CycleChecker { /** * Tests if there is a directed cirlce in the graph formed by the given entities * and relationships. - * + * * @param entities The entities in the graph to check * @param relationships The relationships in the graph to check * @param cycle Populated with the cycle encountered, if there is one. @@ -42,41 +41,35 @@ public class CycleChecker { * @return true if there is a directed circle. Otherwise, * false. */ - public static boolean hasDirectedCircles(LayoutEntity[] entities, LayoutRelationship[] relationships, List cycle) { + public static boolean hasDirectedCircles(LayoutEntity[] entities, LayoutRelationship[] relationships, + List cycle) { if (!AbstractLayoutAlgorithm.verifyInput(entities, relationships)) { - throw new RuntimeException("The endpoints of the relationships aren't contained in the entities list."); + throw new RuntimeException("The endpoints of the relationships aren't contained in the entities list."); //$NON-NLS-1$ } - // Enumeration enum; - // Iterator iterator; - Hashtable endPoints = new Hashtable(); + Map> endPoints = new HashMap<>(); // Initialize the relation(transitive) vector. - for (int i = 0; i < relationships.length; i++) { - LayoutRelationship rel = relationships[i]; - + for (LayoutRelationship rel : relationships) { // Add the relationship to the source endpoint - Object subject = rel.getSourceInLayout(); - List rels = (List) endPoints.get(subject); - if (rels == null) { - rels = new ArrayList(); - endPoints.put(subject, rels); - } - if (!rels.contains(rel)) + LayoutEntity subject = rel.getSourceInLayout(); + List rels = endPoints.computeIfAbsent(subject, sub -> new ArrayList<>()); + if (!rels.contains(rel)) { rels.add(rel); + } } - boolean hasCyle = hasCycle(new ArrayList(Arrays.asList(entities)), endPoints, cycle); - return hasCyle; + return hasCycle(new ArrayList<>(Arrays.asList(entities)), endPoints, cycle); } /** * Check passed in nodes for a cycle */ - private static boolean hasCycle(List nodesToCheck, Hashtable endPoints, List cycle) { - while (nodesToCheck.size() > 0) { - Object checkNode = nodesToCheck.get(0); - List checkedNodes = new ArrayList(); - if (hasCycle(checkNode, new ArrayList(), null, endPoints, checkedNodes, cycle)) { + private static boolean hasCycle(List nodesToCheck, + Map> endPoints, List cycle) { + while (!nodesToCheck.isEmpty()) { + LayoutEntity checkNode = nodesToCheck.get(0); + List checkedNodes = new ArrayList<>(); + if (hasCycle(checkNode, new ArrayList<>(), null, endPoints, checkedNodes, cycle)) { return true; } nodesToCheck.removeAll(checkedNodes); @@ -90,8 +83,9 @@ private static boolean hasCycle(List nodesToCheck, Hashtable endPoints, List cyc * * @returns true if there is a cycle */ - private static boolean hasCycle(Object nodeToCheck, List nodePathSoFar, SimpleRelationship cameFrom, - Hashtable endPoints, List nodesChecked, List cycle) { + private static boolean hasCycle(LayoutEntity nodeToCheck, List nodePathSoFar, + LayoutRelationship cameFrom, Map> endPoints, + List nodesChecked, List cycle) { if (nodePathSoFar.contains(nodeToCheck)) { cycle.addAll(nodePathSoFar); cycle.add(nodeToCheck); @@ -100,24 +94,18 @@ private static boolean hasCycle(Object nodeToCheck, List nodePathSoFar, SimpleRe nodePathSoFar.add(nodeToCheck); nodesChecked.add(nodeToCheck); - List relations = (List) endPoints.get(nodeToCheck); + List relations = endPoints.get(nodeToCheck); if (relations != null) { - for (Iterator iter = relations.iterator(); iter.hasNext();) { - SimpleRelationship rel = (SimpleRelationship) iter.next(); - + for (LayoutRelationship rel : relations) { if (cameFrom == null || !rel.equals(cameFrom)) { - Object currentNode = null; - currentNode = rel.getDestinationInLayout(); + LayoutEntity currentNode = rel.getDestinationInLayout(); if (hasCycle(currentNode, nodePathSoFar, rel, endPoints, nodesChecked, cycle)) { return true; } } - } } - nodePathSoFar.remove(nodeToCheck); - return false; } diff --git a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/internal/DynamicScreen.java b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/internal/DynamicScreen.java index bf108049e..8877a90f7 100644 --- a/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/internal/DynamicScreen.java +++ b/org.eclipse.zest.layouts/src/org/eclipse/zest/layouts/algorithms/internal/DynamicScreen.java @@ -1,14 +1,14 @@ /******************************************************************************* - * Copyright 2005 CHISEL Group, University of Victoria, Victoria, BC, - * Canada. + * Copyright 2005, 2023 CHISEL Group, University of Victoria, Victoria, BC, + * Canada, Johannes Kepler University Linz * - * This program and the accompanying materials are made available under the + * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: The Chisel Group, University of Victoria + * + * Contributors: The Chisel Group, University of Victoria, Alois Zoitl *******************************************************************************/ package org.eclipse.zest.layouts.algorithms.internal; @@ -21,8 +21,8 @@ public class DynamicScreen { - private TreeSet XCoords = null; - private TreeSet YCoords = null; + private final TreeSet xCoords = new TreeSet<>(new XComparator()); + private final TreeSet yCoords = new TreeSet<>(new YComparator()); private DisplayIndependentRectangle screenBounds = null; @@ -38,53 +38,45 @@ public void cleanScreen() { maxY = 0.0; } - class XComparator implements Comparator { + class XComparator implements Comparator { @Override - public int compare(Object arg0, Object arg1) { - InternalNode n1 = (InternalNode) arg0; - InternalNode n2 = (InternalNode) arg1; - if (n1.getInternalX() > n2.getInternalX()) + public int compare(InternalNode n1, InternalNode n2) { + if (n1.getInternalX() > n2.getInternalX()) { return +1; - else if (n1.getInternalX() < n2.getInternalX()) + } + if (n1.getInternalX() < n2.getInternalX()) { return -1; - else { - return n1.toString().compareTo(n2.toString()); } - + return n1.toString().compareTo(n2.toString()); } } - class YComparator implements Comparator { + class YComparator implements Comparator { @Override - public int compare(Object arg0, Object arg1) { - InternalNode n1 = (InternalNode) arg0; - InternalNode n2 = (InternalNode) arg1; - if (n1.getInternalY() > n2.getInternalY()) + public int compare(InternalNode n1, InternalNode n2) { + if (n1.getInternalY() > n2.getInternalY()) { return +1; - else if (n1.getInternalY() < n2.getInternalY()) + } + if (n1.getInternalY() < n2.getInternalY()) { return -1; - else { - return n1.toString().compareTo(n2.toString()); } + return n1.toString().compareTo(n2.toString()); } } public DynamicScreen(int x, int y, int width, int height) { - XCoords = new TreeSet(new XComparator()); - YCoords = new TreeSet(new YComparator()); - this.screenBounds = new DisplayIndependentRectangle(x, y, width, height); } public void removeNode(InternalNode node) { - XCoords.remove(node); - YCoords.remove(node); + xCoords.remove(node); + yCoords.remove(node); } public void addNode(InternalNode node) { - XCoords.add(node); - YCoords.add(node); + xCoords.add(node); + yCoords.add(node); } public DisplayIndependentPoint getScreenLocation(InternalNode node) { @@ -111,10 +103,10 @@ public DisplayIndependentPoint getVirtualLocation(DisplayIndependentPoint point) } private DisplayIndependentRectangle calculateBounds() { - InternalNode n1 = (InternalNode) XCoords.first(); - InternalNode n2 = (InternalNode) XCoords.last(); - InternalNode n3 = (InternalNode) YCoords.first(); - InternalNode n4 = (InternalNode) YCoords.last(); + InternalNode n1 = xCoords.first(); + InternalNode n2 = xCoords.last(); + InternalNode n3 = yCoords.first(); + InternalNode n4 = yCoords.last(); double x = n1.getInternalX(); double width = n2.getInternalX(); double y = n3.getInternalY();