private void layoutElements() { // System.out.println(); for (String id : this.orderedIds) { // System.out.println(id); BPMNElement currentElement = (BPMNElement) this.diagram.getElement(id); List<LayoutingElement> precedingElements = currentElement.getPrecedingElements(); GridContext context = getContextByElement(currentElement); Cell<BPMNElement> cellOfElement = null; cellOfElement = placeElement(currentElement, precedingElements, context); boolean comesFromOtherGrid = precedingElements.size() == 1 && precedingElements.get(0).getParent() != currentElement.getParent(); if (!currentElement.isJoin() && !comesFromOtherGrid && cellOfElement.getPrevCell() != null) { // there is an edge hitting us left, so lets forbid // interleaving to use the left cell, if it's empty cellOfElement.getPrevCell().setPackable(false); } if (currentElement.isSplit()) { prelayoutSuccessors(currentElement, context, cellOfElement); } if (BPMNType.isAActivity(currentElement.getType())) { // search for attached events for (LayoutingElement e : currentElement.getOutgoingLinks()) { if (BPMNType.isACatchingIntermediateEvent(e.getType())) { context.grid.setCellOfItem((BPMNElement) e, cellOfElement); } } } } }
private void prepareLanes(BPMNElement lane, int level) { maxLaneDepth = Math.max(maxLaneDepth, level); List<BPMNElement> childs = new ArrayList<BPMNElement>(); BPMNElement aChild = null; for (LayoutingElement c : diagram.getChildElementsOf(lane)) { BPMNElement child = (BPMNElement) c; if (BPMNType.isASwimlane(child.getType())) { prepareLanes(child, level + 1); childs.add(child); } aChild = child; } // Create Grid for lane (= // aChild.getParent()) if (aChild != null) { getContextByElement(aChild); } else { // create empty grid for empty lanes // to prevent nullpointer-exception GridContext result = new GridContext(); result.grid = new Grid<BPMNElement>(); result.startCell = result.grid.getFirstRow().getFirstCell(); superGrid.add(result.grid); parent2Context.put(lane, result); } lane2LaneChilds.put(lane, childs); }
/** * @param lane * @param absY * @param level */ private void correctLaneElements(BPMNElement lane, double absY, int level) { List<BPMNElement> childs = lane2LaneChilds.get(lane); double height = 0; for (BPMNElement child : childs) { correctLaneElements(child, absY + height, level + 1); height += child.getGeometry().getHeight(); } int xTrans = level * -LANE_HEAD_WIDTH; for (LayoutingElement content : diagram.getChildElementsOf(lane)) { if (!BPMNType.isASwimlane(content.getType())) { LayoutingBounds geom = content.getGeometry(); content.setGeometry( new LayoutingBoundsImpl( geom.getX() + xTrans, geom.getY() - absY, geom.getWidth(), geom.getHeight())); ((BPMNElement) content).updateDataModel(); } } }
/** * @param currentElement * @param context * @param cellOfElement */ private void prelayoutSuccessors( BPMNElement currentElement, GridContext context, Cell<BPMNElement> cellOfElement) { // preLayout following Elements Cell<BPMNElement> baseCell = cellOfElement.after(); Cell<BPMNElement> topCell = baseCell; List<LayoutingElement> followingElements = currentElement.getFollowingElements(); if (BPMNType.isAActivity(currentElement.getType())) { // special case for docked events List<BPMNElement> dockedEventFollowers = new LinkedList<BPMNElement>(); for (LayoutingElement el : currentElement.getOutgoingLinks()) { BPMNElement element = (BPMNElement) el; if (element.isADockedIntermediateEvent()) { for (LayoutingElement follower : element.getFollowingElements()) { dockedEventFollowers.add((BPMNElement) follower); } } } // to avoid crossing edges if there is more than one // docked event Collections.reverse(dockedEventFollowers); // put them under the task Cell<BPMNElement> insertCell = baseCell; for (BPMNElement dockedEventFollower : dockedEventFollowers) { Cell<BPMNElement> oldCell = context.grid.getCellOfItem(dockedEventFollower); if (oldCell != null) { if (oldCell.getValue() == dockedEventFollower) { continue; // Bug-Workaround: Don't prelayout // layouted elements; } } insertCell.getParent().insertRowBeneath(); insertCell = insertCell.beneath(); context.grid.setCellOfItem(dockedEventFollower, insertCell); // prelayout } // remove them from the following processing followingElements.removeAll(dockedEventFollowers); } // heuristic for text- & data-objects: put them to the top List<BPMNElement> textAnnotations = new LinkedList<BPMNElement>(); List<BPMNElement> dataObjects = new LinkedList<BPMNElement>(); for (LayoutingElement el : followingElements) { BPMNElement e = (BPMNElement) el; if (e.getType().equals(BPMNType.TextAnnotation)) { textAnnotations.add(e); } else if (e.getType().equals(BPMNType.DataObject)) { dataObjects.add(e); } } followingElements.removeAll(textAnnotations); followingElements.removeAll(dataObjects); // add them at the front followingElements.addAll(0, dataObjects); followingElements.addAll(0, textAnnotations); // heuristic for direct connection to join BPMNElement directJoin = null; for (LayoutingElement possibleJoin : followingElements) { if (possibleJoin.isJoin()) { directJoin = (BPMNElement) possibleJoin; } } if (directJoin != null) { // put in the middle followingElements.remove(directJoin); int position = (followingElements.size() / 2); followingElements.add(position, directJoin); } // normal preLayout following Elements int follow = 0; for (LayoutingElement newElem : followingElements) { if (newElem.getParent() == currentElement.getParent()) { follow++; } } for (int i = 0; i < follow / 2; i++) { topCell.getParent().insertRowAbove(); baseCell.getParent().insertRowBeneath(); topCell = topCell.above(); } for (LayoutingElement newElem : followingElements) { if (newElem.getParent() != currentElement.getParent()) { continue; } context.grid.setCellOfItem((BPMNElement) newElem, topCell); // prelayout topCell = topCell.beneath(); if (topCell == baseCell && follow % 2 == 0) { // skip baseCell if an even amount of elements is // following topCell = topCell.beneath(); } } }