douglasg14b/BetterConsoleTables

header width not quite right

zmira opened this issue · 3 comments

zmira commented

Hi.

I'm currently using version 2.0.3-rc1 of the library and am getting a weird column width issue

image

The code that generates this is

    var decodingtable = new BetterConsoles.Tables.Table(decodingHeaders.ToArray());
    decodingtable.Config = new BetterConsoles.Tables.Configuration.TableConfig(BetterConsoles.Tables.Style.Unicode);
    foreach (var file in decodingValues.Keys)
    {
        var indexMin = decodingValues[file].IndexOf(decodingValues[file].Min());
        var benchmarkValues = decodingValues[file].ConvertAll(v => v.ToString(@"ss\.ffffff"));
        benchmarkValues[indexMin] = benchmarkValues[indexMin].ForegroundColor(System.Drawing.Color.DarkGreen);
        decodingtable.AddRow(
            Array.Empty<string>()
            .Append(file)
            .Concat(benchmarkValues).ToArray());
    }

    Console.Write(decodingtable.ToString());

I am setting the foreground color as DarkGreen for the cell that contains the minimum value in a list/row.

Any ideas as to why this is happening?

Thanks.

This is expected as the color formatting is occurring outside of the table. This adds ANSI codes to the string that the console renders as formatting. This also means that the string essentially contains a bunch of invisible characters. The header will be sized to the expected column width, but the invisible characters are not actually rendered by the console/terminal. Resulting in the effects seen here.

If you wish for a column or a value be formatted you must use the table API for that, which will calculate the correct column widths and apply formatting after.

To apply column formatting you need to configure the columns in your table:

IColumn[] headers = new[]
{
    new Column(""),
    new Column("QoiCi"),
    new ColumnBuilder("QoiCore")
        .RowsFormat()
            .ForegroundColor(System.Drawing.Color.DarkGreen)
        .GetColumn(),
    new Column("QoiFileTypeNet"),
    new Column("QoiNetStandard"),
    new Column("QoiShark"),
};

var decodingtable = new BetterConsoles.Tables.Table(headers);

Unfortunately I cannot run your example as I don't have an example decodingHeaders or decodingValues to use. But the above should do what you are aiming for if my memory serves me right.

That said, you can find full examples of this and similar APIs in the examples project & file here: (Including the tables in the image on the repo's readme)


Admittedly this API isn't as good as it could be, it's high up on my list of things to make better when I have the time to invest in it.

You could also use:

IColumn[] headers = new[]
{
    new Column(""),
    new Column("QoiCi"),
    new ColumnBuilder("QoiCore")
        .RowsFormat()
            .HasInnerFormatting()
        .GetColumn(),
    new Column("QoiFileTypeNet"),
    new Column("QoiNetStandard"),
    new Column("QoiShark"),
};

And continue coloring it as you currently are. I parse out the ANSI codes when this flag is active, but it has a performance cost (small).

zmira commented

Thanks for the above. Although I had to tweak the code a bit, it now displays correctly.

image

The new code

    var columnsWithMin = new List<int>();
    var decodingTableRows = new List<string[]>();
    foreach (var file in decodingValues.Keys)
    {
        var indexMin = decodingValues[file].IndexOf(decodingValues[file].Min());

        if (!columnsWithMin.Contains(indexMin))
        {
            columnsWithMin.Add(indexMin);
        }

        var benchmarkValues = decodingValues[file]
            .ConvertAll(v => v.ToString(@"ss\.ffffff"));
        benchmarkValues[indexMin] = benchmarkValues[indexMin]
            .ForegroundColor(System.Drawing.Color.DarkGreen);

        decodingTableRows.Add(Array.Empty<string>()
            .Append(file)
            .Concat(benchmarkValues).ToArray());
    }

    var decodingTableHeaders = new List<BetterConsoles.Tables.Models.IColumn>();
    decodingTableHeaders.Add(new BetterConsoles.Tables.Models.Column(string.Empty));

    for (var i = 0; i < decodingHeaders.Count; i++)
    {
        decodingTableHeaders.Add(columnsWithMin.Contains(i)
            ? new BetterConsoles.Tables.Builders.ColumnBuilder(decodingHeaders[i])
                .RowsFormat().HasInnerFormatting().GetColumn()
            : new BetterConsoles.Tables.Models.Column(decodingHeaders[i]));
    }

    var decodingtable = new BetterConsoles.Tables.Table(decodingTableHeaders.ToArray());
    decodingtable.Config = new BetterConsoles.Tables.Configuration.TableConfig(BetterConsoles.Tables.Style.Unicode);
    decodingtable.AddRows(decodingTableRows);

    Console.Write(decodingtable.ToString());