Skip to content

Commit 09c98e1

Browse files
committed
Cache the preferred size of widgets
NanoGUI potentially spends a significant amount of runtime in the functions ``nvgTextBounds()`` and ``nvgTextBoxBounds()`` that are used to compute the preferred size of widgets. This commit adopts a strategy that caches the preferred size in bottom-level widgets (i.e., ones that don't layout a set of child widgets). The main complication is that various kinds of changes (setting different captions, themes, etc.) can invalidate the precomputed preferred size, so a relatively large number of setters need touchups.
1 parent fcc29ab commit 09c98e1

32 files changed

+216
-65
lines changed

include/nanogui/button.h

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,12 @@ class NANOGUI_EXPORT Button : public Widget {
5959
std::string_view caption() const { return m_caption; }
6060

6161
/// Sets the caption of this Button.
62-
void set_caption(std::string_view caption) { m_caption = caption; }
62+
void set_caption(std::string_view caption) {
63+
if (m_caption != caption) {
64+
m_caption = caption;
65+
preferred_size_changed();
66+
}
67+
}
6368

6469
/// Returns the background color of this Button.
6570
const Color &background_color() const { return m_background_color; }
@@ -74,7 +79,12 @@ class NANOGUI_EXPORT Button : public Widget {
7479
/// Returns the icon of this Button. See \ref nanogui::Button::m_icon.
7580
int icon() const { return m_icon; }
7681
/// Sets the icon of this Button. See \ref nanogui::Button::m_icon.
77-
void set_icon(int icon) { m_icon = icon; }
82+
void set_icon(int icon) {
83+
if (m_icon != icon) {
84+
m_icon = icon;
85+
preferred_size_changed();
86+
}
87+
}
7888

7989
/// The current flags of this Button (see \ref nanogui::Button::Flags for options).
8090
int flags() const { return m_flags; }
@@ -84,7 +94,12 @@ class NANOGUI_EXPORT Button : public Widget {
8494
/// The position of the icon for this Button.
8595
IconPosition icon_position() const { return m_icon_position; }
8696
/// Sets the position of the icon for this Button.
87-
void set_icon_position(IconPosition icon_position) { m_icon_position = icon_position; }
97+
void set_icon_position(IconPosition icon_position) {
98+
if (m_icon_position != icon_position) {
99+
m_icon_position = icon_position;
100+
preferred_size_changed();
101+
}
102+
}
88103

89104
/// Whether or not this Button is currently pushed.
90105
bool pushed() const { return m_pushed; }
@@ -109,10 +124,18 @@ class NANOGUI_EXPORT Button : public Widget {
109124
/// The padding of this Button.
110125
const Vector2i &padding() const { return m_padding; }
111126
/// Set the padding of this Button.
112-
void set_padding(const Vector2i &padding) { m_padding = padding; }
127+
void set_padding(const Vector2i &padding) {
128+
if (m_padding != padding) {
129+
m_padding = padding;
130+
preferred_size_changed();
131+
}
132+
}
113133

134+
protected:
114135
/// The preferred size of this Button.
115-
virtual Vector2i preferred_size(NVGcontext *ctx) const override;
136+
virtual Vector2i preferred_size_impl(NVGcontext *ctx) const override;
137+
138+
public:
116139
/// The callback that is called when any type of mouse button event is issued to this Button.
117140
virtual bool mouse_enter_event(const Vector2i &p, bool enter) override;
118141
virtual bool mouse_button_event(const Vector2i &p, int button, bool down, int modifiers) override;

include/nanogui/checkbox.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,12 @@ class NANOGUI_EXPORT CheckBox : public Widget {
5252
std::string_view caption() const { return m_caption; }
5353

5454
/// Sets the caption of this check box
55-
void set_caption(std::string_view caption) { m_caption = caption; }
55+
void set_caption(std::string_view caption) {
56+
if (m_caption != caption) {
57+
m_caption = caption;
58+
preferred_size_changed();
59+
}
60+
}
5661

5762
/// Return whether or not this widget is currently checked.
5863
const bool &checked() const { return m_checked; }
@@ -73,8 +78,11 @@ class NANOGUI_EXPORT CheckBox : public Widget {
7378
/// Mouse button event processing for this check box
7479
virtual bool mouse_button_event(const Vector2i &p, int button, bool down, int modifiers) override;
7580

81+
protected:
7682
/// The preferred size of this CheckBox.
77-
virtual Vector2i preferred_size(NVGcontext *ctx) const override;
83+
virtual Vector2i preferred_size_impl(NVGcontext *ctx) const override;
84+
85+
public:
7886

7987
/// Draws this CheckBox.
8088
virtual void draw(NVGcontext *ctx) override;

include/nanogui/colorwheel.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ class NANOGUI_EXPORT ColorWheel : public Widget {
5050
/// Sets the current Color this ColorWheel has selected.
5151
void set_color(const Color& color);
5252

53-
/// The preferred size of this ColorWheel.
54-
virtual Vector2i preferred_size(NVGcontext *ctx) const override;
5553

5654
/// Draws the ColorWheel.
5755
virtual void draw(NVGcontext *ctx) override;
@@ -99,6 +97,9 @@ class NANOGUI_EXPORT ColorWheel : public Widget {
9997

10098
/// The current callback to execute when the color value has changed.
10199
std::function<void(const Color &)> m_callback;
100+
101+
/// The preferred size of this ColorWheel.
102+
virtual Vector2i preferred_size_impl(NVGcontext *ctx) const override;
102103
};
103104

104105
NAMESPACE_END(nanogui)

include/nanogui/graph.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ class NANOGUI_EXPORT Graph : public Widget {
5050
std::vector<float> &values() { return m_values; }
5151
void set_values(const std::vector<float> &values) { m_values = values; }
5252

53-
virtual Vector2i preferred_size(NVGcontext *ctx) const override;
5453
virtual void draw(NVGcontext *ctx) override;
5554
protected:
55+
virtual Vector2i preferred_size_impl(NVGcontext *ctx) const override;
5656
std::string m_caption, m_header, m_footer;
5757
Color m_background_color, m_fill_color, m_stroke_color, m_text_color;
5858
std::vector<float> m_values;

include/nanogui/imagepanel.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class NANOGUI_EXPORT ImagePanel : public Widget {
2828
public:
2929
ImagePanel(Widget *parent);
3030

31-
void set_images(const Images &data) { m_images = data; }
31+
void set_images(const Images &data) { m_images = data; preferred_size_changed(); }
3232
const Images& images() const { return m_images; }
3333

3434
const std::function<void(int)> &callback() const { return m_callback; }
@@ -38,10 +38,10 @@ class NANOGUI_EXPORT ImagePanel : public Widget {
3838
int modifiers) override;
3939
virtual bool mouse_button_event(const Vector2i &p, int button, bool down,
4040
int modifiers) override;
41-
virtual Vector2i preferred_size(NVGcontext *ctx) const override;
4241
virtual void draw(NVGcontext *ctx) override;
4342

4443
protected:
44+
virtual Vector2i preferred_size_impl(NVGcontext *ctx) const override;
4545
Vector2i grid_size() const;
4646
int index_for_position(const Vector2i &p) const;
4747
protected:

include/nanogui/label.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,20 @@ class NANOGUI_EXPORT Label : public Widget {
3232
/// Get the label's text caption
3333
std::string_view caption() const { return m_caption; }
3434
/// Set the label's text caption
35-
void set_caption(std::string_view caption) { m_caption = caption; }
35+
void set_caption(std::string_view caption) {
36+
if (m_caption != caption) {
37+
m_caption = caption;
38+
preferred_size_changed();
39+
}
40+
}
3641

3742
/// Set the currently active font (2 are available by default: 'sans' and 'sans-bold')
38-
void set_font(std::string_view font) { m_font = font; }
43+
void set_font(std::string_view font) {
44+
if (m_font != font) {
45+
m_font = font;
46+
preferred_size_changed();
47+
}
48+
}
3949
/// Get the currently active font
4050
std::string_view font() const { return m_font; }
4151

@@ -47,8 +57,11 @@ class NANOGUI_EXPORT Label : public Widget {
4757
/// Set the \ref Theme used to draw this widget
4858
virtual void set_theme(Theme *theme) override;
4959

60+
protected:
5061
/// Compute the size needed to fully display the label
51-
virtual Vector2i preferred_size(NVGcontext *ctx) const override;
62+
virtual Vector2i preferred_size_impl(NVGcontext *ctx) const override;
63+
64+
public:
5265

5366
/// Draw the label
5467
virtual void draw(NVGcontext *ctx) override;

include/nanogui/progressbar.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ class NANOGUI_EXPORT ProgressBar : public Widget {
2828
float value() { return m_value; }
2929
void set_value(float value) { m_value = value; }
3030

31-
virtual Vector2i preferred_size(NVGcontext *ctx) const override;
3231
virtual void draw(NVGcontext* ctx) override;
3332
protected:
33+
virtual Vector2i preferred_size_impl(NVGcontext *ctx) const override;
3434
float m_value;
3535
};
3636

include/nanogui/python.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ extern "C" {
6161
bool keyboard_character_event(unsigned int codepoint) override { \
6262
NB_OVERRIDE(keyboard_character_event, codepoint); \
6363
} \
64-
::nanogui::Vector2i preferred_size(NVGcontext *ctx) const override { \
65-
NB_OVERRIDE(preferred_size, ctx); \
64+
::nanogui::Vector2i preferred_size_impl(NVGcontext *ctx) const override { \
65+
NB_OVERRIDE(preferred_size_impl, ctx); \
6666
} \
6767
void perform_layout(NVGcontext *ctx) override { \
6868
NB_OVERRIDE(perform_layout, ctx); \

include/nanogui/slider.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ class NANOGUI_EXPORT Slider : public Widget {
4343
const std::function<void(float)> &final_callback() const { return m_final_callback; }
4444
void set_final_callback(const std::function<void(float)> &callback) { m_final_callback = callback; }
4545

46-
virtual Vector2i preferred_size(NVGcontext *ctx) const override;
46+
protected:
47+
virtual Vector2i preferred_size_impl(NVGcontext *ctx) const override;
48+
49+
public:
4750
virtual bool mouse_drag_event(const Vector2i &p, const Vector2i &rel, int button, int modifiers) override;
4851
virtual bool mouse_button_event(const Vector2i &p, int button, bool down, int modifiers) override;
4952
virtual void draw(NVGcontext* ctx) override;

include/nanogui/tabwidget.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,19 +60,19 @@ class NANOGUI_EXPORT TabWidgetBase : public Widget {
6060
/// Return the caption of the tab with the given ID
6161
const std::string& tab_caption(int id) const { return m_tab_captions[tab_index(id)]; }
6262
/// Change the caption of the tab with the given ID
63-
void set_tab_caption(int id, std::string_view caption) { m_tab_captions[tab_index(id)] = caption; }
63+
void set_tab_caption(int id, std::string_view caption) { m_tab_captions[tab_index(id)] = caption; preferred_size_changed(); }
6464

6565
/// Return whether tabs provide a close button
6666
bool tabs_closeable() const { return m_tabs_closeable; }
67-
void set_tabs_closeable(bool value) { m_tabs_closeable = value; }
67+
void set_tabs_closeable(bool value) { m_tabs_closeable = value; preferred_size_changed(); }
6868

6969
/// Return whether tabs can be dragged to different positions
7070
bool tabs_draggable() const { return m_tabs_draggable; }
7171
void set_tabs_draggable(bool value) { m_tabs_draggable = value; }
7272

7373
/// Return the padding between the tab widget boundary and child widgets
7474
int padding() const { return m_padding; }
75-
void set_padding(int value) { m_padding = value; }
75+
void set_padding(int value) { m_padding = value; preferred_size_changed(); }
7676

7777
/// Set the widget's background color (a global property)
7878
void set_background_color(const Color &background_color) {
@@ -101,7 +101,6 @@ class NANOGUI_EXPORT TabWidgetBase : public Widget {
101101

102102
// Widget implementation
103103
virtual void perform_layout(NVGcontext* ctx) override;
104-
virtual Vector2i preferred_size(NVGcontext* ctx) const override;
105104
virtual void draw(NVGcontext* ctx) override;
106105
virtual bool mouse_button_event(const Vector2i &p, int button, bool down,
107106
int modifiers) override;
@@ -110,6 +109,7 @@ class NANOGUI_EXPORT TabWidgetBase : public Widget {
110109
int modifiers) override;
111110

112111
protected:
112+
virtual Vector2i preferred_size_impl(NVGcontext* ctx) const override;
113113
std::pair<int, bool> tab_at_position(const Vector2i &p,
114114
bool test_vertical = true) const;
115115
virtual void update_visibility();
@@ -198,8 +198,8 @@ class NANOGUI_EXPORT TabWidget : public TabWidgetBase {
198198
void set_remove_children(bool value) { m_remove_children = value; }
199199

200200
virtual void perform_layout(NVGcontext* ctx) override;
201-
virtual Vector2i preferred_size(NVGcontext* ctx) const override;
202201
protected:
202+
virtual Vector2i preferred_size_impl(NVGcontext* ctx) const override;
203203
virtual void update_visibility() override;
204204
protected:
205205
std::vector<std::pair<int, Widget *>> m_widgets;

0 commit comments

Comments
 (0)