Browse Source

Properly fix tab scrolling, fixes #3128, fixes #3314

Juan Linietsky 9 years ago
parent
commit
c4cee22510
3 changed files with 96 additions and 246 deletions
  1. 87 236
      scene/gui/tabs.cpp
  2. 7 9
      scene/gui/tabs.h
  3. 2 1
      tools/editor/editor_node.cpp

+ 87 - 236
scene/gui/tabs.cpp

@@ -65,8 +65,8 @@ Size2 Tabs::get_minimum_size() const {
 			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;
+		if (cb_displaypolicy==CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy==CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i==current)) {
+			Ref<Texture> cb=get_icon("close");
 			Size2 bms = cb->get_size();//+get_stylebox("button")->get_minimum_size();
 			bms.width+=get_constant("hseparation");
 			ms.width+=bms.width;
@@ -108,14 +108,6 @@ void Tabs::_input_event(const InputEvent& p_event) {
 		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)) {
@@ -260,6 +252,7 @@ void Tabs::_notification(int p_what) {
 			Ref<Font> font = get_font("font");
 			Color color_fg = get_color("font_color_fg");
 			Color color_bg = get_color("font_color_bg");
+			Ref<Texture> close=get_icon("close");
 
 			int h = get_size().height;
 
@@ -278,37 +271,10 @@ void Tabs::_notification(int p_what) {
 
 				for(int i=0;i<tabs.size();i++) {
 
-
-					Ref<Texture> tex = tabs[i].icon;
-					if (tex.is_valid()) {
-						if (tabs[i].text!="")
-							mw+=get_constant("hseparation");
-
-					}
+					int sz = get_tab_width(i);
 
 					tabs[i].ofs_cache=mw;
-
-					mw+=font->get_string_size(tabs[i].text).width;
-					if (current==i)
-						mw+=tab_fg->get_minimum_size().width;
-					else
-						mw+=tab_bg->get_minimum_size().width;
-
-					if (tabs[i].right_button.is_valid()) {
-						Ref<Texture> rb=tabs[i].right_button;
-						Size2 bms = rb->get_size();//+get_stylebox("button")->get_minimum_size();
-						bms.width+=get_constant("hseparation");
-
-						mw+=bms.width;
-					}
-
-					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");
-						mw+=bms.width;
-					}
-
+					mw+=sz;
 
 
 				}
@@ -372,56 +338,15 @@ 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;
+				if (cb_displaypolicy==CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy==CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i==current)) {
 
+					lsize+=get_constant("hseparation");
+					//lsize+=style->get_margin(MARGIN_LEFT);
+					lsize+=close->get_width();
+					//lsize+=style->get_margin(MARGIN_RIGHT);
 				}
 
-
 				if (w+lsize > limit) {
 					max_drawn_tab=i-1;
 					missing_right=true;
@@ -495,100 +420,31 @@ void Tabs::_notification(int p_what) {
 				}
 
 
+				if (cb_displaypolicy==CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy==CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i==current)) {
 
+					Ref<StyleBox> style = get_stylebox("button");
+					Ref<Texture> cb=close;
 
-				// 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+=get_constant("hseparation");
 
-						//w+=style->get_margin(MARGIN_LEFT);
+					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;
 
-						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;
-						}
+					if (cb_hover==i) {
+						if (cb_pressing)
+							get_stylebox("button_pressed")->draw(ci,cb_rect);
+						else
+							style->draw(ci,cb_rect);
 					}
-				} break;
-				case SHOW_NEVER:
-				default: {
-					// show nothing
-				} break;
 
+					//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;
 				}
 
 				w+=sb->get_margin(MARGIN_RIGHT);
@@ -695,20 +551,6 @@ 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) {
 
@@ -716,8 +558,6 @@ void Tabs::add_tab(const String& p_str,const Ref<Texture>& p_icon) {
 	t.text=p_str;
 	t.icon=p_icon;
 
-	t.close_button = get_icon("close");
-
 	tabs.push_back(t);
 
 	update();
@@ -749,10 +589,6 @@ 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) {
 
@@ -765,6 +601,49 @@ Tabs::TabAlign Tabs::get_tab_align() const {
 	return tab_align;
 }
 
+int Tabs::get_tab_width(int p_idx) const {
+
+	ERR_FAIL_INDEX_V(p_idx,tabs.size(),0);
+
+	Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
+	Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
+	Ref<Font> font = get_font("font");
+	Ref<Texture> close=get_icon("close");
+
+	int x=0;
+
+	Ref<Texture> tex = tabs[p_idx].icon;
+	if (tex.is_valid()) {
+		if (tabs[p_idx].text!="")
+			x+=get_constant("hseparation");
+
+	}
+
+
+	x+=font->get_string_size(tabs[p_idx].text).width;
+	if (current==p_idx)
+		x+=tab_fg->get_minimum_size().width;
+	else
+		x+=tab_bg->get_minimum_size().width;
+
+	if (tabs[p_idx].right_button.is_valid()) {
+		print_line("has right");
+		Ref<Texture> rb=tabs[p_idx].right_button;
+		Size2 bms = rb->get_size();//+get_stylebox("button")->get_minimum_size();
+		bms.width+=get_constant("hseparation");
+
+		x+=bms.width;
+	}
+
+	if (cb_displaypolicy==CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy==CLOSE_BUTTON_SHOW_ACTIVE_ONLY && p_idx==current)) {
+
+		Size2 bms = close->get_size();//+get_stylebox("button")->get_minimum_size();
+		bms.width+=get_constant("hseparation");
+		x+=bms.width;
+	}
+
+	return x;
+}
 
 void Tabs::ensure_tab_visible(int p_idx) {
 
@@ -773,16 +652,12 @@ void Tabs::ensure_tab_visible(int p_idx) {
 
 	ERR_FAIL_INDEX(p_idx,tabs.size());
 
-	if (p_idx<offset) {
+	if (p_idx<=offset) {
 		offset=p_idx;
 		update();
 		return;
 	}
 
-	Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
-	Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
-	Ref<Font> font = get_font("font");
-
 	Ref<Texture> incr = get_icon("increment");
 	Ref<Texture> decr = get_icon("decrement");
 
@@ -796,49 +671,25 @@ void Tabs::ensure_tab_visible(int p_idx) {
 		if (i<offset)
 			continue;
 
-		Ref<Texture> tex = tabs[i].icon;
-		if (tex.is_valid()) {
-			if (tabs[i].text!="")
-				x+=get_constant("hseparation");
-
-		}
-
+		int sz = get_tab_width(i);
 		tabs[i].x_cache=x;
-
-		x+=font->get_string_size(tabs[i].text).width;
-		if (current==i)
-			x+=tab_fg->get_minimum_size().width;
-		else
-			x+=tab_bg->get_minimum_size().width;
-
-		if (tabs[i].right_button.is_valid()) {
-			Ref<Texture> rb=tabs[i].right_button;
-			Size2 bms = rb->get_size();//+get_stylebox("button")->get_minimum_size();
-			bms.width+=get_constant("hseparation");
-
-			x+=bms.width;
-		}
-
-		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");
-			x+=bms.width;
-		}
-
-		tabs[i].x_size_cache=x-tabs[i].x_cache;
-
-
+		tabs[i].x_size_cache=sz;
+		x+=sz;
 
 	}
 
-	while(offset<tabs.size() && ( (tabs[p_idx].x_cache + tabs[p_idx].x_size_cache) - tabs[offset].x_cache) < limit) {
+	while(offset<tabs.size() && ( (tabs[p_idx].x_cache + tabs[p_idx].x_size_cache) - tabs[offset].x_cache) > limit) {
 		offset++;
 	}
 
 	update();
 }
 
+void Tabs::set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy) {
+	cb_displaypolicy=p_policy;
+	update();
+}
+
 void Tabs::_bind_methods() {
 
 	ObjectTypeDB::bind_method(_MD("_input_event"),&Tabs::_input_event);
@@ -866,10 +717,10 @@ void Tabs::_bind_methods() {
 	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 );
+	BIND_CONSTANT( CLOSE_BUTTON_SHOW_ACTIVE_ONLY );
+	BIND_CONSTANT( CLOSE_BUTTON_SHOW_ALWAYS );
+	BIND_CONSTANT( CLOSE_BUTTON_SHOW_NEVER );
+
 }
 
 
@@ -883,7 +734,7 @@ Tabs::Tabs() {
 
 	cb_hover=-1;
 	cb_pressing=false;
-	cb_displaypolicy = SHOW_NEVER; // Default : no close button
+	cb_displaypolicy = CLOSE_BUTTON_SHOW_NEVER; // Default : no close button
 	offset=0;
 	max_drawn_tab=0;
 

+ 7 - 9
scene/gui/tabs.h

@@ -45,10 +45,9 @@ public:
 
 	enum CloseButtonDisplayPolicy {
 
-		SHOW_ALWAYS,
-		SHOW_ACTIVE_ONLY,
-		SHOW_HOVER,
-		SHOW_NEVER
+		CLOSE_BUTTON_SHOW_NEVER,
+		CLOSE_BUTTON_SHOW_ACTIVE_ONLY,
+		CLOSE_BUTTON_SHOW_ALWAYS,
 	};
 private:
 
@@ -64,7 +63,6 @@ private:
 
 		Ref<Texture> right_button;
 		Rect2 rb_rect;
-		Ref<Texture> close_button;
 		Rect2 cb_rect;
 
 	};
@@ -89,6 +87,8 @@ private:
 
 	int hover;	// hovered tab
 
+	int get_tab_width(int p_idx) const;
+
 protected:
 
 	void _input_event(const InputEvent& p_event);
@@ -108,13 +108,11 @@ 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;
 
+	void set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy);
+
 	int get_tab_count() const;
 	void set_current_tab(int p_current);
 	int get_current_tab() const;

+ 2 - 1
tools/editor/editor_node.cpp

@@ -143,6 +143,7 @@ void EditorNode::_update_scene_tabs() {
 	}
 
 	scene_tabs->set_current_tab(editor_data.get_edited_scene());
+	scene_tabs->ensure_tab_visible(editor_data.get_edited_scene());
 
 }
 
@@ -5055,7 +5056,7 @@ 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_ACTIVE_ONLY);
+	scene_tabs->set_tab_close_display_policy(Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY);
 	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");