Changeset - r20725:6aaae233211b
[Not reviewed]
master
0 1 0
zuu - 11 years ago 2013-09-13 21:01:19
zuu@openttd.org
(svn r25768) -Fix [FS#5617] (r25344): Story Book text elements that use font size modifiers (eg {BIG_FONT}) caused problem with content height calculation. Solution: switch to pixel based content height instead of computing all heights as multiples of line heights.
1 file changed with 37 insertions and 38 deletions:
0 comments (0 inline, 0 general)
src/story_gui.cpp
Show inline comments
 
@@ -174,13 +174,13 @@ protected:
 
			GetString(selected_generic_title, STR_STORY_BOOK_GENERIC_PAGE_ITEM, lastof(selected_generic_title));
 
		}
 

	
 
		this->story_page_elements.ForceRebuild();
 
		this->BuildStoryPageElementList();
 

	
 
		this->vscroll->SetCount(this->CountLines());
 
		this->vscroll->SetCount(this->GetContentHeight());
 
		this->SetWidgetDirty(WID_SB_SCROLLBAR);
 
		this->SetWidgetDirty(WID_SB_SEL_PAGE);
 
		this->SetWidgetDirty(WID_SB_PAGE_PANEL);
 
	}
 

	
 
	/**
 
@@ -265,30 +265,30 @@ protected:
 
	uint GetAvailablePageContentWidth()
 
	{
 
		return this->GetWidget<NWidgetCore>(WID_SB_PAGE_PANEL)->current_x - WD_FRAMETEXT_LEFT - WD_FRAMERECT_RIGHT;
 
	}
 

	
 
	/**
 
	 * Counts how many lines that are used by Date and Title
 
	 * Counts how many pixels of height that are used by Date and Title
 
	 * (excluding marginal after Title, as each body element has
 
	 * an empty row before the elment).
 
	 * @param max_width Available width to display content.
 
	 * @return the number of lines.
 
	 * @return the height in pixels.
 
	 */
 
	uint CountHeadLines(int max_width)
 
	uint GetHeadHeight(int max_width) const
 
	{
 
		StoryPage *page = this->GetSelPage();
 
		if (page == NULL) return 0;
 
		int num_lines = 0;
 
		int height = 0;
 

	
 
		/* Title lines */
 
		num_lines += 1; // Date always use exactly one line.
 
		height += FONT_HEIGHT_NORMAL; // Date always use exactly one line.
 
		SetDParamStr(0, page->title != NULL ? page->title : this->selected_generic_title);
 
		num_lines += GetStringLineCount(STR_STORY_BOOK_TITLE, max_width);
 
		height += GetStringHeight(STR_STORY_BOOK_TITLE, max_width);
 

	
 
		return num_lines;
 
		return height;
 
	}
 

	
 
	/**
 
	 * Decides which sprite to display for a given page element.
 
	 * @param pe The page element.
 
	 * @return The SpriteID of the sprite to display.
 
@@ -307,60 +307,59 @@ protected:
 
			default:
 
				NOT_REACHED();
 
		}
 
	}
 

	
 
	/**
 
	 * Count the number of lines used by a given page element.
 
	 * Get the height in pixels used by a page element.
 
	 * @param pe The story page element.
 
	 * @param max_width Available width to display content.
 
	 * @return the number of lines.
 
	 * @return the height in pixels.
 
	 */
 
	uint CountPageElementLines(const StoryPageElement &pe, int max_width)
 
	uint GetPageElementHeight(const StoryPageElement &pe, int max_width)
 
	{
 
		switch (pe.type) {
 
			case SPET_TEXT:
 
				SetDParamStr(0, pe.text);
 
				return GetStringLineCount(STR_BLACK_RAW_STRING, max_width);
 
				return GetStringHeight(STR_BLACK_RAW_STRING, max_width);
 
				break;
 

	
 
			case SPET_GOAL:
 
			case SPET_LOCATION: {
 
				Dimension sprite_dim = GetSpriteSize(GetPageElementSprite(pe));
 
				int line_height = FONT_HEIGHT_NORMAL;
 
				if (line_height == 0) return 1;
 
				return max((uint)1, sprite_dim.height / (uint)line_height);
 
				return sprite_dim.height;
 
				break;
 
			}
 
			default:
 
				NOT_REACHED();
 
		}
 
	}
 

	
 
	/**
 
	 * Count the number of lines in this window.
 
	 * @return the number of lines.
 
	 * Get the total height of the content displayed
 
	 * in this window.
 
	 * @return the height in pixels
 
	 */
 
	uint CountLines()
 
	uint GetContentHeight()
 
	{
 
		StoryPage *page = this->GetSelPage();
 
		if (page == NULL) return 0;
 
		int max_width = GetAvailablePageContentWidth();
 
		uint element_vertical_dist = FONT_HEIGHT_NORMAL;
 

	
 
		/* Head lines */
 
		int num_lines = CountHeadLines(max_width);
 
		/* Head */
 
		uint height = GetHeadHeight(max_width);
 

	
 
		/* Body lines */
 
		/* Body */
 
		for (const StoryPageElement **iter = this->story_page_elements.Begin(); iter != this->story_page_elements.End(); iter++) {
 
			const StoryPageElement *pe = *iter;
 
			num_lines += 1; // For the space between previous element and current element.
 

	
 
			num_lines += CountPageElementLines(*pe, max_width);
 
			height += element_vertical_dist;
 
			height += GetPageElementHeight(*pe, max_width);
 
		}
 

	
 
		return num_lines;
 
		return height;
 
	}
 

	
 
	/**
 
	 * Draws a page element that is composed of a sprite to the left and a single line of
 
	 * text after that. These page elements are generally clickable and are thus called
 
	 * action elements.
 
@@ -370,13 +369,13 @@ protected:
 
	 * @param action_sprite The sprite to draw.
 
	 * @return the number of lines.
 
	 */
 
	void DrawActionElement(int &y_offset, int width, int line_height, SpriteID action_sprite) const
 
	{
 
		Dimension sprite_dim = GetSpriteSize(action_sprite);
 
		uint element_height = max((uint)1, sprite_dim.height / (uint)line_height) * line_height;
 
		uint element_height = max(sprite_dim.height, (uint)line_height);
 

	
 
		uint sprite_top = y_offset + (element_height - sprite_dim.height) / 2;
 
		uint text_top = y_offset + (element_height - line_height) / 2;
 

	
 
		DrawSprite(action_sprite, PAL_NONE, 0, sprite_top);
 
		DrawString(sprite_dim.width + WD_FRAMETEXT_LEFT, width, text_top, STR_JUST_RAW_STRING, TC_BLACK);
 
@@ -414,12 +413,13 @@ protected:
 

	
 
public:
 
	StoryBookWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
 
	{
 
		this->CreateNestedTree();
 
		this->vscroll = this->GetScrollbar(WID_SB_SCROLLBAR);
 
		this->vscroll->SetStepSize(FONT_HEIGHT_NORMAL);
 

	
 
		/* Initalize page sort. */
 
		this->story_pages.SetSortFuncs(StoryBookWindow::page_sorter_funcs);
 
		this->story_pages.ForceRebuild();
 
		this->BuildStoryPageList();
 
		this->story_page_elements.SetSortFuncs(StoryBookWindow::page_element_sorter_funcs);
 
@@ -496,13 +496,13 @@ public:
 

	
 
		DrawPixelInfo *old_dpi = _cur_dpi;
 
		_cur_dpi = &tmp_dpi;
 

	
 
		/* Draw content (now coordinates given to Draw** are local to the new clipping region). */
 
		int line_height = FONT_HEIGHT_NORMAL;
 
		int y_offset = - this->vscroll->GetPosition() * line_height;
 
		int y_offset = - this->vscroll->GetPosition();
 

	
 
		/* Date */
 
		SetDParam(0, page->date);
 
		DrawString(0, right - x, y_offset, STR_JUST_DATE_LONG, TC_BLACK);
 
		y_offset += line_height;
 

	
 
@@ -576,27 +576,25 @@ public:
 
				d.height += padding.height + WD_DROPDOWNTEXT_TOP + WD_DROPDOWNTEXT_BOTTOM;
 
				*size = maxdim(*size, d);
 
				break;
 
			}
 

	
 
			case WID_SB_PAGE_PANEL: {
 
				resize->height = d.height;
 

	
 
				d.height *= 5;
 
				d.height += padding.height + WD_FRAMETEXT_TOP + WD_FRAMETEXT_BOTTOM;
 
				*size = maxdim(*size, d);
 
				break;
 
			}
 
		}
 

	
 
	}
 

	
 
	virtual void OnResize()
 
	{
 
		this->vscroll->SetCapacityFromWidget(this, WID_SB_PAGE_PANEL, WD_FRAMETEXT_TOP + WD_FRAMETEXT_BOTTOM);
 
		this->vscroll->SetCount(this->CountLines());
 
		this->vscroll->SetCount(this->GetContentHeight());
 
	}
 

	
 
	virtual void OnClick(Point pt, int widget, int click_count)
 
	{
 
		switch (widget) {
 
			case WID_SB_SEL_PAGE: {
 
@@ -621,33 +619,34 @@ public:
 

	
 
			case WID_SB_NEXT_PAGE:
 
				this->SelectNextPage();
 
				break;
 

	
 
			case WID_SB_PAGE_PANEL: {
 
				uint clicked_row = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SB_PAGE_PANEL, WD_FRAMETEXT_TOP);
 
				uint clicked_y = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SB_PAGE_PANEL, WD_FRAMETEXT_TOP);
 
				uint max_width = GetAvailablePageContentWidth();
 

	
 
				/* Skip head rows. */
 
				uint n_head_rows = this->CountHeadLines(max_width);
 
				if (clicked_row < n_head_rows) return;
 
				uint head_height = this->GetHeadHeight(max_width);
 
				if (clicked_y < head_height) return;
 

	
 
				/* Detect if a page element was clicked. */
 
				uint row = n_head_rows;
 
				uint y = head_height;
 
				uint element_vertical_dist = FONT_HEIGHT_NORMAL;
 
				for (const StoryPageElement *const*iter = this->story_page_elements.Begin(); iter != this->story_page_elements.End(); iter++) {
 
					const StoryPageElement *const pe = *iter;
 

	
 
					row += 1; // margin row
 
					y += element_vertical_dist; // margin row
 

	
 
					uint content_rows = CountPageElementLines(*pe, max_width);
 
					if (clicked_row >= row && clicked_row < row + content_rows) {
 
					uint content_height = GetPageElementHeight(*pe, max_width);
 
					if (clicked_y >= y && clicked_y < y + content_height) {
 
						this->OnPageElementClick(*pe);
 
						return;
 
					}
 

	
 
					row += content_rows;
 
					y += content_height;
 
				}
 
			}
 
		}
 
	}
 

	
 
	virtual void OnDropdownSelect(int widget, int index)
0 comments (0 inline, 0 general)