← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/bug-1653460-panel-init-width into lp:widelands

 

GunChleoc has proposed merging lp:~widelands-dev/widelands/bug-1653460-panel-init-width into lp:widelands.

Commit message:
Fixed assertion failure in int UI::Panel::get_inner_h():

- Fixed bug with automatic column sizing for tables where the columns were already being resized before all of them were added.
- Allow getting inner width/height for panels that have their borders set but w/h == 0. Added assertions and fallbacks to set_size and set_desired_size to make sure that width/height will never be negative.
- Explicitly initialize all variables in ui_basic.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1653460 in widelands: "UI::Panel::get_inner_h() const: Assertion `tborder_ + bborder_ <= h_' failed."
  https://bugs.launchpad.net/widelands/+bug/1653460

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-1653460-panel-init-width/+merge/318358

The assertion in the bug should now be fixed for all panels containing tables:

* Fullscreen menus:

    - campaign_select
    - internet_lobby
    - launch_mpg
    - launch_spg
    - loadgame
    - mapselect
    - netsetup_lan

* In-game:
    - game_message_menu
    - game_summary
    - productionsitewindow
    - trainingsitewindow
    - tribal_encyclopedia

* Editor:
    - help
    - main_menu_load_map
    - main_menu_save_map

I don't know why this happened only sometimes and not all the time though.
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/bug-1653460-panel-init-width into lp:widelands.
=== modified file 'src/ui_basic/box.cc'
--- src/ui_basic/box.cc	2017-02-25 13:27:40 +0000
+++ src/ui_basic/box.cc	2017-02-27 14:05:30 +0000
@@ -98,7 +98,7 @@
 	int maxbreadth = mindesiredbreadth_;
 
 	for (uint32_t idx = 0; idx < items_.size(); ++idx) {
-		int depth, breadth;
+		int depth, breadth = 0;
 		get_item_desired_size(idx, &depth, &breadth);
 
 		totaldepth += depth;
@@ -137,7 +137,7 @@
 	int totaldepth = 0;
 
 	for (size_t idx = 0; idx < items_.size(); ++idx) {
-		int depth, unused;
+		int depth, unused = 0;
 		get_item_desired_size(idx, &depth, &unused);
 		totaldepth += depth;
 	}
@@ -221,7 +221,7 @@
 		totalbreadth -= Scrollbar::kSize;
 
 	for (uint32_t idx = 0; idx < items_.size(); ++idx) {
-		int depth, breadth;
+		int depth, breadth = 0;
 		get_item_size(idx, &depth, &breadth);
 
 		if (items_[idx].type == Item::ItemPanel) {
@@ -371,7 +371,7 @@
 
 	switch (it.type) {
 	case Item::ItemPanel: {
-		int32_t breadth, maxbreadth;
+		int32_t breadth, maxbreadth = 0;
 
 		if (orientation_ == Horizontal) {
 			breadth = it.u.panel.panel->get_inner_h();

=== modified file 'src/ui_basic/listselect.cc'
--- src/ui_basic/listselect.cc	2017-02-23 19:38:51 +0000
+++ src/ui_basic/listselect.cc	2017-02-27 14:05:30 +0000
@@ -69,10 +69,9 @@
 	scrollbar_.moved.connect(boost::bind(&BaseListselect::set_scrollpos, this, _1));
 
 	if (selection_mode_ == ListselectLayout::kShowCheck) {
-		int pic_h;
 		check_pic_ = g_gr->images().get("images/ui_basic/list_selected.png");
 		max_pic_width_ = check_pic_->width();
-		pic_h = check_pic_->height();
+		int pic_h = check_pic_->height();
 		if (pic_h > lineheight_)
 			lineheight_ = pic_h;
 	} else {

=== modified file 'src/ui_basic/multilineeditbox.cc'
--- src/ui_basic/multilineeditbox.cc	2017-02-23 17:58:25 +0000
+++ src/ui_basic/multilineeditbox.cc	2017-02-27 14:05:30 +0000
@@ -303,7 +303,7 @@
 			if (d_->cursor_pos < d_->text.size()) {
 				d_->refresh_ww();
 
-				uint32_t cursorline, cursorpos;
+				uint32_t cursorline, cursorpos = 0;
 				d_->ww.calc_wrapped_pos(d_->cursor_pos, cursorline, cursorpos);
 
 				if (cursorline + 1 < d_->ww.nrlines()) {
@@ -332,7 +332,7 @@
 			if (d_->cursor_pos > 0) {
 				d_->refresh_ww();
 
-				uint32_t cursorline, cursorpos;
+				uint32_t cursorline, cursorpos = 0;
 				d_->ww.calc_wrapped_pos(d_->cursor_pos, cursorline, cursorpos);
 
 				if (cursorline > 0) {
@@ -361,7 +361,7 @@
 			} else {
 				d_->refresh_ww();
 
-				uint32_t cursorline, cursorpos;
+				uint32_t cursorline, cursorpos = 0;
 				d_->ww.calc_wrapped_pos(d_->cursor_pos, cursorline, cursorpos);
 
 				d_->set_cursor_pos(d_->ww.line_offset(cursorline));
@@ -379,7 +379,7 @@
 			} else {
 				d_->refresh_ww();
 
-				uint32_t cursorline, cursorpos;
+				uint32_t cursorline, cursorpos = 0;
 				d_->ww.calc_wrapped_pos(d_->cursor_pos, cursorline, cursorpos);
 
 				if (cursorline + 1 < d_->ww.nrlines())
@@ -488,7 +488,7 @@
 void MultilineEditbox::Data::scroll_cursor_into_view() {
 	refresh_ww();
 
-	uint32_t cursorline, cursorpos;
+	uint32_t cursorline, cursorpos = 0;
 	ww.calc_wrapped_pos(cursor_pos, cursorline, cursorpos);
 
 	int32_t lineheight = textstyle.font->height();

=== modified file 'src/ui_basic/multilinetextarea.cc'
--- src/ui_basic/multilinetextarea.cc	2017-02-23 19:38:51 +0000
+++ src/ui_basic/multilinetextarea.cc	2017-02-27 14:05:30 +0000
@@ -79,7 +79,7 @@
  * and adjust scrollbar settings accordingly.
  */
 void MultilineTextarea::recompute() {
-	uint32_t height;
+	int height = 0;
 
 	// We wrap the text twice. We need to do this to account for the presence/absence of the
 	// scollbar.

=== modified file 'src/ui_basic/panel.cc'
--- src/ui_basic/panel.cc	2017-01-25 18:55:59 +0000
+++ src/ui_basic/panel.cc	2017-02-27 14:05:30 +0000
@@ -240,8 +240,12 @@
 	if (nw == w_ && nh == h_)
 		return;
 
-	w_ = nw;
-	h_ = nh;
+	assert(nw >= 0);
+	assert(nh >= 0);
+
+	// Make sure that we never get negative width/height in release builds.
+	w_ = std::max(0, nw);
+	h_ = std::max(0, nh);
 
 	if (parent_)
 		move_inside_parent();
@@ -282,9 +286,12 @@
 
 	assert(w < 3000);
 	assert(h < 3000);
+	assert(w >= 0);
+	assert(h >= 0);
 
-	desired_w_ = w;
-	desired_h_ = h;
+	// Make sure that we never get negative width/height in release builds.
+	desired_w_ = std::max(0, w);
+	desired_h_ = std::max(0, h);
 	if (!get_layout_toplevel() && parent_) {
 		parent_->update_desired_size();
 	} else {
@@ -351,6 +358,7 @@
  * Set the size of the inner area (total area minus border)
  */
 void Panel::set_inner_size(int const nw, int const nh) {
+	assert(nw >= 0 && nh >= 0);
 	set_size(nw + lborder_ + rborder_, nh + tborder_ + bborder_);
 }
 
@@ -366,6 +374,15 @@
 	bborder_ = b;
 }
 
+int Panel::get_inner_w() const {
+	assert(w_ == 0 || lborder_ + rborder_ <= w_);
+	return (w_ == 0 ? 0 : w_ - (lborder_ + rborder_));
+}
+int Panel::get_inner_h() const {
+	assert(h_ == 0 || tborder_ + bborder_ <= h_);
+	return (h_ == 0 ? 0 : h_ - (tborder_ + bborder_));
+}
+
 /**
  * Make this panel the top-most panel in the parent's Z-order.
  */

=== modified file 'src/ui_basic/panel.h'
--- src/ui_basic/panel.h	2017-01-25 18:55:59 +0000
+++ src/ui_basic/panel.h	2017-02-27 14:05:30 +0000
@@ -180,14 +180,8 @@
 		return bborder_;
 	}
 
-	int get_inner_w() const {
-		assert(lborder_ + rborder_ <= w_);
-		return w_ - (lborder_ + rborder_);
-	}
-	int get_inner_h() const {
-		assert(tborder_ + bborder_ <= h_);
-		return h_ - (tborder_ + bborder_);
-	}
+	int get_inner_w() const;
+	int get_inner_h() const;
 
 	const Panel* get_next_sibling() const {
 		return next_;

=== modified file 'src/ui_basic/scrollbar.cc'
--- src/ui_basic/scrollbar.cc	2017-01-25 18:55:59 +0000
+++ src/ui_basic/scrollbar.cc	2017-02-27 14:05:30 +0000
@@ -130,7 +130,7 @@
 }
 
 Scrollbar::Area Scrollbar::get_area_for_point(int32_t x, int32_t y) {
-	int32_t extent;
+	int32_t extent = 0;
 
 	// Out of panel
 	if (x < 0 || x >= static_cast<int32_t>(get_w()) || y < 0 || y >= static_cast<int32_t>(get_h()))

=== modified file 'src/ui_basic/table.cc'
--- src/ui_basic/table.cc	2017-02-26 11:57:15 +0000
+++ src/ui_basic/table.cc	2017-02-27 14:05:30 +0000
@@ -108,7 +108,7 @@
 	//  If there would be existing entries, they would not get the new column.
 	assert(size() == 0);
 
-	uint32_t complete_width = 0;
+	int complete_width = 0;
 	for (const Column& col : columns_) {
 		complete_width += col.width;
 	}
@@ -133,7 +133,6 @@
 			flexible_column_ = columns_.size() - 1;
 		}
 	}
-	layout();
 }
 
 void Table<void*>::set_column_title(uint8_t const col, const std::string& title) {
@@ -209,8 +208,7 @@
 	if (entries == 0) {
 		entries = size();
 	}
-	int tablewidth;
-	int tableheight;
+	int tablewidth, tableheight = 0;
 	get_desired_size(&tablewidth, &tableheight);
 	tableheight = headerheight_ + 2 + get_lineheight() * entries;
 	set_desired_size(tablewidth, tableheight);
@@ -606,15 +604,13 @@
 
 	// Find a column to resize
 	size_t resizeable_column = std::numeric_limits<size_t>::max();
-	if (flexible_column_ != std::numeric_limits<size_t>::max()) {
+	if (flexible_column_ < columns_.size()) {
 		resizeable_column = flexible_column_;
 	} else {
 		// Use the widest column
-		int all_columns_width = scrollbar_ && scrollbar_->is_enabled() ? scrollbar_->get_w() : 0;
 		uint32_t widest_width = columns_[resizeable_column].width;
 		for (size_t i = 1; i < columns_.size(); ++i) {
 			const uint32_t width = columns_[i].width;
-			all_columns_width += width;
 			if (width > widest_width) {
 				widest_width = width;
 				resizeable_column = i;
@@ -630,8 +626,9 @@
 		}
 		if (all_columns_width != get_w()) {
 			Column& column = columns_.at(resizeable_column);
-			column.width = column.width + get_w() - all_columns_width;
+			column.width = std::max(0, column.width + get_w() - all_columns_width);
 			column.btn->set_size(column.width, column.btn->get_h());
+
 			int offset = 0;
 			for (const auto& col : columns_) {
 				col.btn->set_pos(Vector2i(offset, col.btn->get_y()));

=== modified file 'src/ui_basic/table.h'
--- src/ui_basic/table.h	2017-02-26 11:57:15 +0000
+++ src/ui_basic/table.h	2017-02-27 14:05:30 +0000
@@ -184,6 +184,8 @@
 	void set_column_title(uint8_t col, const std::string& title);
 	void set_column_compare(uint8_t col, const CompareFn& fn);
 
+	void layout() override;
+
 	void clear();
 	void set_sort_column(uint8_t const col) {
 		assert(col < columns_.size());
@@ -280,11 +282,10 @@
 private:
 	bool default_compare_string(uint32_t column, uint32_t a, uint32_t b);
 	bool sort_helper(uint32_t a, uint32_t b);
-	void layout() override;
 
 	struct Column {
 		Button* btn;
-		uint32_t width;
+		int width;
 		Align alignment;
 		CompareFn compare;
 	};
@@ -293,8 +294,8 @@
 	static const int32_t ms_darken_value = -20;
 
 	Columns columns_;
-	uint32_t total_width_;
-	uint32_t headerheight_;
+	int total_width_;
+	const uint32_t headerheight_;
 	int32_t lineheight_;
 	const Image* button_background_;
 	Scrollbar* scrollbar_;

=== modified file 'src/ui_basic/tabpanel.cc'
--- src/ui_basic/tabpanel.cc	2017-02-23 19:38:51 +0000
+++ src/ui_basic/tabpanel.cc	2017-02-27 14:05:30 +0000
@@ -139,7 +139,7 @@
 	// size of contents
 	if (active_ < tabs_.size()) {
 		Panel* const panel = tabs_[active_]->panel;
-		int panelw, panelh;
+		int panelw, panelh = 0;
 
 		panel->get_desired_size(&panelw, &panelh);
 		// TODO(unknown):  the panel might be bigger -> add a scrollbar in that case

=== modified file 'src/ui_basic/textarea.cc'
--- src/ui_basic/textarea.cc	2017-02-23 19:38:51 +0000
+++ src/ui_basic/textarea.cc	2017-02-27 14:05:30 +0000
@@ -163,7 +163,7 @@
 	int32_t y = get_y();
 
 	update_desired_size();
-	int w, h;
+	int w, h = 0;
 	get_desired_size(&w, &h);
 
 	switch (align_) {

=== modified file 'src/ui_basic/window.cc'
--- src/ui_basic/window.cc	2017-02-24 10:21:37 +0000
+++ src/ui_basic/window.cc	2017-02-27 14:05:30 +0000
@@ -128,7 +128,7 @@
  */
 void Window::update_desired_size() {
 	if (center_panel_ && !is_minimal_) {
-		int innerw, innerh;
+		int innerw, innerh = 0;
 		center_panel_->get_desired_size(&innerw, &innerh);
 		set_desired_size(
 		   innerw + get_lborder() + get_rborder(), innerh + get_tborder() + get_bborder());

=== modified file 'src/ui_fsmenu/campaign_select.cc'
--- src/ui_fsmenu/campaign_select.cc	2017-02-26 11:57:15 +0000
+++ src/ui_fsmenu/campaign_select.cc	2017-02-27 14:05:30 +0000
@@ -358,6 +358,7 @@
 
 void FullscreenMenuCampaignMapSelect::layout() {
 	// TODO(GunChleoc): Implement when we have box layout for the details.
+	table_.layout();
 }
 
 std::string FullscreenMenuCampaignMapSelect::get_map() {

=== modified file 'src/ui_fsmenu/internet_lobby.cc'
--- src/ui_fsmenu/internet_lobby.cc	2017-02-23 19:38:51 +0000
+++ src/ui_fsmenu/internet_lobby.cc	2017-02-27 14:05:30 +0000
@@ -153,6 +153,7 @@
 
 void FullscreenMenuInternetLobby::layout() {
 	// TODO(GunChleoc): Box layout and then implement
+	clientsonline_list_.layout();
 }
 
 /// think function of the UI (main loop)

=== modified file 'src/ui_fsmenu/loadgame.cc'
--- src/ui_fsmenu/loadgame.cc	2017-02-26 11:57:15 +0000
+++ src/ui_fsmenu/loadgame.cc	2017-02-27 14:05:30 +0000
@@ -188,6 +188,7 @@
 		ta_mapname_.set_tooltip(_("The map that this game is based on"));
 		delete_.set_tooltip(_("Delete this game"));
 	}
+	set_thinks(false);
 	minimap_icon_.set_visible(false);
 
 	back_.sigclicked.connect(boost::bind(&FullscreenMenuLoadGame::clicked_back, boost::ref(*this)));
@@ -240,6 +241,7 @@
 
 void FullscreenMenuLoadGame::layout() {
 	// TODO(GunChleoc): Implement when we have box layout for the details.
+	table_.layout();
 }
 
 void FullscreenMenuLoadGame::think() {

=== modified file 'src/ui_fsmenu/netsetup_lan.cc'
--- src/ui_fsmenu/netsetup_lan.cc	2017-02-23 19:38:51 +0000
+++ src/ui_fsmenu/netsetup_lan.cc	2017-02-27 14:05:30 +0000
@@ -126,6 +126,7 @@
 
 void FullscreenMenuNetSetupLAN::layout() {
 	// TODO(GunChleoc): Box layout and then implement
+	opengames.layout();
 }
 
 void FullscreenMenuNetSetupLAN::think() {

=== modified file 'src/wui/game_message_menu.cc'
--- src/wui/game_message_menu.cc	2017-02-26 11:57:15 +0000
+++ src/wui/game_message_menu.cc	2017-02-27 14:05:30 +0000
@@ -152,6 +152,7 @@
 	   ColTimeSent, boost::bind(&GameMessageMenu::compare_time_sent, this, _1, _2));
 
 	list->set_sort_column(ColTimeSent);
+	list->layout();
 
 	set_can_focus(true);
 	focus();

=== modified file 'src/wui/game_summary.cc'
--- src/wui/game_summary.cc	2017-02-25 13:27:40 +0000
+++ src/wui/game_summary.cc	2017-02-27 14:05:30 +0000
@@ -208,6 +208,7 @@
 	if (!players_status.empty()) {
 		players_table_->select(current_player_position);
 	}
+	players_table_->layout();
 }
 
 void GameSummaryScreen::continue_clicked() {

=== modified file 'src/wui/maptable.cc'
--- src/wui/maptable.cc	2017-02-26 11:57:15 +0000
+++ src/wui/maptable.cc	2017-02-27 14:05:30 +0000
@@ -76,4 +76,5 @@
 		}
 	}
 	sort();
+	layout();
 }


References