From 2f8eaf9183374b30b470ed6ec2ce41b009800a65 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Sun, 27 Dec 2009 13:12:28 +0000 Subject: [PATCH] Fix for text editor line heights with mixed font sizes. Added mouse position velocity to the midi keyboard. Internationalised some text used in the Button class. --- juce_amalgamated.cpp | 215 +++++++++--------- juce_amalgamated.h | 8 +- src/gui/components/buttons/juce_Button.cpp | 3 +- .../components/controls/juce_TextEditor.cpp | 178 +++++++-------- .../special/juce_MidiKeyboardComponent.cpp | 34 ++- .../special/juce_MidiKeyboardComponent.h | 8 +- 6 files changed, 221 insertions(+), 225 deletions(-) diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 2b5338cf09..5de40e5c16 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -42701,7 +42701,7 @@ const String Button::getTooltip() const String key (keyPresses.getReference(i).getTextDescription()); if (key.length() == 1) - tt << " [shortcut: '" << key << "']"; + tt << " [" << TRANS("shortcut") << ": '" << key << "']"; else tt << " [" << key << ']'; } @@ -51610,8 +51610,6 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -#define SHOULD_WRAP(x, wrapwidth) (((x) - 0.0001f) >= (wrapwidth)) - // a word or space that can't be broken down any further struct TextAtom { @@ -51976,12 +51974,11 @@ public: jassert (wordWrapWidth_ > 0); if (sections.size() > 0) + { currentSection = (const UniformTextSection*) sections.getUnchecked (sectionIndex); - if (currentSection != 0) - { - lineHeight = currentSection->font.getHeight(); - maxDescent = currentSection->font.getDescent(); + if (currentSection != 0) + beginNewLine(); } } @@ -52029,7 +52026,7 @@ public: int split; for (split = 0; split < g.getNumGlyphs(); ++split) - if (SHOULD_WRAP (g.getGlyph (split).getRight(), wordWrapWidth)) + if (shouldWrap (g.getGlyph (split).getRight())) break; if (split > 0 && split <= numRemaining) @@ -52061,9 +52058,6 @@ public: atomIndex = 0; currentSection = (const UniformTextSection*) sections.getUnchecked (sectionIndex); - - lineHeight = jmax (lineHeight, currentSection->font.getHeight()); - maxDescent = jmax (maxDescent, currentSection->font.getDescent()); } else { @@ -52094,7 +52088,7 @@ public: lineHeight2 = jmax (lineHeight2, s->font.getHeight()); maxDescent2 = jmax (maxDescent2, s->font.getDescent()); - if (SHOULD_WRAP (right, wordWrapWidth)) + if (shouldWrap (right)) { lineHeight = lineHeight2; maxDescent = maxDescent2; @@ -52116,17 +52110,14 @@ public: indexInText += atom->numChars; if (atom->isNewLine()) - { - atomX = 0; - lineY += lineHeight; - } + beginNewLine(); } atom = currentSection->getAtom (atomIndex); atomRight = atomX + atom->width; ++atomIndex; - if (SHOULD_WRAP (atomRight, wordWrapWidth) || forceNewLine) + if (shouldWrap (atomRight) || forceNewLine) { if (atom->isWhitespace()) { @@ -52135,36 +52126,78 @@ public: } else { - return wrapCurrentAtom(); + atomRight = atom->width; + + if (shouldWrap (atomRight)) // atom too big to fit on a line, so break it up.. + { + tempAtom = *atom; + tempAtom.width = 0; + tempAtom.numChars = 0; + atom = &tempAtom; + + if (atomX > 0) + beginNewLine(); + + return next(); + } + + beginNewLine(); + return true; } } return true; } - bool wrapCurrentAtom() throw() + void beginNewLine() throw() { - atomRight = atom->width; - - if (SHOULD_WRAP (atomRight, wordWrapWidth)) // atom too big to fit on a line, so break it up.. - { - tempAtom = *atom; - tempAtom.width = 0; - tempAtom.numChars = 0; - atom = &tempAtom; - - if (atomX > 0) - { - atomX = 0; - lineY += lineHeight; - } - - return next(); - } - atomX = 0; lineY += lineHeight; - return true; + + int tempSectionIndex = sectionIndex; + int tempAtomIndex = atomIndex; + const UniformTextSection* section = (const UniformTextSection*) sections.getUnchecked (tempSectionIndex); + + lineHeight = section->font.getHeight(); + maxDescent = section->font.getDescent(); + + float x = (atom != 0) ? atom->width : 0; + + while (! shouldWrap (x)) + { + if (tempSectionIndex >= sections.size()) + break; + + bool checkSize = false; + + if (tempAtomIndex >= section->getNumAtoms()) + { + if (++tempSectionIndex >= sections.size()) + break; + + tempAtomIndex = 0; + section = (const UniformTextSection*) sections.getUnchecked (tempSectionIndex); + checkSize = true; + } + + const TextAtom* const nextAtom = section->getAtom (tempAtomIndex); + + if (nextAtom == 0) + break; + + x += nextAtom->width; + + if (shouldWrap (x) || nextAtom->isNewLine()) + break; + + if (checkSize) + { + lineHeight = jmax (lineHeight, section->font.getHeight()); + maxDescent = jmax (maxDescent, section->font.getDescent()); + } + + ++tempAtomIndex; + } } void draw (Graphics& g, const UniformTextSection*& lastSection) const throw() @@ -52280,66 +52313,16 @@ public: return indexInText + j; } - void updateLineHeight() throw() - { - float x = atomRight; - - int tempSectionIndex = sectionIndex; - int tempAtomIndex = atomIndex; - const UniformTextSection* currentSection = (const UniformTextSection*) sections.getUnchecked (tempSectionIndex); - - while (! SHOULD_WRAP (x, wordWrapWidth)) - { - if (tempSectionIndex >= sections.size()) - break; - - bool checkSize = false; - - if (tempAtomIndex >= currentSection->getNumAtoms()) - { - if (++tempSectionIndex >= sections.size()) - break; - - tempAtomIndex = 0; - currentSection = (const UniformTextSection*) sections.getUnchecked (tempSectionIndex); - checkSize = true; - } - - const TextAtom* const atom = currentSection->getAtom (tempAtomIndex); - - if (atom == 0) - break; - - x += atom->width; - - if (SHOULD_WRAP (x, wordWrapWidth) || atom->isNewLine()) - break; - - if (checkSize) - { - lineHeight = jmax (lineHeight, currentSection->font.getHeight()); - maxDescent = jmax (maxDescent, currentSection->font.getDescent()); - } - - ++tempAtomIndex; - } - } - bool getCharPosition (const int index, float& cx, float& cy, float& lineHeight_) throw() { while (next()) { - if (indexInText + atom->numChars >= index) + if (indexInText + atom->numChars > index) { - updateLineHeight(); - - if (indexInText + atom->numChars > index) - { - cx = indexToX (index); - cy = lineY; - lineHeight_ = lineHeight; - return true; - } + cx = indexToX (index); + cy = lineY; + lineHeight_ = lineHeight; + return true; } } @@ -52379,6 +52362,11 @@ private: } } } + + bool shouldWrap (const float x) const throw() + { + return (x - 0.0001f) >= wordWrapWidth; + } }; class TextEditorInsertAction : public UndoableAction @@ -53263,8 +53251,6 @@ void TextEditor::drawContent (Graphics& g) while (i2.next() && i2.lineY < clip.getBottom()) { - i2.updateLineHeight(); - if (i2.lineY + i2.lineHeight >= clip.getY() && selectionEnd >= i2.indexInText && selectionStart <= i2.indexInText + i2.atom->numChars) @@ -53278,8 +53264,6 @@ void TextEditor::drawContent (Graphics& g) while (i.next() && i.lineY < clip.getBottom()) { - i.updateLineHeight(); - if (i.lineY + i.lineHeight >= clip.getY()) { if (selectionEnd >= i.indexInText @@ -54093,9 +54077,6 @@ int TextEditor::indexAtPosition (const float x, const float y) throw() while (i.next()) { - if (i.lineY + getHeight() > y) - i.updateLineHeight(); - if (i.lineY + i.lineHeight > y) { if (i.lineY > y) @@ -74576,6 +74557,7 @@ MidiKeyboardComponent::MidiKeyboardComponent (MidiKeyboardState& state_, firstKey (12 * 4), canScroll (true), mouseDragging (false), + useMousePositionForVelocity (true), keyPresses (4), keyPressNotes (16), keyMappingOctave (6), @@ -74678,9 +74660,10 @@ void MidiKeyboardComponent::setMidiChannelsToDisplay (const int midiChannelMask) triggerAsyncUpdate(); } -void MidiKeyboardComponent::setVelocity (const float velocity_) +void MidiKeyboardComponent::setVelocity (const float velocity_, const bool useMousePositionForVelocity_) { velocity = jlimit (0.0f, 1.0f, velocity_); + useMousePositionForVelocity = useMousePositionForVelocity_; } void MidiKeyboardComponent::getKeyPosition (int midiNoteNumber, const float keyWidth, int& x, int& w) const @@ -74730,7 +74713,7 @@ int MidiKeyboardComponent::getKeyStartPosition (const int midiNoteNumber) const static const uint8 whiteNotes[] = { 0, 2, 4, 5, 7, 9, 11 }; static const uint8 blackNotes[] = { 1, 3, 6, 8, 10 }; -int MidiKeyboardComponent::xyToNote (int x, int y) +int MidiKeyboardComponent::xyToNote (int x, int y, float& mousePositionVelocity) { if (! reallyContains (x, y, false)) return -1; @@ -74745,10 +74728,10 @@ int MidiKeyboardComponent::xyToNote (int x, int y) x = getHeight() - x; } - return remappedXYToNote (x + xOffset, y); + return remappedXYToNote (x + xOffset, y, mousePositionVelocity); } -int MidiKeyboardComponent::remappedXYToNote (int x, int y) const +int MidiKeyboardComponent::remappedXYToNote (int x, int y, float& mousePositionVelocity) const { if (y < blackNoteLength) { @@ -74765,7 +74748,10 @@ int MidiKeyboardComponent::remappedXYToNote (int x, int y) const kx += xOffset; if (x >= kx && x < kx + kw) + { + mousePositionVelocity = y / (float) blackNoteLength; return note; + } } } } @@ -74784,11 +74770,15 @@ int MidiKeyboardComponent::remappedXYToNote (int x, int y) const kx += xOffset; if (x >= kx && x < kx + kw) + { + mousePositionVelocity = y / (float) getHeight(); return note; + } } } } + mousePositionVelocity = 0; return -1; } @@ -75111,8 +75101,9 @@ void MidiKeyboardComponent::resized() getKeyPos (rangeEnd, endOfLastKey, kw); endOfLastKey += kw; + float mousePositionVelocity; const int spaceAvailable = w - scrollButtonW * 2; - const int lastStartKey = remappedXYToNote (endOfLastKey - spaceAvailable, 0) + 1; + const int lastStartKey = remappedXYToNote (endOfLastKey - spaceAvailable, 0, mousePositionVelocity) + 1; if (lastStartKey >= 0 && firstKey > lastStartKey) { @@ -75168,8 +75159,9 @@ void MidiKeyboardComponent::resetAnyKeysInUse() void MidiKeyboardComponent::updateNoteUnderMouse (int x, int y) { + float mousePositionVelocity; const int newNote = (mouseDragging || isMouseOver()) - ? xyToNote (x, y) : -1; + ? xyToNote (x, y, mousePositionVelocity) : -1; if (noteUnderMouse != newNote) { @@ -75181,7 +75173,10 @@ void MidiKeyboardComponent::updateNoteUnderMouse (int x, int y) if (mouseDragging && newNote >= 0) { - state.noteOn (midiChannel, newNote, velocity); + if (! useMousePositionForVelocity) + mousePositionVelocity = 1.0f; + + state.noteOn (midiChannel, newNote, mousePositionVelocity * velocity); mouseDownNote = newNote; } @@ -75204,7 +75199,8 @@ void MidiKeyboardComponent::mouseMove (const MouseEvent& e) void MidiKeyboardComponent::mouseDrag (const MouseEvent& e) { - const int newNote = xyToNote (e.x, e.y); + float mousePositionVelocity; + const int newNote = xyToNote (e.x, e.y, mousePositionVelocity); if (newNote >= 0) mouseDraggedToKey (newNote, e); @@ -75223,7 +75219,8 @@ void MidiKeyboardComponent::mouseDraggedToKey (int /*midiNoteNumber*/, const Mou void MidiKeyboardComponent::mouseDown (const MouseEvent& e) { - const int newNote = xyToNote (e.x, e.y); + float mousePositionVelocity; + const int newNote = xyToNote (e.x, e.y, mousePositionVelocity); mouseDragging = false; if (newNote >= 0 && mouseDownOnKey (newNote, e)) diff --git a/juce_amalgamated.h b/juce_amalgamated.h index f4e30cdaa2..a371ef64f5 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -53878,7 +53878,7 @@ public: @see setMidiChannel */ - void setVelocity (const float velocity); + void setVelocity (const float velocity, const bool useMousePositionForVelocity); /** Changes the midi channel number that will be used for events triggered by clicking on the component. @@ -54178,7 +54178,7 @@ private: BitArray keysPressed, keysCurrentlyDrawnDown; int rangeStart, rangeEnd, firstKey; - bool canScroll, mouseDragging; + bool canScroll, mouseDragging, useMousePositionForVelocity; Button* scrollDown; Button* scrollUp; @@ -54188,8 +54188,8 @@ private: int octaveNumForMiddleC; void getKeyPos (int midiNoteNumber, int& x, int& w) const; - int xyToNote (int x, int y); - int remappedXYToNote (int x, int y) const; + int xyToNote (int x, int y, float& mousePositionVelocity); + int remappedXYToNote (int x, int y, float& mousePositionVelocity) const; void resetAnyKeysInUse(); void updateNoteUnderMouse (int x, int y); void repaintNote (const int midiNoteNumber); diff --git a/src/gui/components/buttons/juce_Button.cpp b/src/gui/components/buttons/juce_Button.cpp index 00ac728828..5c853a68b0 100644 --- a/src/gui/components/buttons/juce_Button.cpp +++ b/src/gui/components/buttons/juce_Button.cpp @@ -30,6 +30,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_Button.h" #include "../juce_ComponentDeletionWatcher.h" #include "../keyboard/juce_KeyPressMappingSet.h" +#include "../../../text/juce_LocalisedStrings.h" //============================================================================== @@ -99,7 +100,7 @@ const String Button::getTooltip() const String key (keyPresses.getReference(i).getTextDescription()); if (key.length() == 1) - tt << " [shortcut: '" << key << "']"; + tt << " [" << TRANS("shortcut") << ": '" << key << "']"; else tt << " [" << key << ']'; } diff --git a/src/gui/components/controls/juce_TextEditor.cpp b/src/gui/components/controls/juce_TextEditor.cpp index 17a22294dc..690d418ee0 100644 --- a/src/gui/components/controls/juce_TextEditor.cpp +++ b/src/gui/components/controls/juce_TextEditor.cpp @@ -34,7 +34,6 @@ BEGIN_JUCE_NAMESPACE #include "../../../text/juce_LocalisedStrings.h" #include "../lookandfeel/juce_LookAndFeel.h" -#define SHOULD_WRAP(x, wrapwidth) (((x) - 0.0001f) >= (wrapwidth)) //============================================================================== // a word or space that can't be broken down any further @@ -406,12 +405,11 @@ public: jassert (wordWrapWidth_ > 0); if (sections.size() > 0) + { currentSection = (const UniformTextSection*) sections.getUnchecked (sectionIndex); - if (currentSection != 0) - { - lineHeight = currentSection->font.getHeight(); - maxDescent = currentSection->font.getDescent(); + if (currentSection != 0) + beginNewLine(); } } @@ -460,7 +458,7 @@ public: int split; for (split = 0; split < g.getNumGlyphs(); ++split) - if (SHOULD_WRAP (g.getGlyph (split).getRight(), wordWrapWidth)) + if (shouldWrap (g.getGlyph (split).getRight())) break; if (split > 0 && split <= numRemaining) @@ -492,9 +490,6 @@ public: atomIndex = 0; currentSection = (const UniformTextSection*) sections.getUnchecked (sectionIndex); - - lineHeight = jmax (lineHeight, currentSection->font.getHeight()); - maxDescent = jmax (maxDescent, currentSection->font.getDescent()); } else { @@ -525,7 +520,7 @@ public: lineHeight2 = jmax (lineHeight2, s->font.getHeight()); maxDescent2 = jmax (maxDescent2, s->font.getDescent()); - if (SHOULD_WRAP (right, wordWrapWidth)) + if (shouldWrap (right)) { lineHeight = lineHeight2; maxDescent = maxDescent2; @@ -547,17 +542,14 @@ public: indexInText += atom->numChars; if (atom->isNewLine()) - { - atomX = 0; - lineY += lineHeight; - } + beginNewLine(); } atom = currentSection->getAtom (atomIndex); atomRight = atomX + atom->width; ++atomIndex; - if (SHOULD_WRAP (atomRight, wordWrapWidth) || forceNewLine) + if (shouldWrap (atomRight) || forceNewLine) { if (atom->isWhitespace()) { @@ -566,36 +558,78 @@ public: } else { - return wrapCurrentAtom(); + atomRight = atom->width; + + if (shouldWrap (atomRight)) // atom too big to fit on a line, so break it up.. + { + tempAtom = *atom; + tempAtom.width = 0; + tempAtom.numChars = 0; + atom = &tempAtom; + + if (atomX > 0) + beginNewLine(); + + return next(); + } + + beginNewLine(); + return true; } } return true; } - bool wrapCurrentAtom() throw() + void beginNewLine() throw() { - atomRight = atom->width; - - if (SHOULD_WRAP (atomRight, wordWrapWidth)) // atom too big to fit on a line, so break it up.. - { - tempAtom = *atom; - tempAtom.width = 0; - tempAtom.numChars = 0; - atom = &tempAtom; - - if (atomX > 0) - { - atomX = 0; - lineY += lineHeight; - } - - return next(); - } - atomX = 0; lineY += lineHeight; - return true; + + int tempSectionIndex = sectionIndex; + int tempAtomIndex = atomIndex; + const UniformTextSection* section = (const UniformTextSection*) sections.getUnchecked (tempSectionIndex); + + lineHeight = section->font.getHeight(); + maxDescent = section->font.getDescent(); + + float x = (atom != 0) ? atom->width : 0; + + while (! shouldWrap (x)) + { + if (tempSectionIndex >= sections.size()) + break; + + bool checkSize = false; + + if (tempAtomIndex >= section->getNumAtoms()) + { + if (++tempSectionIndex >= sections.size()) + break; + + tempAtomIndex = 0; + section = (const UniformTextSection*) sections.getUnchecked (tempSectionIndex); + checkSize = true; + } + + const TextAtom* const nextAtom = section->getAtom (tempAtomIndex); + + if (nextAtom == 0) + break; + + x += nextAtom->width; + + if (shouldWrap (x) || nextAtom->isNewLine()) + break; + + if (checkSize) + { + lineHeight = jmax (lineHeight, section->font.getHeight()); + maxDescent = jmax (maxDescent, section->font.getDescent()); + } + + ++tempAtomIndex; + } } //============================================================================== @@ -714,66 +748,16 @@ public: } //============================================================================== - void updateLineHeight() throw() - { - float x = atomRight; - - int tempSectionIndex = sectionIndex; - int tempAtomIndex = atomIndex; - const UniformTextSection* currentSection = (const UniformTextSection*) sections.getUnchecked (tempSectionIndex); - - while (! SHOULD_WRAP (x, wordWrapWidth)) - { - if (tempSectionIndex >= sections.size()) - break; - - bool checkSize = false; - - if (tempAtomIndex >= currentSection->getNumAtoms()) - { - if (++tempSectionIndex >= sections.size()) - break; - - tempAtomIndex = 0; - currentSection = (const UniformTextSection*) sections.getUnchecked (tempSectionIndex); - checkSize = true; - } - - const TextAtom* const atom = currentSection->getAtom (tempAtomIndex); - - if (atom == 0) - break; - - x += atom->width; - - if (SHOULD_WRAP (x, wordWrapWidth) || atom->isNewLine()) - break; - - if (checkSize) - { - lineHeight = jmax (lineHeight, currentSection->font.getHeight()); - maxDescent = jmax (maxDescent, currentSection->font.getDescent()); - } - - ++tempAtomIndex; - } - } - bool getCharPosition (const int index, float& cx, float& cy, float& lineHeight_) throw() { while (next()) { - if (indexInText + atom->numChars >= index) + if (indexInText + atom->numChars > index) { - updateLineHeight(); - - if (indexInText + atom->numChars > index) - { - cx = indexToX (index); - cy = lineY; - lineHeight_ = lineHeight; - return true; - } + cx = indexToX (index); + cy = lineY; + lineHeight_ = lineHeight; + return true; } } @@ -814,6 +798,11 @@ private: } } } + + bool shouldWrap (const float x) const throw() + { + return (x - 0.0001f) >= wordWrapWidth; + } }; @@ -1716,8 +1705,6 @@ void TextEditor::drawContent (Graphics& g) while (i2.next() && i2.lineY < clip.getBottom()) { - i2.updateLineHeight(); - if (i2.lineY + i2.lineHeight >= clip.getY() && selectionEnd >= i2.indexInText && selectionStart <= i2.indexInText + i2.atom->numChars) @@ -1731,8 +1718,6 @@ void TextEditor::drawContent (Graphics& g) while (i.next() && i.lineY < clip.getBottom()) { - i.updateLineHeight(); - if (i.lineY + i.lineHeight >= clip.getY()) { if (selectionEnd >= i.indexInText @@ -2553,9 +2538,6 @@ int TextEditor::indexAtPosition (const float x, const float y) throw() while (i.next()) { - if (i.lineY + getHeight() > y) - i.updateLineHeight(); - if (i.lineY + i.lineHeight > y) { if (i.lineY > y) diff --git a/src/gui/components/special/juce_MidiKeyboardComponent.cpp b/src/gui/components/special/juce_MidiKeyboardComponent.cpp index 3b81141279..95657c1799 100644 --- a/src/gui/components/special/juce_MidiKeyboardComponent.cpp +++ b/src/gui/components/special/juce_MidiKeyboardComponent.cpp @@ -94,6 +94,7 @@ MidiKeyboardComponent::MidiKeyboardComponent (MidiKeyboardState& state_, firstKey (12 * 4), canScroll (true), mouseDragging (false), + useMousePositionForVelocity (true), keyPresses (4), keyPressNotes (16), keyMappingOctave (6), @@ -198,9 +199,10 @@ void MidiKeyboardComponent::setMidiChannelsToDisplay (const int midiChannelMask) triggerAsyncUpdate(); } -void MidiKeyboardComponent::setVelocity (const float velocity_) +void MidiKeyboardComponent::setVelocity (const float velocity_, const bool useMousePositionForVelocity_) { velocity = jlimit (0.0f, 1.0f, velocity_); + useMousePositionForVelocity = useMousePositionForVelocity_; } //============================================================================== @@ -251,7 +253,7 @@ int MidiKeyboardComponent::getKeyStartPosition (const int midiNoteNumber) const static const uint8 whiteNotes[] = { 0, 2, 4, 5, 7, 9, 11 }; static const uint8 blackNotes[] = { 1, 3, 6, 8, 10 }; -int MidiKeyboardComponent::xyToNote (int x, int y) +int MidiKeyboardComponent::xyToNote (int x, int y, float& mousePositionVelocity) { if (! reallyContains (x, y, false)) return -1; @@ -266,10 +268,10 @@ int MidiKeyboardComponent::xyToNote (int x, int y) x = getHeight() - x; } - return remappedXYToNote (x + xOffset, y); + return remappedXYToNote (x + xOffset, y, mousePositionVelocity); } -int MidiKeyboardComponent::remappedXYToNote (int x, int y) const +int MidiKeyboardComponent::remappedXYToNote (int x, int y, float& mousePositionVelocity) const { if (y < blackNoteLength) { @@ -286,7 +288,10 @@ int MidiKeyboardComponent::remappedXYToNote (int x, int y) const kx += xOffset; if (x >= kx && x < kx + kw) + { + mousePositionVelocity = y / (float) blackNoteLength; return note; + } } } } @@ -305,11 +310,15 @@ int MidiKeyboardComponent::remappedXYToNote (int x, int y) const kx += xOffset; if (x >= kx && x < kx + kw) + { + mousePositionVelocity = y / (float) getHeight(); return note; + } } } } + mousePositionVelocity = 0; return -1; } @@ -633,8 +642,9 @@ void MidiKeyboardComponent::resized() getKeyPos (rangeEnd, endOfLastKey, kw); endOfLastKey += kw; + float mousePositionVelocity; const int spaceAvailable = w - scrollButtonW * 2; - const int lastStartKey = remappedXYToNote (endOfLastKey - spaceAvailable, 0) + 1; + const int lastStartKey = remappedXYToNote (endOfLastKey - spaceAvailable, 0, mousePositionVelocity) + 1; if (lastStartKey >= 0 && firstKey > lastStartKey) { @@ -692,8 +702,9 @@ void MidiKeyboardComponent::resetAnyKeysInUse() void MidiKeyboardComponent::updateNoteUnderMouse (int x, int y) { + float mousePositionVelocity; const int newNote = (mouseDragging || isMouseOver()) - ? xyToNote (x, y) : -1; + ? xyToNote (x, y, mousePositionVelocity) : -1; if (noteUnderMouse != newNote) { @@ -705,7 +716,10 @@ void MidiKeyboardComponent::updateNoteUnderMouse (int x, int y) if (mouseDragging && newNote >= 0) { - state.noteOn (midiChannel, newNote, velocity); + if (! useMousePositionForVelocity) + mousePositionVelocity = 1.0f; + + state.noteOn (midiChannel, newNote, mousePositionVelocity * velocity); mouseDownNote = newNote; } @@ -728,7 +742,8 @@ void MidiKeyboardComponent::mouseMove (const MouseEvent& e) void MidiKeyboardComponent::mouseDrag (const MouseEvent& e) { - const int newNote = xyToNote (e.x, e.y); + float mousePositionVelocity; + const int newNote = xyToNote (e.x, e.y, mousePositionVelocity); if (newNote >= 0) mouseDraggedToKey (newNote, e); @@ -747,7 +762,8 @@ void MidiKeyboardComponent::mouseDraggedToKey (int /*midiNoteNumber*/, const Mou void MidiKeyboardComponent::mouseDown (const MouseEvent& e) { - const int newNote = xyToNote (e.x, e.y); + float mousePositionVelocity; + const int newNote = xyToNote (e.x, e.y, mousePositionVelocity); mouseDragging = false; if (newNote >= 0 && mouseDownOnKey (newNote, e)) diff --git a/src/gui/components/special/juce_MidiKeyboardComponent.h b/src/gui/components/special/juce_MidiKeyboardComponent.h index 756d6d92c3..26823677a8 100644 --- a/src/gui/components/special/juce_MidiKeyboardComponent.h +++ b/src/gui/components/special/juce_MidiKeyboardComponent.h @@ -89,7 +89,7 @@ public: @see setMidiChannel */ - void setVelocity (const float velocity); + void setVelocity (const float velocity, const bool useMousePositionForVelocity); /** Changes the midi channel number that will be used for events triggered by clicking on the component. @@ -395,7 +395,7 @@ private: BitArray keysPressed, keysCurrentlyDrawnDown; int rangeStart, rangeEnd, firstKey; - bool canScroll, mouseDragging; + bool canScroll, mouseDragging, useMousePositionForVelocity; Button* scrollDown; Button* scrollUp; @@ -405,8 +405,8 @@ private: int octaveNumForMiddleC; void getKeyPos (int midiNoteNumber, int& x, int& w) const; - int xyToNote (int x, int y); - int remappedXYToNote (int x, int y) const; + int xyToNote (int x, int y, float& mousePositionVelocity); + int remappedXYToNote (int x, int y, float& mousePositionVelocity) const; void resetAnyKeysInUse(); void updateNoteUnderMouse (int x, int y); void repaintNote (const int midiNoteNumber);