public override void DoLayout()
{
_infos.Sort((a, b) => a.Line.CompareTo(b.Line));
const int padding = 0; // Std.int(4 * getScale());
var displacedX = 0f;
var lastDisplaced = false;
var lastLine = 0;
var anyDisplaced = false;
var direction = Direction;
var w = 0f;
for (int i = 0, j = _infos.Count; i < j; i++)
{
var g = _infos[i].Glyph;
g.Renderer = Renderer;
g.DoLayout();
var displace = false;
if (i == 0)
{
displacedX = g.Width + padding;
}
else
{
// check if note needs to be repositioned
if (Math.Abs(lastLine - _infos[i].Line) <= 1)
{
// reposition if needed
if (!lastDisplaced)
{
displace = true;
g.X = displacedX - (Scale);
anyDisplaced = true;
lastDisplaced = true; // let next iteration know we are displace now
}
else
{
lastDisplaced = false; // let next iteration know that we weren't displaced now
}
}
else // offset is big enough? no displacing needed
{
lastDisplaced = false;
}
}
// for beat direction down we invert the displacement.
// this means: displaced is on the left side of the stem and not displaced is right
if (direction == BeamDirection.Down)
{
g.X = displace
? padding
: displacedX;
}
else
{
g.X = displace
? displacedX
: padding;
}
lastLine = _infos[i].Line;
w = Math.Max(w, g.X + g.Width);
}
if (anyDisplaced)
{
_noteHeadPadding = 0;
UpLineX = displacedX;
DownLineX = displacedX;
}
else
{
_noteHeadPadding = direction == BeamDirection.Down ? -displacedX : 0;
w += _noteHeadPadding;
UpLineX = w;
DownLineX = padding;
}
foreach (var effectKey in BeatEffects)
{
var effect = BeatEffects[effectKey];
effect.Renderer = Renderer;
effect.DoLayout();
}
if (Beat.IsTremolo)
{
int offset;
var baseNote = direction == BeamDirection.Up ? MinNote : MaxNote;
var tremoloX = direction == BeamDirection.Up ? displacedX : 0;
var speed = Beat.TremoloSpeed.Value;
switch (speed)
{
case Duration.ThirtySecond:
offset = direction == BeamDirection.Up ? -15 : 15;
break;
case Duration.Sixteenth:
offset = direction == BeamDirection.Up ? -12 : 15;
break;
case Duration.Eighth:
offset = direction == BeamDirection.Up ? -10 : 10;
break;
default:
offset = direction == BeamDirection.Up ? -10 : 15;
break;
}
_tremoloPicking = new TremoloPickingGlyph(tremoloX, baseNote.Glyph.Y + offset * Scale, Beat.TremoloSpeed.Value);
_tremoloPicking.Renderer = Renderer;
_tremoloPicking.DoLayout();
}
Width = w + padding;
}