| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library - "Jules' Utility Class Extensions"
 -    Copyright 2004-11 by Raw Material Software Ltd.
 - 
 -   ------------------------------------------------------------------------------
 - 
 -    JUCE can be redistributed and/or modified under the terms of the GNU General
 -    Public License (Version 2), as published by the Free Software Foundation.
 -    A copy of the license is included in the JUCE distribution, or can be found
 -    online at www.gnu.org/licenses.
 - 
 -    JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
 -    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 -    A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 - 
 -   ------------------------------------------------------------------------------
 - 
 -    To release a closed-source product which uses JUCE, commercial licenses are
 -    available: visit www.rawmaterialsoftware.com/juce for more information.
 - 
 -   ==============================================================================
 - */
 - 
 - TabBarButton::TabBarButton (const String& name, TabbedButtonBar& owner_)
 -     : Button (name), owner (owner_), overlapPixels (0), extraCompPlacement (afterText)
 - {
 -     setWantsKeyboardFocus (false);
 - }
 - 
 - TabBarButton::~TabBarButton() {}
 - 
 - int TabBarButton::getIndex() const                      { return owner.indexOfTabButton (this); }
 - Colour TabBarButton::getTabBackgroundColour() const     { return owner.getTabBackgroundColour (getIndex()); }
 - bool TabBarButton::isFrontTab() const                   { return getToggleState(); }
 - 
 - void TabBarButton::paintButton (Graphics& g, const bool isMouseOverButton, const bool isButtonDown)
 - {
 -     getLookAndFeel().drawTabButton (*this, g, isMouseOverButton, isButtonDown);
 - }
 - 
 - void TabBarButton::clicked (const ModifierKeys& mods)
 - {
 -     if (mods.isPopupMenu())
 -         owner.popupMenuClickOnTab (getIndex(), getButtonText());
 -     else
 -         owner.setCurrentTabIndex (getIndex());
 - }
 - 
 - bool TabBarButton::hitTest (int mx, int my)
 - {
 -     const Rectangle<int> area (getActiveArea());
 - 
 -     if (owner.isVertical())
 -     {
 -         if (isPositiveAndBelow (mx, getWidth())
 -              && my >= area.getY() + overlapPixels && my < area.getBottom() - overlapPixels)
 -             return true;
 -     }
 -     else
 -     {
 -         if (isPositiveAndBelow (my, getHeight())
 -              && mx >= area.getX() + overlapPixels && mx < area.getRight() - overlapPixels)
 -             return true;
 -     }
 - 
 -     Path p;
 -     getLookAndFeel().createTabButtonShape (*this, p, false, false);
 - 
 -     return p.contains ((float) (mx - area.getX()),
 -                        (float) (my - area.getY()));
 - }
 - 
 - int TabBarButton::getBestTabLength (const int depth)
 - {
 -     return getLookAndFeel().getTabButtonBestWidth (*this, depth);
 - }
 - 
 - void TabBarButton::calcAreas (Rectangle<int>& extraComp, Rectangle<int>& textArea) const
 - {
 -     LookAndFeel& lf = getLookAndFeel();
 -     textArea = getActiveArea();
 - 
 -     const int depth = owner.isVertical() ? textArea.getWidth() : textArea.getHeight();
 -     const int overlap = lf.getTabButtonOverlap (depth);
 - 
 -     if (overlap > 0)
 -     {
 -         if (owner.isVertical())
 -             textArea.reduce (0, overlap);
 -         else
 -             textArea.reduce (overlap, 0);
 -     }
 - 
 -     if (extraComponent != nullptr)
 -         extraComp = lf.getTabButtonExtraComponentBounds (*this, textArea, *extraComponent);
 - }
 - 
 - Rectangle<int> TabBarButton::getTextArea() const
 - {
 -     Rectangle<int> extraComp, textArea;
 -     calcAreas (extraComp, textArea);
 -     return textArea;
 - }
 - 
 - Rectangle<int> TabBarButton::getActiveArea() const
 - {
 -     Rectangle<int> r (getLocalBounds());
 -     const int spaceAroundImage = getLookAndFeel().getTabButtonSpaceAroundImage();
 -     const TabbedButtonBar::Orientation orientation = owner.getOrientation();
 - 
 -     if (orientation != TabbedButtonBar::TabsAtLeft)      r.removeFromRight  (spaceAroundImage);
 -     if (orientation != TabbedButtonBar::TabsAtRight)     r.removeFromLeft   (spaceAroundImage);
 -     if (orientation != TabbedButtonBar::TabsAtBottom)    r.removeFromTop    (spaceAroundImage);
 -     if (orientation != TabbedButtonBar::TabsAtTop)       r.removeFromBottom (spaceAroundImage);
 - 
 -     return r;
 - }
 - 
 - void TabBarButton::setExtraComponent (Component* comp, ExtraComponentPlacement placement)
 - {
 -     jassert (extraCompPlacement == beforeText || extraCompPlacement == afterText);
 -     extraCompPlacement = placement;
 -     addAndMakeVisible (extraComponent = comp);
 -     resized();
 - }
 - 
 - void TabBarButton::childBoundsChanged (Component* c)
 - {
 -     if (c == extraComponent)
 -     {
 -         owner.resized();
 -         resized();
 -     }
 - }
 - 
 - void TabBarButton::resized()
 - {
 -     if (extraComponent != nullptr)
 -     {
 -         Rectangle<int> extraComp, textArea;
 -         calcAreas (extraComp, textArea);
 - 
 -         if (! extraComp.isEmpty())
 -             extraComponent->setBounds (extraComp);
 -     }
 - }
 - 
 - //==============================================================================
 - class TabbedButtonBar::BehindFrontTabComp  : public Component,
 -                                              public ButtonListener // (can't use Button::Listener due to idiotic VC2005 bug)
 - {
 - public:
 -     BehindFrontTabComp (TabbedButtonBar& owner_)
 -         : owner (owner_)
 -     {
 -         setInterceptsMouseClicks (false, false);
 -     }
 - 
 -     void paint (Graphics& g)
 -     {
 -         getLookAndFeel().drawTabAreaBehindFrontButton (owner, g, getWidth(), getHeight());
 -     }
 - 
 -     void enablementChanged()
 -     {
 -         repaint();
 -     }
 - 
 -     void buttonClicked (Button*)
 -     {
 -         owner.showExtraItemsMenu();
 -     }
 - 
 - private:
 -     TabbedButtonBar& owner;
 - 
 -     JUCE_DECLARE_NON_COPYABLE (BehindFrontTabComp)
 - };
 - 
 - 
 - //==============================================================================
 - TabbedButtonBar::TabbedButtonBar (const Orientation orientation_)
 -     : orientation (orientation_),
 -       minimumScale (0.7),
 -       currentTabIndex (-1)
 - {
 -     setInterceptsMouseClicks (false, true);
 -     addAndMakeVisible (behindFrontTab = new BehindFrontTabComp (*this));
 -     setFocusContainer (true);
 - }
 - 
 - TabbedButtonBar::~TabbedButtonBar()
 - {
 -     tabs.clear();
 -     extraTabsButton = nullptr;
 - }
 - 
 - //==============================================================================
 - void TabbedButtonBar::setOrientation (const Orientation newOrientation)
 - {
 -     orientation = newOrientation;
 - 
 -     for (int i = getNumChildComponents(); --i >= 0;)
 -         getChildComponent (i)->resized();
 - 
 -     resized();
 - }
 - 
 - TabBarButton* TabbedButtonBar::createTabButton (const String& name, const int /*index*/)
 - {
 -     return new TabBarButton (name, *this);
 - }
 - 
 - void TabbedButtonBar::setMinimumTabScaleFactor (double newMinimumScale)
 - {
 -     minimumScale = newMinimumScale;
 -     resized();
 - }
 - 
 - //==============================================================================
 - void TabbedButtonBar::clearTabs()
 - {
 -     tabs.clear();
 -     extraTabsButton = nullptr;
 -     setCurrentTabIndex (-1);
 - }
 - 
 - void TabbedButtonBar::addTab (const String& tabName,
 -                               const Colour& tabBackgroundColour,
 -                               int insertIndex)
 - {
 -     jassert (tabName.isNotEmpty()); // you have to give them all a name..
 - 
 -     if (tabName.isNotEmpty())
 -     {
 -         if (! isPositiveAndBelow (insertIndex, tabs.size()))
 -             insertIndex = tabs.size();
 - 
 -         TabInfo* const currentTab = tabs [currentTabIndex];
 - 
 -         TabInfo* newTab = new TabInfo();
 -         newTab->name = tabName;
 -         newTab->colour = tabBackgroundColour;
 -         newTab->button = createTabButton (tabName, insertIndex);
 -         jassert (newTab->button != nullptr);
 - 
 -         tabs.insert (insertIndex, newTab);
 -         currentTabIndex = tabs.indexOf (currentTab);
 -         addAndMakeVisible (newTab->button, insertIndex);
 - 
 -         resized();
 - 
 -         if (currentTabIndex < 0)
 -             setCurrentTabIndex (0);
 -     }
 - }
 - 
 - void TabbedButtonBar::setTabName (const int tabIndex, const String& newName)
 - {
 -     if (TabInfo* const tab = tabs [tabIndex])
 -     {
 -         if (tab->name != newName)
 -         {
 -             tab->name = newName;
 -             tab->button->setButtonText (newName);
 -             resized();
 -         }
 -     }
 - }
 - 
 - void TabbedButtonBar::removeTab (const int tabIndex)
 - {
 -     if (tabIndex == currentTabIndex)
 -         setCurrentTabIndex (-1);
 - 
 -     TabInfo* const currentTab = tabs [currentTabIndex];
 -     tabs.remove (tabIndex);
 -     currentTabIndex = tabs.indexOf (currentTab);
 -     resized();
 - }
 - 
 - void TabbedButtonBar::moveTab (const int currentIndex, const int newIndex)
 - {
 -     TabInfo* const currentTab = tabs [currentTabIndex];
 -     tabs.move (currentIndex, newIndex);
 -     currentTabIndex = tabs.indexOf (currentTab);
 -     resized();
 - }
 - 
 - int TabbedButtonBar::getNumTabs() const
 - {
 -     return tabs.size();
 - }
 - 
 - String TabbedButtonBar::getCurrentTabName() const
 - {
 -     TabInfo* tab = tabs [currentTabIndex];
 -     return tab == nullptr ? String::empty : tab->name;
 - }
 - 
 - StringArray TabbedButtonBar::getTabNames() const
 - {
 -     StringArray names;
 - 
 -     for (int i = 0; i < tabs.size(); ++i)
 -         names.add (tabs.getUnchecked(i)->name);
 - 
 -     return names;
 - }
 - 
 - void TabbedButtonBar::setCurrentTabIndex (int newIndex, const bool sendChangeMessage_)
 - {
 -     if (currentTabIndex != newIndex)
 -     {
 -         if (! isPositiveAndBelow (newIndex, tabs.size()))
 -             newIndex = -1;
 - 
 -         currentTabIndex = newIndex;
 - 
 -         for (int i = 0; i < tabs.size(); ++i)
 -         {
 -             TabBarButton* tb = tabs.getUnchecked(i)->button;
 -             tb->setToggleState (i == newIndex, false);
 -         }
 - 
 -         resized();
 - 
 -         if (sendChangeMessage_)
 -             sendChangeMessage();
 - 
 -         currentTabChanged (newIndex, getCurrentTabName());
 -     }
 - }
 - 
 - TabBarButton* TabbedButtonBar::getTabButton (const int index) const
 - {
 -     TabInfo* const tab = tabs[index];
 -     return tab == nullptr ? nullptr : static_cast <TabBarButton*> (tab->button);
 - }
 - 
 - int TabbedButtonBar::indexOfTabButton (const TabBarButton* button) const
 - {
 -     for (int i = tabs.size(); --i >= 0;)
 -         if (tabs.getUnchecked(i)->button == button)
 -             return i;
 - 
 -     return -1;
 - }
 - 
 - void TabbedButtonBar::lookAndFeelChanged()
 - {
 -     extraTabsButton = nullptr;
 -     resized();
 - }
 - 
 - void TabbedButtonBar::resized()
 - {
 -     LookAndFeel& lf = getLookAndFeel();
 - 
 -     int depth = getWidth();
 -     int length = getHeight();
 - 
 -     if (! isVertical())
 -         std::swap (depth, length);
 - 
 -     const int overlap = lf.getTabButtonOverlap (depth) + lf.getTabButtonSpaceAroundImage() * 2;
 - 
 -     int totalLength = jmax (0, overlap);
 -     int numVisibleButtons = tabs.size();
 - 
 -     for (int i = 0; i < tabs.size(); ++i)
 -     {
 -         TabBarButton* const tb = tabs.getUnchecked(i)->button;
 - 
 -         totalLength += tb->getBestTabLength (depth) - overlap;
 -         tb->overlapPixels = jmax (0, overlap / 2);
 -     }
 - 
 -     double scale = 1.0;
 - 
 -     if (totalLength > length)
 -         scale = jmax (minimumScale, length / (double) totalLength);
 - 
 -     const bool isTooBig = (int) (totalLength * scale) > length;
 -     int tabsButtonPos = 0;
 - 
 -     if (isTooBig)
 -     {
 -         if (extraTabsButton == nullptr)
 -         {
 -             addAndMakeVisible (extraTabsButton = lf.createTabBarExtrasButton());
 -             extraTabsButton->addListener (behindFrontTab);
 -             extraTabsButton->setAlwaysOnTop (true);
 -             extraTabsButton->setTriggeredOnMouseDown (true);
 -         }
 - 
 -         const int buttonSize = jmin (proportionOfWidth (0.7f), proportionOfHeight (0.7f));
 -         extraTabsButton->setSize (buttonSize, buttonSize);
 - 
 -         if (isVertical())
 -         {
 -             tabsButtonPos = getHeight() - buttonSize / 2 - 1;
 -             extraTabsButton->setCentrePosition (getWidth() / 2, tabsButtonPos);
 -         }
 -         else
 -         {
 -             tabsButtonPos = getWidth() - buttonSize / 2 - 1;
 -             extraTabsButton->setCentrePosition (tabsButtonPos, getHeight() / 2);
 -         }
 - 
 -         totalLength = 0;
 - 
 -         for (int i = 0; i < tabs.size(); ++i)
 -         {
 -             TabBarButton* const tb = tabs.getUnchecked(i)->button;
 -             const int newLength = totalLength + tb->getBestTabLength (depth);
 - 
 -             if (i > 0 && newLength * minimumScale > tabsButtonPos)
 -             {
 -                 totalLength += overlap;
 -                 break;
 -             }
 - 
 -             numVisibleButtons = i + 1;
 -             totalLength = newLength - overlap;
 -         }
 - 
 -         scale = jmax (minimumScale, tabsButtonPos / (double) totalLength);
 -     }
 -     else
 -     {
 -         extraTabsButton = nullptr;
 -     }
 - 
 -     int pos = 0;
 - 
 -     TabBarButton* frontTab = nullptr;
 - 
 -     for (int i = 0; i < tabs.size(); ++i)
 -     {
 -         if (TabBarButton* const tb = getTabButton (i))
 -         {
 -             const int bestLength = roundToInt (scale * tb->getBestTabLength (depth));
 - 
 -             if (i < numVisibleButtons)
 -             {
 -                 if (isVertical())
 -                     tb->setBounds (0, pos, getWidth(), bestLength);
 -                 else
 -                     tb->setBounds (pos, 0, bestLength, getHeight());
 - 
 -                 tb->toBack();
 - 
 -                 if (i == currentTabIndex)
 -                     frontTab = tb;
 - 
 -                 tb->setVisible (true);
 -             }
 -             else
 -             {
 -                 tb->setVisible (false);
 -             }
 - 
 -             pos += bestLength - overlap;
 -         }
 -     }
 - 
 -     behindFrontTab->setBounds (getLocalBounds());
 - 
 -     if (frontTab != nullptr)
 -     {
 -         frontTab->toFront (false);
 -         behindFrontTab->toBehind (frontTab);
 -     }
 - }
 - 
 - //==============================================================================
 - Colour TabbedButtonBar::getTabBackgroundColour (const int tabIndex)
 - {
 -     TabInfo* const tab = tabs [tabIndex];
 -     return tab == nullptr ? Colours::white : tab->colour;
 - }
 - 
 - void TabbedButtonBar::setTabBackgroundColour (const int tabIndex, const Colour& newColour)
 - {
 -     if (TabInfo* const tab = tabs [tabIndex])
 -     {
 -         if (tab->colour != newColour)
 -         {
 -             tab->colour = newColour;
 -             repaint();
 -         }
 -     }
 - }
 - 
 - void TabbedButtonBar::extraItemsMenuCallback (int result, TabbedButtonBar* bar)
 - {
 -     if (bar != nullptr && result > 0)
 -         bar->setCurrentTabIndex (result - 1);
 - }
 - 
 - void TabbedButtonBar::showExtraItemsMenu()
 - {
 -     PopupMenu m;
 - 
 -     for (int i = 0; i < tabs.size(); ++i)
 -     {
 -         const TabInfo* const tab = tabs.getUnchecked(i);
 - 
 -         if (! tab->button->isVisible())
 -             m.addItem (i + 1, tab->name, true, i == currentTabIndex);
 -     }
 - 
 -     m.showMenuAsync (PopupMenu::Options().withTargetComponent (extraTabsButton),
 -                      ModalCallbackFunction::forComponent (extraItemsMenuCallback, this));
 - }
 - 
 - //==============================================================================
 - void TabbedButtonBar::currentTabChanged (const int, const String&)
 - {
 - }
 - 
 - void TabbedButtonBar::popupMenuClickOnTab (const int, const String&)
 - {
 - }
 
 
  |