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/StarPane.cpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/windowing/StarPane.cpp')
-rw-r--r-- | source/windowing/StarPane.cpp | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/source/windowing/StarPane.cpp b/source/windowing/StarPane.cpp new file mode 100644 index 0000000..d1dfb0f --- /dev/null +++ b/source/windowing/StarPane.cpp @@ -0,0 +1,369 @@ +#include "StarPane.hpp" +#include "StarRoot.hpp" +#include "StarJsonExtra.hpp" +#include "StarAssets.hpp" + +namespace Star { + +EnumMap<PaneAnchor> const PaneAnchorNames{ + {PaneAnchor::None, "none"}, + {PaneAnchor::BottomLeft, "bottomLeft"}, + {PaneAnchor::BottomRight, "bottomRight"}, + {PaneAnchor::TopLeft, "topLeft"}, + {PaneAnchor::TopRight, "topRight"}, + {PaneAnchor::CenterBottom, "centerBottom"}, + {PaneAnchor::CenterTop, "centerTop"}, + {PaneAnchor::CenterLeft, "centerLeft"}, + {PaneAnchor::CenterRight, "centerRight"}, + {PaneAnchor::Center, "center"}, +}; + +Pane::Pane() { + m_dragActive = m_lockPosition = false; + m_dismissed = true; + m_centerOffset = Vec2I(); + m_anchor = PaneAnchor::None; + m_anchorOffset = Vec2I(); + m_visible = false; + m_hasDisplayed = false; + + auto assets = Root::singleton().assets(); + m_fontSize = assets->json("/interface.config:font.baseSize").toInt(); + m_iconOffset = jsonToVec2I(assets->json("/interface.config:paneIconOffset")); + m_titleOffset = jsonToVec2I(assets->json("/interface.config:paneTitleOffset")); + m_subTitleOffset = jsonToVec2I(assets->json("/interface.config:paneSubTitleOffset")); + m_titleColor = jsonToColor(assets->json("/interface.config:paneTitleColor")); + m_subTitleColor = jsonToColor(assets->json("/interface.config:paneSubTitleColor")); +} + +void Pane::displayed() { + m_dismissed = false; + m_hasDisplayed = true; + show(); +} + +void Pane::dismissed() { + if (m_clickDown) + m_clickDown->mouseOut(); + m_clickDown.reset(); + if (m_mouseOver) + m_mouseOver->mouseOut(); + m_mouseOver.reset(); + hide(); + m_dismissed = true; +} + +void Pane::dismiss() { + m_dismissed = true; +} + +bool Pane::isDismissed() const { + return m_dismissed; +} + +bool Pane::isDisplayed() const { + return !m_dismissed; +} + +bool Pane::sendEvent(InputEvent const& event) { + if (m_visible) { + if (event.is<MouseButtonDownEvent>() || event.is<MouseButtonUpEvent>() || event.is<MouseMoveEvent>() + || event.is<MouseWheelEvent>()) { + Vec2I mousePos = *m_context->mousePosition(event); + // First, handle preliminary mouse out / click up events + if (m_mouseOver) { + if (!m_mouseOver->inMember(mousePos) || !m_mouseOver->active()) { + m_mouseOver->mouseOut(); + m_mouseOver.reset(); + } + } + + if (event.is<MouseButtonUpEvent>()) + m_clickDown.reset(); + + WidgetPtr newClickDown; + WidgetPtr newMouseOver; + WidgetPtr newFocusWidget; + + // Then, go through widgets in highest to lowest z-order and handle mouse + // over, focus, and capture events. + for (auto const& widget : reverseIterate(m_members)) { + if (widget->inMember(mousePos) && widget->active() && widget->interactive()) { + WidgetPtr topWidget = widget; + WidgetPtr child = getChildAt(mousePos); + if (child->active() && child->interactive()) { + if (event.is<MouseButtonDownEvent>() + && (event.get<MouseButtonDownEvent>().mouseButton == MouseButton::Left + || event.get<MouseButtonDownEvent>().mouseButton == MouseButton::Right)) { + if (!newClickDown) + newClickDown = child; + + if (!newFocusWidget) + newFocusWidget = child; + } + + if (!newMouseOver) + newMouseOver = child; + } + } + } + + if (m_clickDown != newClickDown) + m_clickDown = newClickDown; + + if (m_mouseOver != newMouseOver) { + if (m_mouseOver) + m_mouseOver->mouseOut(); + m_mouseOver = newMouseOver; + if (m_mouseOver) { + if (m_clickDown == m_mouseOver) + m_mouseOver->mouseReturnStillDown(); + else + m_mouseOver->mouseOver(); + } + } + + if (newFocusWidget && m_focusWidget != newFocusWidget) { + if (auto focusWidget = m_focusWidget) + focusWidget->blur(); + m_focusWidget = newFocusWidget; + m_focusWidget->focus(); + } + + // Finally go through widgets in highest to lowest z-order and send the + // raw event, stopping further processing if the widget consumes it. + for (auto const& widget : reverseIterate(m_members)) { + if (widget->inMember(mousePos) && widget->active() && widget->interactive()) { + if (widget->sendEvent(event)) + return true; + } + } + } + + if (event.is<MouseButtonDownEvent>()) { + Vec2I mousePos = *m_context->mousePosition(event); + if (inDragArea(mousePos) && !m_lockPosition) { + setDragActive(true, mousePos); + return true; + } + if (inWindow(mousePos)) + return true; + } + + if (m_focusWidget) { + if (m_focusWidget->sendEvent(event)) + return true; + } + } + return false; +} + +void Pane::setFocus(Widget const* focus) { + if (m_focusWidget.get() == focus) + return; + if (m_focusWidget) + m_focusWidget->blur(); + if (auto c = childPtr(focus)) + m_focusWidget = move(c); + else + throw GuiException("Cannot set focus on a widget which is not a child of this pane"); +} + +void Pane::removeFocus(Widget const* focus) { + if (m_focusWidget.get() == focus) + m_focusWidget.reset(); +} + +void Pane::removeFocus() { + m_focusWidget.reset(); +} + +Pane const* Pane::window() const { + return this; +} + +Pane* Pane::window() { + return this; +} + +void Pane::renderImpl() { + if (m_bgFooter != "") + m_context->drawInterfaceQuad(m_bgFooter, Vec2F(position())); + + if (m_bgBody != "") + m_context->drawInterfaceQuad(m_bgBody, Vec2F(position()) + Vec2F(0, m_footerSize[1])); + + if (m_bgHeader != "") { + auto headerPos = Vec2F(position()) + Vec2F(0, m_footerSize[1] + m_bodySize[1]); + m_context->drawInterfaceQuad(m_bgHeader, headerPos); + + if (m_icon) { + m_icon->setPosition(Vec2I(0, m_footerSize[1] + m_bodySize[1]) + m_iconOffset); + m_icon->render(m_drawingArea); + m_context->resetInterfaceScissorRect(); + } + + m_context->setFontSize(m_fontSize); + m_context->setFontColor(m_titleColor.toRgba()); + m_context->setFontMode(FontMode::Shadow); + m_context->renderInterfaceText(m_title, {headerPos + Vec2F(m_titleOffset)}); + m_context->setFontColor(m_subTitleColor.toRgba()); + m_context->renderInterfaceText(m_subTitle, {headerPos + Vec2F(m_subTitleOffset)}); + m_context->setFontMode(FontMode::Normal); + } +} + +void Pane::update() { + if (m_visible) { + for (auto const& widget : m_members) { + widget->update(); + if ((m_focusWidget == widget) != widget->hasFocus()) { + m_focusWidget.reset(); + widget->blur(); + } + } + } +} + +void Pane::tick() {} + +bool Pane::dragActive() const { + return m_dragActive; +} + +Vec2I Pane::dragMouseOrigin() const { + return m_dragMouseOrigin; +} + +void Pane::setDragActive(bool dragActive, Vec2I dragMouseOrigin) { + m_dragActive = dragActive; + m_dragMouseOrigin = dragMouseOrigin; +} + +void Pane::drag(Vec2I mousePosition) { + Vec2I delta = mousePosition - m_dragMouseOrigin; + setPosition(position() + delta); + m_dragMouseOrigin += delta; +} + +bool Pane::inWindow(Vec2I const& position) const { + return screenBoundRect().contains(position); +} + +bool Pane::inDragArea(Vec2I const& position) const { + return inWindow(position) && (position[1] < (this->position()[1] + m_footerSize[1]) + || position[1] > (this->position()[1] + (m_footerSize[1] + m_bodySize[1]))); +} + +Vec2I Pane::cursorRelativeToPane(Vec2I const& position) const { + return position - this->position(); +} + +Vec2I Pane::centerOffset() const { + return m_centerOffset; +} + +void Pane::setBG(BGResult const& res) { + setBG(res.header, res.body, res.footer); +} + +void Pane::setBG(String const& header, String const& body, String const& footer) { + m_bgHeader = header; + m_bgBody = body; + m_bgFooter = footer; + if (m_bgHeader != "") { + m_headerSize = Vec2I(m_context->textureSize(m_bgHeader)); + } else { + m_headerSize = {}; + } + if (m_bgBody != "") { + m_bodySize = Vec2I(m_context->textureSize(m_bgBody)); + } else { + m_bodySize = {}; + } + if (m_bgFooter != "") { + m_footerSize = Vec2I(m_context->textureSize(m_bgFooter)); + } else { + m_footerSize = {}; + } + + setSize(Vec2I(std::max(std::max(m_headerSize[0], m_bodySize[0]), m_footerSize[0]), + m_headerSize[1] + m_bodySize[1] + m_footerSize[1])); +} + +Pane::BGResult Pane::getBG() const { + return {m_bgHeader, m_bgBody, m_bgFooter}; +} + +void Pane::lockPosition() { + m_lockPosition = true; +} + +void Pane::unlockPosition() { + m_lockPosition = false; +} + +void Pane::setTitle(WidgetPtr icon, String const& title, String const& subTitle) { + m_icon = icon; + m_title = title; + m_subTitle = subTitle; + if (m_icon) { + m_icon->setParent(this); + m_icon->show(); + } +} + +void Pane::setTitleString(String const& title, String const& subTitle) { + m_title = title; + m_subTitle = subTitle; +} + +void Pane::setTitleIcon(WidgetPtr icon) { + m_icon = icon; + if (m_icon) { + m_icon->setParent(this); + m_icon->show(); + } +} + +String Pane::title() const { + return m_title; +} + +String Pane::subTitle() const { + return m_subTitle; +} + +WidgetPtr Pane::titleIcon() const { + return m_icon; +} + +PaneAnchor Pane::anchor() { + return m_anchor; +} + +void Pane::setAnchor(PaneAnchor anchor) { + m_anchor = anchor; +} + +Vec2I Pane::anchorOffset() const { + return m_anchorOffset; +} + +void Pane::setAnchorOffset(Vec2I anchorOffset) { + m_anchorOffset = anchorOffset; +} + +bool Pane::hasDisplayed() const { + return m_hasDisplayed; +} + +PanePtr Pane::createTooltip(Vec2I const&) { + return {}; +} + +Maybe<String> Pane::cursorOverride(Vec2I const&) { + return {}; +} + +} |