BsEditorWidgetContainer.cpp 5.9 KB

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