void PortionDrawer::drawNodes(DiagramDrawer &drawer) { drawer.groupShapes(true, Color(0,0,0), Color(245,245,255)); for(size_t i=0; i<mNodePositions.size(); i++) { if(mGraph->getNodes()[i].getNodeType() == PNT_Attribute) { drawer.drawRect(getNodeRect(drawer, i)); } else { drawer.drawEllipse(getNodeRect(drawer, i)); } } drawer.groupShapes(false, 0, 0); drawer.groupShapes(true, Color(0,0,255), Color(245,245,255)); for(size_t i=0; i<mNodePositions.size(); i++) { if(mGraph->getNodes()[i].getNodeType() == PNT_NonMemberVariable) { drawer.drawRect(getNodeRect(drawer, i)); } } drawer.groupShapes(false, 0, 0); }
GraphSize OperationDrawer::drawClass(DiagramDrawer &drawer, const OperationClass &node, const OperationDrawOptions & /*options*/, bool draw) { GraphPoint startpos = node.getPosition(); const ModelType *type = node.getType(); OovStringRef const typeName = type->getName(); int rectx = 0; int recty = 0; const ModelClassifier *classifier = type->getClass(); if(classifier) { if(draw) { drawer.groupText(true, false); } OovStringVec strs; std::vector<GraphPoint> positions; strs.push_back(typeName); splitStrings(strs, 30, 40); for(auto const &str : strs) { recty += mCharHeight + (mPad * 2); positions.push_back(GraphPoint(startpos.x+mPad, startpos.y + recty - mPad)); int curx = static_cast<int>(drawer.getTextExtentWidth(str)) + mPad*2; if(curx > rectx) rectx = curx; } if(draw) { drawer.groupShapes(true, Color(0,0,0), Color(245,245,255)); drawer.drawRect(GraphRect(startpos.x, startpos.y, rectx, recty)); drawer.groupShapes(false, Color(0,0,0), Color(245,245,255)); for(size_t i=0; i<strs.size(); i++) { drawer.drawText(positions[i], strs[i]); } drawer.groupText(false, false); } } return GraphSize(rectx, recty); }
GraphSize OperationDrawer::drawOperationNoText(DiagramDrawer &drawer, GraphPoint pos, OperationDefinition &operDef, const OperationGraph &graph, const OperationDrawOptions &options, std::set<const OperationDefinition*> &drawnOperations, std::vector<DrawString> &drawStrings, bool draw, int callDepth) { GraphPoint startpos = pos; // Add space between bottom of class and operation name int starty = startpos.y+(mPad*2); int y=starty; size_t sourceIndex = operDef.getOperClassIndex(); int arrowLen = mCharHeight * 7 / 10; std::vector<int> condStartPosY; drawnOperations.insert(&operDef); const OperationClass &cls = graph.getClass(sourceIndex); if(callDepth == 0) { // Reinit all polys to initial conditions. mLifelinePolygons.clear(); mLifelinePolygons.resize(graph.getClasses().size()); } BlockPolygon &poly = mLifelinePolygons[sourceIndex]; poly.setup(cls.getLifelinePosX(), mPad); if(!graph.isOperCalled(operDef)) { // Show starting operation operDef.setRect(GraphPoint(cls.getPosition().x, y), GraphSize(mCharHeight*50, mCharHeight+mPad)); y += mCharHeight; drawStrings.push_back(DrawString(GraphPoint( cls.getPosition().x, y), operDef.getName())); // Add space between operation name and called operations. y += (mPad * 2); int lineY = y + mPad*2; if(draw) { drawCall(drawer, GraphPoint(cls.getPosition().x, lineY), GraphPoint(cls.getLifelinePosX(), lineY), operDef.isConst(), arrowLen); } } for(const auto &stmt : operDef.getStatements()) { int condOffset = poly.getDepth() * mPad; switch(stmt->getStatementType()) { case ST_Call: { OperationCall *call = stmt->getCall(); size_t targetIndex = call->getOperClassIndex(); int lineY = y + mCharHeight + mPad*2; int sourcex = cls.getLifelinePosX(); sourcex += condOffset; const OperationClass &targetCls = graph.getClass(targetIndex); int targetx = targetCls.getLifelinePosX(); if(targetIndex == NO_INDEX) { // Handle [else] // int len = mCharHeight*3; // mDrawer.drawLine(GraphPoint(sourcex, lineY), // GraphPoint(sourcex+len, lineY), call->isConst()); } else if(targetIndex != sourceIndex) { if(draw) { drawCall(drawer, GraphPoint(sourcex, lineY), GraphPoint(targetx, lineY), call->isConst(), arrowLen); } } else { // Draw line back to same class int len = mCharHeight*3; int height = 3; if(draw) { drawer.drawLine(GraphPoint(sourcex, lineY), GraphPoint(sourcex+len, lineY), call->isConst()); drawer.drawLine(GraphPoint(sourcex+len, lineY), GraphPoint(sourcex+len, lineY+height)); drawer.drawLine(GraphPoint(sourcex, lineY+height), GraphPoint(sourcex+len, lineY+height), call->isConst()); } y += height; } int textX = (sourceIndex < targetIndex) ? cls.getLifelinePosX() : targetCls.getLifelinePosX(); GraphPoint callPos(textX+condOffset+mPad, y+mCharHeight); drawStrings.push_back(DrawString(callPos, call->getName())); call->setRect(GraphPoint(callPos.x, callPos.y-mCharHeight), GraphSize(mCharHeight*50, mCharHeight+mPad)); y += mCharHeight*2; // Draw child definition. OperationDefinition *childDef = graph.getOperDefinition(*call); if(childDef) { // poly.startChildBlock(condDepth, y); if(drawnOperations.find(childDef) == drawnOperations.end()) { poly.incDepth(y); GraphSize childSize = drawOperationNoText(drawer, GraphPoint(pos.x, y), *childDef, graph, options, drawnOperations, drawStrings, draw, callDepth+1); y += childSize.y + mPad * 2; poly.decDepth(y); } else { // This draws a rectangle to signify that it is defined // elsewhere in the diagram. GraphRect rect(targetx + mPad*2, callPos.y + mPad*2, mCharHeight+mPad, mCharHeight+mPad); if(draw) { drawer.drawRect(rect); } y += mCharHeight+mPad; } // poly.endChildBlock(condDepth, y); } } break; case ST_VarRef: { OperationVarRef *ref = stmt->getVarRef(); size_t targetIndex = ref->getOperClassIndex(); int lineY = y + mCharHeight + mPad*2; int sourcex = cls.getLifelinePosX(); sourcex += condOffset; const OperationClass &targetCls = graph.getClass(targetIndex); int targetx = targetCls.getLifelinePosX(); if(targetIndex == NO_INDEX) { int len = mCharHeight*3; if(draw) { drawer.drawLine(GraphPoint(sourcex, lineY), GraphPoint(sourcex+len, lineY), ref->isConst()); } } else if(targetIndex != sourceIndex) { if(draw) { drawCall(drawer, GraphPoint(sourcex, lineY), GraphPoint(targetx, lineY), ref->isConst(), arrowLen); } } else { // Draw line back to same class int len = mCharHeight*3; int height = 3; if(draw) { drawer.drawLine(GraphPoint(sourcex, lineY), GraphPoint(sourcex+len, lineY), ref->isConst()); drawer.drawLine(GraphPoint(sourcex+len, lineY), GraphPoint(sourcex+len, lineY+height)); drawer.drawLine(GraphPoint(sourcex, lineY+height), GraphPoint(sourcex+len, lineY+height), ref->isConst()); } y += height; } int textX = (sourceIndex < targetIndex) ? cls.getLifelinePosX() : targetCls.getLifelinePosX(); GraphPoint callPos(textX+condOffset+mPad, y+mCharHeight); if(draw) { drawStrings.push_back(DrawString(callPos, ref->getName())); } ref->setRect(GraphPoint(callPos.x, callPos.y-mCharHeight), GraphSize(mCharHeight*50, mCharHeight+mPad)); y += mCharHeight*2; } break; case ST_OpenNest: { GraphPoint lifePos(cls.getLifelinePosX()+condOffset+ mPad, y+mCharHeight); const OperationNestStart *cond = stmt->getNestStart(); if(draw) { drawStrings.push_back(DrawString(lifePos, cond->getExpr())); } condStartPosY.push_back(y); y += mCharHeight*2; poly.incDepth(y); } break; case ST_CloseNest: { poly.decDepth(y); } break; } } if(callDepth == 0) { for(auto &poly : mLifelinePolygons) { poly.finishBlock(); if(draw) { drawer.drawPoly(poly, Color(245,245,255)); } } } return GraphSize(0, y - startpos.y); }