Changeset - r22679:0c1ff6201584
[Not reviewed]
master
0 2 0
frosch - 7 years ago 2017-08-27 11:48:38
frosch@openttd.org
(svn r27900) -Change [FS#6568]: Remove the gap between windows when positioning them after opening.
-Fix: Make automatic window-positioning RTL-aware.
-Fix: Automatic window-positioning now uses GUI-scale/style dependent sizes/distances instead of fixed pixel values.
2 files changed with 66 insertions and 38 deletions:
0 comments (0 inline, 0 general)
src/widget_type.h
Show inline comments
 
@@ -779,13 +779,13 @@ public:
 
	static void InvalidateDimensionCache();
 

	
 
	static Dimension dropdown_dimension;  ///< Cached size of a dropdown widget.
 
	static Dimension resizebox_dimension; ///< Cached size of a resizebox widget.
 
	static Dimension closebox_dimension;  ///< Cached size of a closebox widget.
 
private:
 
	static Dimension shadebox_dimension;  ///< Cached size of a shadebox widget.
 
	static Dimension debugbox_dimension;  ///< Cached size of a debugbox widget.
 
	static Dimension defsizebox_dimension; ///< Cached size of a defsizebox widget.
 
	static Dimension stickybox_dimension; ///< Cached size of a stickybox widget.
 
	static Dimension resizebox_dimension; ///< Cached size of a resizebox widget.
 
	static Dimension closebox_dimension;  ///< Cached size of a closebox widget.
 
};
 

	
 
/**
src/window.cpp
Show inline comments
 
@@ -1555,16 +1555,16 @@ void Window::FindWindowPlacementAndResiz
 
 * @param top     Top edge of the rectangle
 
 * @param width   Width of the rectangle
 
 * @param height  Height of the rectangle
 
 * @param toolbar_y Height of main toolbar
 
 * @param pos     If rectangle is good, use this parameter to return the top-left corner of the new window
 
 * @return Boolean indication that the rectangle is a good place for the new window
 
 */
 
static bool IsGoodAutoPlace1(int left, int top, int width, int height, Point &pos)
 
static bool IsGoodAutoPlace1(int left, int top, int width, int height, int toolbar_y, Point &pos)
 
{
 
	int right  = width + left;
 
	int bottom = height + top;
 

	
 
	const Window *main_toolbar = FindWindowByClass(WC_MAIN_TOOLBAR);
 
	if (left < 0 || (main_toolbar != NULL && top < main_toolbar->height) || right > _screen.width || bottom > _screen.height) return false;
 
	if (left < 0 || top < toolbar_y || right > _screen.width || bottom > _screen.height) return false;
 

	
 
	/* Make sure it is not obscured by any window. */
 
	const Window *w;
 
@@ -1592,17 +1592,25 @@ static bool IsGoodAutoPlace1(int left, i
 
 * @param top     Top edge of the rectangle
 
 * @param width   Width of the rectangle
 
 * @param height  Height of the rectangle
 
 * @param toolbar_y Height of main toolbar
 
 * @param pos     If rectangle is good, use this parameter to return the top-left corner of the new window
 
 * @return Boolean indication that the rectangle is a good place for the new window
 
 */
 
static bool IsGoodAutoPlace2(int left, int top, int width, int height, Point &pos)
 
static bool IsGoodAutoPlace2(int left, int top, int width, int height, int toolbar_y, Point &pos)
 
{
 
	bool rtl = _current_text_dir == TD_RTL;
 

	
 
	/* Left part of the rectangle may be at most 1/4 off-screen,
 
	 * right part of the rectangle may be at most 1/2 off-screen
 
	 */
 
	if (left < -(width >> 2) || left > _screen.width - (width >> 1)) return false;
 
	if (rtl) {
 
		if (left < -(width >> 1) || left > _screen.width - (width >> 2)) return false;
 
	} else {
 
		if (left < -(width >> 2) || left > _screen.width - (width >> 1)) return false;
 
	}
 

	
 
	/* Bottom part of the rectangle may be at most 1/4 off-screen */
 
	if (top < 22 || top > _screen.height - (height >> 2)) return false;
 
	if (top < toolbar_y || top > _screen.height - (height >> 2)) return false;
 

	
 
	/* Make sure it is not obscured by any window. */
 
	const Window *w;
 
@@ -1632,11 +1640,14 @@ static Point GetAutoPlacePosition(int wi
 
{
 
	Point pt;
 

	
 
	bool rtl = _current_text_dir == TD_RTL;
 

	
 
	/* First attempt, try top-left of the screen */
 
	const Window *main_toolbar = FindWindowByClass(WC_MAIN_TOOLBAR);
 
	if (IsGoodAutoPlace1(0, main_toolbar != NULL ? main_toolbar->height + 2 : 2, width, height, pt)) return pt;
 

	
 
	/* Second attempt, try around all existing windows with a distance of 2 pixels.
 
	const int toolbar_y =  main_toolbar != NULL ? main_toolbar->height : 0;
 
	if (IsGoodAutoPlace1(rtl ? _screen.width - width : 0, toolbar_y, width, height, toolbar_y, pt)) return pt;
 

	
 
	/* Second attempt, try around all existing windows.
 
	 * The new window must be entirely on-screen, and not overlap with an existing window.
 
	 * Eight starting points are tried, two at each corner.
 
	 */
 
@@ -1644,39 +1655,41 @@ static Point GetAutoPlacePosition(int wi
 
	FOR_ALL_WINDOWS_FROM_BACK(w) {
 
		if (w->window_class == WC_MAIN_WINDOW) continue;
 

	
 
		if (IsGoodAutoPlace1(w->left + w->width + 2, w->top, width, height, pt)) return pt;
 
		if (IsGoodAutoPlace1(w->left - width - 2,    w->top, width, height, pt)) return pt;
 
		if (IsGoodAutoPlace1(w->left, w->top + w->height + 2, width, height, pt)) return pt;
 
		if (IsGoodAutoPlace1(w->left, w->top - height - 2,    width, height, pt)) return pt;
 
		if (IsGoodAutoPlace1(w->left + w->width + 2, w->top + w->height - height, width, height, pt)) return pt;
 
		if (IsGoodAutoPlace1(w->left - width - 2,    w->top + w->height - height, width, height, pt)) return pt;
 
		if (IsGoodAutoPlace1(w->left + w->width - width, w->top + w->height + 2, width, height, pt)) return pt;
 
		if (IsGoodAutoPlace1(w->left + w->width - width, w->top - height - 2,    width, height, pt)) return pt;
 
		if (IsGoodAutoPlace1(w->left + w->width,         w->top,                      width, height, toolbar_y, pt)) return pt;
 
		if (IsGoodAutoPlace1(w->left            - width, w->top,                      width, height, toolbar_y, pt)) return pt;
 
		if (IsGoodAutoPlace1(w->left,                    w->top + w->height,          width, height, toolbar_y, pt)) return pt;
 
		if (IsGoodAutoPlace1(w->left,                    w->top             - height, width, height, toolbar_y, pt)) return pt;
 
		if (IsGoodAutoPlace1(w->left + w->width,         w->top + w->height - height, width, height, toolbar_y, pt)) return pt;
 
		if (IsGoodAutoPlace1(w->left            - width, w->top + w->height - height, width, height, toolbar_y, pt)) return pt;
 
		if (IsGoodAutoPlace1(w->left + w->width - width, w->top + w->height,          width, height, toolbar_y, pt)) return pt;
 
		if (IsGoodAutoPlace1(w->left + w->width - width, w->top             - height, width, height, toolbar_y, pt)) return pt;
 
	}
 

	
 
	/* Third attempt, try around all existing windows with a distance of 2 pixels.
 
	/* Third attempt, try around all existing windows.
 
	 * The new window may be partly off-screen, and must not overlap with an existing window.
 
	 * Only four starting points are tried.
 
	 */
 
	FOR_ALL_WINDOWS_FROM_BACK(w) {
 
		if (w->window_class == WC_MAIN_WINDOW) continue;
 

	
 
		if (IsGoodAutoPlace2(w->left + w->width + 2, w->top, width, height, pt)) return pt;
 
		if (IsGoodAutoPlace2(w->left - width - 2,    w->top, width, height, pt)) return pt;
 
		if (IsGoodAutoPlace2(w->left, w->top + w->height + 2, width, height, pt)) return pt;
 
		if (IsGoodAutoPlace2(w->left, w->top - height - 2,    width, height, pt)) return pt;
 
		if (IsGoodAutoPlace2(w->left + w->width, w->top,             width, height, toolbar_y, pt)) return pt;
 
		if (IsGoodAutoPlace2(w->left    - width, w->top,             width, height, toolbar_y, pt)) return pt;
 
		if (IsGoodAutoPlace2(w->left,            w->top + w->height, width, height, toolbar_y, pt)) return pt;
 
		if (IsGoodAutoPlace2(w->left,            w->top - height,    width, height, toolbar_y, pt)) return pt;
 
	}
 

	
 
	/* Fourth and final attempt, put window at diagonal starting from (0, 24), try multiples
 
	 * of (+5, +5)
 
	/* Fourth and final attempt, put window at diagonal starting from (0, toolbar_y), try multiples
 
	 * of the closebox
 
	 */
 
	int left = 0, top = 24;
 
	int left = rtl ? _screen.width - width : 0, top = toolbar_y;
 
	int offset_x = rtl ? -NWidgetLeaf::closebox_dimension.width : NWidgetLeaf::closebox_dimension.width;
 
	int offset_y = max<int>(NWidgetLeaf::closebox_dimension.height, FONT_HEIGHT_NORMAL + WD_CAPTIONTEXT_TOP + WD_CAPTIONTEXT_BOTTOM);
 

	
 
restart:
 
	FOR_ALL_WINDOWS_FROM_BACK(w) {
 
		if (w->left == left && w->top == top) {
 
			left += 5;
 
			top += 5;
 
			left += offset_x;
 
			top += offset_y;
 
			goto restart;
 
		}
 
	}
 
@@ -1725,16 +1738,31 @@ static Point LocalGetWindowPlacement(con
 
	int16 default_width  = max(desc->GetDefaultWidth(),  sm_width);
 
	int16 default_height = max(desc->GetDefaultHeight(), sm_height);
 

	
 
	if (desc->parent_cls != 0 /* WC_MAIN_WINDOW */ &&
 
			(w = FindWindowById(desc->parent_cls, window_number)) != NULL &&
 
			w->left < _screen.width - 20 && w->left > -60 && w->top < _screen.height - 20) {
 

	
 
		pt.x = w->left + ((desc->parent_cls == WC_BUILD_TOOLBAR || desc->parent_cls == WC_SCEN_LAND_GEN) ? 0 : 10);
 
		if (pt.x > _screen.width + 10 - default_width) {
 
			pt.x = (_screen.width + 10 - default_width) - 20;
 
	if (desc->parent_cls != 0 /* WC_MAIN_WINDOW */ && (w = FindWindowById(desc->parent_cls, window_number)) != NULL) {
 
		bool rtl = _current_text_dir == TD_RTL;
 
		if (desc->parent_cls == WC_BUILD_TOOLBAR || desc->parent_cls == WC_SCEN_LAND_GEN) {
 
			pt.x = w->left + (rtl ? w->width - default_width : 0);
 
			pt.y = w->top + w->height;
 
			return pt;
 
		} else {
 
			/* Position child window with offset of closebox, but make sure that either closebox or resizebox is visible
 
			 *  - Y position: closebox of parent + closebox of child + statusbar
 
			 *  - X position: closebox on left/right, resizebox on right/left (depending on ltr/rtl)
 
			 */
 
			int indent_y = max<int>(NWidgetLeaf::closebox_dimension.height, FONT_HEIGHT_NORMAL + WD_CAPTIONTEXT_TOP + WD_CAPTIONTEXT_BOTTOM);
 
			if (w->top + 3 * indent_y < _screen.height) {
 
				pt.y = w->top + indent_y;
 
				int indent_close = NWidgetLeaf::closebox_dimension.width;
 
				int indent_resize = NWidgetLeaf::resizebox_dimension.width;
 
				if (_current_text_dir == TD_RTL) {
 
					pt.x = max(w->left + w->width - default_width - indent_close, 0);
 
					if (pt.x + default_width >= indent_close && pt.x + indent_resize <= _screen.width) return pt;
 
				} else {
 
					pt.x = min(w->left + indent_close, _screen.width - default_width);
 
					if (pt.x + default_width >= indent_resize && pt.x + indent_close <= _screen.width) return pt;
 
				}
 
			}
 
		}
 
		pt.y = w->top + ((desc->parent_cls == WC_BUILD_TOOLBAR || desc->parent_cls == WC_SCEN_LAND_GEN) ? w->height : 10);
 
		return pt;
 
	}
 

	
 
	switch (desc->default_pos) {
0 comments (0 inline, 0 general)