Vital
Loading...
Searching...
No Matches
wavetable_component_list.cpp
Go to the documentation of this file.
2
3#include "paths.h"
4#include "skin.h"
7#include "wavetable_creator.h"
8#include "wavetable_group.h"
9
10namespace {
11 void componentRowCallback(int result, WavetableComponentList* component_list) {
12 if (component_list == nullptr)
13 return;
15 component_list->resetComponent();
16 else if (result == WavetableComponentList::kRemove)
17 component_list->removeComponent();
18 else if (result == WavetableComponentList::kMoveUp)
19 component_list->moveModifierUp();
20 else if (result == WavetableComponentList::kMoveDown)
21 component_list->moveModifierDown();
22 }
23
24 void componentRowGroupCallback(int result, WavetableComponentList* component_list) {
25 if (component_list == nullptr)
26 return;
28 component_list->resetComponent();
29 else if (result == WavetableComponentList::kRemove)
30 component_list->removeGroup();
31 else if (result == WavetableComponentList::kMoveUp)
32 component_list->moveGroupUp();
33 else if (result == WavetableComponentList::kMoveDown)
34 component_list->moveGroupDown();
35 }
36} // namespace
37
39 SynthSection("component list"), wavetable_creator_(wavetable_creator),
40 component_backgrounds_(kMaxRows, Shaders::kRoundedRectangleFragment), row_height_(0) {
43
44 addAndMakeVisible(component_container_);
45
48
49 create_component_button_ = std::make_unique<OpenGlToggleButton>("Add Source");
50 component_container_.addAndMakeVisible(create_component_button_.get());
52 create_component_button_->setUiButton(false);
53 create_component_button_->addListener(this);
54 create_component_button_->setJustification(Justification::centredLeft);
55
56 for (int i = 0; i < kMaxSources; ++i) {
57 add_modifier_buttons_[i] = std::make_unique<OpenGlToggleButton>("Add Modifier");
58 component_container_.addAndMakeVisible(add_modifier_buttons_[i].get());
59 addOpenGlComponent(add_modifier_buttons_[i]->getGlComponent());
60 add_modifier_buttons_[i]->setUiButton(false);
61 add_modifier_buttons_[i]->addListener(this);
62 add_modifier_buttons_[i]->setJustification(Justification::centredLeft);
63 }
64
65 for (int i = 0; i <= kMaxSources; ++i) {
66 plus_icons_[i] = std::make_unique<PlainShapeComponent>("plus");
67 plus_icons_[i]->setJustification(Justification::centredLeft);
68 component_container_.addAndMakeVisible(plus_icons_[i].get());
69 plus_icons_[i]->setVisible(false);
70 open_gl_components_.push_back(plus_icons_[i].get());
71 }
72 plus_icons_[kMaxSources]->setVisible(true);
73
74 addAndMakeVisible(viewport_);
75 viewport_.setViewedComponent(&component_container_);
76 viewport_.setScrollBarsShown(false, false, true, false);
78
79 scroll_bar_ = std::make_unique<OpenGlScrollBar>();
80 addAndMakeVisible(scroll_bar_.get());
81 addOpenGlComponent(scroll_bar_->getGlComponent());
82 scroll_bar_->addListener(this);
83 scroll_bar_->setAlwaysOnTop(true);
84 scroll_bar_->setShrinkLeft(true);
85
86 for (int i = 0; i < kMaxRows; ++i) {
87 names_[i] = std::make_unique<PlainTextComponent>(String(i), "");
88 names_[i]->setFontType(PlainTextComponent::kLight);
89 names_[i]->setInterceptsMouseClicks(false, false);
90 names_[i]->setJustification(Justification::centredLeft);
91 names_[i]->setScissor(true);
92 component_container_.addChildComponent(names_[i].get());
93 open_gl_components_.push_back(names_[i].get());
94
95 menu_buttons_[i] = std::make_unique<OpenGlShapeButton>(String(i));
96 menu_buttons_[i]->setShape(Paths::menu());
97 component_container_.addChildComponent(menu_buttons_[i].get());
98 addOpenGlComponent(menu_buttons_[i]->getGlComponent());
99 menu_buttons_[i]->addListener(this);
100 }
101}
102
106
110
112 Colour lighten = findColour(Skin::kLightenScreen, true);
114 scroll_bar_->setColor(lighten);
115
116 Colour ui_button_text = findColour(Skin::kUiButtonText, true);
117 for (int i = 0; i <= kMaxSources; ++i)
118 plus_icons_[i]->setColor(ui_button_text);
119
121}
122
124 static constexpr float kScrollBarWidth = 13.0f;
126
127 scroll_bar_->setBounds(0, 0, size_ratio_ * kScrollBarWidth, getHeight());
128 resetGroups();
129}
130
132 int num_groups = numGroups();
133 int index = 0;
134 for (int i = 0; i < num_groups; ++i) {
136 int num_components = group->numComponents();
137
138 for (int n = 0; n < num_components; ++n) {
139 WavetableComponent* component = group->getComponent(n);
140 String name = WavetableComponentFactory::getComponentName(component->getType());
141 names_[index]->setText(name);
142 names_[index]->setTextSize(row_height_ * 0.5f);
143 index++;
144 }
145 }
146
148}
149
151 viewport_.setScrollBarThickness(0.0f);
152 viewport_.setBounds(0, 0, getWidth(), getHeight());
153
156
157 int total_rows = 0;
158 int num_groups = numGroups();
159 for (int i = 0; i < num_groups; ++i)
160 total_rows += wavetable_creator_->getGroup(i)->numComponents() + 1;
161
162 int cell_height = row_height_ - 2;
163 int button_y = total_rows * row_height_ + 2;
164 create_component_button_->getGlComponent()->text().setBuffer(rounding * 0.5f + cell_height);
165 create_component_button_->setBounds(row_height_ - rounding, button_y, getWidth(), cell_height);
166 plus_icons_[kMaxSources]->setBounds(row_height_ - rounding * 0.5f, button_y, cell_height, cell_height);
167 component_container_.setBounds(0, 0, getWidth(), button_y + cell_height + row_height_ * 0.5f);
168
169 int index = 0;
170 int row = 0;
171 int width = getWidth();
172 float source_gl_x = (row_height_ - rounding) * 2.0f / width - 1.0f;
173 float modifier_gl_x = (2.0f * row_height_ - rounding) * 2.0f / width - 1.0f;
174 float gl_width = 2.0f + row_height_ * 2.0f / width;
175 int container_height = component_container_.getHeight();
176 float gl_height = 2.0f * cell_height / container_height;
177 Path menu = Paths::menu(cell_height);
178 Path plus = Paths::plus(cell_height);
179 plus_icons_[kMaxSources]->setShape(plus);
180
181 for (int i = 0; i < num_groups; ++i) {
183 int num_components = group->numComponents();
184
185 for (int n = 0; n < num_components; ++n) {
186 int y = row * row_height_ + 2;
187 float gl_y = 1.0f - y * 2.0f / container_height - gl_height;
188
189 menu_buttons_[index]->setBounds(width - cell_height, y, cell_height, cell_height);
190
191 if (n == 0) {
192 names_[index]->setBounds(row_height_, y, width - row_height_, cell_height);
193 component_backgrounds_.setQuad(index, source_gl_x, gl_y, gl_width, gl_height);
194 }
195 else {
196 names_[index]->setBounds(2 * row_height_, y, width - 2 * row_height_, cell_height);
197 component_backgrounds_.setQuad(index, modifier_gl_x, gl_y, gl_width, gl_height);
198 }
199 names_[index]->setVisible(true);
200 names_[index]->redrawImage(false);
201 menu_buttons_[index]->setShape(menu);
202 menu_buttons_[index]->setVisible(true);
203
204 index++;
205 row++;
206 }
207
208 int add_modifier_y = row * row_height_ + 2;
209 add_modifier_buttons_[i]->getGlComponent()->text().setBuffer(rounding * 0.5f + cell_height);
210 add_modifier_buttons_[i]->setBounds(2 * row_height_ - rounding, add_modifier_y, width, cell_height);
211 add_modifier_buttons_[i]->setVisible(true);
212
213 plus_icons_[i]->setBounds(2 * row_height_ - rounding * 0.5f, add_modifier_y, cell_height, cell_height);
214 plus_icons_[i]->setShape(plus);
215 plus_icons_[i]->setVisible(true);
216
217 row++;
218 }
219
220 for (int i = num_groups; i < kMaxSources; ++i) {
221 add_modifier_buttons_[i]->setVisible(false);
222 plus_icons_[i]->setVisible(false);
223 }
224
226 for (int i = index; i < kMaxRows; ++i) {
227 names_[i]->setVisible(false);
228 menu_buttons_[i]->setVisible(false);
229 }
230
232}
233
235 scroll_bar_->setRangeLimits(0.0, component_container_.getHeight());
236 scroll_bar_->setCurrentRange(scroll_bar_->getCurrentRangeStart(), viewport_.getHeight(), dontSendNotification);
237}
238
239std::pair<int, int> WavetableComponentList::getIndicesForRow(int row_index) {
240 int num_groups = numGroups();
241 int index = row_index;
242 for (int i = 0; i < num_groups; ++i) {
244 int num_components = group->numComponents();
245 if (index < num_components)
246 return { i, index };
247
248 index -= num_components;
249 }
250 return { -1, -1 };
251}
252
254 PopupItems options;
255
256 current_group_index_ = getIndicesForRow(row_index).first;
258 if (current_group_index_ < 0)
259 return;
260
261 if (current_group_index_ > 0)
262 options.addItem(kMoveUp, "Move Group Up");
264 options.addItem(kMoveDown, "Move Group Down");
265
266 options.addItem(kReset, "Reset Source");
267 options.addItem(kRemove, "Remove Group");
268
269 OpenGlShapeButton* button = menu_buttons_[row_index].get();
270 showPopupSelector(this, Point<int>(button->getX(), button->getBottom()), options,
271 [=](int selection) { componentRowGroupCallback(selection, this); });
272 button->setState(Button::buttonNormal);
273}
274
276 PopupItems options;
277
278 std::pair<int, int> indices = getIndicesForRow(row_index);
279 current_group_index_ = indices.first;
280 current_component_index_ = indices.second;
281 if (current_group_index_ < 0)
282 return;
283
285 options.addItem(kMoveUp, "Move Up");
287 options.addItem(kMoveDown, "Move Down");
288
289 options.addItem(kReset, "Reset");
290 options.addItem(kRemove, "Remove");
291 OpenGlShapeButton* button = menu_buttons_[row_index].get();
292 showPopupSelector(this, Point<int>(button->getX(), button->getBottom()), options,
293 [=](int selection) { componentRowCallback(selection, this); });
294 button->setState(Button::buttonNormal);
295}
296
298 if (getIndicesForRow(row_index).second == 0)
299 groupMenuClicked(row_index);
300 else
301 modifierMenuClicked(row_index);
302}
303
305 current_group_index_ = group_index;
306 PopupItems options;
307
308 for (int i = 0; i < WavetableComponentFactory::numModifierTypes(); ++i) {
311 }
312
313 Component* button = add_modifier_buttons_[current_group_index_].get();
314 showPopupSelector(this, Point<int>(button->getX(), button->getBottom()), options,
315 [=](int selection) { addComponent(selection); });
316}
317
319 PopupItems options;
320
321 for (int i = 0; i < WavetableComponentFactory::numSourceTypes(); ++i) {
324 }
325
326 showPopupSelector(this, Point<int>(create_component_button_->getX(), create_component_button_->getBottom()), options,
327 [=](int selection) { addSource(selection); });
328}
329
331 if (button == create_component_button_.get()) {
333 return;
334 }
335 for (int i = 0; i < kMaxSources; ++i) {
336 if (button == add_modifier_buttons_[i].get()) {
338 return;
339 }
340 }
341 for (int i = 0; i < kMaxRows; ++i) {
342 if (button == menu_buttons_[i].get()) {
343 menuClicked(i);
344 return;
345 }
346 }
347}
348
350 int offset = viewport_.getVerticalScrollBar().getCurrentRangeStart();
351 for (Listener* listener : listeners_)
352 listener->componentsScrolled(-offset);
353
354 scroll_bar_->setCurrentRange(offset, viewport_.getHeight(), dontSendNotification);
355}
356
357void WavetableComponentList::scrollBarMoved(ScrollBar* scroll_bar, double range_start) {
358 viewport_.setViewPosition({ 0, (int)range_start });
359}
360
373
375 WavetableGroup* to_remove = wavetable_creator_->getGroup(index);
376
377 for (int i = 0; i < to_remove->numComponents(); ++i)
381}
382
396
406
417
419 if (current_group_index_ >= 0) {
421 int num_components = group->numComponents();
422 for (int i = 0; i < num_components; ++i)
424
426 resetGroups();
427 }
428
430}
431
440
449
458
468
470 resetGroups();
471 for (Listener* listener : listeners_)
472 listener->componentAdded(component);
473}
474
476 resetGroups();
477 for (Listener* listener : listeners_)
478 listener->componentRemoved(component);
479}
480
482 for (Listener* listener : listeners_)
483 listener->componentsReordered();
485}
486
488 for (Listener* listener : listeners_)
489 listener->componentsChanged();
490}
void setQuad(int i, float x, float y, float w, float h)
Sets the position and size of a quad in normalized device space.
Definition open_gl_multi_quad.h:313
void setTargetComponent(Component *target_component)
Sets a target component to help position the quads.
Definition open_gl_multi_quad.h:358
void setNumQuads(int num_quads)
Sets how many quads will actually be drawn (up to max_quads).
Definition open_gl_multi_quad.h:92
force_inline void setColor(Colour color)
Sets the base color for the quads.
Definition open_gl_multi_quad.h:102
void setRounding(float rounding)
Sets the rounding radius of the quads.
Definition open_gl_multi_quad.h:347
A ToggleButton that uses an OpenGlShapeButtonComponent for its rendering.
Definition synth_button.h:110
static Path plus(int width)
Definition paths.h:305
static Path menu()
Creates a menu icon path (three horizontal lines).
Definition paths.h:271
@ kLight
Definition open_gl_image_component.h:309
Manages and provides access to vertex and fragment shaders used by the OpenGL rendering pipeline.
Definition shaders.h:19
@ kLabelBackgroundRounding
Definition skin.h:74
@ kUiButtonText
Definition skin.h:193
@ kLightenScreen
Definition skin.h:141
Base class for all synthesizer sections, providing UI layout, painting, and interaction logic.
Definition synth_section.h:193
std::vector< OpenGlComponent * > open_gl_components_
Definition synth_section.h:804
void paintOpenGlChildrenBackgrounds(Graphics &g)
Paints the backgrounds for all OpenGL child components.
Definition synth_section.cpp:267
virtual void resized() override
Called when the component is resized. Arranges layout of child components.
Definition synth_section.cpp:35
void showPopupSelector(Component *source, Point< int > position, const PopupItems &options, std::function< void(int)> callback, std::function< void()> cancel={ })
Shows a popup selector with options.
Definition synth_section.cpp:119
float size_ratio_
Definition synth_section.h:821
float findValue(Skin::ValueId value_id) const
Finds a value in the skin overrides or from the parent if not found locally.
Definition synth_section.cpp:18
void addOpenGlComponent(OpenGlComponent *open_gl_component, bool to_beginning=false)
Definition synth_section.cpp:489
static WavetableComponent * createComponent(ComponentType type)
Creates a new WavetableComponent instance of a given enumerated type.
Definition wavetable_component_factory.cpp:19
ComponentType
Enumerates all known WavetableComponents, including sources and modifiers.
Definition wavetable_component_factory.h:28
@ kBeginModifierTypes
Definition wavetable_component_factory.h:35
static ComponentType getModifierType(int type)
Converts an integer index to a modifier ComponentType.
Definition wavetable_component_factory.h:104
static ComponentType getSourceType(int type)
Converts an integer index to a source ComponentType.
Definition wavetable_component_factory.h:96
static int numSourceTypes()
Returns the number of source types defined.
Definition wavetable_component_factory.h:57
static std::string getComponentName(ComponentType type)
Gets the human-readable name of a component from its enumerated type.
Definition wavetable_component_factory.cpp:75
static int numModifierTypes()
Returns the number of modifier types defined.
Definition wavetable_component_factory.h:64
A base class representing a component in a wavetable synthesis chain.
Definition wavetable_component.h:32
void reset()
Clears all keyframes and inserts a default one at position 0.
Definition wavetable_component.cpp:62
WavetableKeyframe * insertNewKeyframe(int position)
Inserts a new keyframe at the given position, creating and sorting it into the array.
Definition wavetable_component.cpp:8
virtual WavetableComponentFactory::ComponentType getType()=0
Returns the type of this WavetableComponent.
Interface for objects wanting to know when the component list changes.
Definition wavetable_component_list.h:86
A UI component that lists and manages the wavetable sources and modifiers.
Definition wavetable_component_list.h:65
void paintBackground(Graphics &g) override
Overridden to paint the background and related elements.
Definition wavetable_component_list.cpp:111
std::unique_ptr< OpenGlToggleButton > add_modifier_buttons_[kMaxSources]
Buttons to add modifiers.
Definition wavetable_component_list.h:330
void moveModifierUp()
Moves the currently selected modifier up in its group.
Definition wavetable_component_list.cpp:450
int current_component_index_
The currently selected component index.
Definition wavetable_component_list.h:324
std::unique_ptr< PlainShapeComponent > plus_icons_[kMaxSources+1]
Plus icons next to buttons.
Definition wavetable_component_list.h:331
int numGroups()
Returns the number of groups in the wavetable.
Definition wavetable_component_list.h:262
int row_height_
Height of each row in pixels.
Definition wavetable_component_list.h:332
WavetableComponentViewport viewport_
Viewport for scrolling the component list.
Definition wavetable_component_list.h:318
void modifierMenuClicked(int row_index)
Displays a menu for the modifier row at the given index.
Definition wavetable_component_list.cpp:275
void addComponent(int type)
Adds a new component (modifier) of the given type.
Definition wavetable_component_list.cpp:383
void positionGroups()
Positions the groups and modifiers in the scrollable list.
Definition wavetable_component_list.cpp:150
std::unique_ptr< OpenGlScrollBar > scroll_bar_
A custom scrollbar for vertical scrolling.
Definition wavetable_component_list.h:320
void moveModifierDown()
Moves the currently selected modifier down in its group.
Definition wavetable_component_list.cpp:459
std::unique_ptr< OpenGlShapeButton > menu_buttons_[kMaxRows]
Menu buttons for each row.
Definition wavetable_component_list.h:328
void menuClicked(int row_index)
Displays a general menu for the given row index, determining if it's a group or modifier.
Definition wavetable_component_list.cpp:297
void buttonClicked(Button *button) override
Overridden to handle button clicks (menus, add source/modifier).
Definition wavetable_component_list.cpp:330
WavetableComponentList(WavetableCreator *wavetable_creator)
Constructs a WavetableComponentList for managing sources and modifiers.
Definition wavetable_component_list.cpp:38
std::unique_ptr< PlainTextComponent > names_[kMaxRows]
Text labels for each component row.
Definition wavetable_component_list.h:327
void removeGroup(int index)
Removes a source group by index.
Definition wavetable_component_list.cpp:374
void groupMenuClicked(int row_index)
Displays a menu for the group row at the given index.
Definition wavetable_component_list.cpp:253
void init()
Initializes the component list after construction.
Definition wavetable_component_list.cpp:107
static constexpr int kMaxSources
Maximum number of source groups.
Definition wavetable_component_list.h:68
std::vector< Listener * > listeners_
Listeners for changes in the component list.
Definition wavetable_component_list.h:325
void addSource(int index)
Adds a new source of the given index (maps to a component type).
Definition wavetable_component_list.cpp:361
void removeGroup()
Removes the currently selected group.
Definition wavetable_component_list.cpp:418
void componentsScrolled() override
Called when the components are scrolled.
Definition wavetable_component_list.cpp:349
WavetableCreator * wavetable_creator_
The wavetable creator managing group/components.
Definition wavetable_component_list.h:322
void notifyComponentAdded(WavetableComponent *component)
Notifies listeners that a component was added.
Definition wavetable_component_list.cpp:469
void addModifierClicked(int group_index)
Called when the "Add Modifier" button is clicked for a particular group.
Definition wavetable_component_list.cpp:304
Component component_container_
Container holding all UI elements for the list.
Definition wavetable_component_list.h:319
void removeComponent()
Removes the currently selected component.
Definition wavetable_component_list.cpp:397
void moveGroupUp()
Moves the currently selected group up in the list.
Definition wavetable_component_list.cpp:432
std::unique_ptr< OpenGlToggleButton > create_component_button_
Button to add a new source.
Definition wavetable_component_list.h:329
void notifyComponentRemoved(WavetableComponent *component)
Notifies listeners that a component was removed.
Definition wavetable_component_list.cpp:475
OpenGlMultiQuad component_backgrounds_
Background rectangles for each row.
Definition wavetable_component_list.h:326
std::pair< int, int > getIndicesForRow(int row_index)
Retrieves the group and component indices for a given row index.
Definition wavetable_component_list.cpp:239
void setScrollBarRange()
Sets the scrollbar range based on content size.
Definition wavetable_component_list.cpp:234
int current_group_index_
The currently selected group index.
Definition wavetable_component_list.h:323
void moveGroupDown()
Moves the currently selected group down in the list.
Definition wavetable_component_list.cpp:441
static constexpr int kMaxRows
Maximum number of rows for components.
Definition wavetable_component_list.h:67
void resetGroups()
Resets the display of groups and modifiers in the UI.
Definition wavetable_component_list.cpp:131
void addSourceClicked()
Called when the "Add Source" button is clicked.
Definition wavetable_component_list.cpp:318
void notifyComponentsReordered()
Notifies listeners that components have been reordered.
Definition wavetable_component_list.cpp:481
void resized() override
Overridden to layout and refresh the UI.
Definition wavetable_component_list.cpp:123
void scrollBarMoved(ScrollBar *scroll_bar, double range_start) override
Called when the scroll bar moves.
Definition wavetable_component_list.cpp:357
void clear()
Clears the list of sources and modifiers.
Definition wavetable_component_list.cpp:103
void notifyComponentsChanged()
Notifies listeners that components have changed.
Definition wavetable_component_list.cpp:487
@ kMoveUp
Definition wavetable_component_list.h:77
@ kReset
Definition wavetable_component_list.h:76
@ kRemove
Definition wavetable_component_list.h:79
@ kMoveDown
Definition wavetable_component_list.h:78
void resetComponent()
Resets the currently selected component to default state.
Definition wavetable_component_list.cpp:407
void addListener(Listener *listener)
Adds a listener that will be notified on scroll events.
Definition wavetable_component_list.h:39
A class responsible for creating complete wavetables from groups of wavetable components.
Definition wavetable_creator.h:27
void removeGroup(int index)
Definition wavetable_creator.cpp:51
WavetableGroup * getGroup(int index) const
Retrieves a WavetableGroup by index.
Definition wavetable_creator.h:71
void moveUp(int index)
Definition wavetable_creator.cpp:37
void addGroup(WavetableGroup *group)
Definition wavetable_creator.h:53
void moveDown(int index)
Definition wavetable_creator.cpp:44
A class representing a group of WavetableComponents combined to form part of a wavetable.
Definition wavetable_group.h:24
void addComponent(WavetableComponent *component)
Adds a new WavetableComponent to this group.
Definition wavetable_group.h:44
WavetableComponent * getComponent(int index) const
Retrieves a component by index.
Definition wavetable_group.h:92
void moveUp(int index)
Moves a component one position up in the ordering.
Definition wavetable_group.cpp:20
void removeComponent(int index)
Removes a component at a given index.
Definition wavetable_group.cpp:36
int numComponents() const
Gets the number of WavetableComponents in this group.
Definition wavetable_group.h:84
void moveDown(int index)
Moves a component one position down in the ordering.
Definition wavetable_group.cpp:28
A hierarchical structure of popup menu items for a selector component.
Definition synth_section.h:29
void addItem(int sub_id, const std::string &sub_name, bool sub_selected=false)
Adds a new item as a submenu entry.
Definition synth_section.h:51