From f27ea1aff738f3222c782a7fac5b9172fc3cf67c Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 7 Feb 2012 22:50:49 -0800
Subject: [PATCH] EXP-1181 WIP as a designer I would like to specify default
 floater positions using realtive coordinates fixed build moved conversion
 funcs to llwindow.cpp as they work on all platforms refactored
 translateintorect to take overlap as parameter

---
 indra/llmath/llcoord.h           | 13 ++---
 indra/llui/llcombobox.cpp        |  2 +-
 indra/llui/llfloater.cpp         | 81 +++++++++++++++++++++++++++++---
 indra/llui/llview.cpp            | 69 ++++++++-------------------
 indra/llui/llview.h              |  2 +-
 indra/llwindow/llwindow.cpp      | 39 +++++++++++++++
 indra/llwindow/llwindowwin32.cpp | 38 ---------------
 7 files changed, 143 insertions(+), 101 deletions(-)

diff --git a/indra/llmath/llcoord.h b/indra/llmath/llcoord.h
index 0b1d7e04f59..1f617e649e9 100644
--- a/indra/llmath/llcoord.h
+++ b/indra/llmath/llcoord.h
@@ -26,9 +26,12 @@
 #ifndef LL_LLCOORD_H
 #define LL_LLCOORD_H
 
-struct LL_COORD_TYPE_COMMON 
+struct LLCoordCommon
 {
-	typedef S32 value_t;
+	LLCoordCommon(S32 x, S32 y) : mX(x), mY(y) {}
+	LLCoordCommon() : mX(0), mY(0) {}
+	S32 mX;
+	S32 mY;
 };
 
 // A two-dimensional pixel value
@@ -45,12 +48,12 @@ class LLCoord : protected COORD_FRAME
 	LLCoord(S32 x, S32 y): mX(x), mY(y)
 	{}
 
-	LLCoord(const LLCoord<LL_COORD_TYPE_COMMON>& other)
+	LLCoord(const LLCoordCommon& other)
 	{
 		COORD_FRAME::convertFromCommon(other);
 	}
 
-	LLCoord<LL_COORD_TYPE_COMMON> convert() const
+	LLCoordCommon convert() const
 	{
 		return COORD_FRAME::convertToCommon();
 	}
@@ -61,8 +64,6 @@ class LLCoord : protected COORD_FRAME
 
 };
 
-typedef LLCoord<LL_COORD_TYPE_COMMON> LLCoordCommon;
-
 struct LL_COORD_TYPE_GL 
 {
 	typedef S32 value_t;
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index 89d8842393b..806d2ef3f65 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -613,7 +613,7 @@ void LLComboBox::showList()
 	}
 	mList->setOrigin(rect.mLeft, rect.mBottom);
 	mList->reshape(rect.getWidth(), rect.getHeight());
-	mList->translateIntoRect(root_view_local, FALSE);
+	mList->translateIntoRect(root_view_local);
 
 	// Make sure we didn't go off bottom of screen
 	S32 x, y;
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 6274caa97fc..3afa1b8e3ad 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -926,7 +926,7 @@ void LLFloater::applyPositioning(LLFloater* other)
 			setOrigin(mSpecifiedLeft, mSpecifiedBottom);
 			const LLRect& snap_rect = gFloaterView->getSnapRect();
 			translate(snap_rect.mLeft, snap_rect.mBottom);
-			translateIntoRect(snap_rect, FALSE);
+			translateIntoRect(snap_rect);
 		}
 		break;
 
@@ -950,7 +950,7 @@ void LLFloater::applyPositioning(LLFloater* other)
 			setOrigin(horizontal_offset, vertical_offset - rect_height);
 
 			translate(snap_rect.mLeft, snap_rect.mBottom);
-			translateIntoRect(snap_rect, FALSE);
+			translateIntoRect(snap_rect);
 		}
 		break;
 
@@ -2644,6 +2644,8 @@ void LLFloaterView::refresh()
 	}
 }
 
+const S32 FLOATER_MIN_VISIBLE_PIXELS = 16;
+
 void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside)
 {
 	if (floater->getParent() != this)
@@ -2697,7 +2699,7 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
 	}
 
 	// move window fully onscreen
-	if (floater->translateIntoRect( getSnapRect(), allow_partial_outside ))
+	if (floater->translateIntoRect( getSnapRect(), allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX ))
 	{
 		floater->clearSnapTarget();
 	}
@@ -3305,12 +3307,79 @@ bool LLCoordFloater::operator==(const LLCoordFloater& other) const
 LLCoordCommon LL_COORD_FLOATER::convertToCommon() const
 {
 	const LLCoordFloater& self = static_cast<const LLCoordFloater&>(*this);
-	return LLCoordCommon(self.mX, self.mY);
+
+	LLRect snap_rect = gFloaterView->getSnapRect();
+	LLFloater* floaterp = mFloater.get();
+	S32 floater_width = floaterp ? floaterp->getRect().getWidth() : 0;
+	S32 floater_height = floaterp ? floaterp->getRect().getHeight() : 0;
+	LLCoordCommon out;
+	if (self.mX < -0.5f)
+	{
+		out.mX = llround(rescale(self.mX, -1.f, -0.5f, snap_rect.mLeft - (floater_width - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mLeft));
+	}
+	else if (self.mX > 0.5f)
+	{
+		out.mX = llround(rescale(self.mX, 0.5f, 1.f, snap_rect.mRight - floater_width, snap_rect.mRight - FLOATER_MIN_VISIBLE_PIXELS));
+	}
+	else
+	{
+		out.mX = llround(rescale(self.mX, -0.5f, 0.5f, snap_rect.mLeft, snap_rect.mRight - floater_width));
+	}
+
+	if (self.mY < -0.5f)
+	{
+		out.mY = llround(rescale(self.mY, -1.f, -0.5f, snap_rect.mBottom - (floater_height - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mBottom));
+	}
+	else if (self.mY > 0.5f)
+	{
+		out.mY = llround(rescale(self.mY, 0.5f, 1.f, snap_rect.mTop - floater_height, snap_rect.mTop - FLOATER_MIN_VISIBLE_PIXELS));
+	}
+	else
+	{
+		out.mY = llround(rescale(self.mY, -0.5f, 0.5f, snap_rect.mBottom, snap_rect.mTop - floater_height));
+	}
+
+	// return center point instead of lower left
+	out.mX += floater_width / 2;
+	out.mY += floater_height / 2;
+
+	return out;
 }
 
 void LL_COORD_FLOATER::convertFromCommon(const LLCoordCommon& from)
 {
 	LLCoordFloater& self = static_cast<LLCoordFloater&>(*this);
-	self.mX = from.mX;
-	self.mY = from.mY;
+	LLRect snap_rect = gFloaterView->getSnapRect();
+	LLFloater* floaterp = mFloater.get();
+	S32 floater_width = floaterp ? floaterp->getRect().getWidth() : 0;
+	S32 floater_height = floaterp ? floaterp->getRect().getHeight() : 0;
+
+	S32 from_x = from.mX - floater_width / 2;
+	S32 from_y = from.mY - floater_height / 2;
+
+	if (from_x < snap_rect.mLeft)
+	{
+		self.mX = rescale(from_x, snap_rect.mLeft - (floater_width - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mLeft, -1.f, -0.5f);
+	}
+	else if (from_x + floater_width > snap_rect.mRight)
+	{
+		self.mX = rescale(from_x, snap_rect.mRight - floater_width, snap_rect.mRight - FLOATER_MIN_VISIBLE_PIXELS, 0.5f, 1.f);
+	}
+	else
+	{
+		self.mX = rescale(from_x, snap_rect.mLeft, snap_rect.mRight - floater_width, -0.5f, 0.5f);
+	}
+
+	if (from_y < snap_rect.mBottom)
+	{
+		self.mY = rescale(from_y, snap_rect.mBottom - (floater_height - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mBottom, -1.f, -0.5f);
+	}
+	else if (from_y + floater_height > snap_rect.mTop)
+	{
+		self.mY = rescale(from_y, snap_rect.mTop - floater_height, snap_rect.mTop - FLOATER_MIN_VISIBLE_PIXELS, 0.5f, 1.f);
+	}
+	else
+	{
+		self.mY = rescale(from_y, snap_rect.mBottom, snap_rect.mTop - floater_height, -0.5f, 0.5f);
+	}
 }
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 1a62fe75fcc..d22e14745f0 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -1616,59 +1616,30 @@ LLView* LLView::findNextSibling(LLView* child)
 }
 
 
-LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, BOOL allow_partial_outside)
+LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, S32 min_overlap_pixels)
 {
 	LLCoordGL delta;
 
-	if (allow_partial_outside)
-	{
-		const S32 KEEP_ONSCREEN_PIXELS = 16;
+	const S32 KEEP_ONSCREEN_PIXELS_WIDTH = llmin(min_overlap_pixels, input.getWidth());
+	const S32 KEEP_ONSCREEN_PIXELS_HEIGHT = llmin(min_overlap_pixels, input.getHeight());
 
-		if( input.mRight - KEEP_ONSCREEN_PIXELS < constraint.mLeft )
-		{
-			delta.mX = constraint.mLeft - (input.mRight - KEEP_ONSCREEN_PIXELS);
-		}
-		else
-		if( input.mLeft + KEEP_ONSCREEN_PIXELS > constraint.mRight )
-		{
-			delta.mX = constraint.mRight - (input.mLeft + KEEP_ONSCREEN_PIXELS);
-		}
+	if( input.mRight - KEEP_ONSCREEN_PIXELS_WIDTH < constraint.mLeft )
+	{
+		delta.mX = constraint.mLeft - (input.mRight - KEEP_ONSCREEN_PIXELS_WIDTH);
+	}
+	else if( input.mLeft + KEEP_ONSCREEN_PIXELS_WIDTH > constraint.mRight )
+	{
+		delta.mX = constraint.mRight - (input.mLeft + KEEP_ONSCREEN_PIXELS_WIDTH);
+	}
 
-		if( input.mTop > constraint.mTop )
-		{
-			delta.mY = constraint.mTop - input.mTop;
-		}
-		else
-		if( input.mTop - KEEP_ONSCREEN_PIXELS < constraint.mBottom )
-		{
-			delta.mY = constraint.mBottom - (input.mTop - KEEP_ONSCREEN_PIXELS);
-		}
+	if( input.mTop > constraint.mTop )
+	{
+		delta.mY = constraint.mTop - input.mTop;
 	}
 	else
+	if( input.mTop - KEEP_ONSCREEN_PIXELS_HEIGHT < constraint.mBottom )
 	{
-		if( input.mLeft < constraint.mLeft )
-		{
-			delta.mX = constraint.mLeft - input.mLeft;
-		}
-		else
-		if( input.mRight > constraint.mRight )
-		{
-			delta.mX = constraint.mRight - input.mRight;
-			// compensate for left edge possible going off screen
-			delta.mX += llmax( 0, input.getWidth() - constraint.getWidth() );
-		}
-
-		if( input.mTop > constraint.mTop )
-		{
-			delta.mY = constraint.mTop - input.mTop;
-		}
-		else
-		if( input.mBottom < constraint.mBottom )
-		{
-			delta.mY = constraint.mBottom - input.mBottom;
-			// compensate for top edge possible going off screen
-			delta.mY -= llmax( 0, input.getHeight() - constraint.getHeight() );
-		}
+		delta.mY = constraint.mBottom - (input.mTop - KEEP_ONSCREEN_PIXELS_HEIGHT);
 	}
 
 	return delta;
@@ -1677,9 +1648,9 @@ LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, BO
 // Moves the view so that it is entirely inside of constraint.
 // If the view will not fit because it's too big, aligns with the top and left.
 // (Why top and left?  That's where the drag bars are for floaters.)
-BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outside )
+BOOL LLView::translateIntoRect(const LLRect& constraint, S32 min_overlap_pixels)
 {
-	LLCoordGL translation = getNeededTranslation(getRect(), constraint, allow_partial_outside);
+	LLCoordGL translation = getNeededTranslation(getRect(), constraint, min_overlap_pixels);
 
 	if (translation.mX != 0 || translation.mY != 0)
 	{
@@ -1691,9 +1662,9 @@ BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outs
 
 // move this view into "inside" but not onto "exclude"
 // NOTE: if this view is already contained in "inside", we ignore the "exclude" rect
-BOOL LLView::translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside )
+BOOL LLView::translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, S32 min_overlap_pixels)
 {
-	LLCoordGL translation = getNeededTranslation(getRect(), inside, allow_partial_outside);
+	LLCoordGL translation = getNeededTranslation(getRect(), inside, min_overlap_pixels);
 	
 	if (translation.mX != 0 || translation.mY != 0)
 	{
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index f1fac5f69ce..de2fab963bf 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -370,7 +370,7 @@ class LLView
 	virtual void	reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
 	virtual void	translate( S32 x, S32 y );
 	void			setOrigin( S32 x, S32 y )	{ mRect.translate( x - mRect.mLeft, y - mRect.mBottom ); }
-	BOOL			translateIntoRect( const LLRect& constraint, BOOL allow_partial_outside );
+	BOOL			translateIntoRect( const LLRect& constraint, S32 min_overlap_pixels = S32_MAX);
 	BOOL			translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside );
 	void			centerWithin(const LLRect& bounds);
 
diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp
index 2e9e31bfea1..6834b34387c 100644
--- a/indra/llwindow/llwindow.cpp
+++ b/indra/llwindow/llwindow.cpp
@@ -436,3 +436,42 @@ BOOL LLWindowManager::isWindowValid(LLWindow *window)
 {
 	return sWindowList.find(window) != sWindowList.end();
 }
+
+//coordinate conversion utility funcs that forward to llwindow
+LLCoordCommon LL_COORD_TYPE_WINDOW::convertToCommon() const
+{
+	const LLCoordWindow& self = static_cast<const LLCoordWindow&>(*this);
+
+	LLWindow* windowp = &(*LLWindow::beginInstances());
+	LLCoordGL out;
+	windowp->convertCoords(self, &out);
+	return out.convert();
+}
+
+void LL_COORD_TYPE_WINDOW::convertFromCommon(const LLCoordCommon& from)
+{
+	LLCoordWindow& self = static_cast<LLCoordWindow&>(*this);
+
+	LLWindow* windowp = &(*LLWindow::beginInstances());
+	LLCoordGL from_gl(from);
+	windowp->convertCoords(from_gl, &self);
+}
+
+LLCoordCommon LL_COORD_TYPE_SCREEN::convertToCommon() const
+{
+	const LLCoordScreen& self = static_cast<const LLCoordScreen&>(*this);
+
+	LLWindow* windowp = &(*LLWindow::beginInstances());
+	LLCoordGL out;
+	windowp->convertCoords(self, &out);
+	return out.convert();
+}
+
+void LL_COORD_TYPE_SCREEN::convertFromCommon(const LLCoordCommon& from)
+{
+	LLCoordScreen& self = static_cast<LLCoordScreen&>(*this);
+
+	LLWindow* windowp = &(*LLWindow::beginInstances());
+	LLCoordGL from_gl(from);
+	windowp->convertCoords(from_gl, &self);
+}
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index a8d2836f48b..ebc3203f14e 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -2560,44 +2560,6 @@ BOOL LLWindowWin32::convertCoords(LLCoordGL from, LLCoordWindow *to)
 	return TRUE;
 }
 
-LLCoordCommon LL_COORD_TYPE_WINDOW::convertToCommon() const
-{
-	const LLCoordWindow& self = static_cast<const LLCoordWindow&>(*this);
-
-	LLWindow* windowp = &(*LLWindow::beginInstances());
-	LLCoordGL out;
-	windowp->convertCoords(self, &out);
-	return out.convert();
-}
-
-void LL_COORD_TYPE_WINDOW::convertFromCommon(const LLCoordCommon& from)
-{
-	LLCoordWindow& self = static_cast<LLCoordWindow&>(*this);
-
-	LLWindow* windowp = &(*LLWindow::beginInstances());
-	LLCoordGL from_gl(from);
-	windowp->convertCoords(from_gl, &self);
-}
-
-LLCoordCommon LL_COORD_TYPE_SCREEN::convertToCommon() const
-{
-	const LLCoordScreen& self = static_cast<const LLCoordScreen&>(*this);
-
-	LLWindow* windowp = &(*LLWindow::beginInstances());
-	LLCoordGL out;
-	windowp->convertCoords(self, &out);
-	return out.convert();
-}
-
-void LL_COORD_TYPE_SCREEN::convertFromCommon(const LLCoordCommon& from)
-{
-	LLCoordScreen& self = static_cast<LLCoordScreen&>(*this);
-
-	LLWindow* windowp = &(*LLWindow::beginInstances());
-	LLCoordGL from_gl(from);
-	windowp->convertCoords(from_gl, &self);
-}
-
 BOOL LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordGL* to)
 {
 	S32		client_height;
-- 
GitLab