public override Size Draw(DrawingContext drawingContext) { // format margins and padding for raster images var margin = GetMarginValue(DepictionGenerator.DefaultPixelMargin); var padding = GetPaddingValue(DefaultPaddingFactor * margin); var scale = model.GetScale(); var zoom = model.GetZoomFactor(); // row and col offsets for alignment var yOffset = new double[nRow + 1]; var xOffset = new double[nCol + 1]; var required = Dimensions.OfGrid(elements, yOffset, xOffset).Scale(scale * zoom); var total = CalcTotalDimensions(margin, padding, required, null); var fitting = CalcFitting(margin, padding, required, null); var visitor = WPFDrawVisitor.ForVectorGraphics(drawingContext); if (model.GetBackgroundColor() != Colors.Transparent) { visitor.Visit(new RectangleElement(new Point(0, 0), total.width, total.height, true, model.GetBackgroundColor()), Transform.Identity); } // compound the zoom, fitting and scaling into a single value var rescale = zoom * fitting * scale; // x,y base coordinates include the margin and centering (only if fitting to a size) var xBase = margin + (total.width - 2 * margin - (nCol - 1) * padding - (rescale * xOffset[nCol])) / 2; var yBase = margin + (total.height - 2 * margin - (nRow - 1) * padding - (rescale * yOffset[nRow])) / 2; for (int i = 0; i < elements.Count; i++) { var row = i / nCol; var col = i % nCol; // skip empty elements var bounds = this.elements[i]; if (bounds.IsEmpty()) { continue; } // calculate the 'view' bounds: // amount of padding depends on which row or column we are in. // the width/height of this col/row can be determined by the next offset var x = xBase + col * padding + rescale * xOffset[col]; var y = yBase + row * padding + rescale * yOffset[row]; var w = rescale * (xOffset[col + 1] - xOffset[col]); var h = rescale * (yOffset[row + 1] - yOffset[row]); Draw(visitor, zoom, bounds, new Rect(x, y, w, h)); } return(new Size(total.width, total.height)); }
public override Size Draw(DrawingContext g2) { // we use the AWT for vector graphics if though we're raster because // fractional strokes can be figured out by interpolation, without // when we shrink diagrams bonds can look too bold/chubby // format margins and padding for raster images var scale = model.GetScale(); var zoom = model.GetZoomFactor(); var margin = GetMarginValue(DepictionGenerator.DefaultPixelMargin); var padding = GetPaddingValue(DefaultPaddingFactor * margin); // work out the required space of the main and side components separately // will draw these in two passes (main then side) hence want different offsets for each var nSideCol = xOffsetSide.Length - 1; var nSideRow = yOffsetSide.Length - 1; var sideRequired = sideDim.Scale(scale * zoom); var mainRequired = mainDim.Scale(scale * zoom); var condRequired = condDim.Scale(scale * zoom); var titleRequired = new Dimensions(title.Width, title.Height).Scale(scale * zoom); var firstRowHeight = scale * zoom * yOffsets[1]; var total = CalcTotalDimensions(margin, padding, mainRequired, sideRequired, titleRequired, firstRowHeight, null); var fitting = CalcFitting(margin, padding, mainRequired, sideRequired, titleRequired, firstRowHeight, null); var visitor = WPFDrawVisitor.ForVectorGraphics(g2); if (model.GetBackgroundColor() != Colors.Transparent) { visitor.Visit(new RectangleElement(new Point(0, 0), total.width, total.height, true, model.GetBackgroundColor()), Transform.Identity); } // compound the zoom, fitting and scaling into a single value var rescale = zoom * fitting * scale; double mainCompOffset = 0; // shift product x-offset to make room for the arrow / side components mainCompOffset = fitting * sideRequired.height + nSideRow * padding - fitting * firstRowHeight / 2; for (int i = arrowIdx + 1; i < xOffsets.Length; i++) { xOffsets[i] += sideRequired.width * 1 / (scale * zoom); } // MAIN COMPONENTS DRAW // x,y base coordinates include the margin and centering (only if fitting to a size) var totalRequiredWidth = 2 * margin + Math.Max(0, nCol - 1) * padding + Math.Max(0, nSideCol - 1) * padding + (rescale * xOffsets[nCol]); var totalRequiredHeight = 2 * margin + Math.Max(0, nRow - 1) * padding + (!title.IsEmpty() ? padding : 0) + Math.Max(mainCompOffset, 0) + fitting * mainRequired.height + fitting * Math.Max(0, titleRequired.height); var xBase = margin + (total.width - totalRequiredWidth) / 2; var yBase = margin + Math.Max(mainCompOffset, 0) + (total.height - totalRequiredHeight) / 2; for (int i = 0; i < mainComp.Count; i++) { var row = i / nCol; var col = i % nCol; // calculate the 'view' bounds: // amount of padding depends on which row or column we are in. // the width/height of this col/row can be determined by the next offset var x = xBase + col * padding + rescale * xOffsets[col]; var y = yBase + row * padding + rescale * yOffsets[row]; var w = rescale * (xOffsets[col + 1] - xOffsets[col]); var h = rescale * (yOffsets[row + 1] - yOffsets[row]); // intercept arrow draw and make it as big as need if (i == arrowIdx) { w = rescale * (xOffsets[i + 1] - xOffsets[i]) + Math.Max(0, nSideCol - 1) * padding; Draw(visitor, 1, // no zoom since arrows is drawn as big as needed CreateArrow(w, arrowHeight * rescale), MakeRect(x, y, w, h)); continue; } // extra padding from the side components if (i > arrowIdx) { x += Math.Max(0, nSideCol - 1) * padding; } // skip empty elements Bounds bounds = this.mainComp[i]; if (bounds.IsEmpty()) { continue; } Draw(visitor, zoom, bounds, MakeRect(x, y, w, h)); } // RXN TITLE DRAW if (!title.IsEmpty()) { var y = yBase + nRow * padding + rescale * yOffsets[nRow]; var h = rescale * title.Height; Draw(visitor, zoom, title, MakeRect(0, y, total.width, h)); } // SIDE COMPONENTS DRAW xBase += arrowIdx * padding + rescale * xOffsets[arrowIdx]; yBase -= mainCompOffset; for (int i = 0; i < sideComps.Count; i++) { var row = i / nSideCol; var col = i % nSideCol; // calculate the 'view' bounds: // amount of padding depends on which row or column we are in. // the width/height of this col/row can be determined by the next offset var x = xBase + col * padding + rescale * xOffsetSide[col]; var y = yBase + row * padding + rescale * yOffsetSide[row]; var w = rescale * (xOffsetSide[col + 1] - xOffsetSide[col]); var h = rescale * (yOffsetSide[row + 1] - yOffsetSide[row]); Draw(visitor, zoom, sideComps[i], MakeRect(x, y, w, h)); } // CONDITIONS DRAW if (!conditions.IsEmpty()) { yBase += mainCompOffset; // back to top yBase += (fitting * mainRequired.height) / 2; // now on center line (arrow) yBase += arrowHeight; // now just bellow Draw(visitor, zoom, conditions, MakeRect(xBase, yBase, fitting * condRequired.width, fitting * condRequired.height)); } // reset shared xOffsets for (int i = arrowIdx + 1; i < xOffsets.Length; i++) { xOffsets[i] -= sideRequired.width * 1 / (scale * zoom); } return(new Size(total.width, total.height)); }