void MidiKeyboardComponent::updateNoteUnderMouse (const Point<int>& pos)
{
    float mousePositionVelocity = 0.0f;
    const int newNote = (mouseDragging || isMouseOver())
                            ? xyToNote (pos, mousePositionVelocity) : -1;

    if (noteUnderMouse != newNote)
    {
        if (mouseDownNote >= 0)
        {
            state.noteOff (midiChannel, mouseDownNote);
            mouseDownNote = -1;
        }

        if (mouseDragging && newNote >= 0)
        {
            if (! useMousePositionForVelocity)
                mousePositionVelocity = 1.0f;

            state.noteOn (midiChannel, newNote, mousePositionVelocity * velocity);
            mouseDownNote = newNote;
        }

        repaintNote (noteUnderMouse);
        noteUnderMouse = newNote;
        repaintNote (noteUnderMouse);
    }
    else if (mouseDownNote >= 0 && ! mouseDragging)
    {
        state.noteOff (midiChannel, mouseDownNote);
        mouseDownNote = -1;
    }
}
void MidiKeyboardComponent::mouseDrag (const MouseEvent& e)
{
    float mousePositionVelocity;
    const int newNote = xyToNote (e.getPosition(), mousePositionVelocity);

    if (newNote >= 0)
        mouseDraggedToKey (newNote, e);

    updateNoteUnderMouse (e.getPosition());
}
void MidiKeyboardComponent::mouseDrag (const MouseEvent& e)
{
    float mousePositionVelocity;
    auto newNote = xyToNote (e.position, mousePositionVelocity);

    if (newNote >= 0)
        mouseDraggedToKey (newNote, e);

    updateNoteUnderMouse (e, true);
}
void MidiKeyboardComponent::mouseUp (const MouseEvent& e)
{
    updateNoteUnderMouse (e, false);
    shouldCheckMousePos = false;

    float mousePositionVelocity;
    auto note = xyToNote (e.position, mousePositionVelocity);

    if (note >= 0)
        mouseUpOnKey (note, e);
}
void MidiKeyboardComponent::mouseDown (const MouseEvent& e)
{
    float mousePositionVelocity;
    auto newNote = xyToNote (e.position, mousePositionVelocity);

    if (newNote >= 0 && mouseDownOnKey (newNote, e))
    {
        updateNoteUnderMouse (e, true);
        shouldCheckMousePos = true;
    }
}
void GuitarNeckComponent::mouseDrag (const MouseEvent& e)
{
    float mousePositionVelocity;
    const FrettedNote newNote = xyToNote (e.getPosition(), mousePositionVelocity);

	if (newNote.isValid())
		mouseDraggedToKey (newNote.fret,newNote.string, e);

    updateNoteUnderMouse (e.getPosition());
	repaint();
}
void MidiKeyboardComponent::mouseDown (const MouseEvent& e)
{
    float mousePositionVelocity;
    const int newNote = xyToNote (e.getPosition(), mousePositionVelocity);
    mouseDragging = false;

    if (newNote >= 0 && mouseDownOnKey (newNote, e))
    {
        repaintNote (noteUnderMouse);
        noteUnderMouse = -1;
        mouseDragging = true;

        updateNoteUnderMouse (e.getPosition());
        startTimer (500);
    }
}
void MidiKeyboardComponent::updateNoteUnderMouse (const Point<int>& pos, bool isDown, int fingerNum)
{
    float mousePositionVelocity = 0.0f;
    const int newNote = xyToNote (pos, mousePositionVelocity);
    const int oldNote = mouseOverNotes.getUnchecked (fingerNum);

    if (oldNote != newNote)
    {
        repaintNote (oldNote);
        repaintNote (newNote);
        mouseOverNotes.set (fingerNum, newNote);
    }

    int oldNoteDown = mouseDownNotes.getUnchecked (fingerNum);

    if (isDown)
    {
        if (newNote != oldNoteDown)
        {
            if (oldNoteDown >= 0)
            {
                mouseDownNotes.set (fingerNum, -1);

                if (! mouseDownNotes.contains (oldNoteDown))
                    state.noteOff (midiChannel, oldNoteDown);
            }

            if (newNote >= 0)
            {
                if (! useMousePositionForVelocity)
                    mousePositionVelocity = 1.0f;

                state.noteOn (midiChannel, newNote, mousePositionVelocity * velocity);
                mouseDownNotes.set (fingerNum, newNote);
            }
        }
    }
    else if (oldNoteDown >= 0)
    {
        mouseDownNotes.set (fingerNum, -1);

        if (! mouseDownNotes.contains (oldNoteDown))
            state.noteOff (midiChannel, oldNoteDown);
    }
}
void GuitarNeckComponent::mouseDown (const MouseEvent& e)
{
    float mousePositionVelocity;
    const FrettedNote newNote = xyToNote (e.getPosition(), mousePositionVelocity);
    mouseDragging = false;

	if (newNote.isValid() && mouseDownOnKey (newNote.fret,newNote.string, e))
    {
		//repaintNote (noteUnderMouse.fret);
		noteUnderMouse.invalidate();
        mouseDragging = true;

		currentlyFrettedFret[newNote.string]=newNote.fret;
        updateNoteUnderMouse (e.getPosition());
        startTimer (500);
		repaint();
    }
}
void MidiKeyboardComponent::updateNoteUnderMouse (Point<float> pos, bool isDown, int fingerNum)
{
    float mousePositionVelocity = 0.0f;
    auto newNote = xyToNote (pos, mousePositionVelocity);
    auto oldNote = mouseOverNotes.getUnchecked (fingerNum);
    auto oldNoteDown = mouseDownNotes.getUnchecked (fingerNum);
    auto eventVelocity = useMousePositionForVelocity ? mousePositionVelocity * velocity : velocity;

    if (oldNote != newNote)
    {
        repaintNote (oldNote);
        repaintNote (newNote);
        mouseOverNotes.set (fingerNum, newNote);
    }

    if (isDown)
    {
        if (newNote != oldNoteDown)
        {
            if (oldNoteDown >= 0)
            {
                mouseDownNotes.set (fingerNum, -1);

                if (! mouseDownNotes.contains (oldNoteDown))
                    state.noteOff (midiChannel, oldNoteDown, eventVelocity);
            }

            if (newNote >= 0 && ! mouseDownNotes.contains (newNote))
            {
                state.noteOn (midiChannel, newNote, eventVelocity);
                mouseDownNotes.set (fingerNum, newNote);
            }
        }
    }
    else if (oldNoteDown >= 0)
    {
        mouseDownNotes.set (fingerNum, -1);

        if (! mouseDownNotes.contains (oldNoteDown))
            state.noteOff (midiChannel, oldNoteDown, eventVelocity);
    }
}
void GuitarNeckComponent::updateNoteUnderMouse (const Point<int>& pos)
{
    float mousePositionVelocity = 0.0f;
    const FrettedNote newNote = (mouseDragging || isMouseOver())
                            ? xyToNote (pos, mousePositionVelocity) : FrettedNote();

    if (noteUnderMouse != newNote)
    {
        if (mouseDownNote.isValid())
        {
			//state.noteOff (mouseDownNote.string+1, getNote(mouseDownNote));
			currentlyFrettedFret[newNote.string]=-1;
			mouseDownNote.invalidate();
        }

		if (mouseDragging && newNote.isValid())
        {
            //if (! useMousePositionForVelocity)
                mousePositionVelocity = 1.0f;

			//state.noteOn (newNote.string+1, getNote(newNote), mousePositionVelocity * velocity);
			int oldFret = currentlyFrettedFret[newNote.string];
			currentlyFrettedFret[newNote.string] = newNote.fret;
			repaintNote(oldFret);
            mouseDownNote = newNote;
        }

		repaintNote (noteUnderMouse.fret);
        noteUnderMouse = newNote;
		repaintNote (noteUnderMouse.fret);
    }
	else if (mouseDownNote.isValid() && ! mouseDragging)
    {
		//state.noteOff (mouseDownNote.string+1, getNote(mouseDownNote));
		//currentlyFrettedFret[newNote.string]=-1;
		mouseDownNote.invalidate();
    }
}
int MidiKeyboardComponent::getNoteAtPosition (Point<float> p)
{
    float v;
    return xyToNote (p, v);
}