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);*/
|
||||
|
||||
listBox.setModel(&listBoxModel);
|
||||
listBox.setRowHeight(30);
|
||||
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
|
||||
#include "JuceHeader.h"
|
||||
#include "VListBox.h"
|
||||
|
||||
// Your item-data container must inherit from this, and override at least the first
|
||||
// four member functions.
|
||||
|
@ -19,7 +20,7 @@ struct DraggableListBoxItemData
|
|||
|
||||
// DraggableListBox is basically just a ListBox, that inherits from DragAndDropContainer.
|
||||
// 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;
|
||||
};
|
||||
|
||||
class DraggableListBoxModel : public juce::ListBoxModel
|
||||
class DraggableListBoxModel : public juce::jc::ListBoxModel
|
||||
{
|
||||
public:
|
||||
DraggableListBoxModel(DraggableListBox& lb, DraggableListBoxItemData& md)
|
||||
|
|
|
@ -6,16 +6,22 @@ EffectComponent::EffectComponent(double min, double max, double step, double val
|
|||
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();
|
||||
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, Effect& effect, bool checkboxVisible) : EffectComponent(min, max, step, effect) {
|
||||
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) {
|
||||
setCheckboxVisible(checkboxVisible);
|
||||
}
|
||||
|
||||
void EffectComponent::componentSetup() {
|
||||
addAndMakeVisible(slider);
|
||||
addAndMakeVisible(selected);
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
class EffectComponent : public juce::Component {
|
||||
public:
|
||||
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, bool checkboxVisible);
|
||||
~EffectComponent();
|
||||
|
|
|
@ -1,31 +1,42 @@
|
|||
#include "EffectsListComponent.h"
|
||||
|
||||
EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, std::shared_ptr<EffectComponent> effectComponent) : DraggableListBoxItem(lb, data, rn), effectComponent(effectComponent) {
|
||||
addAndMakeVisible(*effectComponent);
|
||||
EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, std::shared_ptr<Effect> effect) : DraggableListBoxItem(lb, data, rn), effect(effect) {
|
||||
auto details = effect->getDetails();
|
||||
for (int i = 0; i < details.size(); i++) {
|
||||
std::shared_ptr<EffectComponent> effectComponent = std::make_shared<EffectComponent>(0, 1, 0.01, details[i], i == 0);
|
||||
effectComponent->slider.setValue(details[i].value, juce::dontSendNotification);
|
||||
effectComponent->slider.onValueChange = [this, i, effectComponent] {
|
||||
this->effect->setValue(i, effectComponent->slider.getValue());
|
||||
};
|
||||
|
||||
effectComponent->slider.setValue(data.getValue(rn), juce::dontSendNotification);
|
||||
effectComponent->slider.onValueChange = [this] {
|
||||
((AudioEffectListBoxItemData&)modelData).setValue(rowNum, this->effectComponent->slider.getValue());
|
||||
};
|
||||
if (i == 0) {
|
||||
bool isSelected = false;
|
||||
|
||||
bool isSelected = false;
|
||||
{
|
||||
juce::SpinLock::ScopedLockType lock(data.audioProcessor.effectsLock);
|
||||
// check if effect is in audioProcessor enabled effects
|
||||
for (auto processorEffect : data.audioProcessor.enabledEffects) {
|
||||
if (processorEffect->getId() == effect->getId()) {
|
||||
isSelected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
effectComponent->selected.setToggleState(isSelected, juce::dontSendNotification);
|
||||
effectComponent->selected.onClick = [this, effectComponent] {
|
||||
auto data = (AudioEffectListBoxItemData&)modelData;
|
||||
juce::SpinLock::ScopedLockType lock(data.audioProcessor.effectsLock);
|
||||
data.setSelected(rowNum, effectComponent->selected.getToggleState());
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
juce::SpinLock::ScopedLockType lock(data.audioProcessor.effectsLock);
|
||||
// check if effect is in audioProcessor enabled effects
|
||||
for (auto effect : data.audioProcessor.enabledEffects) {
|
||||
if (effect->getId() == data.getId(rn)) {
|
||||
isSelected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
listModel.addComponent(effectComponent);
|
||||
}
|
||||
effectComponent->selected.setToggleState(isSelected, juce::dontSendNotification);
|
||||
effectComponent->selected.onClick = [this] {
|
||||
auto data = (AudioEffectListBoxItemData&)modelData;
|
||||
juce::SpinLock::ScopedLockType lock(data.audioProcessor.effectsLock);
|
||||
((AudioEffectListBoxItemData&)modelData).setSelected(rowNum, this->effectComponent->selected.getToggleState());
|
||||
};
|
||||
|
||||
list.setModel(&listModel);
|
||||
list.setRowHeight(30);
|
||||
list.updateContent();
|
||||
addAndMakeVisible(list);
|
||||
}
|
||||
|
||||
EffectsListComponent::~EffectsListComponent() {}
|
||||
|
@ -51,15 +62,23 @@ void EffectsListComponent::paint(juce::Graphics& g) {
|
|||
void EffectsListComponent::resized() {
|
||||
auto area = getLocalBounds();
|
||||
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) {
|
||||
std::unique_ptr<EffectsListComponent> item(dynamic_cast<EffectsListComponent*>(existingComponentToUpdate));
|
||||
if (juce::isPositiveAndBelow(rowNumber, modelData.getNumItems())) {
|
||||
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, effectComponent);
|
||||
item = std::make_unique<EffectsListComponent>(listBox, (AudioEffectListBoxItemData&)modelData, rowNumber, data.getEffect(rowNumber));
|
||||
}
|
||||
return item.release();
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "../PluginProcessor.h"
|
||||
#include "../audio/Effect.h"
|
||||
#include "EffectComponent.h"
|
||||
#include "ComponentList.h"
|
||||
|
||||
// Application-specific data container
|
||||
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) {
|
||||
if (selected) {
|
||||
audioProcessor.enableEffect(data[itemIndex]);
|
||||
|
@ -83,16 +80,8 @@ struct AudioEffectListBoxItemData : public DraggableListBoxItemData
|
|||
}
|
||||
}
|
||||
|
||||
juce::String getText(int itemIndex) {
|
||||
return data[itemIndex]->getName();
|
||||
}
|
||||
|
||||
double getValue(int itemIndex) {
|
||||
return data[itemIndex]->getValue();
|
||||
}
|
||||
|
||||
juce::String getId(int itemIndex) {
|
||||
return data[itemIndex]->getId();
|
||||
std::shared_ptr<Effect> getEffect(int itemIndex) {
|
||||
return data[itemIndex];
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -100,14 +89,16 @@ struct AudioEffectListBoxItemData : public DraggableListBoxItemData
|
|||
class EffectsListComponent : public DraggableListBoxItem
|
||||
{
|
||||
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();
|
||||
|
||||
void paint(juce::Graphics& g) override;
|
||||
void resized() override;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<EffectComponent> effectComponent;
|
||||
std::shared_ptr<Effect> effect;
|
||||
ComponentListModel listModel;
|
||||
juce::ListBox list;
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectsListComponent)
|
||||
};
|
||||
|
@ -124,5 +115,8 @@ public:
|
|||
audioProcessor.updateEffectPrecedence();
|
||||
}
|
||||
|
||||
int getRowHeight(int row) override;
|
||||
bool hasVariableHeightRows() const 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"/>
|
||||
</GROUP>
|
||||
<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="Source/components/DraggableListBox.cpp"/>
|
||||
<FILE id="Y9NEGn" name="DraggableListBox.h" compile="0" resource="0"
|
||||
|
@ -99,6 +102,8 @@
|
|||
file="Source/components/VisualiserComponent.cpp"/>
|
||||
<FILE id="ZueyNl" name="VisualiserComponent.h" compile="0" resource="0"
|
||||
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="Source/components/VolumeComponent.cpp"/>
|
||||
<FILE id="MWkfTv" name="VolumeComponent.h" compile="0" resource="0"
|
||||
|
|
Ładowanie…
Reference in New Issue