kopia lustrzana https://github.com/jameshball/osci-render
Add variable-size listboxes for echo effect
rodzic
a369adb6ae
commit
2462a7978e
|
@ -37,7 +37,6 @@ EffectsComponent::EffectsComponent(OscirenderAudioProcessor& p) : audioProcessor
|
||||||
addAndMakeVisible(addBtn);*/
|
addAndMakeVisible(addBtn);*/
|
||||||
|
|
||||||
listBox.setModel(&listBoxModel);
|
listBox.setModel(&listBoxModel);
|
||||||
listBox.setRowHeight(30);
|
|
||||||
addAndMakeVisible(listBox);
|
addAndMakeVisible(listBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include "ComponentList.h"
|
||||||
|
|
||||||
|
int ComponentListModel::getNumRows() {
|
||||||
|
return components.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComponentListModel::paintListBoxItem(int rowNumber, juce::Graphics& g, int width, int height, bool rowIsSelected) {}
|
||||||
|
|
||||||
|
juce::Component* ComponentListModel::refreshComponentForRow(int rowNum, bool isRowSelected, juce::Component *existingComponentToUpdate) {
|
||||||
|
std::unique_ptr<ComponentWrapper> item(dynamic_cast<ComponentWrapper*>(existingComponentToUpdate));
|
||||||
|
if (juce::isPositiveAndBelow(rowNum, getNumRows())) {
|
||||||
|
item = std::make_unique<ComponentWrapper>(components[rowNum]);
|
||||||
|
}
|
||||||
|
return item.release();
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
#include <JuceHeader.h>
|
||||||
|
|
||||||
|
// This class is a wrapper for a component that allows it to be used in a ListBox
|
||||||
|
// Why is this needed?!?!?!?!
|
||||||
|
class ComponentWrapper : public juce::Component {
|
||||||
|
public:
|
||||||
|
ComponentWrapper(std::shared_ptr<juce::Component> component) : component(component) {
|
||||||
|
addAndMakeVisible(component.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
~ComponentWrapper() override {}
|
||||||
|
|
||||||
|
void resized() override {
|
||||||
|
component->setBounds(getLocalBounds());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<juce::Component> component;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ComponentListModel : public juce::ListBoxModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ComponentListModel() {}
|
||||||
|
~ComponentListModel() override {}
|
||||||
|
|
||||||
|
int getNumRows() override;
|
||||||
|
void paintListBoxItem(int rowNumber, juce::Graphics& g, int width, int height, bool rowIsSelected) override;
|
||||||
|
juce::Component* refreshComponentForRow(int sliderNum, bool isRowSelected, juce::Component *existingComponentToUpdate) override;
|
||||||
|
|
||||||
|
void addComponent(std::shared_ptr<juce::Component> component) {
|
||||||
|
components.push_back(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::shared_ptr<juce::Component>> components;
|
||||||
|
};
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "JuceHeader.h"
|
#include "JuceHeader.h"
|
||||||
|
#include "VListBox.h"
|
||||||
|
|
||||||
// Your item-data container must inherit from this, and override at least the first
|
// Your item-data container must inherit from this, and override at least the first
|
||||||
// four member functions.
|
// four member functions.
|
||||||
|
@ -19,7 +20,7 @@ struct DraggableListBoxItemData
|
||||||
|
|
||||||
// DraggableListBox is basically just a ListBox, that inherits from DragAndDropContainer.
|
// DraggableListBox is basically just a ListBox, that inherits from DragAndDropContainer.
|
||||||
// Declare your list box using this type.
|
// Declare your list box using this type.
|
||||||
class DraggableListBox : public juce::ListBox, public juce::DragAndDropContainer
|
class DraggableListBox : public juce::jc::ListBox, public juce::DragAndDropContainer
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ protected:
|
||||||
bool insertBefore = false;
|
bool insertBefore = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DraggableListBoxModel : public juce::ListBoxModel
|
class DraggableListBoxModel : public juce::jc::ListBoxModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DraggableListBoxModel(DraggableListBox& lb, DraggableListBoxItemData& md)
|
DraggableListBoxModel(DraggableListBox& lb, DraggableListBoxItemData& md)
|
||||||
|
|
|
@ -6,12 +6,18 @@ EffectComponent::EffectComponent(double min, double max, double step, double val
|
||||||
slider.setValue(value, juce::dontSendNotification);
|
slider.setValue(value, juce::dontSendNotification);
|
||||||
}
|
}
|
||||||
|
|
||||||
EffectComponent::EffectComponent(double min, double max, double step, Effect& effect) : name(effect.getName()), id(effect.getId()) {
|
EffectComponent::EffectComponent(double min, double max, double step, EffectDetails details) : name(details.name), id(details.id) {
|
||||||
componentSetup();
|
componentSetup();
|
||||||
slider.setRange(min, max, step);
|
slider.setRange(min, max, step);
|
||||||
slider.setValue(effect.getValue(), juce::dontSendNotification);
|
slider.setValue(details.value, juce::dontSendNotification);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EffectComponent::EffectComponent(double min, double max, double step, EffectDetails details, bool checkboxVisible) : EffectComponent(min, max, step, details) {
|
||||||
|
setCheckboxVisible(checkboxVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
EffectComponent::EffectComponent(double min, double max, double step, Effect& effect) : EffectComponent(min, max, step, effect.getDetails()[0]) {}
|
||||||
|
|
||||||
EffectComponent::EffectComponent(double min, double max, double step, Effect& effect, bool checkboxVisible) : EffectComponent(min, max, step, effect) {
|
EffectComponent::EffectComponent(double min, double max, double step, Effect& effect, bool checkboxVisible) : EffectComponent(min, max, step, effect) {
|
||||||
setCheckboxVisible(checkboxVisible);
|
setCheckboxVisible(checkboxVisible);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
class EffectComponent : public juce::Component {
|
class EffectComponent : public juce::Component {
|
||||||
public:
|
public:
|
||||||
EffectComponent(double min, double max, double step, double value, juce::String name, juce::String id);
|
EffectComponent(double min, double max, double step, double value, juce::String name, juce::String id);
|
||||||
|
EffectComponent(double min, double max, double step, EffectDetails details);
|
||||||
|
EffectComponent(double min, double max, double step, EffectDetails details, bool checkboxVisible);
|
||||||
EffectComponent(double min, double max, double step, Effect& effect);
|
EffectComponent(double min, double max, double step, Effect& effect);
|
||||||
EffectComponent(double min, double max, double step, Effect& effect, bool checkboxVisible);
|
EffectComponent(double min, double max, double step, Effect& effect, bool checkboxVisible);
|
||||||
~EffectComponent();
|
~EffectComponent();
|
||||||
|
|
|
@ -1,33 +1,44 @@
|
||||||
#include "EffectsListComponent.h"
|
#include "EffectsListComponent.h"
|
||||||
|
|
||||||
EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, std::shared_ptr<EffectComponent> effectComponent) : DraggableListBoxItem(lb, data, rn), effectComponent(effectComponent) {
|
EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, std::shared_ptr<Effect> effect) : DraggableListBoxItem(lb, data, rn), effect(effect) {
|
||||||
addAndMakeVisible(*effectComponent);
|
auto details = effect->getDetails();
|
||||||
|
for (int i = 0; i < details.size(); i++) {
|
||||||
effectComponent->slider.setValue(data.getValue(rn), juce::dontSendNotification);
|
std::shared_ptr<EffectComponent> effectComponent = std::make_shared<EffectComponent>(0, 1, 0.01, details[i], i == 0);
|
||||||
effectComponent->slider.onValueChange = [this] {
|
effectComponent->slider.setValue(details[i].value, juce::dontSendNotification);
|
||||||
((AudioEffectListBoxItemData&)modelData).setValue(rowNum, this->effectComponent->slider.getValue());
|
effectComponent->slider.onValueChange = [this, i, effectComponent] {
|
||||||
|
this->effect->setValue(i, effectComponent->slider.getValue());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
bool isSelected = false;
|
bool isSelected = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
juce::SpinLock::ScopedLockType lock(data.audioProcessor.effectsLock);
|
juce::SpinLock::ScopedLockType lock(data.audioProcessor.effectsLock);
|
||||||
// check if effect is in audioProcessor enabled effects
|
// check if effect is in audioProcessor enabled effects
|
||||||
for (auto effect : data.audioProcessor.enabledEffects) {
|
for (auto processorEffect : data.audioProcessor.enabledEffects) {
|
||||||
if (effect->getId() == data.getId(rn)) {
|
if (processorEffect->getId() == effect->getId()) {
|
||||||
isSelected = true;
|
isSelected = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
effectComponent->selected.setToggleState(isSelected, juce::dontSendNotification);
|
effectComponent->selected.setToggleState(isSelected, juce::dontSendNotification);
|
||||||
effectComponent->selected.onClick = [this] {
|
effectComponent->selected.onClick = [this, effectComponent] {
|
||||||
auto data = (AudioEffectListBoxItemData&)modelData;
|
auto data = (AudioEffectListBoxItemData&)modelData;
|
||||||
juce::SpinLock::ScopedLockType lock(data.audioProcessor.effectsLock);
|
juce::SpinLock::ScopedLockType lock(data.audioProcessor.effectsLock);
|
||||||
((AudioEffectListBoxItemData&)modelData).setSelected(rowNum, this->effectComponent->selected.getToggleState());
|
data.setSelected(rowNum, effectComponent->selected.getToggleState());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listModel.addComponent(effectComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
list.setModel(&listModel);
|
||||||
|
list.setRowHeight(30);
|
||||||
|
list.updateContent();
|
||||||
|
addAndMakeVisible(list);
|
||||||
|
}
|
||||||
|
|
||||||
EffectsListComponent::~EffectsListComponent() {}
|
EffectsListComponent::~EffectsListComponent() {}
|
||||||
|
|
||||||
void EffectsListComponent::paint(juce::Graphics& g) {
|
void EffectsListComponent::paint(juce::Graphics& g) {
|
||||||
|
@ -51,15 +62,23 @@ void EffectsListComponent::paint(juce::Graphics& g) {
|
||||||
void EffectsListComponent::resized() {
|
void EffectsListComponent::resized() {
|
||||||
auto area = getLocalBounds();
|
auto area = getLocalBounds();
|
||||||
area.removeFromLeft(20);
|
area.removeFromLeft(20);
|
||||||
effectComponent->setBounds(area);
|
list.setBounds(area);
|
||||||
|
}
|
||||||
|
|
||||||
|
int EffectsListBoxModel::getRowHeight(int row) {
|
||||||
|
auto data = (AudioEffectListBoxItemData&)modelData;
|
||||||
|
return data.getEffect(row)->getDetails().size() * 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EffectsListBoxModel::hasVariableHeightRows() const {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
juce::Component* EffectsListBoxModel::refreshComponentForRow(int rowNumber, bool isRowSelected, juce::Component *existingComponentToUpdate) {
|
juce::Component* EffectsListBoxModel::refreshComponentForRow(int rowNumber, bool isRowSelected, juce::Component *existingComponentToUpdate) {
|
||||||
std::unique_ptr<EffectsListComponent> item(dynamic_cast<EffectsListComponent*>(existingComponentToUpdate));
|
std::unique_ptr<EffectsListComponent> item(dynamic_cast<EffectsListComponent*>(existingComponentToUpdate));
|
||||||
if (juce::isPositiveAndBelow(rowNumber, modelData.getNumItems())) {
|
if (juce::isPositiveAndBelow(rowNumber, modelData.getNumItems())) {
|
||||||
auto data = (AudioEffectListBoxItemData&)modelData;
|
auto data = (AudioEffectListBoxItemData&)modelData;
|
||||||
std::shared_ptr<EffectComponent> effectComponent = std::make_shared<EffectComponent>(0, 1, 0.01, 0, data.getText(rowNumber), data.getId(rowNumber));
|
item = std::make_unique<EffectsListComponent>(listBox, (AudioEffectListBoxItemData&)modelData, rowNumber, data.getEffect(rowNumber));
|
||||||
item = std::make_unique<EffectsListComponent>(listBox, (AudioEffectListBoxItemData&)modelData, rowNumber, effectComponent);
|
|
||||||
}
|
}
|
||||||
return item.release();
|
return item.release();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "../PluginProcessor.h"
|
#include "../PluginProcessor.h"
|
||||||
#include "../audio/Effect.h"
|
#include "../audio/Effect.h"
|
||||||
#include "EffectComponent.h"
|
#include "EffectComponent.h"
|
||||||
|
#include "ComponentList.h"
|
||||||
|
|
||||||
// Application-specific data container
|
// Application-specific data container
|
||||||
struct AudioEffectListBoxItemData : public DraggableListBoxItemData
|
struct AudioEffectListBoxItemData : public DraggableListBoxItemData
|
||||||
|
@ -71,10 +72,6 @@ struct AudioEffectListBoxItemData : public DraggableListBoxItemData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setValue(int itemIndex, double value) {
|
|
||||||
data[itemIndex]->setValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSelected(int itemIndex, bool selected) {
|
void setSelected(int itemIndex, bool selected) {
|
||||||
if (selected) {
|
if (selected) {
|
||||||
audioProcessor.enableEffect(data[itemIndex]);
|
audioProcessor.enableEffect(data[itemIndex]);
|
||||||
|
@ -83,16 +80,8 @@ struct AudioEffectListBoxItemData : public DraggableListBoxItemData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
juce::String getText(int itemIndex) {
|
std::shared_ptr<Effect> getEffect(int itemIndex) {
|
||||||
return data[itemIndex]->getName();
|
return data[itemIndex];
|
||||||
}
|
|
||||||
|
|
||||||
double getValue(int itemIndex) {
|
|
||||||
return data[itemIndex]->getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
juce::String getId(int itemIndex) {
|
|
||||||
return data[itemIndex]->getId();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -100,14 +89,16 @@ struct AudioEffectListBoxItemData : public DraggableListBoxItemData
|
||||||
class EffectsListComponent : public DraggableListBoxItem
|
class EffectsListComponent : public DraggableListBoxItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, std::shared_ptr<EffectComponent> effectComponent);
|
EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, std::shared_ptr<Effect> effect);
|
||||||
~EffectsListComponent();
|
~EffectsListComponent();
|
||||||
|
|
||||||
void paint(juce::Graphics& g) override;
|
void paint(juce::Graphics& g) override;
|
||||||
void resized() override;
|
void resized() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<EffectComponent> effectComponent;
|
std::shared_ptr<Effect> effect;
|
||||||
|
ComponentListModel listModel;
|
||||||
|
juce::ListBox list;
|
||||||
private:
|
private:
|
||||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectsListComponent)
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectsListComponent)
|
||||||
};
|
};
|
||||||
|
@ -124,5 +115,8 @@ public:
|
||||||
audioProcessor.updateEffectPrecedence();
|
audioProcessor.updateEffectPrecedence();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getRowHeight(int row) override;
|
||||||
|
bool hasVariableHeightRows() const override;
|
||||||
|
|
||||||
juce::Component* refreshComponentForRow(int, bool, juce::Component*) override;
|
juce::Component* refreshComponentForRow(int, bool, juce::Component*) override;
|
||||||
};
|
};
|
||||||
|
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,622 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
This file is part of the JUCE library.
|
||||||
|
Copyright (c) 2020 - Raw Material Software Limited
|
||||||
|
|
||||||
|
JUCE is an open source library subject to commercial or open-source
|
||||||
|
licensing.
|
||||||
|
|
||||||
|
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||||
|
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||||
|
|
||||||
|
End User License Agreement: www.juce.com/juce-6-licence
|
||||||
|
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||||
|
|
||||||
|
Or: You may also use this code under the terms of the GPL v3 (see
|
||||||
|
www.gnu.org/licenses).
|
||||||
|
|
||||||
|
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||||
|
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||||
|
DISCLAIMED.
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "JuceHeader.h"
|
||||||
|
|
||||||
|
namespace juce {
|
||||||
|
namespace jc {
|
||||||
|
//==============================================================================
|
||||||
|
/**
|
||||||
|
A subclass of this is used to drive a ListBox.
|
||||||
|
|
||||||
|
@see ListBox
|
||||||
|
|
||||||
|
@tags{GUI}
|
||||||
|
*/
|
||||||
|
class ListBoxModel {
|
||||||
|
public:
|
||||||
|
//==============================================================================
|
||||||
|
/** Destructor. */
|
||||||
|
virtual ~ListBoxModel() = default;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
/** This has to return the number of items in the list.
|
||||||
|
@see ListBox::getNumRows()
|
||||||
|
*/
|
||||||
|
virtual int getNumRows() = 0;
|
||||||
|
|
||||||
|
/** This method must be implemented to draw a row of the list.
|
||||||
|
Note that the rowNumber value may be greater than the number of rows in your
|
||||||
|
list, so be careful that you don't assume it's less than getNumRows().
|
||||||
|
*/
|
||||||
|
virtual void paintListBoxItem(int rowNumber, Graphics& g, int width, int height, bool rowIsSelected) = 0;
|
||||||
|
|
||||||
|
/** This is used to create or update a custom component to go in a row of the list.
|
||||||
|
|
||||||
|
Any row may contain a custom component, or can just be drawn with the paintListBoxItem() method
|
||||||
|
and handle mouse clicks with listBoxItemClicked().
|
||||||
|
|
||||||
|
This method will be called whenever a custom component might need to be updated - e.g.
|
||||||
|
when the list is changed, or ListBox::updateContent() is called.
|
||||||
|
|
||||||
|
If you don't need a custom component for the specified row, then return nullptr.
|
||||||
|
(Bear in mind that even if you're not creating a new component, you may still need to
|
||||||
|
delete existingComponentToUpdate if it's non-null).
|
||||||
|
|
||||||
|
If you do want a custom component, and the existingComponentToUpdate is null, then
|
||||||
|
this method must create a suitable new component and return it.
|
||||||
|
|
||||||
|
If the existingComponentToUpdate is non-null, it will be a pointer to a component previously created
|
||||||
|
by this method. In this case, the method must either update it to make sure it's correctly representing
|
||||||
|
the given row (which may be different from the one that the component was created for), or it can
|
||||||
|
delete this component and return a new one.
|
||||||
|
|
||||||
|
The component that your method returns will be deleted by the ListBox when it is no longer needed.
|
||||||
|
|
||||||
|
Bear in mind that if you put a custom component inside the row but still want the
|
||||||
|
listbox to automatically handle clicking, selection, etc, then you'll need to make sure
|
||||||
|
your custom component doesn't intercept all the mouse events that land on it, e.g by
|
||||||
|
using Component::setInterceptsMouseClicks().
|
||||||
|
*/
|
||||||
|
virtual Component* refreshComponentForRow(int rowNumber, bool isRowSelected, Component* existingComponentToUpdate);
|
||||||
|
|
||||||
|
/** This can be overridden to react to the user clicking on a row.
|
||||||
|
@see listBoxItemDoubleClicked
|
||||||
|
*/
|
||||||
|
virtual void listBoxItemClicked(int row, const MouseEvent&);
|
||||||
|
|
||||||
|
/** This can be overridden to react to the user double-clicking on a row.
|
||||||
|
@see listBoxItemClicked
|
||||||
|
*/
|
||||||
|
virtual void listBoxItemDoubleClicked(int row, const MouseEvent&);
|
||||||
|
|
||||||
|
/** This can be overridden to react to the user clicking on a part of the list where
|
||||||
|
there are no rows.
|
||||||
|
@see listBoxItemClicked
|
||||||
|
*/
|
||||||
|
virtual void backgroundClicked(const MouseEvent&);
|
||||||
|
|
||||||
|
/** Override this to be informed when rows are selected or deselected.
|
||||||
|
|
||||||
|
This will be called whenever a row is selected or deselected. If a range of
|
||||||
|
rows is selected all at once, this will just be called once for that event.
|
||||||
|
|
||||||
|
@param lastRowSelected the last row that the user selected. If no
|
||||||
|
rows are currently selected, this may be -1.
|
||||||
|
*/
|
||||||
|
virtual void selectedRowsChanged(int lastRowSelected);
|
||||||
|
|
||||||
|
/** Override this to be informed when the delete key is pressed.
|
||||||
|
|
||||||
|
If no rows are selected when they press the key, this won't be called.
|
||||||
|
|
||||||
|
@param lastRowSelected the last row that had been selected when they pressed the
|
||||||
|
key - if there are multiple selections, this might not be
|
||||||
|
very useful
|
||||||
|
*/
|
||||||
|
virtual void deleteKeyPressed(int lastRowSelected);
|
||||||
|
|
||||||
|
/** Override this to be informed when the return key is pressed.
|
||||||
|
|
||||||
|
If no rows are selected when they press the key, this won't be called.
|
||||||
|
|
||||||
|
@param lastRowSelected the last row that had been selected when they pressed the
|
||||||
|
key - if there are multiple selections, this might not be
|
||||||
|
very useful
|
||||||
|
*/
|
||||||
|
virtual void returnKeyPressed(int lastRowSelected);
|
||||||
|
|
||||||
|
/** Override this to be informed when the list is scrolled.
|
||||||
|
|
||||||
|
This might be caused by the user moving the scrollbar, or by programmatic changes
|
||||||
|
to the list position.
|
||||||
|
*/
|
||||||
|
virtual void listWasScrolled();
|
||||||
|
|
||||||
|
/** To allow rows from your list to be dragged-and-dropped, implement this method.
|
||||||
|
|
||||||
|
If this returns a non-null variant then when the user drags a row, the listbox will
|
||||||
|
try to find a DragAndDropContainer in its parent hierarchy, and will use it to trigger
|
||||||
|
a drag-and-drop operation, using this string as the source description, with the listbox
|
||||||
|
itself as the source component.
|
||||||
|
|
||||||
|
@see DragAndDropContainer::startDragging
|
||||||
|
*/
|
||||||
|
virtual var getDragSourceDescription(const SparseSet<int>& rowsToDescribe);
|
||||||
|
|
||||||
|
/** You can override this to provide tool tips for specific rows.
|
||||||
|
@see TooltipClient
|
||||||
|
*/
|
||||||
|
virtual String getTooltipForRow(int row);
|
||||||
|
|
||||||
|
/** You can override this to return a custom mouse cursor for each row. */
|
||||||
|
virtual MouseCursor getMouseCursorForRow(int row);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this to return the row height for a given row.
|
||||||
|
*/
|
||||||
|
virtual int getRowHeight(int row) { return 22; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this if your list may have variable row heights.
|
||||||
|
*
|
||||||
|
* Performance is slightly improved if this returns false, but getRowHeight
|
||||||
|
* must then return the same number for all rows.
|
||||||
|
*/
|
||||||
|
virtual bool hasVariableHeightRows() const { return false; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You can override this to improve performance with very long lists.
|
||||||
|
*
|
||||||
|
* If you have many variable height rows you may be able to improve
|
||||||
|
* performance by directly calculating the row for a given y position.
|
||||||
|
*
|
||||||
|
* If the y position is greater than the number of rows return the number
|
||||||
|
* of rows. yPos will never be less than zero.
|
||||||
|
*/
|
||||||
|
virtual int getRowForPosition(int yPos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You can override this to improve performance with very long lists.
|
||||||
|
*
|
||||||
|
* If you have a large number (e.g. thousands of) variable height rows you
|
||||||
|
* may be able to improve performance by overriding this function and
|
||||||
|
* directly calculating the y position of a given row.
|
||||||
|
*/
|
||||||
|
virtual int getPositionForRow(int rowNumber);
|
||||||
|
};
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
/**
|
||||||
|
A list of items that can be scrolled vertically.
|
||||||
|
|
||||||
|
To create a list, you'll need to create a subclass of ListBoxModel. This can
|
||||||
|
either paint each row of the list and respond to events via callbacks, or for
|
||||||
|
more specialised tasks, it can supply a custom component to fill each row.
|
||||||
|
|
||||||
|
@see ComboBox, TableListBox
|
||||||
|
|
||||||
|
@tags{GUI}
|
||||||
|
*/
|
||||||
|
class JUCE_API ListBox : public Component, public SettableTooltipClient {
|
||||||
|
public:
|
||||||
|
//==============================================================================
|
||||||
|
/** Creates a ListBox.
|
||||||
|
|
||||||
|
The model pointer passed-in can be null, in which case you can set it later
|
||||||
|
with setModel().
|
||||||
|
*/
|
||||||
|
ListBox(const String& componentName = String(), ListBoxModel* model = nullptr);
|
||||||
|
|
||||||
|
/** Destructor. */
|
||||||
|
~ListBox() override;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
/** Changes the current data model to display. */
|
||||||
|
void setModel(ListBoxModel* newModel);
|
||||||
|
|
||||||
|
/** Returns the current list model. */
|
||||||
|
ListBoxModel* getModel() const noexcept { return model; }
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
/** Causes the list to refresh its content.
|
||||||
|
|
||||||
|
Call this when the number of rows in the list changes, or if you want it
|
||||||
|
to call refreshComponentForRow() on all the row components.
|
||||||
|
|
||||||
|
This must only be called from the main message thread.
|
||||||
|
*/
|
||||||
|
void updateContent();
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
/** Turns on multiple-selection of rows.
|
||||||
|
|
||||||
|
By default this is disabled.
|
||||||
|
|
||||||
|
When your row component gets clicked you'll need to call the
|
||||||
|
selectRowsBasedOnModifierKeys() method to tell the list that it's been
|
||||||
|
clicked and to get it to do the appropriate selection based on whether
|
||||||
|
the ctrl/shift keys are held down.
|
||||||
|
*/
|
||||||
|
void setMultipleSelectionEnabled(bool shouldBeEnabled) noexcept;
|
||||||
|
|
||||||
|
/** If enabled, this makes the listbox flip the selection status of
|
||||||
|
each row that the user clicks, without affecting other selected rows.
|
||||||
|
|
||||||
|
(This only has an effect if multiple selection is also enabled).
|
||||||
|
If not enabled, you can still get the same row-flipping behaviour by holding
|
||||||
|
down CMD or CTRL when clicking.
|
||||||
|
*/
|
||||||
|
void setClickingTogglesRowSelection(bool flipRowSelection) noexcept;
|
||||||
|
|
||||||
|
/** Sets whether a row should be selected when the mouse is pressed or released.
|
||||||
|
By default this is true, but you may want to turn it off.
|
||||||
|
*/
|
||||||
|
void setRowSelectedOnMouseDown(bool isSelectedOnMouseDown) noexcept;
|
||||||
|
|
||||||
|
/** Makes the list react to mouse moves by selecting the row that the mouse if over.
|
||||||
|
|
||||||
|
This function is here primarily for the ComboBox class to use, but might be
|
||||||
|
useful for some other purpose too.
|
||||||
|
*/
|
||||||
|
void setMouseMoveSelectsRows(bool shouldSelect);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
/** Selects a row.
|
||||||
|
|
||||||
|
If the row is already selected, this won't do anything.
|
||||||
|
|
||||||
|
@param rowNumber the row to select
|
||||||
|
@param dontScrollToShowThisRow if true, the list's position won't change; if false and
|
||||||
|
the selected row is off-screen, it'll scroll to make
|
||||||
|
sure that row is on-screen
|
||||||
|
@param deselectOthersFirst if true and there are multiple selections, these will
|
||||||
|
first be deselected before this item is selected
|
||||||
|
@see isRowSelected, selectRowsBasedOnModifierKeys, flipRowSelection, deselectRow,
|
||||||
|
deselectAllRows, selectRangeOfRows
|
||||||
|
*/
|
||||||
|
void selectRow(int rowNumber, bool dontScrollToShowThisRow = false, bool deselectOthersFirst = true);
|
||||||
|
|
||||||
|
/** Selects a set of rows.
|
||||||
|
|
||||||
|
This will add these rows to the current selection, so you might need to
|
||||||
|
clear the current selection first with deselectAllRows()
|
||||||
|
|
||||||
|
@param firstRow the first row to select (inclusive)
|
||||||
|
@param lastRow the last row to select (inclusive)
|
||||||
|
@param dontScrollToShowThisRange if true, the list's position won't change; if false and
|
||||||
|
the selected range is off-screen, it'll scroll to make
|
||||||
|
sure that the range of rows is on-screen
|
||||||
|
*/
|
||||||
|
void selectRangeOfRows(int firstRow, int lastRow, bool dontScrollToShowThisRange = false);
|
||||||
|
|
||||||
|
/** Deselects a row.
|
||||||
|
If it's not currently selected, this will do nothing.
|
||||||
|
@see selectRow, deselectAllRows
|
||||||
|
*/
|
||||||
|
void deselectRow(int rowNumber);
|
||||||
|
|
||||||
|
/** Deselects any currently selected rows.
|
||||||
|
@see deselectRow
|
||||||
|
*/
|
||||||
|
void deselectAllRows();
|
||||||
|
|
||||||
|
/** Selects or deselects a row.
|
||||||
|
If the row's currently selected, this deselects it, and vice-versa.
|
||||||
|
*/
|
||||||
|
void flipRowSelection(int rowNumber);
|
||||||
|
|
||||||
|
/** Returns a sparse set indicating the rows that are currently selected.
|
||||||
|
@see setSelectedRows
|
||||||
|
*/
|
||||||
|
SparseSet<int> getSelectedRows() const;
|
||||||
|
|
||||||
|
/** Sets the rows that should be selected, based on an explicit set of ranges.
|
||||||
|
|
||||||
|
If sendNotificationEventToModel is true, the ListBoxModel::selectedRowsChanged()
|
||||||
|
method will be called. If it's false, no notification will be sent to the model.
|
||||||
|
|
||||||
|
@see getSelectedRows
|
||||||
|
*/
|
||||||
|
void setSelectedRows(const SparseSet<int>& setOfRowsToBeSelected, NotificationType sendNotificationEventToModel = sendNotification);
|
||||||
|
|
||||||
|
/** Checks whether a row is selected.
|
||||||
|
*/
|
||||||
|
bool isRowSelected(int rowNumber) const;
|
||||||
|
|
||||||
|
/** Returns the number of rows that are currently selected.
|
||||||
|
@see getSelectedRow, isRowSelected, getLastRowSelected
|
||||||
|
*/
|
||||||
|
int getNumSelectedRows() const;
|
||||||
|
|
||||||
|
/** Returns the row number of a selected row.
|
||||||
|
|
||||||
|
This will return the row number of the Nth selected row. The row numbers returned will
|
||||||
|
be sorted in order from low to high.
|
||||||
|
|
||||||
|
@param index the index of the selected row to return, (from 0 to getNumSelectedRows() - 1)
|
||||||
|
@returns the row number, or -1 if the index was out of range or if there aren't any rows
|
||||||
|
selected
|
||||||
|
@see getNumSelectedRows, isRowSelected, getLastRowSelected
|
||||||
|
*/
|
||||||
|
int getSelectedRow(int index = 0) const;
|
||||||
|
|
||||||
|
/** Returns the last row that the user selected.
|
||||||
|
|
||||||
|
This isn't the same as the highest row number that is currently selected - if the user
|
||||||
|
had multiply-selected rows 10, 5 and then 6 in that order, this would return 6.
|
||||||
|
|
||||||
|
If nothing is selected, it will return -1.
|
||||||
|
*/
|
||||||
|
int getLastRowSelected() const;
|
||||||
|
|
||||||
|
/** Multiply-selects rows based on the modifier keys.
|
||||||
|
|
||||||
|
If no modifier keys are down, this will select the given row and
|
||||||
|
deselect any others.
|
||||||
|
|
||||||
|
If the ctrl (or command on the Mac) key is down, it'll flip the
|
||||||
|
state of the selected row.
|
||||||
|
|
||||||
|
If the shift key is down, it'll select up to the given row from the
|
||||||
|
last row selected.
|
||||||
|
|
||||||
|
@see selectRow
|
||||||
|
*/
|
||||||
|
void selectRowsBasedOnModifierKeys(int rowThatWasClickedOn, ModifierKeys modifiers, bool isMouseUpEvent);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
/** Scrolls the list to a particular position.
|
||||||
|
|
||||||
|
The proportion is between 0 and 1.0, so 0 scrolls to the top of the list,
|
||||||
|
1.0 scrolls to the bottom.
|
||||||
|
|
||||||
|
If the total number of rows all fit onto the screen at once, then this
|
||||||
|
method won't do anything.
|
||||||
|
|
||||||
|
@see getVerticalPosition
|
||||||
|
*/
|
||||||
|
void setVerticalPosition(double newProportion);
|
||||||
|
|
||||||
|
/** Returns the current vertical position as a proportion of the total.
|
||||||
|
|
||||||
|
This can be used in conjunction with setVerticalPosition() to save and restore
|
||||||
|
the list's position. It returns a value in the range 0 to 1.
|
||||||
|
|
||||||
|
@see setVerticalPosition
|
||||||
|
*/
|
||||||
|
double getVerticalPosition() const;
|
||||||
|
|
||||||
|
/** Scrolls if necessary to make sure that a particular row is visible. */
|
||||||
|
void scrollToEnsureRowIsOnscreen(int row);
|
||||||
|
|
||||||
|
/** Returns a reference to the vertical scrollbar. */
|
||||||
|
ScrollBar& getVerticalScrollBar() const noexcept;
|
||||||
|
|
||||||
|
/** Returns a reference to the horizontal scrollbar. */
|
||||||
|
ScrollBar& getHorizontalScrollBar() const noexcept;
|
||||||
|
|
||||||
|
/** Finds the row index that contains a given x,y position.
|
||||||
|
The position is relative to the ListBox's top-left.
|
||||||
|
If no row exists at this position, the method will return -1.
|
||||||
|
@see getComponentForRowNumber
|
||||||
|
*/
|
||||||
|
int getRowContainingPosition(int x, int y) const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the height of the specified row. Returns zero if no model has
|
||||||
|
* been set.
|
||||||
|
*/
|
||||||
|
int getRowHeight(int row) const;
|
||||||
|
|
||||||
|
/** Finds a row index that would be the most suitable place to insert a new
|
||||||
|
item for a given position.
|
||||||
|
|
||||||
|
This is useful when the user is e.g. dragging and dropping onto the listbox,
|
||||||
|
because it lets you easily choose the best position to insert the item that
|
||||||
|
they drop, based on where they drop it.
|
||||||
|
|
||||||
|
If the position is out of range, this will return -1. If the position is
|
||||||
|
beyond the end of the list, it will return getNumRows() to indicate the end
|
||||||
|
of the list.
|
||||||
|
|
||||||
|
@see getComponentForRowNumber
|
||||||
|
*/
|
||||||
|
int getInsertionIndexForPosition(int x, int y) const noexcept;
|
||||||
|
|
||||||
|
/** Returns the position of one of the rows, relative to the top-left of
|
||||||
|
the listbox.
|
||||||
|
|
||||||
|
This may be off-screen, and the range of the row number that is passed-in is
|
||||||
|
not checked to see if it's a valid row.
|
||||||
|
*/
|
||||||
|
Rectangle<int> getRowPosition(int rowNumber, bool relativeToComponentTopLeft) const noexcept;
|
||||||
|
|
||||||
|
/** Finds the row component for a given row in the list.
|
||||||
|
|
||||||
|
The component returned will have been created using ListBoxModel::refreshComponentForRow().
|
||||||
|
|
||||||
|
If the component for this row is off-screen or if the row is out-of-range,
|
||||||
|
this will return nullptr.
|
||||||
|
|
||||||
|
@see getRowContainingPosition
|
||||||
|
*/
|
||||||
|
Component* getComponentForRowNumber(int rowNumber) const noexcept;
|
||||||
|
|
||||||
|
/** Returns the row number that the given component represents.
|
||||||
|
If the component isn't one of the list's rows, this will return -1.
|
||||||
|
*/
|
||||||
|
int getRowNumberOfComponent(Component* rowComponent) const noexcept;
|
||||||
|
|
||||||
|
/** Returns the width of a row (which may be less than the width of this component
|
||||||
|
if there's a scrollbar).
|
||||||
|
*/
|
||||||
|
int getVisibleRowWidth() const noexcept;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
/** Returns the number of rows actually visible.
|
||||||
|
|
||||||
|
This is the number of whole rows which will fit on-screen, so the value might
|
||||||
|
be more than the actual number of rows in the list.
|
||||||
|
*/
|
||||||
|
int getNumRowsOnScreen() const noexcept;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
/** A set of colour IDs to use to change the colour of various aspects of the label.
|
||||||
|
|
||||||
|
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
|
||||||
|
methods.
|
||||||
|
|
||||||
|
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
|
||||||
|
*/
|
||||||
|
enum ColourIds {
|
||||||
|
backgroundColourId = 0x1002800, /**< The background colour to fill the list with.
|
||||||
|
Make this transparent if you don't want the background to be filled. */
|
||||||
|
outlineColourId = 0x1002810, /**< An optional colour to use to draw a border around the list.
|
||||||
|
Make this transparent to not have an outline. */
|
||||||
|
textColourId = 0x1002820 /**< The preferred colour to use for drawing text in the listbox. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Sets the thickness of a border that will be drawn around the box.
|
||||||
|
|
||||||
|
To set the colour of the outline, use @code setColour (ListBox::outlineColourId, colourXYZ); @endcode
|
||||||
|
@see outlineColourId
|
||||||
|
*/
|
||||||
|
void setOutlineThickness(int outlineThickness);
|
||||||
|
|
||||||
|
/** Returns the thickness of outline that will be drawn around the listbox.
|
||||||
|
@see setOutlineColour
|
||||||
|
*/
|
||||||
|
int getOutlineThickness() const noexcept { return outlineThickness; }
|
||||||
|
|
||||||
|
/** Sets a component that the list should use as a header.
|
||||||
|
|
||||||
|
This will position the given component at the top of the list, maintaining the
|
||||||
|
height of the component passed-in, but rescaling it horizontally to match the
|
||||||
|
width of the items in the listbox.
|
||||||
|
|
||||||
|
The component will be deleted when setHeaderComponent() is called with a
|
||||||
|
different component, or when the listbox is deleted.
|
||||||
|
*/
|
||||||
|
void setHeaderComponent(std::unique_ptr<Component> newHeaderComponent);
|
||||||
|
|
||||||
|
/** Returns whatever header component was set with setHeaderComponent(). */
|
||||||
|
Component* getHeaderComponent() const noexcept { return headerComponent.get(); }
|
||||||
|
|
||||||
|
/** Changes the width of the rows in the list.
|
||||||
|
|
||||||
|
This can be used to make the list's row components wider than the list itself - the
|
||||||
|
width of the rows will be either the width of the list or this value, whichever is
|
||||||
|
greater, and if the rows become wider than the list, a horizontal scrollbar will
|
||||||
|
appear.
|
||||||
|
|
||||||
|
The default value for this is 0, which means that the rows will always
|
||||||
|
be the same width as the list.
|
||||||
|
*/
|
||||||
|
void setMinimumContentWidth(int newMinimumWidth);
|
||||||
|
|
||||||
|
/** Returns the space currently available for the row items, taking into account
|
||||||
|
borders, scrollbars, etc.
|
||||||
|
*/
|
||||||
|
int getVisibleContentWidth() const noexcept;
|
||||||
|
|
||||||
|
/** Repaints one of the rows.
|
||||||
|
|
||||||
|
This does not invoke updateContent(), it just invokes a straightforward repaint
|
||||||
|
for the area covered by this row.
|
||||||
|
*/
|
||||||
|
void repaintRow(int rowNumber) noexcept;
|
||||||
|
|
||||||
|
/** This fairly obscure method creates an image that shows the row components specified
|
||||||
|
in rows (for example, these could be the currently selected row components).
|
||||||
|
|
||||||
|
It's a handy method for doing drag-and-drop, as it can be passed to the
|
||||||
|
DragAndDropContainer for use as the drag image.
|
||||||
|
|
||||||
|
Note that it will make the row components temporarily invisible, so if you're
|
||||||
|
using custom components this could affect them if they're sensitive to that
|
||||||
|
sort of thing.
|
||||||
|
|
||||||
|
@see Component::createComponentSnapshot
|
||||||
|
*/
|
||||||
|
virtual Image createSnapshotOfRows(const SparseSet<int>& rows, int& x, int& y);
|
||||||
|
|
||||||
|
/** Returns the viewport that this ListBox uses.
|
||||||
|
|
||||||
|
You may need to use this to change parameters such as whether scrollbars
|
||||||
|
are shown, etc.
|
||||||
|
*/
|
||||||
|
Viewport* getViewport() const noexcept;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
/** @internal */
|
||||||
|
bool keyPressed(const KeyPress&) override;
|
||||||
|
/** @internal */
|
||||||
|
bool keyStateChanged(bool isKeyDown) override;
|
||||||
|
/** @internal */
|
||||||
|
void paint(Graphics&) override;
|
||||||
|
/** @internal */
|
||||||
|
void paintOverChildren(Graphics&) override;
|
||||||
|
/** @internal */
|
||||||
|
void resized() override;
|
||||||
|
/** @internal */
|
||||||
|
void visibilityChanged() override;
|
||||||
|
/** @internal */
|
||||||
|
void mouseWheelMove(const MouseEvent&, const MouseWheelDetails&) override;
|
||||||
|
/** @internal */
|
||||||
|
void mouseUp(const MouseEvent&) override;
|
||||||
|
/** @internal */
|
||||||
|
void colourChanged() override;
|
||||||
|
/** @internal */
|
||||||
|
void parentHierarchyChanged() override;
|
||||||
|
/** @internal */
|
||||||
|
void startDragAndDrop(const MouseEvent&,
|
||||||
|
const SparseSet<int>& rowsToDrag,
|
||||||
|
const var& dragDescription,
|
||||||
|
bool allowDraggingToOtherWindows);
|
||||||
|
|
||||||
|
private:
|
||||||
|
//==============================================================================
|
||||||
|
JUCE_PUBLIC_IN_DLL_BUILD(class ListViewport)
|
||||||
|
JUCE_PUBLIC_IN_DLL_BUILD(class RowComponent)
|
||||||
|
friend class ListViewport;
|
||||||
|
friend class TableListBox;
|
||||||
|
ListBoxModel* model;
|
||||||
|
std::unique_ptr<ListViewport> viewport;
|
||||||
|
std::unique_ptr<Component> headerComponent;
|
||||||
|
std::unique_ptr<MouseListener> mouseMoveSelector;
|
||||||
|
SparseSet<int> selected;
|
||||||
|
int totalItems = 0, minimumRowWidth = 0;
|
||||||
|
int outlineThickness = 0;
|
||||||
|
int lastRowSelected = -1;
|
||||||
|
bool multipleSelection = false, alwaysFlipSelection = false, hasDoneInitialUpdate = false, selectOnMouseDown = true;
|
||||||
|
|
||||||
|
void selectRowInternal(int rowNumber, bool dontScrollToShowThisRow, bool deselectOthersFirst, bool isMouseClick);
|
||||||
|
int getContentHeight() const;
|
||||||
|
int getRowForPosition(int y) const;
|
||||||
|
int getPositionForRow(int row) const;
|
||||||
|
|
||||||
|
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE
|
||||||
|
// This method's bool parameter has changed: see the new method signature.
|
||||||
|
JUCE_DEPRECATED(void setSelectedRows(const SparseSet<int>&, bool));
|
||||||
|
|
||||||
|
// Rows can now have different heights. See getRowHeight(int rowNumber) instead.
|
||||||
|
JUCE_DEPRECATED(void getRowHeight());
|
||||||
|
|
||||||
|
// Row height is now set by the ListBoxModel as rows can have different heights.
|
||||||
|
// Implement ListBoxModel::getRowHeight(int rowNumber).
|
||||||
|
JUCE_DEPRECATED(void setRowHeight(int));
|
||||||
|
|
||||||
|
// This method has been replaced by the more flexible method createSnapshotOfRows.
|
||||||
|
// Please call createSnapshotOfRows (getSelectedRows(), x, y) to get the same behaviour.
|
||||||
|
JUCE_DEPRECATED(virtual void createSnapshotOfSelectedRows(int&, int&)) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ListBox)
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace jc
|
||||||
|
} // namespace juce
|
|
@ -79,6 +79,9 @@
|
||||||
<FILE id="CdKZCg" name="Matching.h" compile="0" resource="0" file="Source/chinese_postman/Matching.h"/>
|
<FILE id="CdKZCg" name="Matching.h" compile="0" resource="0" file="Source/chinese_postman/Matching.h"/>
|
||||||
</GROUP>
|
</GROUP>
|
||||||
<GROUP id="{CD81913A-7F0E-5898-DA77-5EBEB369DEB1}" name="components">
|
<GROUP id="{CD81913A-7F0E-5898-DA77-5EBEB369DEB1}" name="components">
|
||||||
|
<FILE id="kUinTt" name="ComponentList.cpp" compile="1" resource="0"
|
||||||
|
file="Source/components/ComponentList.cpp"/>
|
||||||
|
<FILE id="HGTPEW" name="ComponentList.h" compile="0" resource="0" file="Source/components/ComponentList.h"/>
|
||||||
<FILE id="poPVxL" name="DraggableListBox.cpp" compile="1" resource="0"
|
<FILE id="poPVxL" name="DraggableListBox.cpp" compile="1" resource="0"
|
||||||
file="Source/components/DraggableListBox.cpp"/>
|
file="Source/components/DraggableListBox.cpp"/>
|
||||||
<FILE id="Y9NEGn" name="DraggableListBox.h" compile="0" resource="0"
|
<FILE id="Y9NEGn" name="DraggableListBox.h" compile="0" resource="0"
|
||||||
|
@ -99,6 +102,8 @@
|
||||||
file="Source/components/VisualiserComponent.cpp"/>
|
file="Source/components/VisualiserComponent.cpp"/>
|
||||||
<FILE id="ZueyNl" name="VisualiserComponent.h" compile="0" resource="0"
|
<FILE id="ZueyNl" name="VisualiserComponent.h" compile="0" resource="0"
|
||||||
file="Source/components/VisualiserComponent.h"/>
|
file="Source/components/VisualiserComponent.h"/>
|
||||||
|
<FILE id="icFMpl" name="VListBox.cpp" compile="1" resource="0" file="Source/components/VListBox.cpp"/>
|
||||||
|
<FILE id="mvp8je" name="VListBox.h" compile="0" resource="0" file="Source/components/VListBox.h"/>
|
||||||
<FILE id="s8EVcE" name="VolumeComponent.cpp" compile="1" resource="0"
|
<FILE id="s8EVcE" name="VolumeComponent.cpp" compile="1" resource="0"
|
||||||
file="Source/components/VolumeComponent.cpp"/>
|
file="Source/components/VolumeComponent.cpp"/>
|
||||||
<FILE id="MWkfTv" name="VolumeComponent.h" compile="0" resource="0"
|
<FILE id="MWkfTv" name="VolumeComponent.h" compile="0" resource="0"
|
||||||
|
|
Ładowanie…
Reference in New Issue