/// <summary> /// Creates a new <c>PathItem</c> /// </summary> /// <param name="itemType">The type of item involved</param> /// <param name="unit">The distance unit (was default=null)</param> /// <param name="value">The item value (was default=0.0)</param> internal PathItem(PathItemType itemType, DistanceUnit unit, double value) { m_Item = itemType; m_Unit = unit; m_Value = value; m_Leg = 0; }
/// <summary> /// Copy constructor /// </summary> /// <param name="copy">The item to copy from</param> internal PathItem(PathItem copy) { m_Item = copy.m_Item; m_Unit = copy.m_Unit; m_Value = copy.m_Value; m_Leg = copy.m_Leg; }
/// <summary> /// Default constructor creates a null item. /// </summary> internal PathItem() { m_Item = PathItemType.Null; m_Unit = null; m_Value = 0.0; m_Leg = 0; }
public CopyFilesStep(string source, PathItemType sourceType, string target, PathItemType targetType, StepType onStep) : base(onStep) { _source = source; _sourceType = sourceType; _target = target; _targetType = targetType; }
/// <summary> /// Repeats the last path item a specific number of times. The thing to /// repeat HAS to be of type PAT_VALUE (or possibly a PAT_MC that has been /// automatically inserted by <see cref="AddItem"/>). /// </summary> /// <param name="repeat">The number of times the last item should appear (we /// will append n-1 copies of the last item).</param> void AddRepeats(int repeat) { // Confirm that we have something to repeat. if (m_Items.Count == 0) { throw new ApplicationException("Nothing to repeat"); } // If the last item was a PAT_MC, get to the value before that. int prev = m_Items.Count - 1; PathItemType type = m_Items[prev].ItemType; if (type == PathItemType.MissConnect && prev > 0) { prev--; type = m_Items[prev].ItemType; } // It can only be a PAT_VALUE. if (type != PathItemType.Value) { throw new ApplicationException("Unexpected repeat multiplier"); } // Make copies of the last value. for (int i = 1; i < repeat; i++) { PathItem copy = new PathItem(m_Items[prev]); AddItem(copy); } }
public DrawableItem(string itemName, PathItemType itemType = PathItemType.File) { RelativeSizeAxes = Axes.X; Height = DefaultHeight; CornerRadius = 5; Masking = true; AddRange(new Drawable[] { background = new Box { RelativeSizeAxes = Axes.Both, Colour = deselectedBackgroundColor }, new FillFlowContainer { Spacing = new Vector2(5, 0), Direction = FillDirection.Horizontal, AutoSizeAxes = Axes.Both, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Padding = new MarginPadding { Left = 5 }, Children = new Drawable[] { icon = new SpriteIcon { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Size = new Vector2(25) }, text = new SpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft } } } }); ItemName = itemName; ItemType = itemType; selected.ValueChanged += HandleSelectionChanged; }
/// <summary> /// Holds on to an additional path item. /// </summary> /// <param name="item">The item to add.</param> void AddItem(PathItem item) { // If no items have been added, ensure omitted flag has been // freshly initialized. if (m_Items.Count == 0) { m_Omit = false; } // Ignore an attempt to add 2 miss-connects in a row (ValidPath // will complain). PathItemType type = item.ItemType; if (m_Items.Count > 0 && type == PathItemType.MissConnect && m_Items[m_Items.Count - 1].ItemType == PathItemType.MissConnect) { return; } // Add the supplied item into the list. m_Items.Add(item); // If we have just appended a PAT_VALUE, append an additional // miss-connect item if we previously omitted a point. if (m_Omit && type == PathItemType.Value) { m_Omit = false; AddItem(PathItemType.MissConnect); } // Remember whether we just omitted a point. if (type == PathItemType.OmitPoint) { m_Omit = true; } }
/// <summary> /// Holds on to an additional path item. Good for items that /// do not have an associated value. /// </summary> /// <param name="type">The type of item to add.</param> void AddItem(PathItemType type) { PathItem item = new PathItem(type, null, 0.0); AddItem(item); }
void ParseWord(string str) { // Return if string is empty (could be empty if this function // has been called recursively from below). str = str.Trim(); int nc = str.Length; if (nc == 0) { return; } // If we have a new default units specification, make it // the default. There should be whitespace after the "..." if (str.Contains("...")) { DistanceUnit unit = GetUnits(str, true); PathItem item = new PathItem(PathItemType.Units, unit, 0.0); AddItem(item); return; } // If we have a counter-clockwise indicator, just remember it // and parse anything that comes after it. if (nc >= 2 && String.Compare(str.Substring(0, 2), "cc", true) == 0) { AddItem(PathItemType.CounterClockwise); ParseWord(str.Substring(2)); return; } // If we have a BC, remember it & parse anything that follows. if (str[0] == '(') { AddItem(PathItemType.BC); ParseWord(str.Substring(1)); return; } // If we have a EC, remember it & parse anything that follows. if (str[0] == ')') { AddItem(PathItemType.EC); ParseWord(str.Substring(1)); return; } // If we have a single slash character (possibly followed by // a digit or a decimal point), record the single slash & // parse anything that follows. if (str[0] == '/') { // Check for a free-standing slash, or a slash that is // followed by a numeric digit or decimal point. if (nc == 1 || Char.IsDigit(str, 1) || str[1] == '.') { AddItem(PathItemType.Slash); ParseWord(str.Substring(1)); return; } // More than one character, or what follows is not a digit. // So we are dealing with either a miss-connect, or an // omit-point. In either case, there should be whitespace // after that. if (nc == 2) { if (str[1] == '-') { AddItem(PathItemType.MissConnect); return; } if (str[1] == '*') { AddItem(PathItemType.OmitPoint); return; } } // Allow CADCOR-style data entry else if (nc == 3) { if (String.Compare(str, "/mc", true) == 0) { AddItem(PathItemType.MissConnect); return; } if (String.Compare(str, "/op", true) == 0) { AddItem(PathItemType.OmitPoint); return; } } string msg = String.Format("Unexpected qualifier '{0}'", str); throw new ApplicationException(msg); } // If we have a multiplier, it must be immediately followed // by a numeric (integer) value. if (str[0] == '*') { if (nc == 1) { throw new ApplicationException("Unexpected '*' character"); } // Pick up the repeat count (not sure if the digits need to be // followed by white space, or whether non-numeric digits are valid, // so pick up only the digits). string num = GetIntDigits(str.Substring(1)); // Error if repeat count is less than 2. int repeat; if (!Int32.TryParse(num, out repeat) || repeat < 2) { string msg = String.Format("Unexpected repeat count in '{0}'", str); throw new ApplicationException(msg); } if (repeat < 2) { string msg = String.Format("Unexpected repeat count in '{0}'", str); throw new ApplicationException(msg); } // Duplicate the last item using the repeat count. AddRepeats(repeat); // Continue parsing after the repeat count. ParseWord(str.Substring(1 + num.Length)); return; } // If the string contains an embedded qualifier (a "*" or a "/" // character), process the portion of any string prior to the // qualifier. Note that we have just handled the cases where // the qualifier was at the very start of the string. int starIndex = str.IndexOf('*'); int slashIndex = str.IndexOf('/'); if (starIndex >= 0 || slashIndex >= 0) { int qualIndex = starIndex; if (qualIndex < 0 || (slashIndex >= 0 && qualIndex > slashIndex)) { qualIndex = slashIndex; } // Process the stuff prior to the qualifier. string copy = str.Substring(0, qualIndex); ParseWord(copy); // Process the stuff, starting with the qualifier character ParseWord(str.Substring(qualIndex)); return; } // Process this string. We should have either a value or an angle. if (str.IndexOf('-') >= 0 || IsLastItemBC()) { // If the string contains a "c" character, it's a central // angle; process the string only as far as that. PathItemType type = PathItemType.Angle; int caIndex = str.ToUpper().IndexOf('C'); if (caIndex >= 0) { str = str.Substring(0, caIndex); type = PathItemType.CentralAngle; } else { // Check if it's a deflection (if so, strip out the "d"). int dIndex = str.ToUpper().IndexOf('D'); if (dIndex >= 0) { str = str.Substring(0, dIndex) + str.Substring(dIndex + 1); type = PathItemType.Deflection; } } // Try to parse an angular value into radians. double radval; if (RadianValue.TryParse(str, out radval)) { PathItem item = new PathItem(type, null, radval); AddItem(item); return; } // Bad angle. string msg = String.Format("Malformed angle '{0}'", str); throw new ApplicationException(msg); } else { // Get the current distance units. DistanceUnit unit = GetUnits(null, false); // Grab characters that look like a floating point number string num = GetDoubleDigits(str); double val; if (!Double.TryParse(num, out val)) { string msg = String.Format("Malformed value '{0}'", str); throw new ApplicationException(msg); } // If we didn't get right to the end, we may have distance units, // or the ")" character indicating an EC. if (num.Length < str.Length && str[num.Length] != ')') { unit = GetUnits(str.Substring(num.Length), false); if (unit == null) { string msg = String.Format("Malformed value '{0}'", str); throw new ApplicationException(msg); } } PathItem item = new PathItem(PathItemType.Value, unit, val); AddItem(item); if (str.Length > num.Length && str[num.Length] == ')') { ParseWord(str.Substring(num.Length)); } return; } }
/// <summary> /// Creates a straight leg. /// </summary> /// <param name="items">Array of path items.</param> /// <param name="si">Index to the item where the leg data starts.</param> /// <param name="nexti">Index of the item where the next leg starts.</param> /// <returns>The new leg.</returns> static StraightLeg CreateStraightLeg(PathItem[] items, int si, out int nexti) { // Get the leg ID. int legnum = items[si].LegNumber; // How many distances have we got? int ndist = 0; for (nexti = si; nexti < items.Length && items[nexti].LegNumber == legnum; nexti++) { if (items[nexti].IsDistance) { ndist++; } } // Create the leg. StraightLeg leg = new StraightLeg(ndist); // Assign each distance. ndist = 0; for (int i = si; i < nexti; i++) { Distance d = items[i].GetDistance(); if (d != null) { // See if there is a qualifier after the distance LegItemFlag qual = LegItemFlag.Null; if ((i + 1) < nexti) { PathItemType nexttype = items[i + 1].ItemType; if (nexttype == PathItemType.MissConnect) { qual = LegItemFlag.MissConnect; } if (nexttype == PathItemType.OmitPoint) { qual = LegItemFlag.OmitPoint; } } leg.PrimaryFace.SetDistance(d, ndist, qual); ndist++; } } // If the first item is an angle, remember it as part of the leg. if (items[si].ItemType == PathItemType.Angle) { leg.StartAngle = items[si].Value; } else if (items[si].ItemType == PathItemType.Deflection) { leg.SetDeflection(items[si].Value); } // Return a reference to the new leg return(leg); }
/// <summary> /// Creates a circular leg. /// </summary> /// <param name="items">Array of path items.</param> /// <param name="si">Index to the item where the leg data starts.</param> /// <param name="nexti">Index of the item where the next leg starts.</param> /// <returns>The new leg.</returns> static CircularLeg CreateCircularLeg(PathItem[] items, int si, out int nexti) { // Confirm that the first item refers to the BC. if (items[si].ItemType != PathItemType.BC) { throw new Exception("PathParser.CreateCircularLeg - Not starting at BC"); } // The BC has to be followed by at least 3 items: angle, radius // and EC (add an extra 1 to account for 0-based indexing). if (items.Length < si + 4) { throw new Exception("PathParser.CreateCircularLeg - Insufficient curve data"); } double bangle = 0.0; // Angle at BC double cangle = 0.0; // Central angle double eangle = 0.0; // Angle at EC bool twoangles = false; // True if bangle & eangle are both defined. bool clockwise = true; // True if curve is clockwise int irad = 0; // Index of the radius item bool cul = false; // True if cul-de-sac case // Point to item following the BC. nexti = si + 1; PathItemType type = items[nexti].ItemType; // If the angle following the BC is a central angle if (type == PathItemType.CentralAngle) { // We have a cul-de-sac cul = true; // Get the central angle. cangle = items[nexti].Value; nexti++; } else if (type == PathItemType.BcAngle) { // Get the entry angle. bangle = items[nexti].Value; nexti++; // Does an exit angle follow? if (items[nexti].ItemType == PathItemType.EcAngle) { eangle = items[nexti].Value; twoangles = true; nexti++; } } else { // The field after the BC HAS to be an angle. throw new ApplicationException("Angle does not follow BC"); } // Must be followed by radius. if (items[nexti].ItemType != PathItemType.Radius) { throw new ApplicationException("Radius does not follow angle"); } // Get the radius Distance radius = items[nexti].GetDistance(); irad = nexti; nexti++; // The item after the radius indicates whether the curve is counterclockwise. if (items[nexti].ItemType == PathItemType.CounterClockwise) { nexti++; clockwise = false; } // Get the leg ID. int legnum = items[si].LegNumber; // How many distances have we got? int ndist = 0; for (; nexti < items.Length && items[nexti].LegNumber == legnum; nexti++) { if (items[nexti].IsDistance) { ndist++; } } // Create the leg. CircularLeg leg = new CircularLeg(radius, clockwise, ndist); CircularLegMetrics metrics = leg.Metrics; // Set the entry angle or the central angle, depending on what we have. if (cul) { metrics.SetCentralAngle(cangle); } else { metrics.SetEntryAngle(bangle); } // Assign second angle if we have one. if (twoangles) { metrics.SetExitAngle(eangle); } // Assign each distance, starting one after the radius. ndist = 0; for (int i = irad + 1; i < nexti; i++) { Distance dist = items[i].GetDistance(); if (dist != null) { // See if there is a qualifier after the distance LegItemFlag qual = LegItemFlag.Null; if (i + 1 < nexti) { PathItemType nexttype = items[i + 1].ItemType; if (nexttype == PathItemType.MissConnect) { qual = LegItemFlag.MissConnect; } if (nexttype == PathItemType.OmitPoint) { qual = LegItemFlag.OmitPoint; } } leg.PrimaryFace.SetDistance(dist, ndist, qual); ndist++; } } // Return the new leg. return(leg); }
/// <summary> /// Associates each path item with a leg sequence number. /// </summary> /// <returns>The number of legs found.</returns> int SetLegs() { int nleg = 0; // Note that PathItemType.Units may not get a leg number. for (int i = 0; i < m_Items.Count;) // not i++ { PathItemType type = m_Items[i].ItemType; if (type == PathItemType.Distance || type == PathItemType.Angle || type == PathItemType.Deflection || type == PathItemType.BC) { // If we have a distance or angle item, increment the leg // sequence number until we hit an angle or a BC. In the case of // an angle, it always comes at the START of a leg. if (type == PathItemType.Distance || type == PathItemType.Angle || type == PathItemType.Deflection) { nleg++; m_Items[i].LegNumber = nleg; for (i++; i < m_Items.Count; i++) { if (m_Items[i].ItemType == PathItemType.Angle || m_Items[i].ItemType == PathItemType.Deflection || m_Items[i].ItemType == PathItemType.BC) { break; } m_Items[i].LegNumber = nleg; } } else { // We have a BC, so increment the leg sequence number // & scan until we hit the EC. nleg++; for (; i < m_Items.Count; i++) { m_Items[i].LegNumber = -nleg; // negated if (m_Items[i].ItemType == PathItemType.EC) { i++; break; } } } } else { m_Items[i].LegNumber = nleg; i++; } } return(nleg); }