diff options
Diffstat (limited to 'indra/llui/llfloater.cpp')
-rw-r--r-- | indra/llui/llfloater.cpp | 457 |
1 files changed, 316 insertions, 141 deletions
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 432397d3e9..8ca1e685a9 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -58,6 +58,8 @@ #include "llhelp.h" #include "llmultifloater.h" #include "llsdutil.h" +#include <boost/foreach.hpp> + // use this to control "jumping" behavior when Ctrl-Tabbing const S32 TABBED_FLOATER_OFFSET = 0; @@ -66,10 +68,10 @@ namespace LLInitParam { void TypeValues<LLFloaterEnums::EOpenPositioning>::declareValues() { - declare("none", LLFloaterEnums::OPEN_POSITIONING_NONE); - declare("cascading", LLFloaterEnums::OPEN_POSITIONING_CASCADING); - declare("centered", LLFloaterEnums::OPEN_POSITIONING_CENTERED); - declare("specified", LLFloaterEnums::OPEN_POSITIONING_SPECIFIED); + declare("relative", LLFloaterEnums::POSITIONING_RELATIVE); + declare("cascading", LLFloaterEnums::POSITIONING_CASCADING); + declare("centered", LLFloaterEnums::POSITIONING_CENTERED); + declare("specified", LLFloaterEnums::POSITIONING_SPECIFIED); } } @@ -111,7 +113,6 @@ LLFloater::click_callback LLFloater::sButtonCallbacks[BUTTON_COUNT] = LLMultiFloater* LLFloater::sHostp = NULL; BOOL LLFloater::sQuitting = FALSE; // Flag to prevent storing visibility controls while quitting -LLFloater::handle_map_t LLFloater::sFloaterMap; LLFloaterView* gFloaterView = NULL; @@ -176,9 +177,7 @@ LLFloater::Params::Params() save_visibility("save_visibility", false), can_dock("can_dock", false), show_title("show_title", true), - open_positioning("open_positioning", LLFloaterEnums::OPEN_POSITIONING_NONE), - specified_left("specified_left"), - specified_bottom("specified_bottom"), + positioning("positioning", LLFloaterEnums::POSITIONING_RELATIVE), header_height("header_height", 0), legacy_header_height("legacy_header_height", 0), close_image("close_image"), @@ -194,7 +193,8 @@ LLFloater::Params::Params() dock_pressed_image("dock_pressed_image"), help_pressed_image("help_pressed_image"), open_callback("open_callback"), - close_callback("close_callback") + close_callback("close_callback"), + follows("follows") { changeDefault(visible, false); } @@ -247,9 +247,7 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) mCanClose(p.can_close), mDragOnLeft(p.can_drag_on_left), mResizable(p.can_resize), - mOpenPositioning(p.open_positioning), - mSpecifiedLeft(p.specified_left), - mSpecifiedBottom(p.specified_bottom), + mPositioning(p.positioning), mMinWidth(p.min_width), mMinHeight(p.min_height), mHeaderHeight(p.header_height), @@ -268,7 +266,7 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) mMinimizeSignal(NULL) // mNotificationContext(NULL) { - mHandle.bind(this); + mPosition.setFloater(*this); // mNotificationContext = new LLFloaterNotificationContext(getHandle()); // Clicks stop here. @@ -323,9 +321,6 @@ void LLFloater::initFloater(const Params& p) // Floaters are created in the invisible state setVisible(FALSE); - // add self to handle->floater map - sFloaterMap[mHandle] = this; - if (!getParent()) { gFloaterView->addChild(this); @@ -532,8 +527,6 @@ LLFloater::~LLFloater() // correct, non-minimized positions. setMinimized( FALSE ); - sFloaterMap.erase(mHandle); - delete mDragHandle; for (S32 i = 0; i < 4; i++) { @@ -550,10 +543,18 @@ LLFloater::~LLFloater() void LLFloater::storeRectControl() { - if( mRectControl.size() > 1 ) + if (!mRectControl.empty()) { getControlGroup()->setRect( mRectControl, getRect() ); } + if (!mPosXControl.empty() && mPositioning == LLFloaterEnums::POSITIONING_RELATIVE) + { + getControlGroup()->setF32( mPosXControl, mPosition.mX ); + } + if (!mPosYControl.empty() && mPositioning == LLFloaterEnums::POSITIONING_RELATIVE) + { + getControlGroup()->setF32( mPosYControl, mPosition.mY ); + } } void LLFloater::storeVisibilityControl() @@ -572,23 +573,6 @@ void LLFloater::storeDockStateControl() } } -LLRect LLFloater::getSavedRect() const -{ - LLRect rect; - - if (mRectControl.size() > 1) - { - rect = getControlGroup()->getRect(mRectControl); - } - - return rect; -} - -bool LLFloater::hasSavedRect() const -{ - return !getSavedRect().isEmpty(); -} - // static std::string LLFloater::getControlName(const std::string& name, const LLSD& key) { @@ -866,7 +850,7 @@ void LLFloater::applyControlsAndPosition(LLFloater* other) { if (!applyRectControl()) { - applyPositioning(other); + applyPositioning(other, true); } } } @@ -875,29 +859,68 @@ bool LLFloater::applyRectControl() { bool saved_rect = false; + LLRect screen_rect = calcScreenRect(); + mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert(); + LLFloater* last_in_group = LLFloaterReg::getLastFloaterInGroup(mInstanceName); if (last_in_group && last_in_group != this) { // other floaters in our group, position ourselves relative to them and don't save the rect mRectControl.clear(); - mOpenPositioning = LLFloaterEnums::OPEN_POSITIONING_CASCADE_GROUP; + mPositioning = LLFloaterEnums::POSITIONING_CASCADE_GROUP; } - else if (mRectControl.size() > 1) + else { - // If we have a saved rect, use it - const LLRect& rect = getControlGroup()->getRect(mRectControl); - saved_rect = rect.notEmpty(); - if (saved_rect) + bool rect_specified = false; + if (!mRectControl.empty()) { - setOrigin(rect.mLeft, rect.mBottom); - - if (mResizable) + // If we have a saved rect, use it + const LLRect& rect = getControlGroup()->getRect(mRectControl); + if (rect.notEmpty()) saved_rect = true; + if (saved_rect) { - reshape(llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight())); + setOrigin(rect.mLeft, rect.mBottom); + + if (mResizable) + { + reshape(llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight())); + } + mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; + LLRect screen_rect = calcScreenRect(); + mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert(); + rect_specified = true; } } + + LLControlVariablePtr x_control = getControlGroup()->getControl(mPosXControl); + LLControlVariablePtr y_control = getControlGroup()->getControl(mPosYControl); + if (x_control.notNull() + && y_control.notNull() + && !x_control->isDefault() + && !y_control->isDefault()) + { + mPosition.mX = x_control->getValue().asReal(); + mPosition.mY = y_control->getValue().asReal(); + mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; + applyRelativePosition(); + + saved_rect = true; + } + + // remember updated position + if (rect_specified) + { + storeRectControl(); + } } + if (saved_rect) + { + // propagate any derived positioning data back to settings file + storeRectControl(); + } + + return saved_rect; } @@ -914,50 +937,56 @@ bool LLFloater::applyDockState() return docked; } -void LLFloater::applyPositioning(LLFloater* other) +void LLFloater::applyPositioning(LLFloater* other, bool on_open) { // Otherwise position according to the positioning code - switch (mOpenPositioning) + switch (mPositioning) { - case LLFloaterEnums::OPEN_POSITIONING_CENTERED: + case LLFloaterEnums::POSITIONING_CENTERED: center(); break; - case LLFloaterEnums::OPEN_POSITIONING_SPECIFIED: - { - // Translate relative to snap rect - setOrigin(mSpecifiedLeft, mSpecifiedBottom); - const LLRect& snap_rect = gFloaterView->getSnapRect(); - translate(snap_rect.mLeft, snap_rect.mBottom); - translateIntoRect(snap_rect, FALSE); - } + case LLFloaterEnums::POSITIONING_SPECIFIED: break; - case LLFloaterEnums::OPEN_POSITIONING_CASCADE_GROUP: - case LLFloaterEnums::OPEN_POSITIONING_CASCADING: - if (other != NULL && other != this) + case LLFloaterEnums::POSITIONING_CASCADING: + if (!on_open) { - stackWith(*other); + applyRelativePosition(); } - else + // fall through + case LLFloaterEnums::POSITIONING_CASCADE_GROUP: + if (on_open) { - static const U32 CASCADING_FLOATER_HOFFSET = 0; - static const U32 CASCADING_FLOATER_VOFFSET = 0; + if (other != NULL && other != this) + { + stackWith(*other); + } + else + { + static const U32 CASCADING_FLOATER_HOFFSET = 0; + static const U32 CASCADING_FLOATER_VOFFSET = 0; - const LLRect& snap_rect = gFloaterView->getSnapRect(); + const LLRect& snap_rect = gFloaterView->getSnapRect(); - const S32 horizontal_offset = CASCADING_FLOATER_HOFFSET; - const S32 vertical_offset = snap_rect.getHeight() - CASCADING_FLOATER_VOFFSET; + const S32 horizontal_offset = CASCADING_FLOATER_HOFFSET; + const S32 vertical_offset = snap_rect.getHeight() - CASCADING_FLOATER_VOFFSET; - S32 rect_height = getRect().getHeight(); - setOrigin(horizontal_offset, vertical_offset - rect_height); + S32 rect_height = getRect().getHeight(); + setOrigin(horizontal_offset, vertical_offset - rect_height); - translate(snap_rect.mLeft, snap_rect.mBottom); - translateIntoRect(snap_rect, FALSE); + translate(snap_rect.mLeft, snap_rect.mBottom); + } + setFollows(FOLLOWS_TOP | FOLLOWS_LEFT); } break; - case LLFloaterEnums::OPEN_POSITIONING_NONE: + case LLFloaterEnums::POSITIONING_RELATIVE: + { + applyRelativePosition(); + + break; + } default: // Do nothing break; @@ -1038,7 +1067,9 @@ BOOL LLFloater::canSnapTo(const LLView* other_view) if (other_view != getParent()) { const LLFloater* other_floaterp = dynamic_cast<const LLFloater*>(other_view); - if (other_floaterp && other_floaterp->getSnapTarget() == getHandle() && mDependents.find(other_floaterp->getHandle()) != mDependents.end()) + if (other_floaterp + && other_floaterp->getSnapTarget() == getHandle() + && mDependents.find(other_floaterp->getHandle()) != mDependents.end()) { // this is a dependent that is already snapped to us, so don't snap back to it return FALSE; @@ -1073,7 +1104,9 @@ void LLFloater::handleReshape(const LLRect& new_rect, bool by_user) if (by_user && !isMinimized()) { storeRectControl(); - mOpenPositioning = LLFloaterEnums::OPEN_POSITIONING_NONE; + mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; + LLRect screen_rect = calcScreenRect(); + mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert(); } // if not minimized, adjust all snapped dependents to new shape @@ -1251,6 +1284,7 @@ void LLFloater::setMinimized(BOOL minimize) // Reshape *after* setting mMinimized reshape( mExpandedRect.getWidth(), mExpandedRect.getHeight(), TRUE ); + applyPositioning(NULL, false); } make_ui_sound("UISndWindowClose"); @@ -1591,7 +1625,7 @@ void LLFloater::setDocked(bool docked, bool pop_on_undock) if (mDocked) { setMinimized(FALSE); - mOpenPositioning = LLFloaterEnums::OPEN_POSITIONING_NONE; + mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; } updateTitleButtons(); @@ -1625,7 +1659,7 @@ void LLFloater::onClickTearOff(LLFloater* self) self->openFloater(self->getKey()); // only force position for floaters that don't have that data saved - if (self->mRectControl.size() <= 1) + if (self->mRectControl.empty()) { new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - floater_header_size - 5, self->getRect().getWidth(), self->getRect().getHeight()); self->setRect(new_rect); @@ -1677,18 +1711,19 @@ void LLFloater::onClickHelp( LLFloater* self ) LLFloater* LLFloater::getClosableFloaterFromFocus() { LLFloater* focused_floater = NULL; - - handle_map_iter_t iter; - for(iter = sFloaterMap.begin(); iter != sFloaterMap.end(); ++iter) + LLInstanceTracker<LLFloater>::instance_iter it = beginInstances(); + LLInstanceTracker<LLFloater>::instance_iter end_it = endInstances(); + for (; it != end_it; ++it) { - focused_floater = iter->second; - if (focused_floater->hasFocus()) + if (it->hasFocus()) { + LLFloater& floater = *it; + focused_floater = &floater; break; } } - if (iter == sFloaterMap.end()) + if (it == endInstances()) { // nothing found, return return NULL; @@ -1803,7 +1838,7 @@ void LLFloater::draw() const LLFontGL* font = LLFontGL::getFontSansSerif(); LLRect r = getRect(); - gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1, + gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - font->getLineHeight() - 1, titlebar_focus_color % alpha, 0, TRUE); } } @@ -1949,6 +1984,12 @@ void LLFloater::setCanDrag(BOOL can_drag) } } +bool LLFloater::getCanDrag() +{ + return mDragHandle->getEnabled(); +} + + void LLFloater::updateTitleButtons() { static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0); @@ -2158,13 +2199,15 @@ LLFloaterView::LLFloaterView (const Params& p) mSnapOffsetBottom(0), mSnapOffsetRight(0) { + mSnapView = getHandle(); } // By default, adjust vertical. void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent) { - S32 old_width = getRect().getWidth(); - S32 old_height = getRect().getHeight(); + LLView::reshape(width, height, called_from_parent); + + mLastSnapRect = getSnapRect(); for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { @@ -2172,66 +2215,52 @@ void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent) LLFloater* floaterp = (LLFloater*)viewp; if (floaterp->isDependent()) { - // dependents use same follow flags as their "dependee" + // dependents are moved with their "dependee" continue; } - // Make if follow the edge it is closest to - U32 follow_flags = 0x0; - - if (floaterp->isMinimized()) + if (!floaterp->isMinimized() && floaterp->getCanDrag()) { - follow_flags |= (FOLLOWS_LEFT | FOLLOWS_TOP); - } - else - { - LLRect r = floaterp->getRect(); + LLRect old_rect = floaterp->getRect(); + floaterp->applyPositioning(NULL, false); + LLRect new_rect = floaterp->getRect(); - // Compute absolute distance from each edge of screen - S32 left_offset = llabs(r.mLeft - 0); - S32 right_offset = llabs(old_width - r.mRight); + //LLRect r = floaterp->getRect(); - S32 top_offset = llabs(old_height - r.mTop); - S32 bottom_offset = llabs(r.mBottom - 0); + //// Compute absolute distance from each edge of screen + //S32 left_offset = llabs(r.mLeft - 0); + //S32 right_offset = llabs(old_right - r.mRight); + //S32 top_offset = llabs(old_top - r.mTop); + //S32 bottom_offset = llabs(r.mBottom - 0); - if (left_offset < right_offset) - { - follow_flags |= FOLLOWS_LEFT; - } - else - { - follow_flags |= FOLLOWS_RIGHT; - } + S32 translate_x = new_rect.mLeft - old_rect.mLeft; + S32 translate_y = new_rect.mBottom - old_rect.mBottom; - // "No vertical adjustment" usually means that the bottom of the view - // has been pushed up or down. Hence we want the floaters to follow - // the top. - if (top_offset < bottom_offset) - { - follow_flags |= FOLLOWS_TOP; - } - else - { - follow_flags |= FOLLOWS_BOTTOM; - } - } + //if (left_offset > right_offset) + //{ + // translate_x = new_right - old_right; + //} - floaterp->setFollows(follow_flags); + //if (top_offset < bottom_offset) + //{ + // translate_y = new_top - old_top; + //} - //RN: all dependent floaters copy follow behavior of "parent" - for(LLFloater::handle_set_iter_t dependent_it = floaterp->mDependents.begin(); - dependent_it != floaterp->mDependents.end(); ++dependent_it) - { - LLFloater* dependent_floaterp = dependent_it->get(); - if (dependent_floaterp) + // don't reposition immovable floaters + //if (floaterp->getCanDrag()) + //{ + // floaterp->translate(translate_x, translate_y); + //} + BOOST_FOREACH(LLHandle<LLFloater> dependent_floater, floaterp->mDependents) { - dependent_floaterp->setFollows(follow_flags); + if (dependent_floater.get()) + { + dependent_floater.get()->translate(translate_x, translate_y); + } } } } - - LLView::reshape(width, height, called_from_parent); } @@ -2631,6 +2660,12 @@ void LLFloaterView::shiftFloaters(S32 x_offset, S32 y_offset) void LLFloaterView::refresh() { + LLRect snap_rect = getSnapRect(); + if (snap_rect != mLastSnapRect) + { + reshape(getRect().getWidth(), getRect().getHeight(), TRUE); + } + // Constrain children to be entirely on the screen for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { @@ -2643,6 +2678,8 @@ void LLFloaterView::refresh() } } +const S32 FLOATER_MIN_VISIBLE_PIXELS = 16; + void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside) { if (floater->getParent() != this) @@ -2696,7 +2733,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(); } @@ -2910,9 +2947,11 @@ void LLFloater::setInstanceName(const std::string& name) std::string ctrl_name = getControlName(mInstanceName, mKey); // save_rect and save_visibility only apply to registered floaters - if (!mRectControl.empty()) + if (mSaveRect) { mRectControl = LLFloaterReg::declareRectControl(ctrl_name); + mPosXControl = LLFloaterReg::declarePosXControl(ctrl_name); + mPosYControl = LLFloaterReg::declarePosYControl(ctrl_name); } if (!mVisibilityControl.empty()) { @@ -2968,6 +3007,12 @@ void LLFloater::initFromParams(const LLFloater::Params& p) // control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible LLPanel::initFromParams(p); + // override any follows flags + if (mPositioning != LLFloaterEnums::POSITIONING_SPECIFIED) + { + setFollows(FOLLOWS_NONE); + } + mTitle = p.title; mShortTitle = p.short_title; applyTitle(); @@ -2985,14 +3030,9 @@ void LLFloater::initFromParams(const LLFloater::Params& p) mSingleInstance = p.single_instance; mReuseInstance = p.reuse_instance.isProvided() ? p.reuse_instance : p.single_instance; - mOpenPositioning = p.open_positioning; - mSpecifiedLeft = p.specified_left; - mSpecifiedBottom = p.specified_bottom; + mPositioning = p.positioning; - if (p.save_rect && mRectControl.empty()) - { - mRectControl = "t"; // flag to build mRectControl name once mInstanceName is set - } + mSaveRect = p.save_rect; if (p.save_visibility) { mVisibilityControl = "t"; // flag to build mVisibilityControl name once mInstanceName is set @@ -3107,7 +3147,7 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str params.rect.left.set(0); } params.from_xui = true; - applyXUILayout(params, parent); + applyXUILayout(params, parent, parent == gFloaterView ? gFloaterView->getSnapRect() : parent->getLocalRect()); initFromParams(params); initFloater(params); @@ -3266,5 +3306,140 @@ void LLFloater::stackWith(LLFloater& other) next_rect.setLeftTopAndSize(next_rect.mLeft, next_rect.mTop, getRect().getWidth(), getRect().getHeight()); setShape(next_rect); + + if (!other.getHost()) + { + other.mPositioning = LLFloaterEnums::POSITIONING_CASCADE_GROUP; + other.setFollows(FOLLOWS_LEFT | FOLLOWS_TOP); + } +} + +void LLFloater::applyRelativePosition() +{ + LLRect snap_rect = gFloaterView->getSnapRect(); + LLRect floater_view_screen_rect = gFloaterView->calcScreenRect(); + snap_rect.translate(floater_view_screen_rect.mLeft, floater_view_screen_rect.mBottom); + LLRect floater_screen_rect = calcScreenRect(); + + LLCoordGL new_center = mPosition.convert(); + LLCoordGL cur_center(floater_screen_rect.getCenterX(), floater_screen_rect.getCenterY()); + translate(new_center.mX - cur_center.mX, new_center.mY - cur_center.mY); } + +LLCoordFloater::LLCoordFloater(F32 x, F32 y, LLFloater& floater) +: coord_t((S32)x, (S32)y) +{ + mFloater = floater.getHandle(); +} + + +LLCoordFloater::LLCoordFloater(const LLCoordCommon& other, LLFloater& floater) +{ + mFloater = floater.getHandle(); + convertFromCommon(other); +} + +LLCoordFloater& LLCoordFloater::operator=(const LLCoordFloater& other) +{ + mFloater = other.mFloater; + coord_t::operator =(other); + return *this; +} + +void LLCoordFloater::setFloater(LLFloater& floater) +{ + mFloater = floater.getHandle(); +} + +bool LLCoordFloater::operator==(const LLCoordFloater& other) const +{ + return mX == other.mX && mY == other.mY && mFloater == other.mFloater; +} + +LLCoordCommon LL_COORD_FLOATER::convertToCommon() const +{ + const LLCoordFloater& self = static_cast<const LLCoordFloater&>(LLCoordFloater::getTypedCoords(*this)); + + LLRect snap_rect = gFloaterView->getSnapRect(); + LLRect floater_view_screen_rect = gFloaterView->calcScreenRect(); + snap_rect.translate(floater_view_screen_rect.mLeft, floater_view_screen_rect.mBottom); + + 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&>(LLCoordFloater::getTypedCoords(*this)); + LLRect snap_rect = gFloaterView->getSnapRect(); + LLRect floater_view_screen_rect = gFloaterView->calcScreenRect(); + snap_rect.translate(floater_view_screen_rect.mLeft, floater_view_screen_rect.mBottom); + + + 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); + } +} |