BsEditorWidgetContainer.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #include "BsEditorWidgetContainer.h"
  2. #include "BsGUITabbedTitleBar.h"
  3. #include "BsEditorWidget.h"
  4. #include "BsDragAndDropManager.h"
  5. #include "BsEditorWindow.h"
  6. #include "BsGUIArea.h"
  7. #include "CmMath.h"
  8. #include "CmInput.h"
  9. #include "BsGUIWidget.h"
  10. #include "BsGUILayout.h"
  11. using namespace std::placeholders;
  12. namespace BansheeEngine
  13. {
  14. const UINT32 EditorWidgetContainer::TitleBarHeight = 13;
  15. EditorWidgetContainer::EditorWidgetContainer(GUIWidget* parent, RenderWindow* renderWindow, EditorWindow* parentEditorWindow)
  16. :mParent(parent), mX(0), mY(0), mWidth(0), mHeight(0), mTitleBar(nullptr), mActiveWidget(-1),
  17. mTitleBarArea(nullptr), mParentWindow(parentEditorWindow)
  18. {
  19. mTitleBarArea = GUIArea::create(*parent, 0, 0, 0, 0, 9900);
  20. mTitleBar = GUITabbedTitleBar::create(renderWindow);
  21. mTitleBar->onTabActivated.connect(std::bind(&EditorWidgetContainer::tabActivated, this, _1));
  22. mTitleBar->onTabClosed.connect(std::bind(&EditorWidgetContainer::tabClosed, this, _1));
  23. mTitleBar->onTabDraggedOff.connect(std::bind(&EditorWidgetContainer::tabDraggedOff, this, _1));
  24. mTitleBar->onTabDraggedOn.connect(std::bind(&EditorWidgetContainer::tabDraggedOn, this, _1));
  25. mTitleBarArea->getLayout().addElement(mTitleBar);
  26. }
  27. EditorWidgetContainer::~EditorWidgetContainer()
  28. {
  29. for(auto& widget : mWidgets)
  30. {
  31. widget.second->close();
  32. }
  33. GUIArea::destroy(mTitleBarArea);
  34. GUIElement::destroy(mTitleBar);
  35. }
  36. void EditorWidgetContainer::add(EditorWidgetBase& widget)
  37. {
  38. insert((UINT32)mWidgets.size(), widget);
  39. }
  40. void EditorWidgetContainer::remove(EditorWidgetBase& widget)
  41. {
  42. removeInternal(widget);
  43. if(!onWidgetClosed.empty())
  44. onWidgetClosed();
  45. }
  46. void EditorWidgetContainer::removeInternal(EditorWidgetBase& widget)
  47. {
  48. INT32 tabIdx = 0;
  49. for(auto& curWidget : mWidgets)
  50. {
  51. if(curWidget.second == &widget)
  52. {
  53. tabIdx = curWidget.first;
  54. break;
  55. }
  56. }
  57. if(tabIdx == -1)
  58. return;
  59. mWidgets.erase((UINT32)tabIdx);
  60. mTitleBar->removeTab((UINT32)tabIdx);
  61. widget._changeParent(nullptr);
  62. if(tabIdx == mActiveWidget)
  63. {
  64. mActiveWidget = -1;
  65. if(mTitleBar->getNumTabs() > 0)
  66. {
  67. setActiveWidget(mTitleBar->getTabIdx(0));
  68. }
  69. }
  70. }
  71. void EditorWidgetContainer::insert(UINT32 idx, EditorWidgetBase& widget)
  72. {
  73. if(contains(widget))
  74. return;
  75. idx = Math::clamp(idx, 0U, (UINT32)mWidgets.size());
  76. UINT32 tabIdx = mTitleBar->insertTab(idx, widget.getDisplayName());
  77. mWidgets[tabIdx] = &widget;
  78. widget._changeParent(this);
  79. if(mActiveWidget == -1)
  80. setActiveWidget(mTitleBar->getTabIdx(mTitleBar->getNumTabs() - 1));
  81. else
  82. widget._disable();
  83. }
  84. bool EditorWidgetContainer::contains(EditorWidgetBase& widget)
  85. {
  86. for(auto& curWidget : mWidgets)
  87. {
  88. if(curWidget.second == &widget)
  89. return true;
  90. }
  91. return false;
  92. }
  93. EditorWidgetBase* EditorWidgetContainer::getWidget(UINT32 idx) const
  94. {
  95. if(idx >= (UINT32)mWidgets.size())
  96. return nullptr;
  97. UINT32 tabIdx = mTitleBar->getTabIdx(idx);
  98. auto iterFind = mWidgets.find(tabIdx);
  99. if(iterFind != mWidgets.end())
  100. return iterFind->second;
  101. return nullptr;
  102. }
  103. void EditorWidgetContainer::setSize(UINT32 width, UINT32 height)
  104. {
  105. // TODO - Title bar is always TitleBarHeight size, so what happens when the container area is smaller than that?
  106. mTitleBarArea->setSize(width, TitleBarHeight);
  107. if(mActiveWidget >= 0)
  108. {
  109. EditorWidgetBase* activeWidgetPtr = mWidgets[mActiveWidget];
  110. UINT32 contentHeight = (UINT32)std::max(0, (INT32)height - (INT32)TitleBarHeight);
  111. activeWidgetPtr->_setSize(width, contentHeight);
  112. }
  113. mWidth = width;
  114. mHeight = height;
  115. }
  116. void EditorWidgetContainer::setPosition(INT32 x, INT32 y)
  117. {
  118. mTitleBarArea->setPosition(x, y);
  119. if(mActiveWidget >= 0)
  120. {
  121. EditorWidgetBase* activeWidgetPtr = mWidgets[mActiveWidget];
  122. activeWidgetPtr->_setPosition(x, y + TitleBarHeight);
  123. }
  124. mX = x;
  125. mY = y;
  126. }
  127. void EditorWidgetContainer::setActiveWidget(UINT32 idx)
  128. {
  129. if(mActiveWidget == idx)
  130. return;
  131. mActiveWidget = idx;
  132. for(auto& curWidget : mWidgets)
  133. {
  134. if(curWidget.first != (UINT32)mActiveWidget)
  135. curWidget.second->_disable();
  136. else
  137. curWidget.second->_enable();
  138. }
  139. mTitleBar->setActive(idx);
  140. setPosition(mX, mY);
  141. setSize(mWidth, mHeight);
  142. }
  143. void EditorWidgetContainer::tabActivated(UINT32 uniqueIdx)
  144. {
  145. setActiveWidget(uniqueIdx);
  146. }
  147. void EditorWidgetContainer::tabClosed(UINT32 uniqueIdx)
  148. {
  149. EditorWidgetBase* widget = mWidgets[uniqueIdx];
  150. widget->close();
  151. if(!onWidgetClosed.empty())
  152. onWidgetClosed();
  153. }
  154. void EditorWidgetContainer::tabDraggedOff(UINT32 uniqueIdx)
  155. {
  156. EditorWidgetBase* widget = mWidgets[uniqueIdx];
  157. removeInternal(*widget);
  158. DragAndDropManager::instance().startDrag((UINT32)DragAndDropType::EditorWidget, (void*)widget,
  159. std::bind(&EditorWidgetContainer::tabDroppedCallback, _1), false);
  160. if(!onWidgetClosed.empty())
  161. onWidgetClosed();
  162. }
  163. void EditorWidgetContainer::tabDraggedOn(UINT32 seqIdx)
  164. {
  165. #if CM_DEBUG_MODE
  166. if(!DragAndDropManager::instance().isDragInProgress())
  167. CM_EXCEPT(InternalErrorException, "Tab drag and drop reported but no drag in progress.");
  168. if(DragAndDropManager::instance().getDragTypeId() != (UINT32)DragAndDropType::EditorWidget)
  169. CM_EXCEPT(InternalErrorException, "Tab drag and drop reported but drag type is invalid.");
  170. #endif
  171. EditorWidgetBase* draggedWidget = static_cast<EditorWidgetBase*>(DragAndDropManager::instance().getDragData());
  172. insert(seqIdx, *draggedWidget);
  173. setActiveWidget(mTitleBar->getTabIdx(seqIdx));
  174. }
  175. void EditorWidgetContainer::tabDroppedCallback(bool wasDragProcessed)
  176. {
  177. if(DragAndDropManager::instance().getDragTypeId() != (UINT32)DragAndDropType::EditorWidget)
  178. return;
  179. if(!wasDragProcessed)
  180. {
  181. EditorWidgetBase* draggedWidget = static_cast<EditorWidgetBase*>(DragAndDropManager::instance().getDragData());
  182. EditorWindow* newWindow = EditorWindow::create();
  183. newWindow->widgets().add(*draggedWidget);
  184. Vector2I mousePos = Input::instance().getCursorPosition();
  185. newWindow->setPosition(mousePos.x, mousePos.y);
  186. }
  187. }
  188. RectI EditorWidgetContainer::getContentBounds() const
  189. {
  190. return RectI(mX, mY + TitleBarHeight, mWidth, (UINT32)std::max(0, (INT32)mHeight - (INT32)TitleBarHeight));
  191. }
  192. Vector<RectI>::type EditorWidgetContainer::getDraggableAreas() const
  193. {
  194. return mTitleBar->calcDraggableAreas(mX, mY, mWidth, TitleBarHeight);
  195. }
  196. void EditorWidgetContainer::_notifyWidgetDestroyed(EditorWidgetBase* widget)
  197. {
  198. for(auto& curWidget : mWidgets)
  199. {
  200. if(curWidget.second == widget)
  201. {
  202. removeInternal(*widget);
  203. if(!onWidgetClosed.empty())
  204. onWidgetClosed();
  205. return;
  206. }
  207. }
  208. }
  209. }