// ---------------------------------------------------------------------------- // - Open3D: www.open3d.org - // ---------------------------------------------------------------------------- // Copyright (c) 2018-2023 www.open3d.org // SPDX-License-Identifier: MIT // ---------------------------------------------------------------------------- #pragma once #include "open3d/visualization/gui/Widget.h" namespace open3d { namespace visualization { namespace gui { struct Margins { int left; int top; int right; int bottom; /// Margins are specified in pixels, which are not the same size on all /// monitors. It is best to use a multiple of /// Window::GetTheme().fontSize to specify margins. Theme::fontSize, /// represents 1em and is scaled according to the scaling factor of the /// window. For example, 0.5em (that is, 0.5 * theme.fontSize) is typically /// a good size for a margin. Margins(); // all values zero Margins(int px); Margins(int horiz_px, int vert_px); Margins(int left_px, int top_px, int right_px, int bottom_px); /// Convenience function that returns left + right int GetHoriz() const; /// Convenience function that returns top + bottom int GetVert() const; }; /// Lays out widgets either horizontally or vertically. /// Base class for Vert and Horiz. class Layout1D : public Widget { using Super = Widget; public: enum Dir { VERT, HORIZ }; static void debug_PrintPreferredSizes(Layout1D* layout, const LayoutContext& context, const Constraints& constraints, int depth = 0); /// Spacing is in pixels; see the comment in Margin(). 1em is typically /// a good value for spacing. Layout1D(Dir dir, int spacing, const Margins& margins, const std::vector>& children); virtual ~Layout1D(); int GetSpacing() const; const Margins& GetMargins() const; /// Sets spacing. Need to signal a relayout after calling (unless it is /// before a layout that will happen, such as before adding as a child). void SetSpacing(int spacing); /// Sets margins. Need to signal a relayout after calling (unless it is /// before a layout that will happen, such as before adding as a child). void SetMargins(const Margins& margins); Size CalcPreferredSize(const LayoutContext& context, const Constraints& constraints) const override; void Layout(const LayoutContext& context) override; /// Adds a fixed number of pixels after the previously added widget. void AddFixed(int size); /// Adds a virtual widget that takes up as much space as possible. /// This is useful for centering widgets: { stretch, w1, w2, stretch } /// or for aligning widgets to one side or the other: /// { stretch, ok, cancel }. void AddStretch(); public: class Fixed : public Widget { public: Fixed(int size, Dir dir); Size CalcPreferredSize(const LayoutContext& context, const Constraints& constraints) const override; private: int size_; Dir dir_; }; class Stretch : public Widget { Size CalcPreferredSize(const LayoutContext& context, const Constraints& constraints) const override; }; protected: int GetMinorAxisPreferredSize() const; void SetMinorAxisPreferredSize(int size); Margins& GetMutableMargins(); std::vector> GetVisibleChildren() const; private: struct Impl; std::unique_ptr impl_; }; /// Lays out widgets vertically. class Vert : public Layout1D { public: static std::shared_ptr MakeFixed(int size); static std::shared_ptr MakeStretch(); Vert(); /// Spacing is in pixels; see the comment in Margin(). 1em is typically /// a good value for spacing. Vert(int spacing, const Margins& margins = Margins()); Vert(int spacing, const Margins& margins, const std::vector>& children); virtual ~Vert(); int GetPreferredWidth() const; void SetPreferredWidth(int w); }; /// This is a vertical layout with a twisty + title that can be clicked on /// to expand or collapse the layout. Collapsing the layout will hide all /// the items and shrink the size of the layout to the height of the title. class CollapsableVert : public Vert { using Super = Vert; public: CollapsableVert(const char* text); CollapsableVert(const char* text, int spacing, const Margins& margins = Margins()); virtual ~CollapsableVert(); /// You will need to call Window::SetNeedsLayout() after this. /// (If you call this before the widnows is displayed everything /// will work out fine, as layout will automatically be called when /// the window is shown.) void SetIsOpen(bool is_open); /// Returns true if open and false if collapsed. bool GetIsOpen(); FontId GetFontId() const; void SetFontId(FontId font_id); Size CalcPreferredSize(const LayoutContext& context, const Constraints& constraints) const override; void Layout(const LayoutContext& context) override; Widget::DrawResult Draw(const DrawContext& context) override; private: struct Impl; std::unique_ptr impl_; }; /// This a vertical layout that scrolls if it is smaller than its contents class ScrollableVert : public Vert { using Super = Vert; public: ScrollableVert(); ScrollableVert(int spacing, const Margins& margins = Margins()); ScrollableVert(int spacing, const Margins& margins, const std::vector>& children); virtual ~ScrollableVert(); Widget::DrawResult Draw(const DrawContext& context) override; private: struct Impl; std::unique_ptr impl_; }; /// Lays out widgets horizontally. class Horiz : public Layout1D { public: static std::shared_ptr MakeFixed(int size); static std::shared_ptr MakeStretch(); static std::shared_ptr MakeCentered(std::shared_ptr w); Horiz(); /// Spacing is in pixels; see the comment in Margin(). 1em is typically /// a good value for spacing. Horiz(int spacing, const Margins& margins = Margins()); Horiz(int spacing, const Margins& margins, const std::vector>& children); ~Horiz(); int GetPreferredHeight() const; void SetPreferredHeight(int h); }; /// Lays out widgets in a grid. The widgets are assigned to the next /// horizontal column, and when all the columns in a row are used, a new /// row will be created. class VGrid : public Widget { using Super = Widget; public: VGrid(int num_cols, int spacing = 0, const Margins& margins = Margins()); virtual ~VGrid(); int GetSpacing() const; const Margins& GetMargins() const; int GetPreferredWidth() const; void SetPreferredWidth(int w); Size CalcPreferredSize(const LayoutContext& context, const Constraints& constraints) const override; void Layout(const LayoutContext& context) override; private: struct Impl; std::unique_ptr impl_; }; } // namespace gui } // namespace visualization } // namespace open3d