Working multiple window support, including editor
This commit is contained in:
committed by
Juan Linietsky
parent
f51fdc6eef
commit
4758057f20
@ -348,6 +348,9 @@ bool CanvasItem::is_visible_in_tree() const {
|
||||
while (p) {
|
||||
if (!p->visible)
|
||||
return false;
|
||||
if (p->window && !p->window->is_visible()) {
|
||||
return false;
|
||||
}
|
||||
p = p->get_parent_item();
|
||||
}
|
||||
|
||||
@ -549,10 +552,30 @@ void CanvasItem::_notification(int p_what) {
|
||||
_update_texture_repeat_changed(false);
|
||||
|
||||
first_draw = true;
|
||||
if (get_parent()) {
|
||||
CanvasItem *ci = Object::cast_to<CanvasItem>(get_parent());
|
||||
Node *parent = get_parent();
|
||||
if (parent) {
|
||||
CanvasItem *ci = Object::cast_to<CanvasItem>(parent);
|
||||
if (ci)
|
||||
C = ci->children_items.push_back(this);
|
||||
if (!ci) {
|
||||
//look for a window
|
||||
Viewport *viewport = nullptr;
|
||||
|
||||
while (parent) {
|
||||
viewport = Object::cast_to<Viewport>(parent);
|
||||
if (viewport) {
|
||||
break;
|
||||
}
|
||||
parent = parent->get_parent();
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
window = Object::cast_to<Window>(viewport);
|
||||
if (window) {
|
||||
window->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed));
|
||||
}
|
||||
}
|
||||
}
|
||||
_enter_canvas();
|
||||
if (!block_transform_notify && !xform_change.in_list()) {
|
||||
@ -581,6 +604,9 @@ void CanvasItem::_notification(int p_what) {
|
||||
Object::cast_to<CanvasItem>(get_parent())->children_items.erase(C);
|
||||
C = NULL;
|
||||
}
|
||||
if (window) {
|
||||
window->disconnect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed));
|
||||
}
|
||||
global_invalid = true;
|
||||
} break;
|
||||
case NOTIFICATION_DRAW:
|
||||
@ -601,6 +627,14 @@ void CanvasItem::set_visible(bool p_visible) {
|
||||
else
|
||||
hide();
|
||||
}
|
||||
|
||||
void CanvasItem::_window_visibility_changed() {
|
||||
|
||||
if (visible) {
|
||||
_propagate_visibility_changed(window->is_visible());
|
||||
}
|
||||
}
|
||||
|
||||
bool CanvasItem::is_visible() const {
|
||||
|
||||
return visible;
|
||||
@ -1409,6 +1443,7 @@ CanvasItem::TextureRepeat CanvasItem::get_texture_repeat() const {
|
||||
CanvasItem::CanvasItem() :
|
||||
xform_change(this) {
|
||||
|
||||
window = nullptr;
|
||||
canvas_item = VisualServer::get_singleton()->canvas_item_create();
|
||||
visible = true;
|
||||
pending_update = false;
|
||||
|
||||
@ -201,6 +201,7 @@ private:
|
||||
|
||||
int light_mask;
|
||||
|
||||
Window *window;
|
||||
bool first_draw;
|
||||
bool visible;
|
||||
bool pending_update;
|
||||
@ -232,6 +233,8 @@ private:
|
||||
void _enter_canvas();
|
||||
void _exit_canvas();
|
||||
|
||||
void _window_visibility_changed();
|
||||
|
||||
void _notify_transform(CanvasItem *p_node);
|
||||
|
||||
void _set_on_top(bool p_on_top) { set_draw_behind_parent(!p_on_top); }
|
||||
|
||||
@ -438,22 +438,30 @@ void Control::_resize(const Size2 &p_size) {
|
||||
void Control::add_child_notify(Node *p_child) {
|
||||
|
||||
Control *child_c = Object::cast_to<Control>(p_child);
|
||||
if (!child_c)
|
||||
return;
|
||||
|
||||
if (child_c->data.theme.is_null() && data.theme_owner) {
|
||||
_propagate_theme_changed(child_c, data.theme_owner); //need to propagate here, since many controls may require setting up stuff
|
||||
if (child_c && child_c->data.theme.is_null() && (data.theme_owner || data.theme_owner_window)) {
|
||||
_propagate_theme_changed(child_c, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff
|
||||
}
|
||||
|
||||
Window *child_w = Object::cast_to<Window>(p_child);
|
||||
|
||||
if (child_w && child_w->theme.is_null() && (data.theme_owner || data.theme_owner_window)) {
|
||||
_propagate_theme_changed(child_w, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff
|
||||
}
|
||||
}
|
||||
|
||||
void Control::remove_child_notify(Node *p_child) {
|
||||
|
||||
Control *child_c = Object::cast_to<Control>(p_child);
|
||||
if (!child_c)
|
||||
return;
|
||||
|
||||
if (child_c->data.theme_owner && child_c->data.theme.is_null()) {
|
||||
_propagate_theme_changed(child_c, NULL);
|
||||
if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) {
|
||||
_propagate_theme_changed(child_c, NULL, NULL);
|
||||
}
|
||||
|
||||
Window *child_w = Object::cast_to<Window>(p_child);
|
||||
|
||||
if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) {
|
||||
_propagate_theme_changed(child_w, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -808,6 +816,97 @@ Size2 Control::get_minimum_size() const {
|
||||
return Size2();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool Control::_find_theme_item(T &r_ret, T (Theme::*get_func)(const StringName &, const StringName &) const, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_type) const {
|
||||
|
||||
// try with custom themes
|
||||
Control *theme_owner = data.theme_owner;
|
||||
Window *theme_owner_window = data.theme_owner_window;
|
||||
|
||||
while (theme_owner || theme_owner_window) {
|
||||
|
||||
StringName class_name = p_type;
|
||||
|
||||
while (class_name != StringName()) {
|
||||
if (theme_owner && (theme_owner->data.theme.operator->()->*has_func)(p_name, class_name)) {
|
||||
r_ret = (theme_owner->data.theme.operator->()->*get_func)(p_name, class_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (theme_owner_window && (theme_owner_window->theme.operator->()->*has_func)(p_name, class_name)) {
|
||||
r_ret = (theme_owner_window->theme.operator->()->*get_func)(p_name, class_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
class_name = ClassDB::get_parent_class_nocheck(class_name);
|
||||
}
|
||||
|
||||
Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent();
|
||||
|
||||
Control *parent_c = Object::cast_to<Control>(parent);
|
||||
|
||||
if (parent_c) {
|
||||
theme_owner = parent_c->data.theme_owner;
|
||||
theme_owner_window = parent_c->data.theme_owner_window;
|
||||
} else {
|
||||
Window *parent_w = Object::cast_to<Window>(parent);
|
||||
if (parent_w) {
|
||||
theme_owner = parent_w->theme_owner;
|
||||
theme_owner_window = parent_w->theme_owner_window;
|
||||
} else {
|
||||
|
||||
theme_owner = NULL;
|
||||
theme_owner_window = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Control::_has_theme_item(bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_type) const {
|
||||
|
||||
// try with custom themes
|
||||
Control *theme_owner = data.theme_owner;
|
||||
Window *theme_owner_window = data.theme_owner_window;
|
||||
|
||||
while (theme_owner || theme_owner_window) {
|
||||
|
||||
StringName class_name = p_type;
|
||||
|
||||
while (class_name != StringName()) {
|
||||
if (theme_owner && (theme_owner->data.theme.operator->()->*has_func)(p_name, class_name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (theme_owner_window && (theme_owner_window->theme.operator->()->*has_func)(p_name, class_name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
class_name = ClassDB::get_parent_class_nocheck(class_name);
|
||||
}
|
||||
|
||||
Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent();
|
||||
|
||||
Control *parent_c = Object::cast_to<Control>(parent);
|
||||
|
||||
if (parent_c) {
|
||||
theme_owner = parent_c->data.theme_owner;
|
||||
theme_owner_window = parent_c->data.theme_owner_window;
|
||||
} else {
|
||||
Window *parent_w = Object::cast_to<Window>(parent);
|
||||
if (parent_w) {
|
||||
theme_owner = parent_w->theme_owner;
|
||||
theme_owner_window = parent_w->theme_owner_window;
|
||||
} else {
|
||||
|
||||
theme_owner = NULL;
|
||||
theme_owner_window = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Ref<Texture2D> Control::get_icon(const StringName &p_name, const StringName &p_type) const {
|
||||
|
||||
if (p_type == StringName() || p_type == get_class_name()) {
|
||||
@ -819,27 +918,10 @@ Ref<Texture2D> Control::get_icon(const StringName &p_name, const StringName &p_t
|
||||
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
|
||||
// try with custom themes
|
||||
Control *theme_owner = data.theme_owner;
|
||||
Ref<Texture2D> icon;
|
||||
|
||||
while (theme_owner) {
|
||||
|
||||
StringName class_name = type;
|
||||
|
||||
while (class_name != StringName()) {
|
||||
if (theme_owner->data.theme->has_icon(p_name, class_name)) {
|
||||
return theme_owner->data.theme->get_icon(p_name, class_name);
|
||||
}
|
||||
|
||||
class_name = ClassDB::get_parent_class_nocheck(class_name);
|
||||
}
|
||||
|
||||
Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
|
||||
|
||||
if (parent)
|
||||
theme_owner = parent->data.theme_owner;
|
||||
else
|
||||
theme_owner = NULL;
|
||||
if (_find_theme_item(icon, &Theme::get_icon, &Theme::has_icon, p_name, type)) {
|
||||
return icon;
|
||||
}
|
||||
|
||||
if (Theme::get_project_default().is_valid()) {
|
||||
@ -861,27 +943,10 @@ Ref<Shader> Control::get_shader(const StringName &p_name, const StringName &p_ty
|
||||
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
|
||||
// try with custom themes
|
||||
Control *theme_owner = data.theme_owner;
|
||||
Ref<Shader> shader;
|
||||
|
||||
while (theme_owner) {
|
||||
|
||||
StringName class_name = type;
|
||||
|
||||
while (class_name != StringName()) {
|
||||
if (theme_owner->data.theme->has_shader(p_name, class_name)) {
|
||||
return theme_owner->data.theme->get_shader(p_name, class_name);
|
||||
}
|
||||
|
||||
class_name = ClassDB::get_parent_class_nocheck(class_name);
|
||||
}
|
||||
|
||||
Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
|
||||
|
||||
if (parent)
|
||||
theme_owner = parent->data.theme_owner;
|
||||
else
|
||||
theme_owner = NULL;
|
||||
if (_find_theme_item(shader, &Theme::get_shader, &Theme::has_shader, p_name, type)) {
|
||||
return shader;
|
||||
}
|
||||
|
||||
if (Theme::get_project_default().is_valid()) {
|
||||
@ -903,40 +968,18 @@ Ref<StyleBox> Control::get_stylebox(const StringName &p_name, const StringName &
|
||||
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
|
||||
// try with custom themes
|
||||
Control *theme_owner = data.theme_owner;
|
||||
Ref<StyleBox> stylebox;
|
||||
|
||||
StringName class_name = type;
|
||||
|
||||
while (theme_owner) {
|
||||
|
||||
while (class_name != StringName()) {
|
||||
if (theme_owner->data.theme->has_stylebox(p_name, class_name)) {
|
||||
return theme_owner->data.theme->get_stylebox(p_name, class_name);
|
||||
}
|
||||
|
||||
class_name = ClassDB::get_parent_class_nocheck(class_name);
|
||||
}
|
||||
|
||||
class_name = type;
|
||||
|
||||
Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
|
||||
|
||||
if (parent)
|
||||
theme_owner = parent->data.theme_owner;
|
||||
else
|
||||
theme_owner = NULL;
|
||||
if (_find_theme_item(stylebox, &Theme::get_stylebox, &Theme::has_stylebox, p_name, type)) {
|
||||
return stylebox;
|
||||
}
|
||||
|
||||
while (class_name != StringName()) {
|
||||
if (Theme::get_project_default().is_valid() && Theme::get_project_default()->has_stylebox(p_name, type))
|
||||
if (Theme::get_project_default().is_valid()) {
|
||||
if (Theme::get_project_default()->has_stylebox(p_name, type)) {
|
||||
return Theme::get_project_default()->get_stylebox(p_name, type);
|
||||
|
||||
if (Theme::get_default()->has_stylebox(p_name, class_name))
|
||||
return Theme::get_default()->get_stylebox(p_name, class_name);
|
||||
|
||||
class_name = ClassDB::get_parent_class_nocheck(class_name);
|
||||
}
|
||||
}
|
||||
|
||||
return Theme::get_default()->get_stylebox(p_name, type);
|
||||
}
|
||||
Ref<Font> Control::get_font(const StringName &p_name, const StringName &p_type) const {
|
||||
@ -949,29 +992,16 @@ Ref<Font> Control::get_font(const StringName &p_name, const StringName &p_type)
|
||||
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
|
||||
// try with custom themes
|
||||
Control *theme_owner = data.theme_owner;
|
||||
Ref<Font> font;
|
||||
|
||||
while (theme_owner) {
|
||||
if (_find_theme_item(font, &Theme::get_font, &Theme::has_font, p_name, type)) {
|
||||
return font;
|
||||
}
|
||||
|
||||
StringName class_name = type;
|
||||
|
||||
while (class_name != StringName()) {
|
||||
if (theme_owner->data.theme->has_font(p_name, class_name)) {
|
||||
return theme_owner->data.theme->get_font(p_name, class_name);
|
||||
}
|
||||
|
||||
class_name = ClassDB::get_parent_class_nocheck(class_name);
|
||||
if (Theme::get_project_default().is_valid()) {
|
||||
if (Theme::get_project_default()->has_font(p_name, type)) {
|
||||
return Theme::get_project_default()->get_font(p_name, type);
|
||||
}
|
||||
|
||||
if (theme_owner->data.theme->get_default_theme_font().is_valid())
|
||||
return theme_owner->data.theme->get_default_theme_font();
|
||||
Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
|
||||
|
||||
if (parent)
|
||||
theme_owner = parent->data.theme_owner;
|
||||
else
|
||||
theme_owner = NULL;
|
||||
}
|
||||
|
||||
return Theme::get_default()->get_font(p_name, type);
|
||||
@ -985,27 +1015,11 @@ Color Control::get_color(const StringName &p_name, const StringName &p_type) con
|
||||
}
|
||||
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
// try with custom themes
|
||||
Control *theme_owner = data.theme_owner;
|
||||
|
||||
while (theme_owner) {
|
||||
Color color;
|
||||
|
||||
StringName class_name = type;
|
||||
|
||||
while (class_name != StringName()) {
|
||||
if (theme_owner->data.theme->has_color(p_name, class_name)) {
|
||||
return theme_owner->data.theme->get_color(p_name, class_name);
|
||||
}
|
||||
|
||||
class_name = ClassDB::get_parent_class_nocheck(class_name);
|
||||
}
|
||||
|
||||
Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
|
||||
|
||||
if (parent)
|
||||
theme_owner = parent->data.theme_owner;
|
||||
else
|
||||
theme_owner = NULL;
|
||||
if (_find_theme_item(color, &Theme::get_color, &Theme::has_color, p_name, type)) {
|
||||
return color;
|
||||
}
|
||||
|
||||
if (Theme::get_project_default().is_valid()) {
|
||||
@ -1025,27 +1039,11 @@ int Control::get_constant(const StringName &p_name, const StringName &p_type) co
|
||||
}
|
||||
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
// try with custom themes
|
||||
Control *theme_owner = data.theme_owner;
|
||||
|
||||
while (theme_owner) {
|
||||
int constant;
|
||||
|
||||
StringName class_name = type;
|
||||
|
||||
while (class_name != StringName()) {
|
||||
if (theme_owner->data.theme->has_constant(p_name, class_name)) {
|
||||
return theme_owner->data.theme->get_constant(p_name, class_name);
|
||||
}
|
||||
|
||||
class_name = ClassDB::get_parent_class_nocheck(class_name);
|
||||
}
|
||||
|
||||
Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
|
||||
|
||||
if (parent)
|
||||
theme_owner = parent->data.theme_owner;
|
||||
else
|
||||
theme_owner = NULL;
|
||||
if (_find_theme_item(constant, &Theme::get_constant, &Theme::has_constant, p_name, type)) {
|
||||
return constant;
|
||||
}
|
||||
|
||||
if (Theme::get_project_default().is_valid()) {
|
||||
@ -1101,26 +1099,8 @@ bool Control::has_icon(const StringName &p_name, const StringName &p_type) const
|
||||
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
|
||||
// try with custom themes
|
||||
Control *theme_owner = data.theme_owner;
|
||||
|
||||
while (theme_owner) {
|
||||
|
||||
StringName class_name = type;
|
||||
|
||||
while (class_name != StringName()) {
|
||||
if (theme_owner->data.theme->has_icon(p_name, class_name)) {
|
||||
return true;
|
||||
}
|
||||
class_name = ClassDB::get_parent_class_nocheck(class_name);
|
||||
}
|
||||
|
||||
Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
|
||||
|
||||
if (parent)
|
||||
theme_owner = parent->data.theme_owner;
|
||||
else
|
||||
theme_owner = NULL;
|
||||
if (_has_theme_item(&Theme::has_icon, p_name, type)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Theme::get_project_default().is_valid()) {
|
||||
@ -1140,26 +1120,8 @@ bool Control::has_shader(const StringName &p_name, const StringName &p_type) con
|
||||
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
|
||||
// try with custom themes
|
||||
Control *theme_owner = data.theme_owner;
|
||||
|
||||
while (theme_owner) {
|
||||
|
||||
StringName class_name = type;
|
||||
|
||||
while (class_name != StringName()) {
|
||||
if (theme_owner->data.theme->has_shader(p_name, class_name)) {
|
||||
return true;
|
||||
}
|
||||
class_name = ClassDB::get_parent_class_nocheck(class_name);
|
||||
}
|
||||
|
||||
Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
|
||||
|
||||
if (parent)
|
||||
theme_owner = parent->data.theme_owner;
|
||||
else
|
||||
theme_owner = NULL;
|
||||
if (_has_theme_item(&Theme::has_shader, p_name, type)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Theme::get_project_default().is_valid()) {
|
||||
@ -1178,26 +1140,8 @@ bool Control::has_stylebox(const StringName &p_name, const StringName &p_type) c
|
||||
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
|
||||
// try with custom themes
|
||||
Control *theme_owner = data.theme_owner;
|
||||
|
||||
while (theme_owner) {
|
||||
|
||||
StringName class_name = type;
|
||||
|
||||
while (class_name != StringName()) {
|
||||
if (theme_owner->data.theme->has_stylebox(p_name, class_name)) {
|
||||
return true;
|
||||
}
|
||||
class_name = ClassDB::get_parent_class_nocheck(class_name);
|
||||
}
|
||||
|
||||
Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
|
||||
|
||||
if (parent)
|
||||
theme_owner = parent->data.theme_owner;
|
||||
else
|
||||
theme_owner = NULL;
|
||||
if (_has_theme_item(&Theme::has_stylebox, p_name, type)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Theme::get_project_default().is_valid()) {
|
||||
@ -1216,26 +1160,8 @@ bool Control::has_font(const StringName &p_name, const StringName &p_type) const
|
||||
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
|
||||
// try with custom themes
|
||||
Control *theme_owner = data.theme_owner;
|
||||
|
||||
while (theme_owner) {
|
||||
|
||||
StringName class_name = type;
|
||||
|
||||
while (class_name != StringName()) {
|
||||
if (theme_owner->data.theme->has_font(p_name, class_name)) {
|
||||
return true;
|
||||
}
|
||||
class_name = ClassDB::get_parent_class_nocheck(class_name);
|
||||
}
|
||||
|
||||
Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
|
||||
|
||||
if (parent)
|
||||
theme_owner = parent->data.theme_owner;
|
||||
else
|
||||
theme_owner = NULL;
|
||||
if (_has_theme_item(&Theme::has_font, p_name, type)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Theme::get_project_default().is_valid()) {
|
||||
@ -1255,26 +1181,8 @@ bool Control::has_color(const StringName &p_name, const StringName &p_type) cons
|
||||
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
|
||||
// try with custom themes
|
||||
Control *theme_owner = data.theme_owner;
|
||||
|
||||
while (theme_owner) {
|
||||
|
||||
StringName class_name = type;
|
||||
|
||||
while (class_name != StringName()) {
|
||||
if (theme_owner->data.theme->has_color(p_name, class_name)) {
|
||||
return true;
|
||||
}
|
||||
class_name = ClassDB::get_parent_class_nocheck(class_name);
|
||||
}
|
||||
|
||||
Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
|
||||
|
||||
if (parent)
|
||||
theme_owner = parent->data.theme_owner;
|
||||
else
|
||||
theme_owner = NULL;
|
||||
if (_has_theme_item(&Theme::has_color, p_name, type)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Theme::get_project_default().is_valid()) {
|
||||
@ -1294,26 +1202,8 @@ bool Control::has_constant(const StringName &p_name, const StringName &p_type) c
|
||||
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
|
||||
// try with custom themes
|
||||
Control *theme_owner = data.theme_owner;
|
||||
|
||||
while (theme_owner) {
|
||||
|
||||
StringName class_name = type;
|
||||
|
||||
while (class_name != StringName()) {
|
||||
if (theme_owner->data.theme->has_constant(p_name, class_name)) {
|
||||
return true;
|
||||
}
|
||||
class_name = ClassDB::get_parent_class_nocheck(class_name);
|
||||
}
|
||||
|
||||
Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
|
||||
|
||||
if (parent)
|
||||
theme_owner = parent->data.theme_owner;
|
||||
else
|
||||
theme_owner = NULL;
|
||||
if (_has_theme_item(&Theme::has_constant, p_name, type)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Theme::get_project_default().is_valid()) {
|
||||
@ -2222,18 +2112,32 @@ void Control::_modal_stack_remove() {
|
||||
data.modal_prev_focus_owner = ObjectID();
|
||||
}
|
||||
|
||||
void Control::_propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool p_assign) {
|
||||
void Control::_propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign) {
|
||||
|
||||
Control *c = Object::cast_to<Control>(p_at);
|
||||
|
||||
if (c && c != p_owner && c->data.theme.is_valid()) // has a theme, this can't be propagated
|
||||
return;
|
||||
|
||||
Window *w = c == nullptr ? Object::cast_to<Window>(p_at) : nullptr;
|
||||
|
||||
if (c && c != p_owner && c->data.theme.is_valid()) // has a theme, this can't be propagated
|
||||
return;
|
||||
|
||||
if (w && w != p_owner_window && w->theme.is_valid()) // has a theme, this can't be propagated
|
||||
return;
|
||||
|
||||
for (int i = 0; i < p_at->get_child_count(); i++) {
|
||||
|
||||
CanvasItem *child = Object::cast_to<CanvasItem>(p_at->get_child(i));
|
||||
if (child) {
|
||||
_propagate_theme_changed(child, p_owner, p_assign);
|
||||
_propagate_theme_changed(child, p_owner, p_owner_window, p_assign);
|
||||
} else {
|
||||
|
||||
Window *window = Object::cast_to<Window>(p_at->get_child(i));
|
||||
if (window) {
|
||||
_propagate_theme_changed(window, p_owner, p_owner_window, p_assign);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2241,14 +2145,26 @@ void Control::_propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool
|
||||
|
||||
if (p_assign) {
|
||||
c->data.theme_owner = p_owner;
|
||||
c->data.theme_owner_window = p_owner_window;
|
||||
}
|
||||
c->notification(NOTIFICATION_THEME_CHANGED);
|
||||
c->notification(Control::NOTIFICATION_THEME_CHANGED);
|
||||
c->emit_signal(SceneStringNames::get_singleton()->theme_changed);
|
||||
}
|
||||
|
||||
if (w) {
|
||||
|
||||
if (p_assign) {
|
||||
w->theme_owner = p_owner;
|
||||
w->theme_owner_window = p_owner_window;
|
||||
}
|
||||
w->notification(Window::NOTIFICATION_THEME_CHANGED);
|
||||
w->emit_signal(SceneStringNames::get_singleton()->theme_changed);
|
||||
}
|
||||
}
|
||||
|
||||
void Control::_theme_changed() {
|
||||
|
||||
_propagate_theme_changed(this, this, false);
|
||||
_propagate_theme_changed(this, this, nullptr, false);
|
||||
}
|
||||
|
||||
void Control::set_theme(const Ref<Theme> &p_theme) {
|
||||
@ -2264,15 +2180,21 @@ void Control::set_theme(const Ref<Theme> &p_theme) {
|
||||
if (!p_theme.is_null()) {
|
||||
|
||||
data.theme_owner = this;
|
||||
_propagate_theme_changed(this, this);
|
||||
data.theme_owner_window = nullptr;
|
||||
_propagate_theme_changed(this, this, nullptr);
|
||||
} else {
|
||||
|
||||
Control *parent = cast_to<Control>(get_parent());
|
||||
if (parent && parent->data.theme_owner) {
|
||||
_propagate_theme_changed(this, parent->data.theme_owner);
|
||||
} else {
|
||||
Control *parent_c = Object::cast_to<Control>(get_parent());
|
||||
|
||||
_propagate_theme_changed(this, NULL);
|
||||
if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) {
|
||||
Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window);
|
||||
} else {
|
||||
Window *parent_w = cast_to<Window>(get_parent());
|
||||
if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) {
|
||||
Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window);
|
||||
} else {
|
||||
Control::_propagate_theme_changed(this, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2564,6 +2486,12 @@ void Control::minimum_size_changed() {
|
||||
invalidate->data.minimum_size_valid = false;
|
||||
if (invalidate->is_set_as_toplevel())
|
||||
break; // do not go further up
|
||||
if (!invalidate->data.parent && get_parent()) {
|
||||
Window *parent_window = Object::cast_to<Window>(get_parent());
|
||||
if (parent_window && parent_window->is_wrapping_controls()) {
|
||||
parent_window->child_controls_changed();
|
||||
}
|
||||
}
|
||||
invalidate = invalidate->data.parent;
|
||||
}
|
||||
|
||||
@ -2653,6 +2581,7 @@ float Control::get_rotation_degrees() const {
|
||||
void Control::_override_changed() {
|
||||
|
||||
notification(NOTIFICATION_THEME_CHANGED);
|
||||
emit_signal(SceneStringNames::get_singleton()->theme_changed);
|
||||
minimum_size_changed(); // overrides are likely to affect minimum size
|
||||
}
|
||||
|
||||
@ -3078,6 +3007,7 @@ void Control::_bind_methods() {
|
||||
ADD_SIGNAL(MethodInfo("size_flags_changed"));
|
||||
ADD_SIGNAL(MethodInfo("minimum_size_changed"));
|
||||
ADD_SIGNAL(MethodInfo("modal_closed"));
|
||||
ADD_SIGNAL(MethodInfo("theme_changed"));
|
||||
|
||||
BIND_VMETHOD(MethodInfo(Variant::BOOL, "has_point", PropertyInfo(Variant::VECTOR2, "point")));
|
||||
}
|
||||
@ -3092,6 +3022,7 @@ Control::Control() {
|
||||
data.MI = NULL;
|
||||
data.RI = NULL;
|
||||
data.theme_owner = NULL;
|
||||
data.theme_owner_window = NULL;
|
||||
data.modal_exclusive = false;
|
||||
data.default_cursor = CURSOR_ARROW;
|
||||
data.h_size_flags = SIZE_FILL;
|
||||
|
||||
@ -183,6 +183,7 @@ private:
|
||||
uint64_t modal_frame; //frame used to put something as modal
|
||||
Ref<Theme> theme;
|
||||
Control *theme_owner;
|
||||
Window *theme_owner_window;
|
||||
String tooltip;
|
||||
CursorShape default_cursor;
|
||||
|
||||
@ -218,7 +219,6 @@ private:
|
||||
void _set_global_position(const Point2 &p_point);
|
||||
void _set_size(const Size2 &p_size);
|
||||
|
||||
void _propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool p_assign = true);
|
||||
void _theme_changed();
|
||||
|
||||
void _change_notify_margins();
|
||||
@ -244,6 +244,13 @@ private:
|
||||
void _modal_set_prev_focus_owner(ObjectID p_prev);
|
||||
|
||||
void _update_minimum_size_cache();
|
||||
friend class Window;
|
||||
static void _propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign = true);
|
||||
|
||||
template <class T>
|
||||
_FORCE_INLINE_ bool _find_theme_item(T &, T (Theme::*get_func)(const StringName &, const StringName &) const, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_type) const;
|
||||
|
||||
_FORCE_INLINE_ bool _has_theme_item(bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_type) const;
|
||||
|
||||
protected:
|
||||
virtual void add_child_notify(Node *p_child);
|
||||
|
||||
@ -29,6 +29,8 @@
|
||||
/*************************************************************************/
|
||||
|
||||
#include "dialogs.h"
|
||||
|
||||
#include "core/os/keyboard.h"
|
||||
#include "core/print_string.h"
|
||||
#include "core/translation.h"
|
||||
#include "line_edit.h"
|
||||
@ -39,359 +41,51 @@
|
||||
#include "scene/main/window.h" // Only used to check for more modals when dimming the editor.
|
||||
#endif
|
||||
|
||||
// WindowDialog
|
||||
|
||||
void WindowDialog::_post_popup() {
|
||||
|
||||
drag_type = DRAG_NONE; // just in case
|
||||
}
|
||||
|
||||
void WindowDialog::_fix_size() {
|
||||
|
||||
// Perhaps this should be called when the viewport resizes as well or windows go out of bounds...
|
||||
|
||||
// Ensure the whole window is visible.
|
||||
Point2i pos = get_global_position();
|
||||
Size2i size = get_size();
|
||||
Size2i viewport_size = get_viewport_rect().size;
|
||||
|
||||
// Windows require additional padding to keep the window chrome visible.
|
||||
Ref<StyleBox> panel = get_stylebox("panel", "WindowDialog");
|
||||
float top = 0;
|
||||
float left = 0;
|
||||
float bottom = 0;
|
||||
float right = 0;
|
||||
// Check validity, because the theme could contain a different type of StyleBox.
|
||||
if (panel->get_class() == "StyleBoxTexture") {
|
||||
Ref<StyleBoxTexture> panel_texture = Object::cast_to<StyleBoxTexture>(*panel);
|
||||
top = panel_texture->get_expand_margin_size(MARGIN_TOP);
|
||||
left = panel_texture->get_expand_margin_size(MARGIN_LEFT);
|
||||
bottom = panel_texture->get_expand_margin_size(MARGIN_BOTTOM);
|
||||
right = panel_texture->get_expand_margin_size(MARGIN_RIGHT);
|
||||
} else if (panel->get_class() == "StyleBoxFlat") {
|
||||
Ref<StyleBoxFlat> panel_flat = Object::cast_to<StyleBoxFlat>(*panel);
|
||||
top = panel_flat->get_expand_margin_size(MARGIN_TOP);
|
||||
left = panel_flat->get_expand_margin_size(MARGIN_LEFT);
|
||||
bottom = panel_flat->get_expand_margin_size(MARGIN_BOTTOM);
|
||||
right = panel_flat->get_expand_margin_size(MARGIN_RIGHT);
|
||||
}
|
||||
|
||||
pos.x = MAX(left, MIN(pos.x, viewport_size.x - size.x - right));
|
||||
pos.y = MAX(top, MIN(pos.y, viewport_size.y - size.y - bottom));
|
||||
set_global_position(pos);
|
||||
|
||||
if (resizable) {
|
||||
size.x = MIN(size.x, viewport_size.x - left - right);
|
||||
size.y = MIN(size.y, viewport_size.y - top - bottom);
|
||||
set_size(size);
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowDialog::has_point(const Point2 &p_point) const {
|
||||
|
||||
Rect2 r(Point2(), get_size());
|
||||
|
||||
// Enlarge upwards for title bar.
|
||||
int title_height = get_constant("title_height", "WindowDialog");
|
||||
r.position.y -= title_height;
|
||||
r.size.y += title_height;
|
||||
|
||||
// Inflate by the resizable border thickness.
|
||||
if (resizable) {
|
||||
int scaleborder_size = get_constant("scaleborder_size", "WindowDialog");
|
||||
r.position.x -= scaleborder_size;
|
||||
r.size.width += scaleborder_size * 2;
|
||||
r.position.y -= scaleborder_size;
|
||||
r.size.height += scaleborder_size * 2;
|
||||
}
|
||||
|
||||
return r.has_point(p_point);
|
||||
}
|
||||
|
||||
void WindowDialog::_gui_input(const Ref<InputEvent> &p_event) {
|
||||
|
||||
Ref<InputEventMouseButton> mb = p_event;
|
||||
|
||||
if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) {
|
||||
|
||||
if (mb->is_pressed()) {
|
||||
// Begin a possible dragging operation.
|
||||
drag_type = _drag_hit_test(Point2(mb->get_position().x, mb->get_position().y));
|
||||
if (drag_type != DRAG_NONE)
|
||||
drag_offset = get_global_mouse_position() - get_position();
|
||||
drag_offset_far = get_position() + get_size() - get_global_mouse_position();
|
||||
} else if (drag_type != DRAG_NONE && !mb->is_pressed()) {
|
||||
// End a dragging operation.
|
||||
drag_type = DRAG_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
Ref<InputEventMouseMotion> mm = p_event;
|
||||
|
||||
if (mm.is_valid()) {
|
||||
|
||||
if (drag_type == DRAG_NONE) {
|
||||
// Update the cursor while moving along the borders.
|
||||
CursorShape cursor = CURSOR_ARROW;
|
||||
if (resizable) {
|
||||
int preview_drag_type = _drag_hit_test(Point2(mm->get_position().x, mm->get_position().y));
|
||||
switch (preview_drag_type) {
|
||||
case DRAG_RESIZE_TOP:
|
||||
case DRAG_RESIZE_BOTTOM:
|
||||
cursor = CURSOR_VSIZE;
|
||||
break;
|
||||
case DRAG_RESIZE_LEFT:
|
||||
case DRAG_RESIZE_RIGHT:
|
||||
cursor = CURSOR_HSIZE;
|
||||
break;
|
||||
case DRAG_RESIZE_TOP + DRAG_RESIZE_LEFT:
|
||||
case DRAG_RESIZE_BOTTOM + DRAG_RESIZE_RIGHT:
|
||||
cursor = CURSOR_FDIAGSIZE;
|
||||
break;
|
||||
case DRAG_RESIZE_TOP + DRAG_RESIZE_RIGHT:
|
||||
case DRAG_RESIZE_BOTTOM + DRAG_RESIZE_LEFT:
|
||||
cursor = CURSOR_BDIAGSIZE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (get_cursor_shape() != cursor)
|
||||
set_default_cursor_shape(cursor);
|
||||
} else {
|
||||
// Update while in a dragging operation.
|
||||
Point2 global_pos = get_global_mouse_position();
|
||||
global_pos.y = MAX(global_pos.y, 0); // Ensure title bar stays visible.
|
||||
|
||||
Rect2 rect = get_rect();
|
||||
Size2 min_size = get_combined_minimum_size();
|
||||
|
||||
if (drag_type == DRAG_MOVE) {
|
||||
rect.position = global_pos - drag_offset;
|
||||
} else {
|
||||
if (drag_type & DRAG_RESIZE_TOP) {
|
||||
int bottom = rect.position.y + rect.size.height;
|
||||
int max_y = bottom - min_size.height;
|
||||
rect.position.y = MIN(global_pos.y - drag_offset.y, max_y);
|
||||
rect.size.height = bottom - rect.position.y;
|
||||
} else if (drag_type & DRAG_RESIZE_BOTTOM) {
|
||||
rect.size.height = global_pos.y - rect.position.y + drag_offset_far.y;
|
||||
}
|
||||
if (drag_type & DRAG_RESIZE_LEFT) {
|
||||
int right = rect.position.x + rect.size.width;
|
||||
int max_x = right - min_size.width;
|
||||
rect.position.x = MIN(global_pos.x - drag_offset.x, max_x);
|
||||
rect.size.width = right - rect.position.x;
|
||||
} else if (drag_type & DRAG_RESIZE_RIGHT) {
|
||||
rect.size.width = global_pos.x - rect.position.x + drag_offset_far.x;
|
||||
}
|
||||
}
|
||||
|
||||
set_size(rect.size);
|
||||
set_position(rect.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WindowDialog::_notification(int p_what) {
|
||||
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_DRAW: {
|
||||
RID canvas = get_canvas_item();
|
||||
|
||||
// Draw the background.
|
||||
Ref<StyleBox> panel = get_stylebox("panel");
|
||||
Size2 size = get_size();
|
||||
panel->draw(canvas, Rect2(0, 0, size.x, size.y));
|
||||
|
||||
// Draw the title bar text.
|
||||
Ref<Font> title_font = get_font("title_font", "WindowDialog");
|
||||
Color title_color = get_color("title_color", "WindowDialog");
|
||||
int title_height = get_constant("title_height", "WindowDialog");
|
||||
int font_height = title_font->get_height() - title_font->get_descent() * 2;
|
||||
int x = (size.x - title_font->get_string_size(xl_title).x) / 2;
|
||||
int y = (-title_height + font_height) / 2;
|
||||
title_font->draw(canvas, Point2(x, y), xl_title, title_color, size.x - panel->get_minimum_size().x);
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_THEME_CHANGED:
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
close_button->set_normal_texture(get_icon("close", "WindowDialog"));
|
||||
close_button->set_pressed_texture(get_icon("close", "WindowDialog"));
|
||||
close_button->set_hover_texture(get_icon("close_highlight", "WindowDialog"));
|
||||
close_button->set_anchor(MARGIN_LEFT, ANCHOR_END);
|
||||
close_button->set_begin(Point2(-get_constant("close_h_ofs", "WindowDialog"), -get_constant("close_v_ofs", "WindowDialog")));
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_TRANSLATION_CHANGED: {
|
||||
String new_title = tr(title);
|
||||
if (new_title != xl_title) {
|
||||
xl_title = new_title;
|
||||
minimum_size_changed();
|
||||
update();
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_MOUSE_EXIT: {
|
||||
// Reset the mouse cursor when leaving the resizable window border.
|
||||
if (resizable && !drag_type) {
|
||||
if (get_default_cursor_shape() != CURSOR_ARROW)
|
||||
set_default_cursor_shape(CURSOR_ARROW);
|
||||
}
|
||||
} break;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
case NOTIFICATION_POST_POPUP: {
|
||||
if (get_tree() && Engine::get_singleton()->is_editor_hint() && EditorNode::get_singleton()) {
|
||||
was_editor_dimmed = EditorNode::get_singleton()->is_editor_dimmed();
|
||||
EditorNode::get_singleton()->dim_editor(true);
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_POPUP_HIDE: {
|
||||
if (get_tree() && Engine::get_singleton()->is_editor_hint() && EditorNode::get_singleton() && !was_editor_dimmed) {
|
||||
EditorNode::get_singleton()->dim_editor(false);
|
||||
set_pass_on_modal_close_click(false);
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void WindowDialog::_closed() {
|
||||
|
||||
_close_pressed();
|
||||
hide();
|
||||
}
|
||||
|
||||
int WindowDialog::_drag_hit_test(const Point2 &pos) const {
|
||||
int drag_type = DRAG_NONE;
|
||||
|
||||
if (resizable) {
|
||||
int title_height = get_constant("title_height", "WindowDialog");
|
||||
int scaleborder_size = get_constant("scaleborder_size", "WindowDialog");
|
||||
|
||||
Rect2 rect = get_rect();
|
||||
|
||||
if (pos.y < (-title_height + scaleborder_size))
|
||||
drag_type = DRAG_RESIZE_TOP;
|
||||
else if (pos.y >= (rect.size.height - scaleborder_size))
|
||||
drag_type = DRAG_RESIZE_BOTTOM;
|
||||
if (pos.x < scaleborder_size)
|
||||
drag_type |= DRAG_RESIZE_LEFT;
|
||||
else if (pos.x >= (rect.size.width - scaleborder_size))
|
||||
drag_type |= DRAG_RESIZE_RIGHT;
|
||||
}
|
||||
|
||||
if (drag_type == DRAG_NONE && pos.y < 0)
|
||||
drag_type = DRAG_MOVE;
|
||||
|
||||
return drag_type;
|
||||
}
|
||||
|
||||
void WindowDialog::set_title(const String &p_title) {
|
||||
|
||||
if (title != p_title) {
|
||||
title = p_title;
|
||||
xl_title = tr(p_title);
|
||||
minimum_size_changed();
|
||||
update();
|
||||
}
|
||||
}
|
||||
String WindowDialog::get_title() const {
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
void WindowDialog::set_resizable(bool p_resizable) {
|
||||
resizable = p_resizable;
|
||||
}
|
||||
bool WindowDialog::get_resizable() const {
|
||||
return resizable;
|
||||
}
|
||||
|
||||
Size2 WindowDialog::get_minimum_size() const {
|
||||
|
||||
Ref<Font> font = get_font("title_font", "WindowDialog");
|
||||
|
||||
const int button_width = close_button->get_combined_minimum_size().x;
|
||||
const int title_width = font->get_string_size(xl_title).x;
|
||||
const int padding = button_width / 2;
|
||||
const int button_area = button_width + padding;
|
||||
|
||||
// As the title gets centered, title_width + close_button_width is not enough.
|
||||
// We want a width w, such that w / 2 - title_width / 2 >= button_area, i.e.
|
||||
// w >= 2 * button_area + title_width
|
||||
|
||||
return Size2(2 * button_area + title_width, 1);
|
||||
}
|
||||
|
||||
TextureButton *WindowDialog::get_close_button() {
|
||||
|
||||
return close_button;
|
||||
}
|
||||
|
||||
void WindowDialog::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_gui_input"), &WindowDialog::_gui_input);
|
||||
ClassDB::bind_method(D_METHOD("set_title", "title"), &WindowDialog::set_title);
|
||||
ClassDB::bind_method(D_METHOD("get_title"), &WindowDialog::get_title);
|
||||
ClassDB::bind_method(D_METHOD("set_resizable", "resizable"), &WindowDialog::set_resizable);
|
||||
ClassDB::bind_method(D_METHOD("get_resizable"), &WindowDialog::get_resizable);
|
||||
ClassDB::bind_method(D_METHOD("get_close_button"), &WindowDialog::get_close_button);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "window_title", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT_INTL), "set_title", "get_title");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resizable", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT_INTL), "set_resizable", "get_resizable");
|
||||
}
|
||||
|
||||
WindowDialog::WindowDialog() {
|
||||
|
||||
drag_type = DRAG_NONE;
|
||||
resizable = false;
|
||||
close_button = memnew(TextureButton);
|
||||
add_child(close_button);
|
||||
close_button->connect("pressed", callable_mp(this, &WindowDialog::_closed));
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
was_editor_dimmed = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
WindowDialog::~WindowDialog() {
|
||||
}
|
||||
|
||||
// PopupDialog
|
||||
|
||||
void PopupDialog::_notification(int p_what) {
|
||||
|
||||
if (p_what == NOTIFICATION_DRAW) {
|
||||
RID ci = get_canvas_item();
|
||||
get_stylebox("panel")->draw(ci, Rect2(Point2(), get_size()));
|
||||
}
|
||||
}
|
||||
|
||||
PopupDialog::PopupDialog() {
|
||||
}
|
||||
|
||||
PopupDialog::~PopupDialog() {
|
||||
}
|
||||
|
||||
// AcceptDialog
|
||||
|
||||
void AcceptDialog::_post_popup() {
|
||||
void AcceptDialog::_input_from_window(const Ref<InputEvent> &p_event) {
|
||||
Ref<InputEventKey> key = p_event;
|
||||
if (key.is_valid() && key->is_pressed() && key->get_keycode() == KEY_ESCAPE) {
|
||||
_cancel_pressed();
|
||||
}
|
||||
}
|
||||
|
||||
WindowDialog::_post_popup();
|
||||
get_ok()->grab_focus();
|
||||
void AcceptDialog::_parent_focused() {
|
||||
_cancel_pressed();
|
||||
}
|
||||
|
||||
void AcceptDialog::_notification(int p_what) {
|
||||
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_MODAL_CLOSE: {
|
||||
cancel_pressed();
|
||||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||
if (is_visible()) {
|
||||
|
||||
get_ok()->grab_focus();
|
||||
_update_child_rects();
|
||||
parent_visible = get_parent_visible_window();
|
||||
if (parent_visible) {
|
||||
parent_visible->connect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused));
|
||||
}
|
||||
} else {
|
||||
if (parent_visible) {
|
||||
parent_visible->disconnect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused));
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
bg->add_style_override("panel", bg->get_stylebox("panel", "AcceptDialog"));
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_READY:
|
||||
case NOTIFICATION_RESIZED: {
|
||||
_update_child_rects();
|
||||
case NOTIFICATION_WM_SIZE_CHANGED: {
|
||||
if (is_visible()) {
|
||||
_update_child_rects();
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_WM_CLOSE_REQUEST: {
|
||||
_cancel_pressed();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
@ -404,20 +98,28 @@ void AcceptDialog::_text_entered(const String &p_text) {
|
||||
void AcceptDialog::_ok_pressed() {
|
||||
|
||||
if (hide_on_ok)
|
||||
hide();
|
||||
set_visible(false);
|
||||
ok_pressed();
|
||||
emit_signal("confirmed");
|
||||
}
|
||||
|
||||
void AcceptDialog::_close_pressed() {
|
||||
void AcceptDialog::_cancel_pressed() {
|
||||
|
||||
Window *parent_window = parent_visible;
|
||||
if (parent_visible) {
|
||||
parent_visible->disconnect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused));
|
||||
parent_visible = nullptr;
|
||||
}
|
||||
|
||||
call_deferred("hide");
|
||||
|
||||
emit_signal("cancelled");
|
||||
|
||||
cancel_pressed();
|
||||
}
|
||||
|
||||
// FIXME: This is redundant with _closed_pressed, but there's a slight behavior
|
||||
// change (WindowDialog's _closed() also calls hide()) which should be assessed.
|
||||
void AcceptDialog::_on_close_pressed() {
|
||||
_closed(); // From WindowDialog.
|
||||
if (parent_window) {
|
||||
//parent_window->grab_focus();
|
||||
}
|
||||
}
|
||||
|
||||
String AcceptDialog::get_text() const {
|
||||
@ -427,8 +129,10 @@ String AcceptDialog::get_text() const {
|
||||
void AcceptDialog::set_text(String p_text) {
|
||||
|
||||
label->set_text(p_text);
|
||||
minimum_size_changed();
|
||||
_update_child_rects();
|
||||
child_controls_changed();
|
||||
if (is_visible()) {
|
||||
_update_child_rects();
|
||||
}
|
||||
}
|
||||
|
||||
void AcceptDialog::set_hide_on_ok(bool p_hide) {
|
||||
@ -463,7 +167,7 @@ void AcceptDialog::_update_child_rects() {
|
||||
if (label->get_text().empty()) {
|
||||
label_size.height = 0;
|
||||
}
|
||||
int margin = get_constant("margin", "Dialogs");
|
||||
int margin = hbc->get_constant("margin", "Dialogs");
|
||||
Size2 size = get_size();
|
||||
Size2 hminsize = hbc->get_combined_minimum_size();
|
||||
|
||||
@ -475,7 +179,7 @@ void AcceptDialog::_update_child_rects() {
|
||||
if (!c)
|
||||
continue;
|
||||
|
||||
if (c == hbc || c == label || c == get_close_button() || c->is_set_as_toplevel())
|
||||
if (c == hbc || c == label || c == bg || c->is_set_as_toplevel())
|
||||
continue;
|
||||
|
||||
c->set_position(cpos);
|
||||
@ -487,11 +191,14 @@ void AcceptDialog::_update_child_rects() {
|
||||
|
||||
hbc->set_position(cpos);
|
||||
hbc->set_size(csize);
|
||||
|
||||
bg->set_position(Point2());
|
||||
bg->set_size(size);
|
||||
}
|
||||
|
||||
Size2 AcceptDialog::get_minimum_size() const {
|
||||
Size2 AcceptDialog::_get_contents_minimum_size() const {
|
||||
|
||||
int margin = get_constant("margin", "Dialogs");
|
||||
int margin = hbc->get_constant("margin", "Dialogs");
|
||||
Size2 minsize = label->get_combined_minimum_size();
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
@ -499,7 +206,7 @@ Size2 AcceptDialog::get_minimum_size() const {
|
||||
if (!c)
|
||||
continue;
|
||||
|
||||
if (c == hbc || c == label || c == const_cast<AcceptDialog *>(this)->get_close_button() || c->is_set_as_toplevel())
|
||||
if (c == hbc || c == label || c->is_set_as_toplevel())
|
||||
continue;
|
||||
|
||||
Size2 cminsize = c->get_combined_minimum_size();
|
||||
@ -513,7 +220,7 @@ Size2 AcceptDialog::get_minimum_size() const {
|
||||
minsize.x += margin * 2;
|
||||
minsize.y += margin * 3; //one as separation between hbc and child
|
||||
|
||||
Size2 wmsize = WindowDialog::get_minimum_size();
|
||||
Size2 wmsize = get_min_size();
|
||||
minsize.x = MAX(wmsize.x, minsize.x);
|
||||
return minsize;
|
||||
}
|
||||
@ -551,7 +258,7 @@ Button *AcceptDialog::add_cancel(const String &p_cancel) {
|
||||
if (p_cancel == "")
|
||||
c = RTR("Cancel");
|
||||
Button *b = swap_ok_cancel ? add_button(c, true) : add_button(c);
|
||||
b->connect("pressed", callable_mp(this, &AcceptDialog::_on_close_pressed));
|
||||
b->connect("pressed", callable_mp(this, &AcceptDialog::_cancel_pressed));
|
||||
return b;
|
||||
}
|
||||
|
||||
@ -570,6 +277,7 @@ void AcceptDialog::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("has_autowrap"), &AcceptDialog::has_autowrap);
|
||||
|
||||
ADD_SIGNAL(MethodInfo("confirmed"));
|
||||
ADD_SIGNAL(MethodInfo("cancelled"));
|
||||
ADD_SIGNAL(MethodInfo("custom_action", PropertyInfo(Variant::STRING_NAME, "action")));
|
||||
|
||||
ADD_GROUP("Dialog", "dialog");
|
||||
@ -586,12 +294,22 @@ void AcceptDialog::set_swap_ok_cancel(bool p_swap) {
|
||||
|
||||
AcceptDialog::AcceptDialog() {
|
||||
|
||||
int margin = get_constant("margin", "Dialogs");
|
||||
int button_margin = get_constant("button_margin", "Dialogs");
|
||||
parent_visible = nullptr;
|
||||
|
||||
set_visible(false);
|
||||
set_transient(true);
|
||||
|
||||
bg = memnew(Panel);
|
||||
add_child(bg);
|
||||
|
||||
hbc = memnew(HBoxContainer);
|
||||
|
||||
int margin = hbc->get_constant("margin", "Dialogs");
|
||||
int button_margin = hbc->get_constant("button_margin", "Dialogs");
|
||||
|
||||
label = memnew(Label);
|
||||
label->set_anchor(MARGIN_RIGHT, ANCHOR_END);
|
||||
label->set_anchor(MARGIN_BOTTOM, ANCHOR_END);
|
||||
label->set_anchor(MARGIN_RIGHT, Control::ANCHOR_END);
|
||||
label->set_anchor(MARGIN_BOTTOM, Control::ANCHOR_END);
|
||||
label->set_begin(Point2(margin, margin));
|
||||
label->set_end(Point2(-margin, -button_margin - 10));
|
||||
add_child(label);
|
||||
@ -606,10 +324,11 @@ AcceptDialog::AcceptDialog() {
|
||||
hbc->add_spacer();
|
||||
|
||||
ok->connect("pressed", callable_mp(this, &AcceptDialog::_ok_pressed));
|
||||
set_as_toplevel(true);
|
||||
|
||||
hide_on_ok = true;
|
||||
set_title(RTR("Alert!"));
|
||||
|
||||
connect("window_input", callable_mp(this, &AcceptDialog::_input_from_window));
|
||||
}
|
||||
|
||||
AcceptDialog::~AcceptDialog() {
|
||||
@ -631,7 +350,7 @@ ConfirmationDialog::ConfirmationDialog() {
|
||||
|
||||
set_title(RTR("Please Confirm..."));
|
||||
#ifdef TOOLS_ENABLED
|
||||
set_custom_minimum_size(Size2(200, 70) * EDSCALE);
|
||||
set_min_size(Size2(200, 70) * EDSCALE);
|
||||
#endif
|
||||
cancel = add_cancel();
|
||||
}
|
||||
|
||||
@ -37,91 +37,32 @@
|
||||
#include "scene/gui/panel.h"
|
||||
#include "scene/gui/popup.h"
|
||||
#include "scene/gui/texture_button.h"
|
||||
|
||||
class WindowDialog : public Popup {
|
||||
|
||||
GDCLASS(WindowDialog, Popup);
|
||||
|
||||
enum DRAG_TYPE {
|
||||
DRAG_NONE = 0,
|
||||
DRAG_MOVE = 1,
|
||||
DRAG_RESIZE_TOP = 1 << 1,
|
||||
DRAG_RESIZE_RIGHT = 1 << 2,
|
||||
DRAG_RESIZE_BOTTOM = 1 << 3,
|
||||
DRAG_RESIZE_LEFT = 1 << 4
|
||||
};
|
||||
|
||||
TextureButton *close_button;
|
||||
String title;
|
||||
String xl_title;
|
||||
int drag_type;
|
||||
Point2 drag_offset;
|
||||
Point2 drag_offset_far;
|
||||
bool resizable;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
bool was_editor_dimmed;
|
||||
#endif
|
||||
|
||||
void _gui_input(const Ref<InputEvent> &p_event);
|
||||
int _drag_hit_test(const Point2 &pos) const;
|
||||
|
||||
protected:
|
||||
virtual void _post_popup();
|
||||
virtual void _fix_size();
|
||||
virtual void _close_pressed() {}
|
||||
virtual bool has_point(const Point2 &p_point) const;
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
// Not private since used by derived classes signal.
|
||||
void _closed();
|
||||
|
||||
public:
|
||||
TextureButton *get_close_button();
|
||||
|
||||
void set_title(const String &p_title);
|
||||
String get_title() const;
|
||||
void set_resizable(bool p_resizable);
|
||||
bool get_resizable() const;
|
||||
|
||||
Size2 get_minimum_size() const;
|
||||
|
||||
WindowDialog();
|
||||
~WindowDialog();
|
||||
};
|
||||
|
||||
class PopupDialog : public Popup {
|
||||
|
||||
GDCLASS(PopupDialog, Popup);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
PopupDialog();
|
||||
~PopupDialog();
|
||||
};
|
||||
#include "scene/main/window.h"
|
||||
|
||||
class LineEdit;
|
||||
|
||||
class AcceptDialog : public WindowDialog {
|
||||
class AcceptDialog : public Window {
|
||||
|
||||
GDCLASS(AcceptDialog, WindowDialog);
|
||||
GDCLASS(AcceptDialog, Window);
|
||||
|
||||
Window *parent_visible;
|
||||
Panel *bg;
|
||||
HBoxContainer *hbc;
|
||||
Label *label;
|
||||
Button *ok;
|
||||
bool hide_on_ok;
|
||||
|
||||
void _custom_action(const String &p_action);
|
||||
void _close_pressed();
|
||||
void _update_child_rects();
|
||||
|
||||
static bool swap_ok_cancel;
|
||||
|
||||
void _input_from_window(const Ref<InputEvent> &p_event);
|
||||
void _parent_focused();
|
||||
|
||||
protected:
|
||||
virtual void _post_popup();
|
||||
virtual Size2 _get_contents_minimum_size() const;
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
virtual void ok_pressed() {}
|
||||
@ -131,11 +72,9 @@ protected:
|
||||
// Not private since used by derived classes signal.
|
||||
void _text_entered(const String &p_text);
|
||||
void _ok_pressed();
|
||||
void _on_close_pressed();
|
||||
void _cancel_pressed();
|
||||
|
||||
public:
|
||||
Size2 get_minimum_size() const;
|
||||
|
||||
Label *get_label() { return label; }
|
||||
static void set_swap_ok_cancel(bool p_swap);
|
||||
|
||||
|
||||
@ -44,42 +44,46 @@ VBoxContainer *FileDialog::get_vbox() {
|
||||
return vbox;
|
||||
}
|
||||
|
||||
void FileDialog::_theme_changed() {
|
||||
|
||||
Color font_color = vbc->get_color("font_color", "ToolButton");
|
||||
Color font_color_hover = vbc->get_color("font_color_hover", "ToolButton");
|
||||
Color font_color_pressed = vbc->get_color("font_color_pressed", "ToolButton");
|
||||
|
||||
dir_up->add_color_override("icon_color_normal", font_color);
|
||||
dir_up->add_color_override("icon_color_hover", font_color_hover);
|
||||
dir_up->add_color_override("icon_color_pressed", font_color_pressed);
|
||||
|
||||
refresh->add_color_override("icon_color_normal", font_color);
|
||||
refresh->add_color_override("icon_color_hover", font_color_hover);
|
||||
refresh->add_color_override("icon_color_pressed", font_color_pressed);
|
||||
|
||||
show_hidden->add_color_override("icon_color_normal", font_color);
|
||||
show_hidden->add_color_override("icon_color_hover", font_color_hover);
|
||||
show_hidden->add_color_override("icon_color_pressed", font_color_pressed);
|
||||
}
|
||||
|
||||
void FileDialog::_notification(int p_what) {
|
||||
|
||||
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
|
||||
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
|
||||
if (!is_visible()) {
|
||||
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
dir_up->set_icon(get_icon("parent_folder"));
|
||||
refresh->set_icon(get_icon("reload"));
|
||||
show_hidden->set_icon(get_icon("toggle_hidden"));
|
||||
set_process_unhandled_input(false);
|
||||
}
|
||||
}
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
|
||||
Color font_color = get_color("font_color", "ToolButton");
|
||||
Color font_color_hover = get_color("font_color_hover", "ToolButton");
|
||||
Color font_color_pressed = get_color("font_color_pressed", "ToolButton");
|
||||
|
||||
dir_up->add_color_override("icon_color_normal", font_color);
|
||||
dir_up->add_color_override("icon_color_hover", font_color_hover);
|
||||
dir_up->add_color_override("icon_color_pressed", font_color_pressed);
|
||||
|
||||
refresh->add_color_override("icon_color_normal", font_color);
|
||||
refresh->add_color_override("icon_color_hover", font_color_hover);
|
||||
refresh->add_color_override("icon_color_pressed", font_color_pressed);
|
||||
|
||||
show_hidden->add_color_override("icon_color_normal", font_color);
|
||||
show_hidden->add_color_override("icon_color_hover", font_color_hover);
|
||||
show_hidden->add_color_override("icon_color_pressed", font_color_pressed);
|
||||
|
||||
} else if (p_what == NOTIFICATION_POPUP_HIDE) {
|
||||
|
||||
set_process_unhandled_input(false);
|
||||
dir_up->set_icon(vbc->get_icon("parent_folder"));
|
||||
refresh->set_icon(vbc->get_icon("reload"));
|
||||
show_hidden->set_icon(vbc->get_icon("toggle_hidden"));
|
||||
_theme_changed();
|
||||
}
|
||||
}
|
||||
|
||||
void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
|
||||
|
||||
Ref<InputEventKey> k = p_event;
|
||||
if (k.is_valid() && is_window_modal_on_top()) {
|
||||
if (k.is_valid() && has_focus()) {
|
||||
|
||||
if (k->is_pressed()) {
|
||||
|
||||
@ -110,7 +114,7 @@ void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
|
||||
}
|
||||
|
||||
if (handled)
|
||||
accept_event();
|
||||
set_input_as_handled();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -171,7 +175,7 @@ void FileDialog::_post_popup() {
|
||||
update_file_list();
|
||||
invalidated = false;
|
||||
}
|
||||
if (mode == MODE_SAVE_FILE)
|
||||
if (mode == FILE_MODE_SAVE_FILE)
|
||||
file->grab_focus();
|
||||
else
|
||||
tree->grab_focus();
|
||||
@ -179,7 +183,7 @@ void FileDialog::_post_popup() {
|
||||
set_process_unhandled_input(true);
|
||||
|
||||
// For open dir mode, deselect all items on file dialog open.
|
||||
if (mode == MODE_OPEN_DIR) {
|
||||
if (mode == FILE_MODE_OPEN_DIR) {
|
||||
deselect_items();
|
||||
file_box->set_visible(false);
|
||||
} else {
|
||||
@ -189,7 +193,7 @@ void FileDialog::_post_popup() {
|
||||
|
||||
void FileDialog::_action_pressed() {
|
||||
|
||||
if (mode == MODE_OPEN_FILES) {
|
||||
if (mode == FILE_MODE_OPEN_FILES) {
|
||||
|
||||
TreeItem *ti = tree->get_next_selected(NULL);
|
||||
String fbase = dir_access->get_current_dir();
|
||||
@ -211,10 +215,10 @@ void FileDialog::_action_pressed() {
|
||||
|
||||
String f = dir_access->get_current_dir().plus_file(file->get_text());
|
||||
|
||||
if ((mode == MODE_OPEN_ANY || mode == MODE_OPEN_FILE) && dir_access->file_exists(f)) {
|
||||
if ((mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_FILE) && dir_access->file_exists(f)) {
|
||||
emit_signal("file_selected", f);
|
||||
hide();
|
||||
} else if (mode == MODE_OPEN_ANY || mode == MODE_OPEN_DIR) {
|
||||
} else if (mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_DIR) {
|
||||
|
||||
String path = dir_access->get_current_dir();
|
||||
|
||||
@ -231,7 +235,7 @@ void FileDialog::_action_pressed() {
|
||||
hide();
|
||||
}
|
||||
|
||||
if (mode == MODE_SAVE_FILE) {
|
||||
if (mode == FILE_MODE_SAVE_FILE) {
|
||||
|
||||
bool valid = false;
|
||||
|
||||
@ -283,7 +287,7 @@ void FileDialog::_action_pressed() {
|
||||
|
||||
if (!valid) {
|
||||
|
||||
exterr->popup_centered_minsize(Size2(250, 80));
|
||||
exterr->popup_centered(Size2(250, 80));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -307,7 +311,7 @@ void FileDialog::_cancel_pressed() {
|
||||
|
||||
bool FileDialog::_is_open_should_be_disabled() {
|
||||
|
||||
if (mode == MODE_OPEN_ANY || mode == MODE_SAVE_FILE)
|
||||
if (mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_SAVE_FILE)
|
||||
return false;
|
||||
|
||||
TreeItem *ti = tree->get_next_selected(tree->get_root());
|
||||
@ -319,13 +323,13 @@ bool FileDialog::_is_open_should_be_disabled() {
|
||||
}
|
||||
// We have something that we can't select?
|
||||
if (!ti)
|
||||
return mode != MODE_OPEN_DIR; // In "Open folder" mode, having nothing selected picks the current folder.
|
||||
return mode != FILE_MODE_OPEN_DIR; // In "Open folder" mode, having nothing selected picks the current folder.
|
||||
|
||||
Dictionary d = ti->get_metadata(0);
|
||||
|
||||
// Opening a file, but selected a folder? Forbidden.
|
||||
return ((mode == MODE_OPEN_FILE || mode == MODE_OPEN_FILES) && d["dir"]) || // Flipped case, also forbidden.
|
||||
(mode == MODE_OPEN_DIR && !d["dir"]);
|
||||
return ((mode == FILE_MODE_OPEN_FILE || mode == FILE_MODE_OPEN_FILES) && d["dir"]) || // Flipped case, also forbidden.
|
||||
(mode == FILE_MODE_OPEN_DIR && !d["dir"]);
|
||||
}
|
||||
|
||||
void FileDialog::_go_up() {
|
||||
@ -346,15 +350,15 @@ void FileDialog::deselect_items() {
|
||||
|
||||
switch (mode) {
|
||||
|
||||
case MODE_OPEN_FILE:
|
||||
case MODE_OPEN_FILES:
|
||||
case FILE_MODE_OPEN_FILE:
|
||||
case FILE_MODE_OPEN_FILES:
|
||||
get_ok()->set_text(RTR("Open"));
|
||||
break;
|
||||
case MODE_OPEN_DIR:
|
||||
case FILE_MODE_OPEN_DIR:
|
||||
get_ok()->set_text(RTR("Select Current Folder"));
|
||||
break;
|
||||
case MODE_OPEN_ANY:
|
||||
case MODE_SAVE_FILE:
|
||||
case FILE_MODE_OPEN_ANY:
|
||||
case FILE_MODE_SAVE_FILE:
|
||||
// FIXME: Implement, or refactor to avoid duplication with set_mode
|
||||
break;
|
||||
}
|
||||
@ -375,7 +379,7 @@ void FileDialog::_tree_selected() {
|
||||
if (!d["dir"]) {
|
||||
|
||||
file->set_text(d["name"]);
|
||||
} else if (mode == MODE_OPEN_DIR) {
|
||||
} else if (mode == FILE_MODE_OPEN_DIR) {
|
||||
get_ok()->set_text(RTR("Select This Folder"));
|
||||
}
|
||||
|
||||
@ -393,7 +397,7 @@ void FileDialog::_tree_item_activated() {
|
||||
if (d["dir"]) {
|
||||
|
||||
dir_access->change_dir(d["name"]);
|
||||
if (mode == MODE_OPEN_FILE || mode == MODE_OPEN_FILES || mode == MODE_OPEN_DIR || mode == MODE_OPEN_ANY)
|
||||
if (mode == FILE_MODE_OPEN_FILE || mode == FILE_MODE_OPEN_FILES || mode == FILE_MODE_OPEN_DIR || mode == FILE_MODE_OPEN_ANY)
|
||||
file->set_text("");
|
||||
call_deferred("_update_file_list");
|
||||
call_deferred("_update_dir");
|
||||
@ -425,8 +429,8 @@ void FileDialog::update_file_list() {
|
||||
dir_access->list_dir_begin();
|
||||
|
||||
TreeItem *root = tree->create_item();
|
||||
Ref<Texture2D> folder = get_icon("folder");
|
||||
const Color folder_color = get_color("folder_icon_modulate");
|
||||
Ref<Texture2D> folder = vbc->get_icon("folder");
|
||||
const Color folder_color = vbc->get_color("folder_icon_modulate");
|
||||
List<String> files;
|
||||
List<String> dirs;
|
||||
|
||||
@ -523,8 +527,8 @@ void FileDialog::update_file_list() {
|
||||
ti->set_icon(0, icon);
|
||||
}
|
||||
|
||||
if (mode == MODE_OPEN_DIR) {
|
||||
ti->set_custom_color(0, get_color("files_disabled"));
|
||||
if (mode == FILE_MODE_OPEN_DIR) {
|
||||
ti->set_custom_color(0, vbc->get_color("files_disabled"));
|
||||
ti->set_selectable(0, false);
|
||||
}
|
||||
Dictionary d;
|
||||
@ -661,38 +665,38 @@ bool FileDialog::is_mode_overriding_title() const {
|
||||
return mode_overrides_title;
|
||||
}
|
||||
|
||||
void FileDialog::set_mode(Mode p_mode) {
|
||||
void FileDialog::set_file_mode(FileMode p_mode) {
|
||||
|
||||
ERR_FAIL_INDEX((int)p_mode, 5);
|
||||
|
||||
mode = p_mode;
|
||||
switch (mode) {
|
||||
|
||||
case MODE_OPEN_FILE:
|
||||
case FILE_MODE_OPEN_FILE:
|
||||
get_ok()->set_text(RTR("Open"));
|
||||
if (mode_overrides_title)
|
||||
set_title(RTR("Open a File"));
|
||||
makedir->hide();
|
||||
break;
|
||||
case MODE_OPEN_FILES:
|
||||
case FILE_MODE_OPEN_FILES:
|
||||
get_ok()->set_text(RTR("Open"));
|
||||
if (mode_overrides_title)
|
||||
set_title(RTR("Open File(s)"));
|
||||
makedir->hide();
|
||||
break;
|
||||
case MODE_OPEN_DIR:
|
||||
case FILE_MODE_OPEN_DIR:
|
||||
get_ok()->set_text(RTR("Select Current Folder"));
|
||||
if (mode_overrides_title)
|
||||
set_title(RTR("Open a Directory"));
|
||||
makedir->show();
|
||||
break;
|
||||
case MODE_OPEN_ANY:
|
||||
case FILE_MODE_OPEN_ANY:
|
||||
get_ok()->set_text(RTR("Open"));
|
||||
if (mode_overrides_title)
|
||||
set_title(RTR("Open a File or Directory"));
|
||||
makedir->show();
|
||||
break;
|
||||
case MODE_SAVE_FILE:
|
||||
case FILE_MODE_SAVE_FILE:
|
||||
get_ok()->set_text(RTR("Save"));
|
||||
if (mode_overrides_title)
|
||||
set_title(RTR("Save a File"));
|
||||
@ -700,14 +704,14 @@ void FileDialog::set_mode(Mode p_mode) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (mode == MODE_OPEN_FILES) {
|
||||
if (mode == FILE_MODE_OPEN_FILES) {
|
||||
tree->set_select_mode(Tree::SELECT_MULTI);
|
||||
} else {
|
||||
tree->set_select_mode(Tree::SELECT_SINGLE);
|
||||
}
|
||||
}
|
||||
|
||||
FileDialog::Mode FileDialog::get_mode() const {
|
||||
FileDialog::FileMode FileDialog::get_file_mode() const {
|
||||
|
||||
return mode;
|
||||
}
|
||||
@ -741,7 +745,7 @@ void FileDialog::set_access(Access p_access) {
|
||||
|
||||
void FileDialog::invalidate() {
|
||||
|
||||
if (is_visible_in_tree()) {
|
||||
if (is_visible()) {
|
||||
update_file_list();
|
||||
invalidated = false;
|
||||
} else {
|
||||
@ -763,14 +767,14 @@ void FileDialog::_make_dir_confirm() {
|
||||
update_filters();
|
||||
update_dir();
|
||||
} else {
|
||||
mkdirerr->popup_centered_minsize(Size2(250, 50));
|
||||
mkdirerr->popup_centered(Size2(250, 50));
|
||||
}
|
||||
makedirname->set_text(""); // reset label
|
||||
}
|
||||
|
||||
void FileDialog::_make_dir() {
|
||||
|
||||
makedialog->popup_centered_minsize(Size2(250, 80));
|
||||
makedialog->popup_centered(Size2(250, 80));
|
||||
makedirname->grab_focus();
|
||||
}
|
||||
|
||||
@ -826,8 +830,8 @@ void FileDialog::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_current_path", "path"), &FileDialog::set_current_path);
|
||||
ClassDB::bind_method(D_METHOD("set_mode_overrides_title", "override"), &FileDialog::set_mode_overrides_title);
|
||||
ClassDB::bind_method(D_METHOD("is_mode_overriding_title"), &FileDialog::is_mode_overriding_title);
|
||||
ClassDB::bind_method(D_METHOD("set_mode", "mode"), &FileDialog::set_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_mode"), &FileDialog::get_mode);
|
||||
ClassDB::bind_method(D_METHOD("set_file_mode", "mode"), &FileDialog::set_file_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_file_mode"), &FileDialog::get_file_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_vbox"), &FileDialog::get_vbox);
|
||||
ClassDB::bind_method(D_METHOD("get_line_edit"), &FileDialog::get_line_edit);
|
||||
ClassDB::bind_method(D_METHOD("set_access", "access"), &FileDialog::set_access);
|
||||
@ -842,7 +846,7 @@ void FileDialog::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("invalidate"), &FileDialog::invalidate);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "mode_overrides_title"), "set_mode_overrides_title", "is_mode_overriding_title");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Open File,Open Files,Open Folder,Open Any,Save"), "set_mode", "get_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "file_mode", PROPERTY_HINT_ENUM, "Open File,Open Files,Open Folder,Open Any,Save"), "set_file_mode", "get_file_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "filters"), "set_filters", "get_filters");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_hidden_files"), "set_show_hidden_files", "is_showing_hidden_files");
|
||||
@ -854,11 +858,11 @@ void FileDialog::_bind_methods() {
|
||||
ADD_SIGNAL(MethodInfo("files_selected", PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths")));
|
||||
ADD_SIGNAL(MethodInfo("dir_selected", PropertyInfo(Variant::STRING, "dir")));
|
||||
|
||||
BIND_ENUM_CONSTANT(MODE_OPEN_FILE);
|
||||
BIND_ENUM_CONSTANT(MODE_OPEN_FILES);
|
||||
BIND_ENUM_CONSTANT(MODE_OPEN_DIR);
|
||||
BIND_ENUM_CONSTANT(MODE_OPEN_ANY);
|
||||
BIND_ENUM_CONSTANT(MODE_SAVE_FILE);
|
||||
BIND_ENUM_CONSTANT(FILE_MODE_OPEN_FILE);
|
||||
BIND_ENUM_CONSTANT(FILE_MODE_OPEN_FILES);
|
||||
BIND_ENUM_CONSTANT(FILE_MODE_OPEN_DIR);
|
||||
BIND_ENUM_CONSTANT(FILE_MODE_OPEN_ANY);
|
||||
BIND_ENUM_CONSTANT(FILE_MODE_SAVE_FILE);
|
||||
|
||||
BIND_ENUM_CONSTANT(ACCESS_RESOURCES);
|
||||
BIND_ENUM_CONSTANT(ACCESS_USERDATA);
|
||||
@ -884,10 +888,11 @@ FileDialog::FileDialog() {
|
||||
|
||||
mode_overrides_title = true;
|
||||
|
||||
VBoxContainer *vbc = memnew(VBoxContainer);
|
||||
vbc = memnew(VBoxContainer);
|
||||
add_child(vbc);
|
||||
vbc->connect("theme_changed", callable_mp(this, &FileDialog::_theme_changed));
|
||||
|
||||
mode = MODE_SAVE_FILE;
|
||||
mode = FILE_MODE_SAVE_FILE;
|
||||
set_title(RTR("Save a File"));
|
||||
|
||||
HBoxContainer *hbc = memnew(HBoxContainer);
|
||||
@ -907,7 +912,7 @@ FileDialog::FileDialog() {
|
||||
|
||||
dir = memnew(LineEdit);
|
||||
hbc->add_child(dir);
|
||||
dir->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
dir->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
|
||||
refresh = memnew(ToolButton);
|
||||
refresh->set_tooltip(RTR("Refresh files."));
|
||||
@ -938,11 +943,11 @@ FileDialog::FileDialog() {
|
||||
file_box->add_child(memnew(Label(RTR("File:"))));
|
||||
file = memnew(LineEdit);
|
||||
file->set_stretch_ratio(4);
|
||||
file->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
file->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
file_box->add_child(file);
|
||||
filter = memnew(OptionButton);
|
||||
filter->set_stretch_ratio(3);
|
||||
filter->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
filter->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
filter->set_clip_text(true); // too many extensions overflows it
|
||||
file_box->add_child(filter);
|
||||
vbc->add_child(file_box);
|
||||
@ -961,7 +966,7 @@ FileDialog::FileDialog() {
|
||||
filter->connect("item_selected", callable_mp(this, &FileDialog::_filter_selected));
|
||||
|
||||
confirm_save = memnew(ConfirmationDialog);
|
||||
confirm_save->set_as_toplevel(true);
|
||||
// confirm_save->set_as_toplevel(true);
|
||||
add_child(confirm_save);
|
||||
|
||||
confirm_save->connect("confirmed", callable_mp(this, &FileDialog::_save_confirm_pressed));
|
||||
@ -1024,7 +1029,7 @@ LineEditFileChooser::LineEditFileChooser() {
|
||||
|
||||
line_edit = memnew(LineEdit);
|
||||
add_child(line_edit);
|
||||
line_edit->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
line_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
button = memnew(Button);
|
||||
button->set_text(" .. ");
|
||||
add_child(button);
|
||||
|
||||
@ -50,12 +50,12 @@ public:
|
||||
ACCESS_FILESYSTEM
|
||||
};
|
||||
|
||||
enum Mode {
|
||||
MODE_OPEN_FILE,
|
||||
MODE_OPEN_FILES,
|
||||
MODE_OPEN_DIR,
|
||||
MODE_OPEN_ANY,
|
||||
MODE_SAVE_FILE
|
||||
enum FileMode {
|
||||
FILE_MODE_OPEN_FILE,
|
||||
FILE_MODE_OPEN_FILES,
|
||||
FILE_MODE_OPEN_DIR,
|
||||
FILE_MODE_OPEN_ANY,
|
||||
FILE_MODE_SAVE_FILE
|
||||
};
|
||||
|
||||
typedef Ref<Texture2D> (*GetIconFunc)(const String &);
|
||||
@ -70,11 +70,12 @@ private:
|
||||
ConfirmationDialog *makedialog;
|
||||
LineEdit *makedirname;
|
||||
|
||||
VBoxContainer *vbc;
|
||||
Button *makedir;
|
||||
Access access;
|
||||
//Button *action;
|
||||
VBoxContainer *vbox;
|
||||
Mode mode;
|
||||
FileMode mode;
|
||||
LineEdit *dir;
|
||||
HBoxContainer *drives_container;
|
||||
HBoxContainer *shortcuts_container;
|
||||
@ -131,6 +132,8 @@ private:
|
||||
virtual void _post_popup();
|
||||
|
||||
protected:
|
||||
void _theme_changed();
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
//bind helpers
|
||||
@ -153,8 +156,8 @@ public:
|
||||
void set_mode_overrides_title(bool p_override);
|
||||
bool is_mode_overriding_title() const;
|
||||
|
||||
void set_mode(Mode p_mode);
|
||||
Mode get_mode() const;
|
||||
void set_file_mode(FileMode p_mode);
|
||||
FileMode get_file_mode() const;
|
||||
|
||||
VBoxContainer *get_vbox();
|
||||
LineEdit *get_line_edit() { return file; }
|
||||
@ -196,7 +199,7 @@ public:
|
||||
LineEditFileChooser();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(FileDialog::Mode);
|
||||
VARIANT_ENUM_CAST(FileDialog::FileMode);
|
||||
VARIANT_ENUM_CAST(FileDialog::Access);
|
||||
|
||||
#endif
|
||||
|
||||
@ -36,11 +36,25 @@ void Panel::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_DRAW) {
|
||||
|
||||
RID ci = get_canvas_item();
|
||||
Ref<StyleBox> style = get_stylebox("panel");
|
||||
Ref<StyleBox> style = mode == MODE_BACKGROUND ? get_stylebox("panel") : get_stylebox("panel_fg");
|
||||
style->draw(ci, Rect2(Point2(), get_size()));
|
||||
}
|
||||
}
|
||||
|
||||
void Panel::set_mode(Mode p_mode) {
|
||||
mode = p_mode;
|
||||
update();
|
||||
}
|
||||
Panel::Mode Panel::get_mode() const {
|
||||
return mode;
|
||||
}
|
||||
|
||||
void Panel::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_mode", "mode"), &Panel::set_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_mode"), &Panel::get_mode);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Background,Foreground"), "set_mode", "get_mode");
|
||||
}
|
||||
Panel::Panel() {
|
||||
// Has visible stylebox, so stop by default.
|
||||
set_mouse_filter(MOUSE_FILTER_STOP);
|
||||
|
||||
@ -37,12 +37,26 @@ class Panel : public Control {
|
||||
|
||||
GDCLASS(Panel, Control);
|
||||
|
||||
public:
|
||||
enum Mode {
|
||||
MODE_BACKGROUND,
|
||||
MODE_FOREGROUND
|
||||
};
|
||||
|
||||
private:
|
||||
Mode mode = MODE_BACKGROUND;
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_mode(Mode p_mode);
|
||||
Mode get_mode() const;
|
||||
|
||||
Panel();
|
||||
~Panel();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(Panel::Mode)
|
||||
#endif
|
||||
|
||||
@ -132,17 +132,17 @@ void Popup::popup_centered_clamped(const Size2 &p_size, float p_fallback_ratio)
|
||||
popup_size.x = MIN(window_size.x * p_fallback_ratio, popup_size.x);
|
||||
popup_size.y = MIN(window_size.y * p_fallback_ratio, popup_size.y);
|
||||
|
||||
popup_centered(popup_size);
|
||||
popup_centered_size(popup_size);
|
||||
}
|
||||
|
||||
void Popup::popup_centered_minsize(const Size2 &p_minsize) {
|
||||
|
||||
set_custom_minimum_size(p_minsize);
|
||||
_fix_size();
|
||||
popup_centered();
|
||||
popup_centered_size();
|
||||
}
|
||||
|
||||
void Popup::popup_centered(const Size2 &p_size) {
|
||||
void Popup::popup_centered_size(const Size2 &p_size) {
|
||||
|
||||
Rect2 rect;
|
||||
Size2 window_size = get_viewport_rect().size;
|
||||
@ -208,7 +208,7 @@ bool Popup::is_exclusive() const {
|
||||
void Popup::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_as_minsize"), &Popup::set_as_minsize);
|
||||
ClassDB::bind_method(D_METHOD("popup_centered", "size"), &Popup::popup_centered, DEFVAL(Size2()));
|
||||
ClassDB::bind_method(D_METHOD("popup_centered_size", "size"), &Popup::popup_centered_size, DEFVAL(Size2()));
|
||||
ClassDB::bind_method(D_METHOD("popup_centered_ratio", "ratio"), &Popup::popup_centered_ratio, DEFVAL(0.75));
|
||||
ClassDB::bind_method(D_METHOD("popup_centered_minsize", "minsize"), &Popup::popup_centered_minsize, DEFVAL(Size2()));
|
||||
ClassDB::bind_method(D_METHOD("popup_centered_clamped", "size", "fallback_ratio"), &Popup::popup_centered_clamped, DEFVAL(Size2()), DEFVAL(0.75));
|
||||
|
||||
@ -61,7 +61,7 @@ public:
|
||||
bool is_exclusive() const;
|
||||
|
||||
void popup_centered_ratio(float p_screen_ratio = 0.75);
|
||||
void popup_centered(const Size2 &p_size = Size2());
|
||||
void popup_centered_size(const Size2 &p_size = Size2());
|
||||
void popup_centered_minsize(const Size2 &p_minsize = Size2());
|
||||
void set_as_minsize();
|
||||
void popup_centered_clamped(const Size2 &p_size = Size2(), float p_fallback_ratio = 0.75);
|
||||
|
||||
@ -2952,6 +2952,7 @@ void Node::_bind_methods() {
|
||||
BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT);
|
||||
BIND_CONSTANT(NOTIFICATION_WM_CLOSE_REQUEST);
|
||||
BIND_CONSTANT(NOTIFICATION_WM_GO_BACK_REQUEST);
|
||||
BIND_CONSTANT(NOTIFICATION_WM_SIZE_CHANGED);
|
||||
BIND_CONSTANT(NOTIFICATION_OS_MEMORY_WARNING);
|
||||
BIND_CONSTANT(NOTIFICATION_TRANSLATION_CHANGED);
|
||||
BIND_CONSTANT(NOTIFICATION_WM_ABOUT);
|
||||
|
||||
@ -251,6 +251,7 @@ public:
|
||||
NOTIFICATION_WM_FOCUS_OUT = 1005,
|
||||
NOTIFICATION_WM_CLOSE_REQUEST = 1006,
|
||||
NOTIFICATION_WM_GO_BACK_REQUEST = 1007,
|
||||
NOTIFICATION_WM_SIZE_CHANGED = 1008,
|
||||
|
||||
NOTIFICATION_OS_MEMORY_WARNING = MainLoop::NOTIFICATION_OS_MEMORY_WARNING,
|
||||
NOTIFICATION_TRANSLATION_CHANGED = MainLoop::NOTIFICATION_TRANSLATION_CHANGED,
|
||||
|
||||
@ -32,8 +32,9 @@
|
||||
|
||||
#include "core/debugger/engine_debugger.h"
|
||||
#include "core/os/keyboard.h"
|
||||
#include "scene/gui/control.h"
|
||||
#include "scene/resources/dynamic_font.h"
|
||||
|
||||
#include "scene/scene_string_names.h"
|
||||
void Window::set_title(const String &p_title) {
|
||||
title = p_title;
|
||||
if (window_id == DisplayServer::INVALID_WINDOW_ID)
|
||||
@ -73,7 +74,7 @@ Point2i Window::get_position() const {
|
||||
|
||||
void Window::set_size(const Size2i &p_size) {
|
||||
size = p_size;
|
||||
if (window_id == DisplayServer::INVALID_WINDOW_ID) {
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
DisplayServer::get_singleton()->window_set_size(p_size, window_id);
|
||||
}
|
||||
_update_size();
|
||||
@ -255,12 +256,14 @@ void Window::_clear_window() {
|
||||
}
|
||||
|
||||
_update_from_window();
|
||||
print_line("deleting window bye");
|
||||
DisplayServer::get_singleton()->delete_sub_window(window_id);
|
||||
window_id = DisplayServer::INVALID_WINDOW_ID;
|
||||
_update_size();
|
||||
}
|
||||
|
||||
void Window::_resize_callback(const Size2i &p_callback) {
|
||||
|
||||
size = p_callback;
|
||||
_update_size();
|
||||
}
|
||||
@ -289,14 +292,20 @@ void Window::_event_callback(DisplayServer::WindowEvent p_event) {
|
||||
emit_signal("mouse_exited");
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EVENT_FOCUS_IN: {
|
||||
focused = true;
|
||||
_propagate_window_notification(this, NOTIFICATION_WM_FOCUS_IN);
|
||||
emit_signal("focus_entered");
|
||||
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EVENT_FOCUS_OUT: {
|
||||
focused = false;
|
||||
_propagate_window_notification(this, NOTIFICATION_WM_FOCUS_OUT);
|
||||
emit_signal("focus_exited");
|
||||
} break;
|
||||
case DisplayServer::WINDOW_EVENT_CLOSE_REQUEST: {
|
||||
if (exclusive_child != nullptr) {
|
||||
break; //has an exclusive child, can't get events until child is closed
|
||||
}
|
||||
_propagate_window_notification(this, NOTIFICATION_WM_CLOSE_REQUEST);
|
||||
emit_signal("close_requested");
|
||||
} break;
|
||||
@ -307,29 +316,46 @@ void Window::_event_callback(DisplayServer::WindowEvent p_event) {
|
||||
}
|
||||
}
|
||||
|
||||
void Window::show() {
|
||||
set_visible(true);
|
||||
}
|
||||
void Window::hide() {
|
||||
set_visible(false);
|
||||
}
|
||||
|
||||
void Window::set_visible(bool p_visible) {
|
||||
|
||||
if (visible == p_visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
visible = p_visible;
|
||||
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_MSG(get_parent() == nullptr, "Can't change visibility of main window.");
|
||||
|
||||
bool subwindow = get_parent() && get_parent()->get_viewport()->is_embedding_subwindows();
|
||||
|
||||
visible = p_visible;
|
||||
|
||||
if (!subwindow) {
|
||||
if (p_visible && window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
if (!p_visible && window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
_clear_window();
|
||||
}
|
||||
if (!p_visible && window_id == DisplayServer::INVALID_WINDOW_ID) {
|
||||
if (p_visible && window_id == DisplayServer::INVALID_WINDOW_ID) {
|
||||
_make_window();
|
||||
_update_window_callbacks();
|
||||
}
|
||||
} else {
|
||||
_update_size();
|
||||
}
|
||||
|
||||
if (!visible) {
|
||||
focused = false;
|
||||
}
|
||||
notification(NOTIFICATION_VISIBILITY_CHANGED);
|
||||
emit_signal(SceneStringNames::get_singleton()->visibility_changed);
|
||||
}
|
||||
|
||||
void Window::_clear_transient() {
|
||||
@ -338,6 +364,9 @@ void Window::_clear_transient() {
|
||||
DisplayServer::get_singleton()->window_set_transient(window_id, DisplayServer::INVALID_WINDOW_ID);
|
||||
}
|
||||
transient_parent->transient_children.erase(this);
|
||||
if (transient_parent->exclusive_child == this) {
|
||||
transient_parent->exclusive_child = nullptr;
|
||||
}
|
||||
transient_parent = nullptr;
|
||||
}
|
||||
}
|
||||
@ -365,6 +394,13 @@ void Window::_make_transient() {
|
||||
if (window) {
|
||||
transient_parent = window;
|
||||
window->transient_children.insert(this);
|
||||
if (exclusive) {
|
||||
if (transient_parent->exclusive_child == nullptr) {
|
||||
transient_parent->exclusive_child = this;
|
||||
} else if (transient_parent->exclusive_child != this) {
|
||||
ERR_PRINT("Making child transient exclusive, but parent has another exclusive child");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//see if we can make transient
|
||||
@ -394,6 +430,30 @@ bool Window::is_transient() const {
|
||||
return transient;
|
||||
}
|
||||
|
||||
void Window::set_exclusive(bool p_exclusive) {
|
||||
|
||||
if (exclusive == p_exclusive) {
|
||||
return;
|
||||
}
|
||||
|
||||
exclusive = p_exclusive;
|
||||
|
||||
if (transient_parent) {
|
||||
if (p_exclusive) {
|
||||
ERR_FAIL_COND_MSG(transient_parent->exclusive_child && transient_parent->exclusive_child != this, "Transient parent has another exclusive child.");
|
||||
transient_parent->exclusive_child = nullptr;
|
||||
} else {
|
||||
if (transient_parent->exclusive_child == this) {
|
||||
transient_parent->exclusive_child = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::is_exclusive() const {
|
||||
return exclusive;
|
||||
}
|
||||
|
||||
bool Window::is_visible() const {
|
||||
return visible;
|
||||
}
|
||||
@ -524,6 +584,8 @@ void Window::_update_size() {
|
||||
DynamicFont::update_oversampling();
|
||||
}
|
||||
}
|
||||
|
||||
notification(NOTIFICATION_WM_SIZE_CHANGED);
|
||||
}
|
||||
|
||||
void Window::_update_window_callbacks() {
|
||||
@ -541,20 +603,34 @@ void Window::_notification(int p_what) {
|
||||
} else {
|
||||
if (get_parent() == nullptr) {
|
||||
//it's the root window!
|
||||
visible = true; //always visible
|
||||
window_id = DisplayServer::MAIN_WINDOW_ID;
|
||||
_update_from_window();
|
||||
_update_size();
|
||||
_update_window_callbacks();
|
||||
} else {
|
||||
//create
|
||||
_make_window();
|
||||
_update_window_callbacks();
|
||||
if (visible) {
|
||||
_make_window();
|
||||
_update_window_callbacks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (transient) {
|
||||
_make_transient();
|
||||
}
|
||||
if (visible) {
|
||||
notification(NOTIFICATION_VISIBILITY_CHANGED);
|
||||
emit_signal(SceneStringNames::get_singleton()->visibility_changed);
|
||||
}
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_READY) {
|
||||
|
||||
if (wrap_controls) {
|
||||
_update_child_controls();
|
||||
}
|
||||
}
|
||||
|
||||
if (p_what == NOTIFICATION_EXIT_TREE) {
|
||||
@ -572,7 +648,7 @@ void Window::_notification(int p_what) {
|
||||
_clear_window();
|
||||
}
|
||||
} else {
|
||||
_update_size();
|
||||
_update_size(); //called by clear and make, which does not happen here
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -619,6 +695,58 @@ DisplayServer::WindowID Window::get_window_id() const {
|
||||
return window_id;
|
||||
}
|
||||
|
||||
void Window::set_wrap_controls(bool p_enable) {
|
||||
wrap_controls = p_enable;
|
||||
if (wrap_controls) {
|
||||
child_controls_changed();
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::is_wrapping_controls() const {
|
||||
return wrap_controls;
|
||||
}
|
||||
|
||||
Size2 Window::_get_contents_minimum_size() const {
|
||||
Size2 max;
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
Control *c = Object::cast_to<Control>(get_child(i));
|
||||
if (c) {
|
||||
Point2i pos = c->get_position();
|
||||
Size2i min = c->get_combined_minimum_size();
|
||||
|
||||
max.x = MAX(pos.x + min.x, max.x);
|
||||
max.y = MAX(pos.y + min.y, max.y);
|
||||
}
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
void Window::_update_child_controls() {
|
||||
|
||||
Size2 max = _get_contents_minimum_size();
|
||||
|
||||
Size2 new_size(MAX(max.x, size.x), MAX(max.y, size.y));
|
||||
|
||||
if (new_size != size) {
|
||||
set_size(new_size);
|
||||
}
|
||||
set_min_size(max);
|
||||
updating_child_controls = false;
|
||||
}
|
||||
void Window::child_controls_changed() {
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (updating_child_controls) {
|
||||
return;
|
||||
}
|
||||
|
||||
updating_child_controls = true;
|
||||
call_deferred("_update_child_controls");
|
||||
}
|
||||
|
||||
void Window::_window_input(const Ref<InputEvent> &p_ev) {
|
||||
|
||||
if (Engine::get_singleton()->is_editor_hint() && (Object::cast_to<InputEventJoypadButton>(p_ev.ptr()) || Object::cast_to<InputEventJoypadMotion>(*p_ev)))
|
||||
@ -632,6 +760,11 @@ void Window::_window_input(const Ref<InputEvent> &p_ev) {
|
||||
}
|
||||
}
|
||||
|
||||
if (exclusive_child != nullptr) {
|
||||
exclusive_child->grab_focus();
|
||||
return; //has an exclusive child, can't get events until child is closed
|
||||
}
|
||||
emit_signal(SceneStringNames::get_singleton()->window_input, p_ev);
|
||||
input(p_ev);
|
||||
if (!is_input_handled()) {
|
||||
unhandled_input(p_ev);
|
||||
@ -644,6 +777,208 @@ void Window::_window_drop_files(const Vector<String> &p_files) {
|
||||
emit_signal("files_dropped", p_files);
|
||||
}
|
||||
|
||||
Viewport *Window::get_parent_viewport() const {
|
||||
|
||||
if (get_parent()) {
|
||||
return get_parent()->get_viewport();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Window *Window::get_parent_visible_window() const {
|
||||
|
||||
Viewport *vp = get_parent_viewport();
|
||||
Window *window = nullptr;
|
||||
while (vp) {
|
||||
window = Object::cast_to<Window>(vp);
|
||||
if (window && window->visible) {
|
||||
break;
|
||||
}
|
||||
if (!vp->get_parent()) {
|
||||
break;
|
||||
}
|
||||
|
||||
vp = vp->get_parent()->get_viewport();
|
||||
}
|
||||
return window;
|
||||
}
|
||||
|
||||
void Window::popup_on_parent(const Rect2 &p_parent_rect) {
|
||||
|
||||
ERR_FAIL_COND(!is_inside_tree());
|
||||
ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window.");
|
||||
|
||||
if (!is_embedded()) {
|
||||
Window *window = get_parent_visible_window();
|
||||
|
||||
if (!window) {
|
||||
popup(p_parent_rect);
|
||||
} else {
|
||||
popup(Rect2(window->get_position() + p_parent_rect.position, p_parent_rect.size));
|
||||
}
|
||||
} else {
|
||||
popup(p_parent_rect);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::popup_centered_clamped(const Size2 &p_size, float p_fallback_ratio) {
|
||||
|
||||
ERR_FAIL_COND(!is_inside_tree());
|
||||
ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window.");
|
||||
|
||||
Rect2 parent_rect;
|
||||
|
||||
if (is_embedded()) {
|
||||
parent_rect = get_parent_viewport()->get_visible_rect();
|
||||
} else {
|
||||
DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id();
|
||||
int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id);
|
||||
parent_rect.position = DisplayServer::get_singleton()->screen_get_position(parent_screen);
|
||||
parent_rect.size = DisplayServer::get_singleton()->screen_get_size(parent_screen);
|
||||
}
|
||||
|
||||
Vector2 size_ratio = parent_rect.size * p_fallback_ratio;
|
||||
|
||||
Rect2 popup_rect;
|
||||
popup_rect.size = Vector2(MIN(size_ratio.x, p_size.x), MIN(size_ratio.y, p_size.y));
|
||||
popup_rect.position = (parent_rect.size - popup_rect.size) / 2;
|
||||
|
||||
popup(popup_rect);
|
||||
}
|
||||
|
||||
void Window::popup_centered(const Size2 &p_minsize) {
|
||||
ERR_FAIL_COND(!is_inside_tree());
|
||||
ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window.");
|
||||
|
||||
Rect2 parent_rect;
|
||||
|
||||
if (is_embedded()) {
|
||||
parent_rect = get_parent_viewport()->get_visible_rect();
|
||||
} else {
|
||||
DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id();
|
||||
int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id);
|
||||
parent_rect.position = DisplayServer::get_singleton()->screen_get_position(parent_screen);
|
||||
parent_rect.size = DisplayServer::get_singleton()->screen_get_size(parent_screen);
|
||||
}
|
||||
|
||||
Rect2 popup_rect;
|
||||
if (p_minsize == Size2()) {
|
||||
popup_rect.size = _get_contents_minimum_size();
|
||||
} else {
|
||||
popup_rect.size = p_minsize;
|
||||
}
|
||||
popup_rect.position = (parent_rect.size - popup_rect.size) / 2;
|
||||
|
||||
popup(popup_rect);
|
||||
}
|
||||
|
||||
void Window::popup_centered_ratio(float p_ratio) {
|
||||
|
||||
ERR_FAIL_COND(!is_inside_tree());
|
||||
ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window.");
|
||||
|
||||
Rect2 parent_rect;
|
||||
|
||||
if (is_embedded()) {
|
||||
parent_rect = get_parent_viewport()->get_visible_rect();
|
||||
} else {
|
||||
DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id();
|
||||
int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id);
|
||||
parent_rect.position = DisplayServer::get_singleton()->screen_get_position(parent_screen);
|
||||
parent_rect.size = DisplayServer::get_singleton()->screen_get_size(parent_screen);
|
||||
}
|
||||
|
||||
Rect2 popup_rect;
|
||||
popup_rect.size = parent_rect.size * p_ratio;
|
||||
popup_rect.position = (parent_rect.size - popup_rect.size) / 2;
|
||||
|
||||
popup(popup_rect);
|
||||
}
|
||||
|
||||
void Window::popup(const Rect2 &p_screen_rect) {
|
||||
if (p_screen_rect != Rect2()) {
|
||||
set_position(p_screen_rect.position);
|
||||
set_size(p_screen_rect.size);
|
||||
}
|
||||
|
||||
set_transient(true);
|
||||
set_visible(true);
|
||||
_post_popup();
|
||||
notification(NOTIFICATION_POST_POPUP);
|
||||
}
|
||||
|
||||
void Window::grab_focus() {
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
DisplayServer::get_singleton()->window_move_to_foreground(window_id);
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::has_focus() const {
|
||||
return focused;
|
||||
}
|
||||
|
||||
void Window::add_child_notify(Node *p_child) {
|
||||
|
||||
Control *child_c = Object::cast_to<Control>(p_child);
|
||||
|
||||
if (child_c && child_c->data.theme.is_null() && (theme_owner || theme_owner_window)) {
|
||||
Control::_propagate_theme_changed(child_c, theme_owner, theme_owner_window); //need to propagate here, since many controls may require setting up stuff
|
||||
}
|
||||
|
||||
Window *child_w = Object::cast_to<Window>(p_child);
|
||||
|
||||
if (child_w && child_w->theme.is_null() && (theme_owner || theme_owner_window)) {
|
||||
Control::_propagate_theme_changed(child_w, theme_owner, theme_owner_window); //need to propagate here, since many controls may require setting up stuff
|
||||
}
|
||||
}
|
||||
|
||||
void Window::remove_child_notify(Node *p_child) {
|
||||
|
||||
Control *child_c = Object::cast_to<Control>(p_child);
|
||||
|
||||
if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) {
|
||||
Control::_propagate_theme_changed(child_c, NULL, NULL);
|
||||
}
|
||||
|
||||
Window *child_w = Object::cast_to<Window>(p_child);
|
||||
|
||||
if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) {
|
||||
Control::_propagate_theme_changed(child_w, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::set_theme(const Ref<Theme> &p_theme) {
|
||||
|
||||
if (theme == p_theme)
|
||||
return;
|
||||
|
||||
theme = p_theme;
|
||||
|
||||
if (!p_theme.is_null()) {
|
||||
|
||||
theme_owner = nullptr;
|
||||
theme_owner_window = this;
|
||||
Control::_propagate_theme_changed(this, nullptr, this);
|
||||
} else {
|
||||
|
||||
Control *parent_c = cast_to<Control>(get_parent());
|
||||
if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) {
|
||||
Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window);
|
||||
} else {
|
||||
Window *parent_w = cast_to<Window>(get_parent());
|
||||
if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) {
|
||||
Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window);
|
||||
} else {
|
||||
Control::_propagate_theme_changed(this, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ref<Theme> Window::get_theme() const {
|
||||
return theme;
|
||||
}
|
||||
|
||||
void Window::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_title", "title"), &Window::set_title);
|
||||
@ -681,10 +1016,18 @@ void Window::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_visible", "visible"), &Window::set_visible);
|
||||
ClassDB::bind_method(D_METHOD("is_visible"), &Window::is_visible);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("hide"), &Window::hide);
|
||||
ClassDB::bind_method(D_METHOD("show"), &Window::show);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_transient", "transient"), &Window::set_transient);
|
||||
ClassDB::bind_method(D_METHOD("is_transient"), &Window::is_transient);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_exclusive", "exclusive"), &Window::set_exclusive);
|
||||
ClassDB::bind_method(D_METHOD("is_exclusive"), &Window::is_exclusive);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("can_draw"), &Window::is_transient);
|
||||
ClassDB::bind_method(D_METHOD("has_focus"), &Window::has_focus);
|
||||
ClassDB::bind_method(D_METHOD("grab_focus"), &Window::grab_focus);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_ime_active"), &Window::set_ime_active);
|
||||
ClassDB::bind_method(D_METHOD("set_ime_position"), &Window::set_ime_position);
|
||||
@ -703,6 +1046,15 @@ void Window::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_use_font_oversampling", "enable"), &Window::set_use_font_oversampling);
|
||||
ClassDB::bind_method(D_METHOD("is_using_font_oversampling"), &Window::is_using_font_oversampling);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_wrap_controls", "enable"), &Window::set_wrap_controls);
|
||||
ClassDB::bind_method(D_METHOD("is_wrapping_controls"), &Window::is_wrapping_controls);
|
||||
ClassDB::bind_method(D_METHOD("child_controls_changed"), &Window::child_controls_changed);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_update_child_controls"), &Window::_update_child_controls);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Window::set_theme);
|
||||
ClassDB::bind_method(D_METHOD("get_theme"), &Window::get_theme);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "position"), "set_position", "get_position");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size");
|
||||
@ -710,7 +1062,9 @@ void Window::_bind_methods() {
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_screen"), "set_current_screen", "get_current_screen");
|
||||
ADD_GROUP("Flags", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "wrap_controls"), "set_wrap_controls", "is_wrapping_controls");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transient"), "set_transient", "is_transient");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclusive"), "set_exclusive", "is_exclusive");
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "unresizable"), "set_flag", "get_flag", FLAG_RESIZE_DISABLED);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "borderless"), "set_flag", "get_flag", FLAG_BORDERLESS);
|
||||
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "always_on_top"), "set_flag", "get_flag", FLAG_ALWAYS_ON_TOP);
|
||||
@ -722,7 +1076,10 @@ void Window::_bind_methods() {
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "content_scale_size"), "set_content_scale_size", "get_content_scale_size");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_mode", PROPERTY_HINT_ENUM, "Disabled,Object,Pixels"), "set_content_scale_mode", "get_content_scale_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_aspect", PROPERTY_HINT_ENUM, "Ignore,Keep,KeepWidth,KeepHeight,Expand"), "set_content_scale_aspect", "get_content_scale_aspect");
|
||||
ADD_GROUP("Theme", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme");
|
||||
|
||||
ADD_SIGNAL(MethodInfo("window_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
|
||||
ADD_SIGNAL(MethodInfo("files_dropped"));
|
||||
ADD_SIGNAL(MethodInfo("mouse_entered"));
|
||||
ADD_SIGNAL(MethodInfo("mouse_exited"));
|
||||
@ -730,6 +1087,9 @@ void Window::_bind_methods() {
|
||||
ADD_SIGNAL(MethodInfo("focus_exited"));
|
||||
ADD_SIGNAL(MethodInfo("close_requested"));
|
||||
ADD_SIGNAL(MethodInfo("go_back_requested"));
|
||||
ADD_SIGNAL(MethodInfo("visibility_changed"));
|
||||
|
||||
BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED);
|
||||
}
|
||||
|
||||
Window::Window() {
|
||||
|
||||
@ -32,8 +32,10 @@
|
||||
#define WINDOW_H
|
||||
|
||||
#include "scene/main/viewport.h"
|
||||
#include "scene/resources/theme.h"
|
||||
#include "servers/display_server.h"
|
||||
|
||||
class Control;
|
||||
class Window : public Viewport {
|
||||
GDCLASS(Window, Viewport)
|
||||
public:
|
||||
@ -83,9 +85,15 @@ private:
|
||||
mutable Mode mode = MODE_WINDOWED;
|
||||
mutable bool flags[FLAG_MAX];
|
||||
bool visible = true;
|
||||
bool focused = false;
|
||||
|
||||
bool use_font_oversampling = false;
|
||||
bool transient = false;
|
||||
bool exclusive = false;
|
||||
bool wrap_controls = false;
|
||||
bool updating_child_controls = false;
|
||||
|
||||
void _update_child_controls();
|
||||
|
||||
Size2i content_scale_size;
|
||||
ContentScaleMode content_scale_mode;
|
||||
@ -114,13 +122,31 @@ private:
|
||||
void _clear_transient();
|
||||
void _make_transient();
|
||||
Window *transient_parent = nullptr;
|
||||
Window *exclusive_child = nullptr;
|
||||
Set<Window *> transient_children;
|
||||
|
||||
friend class Control;
|
||||
Ref<Theme> theme;
|
||||
Control *theme_owner = nullptr;
|
||||
Window *theme_owner_window = nullptr;
|
||||
|
||||
protected:
|
||||
virtual void _post_popup() {}
|
||||
virtual Size2 _get_contents_minimum_size() const;
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
|
||||
virtual void add_child_notify(Node *p_child);
|
||||
virtual void remove_child_notify(Node *p_child);
|
||||
|
||||
public:
|
||||
enum {
|
||||
|
||||
NOTIFICATION_VISIBILITY_CHANGED = 30,
|
||||
NOTIFICATION_POST_POPUP = 31,
|
||||
NOTIFICATION_THEME_CHANGED = 32,
|
||||
};
|
||||
|
||||
void set_title(const String &p_title);
|
||||
String get_title() const;
|
||||
|
||||
@ -155,9 +181,15 @@ public:
|
||||
void set_visible(bool p_visible);
|
||||
bool is_visible() const;
|
||||
|
||||
void show();
|
||||
void hide();
|
||||
|
||||
void set_transient(bool p_transient);
|
||||
bool is_transient() const;
|
||||
|
||||
void set_exclusive(bool p_exclusive);
|
||||
bool is_exclusive() const;
|
||||
|
||||
bool can_draw() const;
|
||||
|
||||
void set_ime_active(bool p_active);
|
||||
@ -176,6 +208,25 @@ public:
|
||||
|
||||
void set_use_font_oversampling(bool p_oversampling);
|
||||
bool is_using_font_oversampling() const;
|
||||
|
||||
void set_wrap_controls(bool p_enable);
|
||||
bool is_wrapping_controls() const;
|
||||
void child_controls_changed();
|
||||
|
||||
Window *get_parent_visible_window() const;
|
||||
Viewport *get_parent_viewport() const;
|
||||
void popup(const Rect2 &p_rect = Rect2());
|
||||
void popup_on_parent(const Rect2 &p_parent_rect);
|
||||
void popup_centered_ratio(float p_ratio = 0.8);
|
||||
void popup_centered(const Size2 &p_minsize = Size2());
|
||||
void popup_centered_clamped(const Size2 &p_size = Size2(), float p_fallback_ratio = 0.75);
|
||||
|
||||
void set_theme(const Ref<Theme> &p_theme);
|
||||
Ref<Theme> get_theme() const;
|
||||
|
||||
void grab_focus();
|
||||
bool has_focus() const;
|
||||
|
||||
Window();
|
||||
~Window();
|
||||
};
|
||||
|
||||
@ -350,8 +350,7 @@ void register_scene_types() {
|
||||
ClassDB::register_class<RichTextLabel>();
|
||||
ClassDB::register_class<RichTextEffect>();
|
||||
ClassDB::register_class<CharFXTransform>();
|
||||
ClassDB::register_class<PopupDialog>();
|
||||
ClassDB::register_class<WindowDialog>();
|
||||
;
|
||||
ClassDB::register_class<AcceptDialog>();
|
||||
ClassDB::register_class<ConfirmationDialog>();
|
||||
ClassDB::register_class<MarginContainer>();
|
||||
|
||||
@ -188,6 +188,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
|
||||
// Panel
|
||||
|
||||
theme->set_stylebox("panel", "Panel", make_stylebox(panel_bg_png, 0, 0, 0, 0));
|
||||
theme->set_stylebox("panel_fg", "Panel", make_stylebox(panel_bg_png, 0, 0, 0, 0));
|
||||
|
||||
// Focus
|
||||
|
||||
@ -523,17 +524,18 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
|
||||
|
||||
// WindowDialog
|
||||
|
||||
theme->set_stylebox("panel", "WindowDialog", sb_expand(make_stylebox(popup_window_png, 10, 26, 10, 8), 8, 24, 8, 6));
|
||||
theme->set_constant("scaleborder_size", "WindowDialog", 4 * scale);
|
||||
theme->set_stylebox("panel", "AcceptDialog", default_style);
|
||||
theme->set_stylebox("window_panel", "AcceptDialog", sb_expand(make_stylebox(popup_window_png, 10, 26, 10, 8), 8, 24, 8, 6));
|
||||
theme->set_constant("scaleborder_size", "AcceptDialog", 4 * scale);
|
||||
|
||||
theme->set_font("title_font", "WindowDialog", large_font);
|
||||
theme->set_color("title_color", "WindowDialog", Color(0, 0, 0));
|
||||
theme->set_constant("title_height", "WindowDialog", 20 * scale);
|
||||
theme->set_font("title_font", "AcceptDialog", large_font);
|
||||
theme->set_color("title_color", "AcceptDialog", Color(0, 0, 0));
|
||||
theme->set_constant("title_height", "AcceptDialog", 20 * scale);
|
||||
|
||||
theme->set_icon("close", "WindowDialog", make_icon(close_png));
|
||||
theme->set_icon("close_highlight", "WindowDialog", make_icon(close_hl_png));
|
||||
theme->set_constant("close_h_ofs", "WindowDialog", 18 * scale);
|
||||
theme->set_constant("close_v_ofs", "WindowDialog", 18 * scale);
|
||||
theme->set_icon("close", "AcceptDialog", make_icon(close_png));
|
||||
theme->set_icon("close_highlight", "AcceptDialog", make_icon(close_hl_png));
|
||||
theme->set_constant("close_h_ofs", "AcceptDialog", 18 * scale);
|
||||
theme->set_constant("close_v_ofs", "AcceptDialog", 18 * scale);
|
||||
|
||||
// File Dialog
|
||||
|
||||
|
||||
@ -195,8 +195,10 @@ SceneStringNames::SceneStringNames() {
|
||||
|
||||
_window_group = StaticCString::create("_window_group");
|
||||
_window_input = StaticCString::create("_window_input");
|
||||
window_input = StaticCString::create("window_input");
|
||||
_window_unhandled_input = StaticCString::create("_window_unhandled_input");
|
||||
|
||||
theme_changed = StaticCString::create("theme_changed");
|
||||
parameters_base_path = "parameters/";
|
||||
|
||||
tracks_changed = "tracks_changed";
|
||||
|
||||
@ -204,6 +204,9 @@ public:
|
||||
StringName _window_group;
|
||||
StringName _window_input;
|
||||
StringName _window_unhandled_input;
|
||||
StringName window_input;
|
||||
|
||||
StringName theme_changed;
|
||||
|
||||
enum {
|
||||
MAX_MATERIALS = 32
|
||||
|
||||
Reference in New Issue
Block a user