diff options
author | Todd Stinson <stinson@lindenlab.com> | 2012-04-03 11:06:33 -0700 |
---|---|---|
committer | Todd Stinson <stinson@lindenlab.com> | 2012-04-03 11:06:33 -0700 |
commit | 36a0a58487063152d8aacdeb22060025fe0021c7 (patch) | |
tree | 58a59dee2b88e1e51391987b157a37b3c8cd710b /indra/llui | |
parent | 8b5b0ace9bfb83540fbc73376b639180d6d63a3b (diff) | |
parent | fa6add3fcd300b21142e3381f35851b3404ee02a (diff) |
Pull and merge from ssh://hg@bitbucket.org/lindenlab/viewer-development.
Diffstat (limited to 'indra/llui')
-rw-r--r-- | indra/llui/llclipboard.cpp | 136 | ||||
-rw-r--r-- | indra/llui/llclipboard.h | 72 | ||||
-rw-r--r-- | indra/llui/llfloater.cpp | 271 | ||||
-rw-r--r-- | indra/llui/llfloater.h | 32 | ||||
-rw-r--r-- | indra/llui/llfloaterreg.cpp | 41 | ||||
-rw-r--r-- | indra/llui/llfloaterreg.h | 4 | ||||
-rw-r--r-- | indra/llui/lllayoutstack.cpp | 73 | ||||
-rw-r--r-- | indra/llui/lllayoutstack.h | 2 | ||||
-rw-r--r-- | indra/llui/lllineeditor.cpp | 19 | ||||
-rw-r--r-- | indra/llui/llscrollcontainer.cpp | 15 | ||||
-rw-r--r-- | indra/llui/llscrollcontainer.h | 6 | ||||
-rw-r--r-- | indra/llui/llscrolllistctrl.cpp | 2 | ||||
-rw-r--r-- | indra/llui/lltexteditor.cpp | 20 | ||||
-rw-r--r-- | indra/llui/llview.cpp | 225 | ||||
-rw-r--r-- | indra/llui/llview.h | 2 |
15 files changed, 541 insertions, 379 deletions
diff --git a/indra/llui/llclipboard.cpp b/indra/llui/llclipboard.cpp index 6910b962a1..14173fdbb0 100644 --- a/indra/llui/llclipboard.cpp +++ b/indra/llui/llclipboard.cpp @@ -34,109 +34,113 @@ #include "llview.h" #include "llwindow.h" -// Global singleton -LLClipboard gClipboard; - - -LLClipboard::LLClipboard() +LLClipboard::LLClipboard() : + mGeneration(0) { - mSourceItem = NULL; + reset(); } - LLClipboard::~LLClipboard() { + reset(); } - -void LLClipboard::copyFromSubstring(const LLWString &src, S32 pos, S32 len, const LLUUID& source_id ) +void LLClipboard::reset() { - mSourceID = source_id; - mString = src.substr(pos, len); - LLView::getWindow()->copyTextToClipboard( mString ); + // Increment the clipboard count + mGeneration++; + // Clear the clipboard + mObjects.clear(); + mCutMode = false; + mString = LLWString(); } -void LLClipboard::copyFromString(const LLWString &src, const LLUUID& source_id ) +// Copy the input uuid to the LL clipboard +bool LLClipboard::copyToClipboard(const LLUUID& src, const LLAssetType::EType type) { - mSourceID = source_id; - mString = src; - LLView::getWindow()->copyTextToClipboard( mString ); + reset(); + return addToClipboard(src, type); } -const LLWString& LLClipboard::getPasteWString( LLUUID* source_id ) +// Add the input uuid to the LL clipboard +// Convert the uuid to string and concatenate that string to the system clipboard if legit +bool LLClipboard::addToClipboard(const LLUUID& src, const LLAssetType::EType type) { - if( mSourceID.notNull() ) + bool res = false; + if (src.notNull()) { - LLWString temp_string; - LLView::getWindow()->pasteTextFromClipboard(temp_string); - - if( temp_string != mString ) + res = true; + if (LLAssetType::lookupIsAssetIDKnowable(type)) { - mSourceID.setNull(); - mString = temp_string; + LLWString source = utf8str_to_wstring(src.asString()); + res = addToClipboard(source, 0, source.size()); + } + if (res) + { + mObjects.push_back(src); + mGeneration++; } } - else - { - LLView::getWindow()->pasteTextFromClipboard(mString); - } + return res; +} - if( source_id ) +bool LLClipboard::pasteFromClipboard(std::vector<LLUUID>& inv_objects) const +{ + bool res = false; + S32 count = mObjects.size(); + if (count > 0) { - *source_id = mSourceID; + res = true; + inv_objects.clear(); + for (S32 i = 0; i < count; i++) + { + inv_objects.push_back(mObjects[i]); + } } - - return mString; + return res; } +// Returns true if the LL Clipboard has pasteable items in it +bool LLClipboard::hasContents() const +{ + return (mObjects.size() > 0); +} -BOOL LLClipboard::canPasteString() const +// Returns true if the input uuid is in the list of clipboard objects +bool LLClipboard::isOnClipboard(const LLUUID& object) const { - return LLView::getWindow()->isClipboardTextAvailable(); + std::vector<LLUUID>::const_iterator iter = std::find(mObjects.begin(), mObjects.end(), object); + return (iter != mObjects.end()); } +// Copy the input string to the LL and the system clipboard +bool LLClipboard::copyToClipboard(const LLWString &src, S32 pos, S32 len, bool use_primary) +{ + return addToClipboard(src, pos, len, use_primary); +} -void LLClipboard::copyFromPrimarySubstring(const LLWString &src, S32 pos, S32 len, const LLUUID& source_id ) +// Concatenate the input string to the LL and the system clipboard +bool LLClipboard::addToClipboard(const LLWString &src, S32 pos, S32 len, bool use_primary) { - mSourceID = source_id; mString = src.substr(pos, len); - LLView::getWindow()->copyTextToPrimary( mString ); + return (use_primary ? LLView::getWindow()->copyTextToPrimary(mString) : LLView::getWindow()->copyTextToClipboard(mString)); } - -const LLWString& LLClipboard::getPastePrimaryWString( LLUUID* source_id ) +// Copy the System clipboard to the output string. +// Manage the LL Clipboard / System clipboard consistency +bool LLClipboard::pasteFromClipboard(LLWString &dst, bool use_primary) { - if( mSourceID.notNull() ) - { - LLWString temp_string; - LLView::getWindow()->pasteTextFromPrimary(temp_string); - - if( temp_string != mString ) - { - mSourceID.setNull(); - mString = temp_string; - } - } - else - { - LLView::getWindow()->pasteTextFromPrimary(mString); - } - - if( source_id ) + bool res = (use_primary ? LLView::getWindow()->pasteTextFromPrimary(dst) : LLView::getWindow()->pasteTextFromClipboard(dst)); + if (res) { - *source_id = mSourceID; + mString = dst; } - - return mString; + return res; } - -BOOL LLClipboard::canPastePrimaryString() const +// Return true if there's something on the System clipboard +bool LLClipboard::isTextAvailable(bool use_primary) const { - return LLView::getWindow()->isPrimaryTextAvailable(); + return (use_primary ? LLView::getWindow()->isPrimaryTextAvailable() : LLView::getWindow()->isClipboardTextAvailable()); } -void LLClipboard::setSourceObject(const LLUUID& source_id, LLAssetType::EType type) -{ - mSourceItem = new LLInventoryObject (source_id, LLUUID::null, type, ""); -} diff --git a/indra/llui/llclipboard.h b/indra/llui/llclipboard.h index 9371b94284..fd2e7610df 100644 --- a/indra/llui/llclipboard.h +++ b/indra/llui/llclipboard.h @@ -27,46 +27,68 @@ #ifndef LL_LLCLIPBOARD_H #define LL_LLCLIPBOARD_H +#include <boost/function.hpp> #include "llstring.h" #include "lluuid.h" #include "stdenums.h" +#include "llsingleton.h" +#include "llassettype.h" #include "llinventory.h" +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLClipboard +// +// This class is used to cut/copy/paste text strings and inventory items around +// the world. Use LLClipboard::instance().method() to use its methods. +// Note that the text and UUIDs are loosely coupled only. There are few cases +// where the viewer does offer a serialized version of the UUID on the clipboard. +// In those case, the text is overridden when copying/cutting the item. +// In all other cases, the text and the UUIDs are very much independent. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLClipboard +class LLClipboard : public LLSingleton<LLClipboard> { public: LLClipboard(); ~LLClipboard(); + + // Clears the clipboard + void reset(); + // Returns the state of the clipboard so client can know if it has been modified (comparing with tracked state) + int getGeneration() const { return mGeneration; } - /* We support two flavors of clipboard. The default is the explicitly - copy-and-pasted clipboard. The second is the so-called 'primary' clipboard - which is implicitly copied upon selection on platforms which expect this - (i.e. X11/Linux). */ - - void copyFromSubstring(const LLWString ©_from, S32 pos, S32 len, const LLUUID& source_id = LLUUID::null ); - void copyFromString(const LLWString ©_from, const LLUUID& source_id = LLUUID::null ); - BOOL canPasteString() const; - const LLWString& getPasteWString(LLUUID* source_id = NULL); + // Text strings management: + // ------------------------ + // We support two flavors of text clipboards. The default is the explicitly + // copy-and-pasted clipboard. The second is the so-called 'primary' clipboard + // which is implicitly copied upon selection on platforms which expect this + // (i.e. X11/Linux, Mac). + bool copyToClipboard(const LLWString& src, S32 pos, S32 len, bool use_primary = false); + bool addToClipboard(const LLWString& src, S32 pos, S32 len, bool use_primary = false); + bool pasteFromClipboard(LLWString& dst, bool use_primary = false); + bool isTextAvailable(bool use_primary = false) const; + + // Object list management: + // ----------------------- + // Clears and adds one single object to the clipboard + bool copyToClipboard(const LLUUID& src, const LLAssetType::EType type = LLAssetType::AT_NONE); + // Adds one object to the current list of objects on the clipboard + bool addToClipboard(const LLUUID& src, const LLAssetType::EType type = LLAssetType::AT_NONE); + // Gets a copy of the objects on the clipboard + bool pasteFromClipboard(std::vector<LLUUID>& inventory_objects) const; + + bool hasContents() const; // True if the clipboard has pasteable objects + bool isOnClipboard(const LLUUID& object) const; // True if the input object uuid is on the clipboard - void copyFromPrimarySubstring(const LLWString ©_from, S32 pos, S32 len, const LLUUID& source_id = LLUUID::null ); - BOOL canPastePrimaryString() const; - const LLWString& getPastePrimaryWString(LLUUID* source_id = NULL); + bool isCutMode() const { return mCutMode; } + void setCutMode(bool mode) { mCutMode = mode; mGeneration++; } - // Support clipboard for object known only by their uuid and asset type - void setSourceObject(const LLUUID& source_id, LLAssetType::EType type); - const LLInventoryObject* getSourceObject() { return mSourceItem; } - private: - LLUUID mSourceID; - LLWString mString; - LLInventoryObject* mSourceItem; + std::vector<LLUUID> mObjects; // Objects on the clipboard. Can be empty while mString contains something licit (e.g. text from chat) + LLWString mString; // The text string. If mObjects is not empty, this string is reflecting them (UUIDs for the moment) if the asset type is knowable. + bool mCutMode; // This is a convenience flag for the viewer. + int mGeneration; // Incremented when the clipboard changes so that interested parties can check for changes on the clipboard. }; - -// Global singleton -extern LLClipboard gClipboard; - - #endif // LL_LLCLIPBOARD_H diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 22b20969fc..a8a3a1f906 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -68,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); } } @@ -177,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"), @@ -249,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), @@ -547,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() @@ -569,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) { @@ -863,7 +850,7 @@ void LLFloater::applyControlsAndPosition(LLFloater* other) { if (!applyRectControl()) { - applyPositioning(other); + applyPositioning(other, true); } } } @@ -872,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; } @@ -911,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); - } + 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); + 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; @@ -1072,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 @@ -1250,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"); @@ -1590,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(); @@ -1624,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); @@ -2164,19 +2199,14 @@ 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_right = mLastSnapRect.mRight; - S32 old_top = mLastSnapRect.mTop; - LLView::reshape(width, height, called_from_parent); - S32 new_right = getSnapRect().mRight; - S32 new_top = getSnapRect().mTop; - mLastSnapRect = getSnapRect(); for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) @@ -2189,35 +2219,39 @@ void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent) continue; } - if (!floaterp->isMinimized()) + if (!floaterp->isMinimized() && floaterp->getCanDrag()) { - 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_right - r.mRight); + //LLRect r = floaterp->getRect(); - S32 top_offset = llabs(old_top - 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 translate_x = 0; - S32 translate_y = 0; + //S32 top_offset = llabs(old_top - r.mTop); + //S32 bottom_offset = llabs(r.mBottom - 0); - if (left_offset > right_offset) - { - translate_x = new_right - old_right; - } + S32 translate_x = new_rect.mLeft - old_rect.mLeft; + S32 translate_y = new_rect.mBottom - old_rect.mBottom; - if (top_offset < bottom_offset) - { - translate_y = new_top - old_top; - } + //if (left_offset > right_offset) + //{ + // translate_x = new_right - old_right; + //} + + //if (top_offset < bottom_offset) + //{ + // translate_y = new_top - old_top; + //} // don't reposition immovable floaters - if (floaterp->getCanDrag()) - { - floaterp->translate(translate_x, translate_y); - } + //if (floaterp->getCanDrag()) + //{ + // floaterp->translate(translate_x, translate_y); + //} BOOST_FOREACH(LLHandle<LLFloater> dependent_floater, floaterp->mDependents) { if (dependent_floater.get()) @@ -2913,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()) { @@ -2972,7 +3008,10 @@ void LLFloater::initFromParams(const LLFloater::Params& p) LLPanel::initFromParams(p); // override any follows flags - setFollows(FOLLOWS_NONE); + if (mPositioning != LLFloaterEnums::POSITIONING_SPECIFIED) + { + setFollows(FOLLOWS_NONE); + } mTitle = p.title; mShortTitle = p.short_title; @@ -2991,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 @@ -3113,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); @@ -3272,8 +3306,24 @@ void LLFloater::stackWith(LLFloater& other) next_rect.setLeftTopAndSize(next_rect.mLeft, next_rect.mTop, getRect().getWidth(), getRect().getHeight()); setShape(next_rect); + + 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) { @@ -3306,9 +3356,12 @@ bool LLCoordFloater::operator==(const LLCoordFloater& other) const LLCoordCommon LL_COORD_FLOATER::convertToCommon() const { - const LLCoordFloater& self = static_cast<const LLCoordFloater&>(*this); + 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; @@ -3348,8 +3401,12 @@ LLCoordCommon LL_COORD_FLOATER::convertToCommon() const void LL_COORD_FLOATER::convertFromCommon(const LLCoordCommon& from) { - LLCoordFloater& self = static_cast<LLCoordFloater&>(*this); + 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; diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index a7cc9ae961..64d6dcea04 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -64,12 +64,12 @@ namespace LLFloaterEnums { enum EOpenPositioning { - OPEN_POSITIONING_NONE, - OPEN_POSITIONING_CASCADING, - OPEN_POSITIONING_CASCADE_GROUP, - OPEN_POSITIONING_CENTERED, - OPEN_POSITIONING_SPECIFIED, - OPEN_POSITIONING_COUNT + POSITIONING_RELATIVE, + POSITIONING_CASCADING, + POSITIONING_CASCADE_GROUP, + POSITIONING_CENTERED, + POSITIONING_SPECIFIED, + POSITIONING_COUNT }; } @@ -163,10 +163,7 @@ public: can_dock, show_title; - Optional<LLFloaterEnums::EOpenPositioning> open_positioning; - Optional<S32> specified_left; - Optional<S32> specified_bottom; - + Optional<LLFloaterEnums::EOpenPositioning> positioning; Optional<S32> header_height, legacy_header_height; // HACK see initFromXML() @@ -272,8 +269,6 @@ public: BOOL isResizable() const { return mResizable; } void setResizeLimits( S32 min_width, S32 min_height ); void getResizeLimits( S32* min_width, S32* min_height ) { *min_width = mMinWidth; *min_height = mMinHeight; } - LLRect getSavedRect() const; - bool hasSavedRect() const; static std::string getControlName(const std::string& name, const LLSD& key); static LLControlGroup* getControlGroup(); @@ -355,7 +350,7 @@ public: void enableResizeCtrls(bool enable, bool width = true, bool height = true); - bool isPositioning(LLFloaterEnums::EOpenPositioning p) const { return (p == mOpenPositioning); } + bool isPositioning(LLFloaterEnums::EOpenPositioning p) const { return (p == mPositioning); } protected: void applyControlsAndPosition(LLFloater* other); @@ -363,7 +358,9 @@ protected: virtual bool applyRectControl(); bool applyDockState(); - void applyPositioning(LLFloater* other); + void applyPositioning(LLFloater* other, bool on_open); + void applyRelativePosition(); + void storeRectControl(); void storeVisibilityControl(); void storeDockStateControl(); @@ -427,7 +424,10 @@ public: commit_signal_t* mMinimizeSignal; protected: + bool mSaveRect; std::string mRectControl; + std::string mPosXControl; + std::string mPosYControl; std::string mVisibilityControl; std::string mDocStateControl; LLSD mKey; // Key used for retrieving instances; set (for now) by LLFLoaterReg @@ -453,9 +453,7 @@ private: BOOL mDragOnLeft; BOOL mResizable; - LLFloaterEnums::EOpenPositioning mOpenPositioning; - S32 mSpecifiedLeft; - S32 mSpecifiedBottom; + LLFloaterEnums::EOpenPositioning mPositioning; LLCoordFloater mPosition; S32 mMinWidth; diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index e144b68f5e..9115eb7174 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -96,7 +96,9 @@ LLFloater* LLFloaterReg::getLastFloaterCascading() { LLFloater* inst = *iter; - if (inst->getVisible() && inst->isPositioning(LLFloaterEnums::OPEN_POSITIONING_CASCADING)) + if (inst->getVisible() + && (inst->isPositioning(LLFloaterEnums::POSITIONING_CASCADING) + || inst->isPositioning(LLFloaterEnums::POSITIONING_CASCADE_GROUP))) { if (candidate_rect.mTop > inst->getRect().mTop) { @@ -358,9 +360,7 @@ void LLFloaterReg::restoreVisibleInstances() //static std::string LLFloaterReg::getRectControlName(const std::string& name) { - std::string res = std::string("floater_rect_") + name; - LLStringUtil::replaceChar( res, ' ', '_' ); - return res; + return std::string("floater_rect_") + getBaseControlName(name); } //static @@ -368,19 +368,48 @@ std::string LLFloaterReg::declareRectControl(const std::string& name) { std::string controlname = getRectControlName(name); LLFloater::getControlGroup()->declareRect(controlname, LLRect(), - llformat("Window Position and Size for %s", name.c_str()), + llformat("Window Size for %s", name.c_str()), TRUE); return controlname; } +std::string LLFloaterReg::declarePosXControl(const std::string& name) +{ + std::string controlname = std::string("floater_pos_") + getBaseControlName(name) + "_x"; + LLFloater::getControlGroup()->declareF32(controlname, + 10.f, + llformat("Window X Position for %s", name.c_str()), + TRUE); + return controlname; +} + +std::string LLFloaterReg::declarePosYControl(const std::string& name) +{ + std::string controlname = std::string("floater_pos_") + getBaseControlName(name) + "_y"; + LLFloater::getControlGroup()->declareF32(controlname, + 10.f, + llformat("Window Y Position for %s", name.c_str()), + TRUE); + + return controlname; +} + + //static std::string LLFloaterReg::getVisibilityControlName(const std::string& name) { - std::string res = std::string("floater_vis_") + name; + return std::string("floater_vis_") + getBaseControlName(name); +} + +//static +std::string LLFloaterReg::getBaseControlName(const std::string& name) +{ + std::string res(name); LLStringUtil::replaceChar( res, ' ', '_' ); return res; } + //static std::string LLFloaterReg::declareVisibilityControl(const std::string& name) { diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h index 534cf8b40a..a1e1f8a988 100644 --- a/indra/llui/llfloaterreg.h +++ b/indra/llui/llfloaterreg.h @@ -115,9 +115,11 @@ public: // Control Variables static std::string getRectControlName(const std::string& name); static std::string declareRectControl(const std::string& name); + static std::string declarePosXControl(const std::string& name); + static std::string declarePosYControl(const std::string& name); static std::string getVisibilityControlName(const std::string& name); static std::string declareVisibilityControl(const std::string& name); - + static std::string getBaseControlName(const std::string& name); static std::string declareDockStateControl(const std::string& name); static std::string getDockStateControlName(const std::string& name); diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index ae262f794e..4c730286da 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -113,7 +113,26 @@ S32 LLLayoutPanel::getLayoutDim() const ? getRect().getWidth() : getRect().getHeight())); } - + +S32 LLLayoutPanel::getTargetDim() const +{ + return mTargetDim; +} + +void LLLayoutPanel::setTargetDim(S32 value) +{ + LLRect new_rect(getRect()); + if (mOrientation == LLLayoutStack::HORIZONTAL) + { + new_rect.mRight = new_rect.mLeft + value; + } + else + { + new_rect.mTop = new_rect.mBottom + value; + } + setShape(new_rect, true); +} + S32 LLLayoutPanel::getVisibleDim() const { F32 min_dim = getRelevantMinDim(); @@ -172,12 +191,15 @@ void LLLayoutPanel::handleReshape(const LLRect& new_rect, bool by_user) LLLayoutStack* stackp = dynamic_cast<LLLayoutStack*>(getParent()); if (stackp) { - stackp->mNeedsLayout = true; if (by_user) - { - // tell layout stack to account for new shape + { // tell layout stack to account for new shape + + // make sure that panels have already been auto resized + stackp->updateLayout(); + // now apply requested size to panel stackp->updatePanelRect(this, new_rect); } + stackp->mNeedsLayout = true; } LLPanel::handleReshape(new_rect, by_user); } @@ -241,7 +263,6 @@ void LLLayoutStack::draw() drawChild(panelp, 0, 0, !clip_rect.isEmpty()); } } - mAnimatedThisFrame = false; } void LLLayoutStack::removeChild(LLView* view) @@ -310,7 +331,7 @@ void LLLayoutStack::updateLayout() if (!mNeedsLayout) return; - bool animation_in_progress = animatePanels(); + bool continue_animating = animatePanels(); F32 total_visible_fraction = 0.f; S32 space_to_distribute = (mOrientation == HORIZONTAL) ? getRect().getWidth() @@ -415,7 +436,7 @@ void LLLayoutStack::updateLayout() // clear animation flag at end, since panel resizes will set it // and leave it set if there is any animation in progress - mNeedsLayout = animation_in_progress; + mNeedsLayout = continue_animating; } // end LLLayoutStack::updateLayout LLLayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const @@ -488,6 +509,7 @@ void LLLayoutStack::updateClass() for (instance_iter it = beginInstances(); it != endInstances(); ++it) { it->updateLayout(); + it->mAnimatedThisFrame = false; } } @@ -557,7 +579,7 @@ void LLLayoutStack::normalizeFractionalSizes() bool LLLayoutStack::animatePanels() { - bool animation_in_progress = false; + bool continue_animating = false; // // animate visibility @@ -577,14 +599,15 @@ bool LLLayoutStack::animatePanels() } } - animation_in_progress = true; + mAnimatedThisFrame = true; + continue_animating = true; } else { if (panelp->mVisibleAmt != 1.f) { panelp->mVisibleAmt = 1.f; - animation_in_progress = true; + mAnimatedThisFrame = true; } } } @@ -601,14 +624,15 @@ bool LLLayoutStack::animatePanels() } } - animation_in_progress = true; + continue_animating = true; + mAnimatedThisFrame = true; } else { if (panelp->mVisibleAmt != 0.f) { panelp->mVisibleAmt = 0.f; - animation_in_progress = true; + mAnimatedThisFrame = true; } } } @@ -616,22 +640,31 @@ bool LLLayoutStack::animatePanels() F32 collapse_state = panelp->mCollapsed ? 1.f : 0.f; if (panelp->mCollapseAmt != collapse_state) { - if (!mAnimatedThisFrame) + if (mAnimate) { - panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLCriticalDamp::getInterpolant(mCloseTimeConstant)); - } - animation_in_progress = true; + if (!mAnimatedThisFrame) + { + panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLCriticalDamp::getInterpolant(mCloseTimeConstant)); + } - if (llabs(panelp->mCollapseAmt - collapse_state) < 0.001f) + if (llabs(panelp->mCollapseAmt - collapse_state) < 0.001f) + { + panelp->mCollapseAmt = collapse_state; + } + + mAnimatedThisFrame = true; + continue_animating = true; + } + else { panelp->mCollapseAmt = collapse_state; + mAnimatedThisFrame = true; } } } - mAnimatedThisFrame = true; - - return animation_in_progress; + if (mAnimatedThisFrame) mNeedsLayout = true; + return continue_animating; } void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect& new_rect ) diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index d32caec5f9..648cd5fdce 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -155,6 +155,8 @@ public: void setVisible(BOOL visible); S32 getLayoutDim() const; + S32 getTargetDim() const; + void setTargetDim(S32 value); S32 getMinDim() const { return llmax(0, mMinDim); } void setMinDim(S32 value) { mMinDim = value; } diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 7e84814c51..d0fbf4b913 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -1047,7 +1047,7 @@ void LLLineEditor::cut() // Prepare for possible rollback LLLineEditorRollback rollback( this ); - gClipboard.copyFromSubstring( mText.getWString(), left_pos, length ); + LLClipboard::instance().copyToClipboard( mText.getWString(), left_pos, length ); deleteSelection(); // Validate new string and rollback the if needed. @@ -1078,13 +1078,13 @@ void LLLineEditor::copy() { S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); S32 length = llabs( mSelectionStart - mSelectionEnd ); - gClipboard.copyFromSubstring( mText.getWString(), left_pos, length ); + LLClipboard::instance().copyToClipboard( mText.getWString(), left_pos, length ); } } BOOL LLLineEditor::canPaste() const { - return !mReadOnly && gClipboard.canPasteString(); + return !mReadOnly && LLClipboard::instance().isTextAvailable(); } void LLLineEditor::paste() @@ -1115,14 +1115,7 @@ void LLLineEditor::pasteHelper(bool is_primary) if (can_paste_it) { LLWString paste; - if (is_primary) - { - paste = gClipboard.getPastePrimaryWString(); - } - else - { - paste = gClipboard.getPasteWString(); - } + LLClipboard::instance().pasteFromClipboard(paste, is_primary); if (!paste.empty()) { @@ -1209,13 +1202,13 @@ void LLLineEditor::copyPrimary() { S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); S32 length = llabs( mSelectionStart - mSelectionEnd ); - gClipboard.copyFromPrimarySubstring( mText.getWString(), left_pos, length ); + LLClipboard::instance().copyToClipboard( mText.getWString(), left_pos, length, true); } } BOOL LLLineEditor::canPastePrimary() const { - return !mReadOnly && gClipboard.canPastePrimaryString(); + return !mReadOnly && LLClipboard::instance().isTextAvailable(true); } void LLLineEditor::updatePrimary() diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index 20bed050ad..9b7e30bb04 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -389,10 +389,17 @@ void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height { *show_h_scrollbar = TRUE; *visible_height -= scrollbar_size; - // Note: Do *not* recompute *show_v_scrollbar here because with - // the (- scrollbar_size) we just did we will always add a vertical scrollbar - // even if the height of the items is actually less than the visible size. - // Fear not though: there's enough calcVisibleSize() calls to add a vertical slider later. + + // The view inside the scroll container should not be extended + // to container's full height to ensure the correct computation + // of *show_v_scrollbar after subtracting horizontal scrollbar_size. + + // Must retest now that visible_height has changed + if( !*show_v_scrollbar && ((doc_height - *visible_height) > 1) ) + { + *show_v_scrollbar = TRUE; + *visible_width -= scrollbar_size; + } } } } diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h index 3aa79cc255..d87c95b3d7 100644 --- a/indra/llui/llscrollcontainer.h +++ b/indra/llui/llscrollcontainer.h @@ -91,7 +91,7 @@ public: void setReserveScrollCorner( BOOL b ) { mReserveScrollCorner = b; } LLRect getVisibleContentRect(); LLRect getContentWindowRect(); - const LLRect& getScrolledViewRect() const { return mScrolledView ? mScrolledView->getRect() : LLRect::null; } + virtual const LLRect getScrolledViewRect() const { return mScrolledView ? mScrolledView->getRect() : LLRect::null; } void pageUp(S32 overlap = 0); void pageDown(S32 overlap = 0); void goToTop(); @@ -116,6 +116,9 @@ public: bool autoScroll(S32 x, S32 y); +protected: + LLView* mScrolledView; + private: // internal scrollbar handlers virtual void scrollHorizontal( S32 new_pos ); @@ -124,7 +127,6 @@ private: void calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const; LLScrollbar* mScrollbar[SCROLLBAR_COUNT]; - LLView* mScrolledView; S32 mSize; BOOL mIsOpaque; LLUIColor mBackgroundColor; diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index f7017064d7..802914e25b 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -2520,7 +2520,7 @@ void LLScrollListCtrl::copy() { buffer += (*itor)->getContentsCSV() + "\n"; } - gClipboard.copyFromSubstring(utf8str_to_wstring(buffer), 0, buffer.length()); + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(buffer), 0, buffer.length()); } // virtual diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 3409b6817d..9720dded6c 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1332,7 +1332,7 @@ void LLTextEditor::cut() } S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); S32 length = llabs( mSelectionStart - mSelectionEnd ); - gClipboard.copyFromSubstring( getWText(), left_pos, length, mSourceID ); + LLClipboard::instance().copyToClipboard( getWText(), left_pos, length); deleteSelection( FALSE ); onKeyStroke(); @@ -1352,12 +1352,12 @@ void LLTextEditor::copy() } S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); S32 length = llabs( mSelectionStart - mSelectionEnd ); - gClipboard.copyFromSubstring(getWText(), left_pos, length, mSourceID); + LLClipboard::instance().copyToClipboard(getWText(), left_pos, length); } BOOL LLTextEditor::canPaste() const { - return !mReadOnly && gClipboard.canPasteString(); + return !mReadOnly && LLClipboard::instance().isTextAvailable(); } // paste from clipboard @@ -1393,16 +1393,8 @@ void LLTextEditor::pasteHelper(bool is_primary) return; } - LLUUID source_id; LLWString paste; - if (is_primary) - { - paste = gClipboard.getPastePrimaryWString(&source_id); - } - else - { - paste = gClipboard.getPasteWString(&source_id); - } + LLClipboard::instance().pasteFromClipboard(paste, is_primary); if (paste.empty()) { @@ -1475,12 +1467,12 @@ void LLTextEditor::copyPrimary() } S32 left_pos = llmin( mSelectionStart, mSelectionEnd ); S32 length = llabs( mSelectionStart - mSelectionEnd ); - gClipboard.copyFromPrimarySubstring(getWText(), left_pos, length, mSourceID); + LLClipboard::instance().copyToClipboard(getWText(), left_pos, length, true); } BOOL LLTextEditor::canPastePrimary() const { - return !mReadOnly && gClipboard.canPastePrimaryString(); + return !mReadOnly && LLClipboard::instance().isTextAvailable(true); } void LLTextEditor::updatePrimary() diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 421166dcd4..54843227b7 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1835,7 +1835,10 @@ const LLCtrlQuery & LLView::getFocusRootsQuery() void LLView::setShape(const LLRect& new_rect, bool by_user) { - handleReshape(new_rect, by_user); + if (new_rect != getRect()) + { + handleReshape(new_rect, by_user); + } } void LLView::handleReshape(const LLRect& new_rect, bool by_user) @@ -2225,145 +2228,163 @@ static bool get_last_child_rect(LLView* parent, LLRect *rect) } //static -void LLView::applyXUILayout(LLView::Params& p, LLView* parent) +void LLView::applyXUILayout(LLView::Params& p, LLView* parent, LLRect layout_rect) { + if (!parent) return; + const S32 VPAD = 4; const S32 MIN_WIDGET_HEIGHT = 10; // *NOTE: This will confuse export of floater/panel coordinates unless // the default is also "topleft". JC - if (p.layout().empty() && parent) + if (p.layout().empty()) { p.layout = parent->getLayout(); } - if (parent) + if (layout_rect.isEmpty()) { - LLRect parent_rect = parent->getLocalRect(); - // overwrite uninitialized rect params, using context - LLRect default_rect = parent->getLocalRect(); + layout_rect = parent->getLocalRect(); + } - bool layout_topleft = (p.layout() == "topleft"); + // overwrite uninitialized rect params, using context + LLRect default_rect = parent->getLocalRect(); - // convert negative or centered coordinates to parent relative values - // Note: some of this logic matches the logic in TypedParam<LLRect>::setValueFromBlock() - if (p.rect.left.isProvided() && p.rect.left < 0) p.rect.left = p.rect.left + parent_rect.getWidth(); - if (p.rect.right.isProvided() && p.rect.right < 0) p.rect.right = p.rect.right + parent_rect.getWidth(); - if (p.rect.bottom.isProvided() && p.rect.bottom < 0) p.rect.bottom = p.rect.bottom + parent_rect.getHeight(); - if (p.rect.top.isProvided() && p.rect.top < 0) p.rect.top = p.rect.top + parent_rect.getHeight(); + bool layout_topleft = (p.layout() == "topleft"); + // convert negative or centered coordinates to parent relative values + // Note: some of this logic matches the logic in TypedParam<LLRect>::setValueFromBlock() + if (p.rect.left.isProvided()) + { + p.rect.left = p.rect.left + ((p.rect.left >= 0) ? layout_rect.mLeft : layout_rect.mRight); + } + if (p.rect.right.isProvided()) + { + p.rect.right = p.rect.right + ((p.rect.right >= 0) ? layout_rect.mLeft : layout_rect.mRight); + } + if (p.rect.bottom.isProvided()) + { + p.rect.bottom = p.rect.bottom + ((p.rect.bottom >= 0) ? layout_rect.mBottom : layout_rect.mTop); if (layout_topleft) { //invert top to bottom - if (p.rect.top.isProvided()) p.rect.top = parent_rect.getHeight() - p.rect.top; - if (p.rect.bottom.isProvided()) p.rect.bottom = parent_rect.getHeight() - p.rect.bottom; + p.rect.bottom = layout_rect.mBottom + layout_rect.mTop - p.rect.bottom; } - - // DEPRECATE: automatically fall back to height of MIN_WIDGET_HEIGHT pixels - if (!p.rect.height.isProvided() && !p.rect.top.isProvided() && p.rect.height == 0) + } + if (p.rect.top.isProvided()) + { + p.rect.top = p.rect.top + ((p.rect.top >= 0) ? layout_rect.mBottom : layout_rect.mTop); + if (layout_topleft) { - p.rect.height = MIN_WIDGET_HEIGHT; + //invert top to bottom + p.rect.top = layout_rect.mBottom + layout_rect.mTop - p.rect.top; } + } + + // DEPRECATE: automatically fall back to height of MIN_WIDGET_HEIGHT pixels + if (!p.rect.height.isProvided() && !p.rect.top.isProvided() && p.rect.height == 0) + { + p.rect.height = MIN_WIDGET_HEIGHT; + } - default_rect.translate(0, default_rect.getHeight()); + default_rect.translate(0, default_rect.getHeight()); - // If there was a recently constructed child, use its rectangle - get_last_child_rect(parent, &default_rect); + // If there was a recently constructed child, use its rectangle + get_last_child_rect(parent, &default_rect); - if (layout_topleft) + if (layout_topleft) + { + // Invert the sense of bottom_delta for topleft layout + if (p.bottom_delta.isProvided()) { - // Invert the sense of bottom_delta for topleft layout - if (p.bottom_delta.isProvided()) - { - p.bottom_delta = -p.bottom_delta; - } - else if (p.top_pad.isProvided()) - { - p.bottom_delta = -(p.rect.height + p.top_pad); - } - else if (p.top_delta.isProvided()) - { - p.bottom_delta = - -(p.top_delta + p.rect.height - default_rect.getHeight()); - } - else if (!p.left_delta.isProvided() - && !p.left_pad.isProvided()) - { - // set default position is just below last rect - p.bottom_delta.set(-(p.rect.height + VPAD), false); - } - else - { - p.bottom_delta.set(0, false); - } - - // default to same left edge - if (!p.left_delta.isProvided()) - { - p.left_delta.set(0, false); - } - if (p.left_pad.isProvided()) - { - // left_pad is based on prior widget's right edge - p.left_delta.set(p.left_pad + default_rect.getWidth(), false); - } - - default_rect.translate(p.left_delta, p.bottom_delta); + p.bottom_delta = -p.bottom_delta; } - else - { - // set default position is just below last rect - if (!p.bottom_delta.isProvided()) - { - p.bottom_delta.set(-(p.rect.height + VPAD), false); - } - if (!p.left_delta.isProvided()) - { - p.left_delta.set(0, false); - } - default_rect.translate(p.left_delta, p.bottom_delta); + else if (p.top_pad.isProvided()) + { + p.bottom_delta = -(p.rect.height + p.top_pad); } - - // this handles case where *both* x and x_delta are provided - // ignore x in favor of default x + x_delta - if (p.bottom_delta.isProvided()) p.rect.bottom.set(0, false); - if (p.left_delta.isProvided()) p.rect.left.set(0, false); - - // selectively apply rectangle defaults, making sure that - // params are not flagged as having been "provided" - // as rect params are overconstrained and rely on provided flags - if (!p.rect.left.isProvided()) + else if (p.top_delta.isProvided()) { - p.rect.left.set(default_rect.mLeft, false); - //HACK: get around the fact that setting a rect param component value won't invalidate the existing rect object value - p.rect.paramChanged(p.rect.left, true); + p.bottom_delta = + -(p.top_delta + p.rect.height - default_rect.getHeight()); } - if (!p.rect.bottom.isProvided()) + else if (!p.left_delta.isProvided() + && !p.left_pad.isProvided()) { - p.rect.bottom.set(default_rect.mBottom, false); - p.rect.paramChanged(p.rect.bottom, true); + // set default position is just below last rect + p.bottom_delta.set(-(p.rect.height + VPAD), false); } - if (!p.rect.top.isProvided()) + else { - p.rect.top.set(default_rect.mTop, false); - p.rect.paramChanged(p.rect.top, true); + p.bottom_delta.set(0, false); } - if (!p.rect.right.isProvided()) + + // default to same left edge + if (!p.left_delta.isProvided()) { - p.rect.right.set(default_rect.mRight, false); - p.rect.paramChanged(p.rect.right, true); - + p.left_delta.set(0, false); } - if (!p.rect.width.isProvided()) + if (p.left_pad.isProvided()) { - p.rect.width.set(default_rect.getWidth(), false); - p.rect.paramChanged(p.rect.width, true); + // left_pad is based on prior widget's right edge + p.left_delta.set(p.left_pad + default_rect.getWidth(), false); } - if (!p.rect.height.isProvided()) + + default_rect.translate(p.left_delta, p.bottom_delta); + } + else + { + // set default position is just below last rect + if (!p.bottom_delta.isProvided()) { - p.rect.height.set(default_rect.getHeight(), false); - p.rect.paramChanged(p.rect.height, true); + p.bottom_delta.set(-(p.rect.height + VPAD), false); } + if (!p.left_delta.isProvided()) + { + p.left_delta.set(0, false); + } + default_rect.translate(p.left_delta, p.bottom_delta); + } + + // this handles case where *both* x and x_delta are provided + // ignore x in favor of default x + x_delta + if (p.bottom_delta.isProvided()) p.rect.bottom.set(0, false); + if (p.left_delta.isProvided()) p.rect.left.set(0, false); + + // selectively apply rectangle defaults, making sure that + // params are not flagged as having been "provided" + // as rect params are overconstrained and rely on provided flags + if (!p.rect.left.isProvided()) + { + p.rect.left.set(default_rect.mLeft, false); + //HACK: get around the fact that setting a rect param component value won't invalidate the existing rect object value + p.rect.paramChanged(p.rect.left, true); + } + if (!p.rect.bottom.isProvided()) + { + p.rect.bottom.set(default_rect.mBottom, false); + p.rect.paramChanged(p.rect.bottom, true); + } + if (!p.rect.top.isProvided()) + { + p.rect.top.set(default_rect.mTop, false); + p.rect.paramChanged(p.rect.top, true); + } + if (!p.rect.right.isProvided()) + { + p.rect.right.set(default_rect.mRight, false); + p.rect.paramChanged(p.rect.right, true); + + } + if (!p.rect.width.isProvided()) + { + p.rect.width.set(default_rect.getWidth(), false); + p.rect.paramChanged(p.rect.width, true); + } + if (!p.rect.height.isProvided()) + { + p.rect.height.set(default_rect.getHeight(), false); + p.rect.paramChanged(p.rect.height, true); } } diff --git a/indra/llui/llview.h b/indra/llui/llview.h index fd19309a56..1c35349510 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -505,7 +505,7 @@ public: // Set up params after XML load before calling new(), // usually to adjust layout. - static void applyXUILayout(Params& p, LLView* parent); + static void applyXUILayout(Params& p, LLView* parent, LLRect layout_rect = LLRect()); // For re-export of floaters and panels, convert the coordinate system // to be top-left based. |