User interface with CC knobs

This commit is contained in:
Jean Pierre Cimalando 2021-02-03 02:05:50 +01:00
parent 751e4f96bb
commit 2ede8fd710
5 changed files with 327 additions and 18 deletions

View file

@ -3,7 +3,7 @@ version 1.0305
header_name {.h}
code_name {.cxx}
widget_class mainView {open
xywh {576 416 800 475} type Double
xywh {571 362 800 475} type Double
class LogicalGroup visible
} {
Fl_Box {} {
@ -197,23 +197,22 @@ widget_class mainView {open
}
}
}
Fl_Group {subPanels_[kPanelControls]} {
xywh {5 110 790 285} hide
Fl_Group {subPanels_[kPanelControls]} {open
xywh {5 110 790 285}
class LogicalGroup
} {
Fl_Group {} {open
xywh {5 110 790 285} box ROUNDED_BOX
class RoundedGroup
} {
Fl_Box {} {
label {Controls not available}
xywh {5 110 790 285} labelsize 40
class Label
}
Fl_Group controlsPanel_ {open selected
xywh {5 110 790 285} box THIN_DOWN_FRAME
class ControlsPanel
} {}
}
}
Fl_Group {subPanels_[kPanelSettings]} {open
xywh {5 109 790 316}
xywh {5 109 790 316} hide
class LogicalGroup
} {
Fl_Group {} {
@ -305,7 +304,7 @@ widget_class mainView {open
}
}
Fl_Group userFilesGroup_ {
label Files open selected
label Files open
xywh {620 270 139 100} box ROUNDED_BOX labelsize 12 align 17
class TitleGroup
} {

View file

@ -106,6 +106,8 @@ struct Editor::Impl : EditorController::Receiver, IControlListener {
SPiano* piano_ = nullptr;
SControlsPanel* controlsPanel_ = nullptr;
void uiReceiveValue(EditId id, const EditValue& v) override;
void uiReceiveMessage(const char* path, const char* sig, const sfizz_arg_t* args) override;
@ -156,6 +158,11 @@ struct Editor::Impl : EditorController::Receiver, IControlListener {
void updateCCValue(unsigned cc, float value);
void updateCCLabel(unsigned cc, const char* label);
// edition of CC by UI
void performCCValueChange(unsigned cc, float value);
void performCCBeginEdit(unsigned cc);
void performCCEndEdit(unsigned cc);
void setActivePanel(unsigned panelId);
static void formatLabel(CTextLabel* label, const char* fmt, ...);
@ -533,6 +540,7 @@ void Editor::Impl::createFrameContents()
typedef STextButton NextFileButton;
typedef SPiano Piano;
typedef SActionMenu ChevronDropDown;
typedef SControlsPanel ControlsPanel;
auto createLogicalGroup = [](const CRect& bounds, int, const char*, CHoriTxtAlign, int) {
CViewContainer* container = new CViewContainer(bounds);
@ -706,6 +714,10 @@ void Editor::Impl::createFrameContents()
container->setBackground(background);
return container;
};
auto createControlsPanel = [](const CRect& bounds, int, const char*, CHoriTxtAlign, int) {
auto* panel = new SControlsPanel(bounds);
return panel;
};
#include "layout/main.hpp"
@ -844,6 +856,18 @@ void Editor::Impl::createFrameContents()
};
}
if (SControlsPanel* panel = controlsPanel_) {
panel->ValueChangeFunction = [this](uint32_t cc, float value) {
performCCValueChange(cc, value);
};
panel->BeginEditFunction = [this](uint32_t cc) {
performCCBeginEdit(cc);
};
panel->EndEditFunction = [this](uint32_t cc) {
performCCEndEdit(cc);
};
}
///
CViewContainer* panel;
activePanel_ = 0;
@ -1169,20 +1193,41 @@ void Editor::Impl::updateStretchedTuningLabel(float stretchedTuning)
void Editor::Impl::updateCCUsed(unsigned cc, bool used)
{
// TODO
fprintf(stderr, "CC%u used: %d\n", cc, used);
if (SControlsPanel* panel = controlsPanel_)
panel->setControlUsed(cc, used);
}
void Editor::Impl::updateCCValue(unsigned cc, float value)
{
// TODO
fprintf(stderr, "CC%u value: %f\n", cc, value);
if (SControlsPanel* panel = controlsPanel_)
panel->setControlValue(cc, value);
}
void Editor::Impl::updateCCLabel(unsigned cc, const char* label)
{
// TODO
fprintf(stderr, "CC%u label: %s\n", cc, label);
if (SControlsPanel* panel = controlsPanel_)
panel->setControlLabelText(cc, label);
}
void Editor::Impl::performCCValueChange(unsigned cc, float value)
{
// TODO(jpc) CC as parameters and automation
char pathBuf[256];
sprintf(pathBuf, "/cc%u/value", cc);
sfizz_arg_t args[1];
args[0].f = value;
sendQueuedOSC(pathBuf, "f", args);
}
void Editor::Impl::performCCBeginEdit(unsigned cc)
{
// TODO(jpc) CC as parameters and automation
}
void Editor::Impl::performCCEndEdit(unsigned cc)
{
// TODO(jpc) CC as parameters and automation
}
void Editor::Impl::setActivePanel(unsigned panelId)

View file

@ -516,3 +516,209 @@ void SStyledKnob::draw(CDrawContext* dc)
dc->drawLine(p1, p2);
}
}
///
SControlsPanel::SControlsPanel(const CRect& size)
: CScrollView(
size, CRect(),
CScrollView::kVerticalScrollbar|CScrollView::kDontDrawFrame|CScrollView::kAutoHideScrollbars),
listener_(new ControlSlotListener(this))
{
setBackgroundColor(CColor(0x00, 0x00, 0x00, 0x00));
setScrollbarWidth(10.0);
}
void SControlsPanel::setControlUsed(uint32_t index, bool used)
{
bool changed = false;
if (used) {
if (index + 1 > slots_.size())
slots_.resize(index + 1);
ControlSlot* slot = slots_[index].get();
changed = !slot;
if (changed) {
slot = new ControlSlot;
slots_[index].reset(slot);
// create controls etc...
CCoord knobWidth = 48.0;
CCoord knobHeight = 72.0;
CCoord labelWidth = 96.0;
CCoord labelHeight = 24.0;
CCoord verticalPadding = -12.0;
CCoord totalWidth = std::max(knobWidth, labelWidth);
CCoord knobX = (totalWidth - knobWidth) / 2.0;
CCoord labelX = (totalWidth - labelWidth) / 2.0;
CRect knobBounds(knobX, 0.0, knobX + knobWidth, knobHeight);
CRect labelBounds(labelX, knobHeight + verticalPadding, labelX + labelWidth, knobHeight + verticalPadding + labelHeight);
CRect boxBounds = CRect(knobBounds).unite(labelBounds);
SharedPointer<SStyledKnob> knob = owned(new SStyledKnob(knobBounds, listener_.get(), index));
SharedPointer<CTextLabel> label = owned(new CTextLabel(labelBounds));
SharedPointer<CViewContainer> box = owned(new CViewContainer(boxBounds));
box->addView(knob);
knob->remember();
box->addView(label);
label->remember();
box->setBackgroundColor(CColor(0x00, 0x00, 0x00, 0x00));
label->setStyle(CTextLabel::kRoundRectStyle);
label->setRoundRectRadius(5.0);
label->setBackColor(CColor(0x2e, 0x34, 0x36));
label->setText(("CC " + std::to_string(index)).c_str());
knob->setActiveTrackColor(CColor(0x00, 0xb6, 0x2a));
knob->setInactiveTrackColor(CColor(0x30, 0x30, 0x30));
knob->setLineIndicatorColor(CColor(0x00, 0x00, 0x00));
slot->knob = knob;
slot->label = label;
slot->box = box;
}
}
else {
if (index < slots_.size() && slots_[index]) {
changed = true;
slots_[index].reset();
}
}
if (changed)
updateLayout();
}
void SControlsPanel::setControlValue(uint32_t index, float value)
{
if (index >= slots_.size())
return;
ControlSlot* slot = slots_[index].get();
if (!slot)
return;
slot->knob->setValue(value);
}
void SControlsPanel::setControlLabelText(uint32_t index, UTF8StringPtr text)
{
if (index >= slots_.size())
return;
ControlSlot* slot = slots_[index].get();
if (!slot)
return;
slot->label->setText(text);
}
void SControlsPanel::recalculateSubViews()
{
CScrollView::recalculateSubViews();
// maybe the operation just created the scroll bar
if (CScrollbar* vsb = getVerticalScrollbar()) {
// update scrollbar style
vsb->setFrameColor(CColor(0x00, 0x00, 0x00, 0x00));
vsb->setBackgroundColor(CColor(0x00, 0x00, 0x00, 0x00));
vsb->setScrollerColor(CColor(0x00, 0x00, 0x00, 0x80));
}
}
void SControlsPanel::updateLayout()
{
removeAll();
const CRect viewBounds = getViewSize();
bool isFirstSlot = true;
CCoord itemWidth {};
CCoord itemHeight {};
CCoord itemOffsetX {};
int numColumns {};
const CCoord horizontalPadding = 24.0;
const CCoord verticalPadding = 5.0;
int currentRow = 0;
int currentColumn = 0;
int containerBottom = 0;
uint32_t numSlots = static_cast<uint32_t>(slots_.size());
for (uint32_t i = 0; i < numSlots; ++i) {
ControlSlot* slot = slots_[i].get();
if (!slot)
continue;
CViewContainer* box = slot->box;
if (isFirstSlot) {
itemWidth = box->getWidth();
itemHeight = box->getHeight();
isFirstSlot = false;
numColumns = int((viewBounds.getWidth() - horizontalPadding) /
(itemWidth + horizontalPadding));
numColumns = std::max(1, numColumns);
itemOffsetX = (viewBounds.getWidth() - horizontalPadding -
numColumns * (itemWidth + horizontalPadding)) / 2.0;
}
CRect itemBounds = box->getViewSize();
itemBounds.moveTo(
itemOffsetX + horizontalPadding + currentColumn * (horizontalPadding + itemWidth),
verticalPadding + currentRow * (verticalPadding + itemHeight));
box->setViewSize(itemBounds);
containerBottom = itemBounds.bottom;
addView(box);
box->remember();
if (++currentColumn == numColumns) {
currentColumn = 0;
++currentRow;
}
}
CRect containerSize = getContainerSize();
containerSize.bottom = containerBottom;
setContainerSize(CRect(0.0, 0.0, viewBounds.getWidth(), containerBottom + verticalPadding));
}
void SControlsPanel::ControlSlotListener::valueChanged(CControl* pControl)
{
if (panel_->ValueChangeFunction)
panel_->ValueChangeFunction(pControl->getTag(), pControl->getValue());
}
void SControlsPanel::ControlSlotListener::controlBeginEdit(CControl* pControl)
{
if (panel_->BeginEditFunction)
panel_->BeginEditFunction(pControl->getTag());
}
void SControlsPanel::ControlSlotListener::controlEndEdit(CControl* pControl)
{
if (panel_->EndEditFunction)
panel_->EndEditFunction(pControl->getTag());
}
///
SPlaceHolder::SPlaceHolder(const CRect& size, const CColor& color)
: CView(size), color_(color)
{
}
void SPlaceHolder::draw(CDrawContext* dc)
{
const CRect bounds = getViewSize();
dc->setDrawMode(kAliasing);
dc->setFrameColor(color_);
dc->drawRect(bounds);
dc->drawLine(bounds.getTopLeft(), bounds.getBottomRight());
dc->drawLine(bounds.getTopRight(), bounds.getBottomLeft());
}

View file

@ -6,6 +6,9 @@
#pragma once
#include <bitset>
#include <vector>
#include <memory>
#include <functional>
#include "utility/vstgui_before.h"
#include "vstgui/lib/controls/cslider.h"
@ -13,8 +16,10 @@
#include "vstgui/lib/controls/ctextlabel.h"
#include "vstgui/lib/controls/cbuttons.h"
#include "vstgui/lib/controls/coptionmenu.h"
#include "vstgui/lib/controls/cscrollbar.h"
#include "vstgui/lib/controls/icontrollistener.h"
#include "vstgui/lib/cviewcontainer.h"
#include "vstgui/lib/cscrollview.h"
#include "vstgui/lib/ccolor.h"
#include "vstgui/lib/dragging.h"
#include "utility/vstgui_after.h"
@ -210,3 +215,56 @@ private:
CColor inactiveTrackColor_;
CColor lineIndicatorColor_;
};
///
class SControlsPanel : public CScrollView {
public:
explicit SControlsPanel(const CRect& size);
void setControlUsed(uint32_t index, bool used);
void setControlValue(uint32_t index, float value);
void setControlLabelText(uint32_t index, UTF8StringPtr text);
std::function<void(uint32_t, float)> ValueChangeFunction;
std::function<void(uint32_t)> BeginEditFunction;
std::function<void(uint32_t)> EndEditFunction;
protected:
void recalculateSubViews() override;
private:
void updateLayout();
private:
struct ControlSlot {
SharedPointer<CControl> knob;
SharedPointer<CTextLabel> label;
SharedPointer<CViewContainer> box;
};
class ControlSlotListener : public IControlListener {
public:
explicit ControlSlotListener(SControlsPanel* panel) : panel_(panel) {}
void valueChanged(CControl* pControl) override;
void controlBeginEdit(CControl* pControl) override;
void controlEndEdit(CControl* pControl) override;
private:
SControlsPanel* panel_ = nullptr;
};
std::vector<std::unique_ptr<ControlSlot>> slots_;
std::unique_ptr<ControlSlotListener> listener_;
};
///
class SPlaceHolder : public CView {
public:
explicit SPlaceHolder(const CRect& size, const CColor& color = {0xff, 0x00, 0x00, 0xff});
protected:
void draw(CDrawContext* dc) override;
private:
CColor color_;
};

View file

@ -100,14 +100,15 @@ view__29->addView(view__39);
LogicalGroup* const view__40 = createLogicalGroup(CRect(5, 110, 795, 395), -1, "", kCenterText, 14);
subPanels_[kPanelControls] = view__40;
view__0->addView(view__40);
view__40->setVisible(false);
RoundedGroup* const view__41 = createRoundedGroup(CRect(0, 0, 790, 285), -1, "", kCenterText, 14);
view__40->addView(view__41);
Label* const view__42 = createLabel(CRect(0, 0, 790, 285), -1, "Controls not available", kCenterText, 40);
ControlsPanel* const view__42 = createControlsPanel(CRect(0, 0, 790, 285), -1, "", kCenterText, 14);
controlsPanel_ = view__42;
view__41->addView(view__42);
LogicalGroup* const view__43 = createLogicalGroup(CRect(5, 109, 795, 425), -1, "", kCenterText, 14);
subPanels_[kPanelSettings] = view__43;
view__0->addView(view__43);
view__43->setVisible(false);
TitleGroup* const view__44 = createTitleGroup(CRect(255, 26, 535, 126), -1, "Engine", kCenterText, 12);
view__43->addView(view__44);
ValueMenu* const view__45 = createValueMenu(CRect(25, 60, 85, 85), kTagSetNumVoices, "", kCenterText, 12);