Added close button to tab. Added 4 display policies for this close button (show always, show never, show active tab only, show hover). Set the scene tabs in editor to follow the hover policy.
This commit is contained in:
parent
c2e2f2e0ae
commit
17fbd20673
4 changed files with 280 additions and 6 deletions
|
@ -64,6 +64,15 @@ Size2 Tabs::get_minimum_size() const {
|
|||
ms.width+=bms.width;
|
||||
ms.height=MAX(bms.height+tab_bg->get_minimum_size().height,ms.height);
|
||||
}
|
||||
|
||||
if (tabs[i].close_button.is_valid()) {
|
||||
Ref<Texture> cb=tabs[i].close_button;
|
||||
Size2 bms = cb->get_size()+get_stylebox("button")->get_minimum_size();
|
||||
bms.width+=get_constant("hseparation");
|
||||
|
||||
ms.width+=bms.width;
|
||||
ms.height=MAX(bms.height+tab_bg->get_minimum_size().height,ms.height);
|
||||
}
|
||||
}
|
||||
|
||||
return ms;
|
||||
|
@ -77,22 +86,48 @@ void Tabs::_input_event(const InputEvent& p_event) {
|
|||
|
||||
Point2 pos( p_event.mouse_motion.x, p_event.mouse_motion.y );
|
||||
|
||||
int hover=-1;
|
||||
int hover_buttons=-1;
|
||||
hover=-1;
|
||||
for(int i=0;i<tabs.size();i++) {
|
||||
|
||||
// test hovering tab to display close button if policy says so
|
||||
if (cb_displaypolicy == SHOW_HOVER) {
|
||||
int ofs=tabs[i].ofs_cache;
|
||||
int size = tabs[i].ofs_cache;
|
||||
if (pos.x >=tabs[i].ofs_cache && pos.x<tabs[i].ofs_cache+tabs[i].size_cache) {
|
||||
hover=i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// test hovering right button and close button
|
||||
if (tabs[i].rb_rect.has_point(pos)) {
|
||||
hover=i;
|
||||
rb_hover=i;
|
||||
hover_buttons = i;
|
||||
break;
|
||||
}
|
||||
else if (tabs[i].cb_rect.has_point(pos)) {
|
||||
cb_hover=i;
|
||||
hover_buttons = i;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (hover!=rb_hover) {
|
||||
rb_hover=hover;
|
||||
update();
|
||||
if (hover_buttons == -1) { // no hover
|
||||
rb_hover= hover_buttons;
|
||||
cb_hover= hover_buttons;
|
||||
}
|
||||
update();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (rb_pressing && p_event.type==InputEvent::MOUSE_BUTTON &&
|
||||
!p_event.mouse_button.pressed &&
|
||||
p_event.mouse_button.button_index==BUTTON_LEFT) {
|
||||
|
@ -106,6 +141,20 @@ void Tabs::_input_event(const InputEvent& p_event) {
|
|||
update();
|
||||
}
|
||||
|
||||
if (cb_pressing && p_event.type==InputEvent::MOUSE_BUTTON &&
|
||||
!p_event.mouse_button.pressed &&
|
||||
p_event.mouse_button.button_index==BUTTON_LEFT) {
|
||||
|
||||
if (cb_hover!=-1) {
|
||||
//pressed
|
||||
emit_signal("tab_close",cb_hover);
|
||||
}
|
||||
|
||||
cb_pressing=false;
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
if (p_event.type==InputEvent::MOUSE_BUTTON &&
|
||||
p_event.mouse_button.pressed &&
|
||||
p_event.mouse_button.button_index==BUTTON_LEFT) {
|
||||
|
@ -122,6 +171,12 @@ void Tabs::_input_event(const InputEvent& p_event) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (tabs[i].cb_rect.has_point(pos)) {
|
||||
cb_pressing=true;
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
int ofs=tabs[i].ofs_cache;
|
||||
int size = tabs[i].ofs_cache;
|
||||
if (pos.x >=tabs[i].ofs_cache && pos.x<tabs[i].ofs_cache+tabs[i].size_cache) {
|
||||
|
@ -148,6 +203,8 @@ void Tabs::_notification(int p_what) {
|
|||
|
||||
case NOTIFICATION_MOUSE_EXIT: {
|
||||
rb_hover=-1;
|
||||
cb_hover=-1;
|
||||
hover=-1;
|
||||
update();
|
||||
} break;
|
||||
case NOTIFICATION_DRAW: {
|
||||
|
@ -186,7 +243,7 @@ void Tabs::_notification(int p_what) {
|
|||
|
||||
String s = tabs[i].text;
|
||||
int lsize=0;
|
||||
int slen=font->get_string_size(s).width;;
|
||||
int slen=font->get_string_size(s).width;
|
||||
lsize+=slen;
|
||||
|
||||
Ref<Texture> icon;
|
||||
|
@ -211,6 +268,56 @@ void Tabs::_notification(int p_what) {
|
|||
|
||||
}
|
||||
|
||||
// Close button
|
||||
switch (cb_displaypolicy) {
|
||||
case SHOW_ALWAYS: {
|
||||
if (tabs[i].close_button.is_valid()) {
|
||||
Ref<StyleBox> style = get_stylebox("button");
|
||||
Ref<Texture> rb=tabs[i].close_button;
|
||||
|
||||
lsize+=get_constant("hseparation");
|
||||
lsize+=style->get_margin(MARGIN_LEFT);
|
||||
lsize+=rb->get_width();
|
||||
lsize+=style->get_margin(MARGIN_RIGHT);
|
||||
|
||||
}
|
||||
} break;
|
||||
case SHOW_ACTIVE_ONLY: {
|
||||
if (i==current) {
|
||||
if (tabs[i].close_button.is_valid()) {
|
||||
Ref<StyleBox> style = get_stylebox("button");
|
||||
Ref<Texture> rb=tabs[i].close_button;
|
||||
|
||||
lsize+=get_constant("hseparation");
|
||||
lsize+=style->get_margin(MARGIN_LEFT);
|
||||
lsize+=rb->get_width();
|
||||
lsize+=style->get_margin(MARGIN_RIGHT);
|
||||
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case SHOW_HOVER: {
|
||||
if (i==current || i==hover) {
|
||||
if (tabs[i].close_button.is_valid()) {
|
||||
Ref<StyleBox> style = get_stylebox("button");
|
||||
Ref<Texture> rb=tabs[i].close_button;
|
||||
|
||||
lsize+=get_constant("hseparation");
|
||||
lsize+=style->get_margin(MARGIN_LEFT);
|
||||
lsize+=rb->get_width();
|
||||
lsize+=style->get_margin(MARGIN_RIGHT);
|
||||
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case SHOW_NEVER: // by default, never show close button
|
||||
default: {
|
||||
// do nothing
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Ref<StyleBox> sb;
|
||||
int va;
|
||||
Color col;
|
||||
|
@ -273,6 +380,103 @@ void Tabs::_notification(int p_what) {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Close button
|
||||
switch (cb_displaypolicy) {
|
||||
case SHOW_ALWAYS: {
|
||||
if (tabs[i].close_button.is_valid()) {
|
||||
Ref<StyleBox> style = get_stylebox("button");
|
||||
Ref<Texture> cb=tabs[i].close_button;
|
||||
|
||||
w+=get_constant("hseparation");
|
||||
|
||||
Rect2 cb_rect;
|
||||
cb_rect.size=style->get_minimum_size()+cb->get_size();
|
||||
cb_rect.pos.x=w;
|
||||
cb_rect.pos.y=sb->get_margin(MARGIN_TOP)+((sb_rect.size.y-sb_ms.y)-(cb_rect.size.y))/2;
|
||||
|
||||
if (cb_hover==i) {
|
||||
if (cb_pressing)
|
||||
get_stylebox("button_pressed")->draw(ci,cb_rect);
|
||||
else
|
||||
style->draw(ci,cb_rect);
|
||||
}
|
||||
|
||||
w+=style->get_margin(MARGIN_LEFT);
|
||||
|
||||
cb->draw(ci,Point2i( w,cb_rect.pos.y+style->get_margin(MARGIN_TOP) ));
|
||||
w+=cb->get_width();
|
||||
w+=style->get_margin(MARGIN_RIGHT);
|
||||
tabs[i].cb_rect=cb_rect;
|
||||
}
|
||||
} break;
|
||||
case SHOW_ACTIVE_ONLY: {
|
||||
if (current==i) {
|
||||
if (tabs[i].close_button.is_valid()) {
|
||||
Ref<StyleBox> style = get_stylebox("button");
|
||||
Ref<Texture> cb=tabs[i].close_button;
|
||||
|
||||
w+=get_constant("hseparation");
|
||||
|
||||
Rect2 cb_rect;
|
||||
cb_rect.size=style->get_minimum_size()+cb->get_size();
|
||||
cb_rect.pos.x=w;
|
||||
cb_rect.pos.y=sb->get_margin(MARGIN_TOP)+((sb_rect.size.y-sb_ms.y)-(cb_rect.size.y))/2;
|
||||
|
||||
if (cb_hover==i) {
|
||||
if (cb_pressing)
|
||||
get_stylebox("button_pressed")->draw(ci,cb_rect);
|
||||
else
|
||||
style->draw(ci,cb_rect);
|
||||
}
|
||||
|
||||
w+=style->get_margin(MARGIN_LEFT);
|
||||
|
||||
cb->draw(ci,Point2i( w,cb_rect.pos.y+style->get_margin(MARGIN_TOP) ));
|
||||
w+=cb->get_width();
|
||||
w+=style->get_margin(MARGIN_RIGHT);
|
||||
tabs[i].cb_rect=cb_rect;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case SHOW_HOVER: {
|
||||
if (current==i || hover==i) {
|
||||
if (tabs[i].close_button.is_valid()) {
|
||||
Ref<StyleBox> style = get_stylebox("button");
|
||||
Ref<Texture> cb=tabs[i].close_button;
|
||||
|
||||
w+=get_constant("hseparation");
|
||||
|
||||
Rect2 cb_rect;
|
||||
cb_rect.size=style->get_minimum_size()+cb->get_size();
|
||||
cb_rect.pos.x=w;
|
||||
cb_rect.pos.y=sb->get_margin(MARGIN_TOP)+((sb_rect.size.y-sb_ms.y)-(cb_rect.size.y))/2;
|
||||
|
||||
if (cb_hover==i) {
|
||||
if (cb_pressing)
|
||||
get_stylebox("button_pressed")->draw(ci,cb_rect);
|
||||
else
|
||||
style->draw(ci,cb_rect);
|
||||
}
|
||||
|
||||
w+=style->get_margin(MARGIN_LEFT);
|
||||
|
||||
cb->draw(ci,Point2i( w,cb_rect.pos.y+style->get_margin(MARGIN_TOP) ));
|
||||
w+=cb->get_width();
|
||||
w+=style->get_margin(MARGIN_RIGHT);
|
||||
tabs[i].cb_rect=cb_rect;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case SHOW_NEVER:
|
||||
default: {
|
||||
// show nothing
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
w+=sb->get_margin(MARGIN_RIGHT);
|
||||
|
||||
tabs[i].size_cache=w-tabs[i].ofs_cache;
|
||||
|
@ -358,11 +562,29 @@ Ref<Texture> Tabs::get_tab_right_button(int p_tab) const{
|
|||
|
||||
}
|
||||
|
||||
void Tabs::set_tab_close_button(int p_tab, const Ref<Texture>& p_close_button) {
|
||||
ERR_FAIL_INDEX(p_tab, tabs.size());
|
||||
tabs[p_tab].close_button=p_close_button;
|
||||
update();
|
||||
minimum_size_changed();
|
||||
}
|
||||
|
||||
|
||||
Ref<Texture> Tabs::get_tab_close_button(int p_tab) const{
|
||||
|
||||
ERR_FAIL_INDEX_V(p_tab,tabs.size(),Ref<Texture>());
|
||||
return tabs[p_tab].close_button;
|
||||
|
||||
}
|
||||
|
||||
void Tabs::add_tab(const String& p_str,const Ref<Texture>& p_icon) {
|
||||
|
||||
Tab t;
|
||||
t.text=p_str;
|
||||
t.icon=p_icon;
|
||||
|
||||
t.close_button = get_icon("Close","EditorIcons");
|
||||
|
||||
tabs.push_back(t);
|
||||
|
||||
update();
|
||||
|
@ -394,6 +616,11 @@ void Tabs::remove_tab(int p_idx) {
|
|||
|
||||
}
|
||||
|
||||
void Tabs::set_tab_close_display_policy(CloseButtonDisplayPolicy p_cb_displaypolicy) {
|
||||
cb_displaypolicy = p_cb_displaypolicy;
|
||||
}
|
||||
|
||||
|
||||
void Tabs::set_tab_align(TabAlign p_align) {
|
||||
|
||||
tab_align=p_align;
|
||||
|
@ -423,14 +650,22 @@ void Tabs::_bind_methods() {
|
|||
|
||||
ADD_SIGNAL(MethodInfo("tab_changed",PropertyInfo(Variant::INT,"tab")));
|
||||
ADD_SIGNAL(MethodInfo("right_button_pressed",PropertyInfo(Variant::INT,"tab")));
|
||||
ADD_SIGNAL(MethodInfo("tab_close",PropertyInfo(Variant::INT,"tab")));
|
||||
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE,"-1,4096,1",PROPERTY_USAGE_EDITOR), _SCS("set_current_tab"), _SCS("get_current_tab") );
|
||||
|
||||
BIND_CONSTANT( ALIGN_LEFT );
|
||||
BIND_CONSTANT( ALIGN_CENTER );
|
||||
BIND_CONSTANT( ALIGN_RIGHT );
|
||||
|
||||
BIND_CONSTANT( SHOW_ACTIVE_ONLY );
|
||||
BIND_CONSTANT( SHOW_ALWAYS );
|
||||
BIND_CONSTANT( SHOW_HOVER );
|
||||
BIND_CONSTANT( SHOW_NEVER );
|
||||
}
|
||||
|
||||
|
||||
Tabs::Tabs() {
|
||||
|
||||
current=0;
|
||||
|
@ -438,4 +673,7 @@ Tabs::Tabs() {
|
|||
rb_hover=-1;
|
||||
rb_pressing=false;
|
||||
|
||||
cb_hover=-1;
|
||||
cb_pressing=false;
|
||||
cb_displaypolicy = SHOW_NEVER; // Default : no close button
|
||||
}
|
||||
|
|
|
@ -42,6 +42,14 @@ public:
|
|||
ALIGN_CENTER,
|
||||
ALIGN_RIGHT
|
||||
};
|
||||
|
||||
enum CloseButtonDisplayPolicy {
|
||||
|
||||
SHOW_ALWAYS,
|
||||
SHOW_ACTIVE_ONLY,
|
||||
SHOW_HOVER,
|
||||
SHOW_NEVER
|
||||
};
|
||||
private:
|
||||
|
||||
|
||||
|
@ -53,6 +61,8 @@ private:
|
|||
int size_cache;
|
||||
Ref<Texture> right_button;
|
||||
Rect2 rb_rect;
|
||||
Ref<Texture> close_button;
|
||||
Rect2 cb_rect;
|
||||
};
|
||||
|
||||
Vector<Tab> tabs;
|
||||
|
@ -63,6 +73,12 @@ private:
|
|||
int rb_hover;
|
||||
bool rb_pressing;
|
||||
|
||||
int cb_hover;
|
||||
bool cb_pressing;
|
||||
CloseButtonDisplayPolicy cb_displaypolicy;
|
||||
|
||||
int hover; // hovered tab
|
||||
|
||||
protected:
|
||||
|
||||
void _input_event(const InputEvent& p_event);
|
||||
|
@ -82,6 +98,10 @@ public:
|
|||
void set_tab_right_button(int p_tab,const Ref<Texture>& p_right_button);
|
||||
Ref<Texture> get_tab_right_button(int p_tab) const;
|
||||
|
||||
void set_tab_close_button(int p_tab, const Ref<Texture>& p_close_button);
|
||||
Ref<Texture> get_tab_close_button(int p_tab) const;
|
||||
void set_tab_close_display_policy(CloseButtonDisplayPolicy p_cb_displaypolicy);
|
||||
|
||||
void set_tab_align(TabAlign p_align);
|
||||
TabAlign get_tab_align() const;
|
||||
|
||||
|
|
|
@ -3620,6 +3620,7 @@ void EditorNode::_bind_methods() {
|
|||
ObjectTypeDB::bind_method("set_current_scene",&EditorNode::set_current_scene);
|
||||
ObjectTypeDB::bind_method("set_current_version",&EditorNode::set_current_version);
|
||||
ObjectTypeDB::bind_method("_scene_tab_changed",&EditorNode::_scene_tab_changed);
|
||||
ObjectTypeDB::bind_method("_scene_tab_closed",&EditorNode::_scene_tab_closed);
|
||||
ObjectTypeDB::bind_method("_scene_tab_script_edited",&EditorNode::_scene_tab_script_edited);
|
||||
ObjectTypeDB::bind_method("_set_main_scene_state",&EditorNode::_set_main_scene_state);
|
||||
ObjectTypeDB::bind_method("_update_scene_tabs",&EditorNode::_update_scene_tabs);
|
||||
|
@ -4072,6 +4073,17 @@ void EditorNode::_scene_tab_script_edited(int p_tab) {
|
|||
edit_resource(script);
|
||||
}
|
||||
|
||||
void EditorNode::_scene_tab_closed(int p_tab) {
|
||||
set_current_scene(p_tab);
|
||||
bool p_confirmed = true;
|
||||
if (unsaved_cache)
|
||||
p_confirmed = false;
|
||||
|
||||
_menu_option_confirm(FILE_CLOSE, p_confirmed);
|
||||
_update_scene_tabs();
|
||||
}
|
||||
|
||||
|
||||
void EditorNode::_scene_tab_changed(int p_tab) {
|
||||
|
||||
|
||||
|
@ -4225,8 +4237,10 @@ EditorNode::EditorNode() {
|
|||
scene_tabs=memnew( Tabs );
|
||||
scene_tabs->add_tab("unsaved");
|
||||
scene_tabs->set_tab_align(Tabs::ALIGN_CENTER);
|
||||
scene_tabs->set_tab_close_display_policy(Tabs::SHOW_HOVER);
|
||||
scene_tabs->connect("tab_changed",this,"_scene_tab_changed");
|
||||
scene_tabs->connect("right_button_pressed",this,"_scene_tab_script_edited");
|
||||
scene_tabs->connect("tab_close", this, "_scene_tab_closed");
|
||||
top_dark_vb->add_child(scene_tabs);
|
||||
//left
|
||||
left_l_hsplit = memnew( HSplitContainer );
|
||||
|
@ -4363,6 +4377,7 @@ EditorNode::EditorNode() {
|
|||
|
||||
main_editor_tabs = memnew( Tabs );
|
||||
main_editor_tabs->connect("tab_changed",this,"_editor_select");
|
||||
main_editor_tabs->set_tab_close_display_policy(Tabs::SHOW_NEVER);
|
||||
HBoxContainer *srth = memnew( HBoxContainer );
|
||||
srt->add_child( srth );
|
||||
Control *tec = memnew( Control );
|
||||
|
|
|
@ -473,6 +473,7 @@ class EditorNode : public Node {
|
|||
void _dock_split_dragged(int ofs);
|
||||
void _dock_popup_exit();
|
||||
void _scene_tab_changed(int p_tab);
|
||||
void _scene_tab_closed(int p_tab);
|
||||
void _scene_tab_script_edited(int p_tab);
|
||||
|
||||
Dictionary _get_main_scene_state();
|
||||
|
|
Loading…
Reference in a new issue