Code behind part 2:
private void HolderCanvas_MouseWheel(object sender, MouseWheelEventArgs e)
{
int NoMeasures = (GridDisplayWidth / DeltaTicks) / 4;
ScaleFactorX = Math.Min(Math.Max(ScaleFactorX + (e.Delta / 2000), 1), NoMeasures / 2);
ScalePianoRoll();
}
Path SelectedNotePath;
NoteOnEvent SelectedNote;
double CursorY;
double CursorX;
bool MouseDownOnNote;
RectangleGeometry SelRectGeom;
double SelRectTop;
double SelRectLeft;
public event NotesChangedEventHandler NotesChanged;
public delegate void NotesChangedEventHandler();
private void MouseUpInNote(object sender, MouseButtonEventArgs e)
{
MouseDownOnNote = false;
SelectedNotePath.ReleaseMouseCapture();
if (NotesChanged != null) {
NotesChanged();
}
}
private bool GetNoteFromGeom(MidiEvent midev)
{
bool IsNote = false;
if (midev.GetType == typeof(NoteOnEvent)) {
NoteOnEvent midnoteonev = (NoteOnEvent)midev;
IsNote = (SelRectGeom.Rect.Left == (midnoteonev.AbsoluteTime * xScale)) & (SelRectGeom.Rect.Top == ((127 - midnoteonev.NoteNumber) * yScale + 1));
//IsNote = IsNote And SelRectGeom.Rect.Width = midnoteonev.NoteLength * xScale 'not necessary - enough to just get the x and y locations
}
return IsNote;
}
private void MouseDownInNote(object sender, MouseButtonEventArgs e)
{
MouseDownOnNote = true;
CursorY = e.GetPosition(sender).Y;
CursorX = e.GetPosition(sender).X;
SelectedNotePath = (Path)sender;
SelRectGeom = SelectedNotePath.Data;
SelRectTop = SelRectGeom.Rect.Y;
SelRectLeft = SelRectGeom.Rect.X;
SelectedNote = MidiEvents.Find(GetNoteFromGeom);
SelectedNotePath.CaptureMouse();
Canvas.SetZIndex(SelectedNotePath, NoteCanvas.Children.Count);
//show this note above all other notes
}
private void MouseMoveNote(object sender, MouseEventArgs e)
{
if (MouseDownOnNote) {
//Snap mouse y position to nearest note and limit to between 0-127
SelectedNote.NoteNumber = Math.Min(Math.Max(127 - Conversion.Int((SelRectTop + e.GetPosition(sender).Y - CursorY) / yScale), 0), 127);
int NewPos = SelRectLeft / xScale + (e.GetPosition(sender).X - CursorX) / (xScale * ScaleFactorX);
//Get the nearest snap position and limit to within max/min range
int SnapPosition = Math.Min(Math.Max(0, (NewPos - Conversion.Int(NewPos % NoteSnapTo))), lastPosition - Conversion.Int(lastPosition % NoteSnapTo));
int prevselnotetime = SelectedNote.AbsoluteTime;
SelectedNote.AbsoluteTime = SnapPosition;
SelectedNote.OffEvent.AbsoluteTime += (SelectedNote.AbsoluteTime - prevselnotetime);
SelRectGeom.Rect = new Rect(Convert.ToDouble(SelectedNote.AbsoluteTime) * xScale, Convert.ToDouble(127 - SelectedNote.NoteNumber) * yScale + 1, Convert.ToDouble(SelectedNote.NoteLength) * xScale, (yScale - 1));
}
//Scroll with mouse drag
if (e.GetPosition(UDScrollViewer).Y < 0) {
UDScrollViewer.ScrollToVerticalOffset(UDScrollViewer.VerticalOffset - 0.1);
}
if (e.GetPosition(UDScrollViewer).Y > UDScrollViewer.ActualHeight) {
UDScrollViewer.ScrollToVerticalOffset(UDScrollViewer.VerticalOffset + 0.1);
}
if (e.GetPosition(RLScrollViewer).X < 0) {
RLScrollBar.Value -= 0.001;
}
if (e.GetPosition(RLScrollViewer).X > RLScrollViewer.ActualWidth) {
RLScrollBar.Value += 0.001;
}
}
private void MouseEnterNote(object sender, MouseEventArgs e)
{
dynamic thisNotePath = (Path)sender;
thisNotePath.Fill = SelectedNoteBrush;
}
private void MouseLeaveNote(object sender, MouseEventArgs e)
{
dynamic thisNotePath = (Path)sender;
thisNotePath.Fill = NoteBrush;
}
int NoteSnapTo = 1;
private void SnapToCB_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
switch (SnapToCB.SelectedValue.ToString) {
case "Snap":
NoteSnapTo = 1;
break;
case "1/2 note":
NoteSnapTo = DeltaTicks * 2;
break;
case "1/4 note":
NoteSnapTo = DeltaTicks;
break;
case "1/8 note":
NoteSnapTo = DeltaTicks / 2;
break;
case "1/16 note":
NoteSnapTo = DeltaTicks / 4;
break;
}
}
}