VST3: fetch midi mappings all at once, use it for note/sound-off
[carla.git] / source / modules / juce_gui_basics / layout / juce_TabbedComponent.cpp
blobb19bc3d30992401d25c478598ef6c3149cbf4725
1 /*
2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
23 ==============================================================================
26 namespace juce
29 namespace TabbedComponentHelpers
31 const Identifier deleteComponentId ("deleteByTabComp_");
33 static void deleteIfNecessary (Component* comp)
35 if (comp != nullptr && (bool) comp->getProperties() [deleteComponentId])
36 delete comp;
39 static Rectangle<int> getTabArea (Rectangle<int>& content, BorderSize<int>& outline,
40 TabbedButtonBar::Orientation orientation, int tabDepth)
42 switch (orientation)
44 case TabbedButtonBar::TabsAtTop: outline.setTop (0); return content.removeFromTop (tabDepth);
45 case TabbedButtonBar::TabsAtBottom: outline.setBottom (0); return content.removeFromBottom (tabDepth);
46 case TabbedButtonBar::TabsAtLeft: outline.setLeft (0); return content.removeFromLeft (tabDepth);
47 case TabbedButtonBar::TabsAtRight: outline.setRight (0); return content.removeFromRight (tabDepth);
48 default: jassertfalse; break;
51 return Rectangle<int>();
55 //==============================================================================
56 struct TabbedComponent::ButtonBar : public TabbedButtonBar
58 ButtonBar (TabbedComponent& tabComp, TabbedButtonBar::Orientation o)
59 : TabbedButtonBar (o), owner (tabComp)
63 void currentTabChanged (int newCurrentTabIndex, const String& newTabName)
65 owner.changeCallback (newCurrentTabIndex, newTabName);
68 void popupMenuClickOnTab (int tabIndex, const String& tabName)
70 owner.popupMenuClickOnTab (tabIndex, tabName);
73 Colour getTabBackgroundColour (int tabIndex)
75 return owner.tabs->getTabBackgroundColour (tabIndex);
78 TabBarButton* createTabButton (const String& tabName, int tabIndex)
80 return owner.createTabButton (tabName, tabIndex);
83 TabbedComponent& owner;
85 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonBar)
88 //==============================================================================
89 TabbedComponent::TabbedComponent (TabbedButtonBar::Orientation orientation)
91 tabs.reset (new ButtonBar (*this, orientation));
92 addAndMakeVisible (tabs.get());
95 TabbedComponent::~TabbedComponent()
97 clearTabs();
98 tabs.reset();
101 //==============================================================================
102 void TabbedComponent::setOrientation (TabbedButtonBar::Orientation orientation)
104 tabs->setOrientation (orientation);
105 resized();
108 TabbedButtonBar::Orientation TabbedComponent::getOrientation() const noexcept
110 return tabs->getOrientation();
113 void TabbedComponent::setTabBarDepth (int newDepth)
115 if (tabDepth != newDepth)
117 tabDepth = newDepth;
118 resized();
122 TabBarButton* TabbedComponent::createTabButton (const String& tabName, int /*tabIndex*/)
124 return new TabBarButton (tabName, *tabs);
127 //==============================================================================
128 void TabbedComponent::clearTabs()
130 if (panelComponent != nullptr)
132 panelComponent->setVisible (false);
133 removeChildComponent (panelComponent.get());
134 panelComponent = nullptr;
137 tabs->clearTabs();
139 for (int i = contentComponents.size(); --i >= 0;)
140 TabbedComponentHelpers::deleteIfNecessary (contentComponents.getReference (i));
142 contentComponents.clear();
145 void TabbedComponent::addTab (const String& tabName,
146 Colour tabBackgroundColour,
147 Component* contentComponent,
148 bool deleteComponentWhenNotNeeded,
149 int insertIndex)
151 contentComponents.insert (insertIndex, WeakReference<Component> (contentComponent));
153 if (deleteComponentWhenNotNeeded && contentComponent != nullptr)
154 contentComponent->getProperties().set (TabbedComponentHelpers::deleteComponentId, true);
156 tabs->addTab (tabName, tabBackgroundColour, insertIndex);
157 resized();
160 void TabbedComponent::setTabName (int tabIndex, const String& newName)
162 tabs->setTabName (tabIndex, newName);
165 void TabbedComponent::removeTab (int tabIndex)
167 if (isPositiveAndBelow (tabIndex, contentComponents.size()))
169 TabbedComponentHelpers::deleteIfNecessary (contentComponents.getReference (tabIndex).get());
170 contentComponents.remove (tabIndex);
171 tabs->removeTab (tabIndex);
175 void TabbedComponent::moveTab (int currentIndex, int newIndex, bool animate)
177 contentComponents.move (currentIndex, newIndex);
178 tabs->moveTab (currentIndex, newIndex, animate);
181 int TabbedComponent::getNumTabs() const
183 return tabs->getNumTabs();
186 StringArray TabbedComponent::getTabNames() const
188 return tabs->getTabNames();
191 Component* TabbedComponent::getTabContentComponent (int tabIndex) const noexcept
193 return contentComponents[tabIndex].get();
196 Colour TabbedComponent::getTabBackgroundColour (int tabIndex) const noexcept
198 return tabs->getTabBackgroundColour (tabIndex);
201 void TabbedComponent::setTabBackgroundColour (int tabIndex, Colour newColour)
203 tabs->setTabBackgroundColour (tabIndex, newColour);
205 if (getCurrentTabIndex() == tabIndex)
206 repaint();
209 void TabbedComponent::setCurrentTabIndex (int newTabIndex, bool sendChangeMessage)
211 tabs->setCurrentTabIndex (newTabIndex, sendChangeMessage);
214 int TabbedComponent::getCurrentTabIndex() const
216 return tabs->getCurrentTabIndex();
219 String TabbedComponent::getCurrentTabName() const
221 return tabs->getCurrentTabName();
224 void TabbedComponent::setOutline (int thickness)
226 outlineThickness = thickness;
227 resized();
228 repaint();
231 void TabbedComponent::setIndent (int indentThickness)
233 edgeIndent = indentThickness;
234 resized();
235 repaint();
238 void TabbedComponent::paint (Graphics& g)
240 g.fillAll (findColour (backgroundColourId));
242 auto content = getLocalBounds();
243 BorderSize<int> outline (outlineThickness);
244 TabbedComponentHelpers::getTabArea (content, outline, getOrientation(), tabDepth);
246 g.reduceClipRegion (content);
247 g.fillAll (tabs->getTabBackgroundColour (getCurrentTabIndex()));
249 if (outlineThickness > 0)
251 RectangleList<int> rl (content);
252 rl.subtract (outline.subtractedFrom (content));
254 g.reduceClipRegion (rl);
255 g.fillAll (findColour (outlineColourId));
259 void TabbedComponent::resized()
261 auto content = getLocalBounds();
262 BorderSize<int> outline (outlineThickness);
264 tabs->setBounds (TabbedComponentHelpers::getTabArea (content, outline, getOrientation(), tabDepth));
265 content = BorderSize<int> (edgeIndent).subtractedFrom (outline.subtractedFrom (content));
267 for (auto& c : contentComponents)
268 if (auto comp = c.get())
269 comp->setBounds (content);
272 void TabbedComponent::lookAndFeelChanged()
274 for (auto& c : contentComponents)
275 if (auto comp = c.get())
276 comp->lookAndFeelChanged();
279 void TabbedComponent::changeCallback (int newCurrentTabIndex, const String& newTabName)
281 auto* newPanelComp = getTabContentComponent (getCurrentTabIndex());
283 if (newPanelComp != panelComponent)
285 if (panelComponent != nullptr)
287 panelComponent->setVisible (false);
288 removeChildComponent (panelComponent);
291 panelComponent = newPanelComp;
293 if (panelComponent != nullptr)
295 // do these ops as two stages instead of addAndMakeVisible() so that the
296 // component has always got a parent when it gets the visibilityChanged() callback
297 addChildComponent (panelComponent);
298 panelComponent->sendLookAndFeelChange();
299 panelComponent->setVisible (true);
300 panelComponent->toFront (true);
303 repaint();
306 resized();
307 currentTabChanged (newCurrentTabIndex, newTabName);
310 void TabbedComponent::currentTabChanged (int, const String&) {}
311 void TabbedComponent::popupMenuClickOnTab (int, const String&) {}
313 //==============================================================================
314 std::unique_ptr<AccessibilityHandler> TabbedComponent::createAccessibilityHandler()
316 return std::make_unique<AccessibilityHandler> (*this, AccessibilityRole::group);
319 } // namespace juce