kopia lustrzana https://github.com/jameshball/osci-render
Start improving design of effect component lists
rodzic
3ab190398b
commit
50cc383e25
|
@ -45,11 +45,13 @@ OscirenderLookAndFeel::OscirenderLookAndFeel() {
|
|||
|
||||
void OscirenderLookAndFeel::drawComboBox(juce::Graphics& g, int width, int height, bool, int, int, int, int, juce::ComboBox& box) {
|
||||
juce::Rectangle<int> boxBounds{0, 0, width, height};
|
||||
|
||||
float alpha = box.isEnabled() ? 1.0f : 0.5f;
|
||||
|
||||
g.setColour(box.findColour(juce::ComboBox::backgroundColourId));
|
||||
g.setColour(box.findColour(juce::ComboBox::backgroundColourId).withAlpha(alpha));
|
||||
g.fillRect(boxBounds.toFloat());
|
||||
|
||||
g.setColour(box.findColour(juce::ComboBox::outlineColourId));
|
||||
g.setColour(box.findColour(juce::ComboBox::outlineColourId).withAlpha(alpha));
|
||||
g.drawRect(boxBounds.toFloat().reduced(0.5f, 0.5f), 1.0f);
|
||||
|
||||
juce::Rectangle<int> arrowZone{width - 15, 0, 10, height};
|
||||
|
@ -59,7 +61,7 @@ void OscirenderLookAndFeel::drawComboBox(juce::Graphics& g, int width, int heigh
|
|||
path.lineTo((float)arrowZone.getRight(), (float)arrowZone.getCentreY() - 3.0f);
|
||||
path.closeSubPath();
|
||||
|
||||
g.setColour(box.findColour(juce::ComboBox::arrowColourId).withAlpha((box.isEnabled() ? 0.9f : 0.2f)));
|
||||
g.setColour(box.findColour(juce::ComboBox::arrowColourId).withAlpha(alpha));
|
||||
g.fillPath(path);
|
||||
}
|
||||
|
||||
|
@ -138,8 +140,102 @@ void OscirenderLookAndFeel::drawGroupComponentOutline(juce::Graphics& g, int wid
|
|||
}
|
||||
|
||||
void OscirenderLookAndFeel::drawLinearSlider(juce::Graphics& g, int x, int y, int width, int height, float sliderPos, float minSliderPos, float maxSliderPos, const juce::Slider::SliderStyle style, juce::Slider& slider) {
|
||||
juce::LookAndFeel_V4::drawLinearSlider(g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider);
|
||||
float alpha = slider.isEnabled() ? 1.0f : 0.5f;
|
||||
|
||||
if (slider.isBar())
|
||||
{
|
||||
g.setColour (slider.findColour (juce::Slider::trackColourId).withAlpha(alpha));
|
||||
g.fillRect (slider.isHorizontal() ? juce::Rectangle<float> (static_cast<float> (x), (float) y + 0.5f, sliderPos - (float) x, (float) height - 1.0f)
|
||||
: juce::Rectangle<float> ((float) x + 0.5f, sliderPos, (float) width - 1.0f, (float) y + ((float) height - sliderPos)));
|
||||
|
||||
drawLinearSliderOutline (g, x, y, width, height, style, slider);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto isTwoVal = (style == juce::Slider::SliderStyle::TwoValueVertical || style == juce::Slider::SliderStyle::TwoValueHorizontal);
|
||||
auto isThreeVal = (style == juce::Slider::SliderStyle::ThreeValueVertical || style == juce::Slider::SliderStyle::ThreeValueHorizontal);
|
||||
|
||||
auto trackWidth = juce::jmin (6.0f, slider.isHorizontal() ? (float) height * 0.25f : (float) width * 0.25f);
|
||||
|
||||
juce::Point<float> startPoint (slider.isHorizontal() ? (float) x : (float) x + (float) width * 0.5f,
|
||||
slider.isHorizontal() ? (float) y + (float) height * 0.5f : (float) (height + y));
|
||||
|
||||
juce::Point<float> endPoint (slider.isHorizontal() ? (float) (width + x) : startPoint.x,
|
||||
slider.isHorizontal() ? startPoint.y : (float) y);
|
||||
|
||||
juce::Path backgroundTrack;
|
||||
backgroundTrack.startNewSubPath (startPoint);
|
||||
backgroundTrack.lineTo (endPoint);
|
||||
g.setColour (slider.findColour (juce::Slider::backgroundColourId));
|
||||
g.strokePath (backgroundTrack, { trackWidth, juce::PathStrokeType::curved, juce::PathStrokeType::rounded });
|
||||
|
||||
juce::Path valueTrack;
|
||||
juce::Point<float> minPoint, maxPoint, thumbPoint;
|
||||
|
||||
if (isTwoVal || isThreeVal)
|
||||
{
|
||||
minPoint = { slider.isHorizontal() ? minSliderPos : (float) width * 0.5f,
|
||||
slider.isHorizontal() ? (float) height * 0.5f : minSliderPos };
|
||||
|
||||
if (isThreeVal)
|
||||
thumbPoint = { slider.isHorizontal() ? sliderPos : (float) width * 0.5f,
|
||||
slider.isHorizontal() ? (float) height * 0.5f : sliderPos };
|
||||
|
||||
maxPoint = { slider.isHorizontal() ? maxSliderPos : (float) width * 0.5f,
|
||||
slider.isHorizontal() ? (float) height * 0.5f : maxSliderPos };
|
||||
}
|
||||
else
|
||||
{
|
||||
auto kx = slider.isHorizontal() ? sliderPos : ((float) x + (float) width * 0.5f);
|
||||
auto ky = slider.isHorizontal() ? ((float) y + (float) height * 0.5f) : sliderPos;
|
||||
|
||||
minPoint = startPoint;
|
||||
maxPoint = { kx, ky };
|
||||
}
|
||||
|
||||
auto thumbWidth = getSliderThumbRadius (slider);
|
||||
|
||||
valueTrack.startNewSubPath (minPoint);
|
||||
valueTrack.lineTo (isThreeVal ? thumbPoint : maxPoint);
|
||||
g.setColour (slider.findColour (juce::Slider::trackColourId).withAlpha(alpha));
|
||||
g.strokePath (valueTrack, { trackWidth, juce::PathStrokeType::curved, juce::PathStrokeType::rounded });
|
||||
|
||||
if (! isTwoVal)
|
||||
{
|
||||
g.setColour (slider.findColour (juce::Slider::thumbColourId));
|
||||
g.fillEllipse (juce::Rectangle<float> (static_cast<float> (thumbWidth), static_cast<float> (thumbWidth)).withCentre (isThreeVal ? thumbPoint : maxPoint));
|
||||
}
|
||||
|
||||
if (isTwoVal || isThreeVal)
|
||||
{
|
||||
auto sr = juce::jmin (trackWidth, (slider.isHorizontal() ? (float) height : (float) width) * 0.4f);
|
||||
auto pointerColour = slider.findColour (juce::Slider::thumbColourId);
|
||||
|
||||
if (slider.isHorizontal())
|
||||
{
|
||||
drawPointer (g, minSliderPos - sr,
|
||||
juce::jmax (0.0f, (float) y + (float) height * 0.5f - trackWidth * 2.0f),
|
||||
trackWidth * 2.0f, pointerColour, 2);
|
||||
|
||||
drawPointer (g, maxSliderPos - trackWidth,
|
||||
juce::jmin ((float) (y + height) - trackWidth * 2.0f, (float) y + (float) height * 0.5f),
|
||||
trackWidth * 2.0f, pointerColour, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
drawPointer (g, juce::jmax (0.0f, (float) x + (float) width * 0.5f - trackWidth * 2.0f),
|
||||
minSliderPos - trackWidth,
|
||||
trackWidth * 2.0f, pointerColour, 1);
|
||||
|
||||
drawPointer (g, juce::jmin ((float) (x + width) - trackWidth * 2.0f, (float) x + (float) width * 0.5f), maxSliderPos - sr,
|
||||
trackWidth * 2.0f, pointerColour, 3);
|
||||
}
|
||||
}
|
||||
|
||||
if (slider.isBar())
|
||||
drawLinearSliderOutline (g, x, y, width, height, style, slider);
|
||||
}
|
||||
|
||||
auto kx = slider.isHorizontal() ? sliderPos : ((float)x + (float)width * 0.5f);
|
||||
auto ky = slider.isHorizontal() ? ((float)y + (float)height * 0.5f) : sliderPos;
|
||||
|
||||
|
@ -147,7 +243,7 @@ void OscirenderLookAndFeel::drawLinearSlider(juce::Graphics& g, int x, int y, in
|
|||
|
||||
auto thumbWidth = getSliderThumbRadius(slider);
|
||||
|
||||
g.setColour(slider.findColour(sliderThumbOutlineColourId));
|
||||
g.setColour(slider.findColour(sliderThumbOutlineColourId).withAlpha(alpha));
|
||||
g.drawEllipse(juce::Rectangle<float>(static_cast<float>(thumbWidth), static_cast<float>(thumbWidth)).withCentre(point), 1.0f);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ void EffectComponent::setupComponent() {
|
|||
|
||||
bool enabled = effect.enabled == nullptr || effect.enabled->getValue();
|
||||
selected.setToggleState(enabled, juce::dontSendNotification);
|
||||
updateEnabled();
|
||||
|
||||
lfoEnabled = parameter->lfo != nullptr && parameter->lfoRate != nullptr;
|
||||
if (lfoEnabled) {
|
||||
|
@ -129,9 +130,12 @@ void EffectComponent::resized() {
|
|||
|
||||
auto checkboxLabel = bounds.removeFromLeft(120);
|
||||
|
||||
if (checkboxVisible) {
|
||||
if (checkboxVisible || subParameter) {
|
||||
checkboxLabel.removeFromLeft(2);
|
||||
selected.setBounds(checkboxLabel.removeFromLeft(25));
|
||||
auto checkboxBounds = checkboxLabel.removeFromLeft(25);
|
||||
if (checkboxVisible) {
|
||||
selected.setBounds(checkboxBounds);
|
||||
}
|
||||
} else {
|
||||
checkboxLabel.removeFromLeft(5);
|
||||
}
|
||||
|
@ -144,6 +148,10 @@ void EffectComponent::paint(juce::Graphics& g) {
|
|||
g.fillAll(findColour(effectComponentBackgroundColourId));
|
||||
g.setColour(juce::Colours::white);
|
||||
g.drawText(effect.parameters[index]->name, textBounds, juce::Justification::left);
|
||||
if (!selected.getToggleState()) {
|
||||
g.setColour(juce::Colours::black.withAlpha(0.5f));
|
||||
g.fillAll();
|
||||
}
|
||||
}
|
||||
|
||||
void EffectComponent::mouseDown(const juce::MouseEvent& event) {
|
||||
|
@ -181,3 +189,15 @@ void EffectComponent::setComponent(std::shared_ptr<juce::Component> component) {
|
|||
void EffectComponent::setCheckboxVisible(bool visible) {
|
||||
checkboxVisible = visible;
|
||||
}
|
||||
|
||||
void EffectComponent::setSubParameter(bool subParameter) {
|
||||
this->subParameter = subParameter;
|
||||
}
|
||||
|
||||
void EffectComponent::updateEnabled() {
|
||||
bool enabled = selected.getToggleState();
|
||||
slider.setEnabled(enabled);
|
||||
lfoSlider.setEnabled(enabled);
|
||||
lfo.setEnabled(enabled);
|
||||
repaint();
|
||||
}
|
||||
|
|
|
@ -18,8 +18,10 @@ public:
|
|||
void parameterValueChanged(int parameterIndex, float newValue) override;
|
||||
void parameterGestureChanged(int parameterIndex, bool gestureIsStarting) override;
|
||||
void handleAsyncUpdate() override;
|
||||
void updateEnabled();
|
||||
|
||||
void setCheckboxVisible(bool visible);
|
||||
void setSubParameter(bool subParameter);
|
||||
void setComponent(std::shared_ptr<juce::Component> component);
|
||||
|
||||
juce::Slider slider;
|
||||
|
@ -32,6 +34,7 @@ public:
|
|||
private:
|
||||
void setupComponent();
|
||||
bool checkboxVisible = true;
|
||||
bool subParameter = false;
|
||||
bool lfoEnabled = true;
|
||||
juce::Rectangle<int> textBounds;
|
||||
std::shared_ptr<juce::Component> component;
|
||||
|
|
|
@ -21,9 +21,12 @@ EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectList
|
|||
auto data = (AudioEffectListBoxItemData&)modelData;
|
||||
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
|
||||
data.setSelected(rowNum, effectComponent->selected.getToggleState());
|
||||
effectComponent->updateEnabled();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
effectComponent->setSubParameter(i != 0);
|
||||
|
||||
auto component = createComponent(parameters[i]);
|
||||
if (component != nullptr) {
|
||||
|
@ -34,7 +37,7 @@ EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectList
|
|||
}
|
||||
|
||||
list.setModel(&listModel);
|
||||
list.setRowHeight(30);
|
||||
list.setRowHeight(ROW_HEIGHT);
|
||||
list.updateContent();
|
||||
addAndMakeVisible(list);
|
||||
}
|
||||
|
@ -43,9 +46,10 @@ EffectsListComponent::~EffectsListComponent() {}
|
|||
|
||||
void EffectsListComponent::paint(juce::Graphics& g) {
|
||||
auto bounds = getLocalBounds();
|
||||
g.fillAll(findColour(effectComponentHandleColourId));
|
||||
g.setColour(findColour(effectComponentHandleColourId));
|
||||
bounds.removeFromBottom(2);
|
||||
g.fillRect(bounds);
|
||||
g.setColour(juce::Colours::white);
|
||||
bounds.removeFromLeft(20);
|
||||
// draw drag and drop handle using circles
|
||||
double size = 4;
|
||||
double leftPad = 4;
|
||||
|
@ -61,12 +65,6 @@ void EffectsListComponent::paint(juce::Graphics& g) {
|
|||
DraggableListBoxItem::paint(g);
|
||||
}
|
||||
|
||||
void EffectsListComponent::paintOverChildren(juce::Graphics& g) {
|
||||
auto bounds = getLocalBounds();
|
||||
g.setColour(juce::Colours::white);
|
||||
g.drawRect(bounds);
|
||||
}
|
||||
|
||||
void EffectsListComponent::resized() {
|
||||
auto area = getLocalBounds();
|
||||
area.removeFromLeft(20);
|
||||
|
@ -105,7 +103,7 @@ std::shared_ptr<juce::Component> EffectsListComponent::createComponent(EffectPar
|
|||
|
||||
int EffectsListBoxModel::getRowHeight(int row) {
|
||||
auto data = (AudioEffectListBoxItemData&)modelData;
|
||||
return data.getEffect(row)->parameters.size() * 30;
|
||||
return data.getEffect(row)->parameters.size() * EffectsListComponent::ROW_HEIGHT + 2;
|
||||
}
|
||||
|
||||
bool EffectsListBoxModel::hasVariableHeightRows() const {
|
||||
|
|
|
@ -19,12 +19,12 @@ struct AudioEffectListBoxItemData : public DraggableListBoxItemData
|
|||
}
|
||||
|
||||
void resetData() {
|
||||
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
|
||||
data.clear();
|
||||
for (int i = 0; i < audioProcessor.toggleableEffects.size(); i++) {
|
||||
auto effect = audioProcessor.toggleableEffects[i];
|
||||
effect->setValue(effect->getValue());
|
||||
data.push_back(effect);
|
||||
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
|
||||
data.clear();
|
||||
for (int i = 0; i < audioProcessor.toggleableEffects.size(); i++) {
|
||||
auto effect = audioProcessor.toggleableEffects[i];
|
||||
effect->setValue(effect->getValue());
|
||||
data.push_back(effect);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,22 +42,22 @@ struct AudioEffectListBoxItemData : public DraggableListBoxItemData
|
|||
// data.push_back(juce::String("Yahoo"));
|
||||
}
|
||||
|
||||
void moveBefore(int indexOfItemToMove, int indexOfItemToPlaceBefore) override {
|
||||
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
|
||||
|
||||
auto effect = data[indexOfItemToMove];
|
||||
|
||||
if (indexOfItemToMove < indexOfItemToPlaceBefore) {
|
||||
move(data, indexOfItemToMove, indexOfItemToPlaceBefore - 1);
|
||||
} else {
|
||||
move(data, indexOfItemToMove, indexOfItemToPlaceBefore);
|
||||
}
|
||||
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
data[i]->setPrecedence(i);
|
||||
}
|
||||
|
||||
audioProcessor.updateEffectPrecedence();
|
||||
void moveBefore(int indexOfItemToMove, int indexOfItemToPlaceBefore) override {
|
||||
juce::SpinLock::ScopedLockType lock(audioProcessor.effectsLock);
|
||||
|
||||
auto effect = data[indexOfItemToMove];
|
||||
|
||||
if (indexOfItemToMove < indexOfItemToPlaceBefore) {
|
||||
move(data, indexOfItemToMove, indexOfItemToPlaceBefore - 1);
|
||||
} else {
|
||||
move(data, indexOfItemToMove, indexOfItemToPlaceBefore);
|
||||
}
|
||||
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
data[i]->setPrecedence(i);
|
||||
}
|
||||
|
||||
audioProcessor.updateEffectPrecedence();
|
||||
}
|
||||
|
||||
void moveAfter(int indexOfItemToMove, int indexOfItemToPlaceAfter) override {
|
||||
|
@ -65,25 +65,25 @@ struct AudioEffectListBoxItemData : public DraggableListBoxItemData
|
|||
|
||||
auto temp = data[indexOfItemToMove];
|
||||
|
||||
if (indexOfItemToMove <= indexOfItemToPlaceAfter) {
|
||||
move(data, indexOfItemToMove, indexOfItemToPlaceAfter);
|
||||
} else {
|
||||
move(data, indexOfItemToMove, indexOfItemToPlaceAfter + 1);
|
||||
if (indexOfItemToMove <= indexOfItemToPlaceAfter) {
|
||||
move(data, indexOfItemToMove, indexOfItemToPlaceAfter);
|
||||
} else {
|
||||
move(data, indexOfItemToMove, indexOfItemToPlaceAfter + 1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
data[i]->setPrecedence(i);
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
data[i]->setPrecedence(i);
|
||||
}
|
||||
|
||||
audioProcessor.updateEffectPrecedence();
|
||||
}
|
||||
|
||||
template <typename t> void move(std::vector<t>& v, size_t oldIndex, size_t newIndex) {
|
||||
if (oldIndex > newIndex) {
|
||||
std::rotate(v.rend() - oldIndex - 1, v.rend() - oldIndex, v.rend() - newIndex);
|
||||
} else {
|
||||
std::rotate(v.begin() + oldIndex, v.begin() + oldIndex + 1, v.begin() + newIndex + 1);
|
||||
}
|
||||
template <typename t> void move(std::vector<t>& v, size_t oldIndex, size_t newIndex) {
|
||||
if (oldIndex > newIndex) {
|
||||
std::rotate(v.rend() - oldIndex - 1, v.rend() - oldIndex, v.rend() - newIndex);
|
||||
} else {
|
||||
std::rotate(v.begin() + oldIndex, v.begin() + oldIndex + 1, v.begin() + newIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void setSelected(int itemIndex, bool selected) {
|
||||
|
@ -107,12 +107,13 @@ public:
|
|||
~EffectsListComponent();
|
||||
|
||||
void paint(juce::Graphics& g) override;
|
||||
void paintOverChildren(juce::Graphics& g) override;
|
||||
void resized() override;
|
||||
|
||||
static const int ROW_HEIGHT = 30;
|
||||
|
||||
protected:
|
||||
Effect& effect;
|
||||
ComponentListModel listModel;
|
||||
Effect& effect;
|
||||
ComponentListModel listModel;
|
||||
juce::ListBox list;
|
||||
private:
|
||||
OscirenderAudioProcessor& audioProcessor;
|
||||
|
|
Ładowanie…
Reference in New Issue