text: /* **************************************************************************************
   *    Author: Scott Mudge
   *    MAIL@SCOTTMUDGE.COM
   *
   *                                  MIT License
   *                                  -----------
   *                               MAIL@SCOTTMUDGE.COM
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in all
   * copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   * SOFTWARE.
   *
   * **************************************************************************************/
  
  // Some changes have been done by eric bachard. See the changelog
  // File Name: imgui_tabs.cpp
  // File Description: Custom ImGui tab system module added by me (Scott)
  /*
   * Usage:
   *      * To start a tab bar, use: ImGui::BeginTabBar(const char* label)
   *          -> The label can be blank if you want, but you MUST!! pass a string of some length. Use the '#' character to
   *              give it an ID without a label.
   *
   *      * Add tabs by using:
   *          if (ImGui::AddTab("Tab Name")){
   *                 < Insert other draw commands here >
   *          }
   *          -> This is much like collapsing header. If the tab is active, then AddTab will return true, allowing drawing
   *              to occur.
   *
   *      * End the tab bar by using ImGui::EndTabBar()
   *
   *      And that's it! You can dynamically add or remove tabs, the bar will reset the ID and tab label vectors appropriately,
   *      but it DOESN'T continuously allocate/deallocate them in memory every time (unless the CRC32 hashes of the tab or tab bar change,
   *      computed from their respective labels).
   *
   *      Notes:
   *          * You can change the rounding by altering:
   *                  "static constexpr const float rounding = 6.0f;"
   *             in the _drawTabBarTop function. Alternatively, you can add it as a parameter, but to save on memory being passed
   *             around, and since I will be using 6 as a constant, I didn't include this.
   *
   *          * The constexpr:
   *                  "static constexpr const float shrink = 1.0f;"
   *             in the _drawTabBarTop function needs to be set to the width of your borders.
   *
   *          * I added custom colors and a new prototype for GetColorU32() to acquire these colors. You can change them here.
   *
   *          * I added extra operator functions for ImVec2 and ImVec4, _YOU MUST_ define IMGUI_DEFINE_MATH_OPERATORS in
   *             imgui_internal.h for this to work.
   *
   *          * Please attribute my work if used or added, along with the original ImGui license/attribution.
   */
  
  
  #ifndef IMGUI_TABS_HPP
  #define IMGUI_TABS_HPP
  
  #ifndef IMGUI_DEFINE_MATH_OPERATORS
  #define IMGUI_DEFINE_MATH_OPERATORS
  #endif
  
  #include <string>
  #include <iostream>
  #include <vector>
  #include "imgui.h"
  #include "imgui_internal.h"
  
  // Define one of them to keep the compatibility with older versions of Dear ImGui
  #define IMGUI_VERSION_150_OR_MINUS
  #define IMGUI_VERSION_153_OR_MINUS
  #define IMGUI_VERSION_152_OR_MINUS
  
  #if defined (IMGUI_VERSION_150_OR_MINUS)
  #define  PathFillConvex  PathFill
  #endif
  
  #if defined (IMGUI_VERSION_152_OR_MINUS)
  #define ImGuiCorner_BotLeft    ImGuiCorner_BottomLeft
  #define ImGuiCorner_BotRight    ImGuiCorner_BottomRight
  #endif
  
  #if defined (IMGUI_VERSION_153_OR_MINUS)
  #define AntiAliasedFill  AntiAliasedShapes
  #define ChildRounding    ChildWindowRounding
  #define ImGuiStyleVar_ChildRounding  ImGuiStyleVar_ChildWindowRounding
  #endif
  
  
  // Extra Math Helpers (Set the proper define below in imgui_internal.h)
  #ifdef IMGUI_DEFINE_MATH_OPERATORS
  static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs)            { return ImVec4(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z, lhs.w+rhs.w); }
  static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs)            { return ImVec4(lhs.x*rhs.x, lhs.y*rhs.y, lhs.z*rhs.z, lhs.w*rhs.w); }
  static inline ImVec4 operator/(const ImVec4& lhs, const ImVec4& rhs)            { return ImVec4(lhs.x/rhs.x, lhs.y/rhs.y, lhs.z/rhs.z, lhs.w/rhs.w); }
  
  static inline ImVec4& operator+=(ImVec4& lhs, const ImVec4& rhs)            { lhs.x += rhs.x; lhs.y += rhs.y; lhs.z += rhs.z; lhs.w += rhs.w; return lhs;}
  static inline ImVec4& operator-=(ImVec4& lhs, const ImVec4& rhs)            { lhs.x -= rhs.x; lhs.y -= rhs.y; lhs.z -= rhs.z; lhs.w -= rhs.w; return lhs;}
  static inline ImVec4& operator*=(ImVec4& lhs, const ImVec4& rhs)            { lhs.x *= rhs.x; lhs.y *= rhs.y; lhs.z *= rhs.z; lhs.w *= rhs.w; return lhs;}
  static inline ImVec4& operator/=(ImVec4& lhs, const ImVec4& rhs)            { lhs.x /= rhs.x; lhs.y /= rhs.y; lhs.z /= rhs.z; lhs.w /= rhs.w; return lhs;}
  #endif
  
  namespace ImGui
  {
      /// User Colors & Style Extensions
      enum ImGuiUserCol_ {
          ImGuiUserCol_TabBorder = 0,
          ImGuiUserCol_TabBorderShadow,
          ImGuiUserCol_TabNormal,
          ImGuiUserCol_COUNT
      };
  
      // New style inspired from Traditionnal Green (gtk+) on Linux + to be improved !
      IMGUI_API void  StyleColorsLightGreen(ImGuiStyle* dst = NULL); // the default style in miniDart software
  
      /// Defines our user style attributes that don't fit within the standard ImGui stack
      IMGUI_API struct ImGuiUserStyle
      {
          ImVec4      Colors[ImGuiUserCol_COUNT];
          ImGuiUserStyle();
      };
  
      IMGUI_API static ImGuiUserStyle UserStyle;
  
      /// Additional prototype to retrieve user-defined colors in this header (to prevent foward compatilibity conflicts)
      IMGUI_API const ImU32 GetColorU32(ImGuiUserCol_ idx, float alpha_mul = 0.0f);
  
      ///Bitmask flags for telling _drawPartialRect() what edges to draw
      enum _EdgeType : char {
          EDGE_NONE   = 0,
          EDGE_LEFT   = 1 << 0,
          EDGE_TOP    = 1 << 1,
          EDGE_RIGHT  = 1 << 2,
          EDGE_BOTTOM = 1 << 3
      };
  
      /// Used internally to draw a rounded rect with the different borders disabled
      /*static*/ void _drawPartialRect(const ImVec2 a, const ImVec2 b, const float rounding, const int rounding_corners,
                                   ImDrawList* dl, const _EdgeType edges, const ImU32 color, const bool shadow = false,
                                   const _EdgeType shadow_edges = EDGE_NONE, const float shadow_offset = 4.0f,
                                   const float shadow_alpha = 0.075f);
  
      /// Struct containing TabBar data
      IMGUI_API struct TabBar{
  
          /// Constructor
          TabBar(const char* label, const ImVec2 tab_bar_size);
  
          /// Stores the titles of the tabs
          std::vector<const char*> tabTitles;
  
          /// Stores hash IDs of the tabs
          std::vector<ImGuiID> tabHashes;
  
          /// Keeps a tally of how many tabs have been added
          int tabCount = 0; // Set to 0 in StartTab
  
          /// Index defining the active tab
          int activeTab = 0;
  
          /// Title of the bar. Use #<ID> to omit the title but pass in an ID
          std::string barTitle;
  
          /// Size
          ImVec2 size = ImVec2(0,0);
  
          /// Hash of the TabBar
          ImU32 hash = 0x0;
  
          /// Index counter, cleared every call to "BeginTabBar"
          int idxCounter = 0;
  
          /// This holds the upper left corner for the final draw sequence
          ImVec2 upperLeft = ImVec2(0,0);
  
          /// Set to true once the tab bar has been initialized
          bool hasBeenInitialized = false;
  
          /// Holds the rounding value for padding reasons
          float corner_rounding = 0;
  
          /// Holds the value of the new selected tab
          int newSelected = -1;
  
          /// Sets the active tab
          void setActiveTab(const unsigned idx);
  
          /// Returns the currently active tab
          const int getActiveTab();
  
          /// Useful enums
          enum _TabType : char {LEFTMOST_TAB, MIDDLE_TAB, RIGHTMOST_TAB};
  
          /// Used internally
          void _drawTabBarTop(const char* label);
  
          void _drawTabBarBottom();
  
          /// Used internally
          void _setTabCount();
      };
  
      /// Struct containing global TabBar status
      IMGUI_API struct TabBarStack{
          /// Vector containing all of our tab bars
          std::vector <TabBar> TabBars;
  
          /// The running count of our tab bar. Useful as it's only written to when a new tab bar is generated. Helps prevent useless calls to std::vector<>::size()
          unsigned TabBarCount = 0;
  
          /// Index pointing to the current tab
          unsigned CurrentTabBar = 0;
  
          /// Returns a pointer to the current tab bar
          TabBar* getCurrentTabBar();
  
          /// Clears the counting index for the current tab bar
          void clearIdxCountCurrentTabBar();
  
          /// Returns true if the tab bar already exists, pass idx if you want a return index value
          const bool doesTabBarExist(const ImU32 hash, unsigned* const idx = NULL);
  
          /// Returns true if the tab bar already exists (computes hash), pass idx if you want a return index value
          const bool doesTabBarExist(const char* id, unsigned* const idx = NULL);
      };
  
      /// Static instantiation of the TabBarStack
      IMGUI_API static TabBarStack TabStack;
  
  // FIXME : unused ?
      /// Outwardly accessible way to set the active tab of the current stack.
      IMGUI_API static void SetActiveTabOfCurrentTabBar(const unsigned idx);
  
      /// Star the Tab Bar with this function. It creates a tab bar based on the computed CRC32 hash and pushes it into the internal stack if so.
      IMGUI_API void BeginTabBar(const char *label, const ImVec2 size = ImVec2(0, 0));
  
      /// Returns true when the tab is active. To use, implement with if(ImGui::AddTab(...)){}
      IMGUI_API const bool AddTab(const char* title);
  
      /// To use, implement with if(ImGui::DrawTabsBackground(...)){} just after ImGui::BeginTabBar();
      IMGUI_API void DrawTabsBackground();
  
      /// Call this after you are done adding tabs
      IMGUI_API void  EndTabBar();
  
  } // namespace ImGui
  #endif //IMGUI_TABS_HPP
  