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); }