/// <summary> /// Generates a node for the state label /// </summary> /// <param name="label"></param> /// <param name="pos_X"></param> /// <param name="pos_Y"></param> /// <returns></returns> public void AddSubgraphNode( GraphViz.Graph graph, DFBState dfbState, DFBStateFrame dfbStateFrame, double?pos_X, double?pos_Y) { // State prior to current frame gives the beginning values for ACU when label was entered DFBStateFrame dfbStateFrameBegValues = dfbState.StatePrior(dfbStateFrame.Cycle); var shapeName = dfbStateFrame.CodeStateCycle.UniqueName; var node = CreateNode(dfbStateFrame, pos_X, pos_Y, dfbStateFrameBegValues, shapeName); graph.Subgraphs .Where(x => x.Tag.ToString() == dfbStateFrame.CodeStateCycle.Label) .FirstOrDefault() .Nodes.Add(node); // Add edge for ACU change from one label call to the next AddEdges(graph, dfbState, dfbStateFrame, dfbStateFrameBegValues, shapeName); }
/// <summary> /// Adds edge connections between labels, and for the change in ACU address between calls to the same label /// </summary> /// <param name="graph"></param> /// <param name="dfbState"></param> /// <param name="dfbStateFrame"></param> /// <param name="dfbStateFrameBegValues"></param> /// <param name="shapeName"></param> private void AddEdges( GraphViz.Graph graph, DFBState dfbState, DFBStateFrame dfbStateFrame, DFBStateFrame dfbStateFrameBegValues, string shapeName) { // State prior to this label's last execution gives the prior beginning values for ACU when label was entered DFBStateFrame dfbStateFramePriorBegValues = null; var statePriorSameLabel = dfbState.StatePriorSameLabel(dfbStateFrame.Cycle); if (statePriorSameLabel != null) { var sameLabelPriorCycleNbr = statePriorSameLabel.Cycle; dfbStateFramePriorBegValues = dfbState.StatePrior(sameLabelPriorCycleNbr); } // State following current frame gives connection target var dfbStateFrameNext = dfbState.StateNext(dfbStateFrame.Cycle); if (dfbStateFrameNext == null) { return; } var shapeNameNext = dfbStateFrameNext.CodeStateCycle.UniqueName; // label var labels = new List <string>(); var state = dfbStateFrame.CodeStateCycle.CodeState.State; var fallThrough = true; if (state.AcuAEQ == 1 && dfbStateFrame.JumpConditions.AcuAEQ) { labels.Add("AcuAEQ"); fallThrough = false; } if (state.AcuBEQ == 1 && dfbStateFrame.JumpConditions.AcuBEQ) { labels.Add("AcuBEQ"); fallThrough = false; } if (state.DpEQ == 1 && dfbStateFrame.JumpConditions.DpEQ) { labels.Add("DpEQ"); fallThrough = false; } if (state.DpSign == 1 && dfbStateFrame.JumpConditions.DpSign) { labels.Add("DpSign"); fallThrough = false; } if (state.DpThresh == 1 && dfbStateFrame.JumpConditions.DpThresh) { labels.Add("DpThresh"); fallThrough = false; } if (state.In1 == 1 && dfbStateFrame.JumpConditions.In1) { labels.Add("In1"); fallThrough = false; } if (state.In2 == 1 && dfbStateFrame.JumpConditions.In2) { labels.Add("In2"); fallThrough = false; } if (state.Sat == 1 && dfbStateFrame.JumpConditions.Sat) { labels.Add("Sat"); fallThrough = false; } if (fallThrough) { labels.Add("false"); } var edge = new GraphViz.Edge(); graph.Edges.Add(edge); edge.Connections.AddRange(new string[] { shapeName, shapeNameNext }); edge.EdgeAttributes.style = GraphViz.Style.Edge.solid; edge.EdgeAttributes.color = KnownColor.ForestGreen; edge.EdgeAttributes.arrowhead = GraphViz.ArrowType.normal; edge.EdgeAttributes.arrowtail = GraphViz.ArrowType.inv; edge.EdgeAttributes.label = new GraphViz.escString(String.Join(" ", labels)); // Add connection for ACU delta from prior call of same label if (dfbStateFramePriorBegValues != null && statePriorSameLabel != null) { // Determine ACU reg address changes from last time this label was executed var shapeNamePriorCall = statePriorSameLabel.CodeStateCycle.UniqueName; Func <int, int, string> sign = delegate(int curr, int prior) { if (prior < curr) { return("+"); } else { return(""); } }; var sb = new StringBuilder(); var acuABeg = (int)dfbStateFrameBegValues.ACU_A.Reg_reg.Value; var acuABegPrior = (int)dfbStateFramePriorBegValues.ACU_A.Reg_reg.Value; var acuABegChange = acuABeg - acuABegPrior; if (acuABegChange != 0) { sb.AppendFormat("\\nACU_A Chg: {0}{1}", sign(acuABeg, acuABegPrior), acuABegChange.ToString()); } var acuBBeg = (int)dfbStateFrameBegValues.ACU_B.Reg_reg.Value; var acuBBegPrior = (int)dfbStateFramePriorBegValues.ACU_B.Reg_reg.Value; var acuBBegChange = acuBBeg - acuBBegPrior; if (acuBBegChange != 0) { if (acuABegChange != 0) { sb.AppendLine(""); } sb.AppendFormat("\\nACU_B Chg: {0}{1}", sign(acuBBeg, acuBBegPrior), acuBBegChange.ToString()); } edge = new GraphViz.Edge(); graph.Edges.Add(edge); edge.Connections.AddRange(new string[] { shapeNamePriorCall, shapeName }); edge.EdgeAttributes.color = KnownColor.Gray; edge.EdgeAttributes.weight = 0.5f; edge.EdgeAttributes.style = GraphViz.Style.Edge.dashed; edge.EdgeAttributes.arrowhead = GraphViz.ArrowType.none; edge.EdgeAttributes.arrowtail = GraphViz.ArrowType.none; edge.EdgeAttributes.headlabel = new GraphViz.escString(sb.ToString()); edge.EdgeAttributes.labeldistance = 0.6f; } }
/// <summary> /// Creates a node for the label call /// </summary> /// <param name="dfbStateFrame"></param> /// <param name="pos_X"></param> /// <param name="pos_Y"></param> /// <param name="dfbStateFrameBegValues"></param> /// <param name="shapeName"></param> /// <returns></returns> private GraphViz.Node CreateNode( DFBStateFrame dfbStateFrame, double?pos_X, double? pos_Y, DFBStateFrame dfbStateFrameBegValues, string shapeName) { const int COL1MINWIDTH = 30; const int COL2MINWIDTH = 30; const int COL3MINWIDTH = 30; // Add Node var node = new GraphViz.Node(shapeName) { Tag = dfbStateFrame }; node.NodeAttributes.shape = GraphViz.Shape.none; // tootip doesn't work in webbrowser control - it bases tooltips off of title attribute //node.NodeAttributes.tooltip = new GraphViz.escString(dfbStateFrame.CodeStateCycle.Instruction.InstructionText); if (pos_X.HasValue && pos_Y.HasValue) { node.NodeAttributes.pos = new GraphViz.Point { InputOnly = true, X = pos_X.Value, Y = pos_Y.Value }; } var table = new HtmlTable { Border = 0 }; table.Attributes.Add("CELLBORDER", "1"); table.CellSpacing = 0; // Header var row = new HtmlTableRow(); string label = null; if (dfbStateFrame.CodeStateCycle.GroupName.Length > callDiagramMaxLabelChars) { label = dfbStateFrame.CodeStateCycle.GroupName.Substring(0, callDiagramMaxLabelChars - 3) + "..."; } else { label = dfbStateFrame.CodeStateCycle.GroupName; } AddHeader1Cell(row, null, 3, label); table.Rows.Add(row); // Details row = new HtmlTableRow(); AddDetailCell(row, COL1MINWIDTH, null, null, "Cycle:", false, true); AddDetailCell(row, COL2MINWIDTH, null, 2, dfbStateFrame.Cycle.ToString()); table.Rows.Add(row); row = new HtmlTableRow(); AddDetailCell(row, COL1MINWIDTH, null, null, "ACU", false, true); AddDetailCell(row, COL2MINWIDTH, null, null, "Beg"); AddDetailCell(row, COL3MINWIDTH, null, null, "End"); table.Rows.Add(row); row = new HtmlTableRow(); AddDetailCell(row, COL1MINWIDTH, null, null, "A.reg", false, true); AddDetailCell(row, COL3MINWIDTH, null, null, dfbStateFrameBegValues != null ? dfbStateFrameBegValues.ACU_A.Reg_reg.FormattedValue : ""); AddDetailCell(row, COL2MINWIDTH, null, null, dfbStateFrame.ACU_A.Reg_reg.FormattedValue); table.Rows.Add(row); row = new HtmlTableRow(); AddDetailCell(row, COL1MINWIDTH, null, null, "B.reg", false, true); AddDetailCell(row, COL3MINWIDTH, null, null, dfbStateFrameBegValues != null ? dfbStateFrameBegValues.ACU_B.Reg_reg.FormattedValue : ""); AddDetailCell(row, COL2MINWIDTH, null, null, dfbStateFrame.ACU_B.Reg_reg.FormattedValue); table.Rows.Add(row); // Add table as label node.NodeAttributes.label = table.ToGraphvizLabelFormat(); return(node); }