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:
Julian Murgia - StraToN 2015-08-18 20:27:01 +02:00
parent c2e2f2e0ae
commit 17fbd20673
4 changed files with 280 additions and 6 deletions

View file

@ -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
}

View file

@ -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;

View file

@ -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 );

View file

@ -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();