public void Draw(SKCanvas canvas, int width, int height)
        {
            canvas.Clear(BackgroundColor);

            if (TableCellData.Count > 0 && TableCellData[0].Count > 0)
            {
                //Figure out how many rows to draw
                int number_of_table_rows = TableCellData.Count;
                if (DisplayHeaderRow)
                {
                    number_of_table_rows++;
                }

                //Figure out how many columns to draw
                int number_of_table_columns = TableCellData[0].Count;

                //Verify that all columns have the same count
                bool column_count_ok = TableCellData.All(x => x.Count == number_of_table_columns);
                if (column_count_ok && Margin >= 0)
                {
                    if (FitCellSizesToLargestText)
                    {
                        float largest_width  = GetLargestTextSize() * 1.25f;
                        float largest_height = Math.Max(TableColumnHeaderTextSize, TableCellContentTextSize) * 1.5f;
                        width  = Convert.ToInt32((largest_width * number_of_table_columns) + (2 * Margin));
                        height = Convert.ToInt32((largest_height * number_of_table_rows) + (2 * Margin));

                        CalculatedWidth  = width;
                        CalculatedHeight = height;
                    }

                    //Account for margins
                    float actual_display_width  = width - (2 * Margin);
                    float actual_display_height = height - (2 * Margin);
                    float actual_top_ypos       = Margin;
                    float actual_bottom_ypos    = height - Margin;
                    float actual_left_xpos      = Margin;
                    float actual_right_xpos     = width - Margin;

                    float column_width      = Convert.ToSingle(actual_display_width) / number_of_table_columns;
                    float row_height        = Convert.ToSingle(actual_display_height) / number_of_table_rows;
                    float half_column_width = column_width / 2.0f;
                    float half_row_height   = row_height / 2.0f;

                    var backgrounds = GetCellBackgroundColors();
                    var foregrounds = GetCellTextColors();

                    //Draw the cell backgrounds
                    for (int r = 0; r < number_of_table_rows; r++)
                    {
                        for (int c = 0; c < number_of_table_columns; c++)
                        {
                            if (backgrounds[r, c] != SKColor.Empty)
                            {
                                float cell_xpos = actual_left_xpos + (column_width * c);
                                float cell_ypos = actual_top_ypos + (row_height * r);

                                using (var paint = new SKPaint()
                                {
                                    Style = SKPaintStyle.StrokeAndFill,
                                    StrokeWidth = GridLinesStrokeWidth,
                                    Color = backgrounds[r, c],
                                    IsAntialias = true
                                })
                                {
                                    canvas.DrawRect(new SKRect(cell_xpos, cell_ypos, cell_xpos + column_width,
                                                               cell_ypos + row_height), paint);
                                }
                            }
                        }
                    }

                    //Draw the grid lines
                    if (GridLineSettings == GridLinesType.AllGridLines)
                    {
                        using (var paint = new SKPaint()
                        {
                            Style = SKPaintStyle.Stroke,
                            StrokeWidth = GridLinesStrokeWidth,
                            Color = GridLinesColor,
                            IsAntialias = true
                        })
                        {
                            //Start with drawing lines to separate columns
                            float xpos = actual_left_xpos;
                            for (int i = 0; i < (number_of_table_columns + 1); i++)
                            {
                                canvas.DrawLine(xpos, actual_top_ypos, xpos, actual_bottom_ypos, paint);
                                xpos += column_width;
                            }

                            //Now let's draw lines to separate the rows
                            float ypos = actual_top_ypos;
                            for (int i = 0; i < (number_of_table_rows + 1); i++)
                            {
                                canvas.DrawLine(actual_left_xpos, ypos, actual_right_xpos, ypos, paint);
                                ypos += row_height;
                            }
                        }
                    }

                    //Now draw the header text for each column
                    if (DisplayHeaderRow)
                    {
                        using (var paint = new SKPaint()
                        {
                            Color = TableColumnHeaderTextColor,
                            TextSize = TableColumnHeaderTextSize,
                            IsAntialias = true,
                            IsStroke = false
                        })
                        {
                            //Iterate over each column
                            float xpos          = actual_left_xpos;
                            float cell_x_center = 0;
                            float cell_y_center = actual_top_ypos + half_row_height;
                            for (int i = 0; i < TableColumnHeaders.Count; i++)
                            {
                                //Change the text color if necessary
                                if (foregrounds[0, i] != SKColors.Empty)
                                {
                                    paint.Color = foregrounds[0, i];
                                }

                                //Measure the text we are about to display
                                var bounds = new SKRect();
                                var text   = TableColumnHeaders[i];
                                if (!string.IsNullOrEmpty(text))
                                {
                                    paint.MeasureText(text, ref bounds);

                                    //Calculate the center of this cell
                                    cell_x_center = xpos + half_column_width;

                                    //Determine where to draw the text
                                    float text_x = cell_x_center - (bounds.Width / 2.0f);
                                    float text_y = cell_y_center + (bounds.Height / 2.0f);

                                    //Draw the text
                                    canvas.DrawText(text, text_x, text_y, paint);
                                }

                                //Increment the x value to go to the next column
                                xpos += column_width;

                                //Revert the text color back to the default setting
                                paint.Color = TableColumnHeaderTextColor;
                            }
                        }
                    }

                    //Now let's draw the actual table data
                    using (var paint = new SKPaint()
                    {
                        Color = TableCellContentTextColor,
                        TextSize = TableCellContentTextSize,
                        IsAntialias = true,
                        IsStroke = false
                    })
                    {
                        float xpos          = actual_left_xpos;
                        float ypos          = (DisplayHeaderRow) ? actual_top_ypos + row_height : actual_top_ypos;
                        float cell_x_center = 0;
                        float cell_y_center = 0;

                        for (int r = 0; r < TableCellData.Count; r++)
                        {
                            xpos          = actual_left_xpos;
                            cell_y_center = ypos + half_row_height;

                            for (int c = 0; c < number_of_table_columns; c++)
                            {
                                //Change the text color if necessary
                                var foregrounds_r = r;
                                if (DisplayHeaderRow)
                                {
                                    foregrounds_r++;
                                }
                                if (foregrounds[foregrounds_r, c] != SKColors.Empty)
                                {
                                    paint.Color = foregrounds[foregrounds_r, c];
                                }

                                //Measure the text we are about to display
                                var bounds = new SKRect();
                                var text   = TableCellData[r][c].ToString();
                                if (!string.IsNullOrEmpty(text))
                                {
                                    paint.MeasureText(text, ref bounds);

                                    //Calculate the center of this cell
                                    cell_x_center = xpos + half_column_width;

                                    //Determine where to draw the text
                                    float text_x = cell_x_center - (bounds.Width / 2.0f);
                                    float text_y = cell_y_center + (bounds.Height / 2.0f);

                                    //Draw the text
                                    canvas.DrawText(text, text_x, text_y, paint);
                                }

                                //Increment the x value to go to the next column
                                xpos += column_width;

                                //Revert the color back to the default
                                paint.Color = TableCellContentTextColor;
                            }

                            ypos += row_height;
                        }
                    }
                }
            }
        }
        public (int, int) GetGridCoordinatesFromCanvasCoordinates(int screen_x, int screen_y)
        {
            int row    = 0;
            int col    = 0;
            int width  = 0;
            int height = 0;

            if (TableCellData.Count > 0 && TableCellData[0].Count > 0)
            {
                //Figure out how many rows
                int number_of_table_rows = TableCellData.Count;
                if (DisplayHeaderRow)
                {
                    number_of_table_rows++;
                }

                //Figure out how many columns
                int number_of_table_columns = TableCellData[0].Count;

                //Verify that all columns have the same count
                bool column_count_ok = TableCellData.All(x => x.Count == number_of_table_columns);
                if (column_count_ok && Margin >= 0)
                {
                    if (FitCellSizesToLargestText)
                    {
                        float largest_width  = GetLargestTextSize() * 1.25f;
                        float largest_height = Math.Max(TableColumnHeaderTextSize, TableCellContentTextSize) * 1.5f;
                        width  = Convert.ToInt32((largest_width * number_of_table_columns) + (2 * Margin));
                        height = Convert.ToInt32((largest_height * number_of_table_rows) + (2 * Margin));

                        CalculatedWidth  = width;
                        CalculatedHeight = height;
                    }

                    //Account for margins
                    float actual_display_width  = width - (2 * Margin);
                    float actual_display_height = height - (2 * Margin);
                    float actual_top_ypos       = Margin;
                    float actual_bottom_ypos    = height - Margin;
                    float actual_left_xpos      = Margin;
                    float actual_right_xpos     = width - Margin;

                    float column_width      = Convert.ToSingle(actual_display_width) / number_of_table_columns;
                    float row_height        = Convert.ToSingle(actual_display_height) / number_of_table_rows;
                    float half_column_width = column_width / 2.0f;
                    float half_row_height   = row_height / 2.0f;

                    float transformed_x = screen_x;
                    float transformed_y = screen_y;

                    transformed_x -= actual_left_xpos;
                    transformed_y -= actual_top_ypos;
                    if (DisplayHeaderRow)
                    {
                        transformed_y -= row_height;
                    }

                    transformed_x /= column_width;
                    transformed_y /= row_height;
                    transformed_x  = Convert.ToSingle(Math.Floor(transformed_x));
                    transformed_y  = Convert.ToSingle(Math.Floor(transformed_y));
                    row            = Convert.ToInt32(transformed_y);
                    col            = Convert.ToInt32(transformed_x);
                }
            }

            return(row, col);
        }