diff --git a/include/nanogui/screen.h b/include/nanogui/screen.h index d2e044f4..63e511a2 100644 --- a/include/nanogui/screen.h +++ b/include/nanogui/screen.h @@ -267,7 +267,7 @@ class NANOGUI_EXPORT Screen : public Widget { /* Internal helper functions */ void update_focus(Widget *widget); - void dispose_window(Window *window); + void dispose_widget(Widget *widget); void center_window(Window *window); void move_window_to_front(Window *window); void draw_widgets(); diff --git a/include/nanogui/widget.h b/include/nanogui/widget.h index cc2a5caf..1bd5b2dd 100644 --- a/include/nanogui/widget.h +++ b/include/nanogui/widget.h @@ -208,6 +208,18 @@ class NANOGUI_EXPORT Widget : public Object { */ void set_icon_extra_scale(float scale) { m_icon_extra_scale = scale; } + /** + * The amount of extra scaling applied to *icon* fonts. + * See \ref nanogui::Widget::mIconExtraScale. + */ + float iconExtraScale() const { return mIconExtraScale; } + + /** + * Sets the amount of extra scaling applied to *icon* fonts. + * See \ref nanogui::Widget::mIconExtraScale. + */ + void setIconExtraScale(float scale) { mIconExtraScale = scale; } + /// Return a pointer to the cursor of the widget Cursor cursor() const { return m_cursor; } /// Set the cursor of the widget @@ -270,6 +282,13 @@ class NANOGUI_EXPORT Widget : public Object { */ float icon_scale() const { return m_theme->m_icon_scale * m_icon_extra_scale; } +private: + /** + * Convenience function to share logic between both signatures of + * ``removeChild``. + */ + void removeChildHelper(const std::vector::iterator& child_it); + protected: Widget *m_parent; ref m_theme; diff --git a/src/screen.cpp b/src/screen.cpp index 4b04e75c..0ae28b4e 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -915,12 +915,19 @@ void Screen::update_focus(Widget *widget) { move_window_to_front((Window *) window); } -void Screen::dispose_window(Window *window) { - if (std::find(m_focus_path.begin(), m_focus_path.end(), window) != m_focus_path.end()) - m_focus_path.clear(); - if (m_drag_widget == window) - m_drag_widget = nullptr; - remove_child(window); +void Screen::dispose_widget(Widget *widget) { + if (std::find(mFocusPath.begin(), mFocusPath.end(), widget) != mFocusPath.end()) + mFocusPath.clear(); + + if (mDragWidget == widget) { + mDragWidget = nullptr; + mDragActive = false; + } + + for (auto child : widget->children()) + disposeWidget(child); + + remove_child(widget); } void Screen::center_window(Window *window) { diff --git a/src/widget.cpp b/src/widget.cpp index 83f06ee7..3a0b76db 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -177,20 +177,24 @@ void Widget::add_child(Widget * widget) { } void Widget::remove_child(const Widget *widget) { - size_t child_count = m_children.size(); - m_children.erase(std::remove(m_children.begin(), m_children.end(), widget), - m_children.end()); - if (m_children.size() == child_count) - throw std::runtime_error("Widget::remove_child(): widget not found!"); - widget->dec_ref(); + removeChildHelper(std::find(m_children.begin(), m_children.end(), widget)); } void Widget::remove_child_at(int index) { - if (index < 0 || index >= (int) m_children.size()) - throw std::runtime_error("Widget::remove_child_at(): out of bounds!"); - Widget *widget = m_children[index]; - m_children.erase(m_children.begin() + index); - widget->dec_ref(); + assert(index >= 0); + assert(index < child_count); + removeChildHelper(m_children.begin() + index); +} + +void Widget::removeChildHelper(const std::vector::iterator& child_it) { + if (child_it == m_children.end()) + return; + Widget *widget = *child_it; + + screen()->disposeWidget(widget); + m_children.erase(child_it); + + widget->decRef(); } int Widget::child_index(Widget *widget) const { @@ -216,7 +220,8 @@ Screen *Widget::screen() { Widget *widget = this; while (true) { if (!widget) - return nullptr; + throw std::runtime_error( + "Widget:internal error (could not find parent screen)"); Screen *screen = dynamic_cast(widget); if (screen) return screen; diff --git a/src/window.cpp b/src/window.cpp index 3fcbf26f..1eb1acde 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -147,7 +147,7 @@ void Window::dispose() { Widget *widget = this; while (widget->parent()) widget = widget->parent(); - ((Screen *) widget)->dispose_window(this); + ((Screen *) widget)->remove_child(this); } void Window::center() {