From 3b08c7880f3c133f76389ed25dfcdf336f448c92 Mon Sep 17 00:00:00 2001 From: Khureshi Date: Sat, 27 Jan 2018 08:22:46 -0800 Subject: [PATCH 01/70] code cleanup - removed unneeded methods --- .../fxgraph/graph/EventHandlers.java | 317 ------------------ 1 file changed, 317 deletions(-) diff --git a/src/main/java/com/application/fxgraph/graph/EventHandlers.java b/src/main/java/com/application/fxgraph/graph/EventHandlers.java index 0d94ce9..078cf52 100644 --- a/src/main/java/com/application/fxgraph/graph/EventHandlers.java +++ b/src/main/java/com/application/fxgraph/graph/EventHandlers.java @@ -36,7 +36,6 @@ public class EventHandlers { private boolean subtreeExpanded = true; private boolean posUpdated = true; - Graph graph; static Main main; @@ -564,11 +563,9 @@ private void expandTreeAt(String cellId, int threadId) { } - private EventHandler onMousePressedToCollapseTree = new EventHandler() { @Override public void handle(MouseEvent event) { - // System.out.println("Nothing happens on in EventHandler::onMousePressedToCollapseTree Event"); invokeOnMousePressedEventHandler((CircleCell) event.getSource(), Integer.valueOf(main.getCurrentSelectedThread())); } }; @@ -876,9 +873,6 @@ private void moveLowerTreeByDelta(String clickedCellID, double clickedCellBottom } - // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> private void updateDBInBackgroundThread(int clickedCellId, double topY, double bottomY, double leftX, double rightX, double delta, double deltaX, boolean isCollapsed, int nextCellId, int threadId, int lastCellId, int parentId) { Statement statement = DatabaseUtil.createStatement(); @@ -937,9 +931,6 @@ protected void failed() { new Thread(task).start(); } - // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> private void updateCollapseValForSubTreeBulk(double topY, double bottomY, double leftX, Statement statement, boolean isMinimized, int startCellId, int endCellId, int threadId) { // Collapsed value -> description @@ -1098,55 +1089,6 @@ private void updateCollapseValForSubTreeBulk(double topY, double bottomY, double // System.out.println("EventHandler::updateCollapseValForSubTreeBulk: method ended"); } - private void insertHighlightsInExpandedSubTree(double topY, double bottomY, double leftX, Statement statement, boolean isMinimized, int startCellId, int endCellId) { - - main.firstCBMap.forEach((pckgFullName, ignore) -> { - - }); - - } - - private void updateCollapseValForEdgesSubTreeBulk(Statement statement, boolean isMinimized, int startCellId, int endCellId) throws SQLException { - String updateEdgeQuery2; - - if (isMinimized) { - updateEdgeQuery2 = "UPDATE " + TableNames.EDGE_TABLE + " " + - "SET COLLAPSED = " + - "CASE " + - "WHEN COLLAPSED = 0 THEN 1 " + - "ELSE COLLAPSED " + - "END " + - "WHERE FK_TARGET_ELEMENT_ID IN " + - "(SELECT ELE.ID FROM " + TableNames.ELEMENT_TABLE + " AS ELE JOIN " + TableNames.EDGE_TABLE + " as EDGE " + - "ON ELE.ID = EDGE.FK_TARGET_ELEMENT_ID " + - "WHERE EDGE.FK_TARGET_ELEMENT_ID > " + startCellId + " " + - "AND EDGE.FK_TARGET_ELEMENT_ID < " + endCellId + " " + - "AND (ELE.COLLAPSED <> 0 OR ELE.COLLAPSED <> 2)" + - ")"; - } else { - - updateEdgeQuery2 = "UPDATE " + TableNames.EDGE_TABLE + " " + - "SET COLLAPSED = " + - "CASE " + - "WHEN COLLAPSED = 1 THEN 0 " + - "ELSE COLLAPSED " + - "END " + - "WHERE FK_TARGET_ELEMENT_ID IN " + - "(SELECT ELE.ID FROM " + TableNames.ELEMENT_TABLE + " AS ELE JOIN " + TableNames.EDGE_TABLE + " as EDGE " + - "ON ELE.ID = EDGE.FK_TARGET_ELEMENT_ID " + - "WHERE EDGE.FK_TARGET_ELEMENT_ID > " + startCellId + " " + - "AND EDGE.FK_TARGET_ELEMENT_ID < " + endCellId + " " + - "AND ELE.COLLAPSED = 0 " + - "AND ELE.COLLAPSED = 2" + - ")"; - } - statement.addBatch(updateEdgeQuery2); - - } - - // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> private void updateTreeBelowYBulk(double y, double delta, Statement statement, int nextCellId, int lastCellId, int threadId) { // System.out.println("EventHandler::updateTreeBelowYBulk: method started"); String updateCellsQuery = "UPDATE " + TableNames.ELEMENT_TABLE + " " + @@ -1192,9 +1134,6 @@ private void updateTreeBelowYBulk(double y, double delta, Statement statement, i // System.out.println("EventHandler::updateTreeBelowYBulk: method ended."); } - // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> - // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> /** * This method gets cell's BOUND_BOX_Y_BOTTOM_LEFT and calculates it's new value. * Then updates cell's BOUND_BOX_Y_BOTTOM_LEFT and BOUND_BOX_Y_BOTTOM_RIGHT values. @@ -1252,24 +1191,6 @@ else if (rectangleCell.getBoundsInParent().contains(finalX, finalY)) { }); } - private void updateAllParentHighlightsInDB(int clickedCellId, double y, double delta, double deltaX, Statement statement, int threadId) { - try { - String updateParentHighlights = "UPDATE " + TableNames.HIGHLIGHT_ELEMENT + " " + - "SET HEIGHT = HEIGHT - " + delta + " " + - "WHERE START_Y <= " + y + " " + - "AND START_Y + HEIGHT >= " + y + " " + - "AND ELEMENT_ID < " + clickedCellId + " " + - "AND COLLAPSED = 0 " + - "AND THREAD_ID = " + threadId; - - statement.addBatch(updateParentHighlights); - // System.out.println("EventHandler::updateAllParentHighlightsInDB: updateParentHighlights: " + updateParentHighlights); - - } catch (SQLException e) { - e.printStackTrace(); - } - } - private void updateChildrenHighlightsInDB(int cellId, boolean isCollapsed, Statement statement, double delta, int nextCellId, int threadId) { // System.out.println("EventHandlers.updateChildrenHighlightsInDB: method started"); @@ -1445,244 +1366,6 @@ private void updateParentHighlightsInDB(int cellId, boolean isCollapsed, Stateme // System.out.println("EventHandlers.updateParentHighlightsInDB method ends"); } - private void updateClickedCellHighlights(int clickedCellId, double y, double delta, double deltaX, Statement statement) { - try { - String updateParentHighlightsForClickedId = "UPDATE " + TableNames.HIGHLIGHT_ELEMENT + " " + - "SET HEIGHT = HEIGHT - " + delta + ", " + - "WIDTH = WIDTH - " + deltaX + " " + - "WHERE ELEMENT_ID = " + clickedCellId; - - statement.addBatch(updateParentHighlightsForClickedId); - // System.out.println("EventHandler::updateAllParentHighlightsInDB: updateParentHighlightsForClickedId: " + updateParentHighlightsForClickedId); - - } catch (SQLException e) { - e.printStackTrace(); - } - } - - // This method returns the edge update query. - // It accepts target x and y coordinate and get the source x and y coordinates. - private String getEdgePosUpdateQuery(int targetId, double endX, double endY) { - // Get the element row for source cell - String getSourceElementRow = "SELECT * FROM " + TableNames.ELEMENT_TABLE + " " + - "WHERE ID = (" + - "SELECT FK_SOURCE_ELEMENT_ID FROM " + TableNames.EDGE_TABLE + " " + - "WHERE FK_TARGET_ELEMENT_ID = " + targetId + ")"; - - String edgeUpdateQuery = null; - - try (ResultSet sourceCellRS = DatabaseUtil.select(getSourceElementRow)) { - if (sourceCellRS.next()) { - // Update edge only if it exists. Edge only exists if there is a source cell for the current cell (target cell) - // get x and y coordinates of source and target cell. The current cell is target cell. - double edgeNewStartX = sourceCellRS.getDouble("bound_box_x_coordinate"); - double edgeNewStartY = sourceCellRS.getDouble("bound_box_y_coordinate"); - double edgeNewEndX = endX; - double edgeNewEndY = endY; - - // For edges, update the pos values. - edgeUpdateQuery = "UPDATE " + TableNames.EDGE_TABLE + " " + - "SET START_X = " + edgeNewStartX + ", " + - "START_Y = " + edgeNewStartY + ", " + - "END_X = " + edgeNewEndX + ", " + - "END_Y = " + edgeNewEndY + - "WHERE FK_TARGET_ELEMENT_ID = " + targetId; - - - // System.out.println("EventHandler::getEdgePosUpdateQuery: Update query for edge: " + edgeUpdateQuery); - - } - } catch (SQLException e) { - System.out.println("SQL that threw exception: " + getSourceElementRow); - e.printStackTrace(); - } - - return edgeUpdateQuery; - } - - - private static void addEdgePosUpdateQueryToStatement(int targetId, double y, Statement statement) throws SQLException { - - - // Update the startX and startY values of all edges that start at current cell. - String updateEdgeStartPosQuery = "UPDATE " + TableNames.EDGE_TABLE + " " + - "SET START_Y = " + y + " " + - "WHERE FK_SOURCE_ELEMENT_ID = " + targetId; - - // System.out.println("EventHandler::getEdgePosUpdateQuery: Update query for edge: change of start pos: " + updateEdgeStartPosQuery); - - // Update the endX and endY values of all edges that end at current cell. - String updateEdgeEndPosQuery = "UPDATE " + TableNames.EDGE_TABLE + " " + - "SET END_Y = " + y + " " + - "WHERE FK_TARGET_ELEMENT_ID = " + targetId; - - // System.out.println("EventHandler::getEdgePosUpdateQuery: Update query for edge: change of end pos: " + updateEdgeEndPosQuery); - - statement.addBatch(updateEdgeStartPosQuery); - statement.addBatch(updateEdgeEndPosQuery); - - } - - - public void expandSubtreeAndUpdateColValsOfSubtreeRootedAt(String cellId) { - Task expandSubtree = new Task() { - @Override - protected Void call() throws Exception { - expandSubtreeAndUpdateColValsRecursive(cellId); - return null; - } - - @Override - protected void succeeded() { - super.succeeded(); - subtreeExpanded = true; - System.out.println("set subtreeExpanded: " + subtreeExpanded); - Platform.runLater(() -> setClickable()); - // System.out.println("EventHandler::updatePosValForLowerTree: Updated the entire tree successfully"); - } - - @Override - protected void failed() { - super.failed(); - System.out.println("EventHandler::updatePosValForLowerTree: Failed to update tree."); - try { - throw new Exception("updatePosValForLowerTree failed"); - } catch (Exception e) { - e.printStackTrace(); - } - } - }; - - // catch the exception in the thread. - expandSubtree.setOnFailed(event -> { - expandSubtree.getException().printStackTrace(); - }); - new Thread(expandSubtree).start(); - - - } - - public void expandSubtreeAndUpdateColValsRecursive(String cellId) { - // Get element row for this cell - try (ResultSet elementRS = ElementDAOImpl.selectWhere("id = " + cellId)) { - if (elementRS.next()) { - int collapsed = elementRS.getInt("collapsed"); - if (collapsed == 0) { - throw new IllegalStateException("Collapsed cannot be 0 here at CellID: " + cellId); - } else if (collapsed == 1) { - System.out.println(" ==> collapse 1 -> 0 at cellId: " + cellId); - ElementDAOImpl.updateWhere("collapsed", "0", "id = " + cellId); - - // Create a new circle cell and add to UI - float xCoordinateTemp = elementRS.getFloat("bound_box_x_coordinate"); - float yCoordinateTemp = elementRS.getFloat("bound_box_y_coordinate"); - CircleCell cell = new CircleCell(cellId, xCoordinateTemp, yCoordinateTemp); - Platform.runLater(() -> graph.getModel().addCell(cell)); - - - // Create a new edge and add to UI. Update edge's collapsed=0 - try (ResultSet parentRS = ElementToChildDAOImpl.selectWhere("child_id = " + cellId)) { - if (parentRS.next()) { - String parentId = String.valueOf(parentRS.getInt("parent_id")); - CircleCell parentCell = graph.getModel().getCircleCellsOnUI().get(parentId); - - Edge edge = new Edge(parentCell, cell); - - EdgeDAOImpl.updateWhere("collapsed", "0", - "fk_target_element_id = " + cellId); - - Platform.runLater(() -> graph.getModel().addEdge(edge)); - } - } - - // graph.myEndUpdate(); - Platform.runLater(() -> graph.updateCellLayer()); - - - // Recurse to this cells children - try (ResultSet childrenRS = ElementToChildDAOImpl.selectWhere("parent_id = " + cellId)) { - while (childrenRS.next()) { - String childId = String.valueOf(childrenRS.getInt("child_id")); - expandSubtreeAndUpdateColValsRecursive(childId); - } - } - - } else if (collapsed == 2) { - System.out.println(" ==> collapse 2 -> 0 at cellId: " + cellId); - - // update collapsed=0 - ElementDAOImpl.updateWhere("collapsed", "0", "id = " + cellId); - // for all children with collapsed=1, show and update collapsed=0 - try (ResultSet childrenRS = ElementToChildDAOImpl.selectWhere("parent_id = " + cellId)) { - while (childrenRS.next()) { - String childId = String.valueOf(childrenRS.getInt("child_id")); - expandSubtreeAndUpdateColValsRecursive(childId); - } - } - - } else if (collapsed == 3) { - System.out.println(" ==> collapse 3 -> 2 at cellId: " + cellId); - - // update collapsed=2 - ElementDAOImpl.updateWhere("collapsed", "2", "id = " + cellId); - - // Create new circle cell and add to UI - float xCoordinateTemp = elementRS.getFloat("bound_box_x_coordinate"); - float yCoordinateTemp = elementRS.getFloat("bound_box_y_coordinate"); - CircleCell cell = new CircleCell(cellId, xCoordinateTemp, yCoordinateTemp); - Platform.runLater(() -> graph.getModel().addCell(cell)); - - // Create a new edge and add to UI. Update edge's collapsed=0 - try (ResultSet parentRS = ElementToChildDAOImpl.selectWhere("child_id = " + cellId)) { - if (parentRS.next()) { - String parentId = String.valueOf(parentRS.getInt("parent_id")); - CircleCell parentCell = graph.getModel().getCircleCellsOnUI().get(parentId); - - Edge edge = new Edge(parentCell, cell); - EdgeDAOImpl.updateWhere("collapsed", "0", - "fk_target_element_id = " + cellId); - - Platform.runLater(() -> graph.getModel().addEdge(edge)); - - } - } - // graph.myEndUpdate(); - Platform.runLater(() -> graph.updateCellLayer()); - - // Do not recurse to children. Stop at this cell. - } - } - } catch (SQLException e) { - e.printStackTrace(); - } - - } - - - public void updateCollapseValForSubTreeRootedAtRecursive(String cellId, List removeCircleCells, List removeEdges) { - try (ResultSet childrenRS = ElementToChildDAOImpl.selectWhere("parent_id = " + cellId)) { - try { - while (childrenRS.next()) { - String childId = String.valueOf(childrenRS.getInt("child_id")); - removeCircleCells.add(childId); - removeEdges.add(childId); - - ElementDAOImpl.updateWhere("collapsed", "1", - "id = " + childId + " AND collapsed = 0"); - ElementDAOImpl.updateWhere("collapsed", "3", - "id = " + childId + " AND collapsed = 2"); - - EdgeDAOImpl.updateWhere("collapsed", "1", - "fk_target_element_id = " + childId); - - updateCollapseValForSubTreeRootedAtRecursive(childId, removeCircleCells, removeEdges); - } - } catch (SQLException e) { - e.printStackTrace(); - } - } catch (SQLException e) { - } - } @SuppressWarnings("unused") EventHandler onMousePressedEventHandler = new EventHandler() { From 8d9961be7b36e42592bdb3ffed33a62696f8df27 Mon Sep 17 00:00:00 2001 From: Khureshi Date: Sat, 27 Jan 2018 22:41:11 -0800 Subject: [PATCH 02/70] Added features - multiple screenshots, mouse over for info and max/min buttons, save scroll positions on thread change. --- .gitignore | 5 +- src/main/java/com/application/Main.java | 40 ++++++-- .../application/fxgraph/cells/CircleCell.java | 74 ++++++++++++--- .../fxgraph/graph/EventHandlers.java | 94 +++++++++++++++++-- 4 files changed, 179 insertions(+), 34 deletions(-) diff --git a/.gitignore b/.gitignore index 55cd965..1d7fbd2 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,7 @@ target/ *.png # intelliJ files -*.iml \ No newline at end of file +*.iml + +# screenshots folder +/Screenshots/ \ No newline at end of file diff --git a/src/main/java/com/application/Main.java b/src/main/java/com/application/Main.java index c8e1e78..19abce4 100644 --- a/src/main/java/com/application/Main.java +++ b/src/main/java/com/application/Main.java @@ -42,6 +42,10 @@ import javax.imageio.ImageIO; import java.io.File; import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; @@ -789,16 +793,19 @@ private void setUpThreadsView() { } - - private int imgId = 0; - private void saveUIImage() { System.out.println("In saveUIImage."); ScrollPane scrollPane = graph.getScrollPane(); WritableImage image = scrollPane.snapshot(new SnapshotParameters(), null); - File file = new File("screenshot-" + imgId + ".png"); - imgId++; + // Create screenshots folder if id doesn't exist. + File dir = new File("Screenshots"); + if (!dir.exists()) { + dir.mkdir(); + } + + String imgPath = "Screenshots" + File.separator + "screenshot-" + dir.list().length + ".png"; + File file = new File(imgPath); try { ImageIO.write(SwingFXUtils.fromFXImage(image, null), "png", file); } catch (IOException e) { @@ -998,7 +1005,7 @@ private void postDatabaseLoad() { // } public void showThread(String threadId) { - System.out.println("Main::showThread: clicked thread: " + threadId); + saveScrollBarPos(Integer.valueOf(currentSelectedThread)); currentSelectedThread = threadId; // Prevent triggering listeners from modifying circleCellsOnUI, edgesOnUI and highlightsOnUI HashMaps @@ -1007,16 +1014,33 @@ public void showThread(String threadId) { // graph.getModel().uiUpdateRequired = true; convertDBtoElementTree.setCurrentThreadId(threadId); convertDBtoElementTree.clearUI(); + positionScrollBarFromHistory(Integer.valueOf(threadId)); updateUi(); // Prevent triggering listeners from modifying circleCellsOnUI, edgesOnUI and highlightsOnUI HashMaps ZoomableScrollPane.turnOnListeners(); graph.getModel().stackRectangles(); - System.out.println("Main::showThread: END"); } - public void updateUi() { + Map vScrollBarPos = new HashMap<>(); + Map hScrollBarPos = new HashMap<>(); + + private void saveScrollBarPos(int threadId) { + vScrollBarPos.put(threadId, graph.getScrollPane().getVvalue()); + hScrollBarPos.put(threadId, graph.getScrollPane().getHvalue()); + } + private void positionScrollBarFromHistory(int threadId) { + graph.getScrollPane().setVvalue(vScrollBarPos.getOrDefault(threadId, 0.0)); + if (vScrollBarPos.get(threadId) != null) { + } + graph.getScrollPane().setHvalue(hScrollBarPos.getOrDefault(threadId, 0.0)); + + if (hScrollBarPos.get(threadId) != null) { + } + } + + public void updateUi() { if (convertDBtoElementTree != null && graph != null) { // System.out.println("Main::updateUi: called by " + caller + " thread " + Thread.currentThread().getName()); BoundingBox viewPortDims = graph.getViewPortDims(); diff --git a/src/main/java/com/application/fxgraph/cells/CircleCell.java b/src/main/java/com/application/fxgraph/cells/CircleCell.java index c82f5fb..ecfed70 100644 --- a/src/main/java/com/application/fxgraph/cells/CircleCell.java +++ b/src/main/java/com/application/fxgraph/cells/CircleCell.java @@ -3,28 +3,42 @@ import com.application.fxgraph.ElementHelpers.Element; import com.application.fxgraph.graph.Cell; import javafx.geometry.Pos; +import javafx.scene.Group; import javafx.scene.control.Label; import javafx.scene.paint.Color; +import javafx.scene.shape.Arc; +import javafx.scene.shape.ArcType; import javafx.scene.shape.Circle; +import javafx.scene.text.Font; import javafx.scene.text.TextAlignment; +import org.controlsfx.glyphfont.FontAwesome; +import org.controlsfx.glyphfont.Glyph; public class CircleCell extends Cell { private Label label; - private Label idLabel; private Label methodName; private Circle circle; + private Group minMaxGroup; + private Group infoGroup; + public CircleCell(String id) { super(id); - // Uncomment to see yellow background on the whole circle cell stack pane. + // Uncomment to see a colored background on the whole circle cell stack pane. // setStyle("-fx-background-color: mediumslateblue"); circle = new Circle(20); + label = new Label("This is a long string"); - idLabel = new Label("-" + id + "-"); + // id label + Label idLabel = new Label(id); + idLabel.relocate(12, 10); + idLabel.setFont(Font.font(15)); + + // method name label methodName = new Label(""); methodName.setPrefWidth(85); methodName.setWrapText(true); @@ -35,10 +49,41 @@ public CircleCell(String id) { circle.setFill(Color.web("#6699CC")); circle.relocate(0,0); - // getChildren().setAll(circle, label); - getChildren().add(circle); - getChildren().add(methodName); - getChildren().add(idLabel); + // Min-Max button + Arc minMaxArc = new Arc(); + minMaxArc.setCenterX(20); + minMaxArc.setCenterY(20); + minMaxArc.setRadiusX(20); + minMaxArc.setRadiusY(20); + minMaxArc.setStartAngle(270); + minMaxArc.setLength(180); + minMaxArc.setType(ArcType.ROUND); + minMaxArc.setFill(Color.TRANSPARENT); + + Glyph minMaxGlyph = new Glyph("FontAwesome", FontAwesome.Glyph.EXPAND); + minMaxGlyph.setColor(Color.TRANSPARENT); + minMaxGlyph.relocate(25, 13); + + minMaxGroup = new Group(minMaxArc, minMaxGlyph); + + // info button + Arc infoArc = new Arc(); + infoArc.setCenterX(20); + infoArc.setCenterY(20); + infoArc.setRadiusX(20); + infoArc.setRadiusY(20); + infoArc.setStartAngle(90); + infoArc.setLength(180); + infoArc.setType(ArcType.ROUND); + infoArc.setFill(Color.TRANSPARENT); + + Glyph infoGlyph = new Glyph("FontAwesome", FontAwesome.Glyph.INFO_CIRCLE); + infoGlyph.setColor(Color.TRANSPARENT); + infoGlyph.relocate(5, 13); + infoGroup = new Group(infoArc, infoGlyph); + + getChildren().addAll(circle, methodName, idLabel, minMaxGroup, infoGroup); + // setView(group); this.toFront(); } @@ -58,18 +103,10 @@ public CircleCell (String id, float xCoordinate, float yCoordinate) { this.toFront(); } - public String getLabel() { - return label.getText(); - } - public void setLabel(String text) { this.label.setText(text); } - public String getMethodName() { - return methodName.getText(); - } - public void setMethodName(String methodName) { this.methodName.setText(methodName); @@ -83,6 +120,13 @@ public void setColor(Color color) { circle.setFill(color); } + public Group getMinMaxGroup() { + return minMaxGroup; + } + + public Group getInfoGroup() { + return infoGroup; + } @Override public String toString() { diff --git a/src/main/java/com/application/fxgraph/graph/EventHandlers.java b/src/main/java/com/application/fxgraph/graph/EventHandlers.java index 078cf52..1a3ecaa 100644 --- a/src/main/java/com/application/fxgraph/graph/EventHandlers.java +++ b/src/main/java/com/application/fxgraph/graph/EventHandlers.java @@ -6,18 +6,23 @@ import com.application.db.DatabaseUtil; import com.application.db.TableNames; import com.application.fxgraph.cells.CircleCell; +import javafx.animation.FillTransition; import javafx.application.Platform; import javafx.concurrent.Task; import javafx.event.EventHandler; import javafx.geometry.Insets; +import javafx.scene.Group; import javafx.scene.Node; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.input.MouseEvent; import javafx.scene.layout.GridPane; import javafx.scene.paint.Color; +import javafx.scene.shape.Arc; import javafx.scene.shape.Circle; +import javafx.util.Duration; import org.controlsfx.control.PopOver; +import org.controlsfx.glyphfont.Glyph; import java.sql.Connection; import java.sql.ResultSet; @@ -51,10 +56,19 @@ public void setCustomMouseEventHandlers(final Node node) { // ***************** // Show popup to display element details on mouse hover on an element. // node.setOnMouseEntered(onMouseHoverToShowInfoEventHandler); - node.setOnMousePressed(onMouseHoverToShowInfoEventHandler); + // node.setOnMousePressed(onMouseHoverToShowInfoEventHandler); // node.setOnMousePressed(onMousePressedToCollapseTree); // ***************** + // ((CircleCell)node).getInfoArc().setOnMouseEntered(infoEnterEventHandler); + + ((CircleCell)node).getInfoGroup().setOnMouseEntered(infoEnterEventHandler); + ((CircleCell)node).getInfoGroup().setOnMouseExited(infoExitEventHandler); + ((CircleCell)node).getInfoGroup().setOnMousePressed(onMouseHoverToShowInfoEventHandler); + + ((CircleCell)node).getMinMaxGroup().setOnMouseEntered(minMaxEnterEventHandler); + ((CircleCell)node).getMinMaxGroup().setOnMouseExited(minMaxExitEventHandler); + ((CircleCell)node).getMinMaxGroup().setOnMousePressed(onMousePressedToCollapseTree); // ***************** // For debugging. Prints all mouse events. @@ -96,7 +110,8 @@ public void handle(MouseEvent event) { } Node node = (Node) event.getSource(); - CircleCell cell = (CircleCell) node; + // CircleCell cell = (CircleCell) node; + CircleCell cell = (CircleCell) node.getParent(); String timeStamp; int methodId, processId, threadId; String parameters, packageName = "", methodName = "", parameterTypes = "", eventType, lockObjectId; @@ -355,9 +370,6 @@ public void handle(MouseEvent event) { // Collapse and Expand subtree button Button minMaxButton = new Button("min / max"); minMaxButton.setOnMouseClicked(event1 -> { - if (popOver != null) { - popOver.hide(); - } invokeOnMousePressedEventHandler(cell, threadId); } ); @@ -387,9 +399,72 @@ public void handle(MouseEvent event) { } }; + EventHandler infoEnterEventHandler = new EventHandler() { + @Override + public void handle(MouseEvent event) { + Group node = (Group) event.getSource(); + Arc arc = (Arc) node.getChildren().get(0); + Glyph glyph = ((Glyph) node.getChildren().get(1)); + + // FillTransition ftArc = new FillTransition(Duration.millis(100), arc, Color.TRANSPARENT, Color.web("#DDDDDD")); + // ftArc.setCycleCount(4); + // ftArc.setAutoReverse(true); + // ftArc.play(); + + // FillTransition ftGlyph = new FillTransition(Duration.millis(500), glyph , Color.TRANSPARENT, Color.BLACK); + // ftGlyph.setCycleCount(4); + // ftGlyph.setAutoReverse(true); + // ftGlyph.play(); + + arc.setFill(Color.web("#DDDDDD")); + glyph.setColor(Color.BLACK); + } + }; + + EventHandler infoExitEventHandler = new EventHandler() { + @Override + public void handle(MouseEvent event) { + Group node = (Group) event.getSource(); + Arc arc = (Arc) node.getChildren().get(0); + Glyph glyph = ((Glyph) node.getChildren().get(1)); + + arc.setFill(Color.TRANSPARENT); + glyph.setColor(Color.TRANSPARENT); + } + }; + + + EventHandler minMaxEnterEventHandler = new EventHandler() { + @Override + public void handle(MouseEvent event) { + Group node = (Group) event.getSource(); + Arc arc = (Arc) node.getChildren().get(0); + Glyph glyph = ((Glyph) node.getChildren().get(1)); + + arc.setFill(Color.web("#DDDDDD")); + glyph.setColor(Color.BLACK); + } + }; + + EventHandler minMaxExitEventHandler = new EventHandler() { + @Override + public void handle(MouseEvent event) { + Group node = (Group) event.getSource(); + Arc arc = (Arc) node.getChildren().get(0); + Glyph glyph = ((Glyph) node.getChildren().get(1)); + + arc.setFill(Color.TRANSPARENT); + glyph.setColor(Color.TRANSPARENT); + } + }; + private void invokeOnMousePressedEventHandler(CircleCell cell, int threadId) { { + if (popOver != null) { + popOver.hide(); + } + if (!clickable) { System.out.println(">>>>>>>>>>>>>>>>>>> Clickable is false. <<<<<<<<<<<<<<<<<<<<<"); return; @@ -443,14 +518,13 @@ private void invokeOnMousePressedEventHandler(CircleCell cell, int threadId) { // MINIMIZE SUBTREE // System.out.println(">>>> clicked on a collapsed = 0 cell."); - ((Circle) clickedCell.getChildren().get(0)).setFill(Color.BLUE); + // ((Circle) clickedCell.getChildren().get(0)).setFill(Color.BLUE); // ((Circle) ( (Group)cell.getView() ) // .getChildren().get(0)) // .setFill(Color.BLUE); // cell.getChildren().get(0).setStyle("-fx-background-color: blue"); // cell.setStyle("-fx-background-color: blue"); - clickedCell.setLabel("+"); main.setStatus("Please wait ......"); subtreeExpanded = true; @@ -502,9 +576,8 @@ private void invokeOnMousePressedEventHandler(CircleCell cell, int threadId) { } else if (collapsed == 2) { // MAXIMIZE SUBTREE - ((Circle) clickedCell.getChildren().get(0)).setFill(Color.RED); + // ((Circle) clickedCell.getChildren().get(0)).setFill(Color.RED); // ( (Circle) ( (Group)cell.getView() ).getChildren().get(0) ).setFill(Color.RED); - clickedCell.setLabel("-"); main.setStatus("Please wait ......"); System.out.println("====== Maximize cellId: " + clickedCellID + " ++++++ "); @@ -566,7 +639,8 @@ private void expandTreeAt(String cellId, int threadId) { private EventHandler onMousePressedToCollapseTree = new EventHandler() { @Override public void handle(MouseEvent event) { - invokeOnMousePressedEventHandler((CircleCell) event.getSource(), Integer.valueOf(main.getCurrentSelectedThread())); + CircleCell cell = ((CircleCell) ((Node) event.getSource()).getParent()); + invokeOnMousePressedEventHandler(cell, Integer.valueOf(main.getCurrentSelectedThread())); } }; From c7c41719b48ef593ea38947d6cd822ada0060338 Mon Sep 17 00:00:00 2001 From: Khureshi Date: Sun, 28 Jan 2018 13:30:06 -0800 Subject: [PATCH 03/70] Added refresh view menu and supporting functionality --- src/main/java/com/application/Main.java | 58 ++++++++++++++++--- .../fxgraph/graph/EventHandlers.java | 24 ++++---- 2 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/application/Main.java b/src/main/java/com/application/Main.java index 19abce4..6bfd9a1 100644 --- a/src/main/java/com/application/Main.java +++ b/src/main/java/com/application/Main.java @@ -42,10 +42,6 @@ import javax.imageio.ImageIO; import java.io.File; import java.io.IOException; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; @@ -55,7 +51,6 @@ public class Main extends Application { - // Main UI screen private Graph graph; Model model; @@ -114,6 +109,10 @@ public class Main extends Application { private MenuItem printEdgesMenuItem; private MenuItem printHighlightsMenuItem; + private Menu viewMenu; // View menu button + private MenuItem refreshGraphWindowMenuItem; + private Glyph refreshGraphWindowGlyph; + // Status bar private Group statusBar; private Label statusBarLabel = new Label(); @@ -320,6 +319,18 @@ private void setUpMenu() { goToMenu.setDisable(true); menuItems.add(clearHistoryMenuItem); + // ***************** + // View Menu + // ***************** + viewMenu = new Menu("View"); + refreshGraphWindowGlyph = new Glyph(font, FontAwesome.Glyph.REFRESH); + refreshGraphWindowGlyph.setColor(ColorProp.ENABLED); + refreshGraphWindowMenuItem = new MenuItem("Refresh graph widow", refreshGraphWindowGlyph); + + viewMenu.getItems().addAll(refreshGraphWindowMenuItem); + menuItems.add(refreshGraphWindowMenuItem); + glyphs.add(refreshGraphWindowGlyph); + // ***************** // Highlights Menu // ***************** @@ -339,12 +350,13 @@ private void setUpMenu() { printCellsMenuItem = new MenuItem("Print circles on canvas to console"); printEdgesMenuItem = new MenuItem("Print edges on canvas to console"); printHighlightsMenuItem = new MenuItem("Print highlights on canvas to console"); + debugMenu.getItems().addAll(printCellsMenuItem, printEdgesMenuItem, printHighlightsMenuItem); // ***************** // Main Menu // ***************** - menuBar.getMenus().addAll(fileMenu, runMenu, saveImgMenu, goToMenu, highlight, debugMenu); + menuBar.getMenus().addAll(fileMenu, runMenu, viewMenu, saveImgMenu, goToMenu, highlight, debugMenu); glyphs.addAll(Arrays.asList(methodDefnGlyph, callTraceGlyph, resetGlyph, runAnalysisGlyph, saveImgGlyph, recentsGlyph, clearHistoryGlyph, highlightItemsGlyph)); @@ -430,7 +442,9 @@ private void setUpMenuForReloads() { goToMenu.getItems().addAll(recentMenu, clearHistoryMenuItem); menuItems.add(clearHistoryMenuItem); - // Highlight method invocations menu. + // ***************** + // Highlights Menu + // ***************** highlight = new Menu("Highlights"); highlightItemsGlyph = new Glyph(font, FontAwesome.Glyph.FLAG); highlightItemsGlyph.setColor(ColorProp.ENABLED_COLORFUL); @@ -439,6 +453,18 @@ private void setUpMenuForReloads() { highlight.getItems().add(highlightMenuItem); menuItems.add(highlightMenuItem); + // ***************** + // View Menu + // ***************** + viewMenu = new Menu("View"); + refreshGraphWindowGlyph = new Glyph(font, FontAwesome.Glyph.REFRESH); + refreshGraphWindowGlyph.setColor(ColorProp.ENABLED); + refreshGraphWindowMenuItem = new MenuItem("Refresh graph widow", refreshGraphWindowGlyph); + + viewMenu.getItems().addAll(refreshGraphWindowMenuItem); + menuItems.add(refreshGraphWindowMenuItem); + glyphs.add(refreshGraphWindowGlyph); + // ***************** // Debug Menu // ***************** @@ -449,7 +475,7 @@ private void setUpMenuForReloads() { debugMenu.getItems().addAll(printCellsMenuItem, printEdgesMenuItem, printHighlightsMenuItem); // Main menu - menuBar.getMenus().addAll(fileMenu, runMenu, saveImgMenu, goToMenu, highlight, debugMenu); + menuBar.getMenus().addAll(fileMenu, runMenu, viewMenu, saveImgMenu, goToMenu, highlight, debugMenu); glyphs.addAll(Arrays.asList(methodDefnGlyph, callTraceGlyph, resetGlyph, runAnalysisGlyph, saveImgGlyph, recentsGlyph, clearHistoryGlyph, highlightItemsGlyph)); @@ -599,6 +625,10 @@ public void handle(ActionEvent event) { System.out.println("---------------------------------------------------"); }); + refreshGraphWindowMenuItem.setOnAction(event -> { + refreshGraphWindow(); + }); + // System.out.println("Main::setUpMenuActions: method ended"); } @@ -1004,6 +1034,14 @@ private void postDatabaseLoad() { // return resMap; // } + + private void refreshGraphWindow() { + System.out.println("Main.refreshGraphWindow: method started. "); + graph.getModel().uiUpdateRequired = true; + showThread(currentSelectedThread); + System.out.println("Main.refreshGraphWindow: method ended. "); + } + public void showThread(String threadId) { saveScrollBarPos(Integer.valueOf(currentSelectedThread)); currentSelectedThread = threadId; @@ -1013,9 +1051,13 @@ public void showThread(String threadId) { // graph.getModel().uiUpdateRequired = true; convertDBtoElementTree.setCurrentThreadId(threadId); + System.out.println("Main.showThread: before clear UI"); convertDBtoElementTree.clearUI(); + System.out.println("Main.showThread: before after UI"); positionScrollBarFromHistory(Integer.valueOf(threadId)); + updateUi(); + System.out.println("Main.showThread: after updateUI()"); // Prevent triggering listeners from modifying circleCellsOnUI, edgesOnUI and highlightsOnUI HashMaps ZoomableScrollPane.turnOnListeners(); diff --git a/src/main/java/com/application/fxgraph/graph/EventHandlers.java b/src/main/java/com/application/fxgraph/graph/EventHandlers.java index 1a3ecaa..51932ad 100644 --- a/src/main/java/com/application/fxgraph/graph/EventHandlers.java +++ b/src/main/java/com/application/fxgraph/graph/EventHandlers.java @@ -20,6 +20,7 @@ import javafx.scene.paint.Color; import javafx.scene.shape.Arc; import javafx.scene.shape.Circle; +import javafx.scene.shape.Shape; import javafx.util.Duration; import org.controlsfx.control.PopOver; import org.controlsfx.glyphfont.Glyph; @@ -405,19 +406,15 @@ public void handle(MouseEvent event) { Group node = (Group) event.getSource(); Arc arc = (Arc) node.getChildren().get(0); Glyph glyph = ((Glyph) node.getChildren().get(1)); + Node glyphNode = node.getChildren().get(1); - // FillTransition ftArc = new FillTransition(Duration.millis(100), arc, Color.TRANSPARENT, Color.web("#DDDDDD")); - // ftArc.setCycleCount(4); - // ftArc.setAutoReverse(true); - // ftArc.play(); + FillTransition ftArc = new FillTransition(Duration.millis(50), arc, Color.TRANSPARENT, Color.web("#DDDDDD")); + ftArc.setOnFinished(e -> { + glyph.setColor(Color.BLACK); + }); - // FillTransition ftGlyph = new FillTransition(Duration.millis(500), glyph , Color.TRANSPARENT, Color.BLACK); - // ftGlyph.setCycleCount(4); - // ftGlyph.setAutoReverse(true); - // ftGlyph.play(); + ftArc.play(); - arc.setFill(Color.web("#DDDDDD")); - glyph.setColor(Color.BLACK); } }; @@ -428,8 +425,11 @@ public void handle(MouseEvent event) { Arc arc = (Arc) node.getChildren().get(0); Glyph glyph = ((Glyph) node.getChildren().get(1)); - arc.setFill(Color.TRANSPARENT); - glyph.setColor(Color.TRANSPARENT); + FillTransition ftArc = new FillTransition(Duration.millis(50), arc, Color.web("#DDDDDD"), Color.TRANSPARENT); + ftArc.setOnFinished(e -> { + glyph.setColor(Color.TRANSPARENT); + }); + ftArc.play(); } }; From b690e79db7258245c0389b299ed24aa58b2fb98c Mon Sep 17 00:00:00 2001 From: Khureshi Date: Sun, 28 Jan 2018 21:17:05 -0800 Subject: [PATCH 04/70] Added foundational logic for nav bar --- .../ConvertDBtoElementTree.java | 35 ++++++++++++++++ .../ElementHelpers/SimplifiedElement.java | 40 +++++++++++++++++++ .../fxgraph/graph/EventHandlers.java | 24 ++++++++++- .../com/application/fxgraph/graph/Model.java | 17 ++++++++ 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/application/fxgraph/ElementHelpers/SimplifiedElement.java diff --git a/src/main/java/com/application/fxgraph/ElementHelpers/ConvertDBtoElementTree.java b/src/main/java/com/application/fxgraph/ElementHelpers/ConvertDBtoElementTree.java index 0077634..df56064 100644 --- a/src/main/java/com/application/fxgraph/ElementHelpers/ConvertDBtoElementTree.java +++ b/src/main/java/com/application/fxgraph/ElementHelpers/ConvertDBtoElementTree.java @@ -5,9 +5,11 @@ import com.application.db.TableNames; import com.application.fxgraph.cells.CircleCell; import com.application.fxgraph.graph.*; +import com.sun.xml.internal.rngom.digested.DUnaryPattern; import javafx.application.Platform; import javafx.geometry.BoundingBox; import javafx.scene.shape.Line; +import sun.java2d.pipe.SpanShapeRenderer; import java.sql.ResultSet; import java.sql.SQLException; @@ -377,6 +379,9 @@ private void addCircleCells() { curCircleCell = new CircleCell(id, xCoordinate, yCoordinate); curCircleCell.setMethodName(methodName); model.addCell(curCircleCell); + SimplifiedElement ele = new SimplifiedElement(id, methodName); + model.addSimplifiedElementToMap(ele); + String label = ""; switch (eventType.toUpperCase()) { case "WAIT-ENTER": @@ -395,6 +400,7 @@ private void addCircleCells() { // Add parent circle cell if not already added earlier. parentCircleCell = mapCircleCellsOnUI.get(parentId); if (!mapCircleCellsOnUI.containsKey(parentId)) { + System.out.println("now you know this executes ------------------ "); try (ResultSet rsTemp = ElementDAOImpl.selectWhere("id = " + parentId)) { if (rsTemp.next() && rsTemp.getInt("LEVEL_COUNT") > 1) { float xCoordinateTemp = rsTemp.getFloat("bound_box_x_coordinate"); @@ -405,6 +411,33 @@ private void addCircleCells() { } } } + + + // 1 -> 2 -> 3 + String pId = String.valueOf(rs.getInt("PARENT_ID")); + SimplifiedElement childSE = ele, parentSE; + try { + while (Integer.valueOf(pId) != -1) { + System.out.println("stuck here pId: " + pId + "------"); + String q = "SELECT * FROM " + TableNames.ELEMENT_TABLE + " AS E " + + "JOIN " + TableNames.CALL_TRACE_TABLE + " AS CT " + + "ON E.ID_ENTER_CALL_TRACE = CT.ID " + + "WHERE E.ID = " + pId; + ResultSet pRS = DatabaseUtil.select(q); + if (pRS.next()) { + String mName = pRS.getString("MESSAGE"); + parentSE = new SimplifiedElement(pId, mName); + childSE.setParentElement(parentSE); + pId = String.valueOf(pRS.getInt("PARENT_ID")); + childSE = parentSE; + } else { + pId = "-1"; + } + } + System.out.println("out ------"); + } catch (SQLException e) { + e.printStackTrace(); + } } // else { // curCircleCell = mapCircleCellsOnUI.get(id); @@ -488,6 +521,8 @@ private void removeCircleCells(BoundingBox preloadBox) { CircleCell cell = entry.getValue(); if (!preloadBox.contains(cell.getLayoutX(), cell.getLayoutY())) { removeCircleCells.add(cell.getCellId()); + + model.removeSimplifiedElementFromMap(cell.getCellId()); } } diff --git a/src/main/java/com/application/fxgraph/ElementHelpers/SimplifiedElement.java b/src/main/java/com/application/fxgraph/ElementHelpers/SimplifiedElement.java new file mode 100644 index 0000000..56d72d8 --- /dev/null +++ b/src/main/java/com/application/fxgraph/ElementHelpers/SimplifiedElement.java @@ -0,0 +1,40 @@ +package com.application.fxgraph.ElementHelpers; + +import java.util.List; + +public class SimplifiedElement { + + private SimplifiedElement parentElement; + private String elementId; + private String methodName; + private List children; + + public SimplifiedElement(String elementId, String methodName) { + this.elementId = elementId; + this.methodName = methodName; + } + + public SimplifiedElement getParentElement() { + return parentElement; + } + + public void setParentElement(SimplifiedElement parentElement) { + this.parentElement = parentElement; + } + + public String getElementId() { + return elementId; + } + + public void setElementId(String elementId) { + this.elementId = elementId; + } + + public String getMethodName() { + return methodName; + } + + public void setMethodName(String methodName) { + this.methodName = methodName; + } +} diff --git a/src/main/java/com/application/fxgraph/graph/EventHandlers.java b/src/main/java/com/application/fxgraph/graph/EventHandlers.java index 51932ad..69a370b 100644 --- a/src/main/java/com/application/fxgraph/graph/EventHandlers.java +++ b/src/main/java/com/application/fxgraph/graph/EventHandlers.java @@ -5,6 +5,7 @@ import com.application.db.DAOImplementation.*; import com.application.db.DatabaseUtil; import com.application.db.TableNames; +import com.application.fxgraph.ElementHelpers.SimplifiedElement; import com.application.fxgraph.cells.CircleCell; import javafx.animation.FillTransition; import javafx.application.Platform; @@ -24,6 +25,7 @@ import javafx.util.Duration; import org.controlsfx.control.PopOver; import org.controlsfx.glyphfont.Glyph; +import sun.java2d.pipe.SpanShapeRenderer; import java.sql.Connection; import java.sql.ResultSet; @@ -61,7 +63,7 @@ public void setCustomMouseEventHandlers(final Node node) { // node.setOnMousePressed(onMousePressedToCollapseTree); // ***************** - // ((CircleCell)node).getInfoArc().setOnMouseEntered(infoEnterEventHandler); + node.setOnMouseEntered(onMouseEnterToShowNav); ((CircleCell)node).getInfoGroup().setOnMouseEntered(infoEnterEventHandler); ((CircleCell)node).getInfoGroup().setOnMouseExited(infoExitEventHandler); @@ -392,6 +394,26 @@ public void handle(MouseEvent event) { } }; + EventHandler onMouseEnterToShowNav = new EventHandler() { + @Override + public void handle(MouseEvent event) { + CircleCell cell = ((CircleCell) event.getSource()); + SimplifiedElement ele = graph.getModel().getSimplifiedElementMap().get(cell.getCellId()); + + ArrayList methodNames = new ArrayList<>(); + while (ele.getParentElement() != null) { + methodNames.add("Id: " + ele.getElementId() + " Method: " + ele.getMethodName()); + System.out.println("at id: " + ele.getElementId()); + ele = ele.getParentElement(); + } + + Collections.reverse(methodNames); + String navString = String.join(" > ", methodNames); + System.out.println("-----------------hover over: " + cell.getCellId() + "------------------------------- "); + System.out.println(navString); + } + }; + EventHandler onMouseExitToDismissPopover = new EventHandler() { @Override public void handle(MouseEvent event) { diff --git a/src/main/java/com/application/fxgraph/graph/Model.java b/src/main/java/com/application/fxgraph/graph/Model.java index c1fd02a..aed4489 100644 --- a/src/main/java/com/application/fxgraph/graph/Model.java +++ b/src/main/java/com/application/fxgraph/graph/Model.java @@ -1,6 +1,7 @@ package com.application.fxgraph.graph; import com.application.fxgraph.ElementHelpers.Element; +import com.application.fxgraph.ElementHelpers.SimplifiedElement; import com.application.fxgraph.cells.CircleCell; import com.application.fxgraph.cells.RectangleCell; import com.application.fxgraph.cells.TriangleCell; @@ -31,6 +32,7 @@ public class Model { private Map highlightsOnUI = new HashMap<>(); + private Map simplifiedElementMap = new HashMap<>(); public Model() { graphParent = new Cell("_ROOT_"); @@ -66,6 +68,20 @@ public void stackRectangles() { // System.out.println("fronting end ======================================================================"); } + public void addSimplifiedElementToMap(SimplifiedElement element) { + simplifiedElementMap.put(element.getElementId(), element); + } + + public void removeSimplifiedElementFromMap(String elementId) { + if (simplifiedElementMap.get(elementId) != null) { + simplifiedElementMap.remove(elementId); + } + } + + public Map getSimplifiedElementMap() { + return simplifiedElementMap; + } + public void addCell(CircleCell circleCell) { // circleCell.toFront(); // circleCell.setTranslateZ(10); @@ -75,6 +91,7 @@ public void addCell(CircleCell circleCell) { circleCellsOnUI.put(circleCell.getCellId(), circleCell); // System.out.println( "Model::addCell: circleCellsOnUI.size() " +circleCellsOnUI.size()); listCircleCellsOnUI.add(circleCell); + } // } } From 8957fc9df6c5cb67bb9b5fc4e90a8f0e49039a3b Mon Sep 17 00:00:00 2001 From: Khureshi Date: Mon, 29 Jan 2018 09:27:18 -0800 Subject: [PATCH 05/70] Added foundational logic for bookmarks --- src/main/java/com/application/Main.java | 74 +++++++++-- .../DAOImplementation/BookmarksDAOImpl.java | 120 ++++++++++++++++++ .../java/com/application/db/DatabaseUtil.java | 1 + .../java/com/application/db/TableNames.java | 1 + .../com/application/db/model/Bookmark.java | 78 ++++++++++++ .../fxgraph/graph/EventHandlers.java | 32 +++-- .../com/application/fxgraph/graph/Graph.java | 5 + 7 files changed, 287 insertions(+), 24 deletions(-) create mode 100644 src/main/java/com/application/db/DAOImplementation/BookmarksDAOImpl.java create mode 100644 src/main/java/com/application/db/model/Bookmark.java diff --git a/src/main/java/com/application/Main.java b/src/main/java/com/application/Main.java index 6bfd9a1..60d222b 100644 --- a/src/main/java/com/application/Main.java +++ b/src/main/java/com/application/Main.java @@ -100,7 +100,7 @@ public class Main extends Application { private MenuItem clearHistoryMenuItem; private Glyph clearHistoryGlyph; - private Menu highlight; + private Menu highlightMenu; private MenuItem highlightMenuItem; private Glyph highlightItemsGlyph; @@ -113,6 +113,11 @@ public class Main extends Application { private MenuItem refreshGraphWindowMenuItem; private Glyph refreshGraphWindowGlyph; + private Menu bookmarksMenu; // Bookmarks menu button + private Menu bookmarksSubMenu; + private Glyph bookmarksGlyph; + + // Status bar private Group statusBar; private Label statusBarLabel = new Label(); @@ -334,15 +339,27 @@ private void setUpMenu() { // ***************** // Highlights Menu // ***************** - highlight = new Menu("Highlights"); + highlightMenu = new Menu("Highlights"); highlightItemsGlyph = new Glyph(font, FontAwesome.Glyph.FLAG); highlightItemsGlyph.setColor(ColorProp.ENABLED); highlightMenuItem = new MenuItem("Highlight method invocations", highlightItemsGlyph); - highlight.getItems().add(highlightMenuItem); - highlight.setDisable(true); + highlightMenu.getItems().add(highlightMenuItem); + highlightMenu.setDisable(true); menuItems.add(highlightMenuItem); + // ***************** + // Bookmarks Menu + // ***************** + bookmarksMenu = new Menu("Bookmarks"); + bookmarksGlyph = new Glyph(font, FontAwesome.Glyph.BOOKMARK); + bookmarksSubMenu = new Menu("Bookmarks", bookmarksGlyph); + + bookmarksMenu.getItems().add(bookmarksSubMenu); + bookmarksMenu.setDisable(true); + menuItems.add(bookmarksMenu); + glyphs.add(bookmarksGlyph); + // ***************** // Debug Menu // ***************** @@ -356,7 +373,7 @@ private void setUpMenu() { // ***************** // Main Menu // ***************** - menuBar.getMenus().addAll(fileMenu, runMenu, viewMenu, saveImgMenu, goToMenu, highlight, debugMenu); + menuBar.getMenus().addAll(fileMenu, runMenu, viewMenu, saveImgMenu, goToMenu, highlightMenu, debugMenu); glyphs.addAll(Arrays.asList(methodDefnGlyph, callTraceGlyph, resetGlyph, runAnalysisGlyph, saveImgGlyph, recentsGlyph, clearHistoryGlyph, highlightItemsGlyph)); @@ -445,14 +462,26 @@ private void setUpMenuForReloads() { // ***************** // Highlights Menu // ***************** - highlight = new Menu("Highlights"); + highlightMenu = new Menu("Highlights"); highlightItemsGlyph = new Glyph(font, FontAwesome.Glyph.FLAG); highlightItemsGlyph.setColor(ColorProp.ENABLED_COLORFUL); highlightMenuItem = new MenuItem("Highlight method invocations", highlightItemsGlyph); - highlight.getItems().add(highlightMenuItem); + highlightMenu.getItems().add(highlightMenuItem); menuItems.add(highlightMenuItem); + // ***************** + // Bookmarks Menu + // ***************** + bookmarksMenu = new Menu("Bookmarks"); + bookmarksGlyph = new Glyph(font, FontAwesome.Glyph.BOOKMARK); + bookmarksSubMenu = new Menu("Bookmarks", bookmarksGlyph); + + bookmarksMenu.getItems().add(bookmarksSubMenu); + bookmarksMenu.setDisable(true); + menuItems.add(bookmarksMenu); + glyphs.add(bookmarksGlyph); + // ***************** // View Menu // ***************** @@ -475,7 +504,7 @@ private void setUpMenuForReloads() { debugMenu.getItems().addAll(printCellsMenuItem, printEdgesMenuItem, printHighlightsMenuItem); // Main menu - menuBar.getMenus().addAll(fileMenu, runMenu, viewMenu, saveImgMenu, goToMenu, highlight, debugMenu); + menuBar.getMenus().addAll(fileMenu, runMenu, viewMenu, saveImgMenu, goToMenu, highlightMenu, debugMenu); glyphs.addAll(Arrays.asList(methodDefnGlyph, callTraceGlyph, resetGlyph, runAnalysisGlyph, saveImgGlyph, recentsGlyph, clearHistoryGlyph, highlightItemsGlyph)); @@ -539,7 +568,7 @@ private void setUpMenuActions() { saveImgMenu.setDisable(false); goToMenu.setDisable(false); - highlight.setDisable(false); + highlightMenu.setDisable(false); } }); @@ -598,6 +627,8 @@ public void handle(ActionEvent event) { // highlightMenuItem.setOnAction(event -> setUpMethodsWindow()); highlightMenuItem.setOnAction(event -> setUpHighlightsWindow()); + bookmarksSubMenu.setOnAction(event -> showBookmarks()); + printCellsMenuItem.setOnAction(event -> { System.out.println("-----------Cells on canvas ------------------------"); graph.getModel().getCircleCellsOnUI().keySet().stream().sorted(Comparator.comparingInt(Integer::valueOf)).forEach(id -> { @@ -632,6 +663,25 @@ public void handle(ActionEvent event) { // System.out.println("Main::setUpMenuActions: method ended"); } + private void showBookmarks() { + bookmarksSubMenu.getItems().clear(); + BookmarksDAOImpl.getBookmarks().forEach((id, bookmark) -> { + MenuItem bookmarkMenuItem = new MenuItem( + "Id:" + bookmark.getElementId() + + " method:" + bookmark.getMethodName() + + " thread:" + bookmark.getThreadId()); + + bookmarksSubMenu.getItems().add(bookmarkMenuItem); + + bookmarkMenuItem.setOnAction(event -> { + System.out.println("Main.showBookmarks: jumpTo: elementId: " + bookmark.getElementId() ); + graph.getEventHandlers().jumpTo(Integer.valueOf(bookmark.getElementId()), bookmark.getThreadId()); + }); + + }); + + } + public String getCurrentSelectedThread() { return currentSelectedThread; } @@ -728,7 +778,7 @@ public void setUpNavigationBar() { // Get its element id. Get its parent id. // Get clicked cell's parent cell coordinates. // scroll to parent. - // highlight parent. + // highlightMenu parent. // Go To First child. // When an element is clicked. Highlight it. @@ -738,7 +788,7 @@ public void setUpNavigationBar() { // Get its element id. Get its child's id. // Get clicked cell's child cell coordinates. // scroll to child - // highlight parent. + // highlightMenu parent. }); @@ -1708,7 +1758,7 @@ private void updateColors(Statement statement) { private void resetHighlights() { // firstTimeSetUpMethodsWindowCall = true; firstTimeSetUpHighlightsWindowCall = true; - highlight.setDisable(true); + highlightMenu.setDisable(true); } } \ No newline at end of file diff --git a/src/main/java/com/application/db/DAOImplementation/BookmarksDAOImpl.java b/src/main/java/com/application/db/DAOImplementation/BookmarksDAOImpl.java new file mode 100644 index 0000000..afd1d7e --- /dev/null +++ b/src/main/java/com/application/db/DAOImplementation/BookmarksDAOImpl.java @@ -0,0 +1,120 @@ +package com.application.db.DAOImplementation; + +import com.application.db.DatabaseUtil; +import com.application.db.TableNames; +import com.application.db.model.Bookmark; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.HashMap; +import java.util.Map; + +public class BookmarksDAOImpl { + + public static boolean isTableCreated() { + return DatabaseUtil.isTableCreated(TableNames.BOOKMARKS); + } + + public static void createTable() { + if (!isTableCreated()) { + try (Connection c = DatabaseUtil.getConnection(); Statement ps = c.createStatement()) { + String sql = "CREATE TABLE " + TableNames.BOOKMARKS + " (" + + "id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), " + + "element_id INT, " + + "color VARCHAR(10), " + + "collapsed INT" + + ")"; + ps.execute(sql); + System.out.println("** Creating table " + TableNames.HIGHLIGHT_ELEMENT); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + + public static void dropTable() { + if (isTableCreated()) { + try (Connection c = DatabaseUtil.getConnection(); Statement ps = c.createStatement()) { + String sql = "DROP TABLE " + TableNames.BOOKMARKS; + System.out.println(">> Dropping table " + TableNames.HIGHLIGHT_ELEMENT); + ps.execute(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } + + static Connection conn; + static Statement ps; + static String sql; + + public static ResultSet selectWhere(String where) { + if (!isTableCreated()) + createTable(); + + try { + conn = DatabaseUtil.getConnection(); + ps = conn.createStatement(); + sql = "SELECT * FROM " + TableNames.BOOKMARKS + " WHERE " + where; + ResultSet resultSet = ps.executeQuery(sql); + return resultSet; + } catch (SQLException e) { + System.out.println("Line that threw error: " + sql); + e.printStackTrace(); + } + throw new IllegalStateException("No results for the select query. " + sql); + } + + public static void updateWhere(String columnName, String columnValue, String where) { + if (isTableCreated()) { + try { + conn = DatabaseUtil.getConnection(); + ps = conn.createStatement(); + sql = "UPDATE " + TableNames.BOOKMARKS + + " SET " + columnName + " = " + columnValue + + " WHERE " + where; + ps.executeUpdate(sql); + return; + } catch (SQLException e) { + System.out.println("Line that threw error: " + sql); + e.printStackTrace(); + } + } + throw new IllegalStateException("Table does not exist. Hence cannot fetch any rows from it."); + + } + + public static Map getBookmarks() { + Map result = new HashMap<>(); + String query = "SELECT * FROM " + TableNames.BOOKMARKS + " AS B " + + "JOIN " + TableNames.ELEMENT_TABLE + " AS E ON B.ELEMENT_ID = E.ID " + + "JOIN " + TableNames.CALL_TRACE_TABLE + " AS CT ON E.ID_ENTER_CALL_TRACE = CT.ID "; + + try (ResultSet rs = DatabaseUtil.select(query)) { + while (rs.next()) { + result.put(rs.getString("B.ID"), + new Bookmark( + rs.getString("B.ID"), + rs.getString("E.ID"), + rs.getString("CT.THREAD_ID"), + rs.getString("CT.MESSAGE"), + rs.getString("B.COLOR"), + rs.getDouble("E.BOUND_BOX_X_COORDINATE"), + rs.getDouble("E.BOUND_BOX_Y_COORDINATE") + )); + } + } catch (SQLException e) { + System.out.println("Query that threw exception: " + query); + e.printStackTrace(); + } + return result; + } + + public static void insertBookmark(Bookmark bookmark) { + + } + + +} diff --git a/src/main/java/com/application/db/DatabaseUtil.java b/src/main/java/com/application/db/DatabaseUtil.java index b1a0a61..07771f5 100644 --- a/src/main/java/com/application/db/DatabaseUtil.java +++ b/src/main/java/com/application/db/DatabaseUtil.java @@ -372,6 +372,7 @@ public static void resetDB() { EdgeDAOImpl.dropTable(); HighlightDAOImpl.dropTable(); FilesDAOImpl.dropTable(); + BookmarksDAOImpl.dropTable(); CallTraceDAOImpl.createTable(); MethodDefnDAOImpl.createTable(); diff --git a/src/main/java/com/application/db/TableNames.java b/src/main/java/com/application/db/TableNames.java index cf828bd..8e22127 100644 --- a/src/main/java/com/application/db/TableNames.java +++ b/src/main/java/com/application/db/TableNames.java @@ -7,5 +7,6 @@ public class TableNames { public static final String ELEMENT_TO_CHILD_TABLE = "ELEMENT_TO_CHILD"; public static final String EDGE_TABLE = "EDGE_ELEMENT"; public static final String HIGHLIGHT_ELEMENT = "HIGHLIGHT_ELEMENT"; + public static final String BOOKMARKS = "BOOKMARKS"; public static final String FILES_TABLE = "FILES"; } diff --git a/src/main/java/com/application/db/model/Bookmark.java b/src/main/java/com/application/db/model/Bookmark.java new file mode 100644 index 0000000..4d4df80 --- /dev/null +++ b/src/main/java/com/application/db/model/Bookmark.java @@ -0,0 +1,78 @@ +package com.application.db.model; + +public class Bookmark { + + private String id; + private String elementId; + private String threadId; + private String methodName; + private String color; + private double xCoordinate; + private double yCoordinate; + + public Bookmark(String id, String elementId, String threadId, String methodName, String color, double xCoordinate, double yCoordinate) { + this.id = id; + this.elementId = elementId; + this.threadId = threadId; + this.methodName = methodName; + this.color = color; + this.xCoordinate = xCoordinate; + this.yCoordinate = yCoordinate; + } + + public String getThreadId() { + return threadId; + } + + public void setThreadId(String threadId) { + this.threadId = threadId; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getElementId() { + return elementId; + } + + public void setElementId(String elementId) { + this.elementId = elementId; + } + + public String getMethodName() { + return methodName; + } + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } + + public double getxCoordinate() { + return xCoordinate; + } + + public void setxCoordinate(double xCoordinate) { + this.xCoordinate = xCoordinate; + } + + public double getyCoordinate() { + return yCoordinate; + } + + public void setyCoordinate(double yCoordinate) { + this.yCoordinate = yCoordinate; + } +} diff --git a/src/main/java/com/application/fxgraph/graph/EventHandlers.java b/src/main/java/com/application/fxgraph/graph/EventHandlers.java index 69a370b..c33f7b3 100644 --- a/src/main/java/com/application/fxgraph/graph/EventHandlers.java +++ b/src/main/java/com/application/fxgraph/graph/EventHandlers.java @@ -116,7 +116,7 @@ public void handle(MouseEvent event) { // CircleCell cell = (CircleCell) node; CircleCell cell = (CircleCell) node.getParent(); String timeStamp; - int methodId, processId, threadId; + int elementId, methodId, processId, threadId; String parameters, packageName = "", methodName = "", parameterTypes = "", eventType, lockObjectId; double xCord, yCord; @@ -138,6 +138,7 @@ public void handle(MouseEvent event) { // try (ResultSet callTraceRS = CallTraceDAOImpl.selectWhere("id = (Select id_enter_call_trace FROM " + TableNames.ELEMENT_TABLE + // " WHERE id = " + cell.getCellId() + ")")) { if (callTraceRS.next()) { + elementId = callTraceRS.getInt(TableNames.ELEMENT_TABLE + ".ID"); timeStamp = callTraceRS.getString("time_instant"); methodId = callTraceRS.getInt("method_id"); processId = callTraceRS.getInt("process_id"); @@ -235,8 +236,8 @@ public void handle(MouseEvent event) { try (ResultSet elementRS = ElementDAOImpl.selectWhere("id_enter_call_trace = " + ctId)) { // Expecting to see a single row. if (elementRS.next()) { - int elementId = elementRS.getInt("id"); - eleIdList.add(elementId); + int eId = elementRS.getInt("id"); + eleIdList.add(eId); } } } else if (eventType.equalsIgnoreCase("NOTIFY-ENTER")) { @@ -269,8 +270,8 @@ public void handle(MouseEvent event) { try (ResultSet elementRS = ElementDAOImpl.selectWhere("id_exit_call_trace = " + ctId)) { // Expecting to see a single row. if (elementRS.next()) { - int elementId = elementRS.getInt("id"); - eleIdList.add(elementId); + int eId = elementRS.getInt("id"); + eleIdList.add(eId); } } } @@ -302,8 +303,8 @@ public void handle(MouseEvent event) { try (ResultSet elementRS = ElementDAOImpl.selectWhere("id_exit_call_trace = " + id)) { // Can be more than a single row. while (elementRS.next()) { - int elementId = elementRS.getInt("id"); - eleIdList.add(elementId); + int eId = elementRS.getInt("id"); + eleIdList.add(eId); } } catch (SQLException e) { } @@ -314,13 +315,13 @@ public void handle(MouseEvent event) { List