diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
commit | 6352e8e3196f78388b6c771073f9e03eaa612673 (patch) | |
tree | e23772f79a7fbc41bc9108951e9e136857484bf4 /source/windowing/StarListWidget.cpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/windowing/StarListWidget.cpp')
-rw-r--r-- | source/windowing/StarListWidget.cpp | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/source/windowing/StarListWidget.cpp b/source/windowing/StarListWidget.cpp new file mode 100644 index 0000000..cda7f92 --- /dev/null +++ b/source/windowing/StarListWidget.cpp @@ -0,0 +1,262 @@ +#include "StarListWidget.hpp" +#include "StarGuiReader.hpp" +#include "StarJsonExtra.hpp" +#include "StarRandom.hpp" +#include "StarImageWidget.hpp" +#include "StarAssets.hpp" +#include "StarRoot.hpp" + +namespace Star { + +ListWidget::ListWidget(Json const& schema) : m_schema(schema) { + m_selectedItem = NPos; + m_columns = 1; + setSchema(m_schema); + updateSizeAndPosition(); +} + +ListWidget::ListWidget() { + m_selectedItem = NPos; + m_columns = 1; + updateSizeAndPosition(); +} + +RectI ListWidget::relativeBoundRect() const { + if (m_fillDown) + return RectI::withSize(relativePosition() - Vec2I(0, size()[1]), size()); + else + return RectI::withSize(relativePosition(), size()); +} + +void ListWidget::setCallback(WidgetCallbackFunc callback) { + m_callback = move(callback); +} + +bool ListWidget::sendEvent(InputEvent const& event) { + if (!m_visible) + return false; + + for (size_t i = m_members.size(); i != 0; --i) { + auto child = m_members[i - 1]; + if (child->sendEvent(event) + || (event.is<MouseButtonDownEvent>() && child->inMember(*context()->mousePosition(event)) + && event.get<MouseButtonDownEvent>().mouseButton == MouseButton::Left)) { + setSelected(i - 1); + return true; + } + setHovered(i - 1, event.is<MouseMoveEvent>() && child->inMember(*context()->mousePosition(event))); + } + + return false; +} + +void ListWidget::setSchema(Json const& schema) { + clear(); + m_schema = schema; + try { + m_selectedBG = schema.getString("selectedBG", ""); + m_unselectedBG = schema.getString("unselectedBG", ""); + m_hoverBG = schema.getString("hoverBG", ""); + m_disabledBG = schema.getString("disabledBG", ""); + if (m_disabledBG.empty() && !m_unselectedBG.empty()) + m_disabledBG = m_unselectedBG + Root::singleton().assets()->json("/interface.config:disabledButton").toString(); + m_spacing = jsonToVec2I(schema.get("spacing")); + m_memberSize = jsonToVec2I(schema.get("memberSize")); + } catch (JsonException const& e) { + throw GuiException(strf("Missing required value in map: %s", outputException(e, false))); + } + updateSizeAndPosition(); +} + +WidgetPtr ListWidget::addItem() { + auto newItem = constructWidget(); + addChild(strf("%d", Random::randu64()), newItem); + updateSizeAndPosition(); + + return newItem; +} + +WidgetPtr ListWidget::addItem(size_t at) { + auto newItem = constructWidget(); + addChildAt(strf("%d", Random::randu64()), newItem, at); + updateSizeAndPosition(); + + if (m_selectedItem != NPos && at <= m_selectedItem) + setSelected(m_selectedItem + 1); + + return newItem; +} + +WidgetPtr ListWidget::addItem(WidgetPtr existingItem) { + addChild(strf("%d", Random::randu64()), existingItem); + updateSizeAndPosition(); + + return existingItem; +} + +WidgetPtr ListWidget::constructWidget() { + WidgetPtr newItem = make_shared<Widget>(); + m_reader.construct(m_schema.get("listTemplate"), newItem.get()); + newItem->setSize(m_memberSize); + m_doScissor ? newItem->enableScissoring() : newItem->disableScissoring(); + return newItem; +} + +void ListWidget::updateSizeAndPosition() { + int rows = m_members.size() % m_columns ? m_members.size() / m_columns + 1 : m_members.size() / m_columns; + for (size_t i = 0; i < m_members.size(); i++) { + Vec2I currentOffset; + int col = i % m_columns; + int row = rows - (i / m_columns) - 1; + if (m_fillDown) + row -= rows; + currentOffset = Vec2I((m_memberSize[0] + m_spacing[0]) * col, (m_memberSize[1] + m_spacing[1]) * row); + if (!m_fillDown) + currentOffset[1] += m_spacing[1]; + m_members[i]->setPosition(currentOffset); + } + if (m_members.size()) { + auto width = (m_memberSize[0] + m_spacing[0]) * m_columns; + auto height = (m_memberSize[1] + m_spacing[1]) * rows; + setSize(Vec2I(width, height)); + } else { + setSize(Vec2I()); + } +} + +void ListWidget::setEnabled(size_t pos, bool enabled) { + if (pos != NPos && pos < listSize()) { + if (enabled) { + m_disabledItems.remove(pos); + if (auto bgWidget = itemAt(pos)->fetchChild<ImageWidget>("background")) + bgWidget->setImage(pos == m_selectedItem ? m_selectedBG : m_unselectedBG); + } else { + m_disabledItems.add(pos); + if (m_selectedItem == pos) + clearSelected(); + if (auto bgWidget = itemAt(pos)->fetchChild<ImageWidget>("background")) + bgWidget->setImage(m_disabledBG); + } + } +} + +void ListWidget::setHovered(size_t pos, bool hovered) { + if (m_hoverBG == "") + return; + + if (pos != m_selectedItem && pos < listSize() && !m_disabledItems.contains(pos)) { + if (auto bgWidget = itemAt(pos)->fetchChild<ImageWidget>("background")) { + if (hovered) + bgWidget->setImage(m_hoverBG); + else + bgWidget->setImage(m_unselectedBG); + } + } +} + +void ListWidget::setSelected(size_t pos) { + if ((m_selectedItem != NPos) && (m_selectedItem < listSize())) { + if (auto bgWidget = selectedWidget()->fetchChild<ImageWidget>("background")) + bgWidget->setImage(m_unselectedBG); + } + + if (!m_disabledItems.contains(pos) && m_selectedItem != pos) { + m_selectedItem = pos; + if (m_callback) + m_callback(this); + } + + if (m_selectedItem != NPos) { + if (auto bgWidget = selectedWidget()->fetchChild<ImageWidget>("background")) + bgWidget->setImage(m_selectedBG); + } +} + +void ListWidget::clearSelected() { + setSelected(NPos); +} + +void ListWidget::setSelectedWidget(WidgetPtr selected) { + auto offset = itemPosition(selected); + + if (offset == NPos) { + throw GuiException("Attempted to select item not in list."); + } + + setSelected(offset); +} + +void ListWidget::registerMemberCallback(String const& name, WidgetCallbackFunc const& callback) { + m_reader.registerCallback(name, callback); +} + +void ListWidget::setFillDown(bool fillDown) { + m_fillDown = fillDown; +} + +void ListWidget::setColumns(uint64_t columns) { + m_columns = columns; +} + +void ListWidget::removeItem(size_t at) { + removeChildAt(at); + if (m_selectedItem == at) + setSelected(NPos); + else if (m_selectedItem != NPos && m_selectedItem > at) + setSelected(m_selectedItem - 1); + + updateSizeAndPosition(); +} + +void ListWidget::removeItem(WidgetPtr item) { + auto offset = itemPosition(item); + + if (offset == NPos) { + throw GuiException("Attempted to remove item not in list."); + } + + removeItem(offset); +} + +void ListWidget::clear() { + setSelected(NPos); + removeAllChildren(); + updateSizeAndPosition(); +} + +size_t ListWidget::selectedItem() const { + return m_selectedItem; +} + +size_t ListWidget::itemPosition(WidgetPtr item) const { + size_t offset = NPos; + for (size_t i = 0; i < m_members.size(); ++i) { + if (m_members[i] == item) { + offset = i; + break; + } + } + return offset; +} + +WidgetPtr ListWidget::itemAt(size_t n) const { + if (n < m_members.size()) { + return m_members[n]; + } else { + return {}; + } +} + +WidgetPtr ListWidget::selectedWidget() const { + return itemAt(m_selectedItem); +} + +List<WidgetPtr> const& ListWidget::list() const { + return m_members; +} + +size_t ListWidget::listSize() const { + return numChildren(); +} + +} |