diff options
author | RĂ©mi Verschelde <rverschelde@gmail.com> | 2017-03-02 07:57:26 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-02 07:57:26 +0100 |
commit | f592d1ebfc15a2c9123a502a3cc50267d89b7ef7 (patch) | |
tree | 3f07929e7b58cd5b30538540e7b2485a93f28bd1 /scene/gui/dialogs.cpp | |
parent | 68fe36ed26c82d58dd8dffb3c64fd8d3de9569ca (diff) | |
parent | e07aa5deb849fb4b28422e69f785c1537e1b7646 (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.cpp | 209 |
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() { |