/** * This method is called when the user has created manually an edge in the graph, by dragging a * link between two spot cells. It checks whether the matching edge in the model exists, and tune * what should be done accordingly. * * @param cell the mxCell of the edge that has been manually created. */ protected void addEdgeManually(mxCell cell) { if (cell.isEdge()) { final mxIGraphModel graphModel = graph.getModel(); cell.setValue("New"); model.beginUpdate(); graphModel.beginUpdate(); try { Spot source = graph.getSpotFor(cell.getSource()); Spot target = graph.getSpotFor(cell.getTarget()); if (DEBUG) { System.out.println( "[TrackScheme] #addEdgeManually: edge is between 2 spots belonging to the same frame. Removing it."); System.out.println( "[TrackScheme] #addEdgeManually: adding edge between source " + source + " at frame " + source.getFeature(Spot.FRAME).intValue() + " and target " + target + " at frame " + target.getFeature(Spot.FRAME).intValue()); } if (Spot.frameComparator.compare(source, target) == 0) { // Prevent adding edges between spots that belong to the same frame if (DEBUG) { System.out.println( "[TrackScheme] addEdgeManually: edge is between 2 spots belonging to the same frame. Removing it."); } graph.removeCells(new Object[] {cell}); } else { // We can add it to the model // Put them right in order: since we use a oriented graph, // we want the source spot to precede in time. if (Spot.frameComparator.compare(source, target) > 0) { if (DEBUG) { System.out.println( "[TrackScheme] #addEdgeManually: Source " + source + " succeed target " + target + ". Inverting edge direction."); } Spot tmp = source; source = target; target = tmp; } // We add a new jGraphT edge to the underlying model, if it does not exist yet. DefaultWeightedEdge edge = model.getTrackModel().getEdge(source, target); if (null == edge) { edge = model.addEdge(source, target, -1); if (DEBUG) { System.out.println( "[TrackScheme] #addEdgeManually: Creating new edge: " + edge + "."); } } else { // Ah. There was an existing edge in the model we were trying to re-add there, from the // graph. // We remove the graph edge we have added, if (DEBUG) { System.out.println("[TrackScheme] #addEdgeManually: Edge pre-existed. Retrieve it."); } graph.removeCells(new Object[] {cell}); // And re-create a graph edge from the model edge. cell = graph.addJGraphTEdge(edge); cell.setValue(String.format("%.1f", model.getTrackModel().getEdgeWeight(edge))); // We also need now to check if the edge belonged to a visible track. If not, // we make it visible. int ID = model.getTrackModel().trackIDOf(edge); // This will work, because track indices will be reprocessed only after the // graphModel.endUpdate() // reaches 0. So now, it's like we are dealing with the track indices priori to // modification. if (model.getTrackModel().isVisible(ID)) { if (DEBUG) { System.out.println( "[TrackScheme] #addEdgeManually: Track was visible. Do nothing."); } } else { if (DEBUG) { System.out.println( "[TrackScheme] #addEdgeManually: Track was invisible. Make it visible."); } importTrack(ID); } } graph.mapEdgeToCell(edge, cell); } } finally { graphModel.endUpdate(); model.endUpdate(); selectionModel.clearEdgeSelection(); } } }
/** * Create links between all the spots currently in the {@link Model} selection. We update * simultaneously the {@link Model} and the {@link JGraphXAdapter}. */ public void linkSpots() { // Sort spots by time TreeMap<Integer, Spot> spotsInTime = new TreeMap<Integer, Spot>(); for (Spot spot : selectionModel.getSpotSelection()) { spotsInTime.put(spot.getFeature(Spot.FRAME).intValue(), spot); } // Find adequate column int targetColumn = getUnlaidSpotColumn(); // Then link them in this order model.beginUpdate(); graph.getModel().beginUpdate(); try { Iterator<Integer> it = spotsInTime.keySet().iterator(); Integer previousTime = it.next(); Spot previousSpot = spotsInTime.get(previousTime); // If this spot belong to an invisible track, we make it visible Integer ID = model.getTrackModel().trackIDOf(previousSpot); if (ID != null && !model.getTrackModel().isVisible(ID)) { importTrack(ID); } while (it.hasNext()) { Integer currentTime = it.next(); Spot currentSpot = spotsInTime.get(currentTime); // If this spot belong to an invisible track, we make it visible ID = model.getTrackModel().trackIDOf(currentSpot); if (ID != null && !model.getTrackModel().isVisible(ID)) { importTrack(ID); } // Check that the cells matching the 2 spots exist in the graph mxICell currentCell = graph.getCellFor(currentSpot); if (null == currentCell) { currentCell = insertSpotInGraph(currentSpot, targetColumn); if (DEBUG) { System.out.println( "[TrackScheme] linkSpots: creating cell " + currentCell + " for spot " + currentSpot); } } mxICell previousCell = graph.getCellFor(previousSpot); if (null == previousCell) { int frame = previousSpot.getFeature(Spot.FRAME).intValue(); int column = Math.max(targetColumn, getNextFreeColumn(frame)); rowLengths.put(frame, column); previousCell = insertSpotInGraph(previousSpot, column); if (DEBUG) { System.out.println( "[TrackScheme] linkSpots: creating cell " + previousCell + " for spot " + previousSpot); } } // Check if the model does not have already a edge for these 2 spots (that is // the case if the 2 spot are in an invisible track, which track scheme does not // know of). DefaultWeightedEdge edge = model.getTrackModel().getEdge(previousSpot, currentSpot); if (null == edge) { // We create a new edge between 2 spots, and pair it with a new cell edge. edge = model.addEdge(previousSpot, currentSpot, -1); mxCell cell = (mxCell) graph.addJGraphTEdge(edge); cell.setValue("New"); } else { // We retrieve the edge, and pair it with a new cell edge. mxCell cell = (mxCell) graph.addJGraphTEdge(edge); cell.setValue(String.format("%.1f", model.getTrackModel().getEdgeWeight(edge))); // Also, if the existing edge belonged to an existing invisible track, we make it visible. ID = model.getTrackModel().trackIDOf(edge); if (ID != null && !model.getTrackModel().isVisible(ID)) { importTrack(ID); } } previousSpot = currentSpot; } } finally { graph.getModel().endUpdate(); model.endUpdate(); } }