protected void Recalculate()
{
int length;
if (_direction == Direction.Horizontal)
length = this.Width;
else
length = this.Height;
// Is there space for any commands?
if (length > 0)
{
// Count the number of rows needed
int rows = 0;
// Number of items on this row
int columns = 0;
// Create a collection of drawing objects
_drawCommands = new ArrayList();
// Minimum length is a gap on either side of the text
int cellMinLength = _lengthGap * 2;
// Each cell is as broad as the whole control
// int cellBreadth = this.Height;
// Accumulate starting position of each cell
int lengthStart = 0;
// If the chevron is already displayed then reduce length by its length
if (_chevronStartCommand != null)
length -= cellMinLength + _chevronLength;
// Assume chevron is not needed by default
_chevronStartCommand = null;
using(Graphics g = this.CreateGraphics())
{
// Count the item we are processing
int index = 0;
foreach(MenuCommand command in _menuCommands)
{
// Give the command a chance to update its state
command.OnUpdate(EventArgs.Empty);
// Ignore items that are marked as hidden
if (!command.Visible)
continue;
int cellLength = 0;
// Is this a separator?
if (command.Text == "-")
cellLength = _separatorWidth;
else
{
// Calculate the text width of the cell
SizeF dimension = g.MeasureString(command.Text, this.Font);
// Always add 1 to ensure that rounding is up and not down
cellLength = cellMinLength + (int)dimension.Width + 1;
}
Rectangle cellRect;
// Create a new position rectangle
if (_direction == Direction.Horizontal)
cellRect = new Rectangle(lengthStart, _rowHeight * rows, cellLength, _rowHeight);
else
cellRect = new Rectangle(_rowWidth * rows, lengthStart, _rowWidth, cellLength);
lengthStart += cellLength;
columns++;
// If this item is overlapping the control edge and it is not the first
// item on the line then we should wrap around to the next row.
if ((lengthStart > length) && (columns > 1))
{
if (_multiLine)
{
// Move to next row
rows++;
// Reset number of items on this column
columns = 1;
// Reset starting position of next item
lengthStart = cellLength;
// Reset position of this item
if (_direction == Direction.Horizontal)
{
cellRect.X = 0;
cellRect.Y += _rowHeight;
}
else
{
cellRect.X += _rowWidth;
cellRect.Y = 0;
}
}
else
{
// Is a tracked item being make invisible
if (index <= _trackItem)
{
// Need to remove tracking of this item
_trackItem = -1;
}
// Remember which item is first for the chevron submenu
_chevronStartCommand = command;
if (_direction == Direction.Horizontal)
{
cellRect.Y = 0;
cellRect.Width = cellMinLength + _chevronLength;
cellRect.X = this.Width - cellRect.Width;
cellRect.Height = _rowHeight;
}
else
{
cellRect.X = 0;
cellRect.Height = cellMinLength + _chevronLength;
cellRect.Y = this.Height - (cellMinLength + _chevronLength);
cellRect.Width = _rowWidth;
}
// Create a draw command for this chevron
_drawCommands.Add(new DrawCommand(cellRect));
// Exit, do not add the current item or any afterwards
break;
}
}
// Create a drawing object
_drawCommands.Add(new DrawCommand(command, cellRect));
index++;
}
}
if (_direction == Direction.Horizontal)
{
int controlHeight = (rows + 1) * _rowHeight;
// Ensure the control is the correct height
if (this.Height != controlHeight)
this.Height = controlHeight;
}
else
{
int controlWidth = (rows + 1) * _rowWidth;
// Ensure the control is the correct width
if (this.Width != controlWidth)
this.Width = controlWidth;
}
}
}