VectorNodePropertyDisplay.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <QGraphicsLinearLayout>
  9. #include <QGraphicsPixmapItem>
  10. #include <QGraphicsProxyWidget>
  11. #include <QGraphicsSceneDragDropEvent>
  12. #include <QGraphicsView>
  13. #include <QHBoxLayout>
  14. #include <QMimeData>
  15. #include <QPixmap>
  16. #include <QToolButton>
  17. #include <AzQtComponents/Components/Widgets/SpinBox.h>
  18. #include <Components/NodePropertyDisplays/VectorNodePropertyDisplay.h>
  19. #include <GraphCanvas/Components/Slots/Data/DataSlotBus.h>
  20. #include <GraphCanvas/Components/VisualBus.h>
  21. #include <GraphCanvas/Widgets/NodePropertyBus.h>
  22. #include <Widgets/GraphCanvasLabel.h>
  23. namespace GraphCanvas
  24. {
  25. //////////////////////
  26. // VectorEventFilter
  27. //////////////////////
  28. VectorEventFilter::VectorEventFilter(VectorNodePropertyDisplay* owner)
  29. : m_owner(owner)
  30. {
  31. }
  32. bool VectorEventFilter::eventFilter(QObject*, QEvent* event)
  33. {
  34. switch (event->type())
  35. {
  36. case QEvent::FocusIn:
  37. m_owner->EditStart();
  38. break;
  39. case QEvent::FocusOut:
  40. m_owner->EditFinished();
  41. break;
  42. default:
  43. break;
  44. }
  45. return false;
  46. }
  47. //////////////////////////
  48. // ReadOnlyVectorControl
  49. //////////////////////////
  50. ReadOnlyVectorControl::ReadOnlyVectorControl(int index, const VectorDataInterface& dataInterface)
  51. : m_index(index)
  52. , m_dataInterface(dataInterface)
  53. {
  54. m_layout = new QGraphicsLinearLayout(Qt::Orientation::Horizontal);
  55. m_layout->setSpacing(0);
  56. m_layout->setContentsMargins(0, 0, 0, 0);
  57. m_textLabel = aznew GraphCanvasLabel();
  58. m_textLabel->SetRoundedCornersMode(GraphCanvasLabel::RoundedCornersMode::LeftCorners);
  59. m_valueLabel = aznew GraphCanvasLabel();
  60. m_valueLabel->SetRoundedCornersMode(GraphCanvasLabel::RoundedCornersMode::RightCorners);
  61. m_layout->addItem(m_textLabel);
  62. m_layout->addItem(m_valueLabel);
  63. m_textLabel->SetLabel(dataInterface.GetLabel(index));
  64. setContentsMargins(0, 0, 0, 0);
  65. setLayout(m_layout);
  66. }
  67. ReadOnlyVectorControl::~ReadOnlyVectorControl()
  68. {
  69. }
  70. void ReadOnlyVectorControl::RefreshStyle(const AZ::EntityId& sceneId)
  71. {
  72. AZStd::string styleName = m_dataInterface.GetElementStyle(m_index);
  73. m_textLabel->SetSceneStyle(sceneId, NodePropertyDisplay::CreateDisplayLabelStyle(styleName + "_text").c_str());
  74. m_valueLabel->SetSceneStyle(sceneId, NodePropertyDisplay::CreateDisplayLabelStyle(styleName + "_value").c_str());
  75. }
  76. void ReadOnlyVectorControl::UpdateDisplay()
  77. {
  78. double value = m_dataInterface.GetValue(m_index);
  79. AZStd::string displayValue = AZStd::string::format("%.*g%s", m_dataInterface.GetDisplayDecimalPlaces(m_index), value, m_dataInterface.GetSuffix(m_index));
  80. m_valueLabel->SetLabel(displayValue);
  81. }
  82. int ReadOnlyVectorControl::GetIndex() const
  83. {
  84. return m_index;
  85. }
  86. GraphCanvasLabel* ReadOnlyVectorControl::GetTextLabel()
  87. {
  88. return m_textLabel;
  89. }
  90. const GraphCanvasLabel* ReadOnlyVectorControl::GetTextLabel() const
  91. {
  92. return m_textLabel;
  93. }
  94. GraphCanvasLabel* ReadOnlyVectorControl::GetValueLabel()
  95. {
  96. return m_valueLabel;
  97. }
  98. const GraphCanvasLabel* ReadOnlyVectorControl::GetValueLabel() const
  99. {
  100. return m_valueLabel;
  101. }
  102. IconLayoutItem::IconLayoutItem(QGraphicsItem* parent)
  103. : QGraphicsWidget(parent)
  104. , m_pixmap(new QGraphicsPixmapItem(this))
  105. {
  106. setGraphicsItem(m_pixmap);
  107. }
  108. void IconLayoutItem::setIcon(const QPixmap& pixmap)
  109. {
  110. m_pixmap->setPixmap(pixmap);
  111. }
  112. IconLayoutItem::~IconLayoutItem()
  113. {
  114. }
  115. //////////////////////////////
  116. // VectorNodePropertyDisplay
  117. //////////////////////////////
  118. VectorNodePropertyDisplay::VectorNodePropertyDisplay(VectorDataInterface* dataInterface)
  119. : NodePropertyDisplay(dataInterface)
  120. , m_dataInterface(dataInterface)
  121. , m_disabledLabel(nullptr)
  122. , m_propertyVectorCtrl(nullptr)
  123. , m_button(nullptr)
  124. , m_proxyWidget(nullptr)
  125. , m_displayWidget(nullptr)
  126. , m_iconDisplay(nullptr)
  127. {
  128. m_displayWidget = new QGraphicsWidget();
  129. m_displayWidget->setContentsMargins(0, 0, 0, 0);
  130. m_displayWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
  131. QGraphicsLinearLayout* displayLayout = new QGraphicsLinearLayout(Qt::Orientation::Horizontal);
  132. displayLayout->setSpacing(5);
  133. displayLayout->setContentsMargins(0, 0, 0, 0);
  134. displayLayout->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
  135. m_iconDisplay = new IconLayoutItem();
  136. m_iconDisplay->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
  137. displayLayout->addItem(m_iconDisplay);
  138. displayLayout->setAlignment(m_iconDisplay, Qt::AlignBottom);
  139. int elementCount = dataInterface->GetElementCount();
  140. m_vectorDisplays.reserve(elementCount);
  141. for (int i=0; i < elementCount; ++i)
  142. {
  143. m_vectorDisplays.push_back(aznew ReadOnlyVectorControl(i, (*dataInterface)));
  144. displayLayout->addItem(m_vectorDisplays.back());
  145. }
  146. m_displayWidget->setLayout(displayLayout);
  147. m_disabledLabel = aznew GraphCanvasLabel();
  148. }
  149. VectorNodePropertyDisplay::~VectorNodePropertyDisplay()
  150. {
  151. delete m_dataInterface;
  152. m_dataInterface = nullptr;
  153. delete m_disabledLabel;
  154. delete m_displayWidget;
  155. CleanupProxyWidget();
  156. }
  157. void VectorNodePropertyDisplay::RefreshStyle()
  158. {
  159. AZ::EntityId sceneId = GetSceneId();
  160. AZStd::string elementStyle = m_dataInterface->GetStyle();
  161. m_styleHelper.SetScene(sceneId);
  162. m_styleHelper.SetStyle(NodePropertyDisplay::CreateDisplayLabelStyle(elementStyle).c_str());
  163. m_disabledLabel->SetSceneStyle(GetSceneId(), NodePropertyDisplay::CreateDisabledLabelStyle(elementStyle).c_str());
  164. QColor backgroundColor = m_styleHelper.GetAttribute(GraphCanvas::Styling::Attribute::BackgroundColor, QColor(0, 0, 0, 0));
  165. m_displayWidget->setAutoFillBackground(true);
  166. QPalette palette = m_displayWidget->palette();
  167. palette.setColor(QPalette::ColorRole::Window, backgroundColor);
  168. m_displayWidget->setPalette(palette);
  169. qreal spacing = static_cast<QGraphicsLinearLayout*>(m_displayWidget->layout())->spacing();
  170. // Start off with - spacing to make the iteration logic cleaner.
  171. qreal elementWidth = -spacing;
  172. qreal elementHeight = m_styleHelper.GetAttribute(GraphCanvas::Styling::Attribute::Height, 0);
  173. const qreal k_sizingConstraint = 200;
  174. for (auto control : m_vectorDisplays)
  175. {
  176. control->RefreshStyle(sceneId);
  177. QSizeF maximumSize = control->maximumSize();
  178. // Maximum size might be stupidly large, which will cause an error
  179. // from Qt as it tries to overly allocate space for something.
  180. //
  181. // As such we want to put an upper limit on this that is large but not unreasonable.
  182. // Can't really do this at the element level since it messes with the styling
  183. // when I set it. So instead we'll do it here.
  184. elementWidth += AZ::GetMin(maximumSize.width(), k_sizingConstraint) + spacing;
  185. elementHeight = AZStd::GetMax(elementHeight, AZ::GetMin(k_sizingConstraint, maximumSize.height()));
  186. }
  187. elementWidth += m_iconDisplay->preferredWidth();
  188. m_displayWidget->setMinimumSize(elementWidth, elementHeight);
  189. m_displayWidget->setPreferredSize(elementWidth, elementHeight);
  190. m_displayWidget->setMaximumSize(elementWidth, elementHeight);
  191. m_displayWidget->adjustSize();
  192. if (m_propertyVectorCtrl)
  193. {
  194. m_propertyVectorCtrl->setMinimumSize(aznumeric_cast<int>(elementWidth), aznumeric_cast<int>(elementHeight));
  195. m_propertyVectorCtrl->setMaximumSize(aznumeric_cast<int>(elementWidth), aznumeric_cast<int>(elementHeight));
  196. m_propertyVectorCtrl->adjustSize();
  197. }
  198. }
  199. void VectorNodePropertyDisplay::UpdateDisplay()
  200. {
  201. for (auto control : m_vectorDisplays)
  202. {
  203. control->UpdateDisplay();
  204. }
  205. const auto buttonIcon = m_dataInterface->GetIcon();
  206. if (m_iconDisplay)
  207. {
  208. if (!buttonIcon.isNull())
  209. {
  210. m_iconDisplay->setPreferredSize(buttonIcon.size());
  211. m_iconDisplay->setIcon(buttonIcon);
  212. }
  213. m_iconDisplay->setVisible(!buttonIcon.isNull());
  214. }
  215. if (m_button)
  216. {
  217. if (!buttonIcon.isNull())
  218. {
  219. QIcon newIcon(buttonIcon);
  220. m_button->setFixedSize(buttonIcon.size());
  221. m_button->setIconSize(buttonIcon.size());
  222. m_button->setIcon(newIcon);
  223. }
  224. m_button->setVisible(!buttonIcon.isNull());
  225. }
  226. if (m_propertyVectorCtrl)
  227. {
  228. for (int i = 0; i < m_vectorDisplays.size(); ++i)
  229. {
  230. m_propertyVectorCtrl->setValuebyIndex(m_dataInterface->GetValue(i), i);
  231. }
  232. m_proxyWidget->update();
  233. }
  234. }
  235. QGraphicsLayoutItem* VectorNodePropertyDisplay::GetDisabledGraphicsLayoutItem()
  236. {
  237. CleanupProxyWidget();
  238. return m_disabledLabel;
  239. }
  240. QGraphicsLayoutItem* VectorNodePropertyDisplay::GetDisplayGraphicsLayoutItem()
  241. {
  242. CleanupProxyWidget();
  243. return m_displayWidget;
  244. }
  245. QGraphicsLayoutItem* VectorNodePropertyDisplay::GetEditableGraphicsLayoutItem()
  246. {
  247. SetupProxyWidget();
  248. return m_proxyWidget;
  249. }
  250. void VectorNodePropertyDisplay::OnDragDropStateStateChanged(const DragDropState& dragState)
  251. {
  252. for (ReadOnlyVectorControl* vectorControl : m_vectorDisplays)
  253. {
  254. {
  255. Styling::StyleHelper& styleHelper = vectorControl->GetTextLabel()->GetStyleHelper();
  256. UpdateStyleForDragDrop(dragState, styleHelper);
  257. vectorControl->GetTextLabel()->update();
  258. }
  259. {
  260. Styling::StyleHelper& styleHelper = vectorControl->GetValueLabel()->GetStyleHelper();
  261. UpdateStyleForDragDrop(dragState, styleHelper);
  262. vectorControl->GetValueLabel()->update();
  263. }
  264. }
  265. }
  266. void VectorNodePropertyDisplay::EditStart()
  267. {
  268. NodePropertiesRequestBus::Event(GetNodeId(), &NodePropertiesRequests::LockEditState, this);
  269. TryAndSelectNode();
  270. }
  271. void VectorNodePropertyDisplay::SubmitValue()
  272. {
  273. AzQtComponents::VectorElement** elements = m_propertyVectorCtrl->getElements();
  274. const int elementCount = m_propertyVectorCtrl->getSize();
  275. for (int i = 0; i < elementCount; ++i)
  276. {
  277. const AzQtComponents::VectorElement* element = elements[i];
  278. m_dataInterface->SetValue(i, element->getValue());
  279. }
  280. UpdateDisplay();
  281. }
  282. void VectorNodePropertyDisplay::EditFinished()
  283. {
  284. SubmitValue();
  285. NodePropertiesRequestBus::Event(GetNodeId(), &NodePropertiesRequests::UnlockEditState, this);
  286. }
  287. void VectorNodePropertyDisplay::SetupProxyWidget()
  288. {
  289. if (!m_propertyVectorCtrl)
  290. {
  291. m_proxyWidget = new QGraphicsProxyWidget();
  292. m_widgetContainer = new QWidget();
  293. QHBoxLayout* layout = new QHBoxLayout(m_widgetContainer);
  294. m_widgetContainer->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
  295. layout->setAlignment(Qt::AlignLeft);
  296. layout->setContentsMargins(0, 0, 0, 0);
  297. m_button = new QToolButton(m_widgetContainer);
  298. m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
  299. m_button->setVisible(false);
  300. QObject::connect(m_button, &QToolButton::clicked, [this] () {
  301. NodePropertiesRequestBus::Event(GetNodeId(), &NodePropertiesRequests::LockEditState, this);
  302. m_dataInterface->OnPressButton();
  303. UpdateDisplay();
  304. NodePropertiesRequestBus::Event(GetNodeId(), &NodePropertiesRequests::UnlockEditState, this);
  305. });
  306. layout->addWidget(m_button);
  307. m_proxyWidget->setFlag(QGraphicsItem::ItemIsFocusable, true);
  308. m_proxyWidget->setFocusPolicy(Qt::StrongFocus);
  309. m_proxyWidget->setAcceptDrops(false);
  310. const int elementCount = m_dataInterface->GetElementCount();
  311. m_propertyVectorCtrl = new AzQtComponents::VectorInput(m_widgetContainer, elementCount);
  312. for (int i = 0; i < elementCount; ++i)
  313. {
  314. m_propertyVectorCtrl->setLabel(i, m_dataInterface->GetLabel(i));
  315. m_propertyVectorCtrl->setMinimum(m_dataInterface->GetMinimum(i));
  316. m_propertyVectorCtrl->setMaximum(m_dataInterface->GetMaximum(i));
  317. m_propertyVectorCtrl->setDecimals(m_dataInterface->GetDecimalPlaces(i));
  318. m_propertyVectorCtrl->setDisplayDecimals(m_dataInterface->GetDisplayDecimalPlaces(i));
  319. m_propertyVectorCtrl->setSuffix(m_dataInterface->GetSuffix(i));
  320. }
  321. m_propertyVectorCtrl->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
  322. QObject::connect(m_propertyVectorCtrl, &AzQtComponents::VectorInput::editingFinished, [this]() { SubmitValue(); });
  323. layout->addWidget(m_propertyVectorCtrl);
  324. m_widgetContainer->setProperty("HasNoWindowDecorations", true);
  325. m_proxyWidget->setWidget(m_widgetContainer);
  326. UpdateDisplay();
  327. RefreshStyle();
  328. RegisterShortcutDispatcher(m_propertyVectorCtrl);
  329. }
  330. }
  331. void VectorNodePropertyDisplay::CleanupProxyWidget()
  332. {
  333. if (m_propertyVectorCtrl)
  334. {
  335. UnregisterShortcutDispatcher(m_propertyVectorCtrl);
  336. delete m_widgetContainer; // NB: this implicitly deletes m_proxy widget
  337. m_widgetContainer = nullptr;
  338. m_propertyVectorCtrl = nullptr;
  339. m_button= nullptr;
  340. m_proxyWidget = nullptr;
  341. }
  342. }
  343. #include <Source/Components/NodePropertyDisplays/moc_VectorNodePropertyDisplay.cpp>
  344. }