Merge pull request #7628 from RayKoopa/gui_resizable_popups
Added functionality for resizable WindowDialogs
This commit is contained in:
commit
f592d1ebfc
3 changed files with 180 additions and 64 deletions
|
@ -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());
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
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.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.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) {
|
||||
|
||||
if (p_event.type == InputEvent::MOUSE_MOTION && dragging) {
|
||||
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.
|
||||
|
||||
Point2 rel( p_event.mouse_motion.relative_x, p_event.mouse_motion.relative_y );
|
||||
Point2 pos = get_pos();
|
||||
Rect2 rect = get_rect();
|
||||
Size2 min_size = get_minimum_size();
|
||||
|
||||
pos+=rel;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos.y<0)
|
||||
pos.y=0;
|
||||
|
||||
set_pos(pos);
|
||||
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() {
|
||||
|
|
|
@ -44,12 +44,26 @@ 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;
|
||||
bool dragging;
|
||||
int drag_type;
|
||||
Point2 drag_offset;
|
||||
Point2 drag_offset_far;
|
||||
bool resizable;
|
||||
|
||||
void _gui_input(const InputEvent& p_event);
|
||||
void _closed();
|
||||
int _drag_hit_test(const Point2& pos) const;
|
||||
|
||||
protected:
|
||||
virtual void _post_popup();
|
||||
|
||||
|
@ -63,6 +77,8 @@ public:
|
|||
|
||||
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;
|
||||
|
||||
|
|
|
@ -583,24 +583,19 @@ void fill_default_theme(Ref<Theme>& t, const Ref<Font> & default_font, const Ref
|
|||
|
||||
// WindowDialog
|
||||
|
||||
Ref<StyleBoxTexture> style_pp_win = sb_expand(make_stylebox( popup_window_png,10,30,10,8),8,26,8,4);
|
||||
/*for(int i=0;i<4;i++)
|
||||
style_pp_win->set_expand_margin_size((Margin)i,3);
|
||||
style_pp_win->set_expand_margin_size(MARGIN_TOP,26);*/
|
||||
Ref<StyleBoxTexture> style_pp_win = sb_expand(make_stylebox(popup_window_png, 10, 26, 10, 8), 8, 24, 8, 6);
|
||||
t->set_stylebox("panel", "WindowDialog", style_pp_win);
|
||||
t->set_constant("titlebar_height", "WindowDialog", 20 * scale);
|
||||
t->set_constant("scaleborder_size", "WindowDialog", 4);
|
||||
|
||||
t->set_stylebox("panel","WindowDialog", style_pp_win );
|
||||
t->set_font("title_font", "WindowDialog", large_font);
|
||||
t->set_color("title_color", "WindowDialog", Color(0, 0, 0));
|
||||
t->set_constant("title_height", "WindowDialog", 18 * scale);
|
||||
|
||||
t->set_icon("close","WindowDialog", make_icon( close_png ) );
|
||||
t->set_icon("close_hilite","WindowDialog", make_icon( close_hl_png ) );
|
||||
|
||||
t->set_font("title_font","WindowDialog", large_font );
|
||||
|
||||
t->set_color("title_color","WindowDialog", Color(0,0,0) );
|
||||
|
||||
t->set_constant("close_h_ofs","WindowDialog", 22 *scale);
|
||||
t->set_constant("close_v_ofs","WindowDialog", 20 *scale);
|
||||
t->set_constant("titlebar_height","WindowDialog", 18 *scale);
|
||||
t->set_constant("title_height","WindowDialog", 20 *scale);
|
||||
t->set_icon("close", "WindowDialog", make_icon(close_png));
|
||||
t->set_icon("close_hilite", "WindowDialog", make_icon(close_hl_png));
|
||||
t->set_constant("close_h_ofs", "WindowDialog", 18 * scale);
|
||||
t->set_constant("close_v_ofs", "WindowDialog", 18 * scale);
|
||||
|
||||
|
||||
// File Dialog
|
||||
|
|
Loading…
Reference in a new issue