summaryrefslogtreecommitdiff
path: root/scene/gui/dialogs.cpp
diff options
context:
space:
mode:
authorRĂ©mi Verschelde <rverschelde@gmail.com>2017-03-02 07:57:26 +0100
committerGitHub <noreply@github.com>2017-03-02 07:57:26 +0100
commitf592d1ebfc15a2c9123a502a3cc50267d89b7ef7 (patch)
tree3f07929e7b58cd5b30538540e7b2485a93f28bd1 /scene/gui/dialogs.cpp
parent68fe36ed26c82d58dd8dffb3c64fd8d3de9569ca (diff)
parente07aa5deb849fb4b28422e69f785c1537e1b7646 (diff)
Merge pull request #7628 from RayKoopa/gui_resizable_popups
Added functionality for resizable WindowDialogs
Diffstat (limited to 'scene/gui/dialogs.cpp')
-rw-r--r--scene/gui/dialogs.cpp209
1 files changed, 157 insertions, 52 deletions
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index e08d933e03..e889d1acd3 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -33,76 +33,145 @@
void WindowDialog::_post_popup() {
- dragging=false; //just in case
+ drag_type = DRAG_NONE; // just in case
}
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 +180,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 +233,6 @@ Size2 WindowDialog::get_minimum_size() const {
}
-String WindowDialog::get_title() const {
-
- return title;
-}
-
TextureButton *WindowDialog::get_close_button() {
@@ -144,19 +245,23 @@ 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("_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),"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 +291,7 @@ PopupDialog::~PopupDialog() {
}
-//
+// AcceptDialog
void AcceptDialog::_post_popup() {