diff options
Diffstat (limited to 'scene/gui/popup.cpp')
-rw-r--r-- | scene/gui/popup.cpp | 128 |
1 files changed, 85 insertions, 43 deletions
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index 6edafc65a0..36bcca61a7 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "popup.h" -#include "core/engine.h" +#include "core/config/engine.h" #include "core/os/keyboard.h" #include "scene/gui/panel.h" @@ -41,64 +41,89 @@ void Popup::_input_from_window(const Ref<InputEvent> &p_event) { } } -void Popup::_parent_focused() { +void Popup::_initialize_visible_parents() { + visible_parents.clear(); - _close_pressed(); + Window *parent_window = this; + while (parent_window) { + parent_window = parent_window->get_parent_visible_window(); + if (parent_window) { + visible_parents.push_back(parent_window); + parent_window->connect("focus_entered", callable_mp(this, &Popup::_parent_focused)); + parent_window->connect("tree_exited", callable_mp(this, &Popup::_deinitialize_visible_parents)); + } + } } -void Popup::_notification(int p_what) { +void Popup::_deinitialize_visible_parents() { + for (uint32_t i = 0; i < visible_parents.size(); ++i) { + visible_parents[i]->disconnect("focus_entered", callable_mp(this, &Popup::_parent_focused)); + visible_parents[i]->disconnect("tree_exited", callable_mp(this, &Popup::_deinitialize_visible_parents)); + } + + visible_parents.clear(); +} + +void Popup::_notification(int p_what) { switch (p_what) { case NOTIFICATION_VISIBILITY_CHANGED: { if (is_visible()) { - - parent_visible = get_parent_visible_window(); - if (parent_visible) { - parent_visible->connect("focus_entered", callable_mp(this, &Popup::_parent_focused)); - } + _initialize_visible_parents(); } else { - if (parent_visible) { - parent_visible->disconnect("focus_entered", callable_mp(this, &Popup::_parent_focused)); - parent_visible = nullptr; - } - + _deinitialize_visible_parents(); emit_signal("popup_hide"); } } break; - case NOTIFICATION_EXIT_TREE: { - if (parent_visible) { - parent_visible->disconnect("focus_entered", callable_mp(this, &Popup::_parent_focused)); - parent_visible = nullptr; + case NOTIFICATION_WM_WINDOW_FOCUS_IN: { + if (has_focus()) { + popped_up = true; } } break; + case NOTIFICATION_EXIT_TREE: { + _deinitialize_visible_parents(); + } break; case NOTIFICATION_WM_CLOSE_REQUEST: { _close_pressed(); - + } break; + case NOTIFICATION_APPLICATION_FOCUS_OUT: { + _close_pressed(); } break; } } +void Popup::_parent_focused() { + if (popped_up && close_on_parent_focus) { + _close_pressed(); + } +} + void Popup::_close_pressed() { + popped_up = false; - Window *parent_window = parent_visible; - if (parent_visible) { - parent_visible->disconnect("focus_entered", callable_mp(this, &Popup::_parent_focused)); - parent_visible = nullptr; - } + _deinitialize_visible_parents(); call_deferred("hide"); emit_signal("cancelled"); - - if (parent_window) { - //parent_window->grab_focus(); - } } void Popup::set_as_minsize() { set_size(get_contents_minimum_size()); } + +void Popup::set_close_on_parent_focus(bool p_close) { + close_on_parent_focus = p_close; +} + +bool Popup::get_close_on_parent_focus() { + return close_on_parent_focus; +} + void Popup::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_close_on_parent_focus", "close"), &Popup::set_close_on_parent_focus); + ClassDB::bind_method(D_METHOD("get_close_on_parent_focus"), &Popup::get_close_on_parent_focus); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "close_on_parent_focus"), "set_close_on_parent_focus", "get_close_on_parent_focus"); ADD_SIGNAL(MethodInfo("popup_hide")); } @@ -129,13 +154,32 @@ Rect2i Popup::_popup_adjust_rect() const { current.position.y = parent.position.y; } + if (current.size.y > parent.size.y) { + current.size.y = parent.size.y; + } + + if (current.size.x > parent.size.x) { + current.size.x = parent.size.x; + } + + // Early out if max size not set. + Size2i max_size = get_max_size(); + if (max_size <= Size2()) { + return current; + } + + if (current.size.x > max_size.x) { + current.size.x = max_size.x; + } + + if (current.size.y > max_size.y) { + current.size.y = max_size.y; + } + return current; } Popup::Popup() { - - parent_visible = nullptr; - set_wrap_controls(true); set_visible(false); set_transient(true); @@ -149,18 +193,19 @@ Popup::~Popup() { } Size2 PopupPanel::_get_contents_minimum_size() const { - Ref<StyleBox> p = get_theme_stylebox("panel", get_class_name()); Size2 ms; for (int i = 0; i < get_child_count(); i++) { Control *c = Object::cast_to<Control>(get_child(i)); - if (!c || c == panel) + if (!c || c == panel) { continue; + } - if (c->is_set_as_toplevel()) + if (c->is_set_as_top_level()) { continue; + } Size2 cms = c->get_combined_minimum_size(); ms.x = MAX(cms.x, ms.x); @@ -171,7 +216,6 @@ Size2 PopupPanel::_get_contents_minimum_size() const { } void PopupPanel::_update_child_rects() { - Ref<StyleBox> p = get_theme_stylebox("panel", get_class_name()); Vector2 cpos(p->get_offset()); @@ -179,11 +223,13 @@ void PopupPanel::_update_child_rects() { for (int i = 0; i < get_child_count(); i++) { Control *c = Object::cast_to<Control>(get_child(i)); - if (!c) + if (!c) { continue; + } - if (c->is_set_as_toplevel()) + if (c->is_set_as_top_level()) { continue; + } if (c == panel) { c->set_position(Vector2()); @@ -196,21 +242,17 @@ void PopupPanel::_update_child_rects() { } void PopupPanel::_notification(int p_what) { - if (p_what == NOTIFICATION_THEME_CHANGED) { panel->add_theme_style_override("panel", get_theme_stylebox("panel", get_class_name())); } else if (p_what == NOTIFICATION_READY || p_what == NOTIFICATION_ENTER_TREE) { - panel->add_theme_style_override("panel", get_theme_stylebox("panel", get_class_name())); _update_child_rects(); } else if (p_what == NOTIFICATION_WM_SIZE_CHANGED) { - _update_child_rects(); } } PopupPanel::PopupPanel() { - panel = memnew(Panel); add_child(panel); } |