using System;
using System.Drawing;
using System.Windows.Forms;
namespace AdvertsingProfitControl
{
internal class AdvertisingProfitControlTableHelper
{
///
/// Paints rows according to their RowAttribute and detects whether or not they are part of a group.
/// This function offers a faster method of determining all of this by starting at the row index that
/// fired the row leave even. As opposed to the PaintRowGroups function which spins through all the
/// DataGridView's rows.
///
/// The starting index (the row that fired the RowLeave event)
/// The DataGridView to parse.
public void PaintRowGroupsFromIndex(int startingIndex, DataGridView dataGridView)
{
var parser = new RowParsing();
int isHeaderColumn;
int isMemberColumn;
int adSpecialColumn;
if (dataGridView.Columns.Count == Enum.GetNames(typeof(SalesTableColumns)).Length)
{
isHeaderColumn = (int) SalesTableColumns.IsHeaderRow;
isMemberColumn = (int) SalesTableColumns.IsMemberRow;
adSpecialColumn = (int) SalesTableColumns.IsAdSpecialRow;
}
else
{
isHeaderColumn = (int)InventoryTableColumns.IsHeaderRow;
isMemberColumn = (int)InventoryTableColumns.IsMemberRow;
adSpecialColumn = (int) InventoryTableColumns.IsAdSpecialRow;
}
//If the current row is an Ad Special Row, the color code it and return as nothing further needs to be done.
if (parser.CheckForGroupKeyWord(dataGridView.Rows[startingIndex].Cells[(int) SalesTableColumns.AdItem].EditedFormattedValue.ToString()) != "NoGroupFound")
{
dataGridView.Rows[startingIndex].Cells[adSpecialColumn].Value = true;
dataGridView.Rows[startingIndex].DefaultCellStyle.BackColor = Color.Silver;
return;
}
//Spin through the dataGridView rows starting at the row that fired the event.
for (var i = startingIndex; i < (dataGridView.RowCount - 1); i++)
{
//Get the status of the current row.
var rowStatus = parser.GetRowAttribute(dataGridView.Rows[i]);
//IF the current row is a header row...
if (rowStatus == RowAttribute.HeaderRow)
{
//Then check to see if the next row is a row header.
rowStatus = parser.GetRowAttribute(dataGridView.Rows[i + 1]);
//IF so, color code this row as White, since it is not a true group header.
if (rowStatus != RowAttribute.HeaderRow)
{
//Clear the current row of its attributes.
dataGridView.Rows[i].Cells[isHeaderColumn].Value = false;
dataGridView.Rows[i].Cells[isMemberColumn].Value = false;
dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;
}
//IF the current row is not the first row in the data grid (index zero)...
if (i > 0)
{
//The start by checking the previous row's status.
rowStatus = parser.GetRowAttribute(dataGridView.Rows[i - 1]);
//IF the previous row is a header row OR if the previous row is index zero AND a member row, clear its coloring.
if (rowStatus == RowAttribute.HeaderRow || rowStatus == RowAttribute.MemberRow && (i - 1) == 0)
{
//Clear the previous row of its attributes.
dataGridView.Rows[i - 1].Cells[isHeaderColumn].Value = false;
dataGridView.Rows[i - 1].Cells[isMemberColumn].Value = false;
dataGridView.Rows[i - 1].DefaultCellStyle.BackColor = Color.White;
}
//IF the previous row is a header row AND has color coding saying it is a group header, then clear the previous row's color and apply it to this row (i).
else if (rowStatus == RowAttribute.HeaderRow && (bool)dataGridView.Rows[i - 1].Cells[isHeaderColumn].Value)
{
//Clear the previous row of its attributes.
dataGridView.Rows[i - 1].Cells[isHeaderColumn].Value = false;
dataGridView.Rows[i - 1].Cells[isMemberColumn].Value = false;
dataGridView.Rows[i - 1].DefaultCellStyle.BackColor = Color.White;
//Set the current row as a header row.
dataGridView.Rows[i].Cells[isHeaderColumn].Value = true;
dataGridView.Rows[i].Cells[isMemberColumn].Value = false;
dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.LightGray;
}
//IF previous row is Incomplete, then call the stable PaintRowGroups function.
else if (rowStatus == RowAttribute.IncompleteRow)
{
PaintRowGroups(dataGridView);
}
}
else
{
//Then check to see if the next row is a member row
rowStatus = parser.GetRowAttribute(dataGridView.Rows[i + 1]);
if (rowStatus == RowAttribute.MemberRow)
{
//Set the previous row as a header row.
dataGridView.Rows[i].Cells[isHeaderColumn].Value = true;
dataGridView.Rows[i].Cells[isMemberColumn].Value = false;
dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.LightGray;
//Set the next row as a member row.
dataGridView.Rows[i + 1].Cells[isHeaderColumn].Value = false;
dataGridView.Rows[i + 1].Cells[isMemberColumn].Value = true;
dataGridView.Rows[i + 1].DefaultCellStyle.BackColor = Color.LightBlue;
}
}
}
else if (rowStatus == RowAttribute.MemberRow)
{
if (i > 0)
{
//Check the previous row.
rowStatus = parser.GetRowAttribute(dataGridView.Rows[i - 1]);
//IF the previous row is a member row AND is the first row in the data grid, then remove the coloring for it and the current row (i).
if (rowStatus == RowAttribute.MemberRow && (i - 1) == 0)
{
//Clear the previous row of its attributes.
dataGridView.Rows[i - 1].Cells[isHeaderColumn].Value = false;
dataGridView.Rows[i - 1].Cells[isMemberColumn].Value = false;
dataGridView.Rows[i - 1].DefaultCellStyle.BackColor = Color.White;
//Clear the current row of its attributes.
dataGridView.Rows[i].Cells[isHeaderColumn].Value = false;
dataGridView.Rows[i].Cells[isMemberColumn].Value = false;
dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;
}
//IF the previous row is a member row AND it also has color coding suggesting that it is a member of a group, then add the current row (i) as well.
else if (rowStatus == RowAttribute.MemberRow && (bool)dataGridView.Rows[i - 1].Cells[isMemberColumn].Value)
{
//Set the current row as a member row.
dataGridView.Rows[i].Cells[isHeaderColumn].Value = false;
dataGridView.Rows[i].Cells[isMemberColumn].Value = true;
dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.LightBlue;
}
//IF the previous row is simply a member row with no coloring at all, then remove the coloring from the current row (i).
else if (rowStatus == RowAttribute.MemberRow || rowStatus == RowAttribute.AdSpecialRow)
{
//Clear the current row of its attributes.
dataGridView.Rows[i].Cells[isHeaderColumn].Value = false;
dataGridView.Rows[i].Cells[isMemberColumn].Value = false;
dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;
}
//IF the previous row is a header row, then color it as a group header and color the current row as a member of said group.
else if (rowStatus == RowAttribute.HeaderRow)
{
//Set the previous row as a header row.
dataGridView.Rows[i - 1].Cells[isHeaderColumn].Value = true;
dataGridView.Rows[i - 1].Cells[isMemberColumn].Value = false;
dataGridView.Rows[i - 1].DefaultCellStyle.BackColor = Color.LightGray;
//Set the current row as a member row.
dataGridView.Rows[i].Cells[isHeaderColumn].Value = false;
dataGridView.Rows[i].Cells[isMemberColumn].Value = true;
dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.LightBlue;
}
//IF the previous row is incomplete, then call the stable PaintRowGroups function.
else if (rowStatus == RowAttribute.IncompleteRow)
{
PaintRowGroups(dataGridView);
}
}
//ELSE the current row is the first row in the data grid, therefore it can't be a member row so remove all coloring.
else
{
//Clear the current row of its attributes.
dataGridView.Rows[0].Cells[isHeaderColumn].Value = false;
dataGridView.Rows[0].Cells[isMemberColumn].Value = false;
dataGridView.Rows[0].DefaultCellStyle.BackColor = Color.White;
}
}
}
}
public void PaintRowGroups(DataGridView dataGridView)
{
var parser = new RowParsing();
var incompleteRowsFound = 0;
var lastHeaderIndex = -1;
var i = 0;
var adSpecialIndex = -1;
foreach (DataGridViewRow row in dataGridView.Rows)
{
//Get the current row's status.
var rowType = parser.GetRowAttribute(row);
//If the current row is not a group header, the first row in the grid, or a new row and in fact a member row...
if (i != 0 && rowType == RowAttribute.MemberRow && !row.IsNewRow && rowType != RowAttribute.IncompleteRow)
{
//Remove all coloring on the current row.
dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;
//Check to make sure the numbers are within bounds, errors occurs when an incomplete row is found at index zero (0), and the current row is one (1).
if ((i - (1 + incompleteRowsFound)) > 0)
{
//Check to see if the previous row is a header row by subtracting the number of rows that are (incomplete + 1) from the total number of rows (i).
//Adding one (1) to the incomplete count allows for checking the row right before the first incomplete row found so far to see if it's a header row.
if (parser.GetRowAttribute(dataGridView.Rows[i - (1 + incompleteRowsFound)]) == RowAttribute.HeaderRow)
{
row.DefaultCellStyle.BackColor = Color.LightBlue; //Group member
dataGridView.Rows[lastHeaderIndex].DefaultCellStyle.BackColor = Color.LightGray; //Group header
}
//Else if a header row was not found from the previous operation but a header row is set, then its safe to assume that this row can be a member.
else if (lastHeaderIndex >= 0)
{
//Check to make sure that the last header index is underneath the Ad Special Row OR that the current row (i) is before the Ad Special Index.
if (lastHeaderIndex > adSpecialIndex || i < adSpecialIndex)
{
//Assume that the current row is a member of that group header and color it as such.
row.DefaultCellStyle.BackColor = Color.LightBlue;
}
}
}
}
//If the current row is a potential group header AND the next row is as well remove the coloring from the current row, no need for checks.
else if (rowType == RowAttribute.HeaderRow && parser.GetRowAttribute(dataGridView.Rows[i + 1]) == RowAttribute.HeaderRow)
{
dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;
}
//Check to see if this row is the first row, a header index row, AND the next row is a MemberRow.
else if (rowType == RowAttribute.HeaderRow && parser.GetRowAttribute(dataGridView.Rows[i + 1]) == RowAttribute.MemberRow && i == 0)
{
//IF so, set the last header index, and color code of this row along with the next row which is a MemberRow.
lastHeaderIndex = 0;
dataGridView.Rows[0].DefaultCellStyle.BackColor = Color.LightGray;
dataGridView.Rows[i + 1].DefaultCellStyle.BackColor = Color.LightBlue;
}
//Check to see if this row is a group header.
else if (rowType == RowAttribute.HeaderRow)
{
//If so, reset the incomplete rows found count, set the lastHeaderIndex to this row's index (i) and change it's color to white.
incompleteRowsFound = 0;
lastHeaderIndex = i;
dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;
}
//If the current row is the first row in the grid AND is not a group header then remove all color from it, since its not allowed to be a header or a member.
else if (i == 0 && rowType == RowAttribute.MemberRow)
{
dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;
}
//Mark an incomplete row to determine whether or not we found one and remove any coloring it may have, incomplete rows are not allowed to be members or headers.
if (rowType == RowAttribute.IncompleteRow)
{
incompleteRowsFound++;
dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.White;
}
//
if (rowType == RowAttribute.AdSpecialRow)
{
adSpecialIndex = i;
dataGridView.Rows[i].DefaultCellStyle.BackColor = Color.Silver;
}
i++;
}//end for-each
dataGridView.Refresh();
}//End PaintRowGroups
}
public enum SalesTableColumns
{
Id = 0,
AdItem = 1,
Sold = 2,
SalePrice = 3,
TotalSales = 4,
Cost = 5,
ProfitReturn = 6,
TotalProfitReturn = 7,
IsHeaderRow = 8,
IsMemberRow = 9,
IsAdSpecialRow = 10,
IsAdSpecialMember = 11,
IsDirty = 12,
IsInDatabase = 13
}
public enum InventoryTableColumns
{
Id = 0,
AdItem = 1,
BeginningInventory = 2,
Recieved = 3,
Total = 4,
EndingInventory = 5,
IsHeaderRow = 6,
IsMemberRow = 7,
IsAdSpecialRow = 8,
IsAdSpecialMember = 9,
IsDirty = 10,
IsInDatabase = 11
}
public enum TrimmingOperationResult
{
FailedToTrim = 0,
CreatedNewInsertionTable = 1,
CreatedUpdateTable = 2,
CreatedNewInsertionAndUpdateTables = 3
}
}