summaryrefslogtreecommitdiff
path: root/scene/gui/dialogs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui/dialogs.cpp')
-rw-r--r--scene/gui/dialogs.cpp285
1 files changed, 209 insertions, 76 deletions
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index cc6fe7cae8..6d06f8c59c 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -33,76 +33,173 @@
void WindowDialog::_post_popup() {
- dragging=false; //just in case
+ drag_type = DRAG_NONE; // just in case
+}
+
+void WindowDialog::_fix_size() {
+
+ // Perhaps this should be called when the viewport resizes aswell or windows go out of bounds...
+
+ // Ensure the whole window is visible.
+ Point2i pos = get_global_pos();
+ 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 = panel->get_margin(MARGIN_TOP);
+ float left = panel->get_margin(MARGIN_LEFT);
+ float bottom = panel->get_margin(MARGIN_BOTTOM);
+ float right = panel->get_margin(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_pos(pos);
+
+ // Also resize the window to fit if a resize should be possible at all.
+ 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());
- int extra = get_constant("titlebar_height","WindowDialog");
- Rect2 r( Point2(), get_size() );
- r.pos.y-=extra;
- r.size.y+=extra;
- return r.has_point(p_point);
+ // Enlarge upwards for title bar.
+ int titlebar_height = get_constant("titlebar_height", "WindowDialog");
+ r.pos.y -= titlebar_height;
+ r.size.y += titlebar_height;
+ // Inflate by the resizable border thickness.
+ if (resizable) {
+ int scaleborder_size = get_constant("scaleborder_size", "WindowDialog");
+ r.pos.x -= scaleborder_size;
+ r.size.width += scaleborder_size * 2;
+ r.pos.y -= scaleborder_size;
+ r.size.height += scaleborder_size * 2;
+ }
+
+ return r.has_point(p_point);
}
void WindowDialog::_gui_input(const InputEvent& p_event) {
- if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==BUTTON_LEFT) {
-
- if (p_event.mouse_button.pressed && p_event.mouse_button.y < 0)
- dragging=true;
- else if (dragging && !p_event.mouse_button.pressed)
- dragging=false;
+ if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == BUTTON_LEFT) {
+
+ if (p_event.mouse_button.pressed) {
+ // Begin a possible dragging operation.
+ drag_type = _drag_hit_test(Point2(p_event.mouse_button.x, p_event.mouse_button.y));
+ if (drag_type != DRAG_NONE)
+ drag_offset = get_global_mouse_pos() - get_pos();
+ drag_offset_far = get_pos() + get_size() - get_global_mouse_pos();
+ } else if (drag_type != DRAG_NONE && !p_event.mouse_button.pressed) {
+ // End a dragging operation.
+ drag_type = DRAG_NONE;
+ }
}
-
- if (p_event.type == InputEvent::MOUSE_MOTION && dragging) {
-
- Point2 rel( p_event.mouse_motion.relative_x, p_event.mouse_motion.relative_y );
- Point2 pos = get_pos();
-
- pos+=rel;
-
- if (pos.y<0)
- pos.y=0;
-
- set_pos(pos);
+ if (p_event.type == InputEvent::MOUSE_MOTION) {
+
+ 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(p_event.mouse_button.x, p_event.mouse_button.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_pos();
+ global_pos.y = MAX(global_pos.y, 0); // Ensure title bar stays visible.
+
+ Rect2 rect = get_rect();
+ Size2 min_size = get_minimum_size();
+
+ if (drag_type == DRAG_MOVE) {
+ rect.pos = global_pos - drag_offset;
+ } else {
+ if (drag_type & DRAG_RESIZE_TOP) {
+ int bottom = rect.pos.y + rect.size.height;
+ int max_y = bottom - min_size.height;
+ rect.pos.y = MIN(global_pos.y - drag_offset.y, max_y);
+ rect.size.height = bottom - rect.pos.y;
+ } else if (drag_type & DRAG_RESIZE_BOTTOM) {
+ rect.size.height = global_pos.y - rect.pos.y + drag_offset_far.y;
+ }
+ if (drag_type & DRAG_RESIZE_LEFT) {
+ int right = rect.pos.x + rect.size.width;
+ int max_x = right - min_size.width;
+ rect.pos.x = MIN(global_pos.x - drag_offset.x, max_x);
+ rect.size.width = right - rect.pos.x;
+ } else if (drag_type & DRAG_RESIZE_RIGHT) {
+ rect.size.width = global_pos.x - rect.pos.x + drag_offset_far.x;
+ }
+ }
+
+ set_size(rect.size);
+ set_pos(rect.pos);
+ }
}
}
void WindowDialog::_notification(int p_what) {
- switch(p_what) {
-
+ switch (p_what) {
case NOTIFICATION_DRAW: {
- RID ci = get_canvas_item();
- Size2 s = get_size();
- Ref<StyleBox> st = get_stylebox("panel","WindowDialog");
- st->draw(ci,Rect2(Point2(),s));
- int th = get_constant("title_height","WindowDialog");
- Color tc = get_color("title_color","WindowDialog");
- Ref<Font> font = get_font("title_font","WindowDialog");
- int ofs = (s.width-font->get_string_size(title).width)/2;
- //int ofs = st->get_margin(MARGIN_LEFT);
- draw_string(font,Point2(ofs,-th+font->get_ascent()),title,tc,s.width - st->get_minimum_size().width);
+ RID canvas = get_canvas_item();
+ Size2 size = get_size();
+
+ Ref<StyleBox> panel = get_stylebox("panel", "WindowDialog");
+ panel->draw(canvas, Rect2(Point2(), size));
+ int title_height = get_constant("title_height", "WindowDialog");
+ Color title_color = get_color("title_color", "WindowDialog");
+ Ref<Font> font = get_font("title_font", "WindowDialog");
+ int ofs = (size.width - font->get_string_size(title).width) / 2;
+ draw_string(font, Point2(ofs, -title_height + font->get_ascent()), title, title_color, size.width - panel->get_minimum_size().width);
} 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_hilite", "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;
- 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_hilite","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") ));
-
+ 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;
}
-
}
void WindowDialog::_closed() {
@@ -111,11 +208,48 @@ void WindowDialog::_closed() {
hide();
}
+int WindowDialog::_drag_hit_test(const Point2& pos) const {
+ int drag_type = DRAG_NONE;
+
+ if (resizable) {
+ int titlebar_height = get_constant("titlebar_height", "WindowDialog");
+ int scaleborder_size = get_constant("scaleborder_size", "WindowDialog");
+
+ Rect2 rect = get_rect();
+
+ if (pos.y < (-titlebar_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) {
title=XL_MESSAGE(p_title);
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 {
@@ -127,11 +261,6 @@ Size2 WindowDialog::get_minimum_size() const {
}
-String WindowDialog::get_title() const {
-
- return title;
-}
-
TextureButton *WindowDialog::get_close_button() {
@@ -141,22 +270,26 @@ TextureButton *WindowDialog::get_close_button() {
void WindowDialog::_bind_methods() {
- ClassDB::bind_method( _MD("_gui_input"),&WindowDialog::_gui_input);
- ClassDB::bind_method( _MD("set_title","title"),&WindowDialog::set_title);
- ClassDB::bind_method( _MD("get_title"),&WindowDialog::get_title);
- ClassDB::bind_method( _MD("_closed"),&WindowDialog::_closed);
- ClassDB::bind_method( _MD("get_close_button:TextureButton"),&WindowDialog::get_close_button);
+ 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("_closed"),&WindowDialog::_closed);
+ ClassDB::bind_method( D_METHOD("get_close_button:TextureButton"),&WindowDialog::get_close_button);
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"window_title",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_DEFAULT_INTL),_SCS("set_title"),_SCS("get_title"));
+ 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() {
//title="Hello!";
- dragging=false;
- close_button = memnew( TextureButton );
+ drag_type = DRAG_NONE;
+ resizable = false;
+ close_button = memnew(TextureButton);
add_child(close_button);
- close_button->connect("pressed",this,"_closed");
+ close_button->connect("pressed", this, "_closed");
}
@@ -186,7 +319,7 @@ PopupDialog::~PopupDialog() {
}
-//
+// AcceptDialog
void AcceptDialog::_post_popup() {
@@ -201,7 +334,7 @@ void AcceptDialog::_notification(int p_what) {
if (p_what==NOTIFICATION_MODAL_CLOSE) {
cancel_pressed();
- } if (p_what==NOTIFICATION_RESIZED) {
+ } else if (p_what==NOTIFICATION_RESIZED) {
_update_child_rects();
}
@@ -272,7 +405,7 @@ void AcceptDialog::_update_child_rects() {
if (!c)
continue;
- if (c==hbc || c==label || c==get_close_button())
+ if (c==hbc || c==label || c==get_close_button() || c->is_set_as_toplevel())
continue;
c->set_pos(cpos);
@@ -299,7 +432,7 @@ Size2 AcceptDialog::get_minimum_size() const {
if (!c)
continue;
- if (c==hbc || c==label || c==const_cast<AcceptDialog*>(this)->get_close_button())
+ if (c==hbc || c==label || c==const_cast<AcceptDialog*>(this)->get_close_button() || c->is_set_as_toplevel())
continue;
Size2 cminsize = c->get_combined_minimum_size();
@@ -361,25 +494,25 @@ Button* AcceptDialog::add_cancel(const String &p_cancel) {
void AcceptDialog::_bind_methods() {
- ClassDB::bind_method(_MD("_ok"),&AcceptDialog::_ok_pressed);
- ClassDB::bind_method(_MD("get_ok"),&AcceptDialog::get_ok);
- ClassDB::bind_method(_MD("get_label"),&AcceptDialog::get_label);
- ClassDB::bind_method(_MD("set_hide_on_ok","enabled"),&AcceptDialog::set_hide_on_ok);
- ClassDB::bind_method(_MD("get_hide_on_ok"),&AcceptDialog::get_hide_on_ok);
- ClassDB::bind_method(_MD("add_button:Button","text","right","action"),&AcceptDialog::add_button,DEFVAL(false),DEFVAL(""));
- ClassDB::bind_method(_MD("add_cancel:Button","name"),&AcceptDialog::add_cancel);
- ClassDB::bind_method(_MD("_builtin_text_entered"),&AcceptDialog::_builtin_text_entered);
- ClassDB::bind_method(_MD("register_text_enter:LineEdit","line_edit"),&AcceptDialog::register_text_enter);
- ClassDB::bind_method(_MD("_custom_action"),&AcceptDialog::_custom_action);
- ClassDB::bind_method(_MD("set_text","text"),&AcceptDialog::set_text);
- ClassDB::bind_method(_MD("get_text"),&AcceptDialog::get_text);
+ ClassDB::bind_method(D_METHOD("_ok"),&AcceptDialog::_ok_pressed);
+ ClassDB::bind_method(D_METHOD("get_ok"),&AcceptDialog::get_ok);
+ ClassDB::bind_method(D_METHOD("get_label"),&AcceptDialog::get_label);
+ ClassDB::bind_method(D_METHOD("set_hide_on_ok","enabled"),&AcceptDialog::set_hide_on_ok);
+ ClassDB::bind_method(D_METHOD("get_hide_on_ok"),&AcceptDialog::get_hide_on_ok);
+ ClassDB::bind_method(D_METHOD("add_button:Button","text","right","action"),&AcceptDialog::add_button,DEFVAL(false),DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("add_cancel:Button","name"),&AcceptDialog::add_cancel);
+ ClassDB::bind_method(D_METHOD("_builtin_text_entered"),&AcceptDialog::_builtin_text_entered);
+ ClassDB::bind_method(D_METHOD("register_text_enter:LineEdit","line_edit"),&AcceptDialog::register_text_enter);
+ ClassDB::bind_method(D_METHOD("_custom_action"),&AcceptDialog::_custom_action);
+ ClassDB::bind_method(D_METHOD("set_text","text"),&AcceptDialog::set_text);
+ ClassDB::bind_method(D_METHOD("get_text"),&AcceptDialog::get_text);
ADD_SIGNAL( MethodInfo("confirmed") );
ADD_SIGNAL( MethodInfo("custom_action",PropertyInfo(Variant::STRING,"action")) );
ADD_GROUP("Dialog","dialog");
- ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"dialog_text",PROPERTY_HINT_MULTILINE_TEXT,"",PROPERTY_USAGE_DEFAULT_INTL),_SCS("set_text"),_SCS("get_text"));
- ADD_PROPERTY( PropertyInfo(Variant::BOOL, "dialog_hide_on_ok"),_SCS("set_hide_on_ok"),_SCS("get_hide_on_ok") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"dialog_text",PROPERTY_HINT_MULTILINE_TEXT,"",PROPERTY_USAGE_DEFAULT_INTL),"set_text","get_text");
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL, "dialog_hide_on_ok"),"set_hide_on_ok","get_hide_on_ok") ;
}
@@ -429,7 +562,7 @@ AcceptDialog::~AcceptDialog()
void ConfirmationDialog::_bind_methods() {
- ClassDB::bind_method(_MD("get_cancel:Button"),&ConfirmationDialog::get_cancel);
+ ClassDB::bind_method(D_METHOD("get_cancel:Button"),&ConfirmationDialog::get_cancel);
}
Button *ConfirmationDialog::get_cancel() {