Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A lighter weight list view #133

Merged
merged 2 commits into from
Nov 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ add_library(${PROJECT_NAME} STATIC
src/sst/jucegui/components/HSliderFilled.cpp
src/sst/jucegui/components/JogUpDownButton.cpp
src/sst/jucegui/components/Knob.cpp
src/sst/jucegui/components/ListView.cpp
src/sst/jucegui/components/MenuButton.cpp
src/sst/jucegui/components/MultiSwitch.cpp
src/sst/jucegui/components/NamedPanel.cpp
Expand Down
180 changes: 180 additions & 0 deletions examples/component-demo/ListViewDemo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/*
* sst-jucegui - an open source library of juce widgets
* built by Surge Synth Team.
*
* Copyright 2023-2024, various authors, as described in the GitHub
* transaction log.
*
* sst-jucegui is released under the MIT license, as described
* by "LICENSE.md" in this repository. This means you may use this
* in commercial software if you are a JUCE Licensee. If you use JUCE
* in the open source / GPL3 context, your combined work must be
* released under GPL3.
*
* All source in sst-jucegui available at
* https://github.com/surge-synthesizer/sst-jucegui
*/

#ifndef SSTJUCEGUI_EXAMPLES_COMPONENT_DEMO_LISTVIEWDEMO_H
#define SSTJUCEGUI_EXAMPLES_COMPONENT_DEMO_LISTVIEWDEMO_H

#include <string>
#include <sst/jucegui/components/ListView.h>
#include <sst/jucegui/components/NamedPanel.h>
#include <sst/jucegui/components/WindowPanel.h>
#include <sst/jucegui/components/TextPushButton.h>
#include "ExampleUtils.h"

struct ListViewDemo : public sst::jucegui::components::WindowPanel
{
static constexpr const char *name = "ListViews";

struct AList : juce::Component
{
struct RowComp : juce::Component
{
AList *parent{nullptr};
RowComp(AList *parent) : parent(parent) {}
uint32_t row{0};
bool selected{false};
void setRow(uint32_t r)
{
row = r;
repaint();
}
void paint(juce::Graphics &g) override
{
g.fillAll(juce::Colour((row * 17) % 255, 0, 120));
if (selected)
g.setColour(juce::Colours::white);
else
g.setColour(juce::Colours::green);
g.setFont(12);
g.drawText(std::to_string(row), getLocalBounds(), juce::Justification::centred);
g.drawRect(getLocalBounds().reduced(1));
}
void mouseDown(const juce::MouseEvent &e) override
{
parent->listView->rowSelected(
row, !selected,
sst::jucegui::components::ListView::selectionAddActionForModifier(e.mods));
}
};
int rowCount{275}, rowHeight{18};
AList()
{
listView = std::make_unique<sst::jucegui::components::ListView>();
addAndMakeVisible(*listView);

for (int i = 0; i < 3; ++i)
{
auto tb = std::make_unique<sst::jucegui::components::TextPushButton>();
auto amt = (i == 0 ? 275 : i == 1 ? 11 : 750);
tb->setLabel(std::to_string(amt) + " rows");
tb->setOnCallback([amt, w = juce::Component::SafePointer(this)]() {
if (!w)
return;
w->rowCount = amt;
w->listView->refresh();
});
addAndMakeVisible(*tb);
buttons[i] = std::move(tb);
}

for (int i = 3; i < 5; ++i)
{
auto tb = std::make_unique<sst::jucegui::components::TextPushButton>();
auto amt = (i == 3 ? 18 : 67);
tb->setLabel(std::to_string(amt) + " height");
tb->setOnCallback([amt, w = juce::Component::SafePointer(this)]() {
if (!w)
return;
w->rowHeight = amt;
w->listView->refresh();
});
addAndMakeVisible(*tb);
buttons[i] = std::move(tb);
}

for (int i = 5; i < 7; ++i)
{
auto tb = std::make_unique<sst::jucegui::components::TextPushButton>();
auto amt =
(i == 5 ? sst::jucegui::components::ListView::SelectionMode::SINGLE_SELECTION
: sst::jucegui::components::ListView::SelectionMode::MULTI_SELECTION);
tb->setLabel(i == 5 ? "SingSel" : "MultSel");
tb->setOnCallback([amt, w = juce::Component::SafePointer(this)]() {
if (!w)
return;
w->listView->setSelectionMode(amt);
w->listView->refresh();
});
addAndMakeVisible(*tb);
buttons[i] = std::move(tb);
}

listView->getRowHeight = []() { return 18; };
listView->getRowHeight = [w = juce::Component::SafePointer(this)]() {
if (!w)
return 0;
return w->rowHeight;
};
listView->getRowCount = [w = juce::Component::SafePointer(this)]() {
if (!w)
return 0;
return w->rowCount;
};
listView->makeRowComponent = [this]() { return std::make_unique<RowComp>(this); };
listView->assignComponentToRow = [](const auto &rc, auto r) {
auto rcomp = dynamic_cast<RowComp *>(rc.get());
if (rcomp)
{
rcomp->setRow(r);
}
};
listView->setRowSelection = [](const auto &rc, auto r) {
auto rcomp = dynamic_cast<RowComp *>(rc.get());
if (rcomp)
{
rcomp->selected = r;
rcomp->repaint();
}
};
listView->refresh();
}
~AList() {}
void resized() override
{
listView->setBounds(getLocalBounds().withTrimmedTop(25));
auto br = getLocalBounds().withHeight(22);
auto bw = br.getWidth() / buttons.size();
br = br.withWidth(bw);
for (const auto &b : buttons)
{
if (b)
{
b->setBounds(br.reduced(1));
}
br = br.translated(bw, 0);
}
}

std::unique_ptr<sst::jucegui::components::ListView> listView;

std::array<std::unique_ptr<sst::jucegui::components::TextPushButton>, 7> buttons;
};

ListViewDemo()
{
panelOne = std::make_unique<sst::jucegui::components::NamedPanel>("List View");
panelOne->setContentAreaComponent(std::make_unique<AList>());

addAndMakeVisible(*panelOne);
}

void resized() override { panelOne->setBounds(getLocalBounds().reduced(10)); }

std::unique_ptr<sst::jucegui::components::NamedPanel> panelOne;
};

#endif // SST_JUCEGUI_ListViewDemo_H
5 changes: 5 additions & 0 deletions examples/component-demo/SSTJuceGuiDemo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "SevenSegmentDemo.h"
#include "VUMeterDemo.h"
#include "ZoomContainerDemo.h"
#include "ListViewDemo.h"

struct SSTJuceGuiDemo : public juce::JUCEApplication
{
Expand Down Expand Up @@ -133,6 +134,10 @@ struct SSTJuceGuiDemo : public juce::JUCEApplication
mk<VUMeterDemo>();
mk<GlyphDemo>();
mk<ZoomContainerDemo>();
mk<ListViewDemo>();

// Comment this out to also auto launch the last item
buttons.back()->onClick();
}
void paint(juce::Graphics &g) override { g.fillAll(juce::Colours::black); }
void resized() override
Expand Down
96 changes: 96 additions & 0 deletions include/sst/jucegui/components/ListView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* sst-jucegui - an open source library of juce widgets
* built by Surge Synth Team.
*
* Copyright 2023-2024, various authors, as described in the GitHub
* transaction log.
*
* sst-jucegui is released under the MIT license, as described
* by "LICENSE.md" in this repository. This means you may use this
* in commercial software if you are a JUCE Licensee. If you use JUCE
* in the open source / GPL3 context, your combined work must be
* released under GPL3.
*
* All source in sst-jucegui available at
* https://github.com/surge-synthesizer/sst-jucegui
*/

#ifndef INCLUDE_SST_JUCEGUI_COMPONENTS_LISTVIEW_H
#define INCLUDE_SST_JUCEGUI_COMPONENTS_LISTVIEW_H

#include <memory>
#include <string>
#include <optional>
#include <juce_gui_basics/juce_gui_basics.h>
#include <sst/jucegui/style/StyleAndSettingsConsumer.h>
#include <sst/jucegui/style/StyleSheet.h>

#include "BaseStyles.h"
#include "Viewport.h"

namespace sst::jucegui::components
{
struct ListView : public juce::Component,
public style::StyleConsumer,
public style::SettingsConsumer
{
struct Styles : base_styles::Base
{
SCLASS(listview);

static void initialize()
{
style::StyleSheet::addClass(styleClass).withBaseClass(base_styles::Base::styleClass);
}
};

enum ComponentStrategy
{
BRUTE_FORCE, // just make a component per row.
BRUTE_FORCE_NO_REUSE
} strategy{BRUTE_FORCE};

enum SelectionMode
{
NO_SELECTION,
SINGLE_SELECTION,
MULTI_SELECTION
} selectionMode{SINGLE_SELECTION};

ListView(const juce::String &cn = juce::String());
~ListView();

void refresh();

void resized() override
{
viewPort->setBounds(getLocalBounds());
refresh();
}

void setSelectionMode(SelectionMode s);

enum SelectionAddAction
{
SINGLE,
ADD_NON_CONTIGUOUS,
ADD_CONTIGUOUS
};
void rowSelected(uint32_t r, bool select, SelectionAddAction addMode = SINGLE);
static SelectionAddAction selectionAddActionForModifier(const juce::ModifierKeys &);

std::function<uint32_t()> getRowCount{nullptr};
std::function<uint32_t()> getRowHeight{nullptr};
std::function<std::unique_ptr<juce::Component>()> makeRowComponent{nullptr};
std::function<void(const std::unique_ptr<juce::Component> &, uint32_t)> assignComponentToRow{
nullptr};
std::function<void(const std::unique_ptr<juce::Component> &, bool)> setRowSelection{nullptr};

std::unique_ptr<Viewport> viewPort;

struct Innards;
std::unique_ptr<Innards> innards;
};
} // namespace sst::jucegui::components

#endif // LISTVIEW_H
Loading
Loading