int MidiKeyboardComponent::remappedXYToNote (const Point<int>& pos, float& mousePositionVelocity) const { if (pos.getY() < blackNoteLength) { for (int octaveStart = 12 * (rangeStart / 12); octaveStart <= rangeEnd; octaveStart += 12) { for (int i = 0; i < 5; ++i) { const int note = octaveStart + blackNotes [i]; if (note >= rangeStart && note <= rangeEnd) { int kx, kw; getKeyPos (note, kx, kw); kx += xOffset; if (pos.getX() >= kx && pos.getX() < kx + kw) { mousePositionVelocity = pos.getY() / (float) blackNoteLength; return note; } } } } } for (int octaveStart = 12 * (rangeStart / 12); octaveStart <= rangeEnd; octaveStart += 12) { for (int i = 0; i < 7; ++i) { const int note = octaveStart + whiteNotes [i]; if (note >= rangeStart && note <= rangeEnd) { int kx, kw; getKeyPos (note, kx, kw); kx += xOffset; if (pos.getX() >= kx && pos.getX() < kx + kw) { const int whiteNoteLength = (orientation == horizontalKeyboard) ? getHeight() : getWidth(); mousePositionVelocity = pos.getY() / (float) whiteNoteLength; return note; } } } } mousePositionVelocity = 0; return -1; }
Rectangle<float> MidiKeyboardComponent::getRectangleForKey (int note) const { jassert (note >= rangeStart && note <= rangeEnd); auto pos = getKeyPos (note); auto x = pos.getStart(); auto w = pos.getLength(); if (MidiMessage::isMidiNoteBlack (note)) { auto blackNoteLength = getBlackNoteLength(); switch (orientation) { case horizontalKeyboard: return { x, 0, w, blackNoteLength }; case verticalKeyboardFacingLeft: return { getWidth() - blackNoteLength, x, blackNoteLength, w }; case verticalKeyboardFacingRight: return { 0, getHeight() - x - w, blackNoteLength, w }; default: jassertfalse; break; } } else { switch (orientation) { case horizontalKeyboard: return { x, 0, w, (float) getHeight() }; case verticalKeyboardFacingLeft: return { 0, x, (float) getWidth(), w }; case verticalKeyboardFacingRight: return { 0, getHeight() - x - w, (float) getWidth(), w }; default: jassertfalse; break; } } return {}; }
/** * insertKeyVal: inserted the pair keys - val, these keys must be haven't set yet! * @keys the keys * @keynum number of keys passed in * @val value for these keys */ bool MapArraySR::insertKeyVal( int* keys, int keynum, bool issorted,int value ) { int* ikeys = new int[ keynum ]; memcpy( ikeys, keys, sizeof( int ) * keynum ); int pos = 0; if( !getKeyPos( ikeys, keynum ,issorted, pos)) { cout<<"Unable to compute the position for the keys!"<<endl; delete []ikeys; return false; } ////////////////////////////////////////////////////////////////////////// //cout<<"pos:"<<pos<<endl; ////////////////////////////////////////////////////////////////////////// if( posinval[ pos ] != -1 ) { cout<<"These keys have already been set!"<<endl; delete []ikeys; return false; } val.push_back( value ); posinval[ pos ] = val.size() - 1; delete []ikeys; return true; }
/** * insertKeyVal: inserted the pair keys - val, value for these keys will be replaced if exists, otherwise, set it! * @keys the keys * @keynum number of keys passed in * @val value for these keys */ bool MapArraySR::replaceKeyVal( int* keys, int keynum,bool issorted, int value ) { int* ikeys = new int[ keynum ]; memcpy( ikeys, keys, sizeof( int ) * keynum ); //compute the position int pos = 0; if( !getKeyPos( ikeys, keynum , issorted,pos)) { cout<<"Unable to compute the position for the keys!"<<endl; delete []ikeys; return false; } if( posinval[ pos ] != -1 ) { val[ posinval[ pos ] ] = value; } else { val.push_back( value ); posinval[ pos ] = val.size() - 1; } delete []ikeys; return true; }
int MidiKeyboardComponent::remappedXYToNote (Point<float> pos, float& mousePositionVelocity) const { auto blackNoteLength = getBlackNoteLength(); if (pos.getY() < blackNoteLength) { for (int octaveStart = 12 * (rangeStart / 12); octaveStart <= rangeEnd; octaveStart += 12) { for (int i = 0; i < 5; ++i) { auto note = octaveStart + blackNotes[i]; if (note >= rangeStart && note <= rangeEnd) { if (getKeyPos (note).contains (pos.x - xOffset)) { mousePositionVelocity = jmax (0.0f, pos.y / blackNoteLength); return note; } } } } } for (int octaveStart = 12 * (rangeStart / 12); octaveStart <= rangeEnd; octaveStart += 12) { for (int i = 0; i < 7; ++i) { auto note = octaveStart + whiteNotes[i]; if (note >= rangeStart && note <= rangeEnd) { if (getKeyPos (note).contains (pos.x - xOffset)) { auto whiteNoteLength = (orientation == horizontalKeyboard) ? getHeight() : getWidth(); mousePositionVelocity = jmax (0.0f, pos.y / (float) whiteNoteLength); return note; } } } } mousePositionVelocity = 0; return -1; }
//============================================================================== void MidiKeyboardComponent::repaintNote (const int noteNum) { if (noteNum >= rangeStart && noteNum <= rangeEnd) { int x, w; getKeyPos (noteNum, x, w); if (orientation == horizontalKeyboard) repaint (x, 0, w, getHeight()); else if (orientation == verticalKeyboardFacingLeft) repaint (0, x, getWidth(), w); else if (orientation == verticalKeyboardFacingRight) repaint (0, getHeight() - x - w, getWidth(), w); } }
Rectangle<int> MidiKeyboardComponent::getWhiteNotePos (int noteNum) const { int x, w; getKeyPos (noteNum, x, w); Rectangle<int> pos; switch (orientation) { case horizontalKeyboard: pos.setBounds (x, 0, w, getHeight()); break; case verticalKeyboardFacingLeft: pos.setBounds (0, x, getWidth(), w); break; case verticalKeyboardFacingRight: pos.setBounds (0, getHeight() - x - w, getWidth(), w); break; default: break; } return pos; }
bool MapArraySR::getKeyVal(int * keys, int keynum,bool issorted, int& value ) { int* ikeys = new int[ keynum ]; memcpy( ikeys, keys, sizeof( int ) * keynum ); //compute the position int pos = 0; if( !getKeyPos( ikeys, keynum ,issorted, pos)) { cout<<"Unable to compute the position for the keys!"<<endl; delete []ikeys; return false; } value = posinval[ pos ]; if( value == -1 ) //no corresponding value to these keys { delete []ikeys; return false; } value = val[ value ]; //the real value to these keys delete []ikeys; return true; }
void MidiKeyboardComponent::resized() { int w = getWidth(); int h = getHeight(); if (w > 0 && h > 0) { if (orientation != horizontalKeyboard) std::swap (w, h); blackNoteLength = roundToInt (h * 0.7f); int kx2, kw2; getKeyPos (rangeEnd, kx2, kw2); kx2 += kw2; if (firstKey != rangeStart) { int kx1, kw1; getKeyPos (rangeStart, kx1, kw1); if (kx2 - kx1 <= w) { firstKey = rangeStart; sendChangeMessage(); repaint(); } } const bool showScrollButtons = canScroll && (firstKey > rangeStart || kx2 > w + xOffset * 2); scrollDown->setVisible (showScrollButtons); scrollUp->setVisible (showScrollButtons); xOffset = 0; if (showScrollButtons) { const int scrollButtonW = jmin (12, w / 2); if (orientation == horizontalKeyboard) { scrollDown->setBounds (0, 0, scrollButtonW, getHeight()); scrollUp->setBounds (getWidth() - scrollButtonW, 0, scrollButtonW, getHeight()); } else if (orientation == verticalKeyboardFacingLeft) { scrollDown->setBounds (0, 0, getWidth(), scrollButtonW); scrollUp->setBounds (0, getHeight() - scrollButtonW, getWidth(), scrollButtonW); } else if (orientation == verticalKeyboardFacingRight) { scrollDown->setBounds (0, getHeight() - scrollButtonW, getWidth(), scrollButtonW); scrollUp->setBounds (0, 0, getWidth(), scrollButtonW); } int endOfLastKey, kw; getKeyPos (rangeEnd, endOfLastKey, kw); endOfLastKey += kw; float mousePositionVelocity; const int spaceAvailable = w - scrollButtonW * 2; const int lastStartKey = remappedXYToNote (Point<int> (endOfLastKey - spaceAvailable, 0), mousePositionVelocity) + 1; if (lastStartKey >= 0 && firstKey > lastStartKey) { firstKey = jlimit (rangeStart, rangeEnd, lastStartKey); sendChangeMessage(); } int newOffset = 0; getKeyPos (firstKey, newOffset, kw); xOffset = newOffset - scrollButtonW; } else { firstKey = rangeStart; } timerCallback(); repaint(); } }
void MidiKeyboardComponent::paint (Graphics& g) { g.fillAll (Colours::white.overlaidWith (findColour (whiteNoteColourId))); const Colour lineColour (findColour (keySeparatorLineColourId)); const Colour textColour (findColour (textLabelColourId)); int x, w, octave; for (octave = 0; octave < 128; octave += 12) { for (int white = 0; white < 7; ++white) { const int noteNum = octave + whiteNotes [white]; if (noteNum >= rangeStart && noteNum <= rangeEnd) { getKeyPos (noteNum, x, w); if (orientation == horizontalKeyboard) drawWhiteNote (noteNum, g, x, 0, w, getHeight(), state.isNoteOnForChannels (midiInChannelMask, noteNum), noteUnderMouse == noteNum, lineColour, textColour); else if (orientation == verticalKeyboardFacingLeft) drawWhiteNote (noteNum, g, 0, x, getWidth(), w, state.isNoteOnForChannels (midiInChannelMask, noteNum), noteUnderMouse == noteNum, lineColour, textColour); else if (orientation == verticalKeyboardFacingRight) drawWhiteNote (noteNum, g, 0, getHeight() - x - w, getWidth(), w, state.isNoteOnForChannels (midiInChannelMask, noteNum), noteUnderMouse == noteNum, lineColour, textColour); } } } float x1 = 0.0f, y1 = 0.0f, x2 = 0.0f, y2 = 0.0f; if (orientation == verticalKeyboardFacingLeft) { x1 = getWidth() - 1.0f; x2 = getWidth() - 5.0f; } else if (orientation == verticalKeyboardFacingRight) x2 = 5.0f; else y2 = 5.0f; g.setGradientFill (ColourGradient (Colours::black.withAlpha (0.3f), x1, y1, Colours::transparentBlack, x2, y2, false)); getKeyPos (rangeEnd, x, w); x += w; if (orientation == verticalKeyboardFacingLeft) g.fillRect (getWidth() - 5, 0, 5, x); else if (orientation == verticalKeyboardFacingRight) g.fillRect (0, 0, 5, x); else g.fillRect (0, 0, x, 5); g.setColour (lineColour); if (orientation == verticalKeyboardFacingLeft) g.fillRect (0, 0, 1, x); else if (orientation == verticalKeyboardFacingRight) g.fillRect (getWidth() - 1, 0, 1, x); else g.fillRect (0, getHeight() - 1, x, 1); const Colour blackNoteColour (findColour (blackNoteColourId)); for (octave = 0; octave < 128; octave += 12) { for (int black = 0; black < 5; ++black) { const int noteNum = octave + blackNotes [black]; if (noteNum >= rangeStart && noteNum <= rangeEnd) { getKeyPos (noteNum, x, w); if (orientation == horizontalKeyboard) drawBlackNote (noteNum, g, x, 0, w, blackNoteLength, state.isNoteOnForChannels (midiInChannelMask, noteNum), noteUnderMouse == noteNum, blackNoteColour); else if (orientation == verticalKeyboardFacingLeft) drawBlackNote (noteNum, g, getWidth() - blackNoteLength, x, blackNoteLength, w, state.isNoteOnForChannels (midiInChannelMask, noteNum), noteUnderMouse == noteNum, blackNoteColour); else if (orientation == verticalKeyboardFacingRight) drawBlackNote (noteNum, g, 0, getHeight() - x - w, blackNoteLength, w, state.isNoteOnForChannels (midiInChannelMask, noteNum), noteUnderMouse == noteNum, blackNoteColour); } } } }
int MidiKeyboardComponent::getKeyStartPosition (const int midiNoteNumber) const { int x, y; getKeyPos (midiNoteNumber, x, y); return x; }
void MidiKeyboardComponent::resized() { auto w = getWidth(); auto h = getHeight(); if (w > 0 && h > 0) { if (orientation != horizontalKeyboard) std::swap (w, h); auto kx2 = getKeyPos (rangeEnd).getEnd(); if ((int) firstKey != rangeStart) { auto kx1 = getKeyPos (rangeStart).getStart(); if (kx2 - kx1 <= w) { firstKey = (float) rangeStart; sendChangeMessage(); repaint(); } } scrollDown->setVisible (canScroll && firstKey > (float) rangeStart); xOffset = 0; if (canScroll) { auto scrollButtonW = jmin (scrollButtonWidth, w / 2); auto r = getLocalBounds(); if (orientation == horizontalKeyboard) { scrollDown->setBounds (r.removeFromLeft (scrollButtonW)); scrollUp ->setBounds (r.removeFromRight (scrollButtonW)); } else if (orientation == verticalKeyboardFacingLeft) { scrollDown->setBounds (r.removeFromTop (scrollButtonW)); scrollUp ->setBounds (r.removeFromBottom (scrollButtonW)); } else { scrollDown->setBounds (r.removeFromBottom (scrollButtonW)); scrollUp ->setBounds (r.removeFromTop (scrollButtonW)); } auto endOfLastKey = getKeyPos (rangeEnd).getEnd(); float mousePositionVelocity; auto spaceAvailable = w; auto lastStartKey = remappedXYToNote ({ endOfLastKey - spaceAvailable, 0 }, mousePositionVelocity) + 1; if (lastStartKey >= 0 && ((int) firstKey) > lastStartKey) { firstKey = (float) jlimit (rangeStart, rangeEnd, lastStartKey); sendChangeMessage(); } xOffset = getKeyPos ((int) firstKey).getStart(); } else { firstKey = (float) rangeStart; } scrollUp->setVisible (canScroll && getKeyPos (rangeEnd).getStart() > w); repaint(); } }
void MidiKeyboardComponent::paint (Graphics& g) { g.fillAll (findColour (whiteNoteColourId)); auto lineColour = findColour (keySeparatorLineColourId); auto textColour = findColour (textLabelColourId); for (int octave = 0; octave < 128; octave += 12) { for (int white = 0; white < 7; ++white) { auto noteNum = octave + whiteNotes[white]; if (noteNum >= rangeStart && noteNum <= rangeEnd) drawWhiteNote (noteNum, g, getRectangleForKey (noteNum), state.isNoteOnForChannels (midiInChannelMask, noteNum), mouseOverNotes.contains (noteNum), lineColour, textColour); } } float x1 = 0.0f, y1 = 0.0f, x2 = 0.0f, y2 = 0.0f; auto width = getWidth(); auto height = getHeight(); if (orientation == verticalKeyboardFacingLeft) { x1 = width - 1.0f; x2 = width - 5.0f; } else if (orientation == verticalKeyboardFacingRight) x2 = 5.0f; else y2 = 5.0f; auto x = getKeyPos (rangeEnd).getEnd(); auto shadowCol = findColour (shadowColourId); if (! shadowCol.isTransparent()) { g.setGradientFill (ColourGradient (shadowCol, x1, y1, shadowCol.withAlpha (0.0f), x2, y2, false)); switch (orientation) { case horizontalKeyboard: g.fillRect (0.0f, 0.0f, x, 5.0f); break; case verticalKeyboardFacingLeft: g.fillRect (width - 5.0f, 0.0f, 5.0f, x); break; case verticalKeyboardFacingRight: g.fillRect (0.0f, 0.0f, 5.0f, x); break; default: break; } } if (! lineColour.isTransparent()) { g.setColour (lineColour); switch (orientation) { case horizontalKeyboard: g.fillRect (0.0f, height - 1.0f, x, 1.0f); break; case verticalKeyboardFacingLeft: g.fillRect (0.0f, 0.0f, 1.0f, x); break; case verticalKeyboardFacingRight: g.fillRect (width - 1.0f, 0.0f, 1.0f, x); break; default: break; } } auto blackNoteColour = findColour (blackNoteColourId); for (int octave = 0; octave < 128; octave += 12) { for (int black = 0; black < 5; ++black) { auto noteNum = octave + blackNotes[black]; if (noteNum >= rangeStart && noteNum <= rangeEnd) drawBlackNote (noteNum, g, getRectangleForKey (noteNum), state.isNoteOnForChannels (midiInChannelMask, noteNum), mouseOverNotes.contains (noteNum), blackNoteColour); } } }
float MidiKeyboardComponent::getTotalKeyboardWidth() const noexcept { return getKeyPos (rangeEnd).getEnd(); }
float MidiKeyboardComponent::getKeyStartPosition (int midiNoteNumber) const { return getKeyPos (midiNoteNumber).getStart(); }
void MidiKeyboardComponent::paint (Graphics& g) { g.fillAll (Colours::white.overlaidWith (findColour (whiteNoteColourId))); const Colour lineColour (findColour (keySeparatorLineColourId)); const Colour textColour (findColour (textLabelColourId)); int x, w, octave; for (octave = 0; octave < 128; octave += 12) { for (int white = 0; white < 7; ++white) { const int noteNum = octave + whiteNotes [white]; if (noteNum >= rangeStart && noteNum <= rangeEnd) { const Rectangle<int> pos (getWhiteNotePos (noteNum)); drawWhiteNote (noteNum, g, pos.getX(), pos.getY(), pos.getWidth(), pos.getHeight(), state.isNoteOnForChannels (midiInChannelMask, noteNum), mouseOverNotes.contains (noteNum), lineColour, textColour); } } } float x1 = 0.0f, y1 = 0.0f, x2 = 0.0f, y2 = 0.0f; if (orientation == verticalKeyboardFacingLeft) { x1 = getWidth() - 1.0f; x2 = getWidth() - 5.0f; } else if (orientation == verticalKeyboardFacingRight) x2 = 5.0f; else y2 = 5.0f; g.setGradientFill (ColourGradient (Colours::black.withAlpha (0.3f), x1, y1, Colours::transparentBlack, x2, y2, false)); getKeyPos (rangeEnd, x, w); x += w; switch (orientation) { case horizontalKeyboard: g.fillRect (0, 0, x, 5); break; case verticalKeyboardFacingLeft: g.fillRect (getWidth() - 5, 0, 5, x); break; case verticalKeyboardFacingRight: g.fillRect (0, 0, 5, x); break; default: break; } g.setColour (lineColour); switch (orientation) { case horizontalKeyboard: g.fillRect (0, getHeight() - 1, x, 1); break; case verticalKeyboardFacingLeft: g.fillRect (0, 0, 1, x); break; case verticalKeyboardFacingRight: g.fillRect (getWidth() - 1, 0, 1, x); break; default: break; } const Colour blackNoteColour (findColour (blackNoteColourId)); for (octave = 0; octave < 128; octave += 12) { for (int black = 0; black < 5; ++black) { const int noteNum = octave + blackNotes [black]; if (noteNum >= rangeStart && noteNum <= rangeEnd) { getKeyPos (noteNum, x, w); Rectangle<int> pos; switch (orientation) { case horizontalKeyboard: pos.setBounds (x, 0, w, blackNoteLength); break; case verticalKeyboardFacingLeft: pos.setBounds (getWidth() - blackNoteLength, x, blackNoteLength, w); break; case verticalKeyboardFacingRight: pos.setBounds (0, getHeight() - x - w, blackNoteLength, w); break; default: break; } drawBlackNote (noteNum, g, pos.getX(), pos.getY(), pos.getWidth(), pos.getHeight(), state.isNoteOnForChannels (midiInChannelMask, noteNum), mouseOverNotes.contains (noteNum), blackNoteColour); } } } }