/// <summary> /// Sets the width and height of the base symbol based on the symbol code, /// as well as the top and left properties, /// checking first to see if the canvas already has such limits. /// </summary> /// <param name="symbolCode"> /// The symbol code for the symbol. /// </param> private void SetLimits(string symbolCode) { this.SetValue(Canvas.TopProperty, 0.0); this.SetValue(Canvas.LeftProperty, 0.0); if (this.ApplyTemplate()) { if (VisualTreeHelper.GetChild(this, 0) is Canvas canvas && !double.IsNaN(canvas.Height)) { this.Height = canvas.Height; this.Width = canvas.Width; this.SetValue(Canvas.TopProperty, canvas.GetValue(Canvas.TopProperty)); this.SetValue(Canvas.LeftProperty, canvas.GetValue(Canvas.LeftProperty)); return; } } // Need to handle those symbols that still don't have bounds Rect rect = SymbolData.GetBounds(symbolCode); if (!rect.IsEmpty) { this.Height = rect.Height; this.Width = rect.Width; } else { this.Height = this.Width = 0.0; } }
/// <summary> /// Generate the Joker, Faker, or "eXercise" character. /// </summary> /// <param name="symbolCode"> /// The symbol code for which to generate the large character string. /// </param> /// <param name="labels"> /// A dictionary of the labels to be drawn. /// </param> /// <param name="style"> /// The style to apply to the labels. /// </param> /// <returns> /// The TextBlock that incorporates the labels. /// </returns> internal static TextBlock GenerateJokerFakerExercise(string symbolCode, IDictionary <string, string> labels, Style style) { // Check for matching code char theChar = StandardIdentity.GetExerciseAmplifyingDescriptor(symbolCode); if (theChar == (char)0) { return(null); } #if WINDOWS_UWP string theString = theChar.ToString(); #else string theString = theChar.ToString(Culture); #endif if (labels != null && labels.ContainsKey("F")) { theString += " " + labels["F"]; } Rect r = SymbolData.GetBounds(symbolCode); var tb = new TextBlock { Style = style, // BigLabels, Text = theString }; tb.FindTextExtent(); tb.SetValue(Canvas.TopProperty, r.Top - tb.Height); tb.SetValue(Canvas.LeftProperty, r.Right); return(tb); }
/// <summary> /// Generate the right labels for the symbol. /// </summary> /// <param name="symbolCode"> /// The symbol code for which to generate the labels. /// </param> /// <param name="labels"> /// The dictionary of labels to generate. /// </param> /// <param name="style"> /// The style with which to render the labels. /// </param> /// <returns> /// A TextBlock that represents the rendered labels. /// </returns> internal static TextBlock GenerateRight(string symbolCode, IDictionary <string, string> labels, Style style) { // Pick off the left-oriented strings and write them out if (labels == null) { return(null); } var right = new TextBlock { Style = style /*RightLabels*/ }; bool gotLine = false; // If we have an X, J, or K modifier character, skip label F because it is already written out. if (StandardIdentity.GetExerciseAmplifyingDescriptor(symbolCode) != (char)0) { ProcessLabels(labels, false, new[] { string.Empty }, right, ref gotLine); } else { ProcessLabels(labels, false, new[] { "F" }, right, ref gotLine); } var height = gotLine ? (double)right.GetValue(TextBlock.LineHeightProperty) : 0.0; // At this point we need to process the remaining labels as if each row has a label. // Otherwise some label lines may appear in the wrong position // if other label lines are empty. // Setting "gotLine" to true forces a new line for each of the label lines. // More complicated logic might consider the height of the text block, prior to // the elimination of the empty lines. gotLine = true; ProcessLabels(labels, false, new[] { "G" }, right, ref gotLine); ProcessLabels(labels, false, new[] { "H" }, right, ref gotLine); ProcessLabels(labels, false, new[] { "M" }, right, ref gotLine); ProcessLabels(labels, true, new[] { "J", "K", "L", "N", "P" }, right, ref gotLine); TruncateNewLines(right); Rect b = SymbolData.GetBounds(symbolCode); SetTopLeft(right, b.Right + (height / 5.0), b.Top - height); return(right); }
/// <summary> /// Returns the arrow representing a direction of travel for a mil symbol /// </summary> /// <param name="symbolCode">Code for the mil symbol</param> /// <param name="labels">The labels for the symbol, we're looking for "Q"</param> /// <param name="extraOffset">An extra offset for tactical graphics</param> /// <returns>The arrow shape representing the direction of travel</returns> internal static Shape GenerateQ( string symbolCode, IDictionary <string, string> labels, double extraOffset) { if (!SymbolData.Check(ref symbolCode)) { return(null); } string q; if (!labels.TryGetValue("Q", out q)) { return(null); } double angle; if (!double.TryParse(q, out angle)) { return(null); } double off = 0.0; if (CategoryBattleDimension.GetCode(symbolCode) == CategoryBattleDimension.BdGround) { off = SymbolData.GetBounds(symbolCode).Bottom; } off += extraOffset; return(new Path { Style = SymbolData.GetStyle("BS10"), Data = new PathGeometry { Figures = new PathFigureCollection { GenerateArrowPoints(off, angle) } } }); }
/// <summary> /// Generate the left labels for the symbol. /// </summary> /// <param name="symbolCode"> /// The symbol code for which to generate the labels. /// </param> /// <param name="labels"> /// The dictionary of labels to generate. /// </param> /// <param name="style"> /// The style with which to render the labels. /// </param> /// <returns> /// A TextBlock that represents the rendered labels. /// </returns> internal static TextBlock GenerateLeft(string symbolCode, IDictionary <string, string> labels, Style style) { if (!SymbolData.Check(ref symbolCode)) { return(null); } // Pick off the left-oriented strings and write them out if (labels == null) { return(null); } var left = new TextBlock { Style = style /*LeftLabels*/ }; bool gotLine = false; ProcessLabels(labels, false, new[] { "W" }, left, ref gotLine); var height = gotLine ? (double)left.GetValue(TextBlock.LineHeightProperty) : 0.0; // At this point we need to process the remaining labels as if each row has a label. // Otherwise some label lines may appear in the wrong position // if other label lines are empty. // Setting "gotLine" to true forces a new line for each of the label lines. // More complicated logic might consider the height of the text block, prior to // the elimination of the empty lines. gotLine = true; ProcessLabels(labels, false, new[] { "X", "Y" }, left, ref gotLine); ProcessLabels(labels, false, new[] { "V" }, left, ref gotLine); ProcessLabels(labels, false, new[] { "T" }, left, ref gotLine); ProcessLabels(labels, true, new[] { "Z" }, left, ref gotLine); TruncateNewLines(left); Rect b = SymbolData.GetBounds(symbolCode); left.FindTextExtent(); SetTopLeft(left, b.Left - left.Width - 10, b.Top - height); return(left); // we're only doing this to support unit test }
/// <summary> /// Generates barge mobility object. /// </summary> /// <param name="symbolCode"> /// The symbol code containing the mobility indicator for which to create a mobility Shape. /// </param> /// <returns> /// A Shape object representing the mobility object. /// </returns> public static Shape GenerateMobility(string symbolCode) { if (!SymbolData.Check(ref symbolCode)) { return(null); } if (!Mobility.IsMobility(symbolCode)) { return(null); } Rect b = SymbolData.GetBounds(symbolCode); double bottom = b.Bottom + HalfWidth; bool flat = SymbolData.IsBaseFlat(symbolCode); const double X = End - Rad; switch (Mobility.GetCode(symbolCode)) { case Mobility.WheeledLimited: return(GenerateWheels(new[] { -X, X }, bottom)); case Mobility.WheeledCrossCountry: return(GenerateWheels(new[] { -X, 0, X }, bottom)); case Mobility.Tracked: return(GenerateTracked(bottom)); case Mobility.WheeledTracked: return(GenerateWheeledTracked(bottom)); case Mobility.Towed: if (flat) { bottom += Rad; } return(GenerateTowed(bottom)); case Mobility.Railway: return(GenerateWheels(new[] { -X, -X + TwoRad, X - TwoRad, X }, bottom)); case Mobility.OverSnow: if (flat) { bottom += TwoRad; } return(GenerateOverSnow(bottom)); case Mobility.Sled: if (!flat) { bottom -= TwoRad; } return(GenerateSled(bottom)); case Mobility.PackAnimals: return(GeneratePackAnimals(bottom)); case Mobility.Barge: return(GenerateBarge(bottom)); case Mobility.Amphibious: return(GenerateAmphibious(bottom)); case Mobility.TowedArrayShort: return(GenerateArray(new[] { -End - TwoSqr, 0.0, End + TwoSqr }, bottom + ThreeSqr - HalfWidth)); case Mobility.TowedArrayLong: if (!flat) { bottom -= Sqr + HalfWidth; } return(GenerateArray( new[] { -End - TwoSqr, -HalfEnd - Sqr, 0.0, HalfEnd + Sqr, End + TwoSqr }, bottom + ThreeSqr - HalfWidth)); } return(null); }