User interface with CC knobs
This commit is contained in:
parent
751e4f96bb
commit
2ede8fd710
5 changed files with 327 additions and 18 deletions
|
|
@ -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
|
||||
} {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue