diff --git a/include/widget/Widget.hpp b/include/widget/Widget.hpp index 76a55ca8..42e08c5b 100644 --- a/include/widget/Widget.hpp +++ b/include/widget/Widget.hpp @@ -55,6 +55,7 @@ struct Widget : WeakBase { Returns `Rect(Vec(inf, inf), Vec(-inf, -inf))` if there are no children. */ virtual math::Rect getChildrenBoundingBox(); + virtual math::Rect getVisibleChildrenBoundingBox(); /** Returns `v` (given in local coordinates) transformed into the coordinate system of `relative`. */ virtual math::Vec getRelativeOffset(math::Vec v, Widget* relative); diff --git a/src/ui/ScrollWidget.cpp b/src/ui/ScrollWidget.cpp index f3f7a908..3868f470 100644 --- a/src/ui/ScrollWidget.cpp +++ b/src/ui/ScrollWidget.cpp @@ -60,7 +60,7 @@ void ScrollWidget::step() { Widget::step(); // Set containerBox cache - containerBox = container->getChildrenBoundingBox(); + containerBox = container->getVisibleChildrenBoundingBox(); // Clamp scroll offset math::Rect offsetBounds = getContainerOffsetBound(); @@ -93,6 +93,11 @@ void ScrollWidget::onButton(const event::Button& e) { if (e.isConsumed()) return; + // Check if scrollable + math::Rect offsetBound = getContainerOffsetBound(); + if (offsetBound.size.x <= 0.f && offsetBound.size.y <= 0.f) + return; + if (e.button == GLFW_MOUSE_BUTTON_MIDDLE) { e.consume(this); } @@ -100,6 +105,11 @@ void ScrollWidget::onButton(const event::Button& e) { void ScrollWidget::onDragStart(const event::DragStart& e) { + // Check if scrollable + math::Rect offsetBound = getContainerOffsetBound(); + if (offsetBound.size.x <= 0.f && offsetBound.size.y <= 0.f) + return; + if (e.button == GLFW_MOUSE_BUTTON_LEFT || e.button == GLFW_MOUSE_BUTTON_MIDDLE) { e.consume(this); } @@ -119,6 +129,11 @@ void ScrollWidget::onHoverScroll(const event::HoverScroll& e) { if (e.isConsumed()) return; + // Check if scrollable + math::Rect offsetBound = getContainerOffsetBound(); + if (offsetBound.size.x <= 0.f && offsetBound.size.y <= 0.f) + return; + math::Vec scrollDelta = e.scrollDelta; // Flip coordinates if shift is held // Mac (or GLFW?) already does this for us. @@ -137,6 +152,11 @@ void ScrollWidget::onHoverKey(const event::HoverKey& e) { if (e.isConsumed()) return; + // Check if scrollable + math::Rect offsetBound = getContainerOffsetBound(); + if (offsetBound.size.x <= 0.f && offsetBound.size.y <= 0.f) + return; + if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { if (e.key == GLFW_KEY_PAGE_UP && (e.mods & RACK_MOD_MASK) == 0) { offset.y -= box.size.y * 0.5; @@ -155,22 +175,22 @@ void ScrollWidget::onHoverKey(const event::HoverKey& e) { e.consume(this); } if (e.key == GLFW_KEY_HOME && (e.mods & RACK_MOD_MASK) == 0) { - math::Rect containerBox = container->getChildrenBoundingBox(); + math::Rect containerBox = container->getVisibleChildrenBoundingBox(); offset.y = containerBox.getTop(); e.consume(this); } if (e.key == GLFW_KEY_HOME && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) { - math::Rect containerBox = container->getChildrenBoundingBox(); + math::Rect containerBox = container->getVisibleChildrenBoundingBox(); offset.x = containerBox.getLeft(); e.consume(this); } if (e.key == GLFW_KEY_END && (e.mods & RACK_MOD_MASK) == 0) { - math::Rect containerBox = container->getChildrenBoundingBox(); + math::Rect containerBox = container->getVisibleChildrenBoundingBox(); offset.y = containerBox.getBottom(); e.consume(this); } if (e.key == GLFW_KEY_END && (e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) { - math::Rect containerBox = container->getChildrenBoundingBox(); + math::Rect containerBox = container->getVisibleChildrenBoundingBox(); offset.x = containerBox.getRight(); e.consume(this); } diff --git a/src/widget/FramebufferWidget.cpp b/src/widget/FramebufferWidget.cpp index 7f207775..0ef6859d 100644 --- a/src/widget/FramebufferWidget.cpp +++ b/src/widget/FramebufferWidget.cpp @@ -77,7 +77,7 @@ void FramebufferWidget::step() { localBox = box.zeroPos(); } else { - localBox = getChildrenBoundingBox(); + localBox = getVisibleChildrenBoundingBox(); } // DEBUG("rendering FramebufferWidget localBox (%g %g %g %g) fbOffset (%g %g) fbScale (%g %g)", RECT_ARGS(localBox), VEC_ARGS(internal->fbOffsetF), VEC_ARGS(internal->fbScale)); diff --git a/src/widget/Widget.cpp b/src/widget/Widget.cpp index 2c053379..270b863f 100644 --- a/src/widget/Widget.cpp +++ b/src/widget/Widget.cpp @@ -94,6 +94,19 @@ math::Rect Widget::getChildrenBoundingBox() { } +math::Rect Widget::getVisibleChildrenBoundingBox() { + math::Vec min = math::Vec(INFINITY, INFINITY); + math::Vec max = math::Vec(-INFINITY, -INFINITY); + for (Widget* child : children) { + if (!child->isVisible()) + continue; + min = min.min(child->box.getTopLeft()); + max = max.max(child->box.getBottomRight()); + } + return math::Rect::fromMinMax(min, max); +} + + math::Vec Widget::getRelativeOffset(math::Vec v, Widget* relative) { if (this == relative) return v;