BsGUITabbedTitleBar.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #include "BsGUITabbedTitleBar.h"
  2. #include "BsGUIArea.h"
  3. #include "BsGUILayout.h"
  4. #include "BsGUITexture.h"
  5. #include "BsGUIButton.h"
  6. #include "BsGUITabButton.h"
  7. #include "BsGUISpace.h"
  8. #include "BsGUIWindowDropArea.h"
  9. #include "BsEngineGUI.h"
  10. #include "BsGUIWidget.h"
  11. #include "CmMath.h"
  12. #include "CmPlatform.h"
  13. using namespace CamelotFramework;
  14. using namespace BansheeEngine;
  15. namespace BansheeEditor
  16. {
  17. GUITabbedTitleBar::GUITabbedTitleBar(BS::GUIWidget* parent, CM::RenderWindow* parentWindow)
  18. :mParentWindow(parentWindow), mLastDropElement(nullptr), mMinBtn(nullptr), mCloseBtn(nullptr),
  19. mMainArea(nullptr), mMainLayout(nullptr), mParentWidget(parent), mBackgroundArea(nullptr), mUniqueTabIdx(0), mActiveTabIdx(0)
  20. {
  21. mBackgroundArea = GUIArea::create(*parent, 0, 0, 1, 13, 9900);
  22. GUIWindowDropArea* titleBarBg = GUIWindowDropArea::create(*parent, parent->getSkin().getStyle("TitleBarBackground"));
  23. mBackgroundArea->getLayout().addSpace(1);
  24. mBackgroundArea->getLayout().addElement(titleBarBg);
  25. mBackgroundArea->getLayout().addSpace(1);
  26. mMainArea = GUIArea::create(*parent, 0, 0, 1, 13, 9899);
  27. GUIWindowDropArea* dragDropElement = GUIWindowDropArea::create(*parent, GUIOptions(GUIOption::flexibleWidth(20)), parent->getSkin().getStyle("TabbedBarDropArea"));
  28. mLastDropElement = dragDropElement;
  29. mMinBtn = GUIButton::create(*parent, HString(L""), parent->getSkin().getStyle("WinMinimizeBtn"));
  30. mCloseBtn = GUIButton::create(*parent, HString(L""), parent->getSkin().getStyle("WinCloseBtn"));
  31. mCloseBtn->onClick.connect(boost::bind(&GUITabbedTitleBar::tabClosed, this));
  32. mMainArea->getLayout().addSpace(1);
  33. mMainLayout = &mMainArea->getLayout().addLayoutX();
  34. mMainLayout->addElement(dragDropElement);
  35. mMainLayout->addElement(mMinBtn);
  36. mMainLayout->addSpace(3);
  37. mMainLayout->addElement(mCloseBtn);
  38. mMainArea->getLayout().addSpace(3);
  39. refreshNonClientAreas();
  40. }
  41. GUITabbedTitleBar::~GUITabbedTitleBar()
  42. {
  43. GUIArea::destroy(mMainArea);
  44. GUIArea::destroy(mBackgroundArea);
  45. GUIElement::destroy(mLastDropElement);
  46. GUIElement::destroy(mMinBtn);
  47. GUIElement::destroy(mCloseBtn);
  48. for(auto& tabButton : mTabButtons)
  49. {
  50. GUIElement::destroy(tabButton);
  51. }
  52. for(auto& dragDropButton : mDragDropElements)
  53. {
  54. GUIElement::destroy(dragDropButton);
  55. }
  56. }
  57. void GUITabbedTitleBar::addTab(const CM::HString& name)
  58. {
  59. insertTab((UINT32)mTabButtons.size(), name);
  60. }
  61. void GUITabbedTitleBar::insertTab(UINT32 idx, const CM::HString& name)
  62. {
  63. GUITabButton* newTabToggle = GUITabButton::create(*mParentWidget, this, mUniqueTabIdx, name, EngineGUI::instance().getSkin().getStyle("TabbedBarBtn"));
  64. GUIWindowDropArea* newDragDropElement = GUIWindowDropArea::create(*mParentWidget, EngineGUI::instance().getSkin().getStyle("TabbedBarDropArea"));
  65. idx = Math::Clamp(idx, 0U, (UINT32)mTabButtons.size());
  66. newTabToggle->onToggled.connect(boost::bind(&GUITabbedTitleBar::tabToggled, this, mUniqueTabIdx));
  67. newTabToggle->onDragged.connect(boost::bind(&GUITabbedTitleBar::tabDraggedOff, this, _1));
  68. newDragDropElement->onDraggedItemDropped.connect(boost::bind(&GUITabbedTitleBar::tabDraggedOn, this, mUniqueTabIdx));
  69. mTabButtons.insert(mTabButtons.begin() + idx, newTabToggle);
  70. mDragDropElements.insert(mDragDropElements.begin() + idx, newDragDropElement);
  71. mMainLayout->insertElement(idx * 2, newTabToggle);
  72. mMainLayout->insertElement(idx * 2, newDragDropElement);
  73. mUniqueTabIdx++;
  74. refreshNonClientAreas();
  75. }
  76. void GUITabbedTitleBar::removeTab(UINT32 idx)
  77. {
  78. if(mTabButtons.size() == 0)
  79. return;
  80. idx = Math::Clamp(idx, 0U, (UINT32)mTabButtons.size() - 1);
  81. GUIElement::destroy(mTabButtons[idx]);
  82. GUIElement::destroy(mDragDropElements[idx]);
  83. mTabButtons.erase(mTabButtons.begin() + idx);
  84. mDragDropElements.erase(mDragDropElements.begin() + idx);
  85. refreshNonClientAreas();
  86. }
  87. void GUITabbedTitleBar::setPosition(INT32 x, INT32 y)
  88. {
  89. mMainArea->setPosition(x, y);
  90. mBackgroundArea->setPosition(x, y);
  91. refreshNonClientAreas();
  92. }
  93. void GUITabbedTitleBar::setSize(UINT32 width, UINT32 height)
  94. {
  95. mMainArea->setSize(width, height);
  96. mBackgroundArea->setSize(width, height);
  97. refreshNonClientAreas();
  98. }
  99. void GUITabbedTitleBar::tabToggled(CM::UINT32 tabIdx)
  100. {
  101. INT32 idx = uniqueIdxToSeqIdx(tabIdx);
  102. if(idx != -1)
  103. {
  104. if(!onTabActivated.empty())
  105. onTabActivated(idx);
  106. }
  107. mActiveTabIdx = tabIdx;
  108. }
  109. void GUITabbedTitleBar::tabClosed()
  110. {
  111. INT32 idx = uniqueIdxToSeqIdx(mActiveTabIdx);
  112. if(idx != -1)
  113. {
  114. removeTab(idx);
  115. if(mTabButtons.size() > 0)
  116. mActiveTabIdx = mTabButtons[0]->getIndex();
  117. if(!onTabClosed.empty())
  118. onTabClosed(idx);
  119. }
  120. }
  121. void GUITabbedTitleBar::tabDraggedOff(CM::UINT32 tabIdx)
  122. {
  123. INT32 idx = uniqueIdxToSeqIdx(tabIdx);
  124. if(idx != -1)
  125. {
  126. if(!onTabDraggedOff.empty())
  127. onTabDraggedOff(idx);
  128. }
  129. }
  130. void GUITabbedTitleBar::tabDraggedOn(CM::UINT32 tabIdx)
  131. {
  132. INT32 idx = uniqueIdxToSeqIdx(tabIdx);
  133. if(idx != -1)
  134. {
  135. if(!onTabDraggedOn.empty())
  136. onTabDraggedOn(idx + 1);
  137. }
  138. }
  139. CM::INT32 GUITabbedTitleBar::uniqueIdxToSeqIdx(CM::UINT32 uniqueIdx) const
  140. {
  141. UINT32 idx = 0;
  142. for(auto& tab : mTabButtons)
  143. {
  144. if(tab->getIndex() == uniqueIdx)
  145. return idx;
  146. idx++;
  147. }
  148. return -1;
  149. }
  150. void GUITabbedTitleBar::refreshNonClientAreas()
  151. {
  152. // If the size or contents of the area changed this frame the layout won't be updated yet,
  153. // so force the update right away so we get correct element bounds
  154. mMainArea->_update();
  155. CM::Vector<CM::Rect>::type nonClientAreas;
  156. for(auto& elem : mDragDropElements)
  157. {
  158. nonClientAreas.push_back(elem->getBounds());
  159. }
  160. nonClientAreas.push_back(mLastDropElement->getBounds());
  161. Platform::setCaptionNonClientAreas(*mParentWindow, nonClientAreas);
  162. }
  163. }