diff --git a/include/widget/Widget.hpp b/include/widget/Widget.hpp index 0e5a37ef..bd631f00 100644 --- a/include/widget/Widget.hpp +++ b/include/widget/Widget.hpp @@ -50,14 +50,27 @@ struct Widget { void requestDelete(); + /** Returns the smallest rectangle containing this widget's children (visible and invisible) in its local coordinates. + Returns `Rect(Vec(inf, inf), Vec(-inf, -inf))` if there are no children. + */ virtual math::Rect getChildrenBoundingBox(); - /** Returns `v` transformed into the coordinate system of `relative` */ + /** Returns `v` (given in local coordinates) transformed into the coordinate system of `relative`. + */ virtual math::Vec getRelativeOffset(math::Vec v, Widget* relative); - /** Returns `v` transformed into world coordinates */ + /** Returns `v` transformed into world/root/global/absolute coordinates. + */ math::Vec getAbsoluteOffset(math::Vec v) { return getRelativeOffset(v, NULL); } - /** Returns a subset of the given math::Rect bounded by the box of this widget and all ancestors */ + /** Returns the zoom level in the coordinate system of `relative`. + Only `ZoomWidget` should override this to return value other than 1. + */ + virtual float getRelativeZoom(Widget* relative); + float getAbsoluteZoom() { + return getRelativeZoom(NULL); + } + /** Returns a subset of the given Rect bounded by the box of this widget and all ancestors. + */ virtual math::Rect getViewport(math::Rect r); template diff --git a/include/widget/ZoomWidget.hpp b/include/widget/ZoomWidget.hpp index ee3f5cfc..167b54cd 100644 --- a/include/widget/ZoomWidget.hpp +++ b/include/widget/ZoomWidget.hpp @@ -11,6 +11,7 @@ struct ZoomWidget : Widget { float zoom = 1.f; math::Vec getRelativeOffset(math::Vec v, Widget* relative) override; + float getRelativeZoom(Widget* relative) override; math::Rect getViewport(math::Rect r) override; void setZoom(float zoom); float getZoom() { diff --git a/src/widget/Widget.cpp b/src/widget/Widget.cpp index 35d4f089..2c053379 100644 --- a/src/widget/Widget.cpp +++ b/src/widget/Widget.cpp @@ -87,8 +87,6 @@ math::Rect Widget::getChildrenBoundingBox() { math::Vec min = math::Vec(INFINITY, INFINITY); math::Vec max = math::Vec(-INFINITY, -INFINITY); for (Widget* child : children) { - if (!child->visible) - continue; min = min.min(child->box.getTopLeft()); max = max.max(child->box.getBottomRight()); } @@ -97,14 +95,22 @@ math::Rect Widget::getChildrenBoundingBox() { math::Vec Widget::getRelativeOffset(math::Vec v, Widget* relative) { - if (this == relative) { + if (this == relative) return v; - } + // Translate offset v = v.plus(box.pos); - if (parent) { - v = parent->getRelativeOffset(v, relative); - } - return v; + if (!parent) + return v; + return parent->getRelativeOffset(v, relative); +} + + +float Widget::getRelativeZoom(Widget* relative) { + if (this == relative) + return 1.f; + if (!parent) + return 1.f; + return parent->getRelativeZoom(relative); } diff --git a/src/widget/ZoomWidget.cpp b/src/widget/ZoomWidget.cpp index c4ffca85..d608d278 100644 --- a/src/widget/ZoomWidget.cpp +++ b/src/widget/ZoomWidget.cpp @@ -6,9 +6,17 @@ namespace widget { math::Vec ZoomWidget::getRelativeOffset(math::Vec v, Widget* relative) { - return Widget::getRelativeOffset(v.mult(zoom), relative); + // Transform `v` (which is in child coordinates) to local coordinates. + v = v.mult(zoom); + return Widget::getRelativeOffset(v, relative); } + +float ZoomWidget::getRelativeZoom(Widget* relative) { + return zoom * Widget::getRelativeZoom(relative); +} + + math::Rect ZoomWidget::getViewport(math::Rect r) { r.pos = r.pos.mult(zoom); r.size = r.size.mult(zoom); @@ -18,6 +26,7 @@ math::Rect ZoomWidget::getViewport(math::Rect r) { return r; } + void ZoomWidget::setZoom(float zoom) { if (zoom == this->zoom) return; @@ -30,6 +39,7 @@ void ZoomWidget::setZoom(float zoom) { Widget::onDirty(eDirty); } + void ZoomWidget::draw(const DrawArgs& args) { DrawArgs zoomCtx = args; zoomCtx.clipBox.pos = zoomCtx.clipBox.pos.div(zoom);