We have built a reporting tool for the Clover ePos which creates a text report for printing using the built-in receipt printer. The app has been through numerous iterations and the code which specifically handles alignment has always bugged me. The task seems trivial to the human mind, but when trying to code seems to throw a lot of curve balls! Here are some examples of the anticipated behavior;

alignment_examples

So we revisited it, and I hope have now built a simpler “one size fits all” (not exactly, but considerably less conditional than before). The code accepts a string with pipe separators to determine alignment (refer to the diagram above for a bit more info) and spits out a string padded accordingly;

public static string Align(string key, int width)
        {
            string newKey = "";
            string[] keyElements = key.Split('|');

            if (keyElements.Length == 1)
            {
                newKey += key;
            }
            else if (keyElements.Length == 2)
            {
                //left align the first chunk
                newKey += keyElements[0];
                //insert blank spaces so the entire line length will be a multiple of width
                newKey += new string('.', width - ((key.Length - 1) % width));
                //insert the last chunk
                newKey += keyElements[1];
            }
            else if (keyElements.Length == 3)
            {
                if (keyElements[0] != "")
                {
                    //left align the first chunk 
                    newKey += keyElements[0];
                    //and pad the rest of the line
                    newKey += new string('.', width - (keyElements[0].Length % width));
                }
                //pad the left, center the second chunk and pad the right
                double sidePadding = width - (keyElements[1].Length % width);
                int leftPadding = (int)Math.Floor(sidePadding / 2);
                int rightPadding = (int)Math.Ceiling(sidePadding / 2);
                newKey += new string('.', leftPadding) + keyElements[1] + new string('.', rightPadding);

                if (keyElements[2] != "")
                {
                    //pad the line
                    newKey += new string('.', width - (keyElements[2].Length % width));
                    //and right align the last chunk
                    newKey += keyElements[2];
                }
            }

            return newKey;
        }

The receipt printer automatically wraps the string but we use a small method to split the string into chunks and add carriage returns/new lines for ease of use. Initially, this too was cumbersome (with loops and ifs etc), but we found a more elegant solution (avoiding re-inventing the wheel and reducing the number of lines of code- though I appreciate a loop is still occurring under the hood);

        public static string Wrap(string key, int width)
        {
            return Regex.Replace(key, ".{" + width + "}", "$0" + Environment.NewLine);
        }

 

Here’s some code we used to test the method(s);

        static void Main(string[] args)
        {
            int width = 33;

            List keys = new List();
            keys.Add("Simple");
            keys.Add("The|quick");
            keys.Add("This first part is really long|quick");
            keys.Add("The|second part is ridiculously long");
            keys.Add("The|quick|brown");
            keys.Add("The centre segment will always sit on it's own line|quick|brown");

            foreach (string key in keys)
            {
                Console.WriteLine(new string('=', width));
                Console.WriteLine("Input: " + key);
                Console.WriteLine(new string('-', width));
                string aligned = Align(key, width);
                string wrapped = Wrap(aligned, width);
                Console.WriteLine(wrapped);
            }

            Console.ReadKey();
        }

Can you think of any further way we can simplify/improve the code?