Mema
Memory Matrix — multi-channel audio matrix monitor and router
Loading...
Searching...
No Matches
MemaUIComponent.cpp
Go to the documentation of this file.
1/* Copyright (c) 2024, Christian Ahrens
2 *
3 * This file is part of Mema <https://github.com/ChristianAhrens/Mema>
4 *
5 * This tool is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU Lesser General Public License version 3.0 as published
7 * by the Free Software Foundation.
8 *
9 * This tool is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 * details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this tool; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19#include "MemaUIComponent.h"
20
21#include "AboutComponent.h"
23
24#include <AppConfigurationBase.h>
25
26//==============================================================================
27class LoadBar : public juce::Component
28{
29public:
30 LoadBar(juce::String label, bool showPercent = true, bool showMax = true) : juce::Component::Component() { m_label = label; m_showPercent = showPercent; m_showMax = showMax; }
32
33 //==============================================================================
34 void paint(Graphics& g) override
35 {
36 auto margin = 1.0f;
37
38 auto bounds = getLocalBounds().toFloat();
39
40 g.setColour(getLookAndFeel().findColour(juce::LookAndFeel_V4::ColourScheme::windowBackground));
41 g.fillRect(bounds);
42
43 auto barBounds = bounds.reduced(margin);
44
45 auto loadBarHeight = barBounds.getHeight();
46 if (!m_loadsPercent.empty())
47 loadBarHeight = (barBounds.getHeight() / m_loadsPercent.size());
48
49 auto avgLoad = 0;
50 auto maxLoad = 0;
51 int i = 0;
52 for (auto & loadPercentKV : m_loadsPercent)
53 {
54 auto loadPercent = loadPercentKV.second;
55 auto alert = m_alerts[loadPercentKV.first];
56
57 auto normalPercent = loadPercent;
58 auto warningPercent = 0;
59 auto criticalPercent = 0;
60 if (loadPercent > 75)
61 {
62 normalPercent = 75;
63 warningPercent = loadPercent - normalPercent;
64 }
65 if (loadPercent > 95)
66 {
67 warningPercent = 20;
68 criticalPercent = loadPercent - normalPercent - warningPercent;
69 }
70 if (loadPercent >= 100)
71 {
72 criticalPercent = 5;
73 }
74
75 auto individualBarBounds = barBounds.removeFromTop(loadBarHeight);
76 if (i < m_loadsPercent.size()-1)
77 individualBarBounds.removeFromBottom(margin);
78
79 if (alert)
80 {
81 g.setColour(juce::Colour(0xff, 0x30, 0x02).withAlpha(0.8f));
82 g.fillRect(individualBarBounds);
83 }
84 else
85 {
86 g.setColour(getLookAndFeel().findColour(juce::TextButton::ColourIds::buttonColourId));
87 g.fillRect(individualBarBounds.removeFromLeft(individualBarBounds.getWidth() * (float(normalPercent) / 100.0f)));
88 if (warningPercent > 0)
89 {
90 g.setColour(juce::Colour(0xff, 0xe8, 0x00).withAlpha(0.5f));
91 g.fillRect(individualBarBounds.removeFromLeft(individualBarBounds.getWidth() * (float(warningPercent) / 25.0f)));
92 }
93 if (criticalPercent > 0)
94 {
95 g.setColour(juce::Colour(0xff, 0x40, 0x02).withAlpha(0.5f));
96 g.fillRect(individualBarBounds.removeFromLeft(individualBarBounds.getWidth() * (float(criticalPercent) / 5.0f)));
97 }
98 }
99
100 avgLoad += loadPercent;
101 if (maxLoad < loadPercent)
102 maxLoad = loadPercent;
103 i++;
104 }
105
106 if (!m_loadsPercent.empty())
107 avgLoad /= int(m_loadsPercent.size());
108
109 auto labelText = m_label;
110 if (m_showPercent)
111 labelText += juce::String(" ") + juce::String(m_showMax ? maxLoad : avgLoad) + juce::String("%");
112
113 g.setColour(getLookAndFeel().findColour(juce::TextButton::ColourIds::textColourOnId));
114 g.drawText(labelText, bounds, juce::Justification::centred);
115 };
116 void mouseUp(const MouseEvent& event) override
117 {
118 if (contains(event.position))
119 JUCEAppBasics::ServiceTopologyManager::showServiceTopologyMenu(m_sessionTopology);
120 };
121
122 //==============================================================================
123 void setSessionTopology(const JUCEAppBasics::SessionServiceTopology& sessionTopology)
124 {
125 m_sessionTopology = sessionTopology;
126 }
127
128 //==============================================================================
129 void setLoadPercent(int loadPercent, int id = 0)
130 {
131 m_loadsPercent[id] = loadPercent;
132 repaint();
133 };
134 void setAlert(bool alert, int id = 0)
135 {
136 m_alerts[id] = alert;
137 repaint();
138 };
139
140private:
141 std::map<int, int> m_loadsPercent;
142 std::map<int, bool> m_alerts;
143 juce::String m_label;
144 bool m_showPercent = false;
145 bool m_showMax = false;
146 JUCEAppBasics::SessionServiceTopology m_sessionTopology;
147};
148
149//==============================================================================
150class EmptySpace :public juce::Component
151{
152public:
153 EmptySpace() : juce::Component::Component() {}
155
156 //==============================================================================
157 void paint(Graphics& g) override
158 {
159 g.fillAll(getLookAndFeel().findColour(juce::ResizableWindow::backgroundColourId));
160 };
161};
162
163namespace Mema
164{
165
167 : juce::Component()
168{
169 setOpaque(true);
170
171 m_toggleStandaloneWindowButton = std::make_unique<juce::DrawableButton>("Show as standalone window", juce::DrawableButton::ButtonStyle::ImageFitted);
172 m_toggleStandaloneWindowButton->setTooltip("Show as standalone window");
173 m_toggleStandaloneWindowButton->onClick = [this] { if (onToggleStandaloneWindow) onToggleStandaloneWindow(!m_isStandaloneWindow); };
174#if JUCE_LINUX
175 m_toggleStandaloneWindowButton->setEnabled(false);
176#endif
177 addAndMakeVisible(m_toggleStandaloneWindowButton.get());
178
179 m_audioSetupButton = std::make_unique<juce::DrawableButton>("Audio Device Setup", juce::DrawableButton::ButtonStyle::ImageFitted);
180 m_audioSetupButton->setTooltip("Audio Device Setup");
181 m_audioSetupButton->onClick = [this] {
183 };
184 addAndMakeVisible(m_audioSetupButton.get());
185
186 // default lookandfeel is follow local, therefor none selected
187 m_settingsItems[MemaSettingsOption::LookAndFeel_Automatic] = std::make_pair("Automatic", 1);
188 m_settingsItems[MemaSettingsOption::LookAndFeel_Dark] = std::make_pair("Dark", 0);
189 m_settingsItems[MemaSettingsOption::LookAndFeel_Light] = std::make_pair("Light", 0);
190 // default metering colour is green
191 m_settingsItems[MemaSettingsOption::MeteringColour_Green] = std::make_pair("Green", 1);
192 m_settingsItems[MemaSettingsOption::MeteringColour_Red] = std::make_pair("Red", 0);
193 m_settingsItems[MemaSettingsOption::MeteringColour_Blue] = std::make_pair("Blue", 0);
194 m_settingsItems[MemaSettingsOption::MeteringColour_Pink] = std::make_pair("Anni Pink", 0);
195 m_settingsItems[MemaSettingsOption::MeteringColour_Laser] = std::make_pair("Laser", 0);
196 m_appSettingsButton = std::make_unique<juce::DrawableButton>("Application settings", juce::DrawableButton::ButtonStyle::ImageFitted);
197 m_appSettingsButton->setTooltip("Application settings");
198 m_appSettingsButton->onClick = [this] {
199 juce::PopupMenu lookAndFeelSubMenu;
201 lookAndFeelSubMenu.addItem(i, m_settingsItems[i].first, true, m_settingsItems[i].second == 1);
202
203 juce::PopupMenu meteringColourSubMenu;
205 meteringColourSubMenu.addItem(i, m_settingsItems[i].first, true, m_settingsItems[i].second == 1);
206
207 juce::PopupMenu settingsMenu;
208 settingsMenu.addSubMenu("LookAndFeel", lookAndFeelSubMenu);
209 settingsMenu.addSubMenu("Metering colour", meteringColourSubMenu);
210 settingsMenu.addSeparator();
211 auto loadDrawable = juce::Drawable::createFromSVG(*juce::XmlDocument::parse(BinaryData::folder_open24px_svg).get());
212 loadDrawable->replaceColour(juce::Colours::black, getLookAndFeel().findColour(juce::TextButton::ColourIds::textColourOnId));
213 settingsMenu.addItem(MemaSettingsOption::LoadConfig, "Load config...", true, false, std::move(loadDrawable));
214 auto saveDrawable = juce::Drawable::createFromSVG(*juce::XmlDocument::parse(BinaryData::save24px_svg).get());
215 saveDrawable->replaceColour(juce::Colours::black, getLookAndFeel().findColour(juce::TextButton::ColourIds::textColourOnId));
216 settingsMenu.addItem(MemaSettingsOption::SaveConfig, "Save config...", true, false, std::move(saveDrawable));
217 settingsMenu.showMenuAsync(juce::PopupMenu::Options(), [=](int selectedId) { handleSettingsMenuResult(selectedId); });
218 };
219 addAndMakeVisible(m_appSettingsButton.get());
220
221 m_aboutComponent = std::make_unique<AboutComponent>(BinaryData::MemaRect_png, BinaryData::MemaRect_pngSize);
222 m_aboutButton = std::make_unique<juce::DrawableButton>("About", juce::DrawableButton::ButtonStyle::ImageFitted);
223 m_aboutButton->setTooltip(juce::String("About") + juce::JUCEApplication::getInstance()->getApplicationName());
224 m_aboutButton->onClick = [this] {
225 juce::PopupMenu aboutMenu;
226 aboutMenu.addCustomItem(1, std::make_unique<CustomAboutItem>(m_aboutComponent.get(), juce::Rectangle<int>(250, 250)), nullptr, juce::String("Info about") + juce::JUCEApplication::getInstance()->getApplicationName());
227 aboutMenu.showMenuAsync(juce::PopupMenu::Options());
228 };
229 addAndMakeVisible(m_aboutButton.get());
230
231 m_powerButton = std::make_unique<juce::DrawableButton>("Quit application", juce::DrawableButton::ButtonStyle::ImageFitted);
232 m_powerButton->setTooltip("Quit application");
233 m_powerButton->onClick = [this] {
234 juce::JUCEApplication::getInstance()->quit();
235 };
236 addAndMakeVisible(m_powerButton.get());
237
238 m_emptySpace = std::make_unique<EmptySpace>();
239 addAndMakeVisible(m_emptySpace.get());
240
241 m_sysLoadBar = std::make_unique<LoadBar>("PLoad");
242 addAndMakeVisible(m_sysLoadBar.get());
243
244 m_netHealthBar = std::make_unique<LoadBar>("NLoad");
245 addAndMakeVisible(m_netHealthBar.get());
246
247 juce::Desktop::getInstance().addDarkModeSettingListener(this);
248 darkModeSettingChanged(); // initially trigger correct colourscheme
249
250}
251
253{
254 juce::Desktop::getInstance().removeDarkModeSettingListener(this);
255
256 if (onDeleted)
257 onDeleted();
258}
259
260
262{
263 m_isStandaloneWindow = standalone;
264
265 if (standalone)
266 {
267 int styleFlags = juce::ComponentPeer::windowHasDropShadow
268 | juce::ComponentPeer::windowAppearsOnTaskbar
269 | juce::ComponentPeer::windowHasTitleBar;
270
271 setVisible(true);
273
274 lookAndFeelChanged(); // trigger lookandfeel change to update icon (dock vs undock)
275 }
276 else
277 {
279 setVisible(false);
280 }
281}
282
284{
285 return m_isStandaloneWindow;
286}
287
288void MemaUIComponent::setEditorComponent(juce::Component* editorComponent)
289{
290 if (m_editorComponent)
291 removeChildComponent(m_editorComponent);
292
293 m_editorComponent = editorComponent;
294
296}
297
298void MemaUIComponent::handleEditorSizeChangeRequest(const juce::Rectangle<int>& requestedSize)
299{
300 auto width = requestedSize.getWidth();
301 auto height = requestedSize.getHeight() + sc_buttonSize;
302
303 if (width < (2 * sc_loadNetWidth + 5 * sc_buttonSize))
304 width = 2 * sc_loadNetWidth + 5 * sc_buttonSize;
305
307}
308
310{
311 if (m_sysLoadBar)
312 m_sysLoadBar->setLoadPercent(loadPercent);
313}
314
315void MemaUIComponent::updateNetworkUsage(const std::map<int, std::pair<double, bool>>& netLoads)
316{
317 if (m_netHealthBar)
318 {
319 for (auto const& netLoad : netLoads)
320 {
321 m_netHealthBar->setLoadPercent(int(netLoad.second.first * 100.0), netLoad.first);
322 m_netHealthBar->setAlert(netLoad.second.second, netLoad.first);
323 }
324 }
325}
326
327void MemaUIComponent::updateSessionServiceTopology(const JUCEAppBasics::SessionServiceTopology& sessionServiceTopology)
328{
329 if (m_netHealthBar)
330 m_netHealthBar->setSessionTopology(sessionServiceTopology);
331}
332
333void MemaUIComponent::paint(Graphics &g)
334{
335 g.fillAll(getLookAndFeel().findColour(juce::LookAndFeel_V4::ColourScheme::defaultFill));
336}
337
339{
340 auto safeBounds = getLocalBounds();
341
342 auto margin = 1;
343 auto setupElementArea = safeBounds.removeFromTop(sc_buttonSize);
345 contentAreaBounds.removeFromTop(1);
346
347 // buttons from right
348 if (m_powerButton)
349 m_powerButton->setBounds(setupElementArea.removeFromRight(setupElementArea.getHeight()));
350 setupElementArea.removeFromRight(margin);
351 if (m_aboutButton)
352 m_aboutButton->setBounds(setupElementArea.removeFromRight(setupElementArea.getHeight()));
353 setupElementArea.removeFromRight(margin);
354 if (m_appSettingsButton)
355 m_appSettingsButton->setBounds(setupElementArea.removeFromRight(setupElementArea.getHeight()));
356 setupElementArea.removeFromRight(margin);
357 if (m_audioSetupButton)
358 m_audioSetupButton->setBounds(setupElementArea.removeFromRight(setupElementArea.getHeight()));
359 setupElementArea.removeFromRight(margin);
360 if (m_toggleStandaloneWindowButton)
361 m_toggleStandaloneWindowButton->setBounds(setupElementArea.removeFromRight(setupElementArea.getHeight()));
362 setupElementArea.removeFromRight(margin);
363
364 // load bars from left
365 if (m_sysLoadBar)
366 m_sysLoadBar->setBounds(setupElementArea.removeFromLeft(sc_loadNetWidth));
367 setupElementArea.removeFromLeft(margin);
368 if (m_netHealthBar)
369 m_netHealthBar->setBounds(setupElementArea.removeFromLeft(sc_loadNetWidth));
370 setupElementArea.removeFromLeft(margin);
371
372 // correct-background spacing inbetween
373 if (m_emptySpace)
374 m_emptySpace->setBounds(setupElementArea);
375
376 if (m_editorComponent)
377 m_editorComponent->setBounds(contentAreaBounds);
378}
379
381{
382 if (!m_followLocalStyle)
383 return;
384
385 if (juce::Desktop::getInstance().isDarkModeActive())
386 {
387 // go dark
388 applyPaletteStyle(JUCEAppBasics::CustomLookAndFeel::PS_Dark);
389 }
390 else
391 {
392 // go light
393 applyPaletteStyle(JUCEAppBasics::CustomLookAndFeel::PS_Light);
394 }
395
397}
398
399void MemaUIComponent::applyPaletteStyle(const JUCEAppBasics::CustomLookAndFeel::PaletteStyle& paletteStyle)
400{
403}
404
406{
407 auto powerDrawable = juce::Drawable::createFromSVG(*juce::XmlDocument::parse(BinaryData::power_settings_24dp_svg).get());
408 powerDrawable->replaceColour(juce::Colours::black, getLookAndFeel().findColour(juce::TextButton::ColourIds::textColourOnId));
409 m_powerButton->setImages(powerDrawable.get());
410
411 auto appSettingsButtonDrawable = juce::Drawable::createFromSVG(*juce::XmlDocument::parse(BinaryData::settings_24dp_svg).get());
412 appSettingsButtonDrawable->replaceColour(juce::Colours::black, getLookAndFeel().findColour(juce::TextButton::ColourIds::textColourOnId));
413 m_appSettingsButton->setImages(appSettingsButtonDrawable.get());
414
415 auto audioSetupButtonDrawable = juce::Drawable::createFromSVG(*juce::XmlDocument::parse(BinaryData::tune_24dp_svg).get());
416 audioSetupButtonDrawable->replaceColour(juce::Colours::black, getLookAndFeel().findColour(juce::TextButton::ColourIds::textColourOnId));
417 m_audioSetupButton->setImages(audioSetupButtonDrawable.get());
418
419 auto aboutButtonDrawable = juce::Drawable::createFromSVG(*juce::XmlDocument::parse(BinaryData::question_mark_24dp_svg).get());
420 aboutButtonDrawable->replaceColour(juce::Colours::black, getLookAndFeel().findColour(juce::TextButton::ColourIds::textColourOnId));
421 m_aboutButton->setImages(aboutButtonDrawable.get());
422
423 auto standaloneWindowDrawable = juce::Drawable::createFromSVG(*juce::XmlDocument::parse((isStandaloneWindow() ? BinaryData::open_in_new_down_24dp_svg : BinaryData::open_in_new24px_svg)).get());
424 standaloneWindowDrawable->replaceColour(juce::Colours::black, getLookAndFeel().findColour(juce::TextButton::ColourIds::textColourOnId));
425 m_toggleStandaloneWindowButton->setImages(standaloneWindowDrawable.get());
426
429
430 applyMeteringColour();
431}
432
433std::unique_ptr<XmlElement> MemaUIComponent::createStateXml()
434{
435 auto stateXml = std::make_unique<juce::XmlElement>(MemaAppConfiguration::getTagName(MemaAppConfiguration::TagID::UICONFIG));
436
437 int paletteStyle = -1;
438 if (!m_followLocalStyle)
439 {
440 if (auto customLAF = dynamic_cast<JUCEAppBasics::CustomLookAndFeel*>(&getLookAndFeel()))
441 paletteStyle = customLAF->getPaletteStyle();
442 }
445
446 return stateXml;
447}
448
449bool MemaUIComponent::setStateXml(XmlElement* stateXml)
450{
452 return false;
453
455 m_followLocalStyle = (-1 == paletteStyle);
456 if (m_followLocalStyle)
458 else
459 applyPaletteStyle(JUCEAppBasics::CustomLookAndFeel::PaletteStyle(paletteStyle));
460 m_settingsItems[MemaSettingsOption::LookAndFeel_Automatic] = std::make_pair("Automatic", -1 == paletteStyle);
461 m_settingsItems[MemaSettingsOption::LookAndFeel_Dark] = std::make_pair("Dark", JUCEAppBasics::CustomLookAndFeel::PaletteStyle::PS_Dark == paletteStyle);
462 m_settingsItems[MemaSettingsOption::LookAndFeel_Light] = std::make_pair("Light", JUCEAppBasics::CustomLookAndFeel::PaletteStyle::PS_Light == paletteStyle);
463
465 setMeteringColour(meteringColour);
466 m_settingsItems[MemaSettingsOption::MeteringColour_Green] = std::make_pair("Green", juce::Colours::forestgreen == meteringColour);
467 m_settingsItems[MemaSettingsOption::MeteringColour_Red] = std::make_pair("Red", juce::Colours::orangered == meteringColour);
468 m_settingsItems[MemaSettingsOption::MeteringColour_Blue] = std::make_pair("Blue", juce::Colours::dodgerblue == meteringColour);
469 m_settingsItems[MemaSettingsOption::MeteringColour_Pink] = std::make_pair("Anni Pink", juce::Colours::deeppink == meteringColour);
470 m_settingsItems[MemaSettingsOption::MeteringColour_Laser] = std::make_pair("Laser", juce::Colour(0xd1, 0xff, 0x4f) == meteringColour);
471
472 return true;
473}
474
475void MemaUIComponent::handleSettingsMenuResult(int selectedId)
476{
477 if (0 == selectedId)
478 {
479 return; // nothing selected, dismiss
480 }
482 {
483 handleSettingsLookAndFeelMenuResult(selectedId);
484 }
486 {
487 handleSettingsMeteringColourMenuResult(selectedId);
488 }
490 {
492 }
494 {
496 }
497 else
498 jassertfalse; // unhandled menu entry!?
499
502}
503
504void MemaUIComponent::handleSettingsLookAndFeelMenuResult(int selectedId)
505{
506 // helper internal function to avoid code clones
507 std::function<void(int, int, int)> setSettingsItemsCheckState = [=](int a, int b, int c) {
508 m_settingsItems[MemaSettingsOption::LookAndFeel_Automatic].second = a;
509 m_settingsItems[MemaSettingsOption::LookAndFeel_Dark].second = b;
510 m_settingsItems[MemaSettingsOption::LookAndFeel_Light].second = c;
511 };
512
513 switch (selectedId)
514 {
517 m_followLocalStyle = true;
519 break;
522 m_followLocalStyle = false;
523 applyPaletteStyle(JUCEAppBasics::CustomLookAndFeel::PaletteStyle::PS_Dark);
524 break;
527 m_followLocalStyle = false;
528 applyPaletteStyle(JUCEAppBasics::CustomLookAndFeel::PaletteStyle::PS_Light);
529 break;
530 default:
531 jassertfalse; // unknown id fed in unintentionally ?!
532 break;
533 }
534}
535
536void MemaUIComponent::handleSettingsMeteringColourMenuResult(int selectedId)
537{
538 // helper internal function to avoid code clones
539 std::function<void(int, int, int, int, int)> setSettingsItemsCheckState = [=](int green, int red, int blue, int pink, int laser) {
540 m_settingsItems[MemaSettingsOption::MeteringColour_Green].second = green;
541 m_settingsItems[MemaSettingsOption::MeteringColour_Red].second = red;
542 m_settingsItems[MemaSettingsOption::MeteringColour_Blue].second = blue;
543 m_settingsItems[MemaSettingsOption::MeteringColour_Pink].second = pink;
544 m_settingsItems[MemaSettingsOption::MeteringColour_Laser].second = laser;
545 };
546
547 switch (selectedId)
548 {
550 setSettingsItemsCheckState(1, 0, 0, 0, 0);
551 setMeteringColour(juce::Colours::forestgreen);
552 break;
554 setSettingsItemsCheckState(0, 1, 0, 0, 0);
555 setMeteringColour(juce::Colours::orangered);
556 break;
558 setSettingsItemsCheckState(0, 0, 1, 0, 0);
559 setMeteringColour(juce::Colours::dodgerblue);
560 break;
562 setSettingsItemsCheckState(0, 0, 0, 1, 0);
563 setMeteringColour(juce::Colours::deeppink);
564 break;
566 setSettingsItemsCheckState(0, 0, 0, 0, 1);
567 setMeteringColour(juce::Colour(0xd1, 0xff, 0x4f));
568 break;
569 default:
570 break;
571 }
572}
573
574void MemaUIComponent::setMeteringColour(const juce::Colour& meteringColour)
575{
576 m_meteringColour = meteringColour;
577
578 applyMeteringColour();
579}
580
581void MemaUIComponent::applyMeteringColour()
582{
583 auto customLookAndFeel = dynamic_cast<JUCEAppBasics::CustomLookAndFeel*>(&getLookAndFeel());
585 {
586 switch (customLookAndFeel->getPaletteStyle())
587 {
588 case JUCEAppBasics::CustomLookAndFeel::PS_Light:
589 getLookAndFeel().setColour(JUCEAppBasics::CustomLookAndFeel::ColourIds::MeteringPeakColourId, m_meteringColour.brighter());
590 getLookAndFeel().setColour(JUCEAppBasics::CustomLookAndFeel::ColourIds::MeteringRmsColourId, m_meteringColour);
591 break;
592 case JUCEAppBasics::CustomLookAndFeel::PS_Dark:
593 default:
594 getLookAndFeel().setColour(JUCEAppBasics::CustomLookAndFeel::ColourIds::MeteringPeakColourId, m_meteringColour.darker());
595 getLookAndFeel().setColour(JUCEAppBasics::CustomLookAndFeel::ColourIds::MeteringRmsColourId, m_meteringColour);
596 break;
597 }
598 }
599}
600
601} // namespace Mema
void paint(Graphics &g) override
void mouseUp(const MouseEvent &event) override
void setAlert(bool alert, int id=0)
void setSessionTopology(const JUCEAppBasics::SessionServiceTopology &sessionTopology)
void setLoadPercent(int loadPercent, int id=0)
LoadBar(juce::String label, bool showPercent=true, bool showMax=true)
void paint(Graphics &g) override
static juce::String getTagName(TagID ID)
@ UICONFIG
UI layout and appearance.
static juce::String getAttributeName(AttributeID ID)
@ METERINGCOLOR
Metering bar colour.
@ PALETTESTYLE
Look-and-feel palette style index.
std::function< void()> onDeleted
Called when this component is destroyed.
std::function< void(const JUCEAppBasics::CustomLookAndFeel::PaletteStyle &)> onPaletteStyleChange
Called when palette style changes.
std::function< void()> onSettingsChanged
Called when any setting changes.
std::function< void()> onLoadConfig
Called when the user selects Load Config.
std::function< void(bool)> onToggleStandaloneWindow
Called when the user toggles standalone/popup mode.
@ SaveConfig
Save configuration to file.
@ MeteringColour_Blue
Blue metering bars.
@ MeteringColour_Pink
Pink metering bars.
@ LookAndFeel_Dark
Force dark look-and-feel.
@ LookAndFeel_Automatic
Match the host OS appearance.
@ LoadConfig
Load configuration from file.
@ MeteringColour_Red
Red metering bars.
@ MeteringColour_Green
Green metering bars (default).
@ LookAndFeel_Light
Force light look-and-feel.
@ MeteringColour_Laser
High-visibility laser-green metering bars.
void setStandaloneWindow(bool standalone)
Switches between popup mode (embedded in the system tray/menubar popover) and standalone window mode.
void updateSessionServiceTopology(const JUCEAppBasics::SessionServiceTopology &serviceDiscoveryTopologyString)
Updates the service-topology display (if any) with freshly discovered Mema instances.
void paint(Graphics &) override
Paints the component background using the current look-and-feel background colour.
void setEditorComponent(juce::Component *editorComponent)
Attaches the MemaProcessorEditor to be displayed in the central content area.
std::function< void()> onLookAndFeelChanged
Called after a look-and-feel change is applied.
std::function< void()> onAudioSetupMenuClicked
Called when the audio-setup button is clicked.
bool setStateXml(juce::XmlElement *stateXml) override
Restores UI state from a <UICONFIG> XmlElement.
void updateCpuUsageBar(int loadPercent)
Updates the CPU-load progress bar to reflect the current audio processing load.
std::unique_ptr< juce::XmlElement > createStateXml() override
Serialises the UI state (standalone mode, palette style, metering colour) to XML.
bool isStandaloneWindow()
Returns true when the component is currently shown in standalone window mode.
void resized() override
Lays out all child components.
std::function< void()> onSaveConfig
Called when the user selects Save Config.
void darkModeSettingChanged() override
Responds to an OS dark-mode toggle.
void updateNetworkUsage(const std::map< int, std::pair< double, bool > > &netLoads)
Updates the network-health bar with per-connection traffic metrics.
void handleEditorSizeChangeRequest(const juce::Rectangle< int > &requestedSize)
Responds to a resize request from the embedded editor.
MemaUIComponent()
Constructs the UI component and wires up child components.
void lookAndFeelChanged() override
Propagates a look-and-feel change to all child buttons and bars.
Definition Mema.cpp:27