git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce
subrepo: subdir: "deps/juce" merged: "b13f9084e" upstream: origin: "https://github.com/essej/JUCE.git" branch: "sono6good" commit: "b13f9084e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
324
deps/juce/modules/juce_gui_basics/layout/juce_TabbedComponent.cpp
vendored
Normal file
324
deps/juce/modules/juce_gui_basics/layout/juce_TabbedComponent.cpp
vendored
Normal file
@ -0,0 +1,324 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
namespace TabbedComponentHelpers
|
||||
{
|
||||
const Identifier deleteComponentId ("deleteByTabComp_");
|
||||
|
||||
static void deleteIfNecessary (Component* comp)
|
||||
{
|
||||
if (comp != nullptr && (bool) comp->getProperties() [deleteComponentId])
|
||||
delete comp;
|
||||
}
|
||||
|
||||
static Rectangle<int> getTabArea (Rectangle<int>& content, BorderSize<int>& outline,
|
||||
TabbedButtonBar::Orientation orientation, int tabDepth)
|
||||
{
|
||||
switch (orientation)
|
||||
{
|
||||
case TabbedButtonBar::TabsAtTop: outline.setTop (0); return content.removeFromTop (tabDepth);
|
||||
case TabbedButtonBar::TabsAtBottom: outline.setBottom (0); return content.removeFromBottom (tabDepth);
|
||||
case TabbedButtonBar::TabsAtLeft: outline.setLeft (0); return content.removeFromLeft (tabDepth);
|
||||
case TabbedButtonBar::TabsAtRight: outline.setRight (0); return content.removeFromRight (tabDepth);
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
return Rectangle<int>();
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
struct TabbedComponent::ButtonBar : public TabbedButtonBar
|
||||
{
|
||||
ButtonBar (TabbedComponent& tabComp, TabbedButtonBar::Orientation o)
|
||||
: TabbedButtonBar (o), owner (tabComp)
|
||||
{
|
||||
}
|
||||
|
||||
void currentTabChanged (int newCurrentTabIndex, const String& newTabName)
|
||||
{
|
||||
owner.changeCallback (newCurrentTabIndex, newTabName);
|
||||
}
|
||||
|
||||
void popupMenuClickOnTab (int tabIndex, const String& tabName)
|
||||
{
|
||||
owner.popupMenuClickOnTab (tabIndex, tabName);
|
||||
}
|
||||
|
||||
Colour getTabBackgroundColour (int tabIndex)
|
||||
{
|
||||
return owner.tabs->getTabBackgroundColour (tabIndex);
|
||||
}
|
||||
|
||||
TabBarButton* createTabButton (const String& tabName, int tabIndex)
|
||||
{
|
||||
return owner.createTabButton (tabName, tabIndex);
|
||||
}
|
||||
|
||||
TabbedComponent& owner;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonBar)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
TabbedComponent::TabbedComponent (TabbedButtonBar::Orientation orientation)
|
||||
{
|
||||
tabs.reset (new ButtonBar (*this, orientation));
|
||||
addAndMakeVisible (tabs.get());
|
||||
}
|
||||
|
||||
TabbedComponent::~TabbedComponent()
|
||||
{
|
||||
clearTabs();
|
||||
tabs.reset();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void TabbedComponent::setOrientation (TabbedButtonBar::Orientation orientation)
|
||||
{
|
||||
tabs->setOrientation (orientation);
|
||||
resized();
|
||||
}
|
||||
|
||||
TabbedButtonBar::Orientation TabbedComponent::getOrientation() const noexcept
|
||||
{
|
||||
return tabs->getOrientation();
|
||||
}
|
||||
|
||||
void TabbedComponent::setTabBarDepth (int newDepth)
|
||||
{
|
||||
if (tabDepth != newDepth)
|
||||
{
|
||||
tabDepth = newDepth;
|
||||
resized();
|
||||
}
|
||||
}
|
||||
|
||||
TabBarButton* TabbedComponent::createTabButton (const String& tabName, int /*tabIndex*/)
|
||||
{
|
||||
return new TabBarButton (tabName, *tabs);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void TabbedComponent::clearTabs()
|
||||
{
|
||||
if (panelComponent != nullptr)
|
||||
{
|
||||
panelComponent->setVisible (false);
|
||||
removeChildComponent (panelComponent.get());
|
||||
panelComponent = nullptr;
|
||||
}
|
||||
|
||||
tabs->clearTabs();
|
||||
|
||||
for (int i = contentComponents.size(); --i >= 0;)
|
||||
TabbedComponentHelpers::deleteIfNecessary (contentComponents.getReference (i));
|
||||
|
||||
contentComponents.clear();
|
||||
}
|
||||
|
||||
void TabbedComponent::addTab (const String& tabName,
|
||||
Colour tabBackgroundColour,
|
||||
Component* contentComponent,
|
||||
bool deleteComponentWhenNotNeeded,
|
||||
int insertIndex)
|
||||
{
|
||||
contentComponents.insert (insertIndex, WeakReference<Component> (contentComponent));
|
||||
|
||||
if (deleteComponentWhenNotNeeded && contentComponent != nullptr)
|
||||
contentComponent->getProperties().set (TabbedComponentHelpers::deleteComponentId, true);
|
||||
|
||||
tabs->addTab (tabName, tabBackgroundColour, insertIndex);
|
||||
resized();
|
||||
}
|
||||
|
||||
void TabbedComponent::setTabDeleteComponentWhenNotNeeded (int tabIndex, bool flag)
|
||||
{
|
||||
contentComponents [tabIndex]->getProperties().set (TabbedComponentHelpers::deleteComponentId, flag);
|
||||
}
|
||||
|
||||
void TabbedComponent::setTabName (int tabIndex, const String& newName)
|
||||
{
|
||||
tabs->setTabName (tabIndex, newName);
|
||||
}
|
||||
|
||||
void TabbedComponent::removeTab (int tabIndex)
|
||||
{
|
||||
if (isPositiveAndBelow (tabIndex, contentComponents.size()))
|
||||
{
|
||||
TabbedComponentHelpers::deleteIfNecessary (contentComponents.getReference (tabIndex).get());
|
||||
contentComponents.remove (tabIndex);
|
||||
tabs->removeTab (tabIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void TabbedComponent::moveTab (int currentIndex, int newIndex, bool animate)
|
||||
{
|
||||
contentComponents.move (currentIndex, newIndex);
|
||||
tabs->moveTab (currentIndex, newIndex, animate);
|
||||
}
|
||||
|
||||
int TabbedComponent::getNumTabs() const
|
||||
{
|
||||
return tabs->getNumTabs();
|
||||
}
|
||||
|
||||
StringArray TabbedComponent::getTabNames() const
|
||||
{
|
||||
return tabs->getTabNames();
|
||||
}
|
||||
|
||||
Component* TabbedComponent::getTabContentComponent (int tabIndex) const noexcept
|
||||
{
|
||||
return contentComponents[tabIndex].get();
|
||||
}
|
||||
|
||||
Colour TabbedComponent::getTabBackgroundColour (int tabIndex) const noexcept
|
||||
{
|
||||
return tabs->getTabBackgroundColour (tabIndex);
|
||||
}
|
||||
|
||||
void TabbedComponent::setTabBackgroundColour (int tabIndex, Colour newColour)
|
||||
{
|
||||
tabs->setTabBackgroundColour (tabIndex, newColour);
|
||||
|
||||
if (getCurrentTabIndex() == tabIndex)
|
||||
repaint();
|
||||
}
|
||||
|
||||
void TabbedComponent::setCurrentTabIndex (int newTabIndex, bool sendChangeMessage)
|
||||
{
|
||||
tabs->setCurrentTabIndex (newTabIndex, sendChangeMessage);
|
||||
}
|
||||
|
||||
int TabbedComponent::getCurrentTabIndex() const
|
||||
{
|
||||
return tabs->getCurrentTabIndex();
|
||||
}
|
||||
|
||||
String TabbedComponent::getCurrentTabName() const
|
||||
{
|
||||
return tabs->getCurrentTabName();
|
||||
}
|
||||
|
||||
void TabbedComponent::setOutline (int thickness)
|
||||
{
|
||||
outlineThickness = thickness;
|
||||
resized();
|
||||
repaint();
|
||||
}
|
||||
|
||||
void TabbedComponent::setIndent (int indentThickness)
|
||||
{
|
||||
edgeIndent = indentThickness;
|
||||
resized();
|
||||
repaint();
|
||||
}
|
||||
|
||||
void TabbedComponent::paint (Graphics& g)
|
||||
{
|
||||
g.fillAll (findColour (backgroundColourId));
|
||||
|
||||
auto content = getLocalBounds();
|
||||
BorderSize<int> outline (outlineThickness);
|
||||
TabbedComponentHelpers::getTabArea (content, outline, getOrientation(), tabDepth);
|
||||
|
||||
g.reduceClipRegion (content);
|
||||
g.fillAll (tabs->getTabBackgroundColour (getCurrentTabIndex()));
|
||||
|
||||
if (outlineThickness > 0)
|
||||
{
|
||||
RectangleList<int> rl (content);
|
||||
rl.subtract (outline.subtractedFrom (content));
|
||||
|
||||
g.reduceClipRegion (rl);
|
||||
g.fillAll (findColour (outlineColourId));
|
||||
}
|
||||
}
|
||||
|
||||
void TabbedComponent::resized()
|
||||
{
|
||||
auto content = getLocalBounds();
|
||||
BorderSize<int> outline (outlineThickness);
|
||||
|
||||
tabs->setBounds (TabbedComponentHelpers::getTabArea (content, outline, getOrientation(), tabDepth));
|
||||
content = BorderSize<int> (edgeIndent).subtractedFrom (outline.subtractedFrom (content));
|
||||
|
||||
for (auto& c : contentComponents)
|
||||
if (auto comp = c.get())
|
||||
comp->setBounds (content);
|
||||
}
|
||||
|
||||
void TabbedComponent::lookAndFeelChanged()
|
||||
{
|
||||
for (auto& c : contentComponents)
|
||||
if (auto comp = c.get())
|
||||
comp->lookAndFeelChanged();
|
||||
}
|
||||
|
||||
void TabbedComponent::changeCallback (int newCurrentTabIndex, const String& newTabName)
|
||||
{
|
||||
auto* newPanelComp = getTabContentComponent (getCurrentTabIndex());
|
||||
|
||||
if (newPanelComp != panelComponent)
|
||||
{
|
||||
if (panelComponent != nullptr)
|
||||
{
|
||||
panelComponent->setVisible (false);
|
||||
removeChildComponent (panelComponent);
|
||||
}
|
||||
|
||||
panelComponent = newPanelComp;
|
||||
|
||||
if (panelComponent != nullptr)
|
||||
{
|
||||
// do these ops as two stages instead of addAndMakeVisible() so that the
|
||||
// component has always got a parent when it gets the visibilityChanged() callback
|
||||
addChildComponent (panelComponent);
|
||||
panelComponent->sendLookAndFeelChange();
|
||||
panelComponent->setVisible (true);
|
||||
panelComponent->toFront (true);
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
resized();
|
||||
currentTabChanged (newCurrentTabIndex, newTabName);
|
||||
}
|
||||
|
||||
void TabbedComponent::currentTabChanged (int, const String&) {}
|
||||
void TabbedComponent::popupMenuClickOnTab (int, const String&) {}
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<AccessibilityHandler> TabbedComponent::createAccessibilityHandler()
|
||||
{
|
||||
return std::make_unique<AccessibilityHandler> (*this, AccessibilityRole::group);
|
||||
}
|
||||
|
||||
} // namespace juce
|
Reference in New Issue
Block a user