Initial release

This commit is contained in:
civ
2026-08-16 18:24:52 +07:00
commit 876886a39a
13244 changed files with 2353959 additions and 0 deletions
@@ -0,0 +1,269 @@
//------------------------------------------------------------------------
// This file is part of VSTGUI. It is subject to the license terms
// in the LICENSE file found in the top-level directory of this
// distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
// Flags : clang-format SMTGSequencer
#pragma once
#include "vstgui/lib/vstguifwd.h"
#include "vstgui/lib/ccolor.h"
#include "vstgui/lib/cview.h"
#include "vstgui/lib/dispatchlist.h"
#include "vstgui/lib/itouchevent.h"
#include <array>
#include <bitset>
#include <map>
namespace VSTGUI {
//------------------------------------------------------------------------
class KeyboardViewBase : public CView
{
public:
using NoteIndex = int16_t;
using NumNotes = uint8_t;
static constexpr NumNotes MaxNotes = 128;
enum class BitmapID
{
WhiteKeyPressed = 0,
WhiteKeyUnpressed,
BlackKeyPressed,
BlackKeyUnpressed,
WhiteKeyShadowLeft,
WhiteKeyShadowRight,
NumBitmaps
};
KeyboardViewBase ();
void setKeyPressed (NoteIndex note, bool state);
virtual void setKeyRange (NoteIndex startNote, NumNotes numKeys);
NoteIndex getKeyRangeStart () const { return startNote; }
NumNotes getNumKeys () const { return numKeys; }
NumNotes getNumWhiteKeys () const;
void setWhiteKeyWidth (CCoord width);
void setBlackKeyWidth (CCoord width);
void setBlackKeyHeight (CCoord height);
void setLineWidth (CCoord width);
CCoord getWhiteKeyWidth () const { return whiteKeyWidth; }
CCoord getBlackKeyWidth () const { return blackKeyWidth; }
CCoord getBlackKeyHeight () const { return blackKeyHeight; }
CCoord getLineWidth () const { return lineWidth; }
void setFrameColor (CColor color);
void setFontColor (CColor color);
void setWhiteKeyColor (CColor color);
void setWhiteKeyPressedColor (CColor color);
void setBlackKeyColor (CColor color);
void setBlackKeyPressedColor (CColor color);
CColor getFrameColor () const { return frameColor; }
CColor getFontColor () const { return fontColor; }
CColor getWhiteKeyColor () const { return whiteKeyColor; }
CColor getWhiteKeyPressedColor () const { return whiteKeyPressedColor; }
CColor getBlackKeyColor () const { return blackKeyColor; }
CColor getBlackKeyPressedColor () const { return blackKeyPressedColor; }
void setNoteNameFont (CFontDesc* font);
CFontDesc* getNoteNameFont () const { return noteNameFont; }
void setDrawNoteText (bool state);
bool getDrawNoteText () const { return drawNoteText; }
void setBitmap (BitmapID bID, CBitmap* bitmap);
CBitmap* getBitmap (BitmapID bID) const;
void setWhiteKeyBitmapInset (const CRect& inset); // TODO: uidesc
void setBlackKeyBitmapInset (const CRect& inset); // TODO: uidesc
const CRect& getNoteRect (NoteIndex note) const { return noteRectCache[note]; }
bool isWhiteKey (NoteIndex note) const;
void drawRect (CDrawContext* context, const CRect& dirtyRect) override;
void setViewSize (const CRect& rect, bool invalid = true) override;
bool sizeToFit () override;
//------------------------------------------------------------------------
protected:
using NoteRectCache = std::array<CRect, MaxNotes>;
void invalidNote (NoteIndex note);
NoteIndex pointToNote (const CPoint& p, bool ignoreY) const;
const NoteRectCache& getNoteRectCache () const { return noteRectCache; }
private:
void drawNote (CDrawContext* context, CRect& rect, NoteIndex note, bool isWhite) const;
CRect calcNoteRect (NoteIndex note) const;
void updateNoteRectCache () const;
void createBitmapCache ();
using BitmapArray =
std::array<SharedPointer<CBitmap>, static_cast<size_t> (BitmapID::NumBitmaps)>;
BitmapArray bitmaps;
SharedPointer<CBitmap> whiteKeyBitmapCache;
SharedPointer<CBitmap> blackKeyBitmapCache;
SharedPointer<CFontDesc> noteNameFont;
CRect whiteKeyBitmapInset;
CRect blackKeyBitmapInset;
CCoord whiteKeyWidth {30};
CCoord blackKeyWidth {20};
CCoord blackKeyHeight {20};
CCoord lineWidth {1.};
CColor frameColor {kBlackCColor};
CColor fontColor {kBlackCColor};
CColor whiteKeyColor {kWhiteCColor};
CColor whiteKeyPressedColor {kGreyCColor};
CColor blackKeyColor {kBlackCColor};
CColor blackKeyPressedColor {kGreyCColor};
NumNotes numKeys {88};
NoteIndex startNote {21};
bool drawNoteText {false};
mutable bool noteRectCacheInvalid {true};
mutable NoteRectCache noteRectCache;
std::bitset<MaxNotes> keyPressed {};
};
class KeyboardViewRangeSelector;
//------------------------------------------------------------------------
struct IKeyboardViewKeyRangeChangedListener
{
virtual void onKeyRangeChanged (KeyboardViewRangeSelector*) = 0;
virtual ~IKeyboardViewKeyRangeChangedListener () noexcept = default;
};
//------------------------------------------------------------------------
class KeyboardViewRangeSelector : public KeyboardViewBase
{
public:
struct Range
{
NoteIndex position;
NumNotes length;
Range (NoteIndex position = 0, NumNotes length = 0) : position (position), length (length)
{
}
bool operator!= (const Range& r) const
{
return position != r.position || length != r.length;
}
};
KeyboardViewRangeSelector () = default;
void drawRect (CDrawContext* context, const CRect& dirtyRect) override;
void setKeyRange (NoteIndex startNote, NumNotes numKeys) override;
void setSelectionRange (const Range& range);
void setSelectionMinMax (NumNotes minRange, NumNotes maxRange);
const Range& getSelectionRange () const { return selectionRange; }
NumNotes getSelectionMin () const { return rangeMin; }
NumNotes getSelectionMax () const { return rangeMax; }
NumNotes getNumWhiteKeysSelected () const;
void registerKeyRangeChangedListener (IKeyboardViewKeyRangeChangedListener* listener);
void unregisterKeyRangeChangedListener (IKeyboardViewKeyRangeChangedListener* listener);
//------------------------------------------------------------------------
private:
DispatchList<IKeyboardViewKeyRangeChangedListener*> listeners;
Range selectionRange {0, 12};
NumNotes rangeMin {12};
NumNotes rangeMax {24};
#if VSTGUI_TOUCH_EVENT_HANDLING
void onTouchEvent (ITouchEvent& event) override;
bool wantsMultiTouchEvents () const override;
void onTouchBegin (const ITouchEvent::TouchPair& touch, ITouchEvent& event);
void onTouchMove (const ITouchEvent::TouchPair& touch, ITouchEvent& event);
enum TouchMode {kUnknown, kMoveRange, kChangeRangeFront, kChangeRangeBack};
Range selectionRangeOnTouchStart;
int32_t touchIds[2] {-1};
TouchMode touchMode {kUnknown};
NoteIndex touchStartNote[2];
#else
CMouseEventResult onMouseDown (CPoint& where, const CButtonState& buttons) override;
CMouseEventResult onMouseMoved (CPoint& where, const CButtonState& buttons) override;
CMouseEventResult onMouseUp (CPoint& where, const CButtonState& buttons) override;
CMouseEventResult onMouseCancel () override;
Range moveStartRange;
NoteIndex moveStartNote {-1};
#endif
};
//------------------------------------------------------------------------
struct IKeyboardViewPlayerDelegate
{
using NoteIndex = KeyboardViewBase::NoteIndex;
virtual int32_t onNoteOn (NoteIndex note, double xPos, double yPos) = 0;
virtual void onNoteOff (NoteIndex note, int32_t noteID) = 0;
virtual void onNoteModulation (int32_t noteID, double xPos, double yPos) = 0;
virtual ~IKeyboardViewPlayerDelegate () noexcept = default;
};
//------------------------------------------------------------------------
struct KeyboardViewPlayerDelegate : public IKeyboardViewPlayerDelegate
{
int32_t onNoteOn (NoteIndex note, double xPos, double yPos) override { return -1; }
void onNoteOff (NoteIndex note, int32_t noteID) override {}
void onNoteModulation (int32_t noteID, double xPos, double yPos) override {}
};
//------------------------------------------------------------------------
class KeyboardView : public KeyboardViewBase
{
public:
KeyboardView ();
void setDelegate (IKeyboardViewPlayerDelegate* inDelegate) { delegate = inDelegate; }
private:
double calcYParameter (NoteIndex note, CCoord y) const;
double calcXParameter (NoteIndex note, CCoord x) const;
#if VSTGUI_TOUCH_EVENT_HANDLING
bool wantsMultiTouchEvents () const override { return true; }
void onTouchEvent (ITouchEvent& event) override;
void onTouchBegin (const ITouchEvent::TouchPair& touch, ITouchEvent& event);
void onTouchMove (const ITouchEvent::TouchPair& touch, ITouchEvent& event);
void onTouchEnd (const ITouchEvent::TouchPair& touch, ITouchEvent& event);
struct NoteTouch
{
NoteIndex note;
int32_t noteID;
NoteTouch (NoteIndex note) : note (note), noteID (-1) {}
};
std::map<int32_t, NoteTouch> noteTouches;
#else
void doNoteOff ();
void doNoteOn (NoteIndex note, double yPos, double xPos);
CMouseEventResult onMouseDown (CPoint& where, const CButtonState& buttons) override;
CMouseEventResult onMouseMoved (CPoint& where, const CButtonState& buttons) override;
CMouseEventResult onMouseUp (CPoint& where, const CButtonState& buttons) override;
CMouseEventResult onMouseCancel () override;
NoteIndex pressedNote {-1};
int32_t noteID {-1};
#endif
IKeyboardViewPlayerDelegate* delegate {nullptr};
};
//------------------------------------------------------------------------
} // VSTGUI