// Place a punch pattern in the dot grid. void SetPunchPattern(PunchPattern punch) { if (punch == null) { dotGrid.DotsAcross = PunchcardAppearance.gridSize; dotGrid.DotsDown = PunchcardAppearance.gridSize; dotGrid.Clear(); } else { dotGrid.DotsAcross = punch.size; dotGrid.DotsDown = punch.size; dotGrid.SetAllDots(punch.dots); } }
// Read the current punch pattern out of the dotGrid PunchPattern GetPunchPattern() { PunchPattern punch = new PunchPattern(); punch.size = dotGrid.DotsAcross; punch.dots = dotGrid.GetAllDots(); if (punch.IsEmpty) return null; else return punch; }
public object Clone() { PunchPattern n = new PunchPattern(); n.size = size; n.dots = (bool[,]) dots.Clone(); return n; }
public override void ReadAttributesAndContent(XmlInput xmlinput) { string kindText = xmlinput.GetAttributeString("kind"); switch (kindText) { case "normal": kind = ControlPointKind.Normal; break; case "start": kind = ControlPointKind.Start; break; case "finish": kind = ControlPointKind.Finish; break; case "crossing-point": kind = ControlPointKind.CrossingPoint; break; case "map-exchange": kind = ControlPointKind.MapExchange; break; default: xmlinput.BadXml("Invalid control point kind '{0}'", kindText); break; } if (kind == ControlPointKind.Normal || kind == ControlPointKind.Start || kind == ControlPointKind.MapExchange) symbolIds = new string[6]; else if (kind == ControlPointKind.Finish || kind == ControlPointKind.CrossingPoint) symbolIds = new string[1]; code = null; descriptionText = null; columnFText = null; // Old file format had a single gaps attribute for all scales. Put this in the dictionary with scale of 0, then update after load is finished. string gapText = xmlinput.GetAttributeString("gaps", ""); if (gapText != "") { uint gapValue = Convert.ToUInt32(gapText, 2); if (gaps == null) gaps = new Dictionary<int, CircleGap[]>(); gaps[0] = CircleGap.ComputeCircleGaps(gapValue); } string codeAngle = xmlinput.GetAttributeString("all-controls-code-angle", ""); if (codeAngle != "") { customCodeLocation = true; codeLocationAngle = XmlConvert.ToSingle(codeAngle); } if (kind == ControlPointKind.CrossingPoint) orientation = xmlinput.GetAttributeFloat("orientation"); bool first = true; while (xmlinput.FindSubElement(first, "code", "location", "description", "description-text", "gaps", "circle-gaps", "punch-pattern", "description-text-line")) { switch (xmlinput.Name) { case "code": if (kind != ControlPointKind.Normal) xmlinput.BadXml("Only normal control points can have a code"); code = xmlinput.GetContentString(); break; case "location": float x = xmlinput.GetAttributeFloat("x"); float y = xmlinput.GetAttributeFloat("y"); location = new PointF(x, y); xmlinput.Skip(); break; case "punch-pattern": punches = new PunchPattern(); punches.size = xmlinput.GetAttributeInt("size"); punches.dots = new bool[punches.size, punches.size]; string punchPattern = xmlinput.GetContentString(); int index = 0; for (int i = 0; i < punches.size; ++i) for (int j = 0; j < punches.size; ++j) { char c; do { if (index >= punchPattern.Length) { xmlinput.BadXml("invalid punch pattern"); goto QUITPUNCHPATTERN; } c = punchPattern[index++]; } while (c != '0' && c != '1'); punches.dots[i, j] = (c == '1'); } QUITPUNCHPATTERN: break; case "gaps": { int scale = xmlinput.GetAttributeInt("scale", 0); gapText = xmlinput.GetContentString().Trim(); if (gapText != "") { if (gaps == null) gaps = new Dictionary<int, CircleGap[]>(); if (gapText.Contains(":")) { // For 2.0 beta 1 compatibility only. gaps[scale] = CircleGap.DecodeGaps(gapText); } else if (!gaps.ContainsKey(scale)) { // Only use the old-style if the new-style wasn't found. uint gapValue = Convert.ToUInt32(gapText, 2); gaps[scale] = CircleGap.ComputeCircleGaps(gapValue); } } break; } case "circle-gaps": { int scale = xmlinput.GetAttributeInt("scale", 0); gapText = xmlinput.GetContentString().Trim(); if (gapText != "") { if (gaps == null) gaps = new Dictionary<int, CircleGap[]>(); if (gapText.Contains(":")) { // This is the new-style; overrides old style if both present. gaps[scale] = CircleGap.DecodeGaps(gapText); } } break; } case "description-text": descriptionText = xmlinput.GetContentString(); break; case "description-text-line": xmlinput.CheckElement("description-text-line"); string locationText = xmlinput.GetAttributeString("location"); if (locationText == "before") descTextBefore = xmlinput.GetContentString(); else if (locationText == "after") descTextAfter = xmlinput.GetContentString(); else { xmlinput.BadXml("location attribute on description-text-line must be \"before\" or \"after\""); xmlinput.Skip(); } break; case "description": string box = xmlinput.GetAttributeString("box"); string symbolId = xmlinput.GetAttributeString("iof-2004-ref", null); string text = xmlinput.GetContentString(); switch (box) { case "all": symbolIds[0] = symbolId; break; case "C": symbolIds[0] = symbolId; break; case "D": symbolIds[1] = symbolId; break; case "E": symbolIds[2] = symbolId; break; case "F": symbolIds[3] = symbolId; break; case "G": symbolIds[4] = symbolId; break; case "H": symbolIds[5] = symbolId; break; default: xmlinput.BadXml("Invalid box type '{0}'", box); break; } if (box == "F" && !string.IsNullOrEmpty(text)) columnFText = text; break; } first = false; } }
// Draw a pattern of dots. The center of the edge dots are on the edges of the given rectangle, so the dots // protrude out a dot radius from the rectangle. private void DrawPattern(Graphics g, PunchPattern pattern, RectangleF punchRect) { float dxPerDot = (pattern.size > 1) ? punchRect.Width / (pattern.size - 1) : 0; float dyPerDot = (pattern.size > 1) ? punchRect.Height / (pattern.size - 1) : 0; float r = PunchcardAppearance.dotRadius; for (int row = 0; row < pattern.size; ++row) { for (int col = 0; col < pattern.size; ++col) { if (pattern.dots[row, col]) { float xCenter = punchRect.Left + dxPerDot * col; float yCenter = punchRect.Top + dyPerDot * row; g.FillEllipse(Brushes.Black, xCenter - r, yCenter - r, r * 2, r * 2); } } } }