diff options
author | Steven Bennetts <steve@lindenlab.com> | 2009-09-07 22:55:07 +0000 |
---|---|---|
committer | Steven Bennetts <steve@lindenlab.com> | 2009-09-07 22:55:07 +0000 |
commit | 79653dfed48105019b8ecca9cf4bfaa2a390e100 (patch) | |
tree | 455943795bf3371bbff0689604cf5eedd903fae4 /indra | |
parent | a9b2296b2b5664cfc8d86c7f99c00c10268e250a (diff) |
merge https://svn.aws.productengine.com/secondlife/export-from-ll/viewer-2-0@1566 https://svn.aws.productengine.com/secondlife/pe/stable-2@1580 -> viewer-2.0.0-3
* Bugs: EXT-807 EXT-810 EXT-811 EXT-784 EXT-820 EXT-393 EXT-826 EXT-811 EXT-801 EXT-808 EXT-393 EXT-743 EXT-699 EXT-397 EXT-812 EXT-736 EXT-744 EXT-809 EXT-306 EXT-854 EXT-857 EXT-790
* New Dev: EXT-694 EXT-393 EXT-367 EXT-819 EXT-795 EXT-827 EXT-788
* EXT-272 - Draggable Landmarks
* EXT-715 - Block List Panel
* EXT-782 - Implement advanced place information accordions
Diffstat (limited to 'indra')
88 files changed, 3184 insertions, 541 deletions
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index 2b4d8ed831..64af6c94f5 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -100,7 +100,7 @@ public: BOOL getIsLinkType() const; // mutators - will not call updateServer(); void setUUID(const LLUUID& new_uuid); - void rename(const std::string& new_name); + virtual void rename(const std::string& new_name); void setParent(const LLUUID& new_parent); void setType(LLAssetType::EType type); diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 99f364a589..45573cd817 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -105,7 +105,7 @@ bool removeSubString(std::string& str, const std::string& substr) size_t pos = str.find(substr); if (pos != string::npos) { - str.erase(pos); + str.erase(pos, substr.size()); return true; } return false; diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 790f2d5729..95d693cdc4 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -34,6 +34,8 @@ set(llui_SOURCE_FILES llconsole.cpp llcontainerview.cpp llctrlselectioninterface.cpp + lldockablefloater.cpp + lldockcontrol.cpp lldraghandle.cpp lleditmenuhandler.cpp llf32uictrl.cpp @@ -113,6 +115,8 @@ set(llui_HEADER_FILES llcontainerview.h llctrlselectioninterface.h lldraghandle.h + lldockablefloater.h + lldockcontrol.h lleditmenuhandler.h llf32uictrl.h llfiltereditor.h diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 98e8c9a988..bf58e19949 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -355,11 +355,19 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask) setFocus(TRUE); } + /* + * ATTENTION! This call fires another mouse down callback. + * If you wish to remove this call emit that signal directly + * by calling LLUICtrl::mMouseDownSignal(x, y, mask); + */ + LLUICtrl::handleMouseDown(x, y, mask); + mMouseDownSignal(this, LLSD()); mMouseDownTimer.start(); mMouseDownFrame = (S32) LLFrameTimer::getFrameCount(); mMouseHeldDownCount = 0; + if (getSoundFlags() & MOUSE_DOWN) { @@ -378,6 +386,13 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) // Always release the mouse gFocusMgr.setMouseCapture( NULL ); + /* + * ATTENTION! This call fires another mouse up callback. + * If you wish to remove this call emit that signal directly + * by calling LLUICtrl::mMouseUpSignal(x, y, mask); + */ + LLUICtrl::handleMouseUp(x, y, mask); + // Regardless of where mouseup occurs, handle callback mMouseUpSignal(this, LLSD()); @@ -460,12 +475,16 @@ BOOL LLButton::handleRightMouseUp(S32 x, S32 y, MASK mask) void LLButton::onMouseEnter(S32 x, S32 y, MASK mask) { + LLUICtrl::onMouseEnter(x, y, mask); + if (isInEnabledChain()) mNeedsHighlight = TRUE; } void LLButton::onMouseLeave(S32 x, S32 y, MASK mask) { + LLUICtrl::onMouseLeave(x, y, mask); + mNeedsHighlight = FALSE; } diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp new file mode 100644 index 0000000000..d0789d6502 --- /dev/null +++ b/indra/llui/lldockablefloater.cpp @@ -0,0 +1,86 @@ +/** + * @file lldockablefloater.cpp + * @brief Creates a panel of a specific kind for a toast + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lldockablefloater.h" + +LLDockableFloater::LLDockableFloater(LLDockControl* dockControl, + const LLSD& key, const Params& params) : + LLFloater(key, params), mDockControl(dockControl) +{ +} + +LLDockableFloater::~LLDockableFloater() +{ +} + +BOOL LLDockableFloater::postBuild() +{ + mDockTongue = LLUI::getUIImage("windows/Flyout_Pointer.png"); + LLFloater::setDocked(true); + return LLView::postBuild(); +} + +void LLDockableFloater::setDocked(bool docked, bool pop_on_undock) +{ + if (docked) + { + mDockControl.get()->on(); + } + else + { + mDockControl.get()->off(); + } + LLFloater::setDocked(docked, pop_on_undock); +} + +void LLDockableFloater::draw() +{ + mDockControl.get()->repositionDockable(); + mDockControl.get()->drawToungue(); + LLFloater::draw(); +} + +void LLDockableFloater::setDockControl(LLDockControl* dockControl) +{ + mDockControl.reset(dockControl); +} +const LLUIImagePtr& LLDockableFloater::getDockTongue() +{ + return mDockTongue; +} + +LLDockControl* LLDockableFloater::getDockControl() +{ + return mDockControl.get(); +} diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h new file mode 100644 index 0000000000..5ece78a925 --- /dev/null +++ b/indra/llui/lldockablefloater.h @@ -0,0 +1,65 @@ +/** + * @file lldockablefloater.h + * @brief Creates a panel of a specific kind for a toast. + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_DOCKABLEFLOATER_H +#define LL_DOCKABLEFLOATER_H + +#include "llerror.h" +#include "llfloater.h" +#include "lldockcontrol.h" + +/** + * Represents floater that can dock. + * In case impossibility deriving from LLDockableFloater use LLDockControl. + */ +class LLDockableFloater : public LLFloater +{ +public: + LOG_CLASS(LLDockableFloater); + LLDockableFloater(LLDockControl* dockControl, const LLSD& key, const Params& params = getDefaultParams()); + virtual ~LLDockableFloater(); + + /* virtula */BOOL postBuild(); + /* virtual */void setDocked(bool docked, bool pop_on_undock = true); + /* virtual */void draw(); + +protected: + void setDockControl(LLDockControl* dockControl); + LLDockControl* getDockControl(); + const LLUIImagePtr& getDockTongue(); + +private: + std::auto_ptr<LLDockControl> mDockControl; + LLUIImagePtr mDockTongue; +}; + +#endif /* LL_DOCKABLEFLOATER_H */ diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp new file mode 100644 index 0000000000..bec7f04cc0 --- /dev/null +++ b/indra/llui/lldockcontrol.cpp @@ -0,0 +1,126 @@ +/** + * @file lldockcontrol.cpp + * @brief Creates a panel of a specific kind for a toast + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lldockcontrol.h" + +LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, + const LLUIImagePtr& dockTongue, DocAt dockAt, bool enabled) : + mDockWidget(dockWidget), mDockableFloater(dockableFloater), mDockTongue( + dockTongue) +{ + mDockAt = dockAt; + if (enabled) + { + on(); + } + else + { + off(); + } +} + +LLDockControl::~LLDockControl() +{ +} + +void LLDockControl::repositionDockable() +{ + if (mEnabled) + { + calculateDockablePosition(); + } +} + +void LLDockControl::calculateDockablePosition() +{ + LLRect dockRect = mDockWidget->calcScreenRect(); + if (mPrevDockRect != dockRect || mRecalculateDocablePosition) + { + LLRect dockableRect = mDockableFloater->calcScreenRect(); + LLRect rootRect = mDockableFloater->getRootView()->getRect(); + + S32 x = 0; + S32 y = 0; + switch (mDockAt) + { + case TOP: + x = dockRect.getCenterX() - dockableRect.getWidth() / 2; + y = dockRect.mTop + mDockTongue->getHeight() + + dockableRect.getHeight(); + if (x < rootRect.mLeft) + { + x = rootRect.mLeft; + } + if (x + dockableRect.getWidth() > rootRect.mRight) + { + x = rootRect.mRight - dockableRect.getWidth(); + } + mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2; + mDockTongueY = dockRect.mTop; + break; + } + dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(), + dockableRect.getHeight()); + LLRect localDocableParentRect; + mDockableFloater->getParent()->screenRectToLocal(dockableRect, + &localDocableParentRect); + mDockableFloater->setRect(localDocableParentRect); + + mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY, + &mDockTongueX, &mDockTongueY); + mPrevDockRect = dockRect; + mRecalculateDocablePosition = false; + } +} + +void LLDockControl::on() +{ + mDockableFloater->setCanDrag(false); + mEnabled = true; + mRecalculateDocablePosition = true; +} + +void LLDockControl::off() +{ + mDockableFloater->setCanDrag(true); + mEnabled = false; +} + +void LLDockControl::drawToungue() +{ + if (mEnabled) + { + mDockTongue->draw(mDockTongueX, mDockTongueY); + } +} diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h new file mode 100644 index 0000000000..0e1f4c8e64 --- /dev/null +++ b/indra/llui/lldockcontrol.h @@ -0,0 +1,81 @@ +/** + * @file lldockcontrol.h + * @brief Creates a panel of a specific kind for a toast. + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_DOCKCONTROL_H +#define LL_DOCKCONTROL_H + +#include "llerror.h" +#include "llview.h" +#include "llfloater.h" +#include "lluiimage.h" + +/** + * Provides services for docking of specified floater. + * This class should be used in case impossibility deriving from LLDockableFloater. + */ +class LLDockControl +{ +public: + enum DocAt + { + TOP + }; + +public: + LOG_CLASS(LLDockControl); + LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, + const LLUIImagePtr& dockTongue, DocAt dockAt, + bool enabled); + virtual ~LLDockControl(); + +public: + void on(); + void off(); + void setDock(LLView* dockWidget) + { mDockWidget = dockWidget;}; + void repositionDockable(); + void drawToungue(); +protected: + virtual void calculateDockablePosition(); +private: + bool mEnabled; + bool mRecalculateDocablePosition; + DocAt mDockAt; + LLView* mDockWidget; + LLRect mPrevDockRect; + LLFloater* mDockableFloater; + LLUIImagePtr mDockTongue; + S32 mDockTongueX; + S32 mDockTongueY; +}; + +#endif /* LL_DOCKCONTROL_H */ diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index b9a253aac8..36a3b007b6 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -123,6 +123,7 @@ LLScrollListCtrl::Params::Params() sort_ascending("sort_ascending", true), commit_on_keyboard_movement("commit_on_keyboard_movement", true), heading_height("heading_height"), + page_lines("page_lines", 0), background_visible("background_visible"), draw_stripes("draw_stripes"), column_padding("column_padding"), @@ -145,7 +146,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) : LLUICtrl(p), mLineHeight(0), mScrollLines(0), - mPageLines(0), + mPageLines(p.page_lines), mMaxSelectable(0), mAllowKeyboardMovement(TRUE), mCommitOnKeyboardMovement(p.commit_on_keyboard_movement), @@ -196,8 +197,6 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) updateLineHeight(); - mPageLines = mLineHeight? (mItemListRect.getHeight()) / mLineHeight : 0; - // Init the scrollbar static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); @@ -214,7 +213,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) sbparams.orientation(LLScrollbar::VERTICAL); sbparams.doc_size(getItemCount()); sbparams.doc_pos(mScrollLines); - sbparams.page_size(mPageLines); + sbparams.page_size( mPageLines ? mPageLines : getItemCount() ); sbparams.change_callback(boost::bind(&LLScrollListCtrl::onScrollChange, this, _1, _2)); sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); sbparams.visible(false); @@ -469,8 +468,12 @@ void LLScrollListCtrl::updateLayout() getChildView("comment_text")->setShape(mItemListRect); // how many lines of content in a single "page" - mPageLines = mLineHeight? mItemListRect.getHeight() / mLineHeight : 0; - BOOL scrollbar_visible = getItemCount() > mPageLines; + S32 page_lines = mLineHeight? mItemListRect.getHeight() / mLineHeight : getItemCount(); + //if mPageLines is NOT provided display all item + if(mPageLines) + page_lines = mPageLines; + + BOOL scrollbar_visible = mLineHeight * getItemCount() > mItemListRect.getHeight(); if (scrollbar_visible) { // provide space on the right for scrollbar @@ -479,7 +482,7 @@ void LLScrollListCtrl::updateLayout() mScrollbar->setOrigin(getRect().getWidth() - mBorderThickness - scrollbar_size, mItemListRect.mBottom); mScrollbar->reshape(scrollbar_size, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0)); - mScrollbar->setPageSize( mPageLines ); + mScrollbar->setPageSize(page_lines); mScrollbar->setDocSize( getItemCount() ); mScrollbar->setVisible(scrollbar_visible); @@ -491,6 +494,9 @@ void LLScrollListCtrl::updateLayout() void LLScrollListCtrl::fitContents(S32 max_width, S32 max_height) { S32 height = llmin( getRequiredRect().getHeight(), max_height ); + if(mPageLines) + height = llmin( mPageLines * mLineHeight + (mDisplayColumnHeaders ? mHeadingHeight : 0), height ); + S32 width = getRect().getWidth(); reshape( width, height ); @@ -721,6 +727,12 @@ void LLScrollListCtrl::setHeadingHeight(S32 heading_height) updateLayout(); } +void LLScrollListCtrl::setPageLines(S32 new_page_lines) +{ + mPageLines = new_page_lines; + + updateLayout(); +} BOOL LLScrollListCtrl::selectFirstItem() { @@ -1367,7 +1379,7 @@ void LLScrollListCtrl::drawItems() S32 y = mItemListRect.mTop - mLineHeight; // allow for partial line at bottom - S32 num_page_lines = mPageLines + 1; + S32 num_page_lines = (mPageLines)? mPageLines : getItemCount() + 1; LLRect item_rect; @@ -1856,7 +1868,7 @@ LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y ) mLineHeight ); // allow for partial line at bottom - S32 num_page_lines = mPageLines + 1; + S32 num_page_lines = (mPageLines)? mPageLines : getItemCount() + 1; S32 line = 0; item_list::iterator iter; @@ -2421,7 +2433,8 @@ void LLScrollListCtrl::scrollToShowSelected() } S32 lowest = mScrollLines; - S32 highest = mScrollLines + mPageLines; + S32 page_lines = (mPageLines)? mPageLines : getItemCount(); + S32 highest = mScrollLines + page_lines; if (index < lowest) { @@ -2430,7 +2443,7 @@ void LLScrollListCtrl::scrollToShowSelected() } else if (highest <= index) { - setScrollPos(index - mPageLines + 1); + setScrollPos(index - page_lines + 1); } } diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 7a7e5be0be..5c18f85160 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -87,6 +87,7 @@ public: // layout Optional<S32> column_padding, + page_lines, heading_height; // sort and search behavior @@ -314,6 +315,11 @@ public: S32 getMaxContentWidth() { return mMaxContentWidth; } void setHeadingHeight(S32 heading_height); + /** + * Sets max visible lines without scroolbar, if this value equals to 0, + * then display all items. + */ + void setPageLines(S32 page_lines ); void setCollapseEmptyColumns(BOOL collapse); LLScrollListItem* hitItem(S32 x,S32 y); @@ -368,11 +374,13 @@ protected: typedef std::deque<LLScrollListItem *> item_list; item_list& getItemList() { return mItemList; } + void updateLineHeight(); + private: void selectPrevItem(BOOL extend_selection); void selectNextItem(BOOL extend_selection); void drawItems(); - void updateLineHeight(); + void updateLineHeightInsert(LLScrollListItem* item); void reportInvalidInput(); BOOL isRepeatedChars(const LLWString& string) const; diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 7a92bfb74c..30bf182deb 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -481,7 +481,10 @@ void LLTextBox::drawText( S32 x, S32 y, const LLWString &text, const LLColor4& c mShadowType, line_length, getRect().getWidth(), NULL, mUseEllipses ); cur_pos += line_length + 1; - y -= llfloor(mDefaultFont->getLineHeight()) + mLineSpacing; + S32 line_height = llfloor(mDefaultFont->getLineHeight()) + mLineSpacing; + y -= line_height; + if(y < line_height) + break; } } } diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 296ccea0e4..51c259ff53 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -3412,11 +3412,8 @@ void LLTextEditor::endOfDoc() // Sets the scrollbar from the cursor position void LLTextEditor::updateScrollFromCursor() { - if (mReadOnly) - { - // no cursor in read only mode - return; - } + // Update scroll position even in read-only mode (when there's no cursor displayed) + // because startOfDoc()/endOfDoc() modify cursor position. See EXT-736. if (!mScrollNeeded) { diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 83d45f0dfa..55d94b325f 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -2741,11 +2741,11 @@ void LLView::notifyParent(const LLSD& info) if(parent) parent->notifyParent(info); } -void LLView::notifyChilds(const LLSD& info) +void LLView::notifyChildren(const LLSD& info) { for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it) { - (*child_it)->notifyChilds(info); + (*child_it)->notifyChildren(info); } } diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 87298b5292..1d48378081 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -550,7 +550,7 @@ public: virtual void handleReshape(const LLRect& rect, bool by_user); virtual void notifyParent(const LLSD& info); - virtual void notifyChilds(const LLSD& info); + virtual void notifyChildren(const LLSD& info); protected: void drawDebugRect(); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 05459cfcac..f4194ed511 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -180,7 +180,6 @@ set(viewer_SOURCE_FILES llfloaterlandholdings.cpp llfloatermap.cpp llfloatermemleak.cpp - llfloatermute.cpp llfloaternamedesc.cpp llfloaternotificationsconsole.cpp llfloateropenobject.cpp @@ -286,6 +285,7 @@ set(viewer_SOURCE_FILES llpanelavatar.cpp llpanelavatarrow.cpp llpanelavatartag.cpp + llpanelblockedlist.cpp llpanelclassified.cpp llpanelcontents.cpp llpaneldirbrowser.cpp @@ -348,6 +348,8 @@ set(viewer_SOURCE_FILES llremoteparcelrequest.cpp llsavedsettingsglue.cpp llscreenchannel.cpp + llsearchcombobox.cpp + llsearchhistory.cpp llselectmgr.cpp llsidetray.cpp llsidetraypanelcontainer.cpp @@ -634,7 +636,6 @@ set(viewer_HEADER_FILES llfloaterlandholdings.h llfloatermap.h llfloatermemleak.h - llfloatermute.h llfloaternamedesc.h llfloaternotificationsconsole.h llfloateropenobject.h @@ -738,6 +739,7 @@ set(viewer_HEADER_FILES llpanelavatar.h llpanelavatarrow.h llpanelavatartag.h + llpanelblockedlist.h llpanelclassified.h llpanelcontents.h llpaneldirbrowser.h @@ -802,6 +804,8 @@ set(viewer_HEADER_FILES llrootview.h llscreenchannel.h llsavedsettingsglue.h + llsearchcombobox.h + llsearchhistory.h llselectmgr.h llsidetray.h llsidetraypanelcontainer.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index e88bc5a91f..32b1443157 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6866,10 +6866,10 @@ <key>Value</key> <integer>0</integer> </map> - <key>ShowPGSearchAll</key> + <key>ShowCameraAndMoveControls</key> <map> <key>Comment</key> - <string>Show/Hide Navigation Bar Favorites Panel</string> + <string>Show/Hide Camera and Move controls in the bottom tray</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -6880,7 +6880,7 @@ <key>ShowNavbarFavoritesPanel</key> <map> <key>Comment</key> - <string>Show/Hide Navigation Bar Navigation Panel</string> + <string>Show/Hide Navigation Bar Favorites Panel</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -6891,6 +6891,17 @@ <key>ShowNavbarNavigationPanel</key> <map> <key>Comment</key> + <string>Show/Hide Navigation Bar Navigation Panel</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowPGSearchAll</key> + <map> + <key>Comment</key> <string>Display results of search All that are flagged as PG</string> <key>Persist</key> <integer>1</integer> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index e1747930b0..08681db6cb 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -47,7 +47,6 @@ #include "llfloaterdirectory.h" #include "llfloaterland.h" -#include "llfloatermute.h" #include "llfloatersnapshot.h" #include "llfloatertools.h" #include "llfloaterworldmap.h" diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index e0322e26b9..a121d327f7 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -223,12 +223,13 @@ BOOL LLAvatarList::update(const std::vector<LLUUID>& all_buddies, const std::str #endif setScrollPos(pos); + updateLineHeight(); LLRect rect = getRequiredRect(); LLSD params; params["action"] = "size_changes"; params["width"] = rect.getWidth(); - params["height"] = rect.getHeight(); + params["height"] = llmax(rect.getHeight(),20) + 5; getParent()->notifyParent(params); diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index fe13d4f652..861f23abb7 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -60,7 +60,6 @@ LLBottomTray::LLBottomTray(const LLSD&) mSysWell = getChild<LLNotificationChiclet>("sys_well"); mSysWell->setNotificationChicletWindow(LLFloaterReg::getInstance("syswell_window")); - LLFloaterReg::getTypedInstance<LLSysWellWindow>("syswell_window")->setSysWell(mSysWell); mChicletPanel->setChicletClickedCallback(boost::bind(&LLBottomTray::onChicletClick,this,_1)); @@ -80,8 +79,16 @@ LLBottomTray::LLBottomTray(const LLSD&) BOOL LLBottomTray::postBuild() { + mCommitCallbackRegistrar.add("ShowCamMoveCtrls.Action", boost::bind(&LLBottomTray::onShowCamMoveCtrlsContextMenuItemClicked, this, _2)); + mEnableCallbackRegistrar.add("ShowCamMoveCtrls.EnableMenuItem", boost::bind(&LLBottomTray::onShowCamMoveCtrlsContextMenuItemEnabled, this, _2)); + + mShowCamMoveCtrlsContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_hide_camera_move_controls.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + gMenuHolder->addChild(mShowCamMoveCtrlsContextMenu); + mNearbyChatBar = getChild<LLNearbyChatBar>("chat_bar"); mToolbarStack = getChild<LLLayoutStack>("toolbar_stack"); + mMovementPanel = getChild<LLPanel>("movement_panel"); + mCamPanel = getChild<LLPanel>("cam_panel"); return TRUE; } @@ -205,8 +212,9 @@ void LLBottomTray::setVisible(BOOL visible) child_it != mToolbarStack->getChildList()->end(); child_it++) { LLView* viewp = *child_it; + std::string name = viewp->getName(); - if ("chat_bar" == viewp->getName()) + if ("chat_bar" == name || "movement_panel" == name || "cam_panel" == name) continue; else { @@ -216,3 +224,45 @@ void LLBottomTray::setVisible(BOOL visible) } } +BOOL LLBottomTray::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + if (mShowCamMoveCtrlsContextMenu) + { + mShowCamMoveCtrlsContextMenu->buildDrawLabels(); + mShowCamMoveCtrlsContextMenu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, mShowCamMoveCtrlsContextMenu, x, y); + } + + return TRUE; +} + +bool LLBottomTray::onShowCamMoveCtrlsContextMenuItemEnabled(const LLSD& userdata) +{ + std::string item = userdata.asString(); + + if (item == "show_camera_move_controls") + { + return gSavedSettings.getBOOL("ShowCameraAndMoveControls"); + } + + return FALSE; +} + +void LLBottomTray::onShowCamMoveCtrlsContextMenuItemClicked(const LLSD& userdata) +{ + std::string item = userdata.asString(); + + if (item == "show_camera_move_controls") + { + BOOL state = !gSavedSettings.getBOOL("ShowCameraAndMoveControls"); + + showCameraAndMoveControls(state); + gSavedSettings.setBOOL("ShowCameraAndMoveControls", state); + } +} + +void LLBottomTray::showCameraAndMoveControls(BOOL visible) +{ + mCamPanel->setVisible(visible); + mMovementPanel->setVisible(visible); +} diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index a8fe65a9d3..c3c840ede0 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -33,6 +33,8 @@ #ifndef LL_LLBOTTOMPANEL_H #define LL_LLBOTTOMPANEL_H +#include <llmenugl.h> + #include "llpanel.h" #include "llimview.h" @@ -68,6 +70,10 @@ public: virtual void onFocusLost(); virtual void setVisible(BOOL visible); + virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + + void showCameraAndMoveControls(BOOL visible); + private: protected: @@ -76,6 +82,9 @@ protected: void onChicletClick(LLUICtrl* ctrl); + bool onShowCamMoveCtrlsContextMenuItemEnabled(const LLSD& userdata); + void onShowCamMoveCtrlsContextMenuItemClicked(const LLSD& userdata); + static void* createNearbyChatBar(void* userdata); /** @@ -88,7 +97,9 @@ protected: LLTalkButton* mTalkBtn; LLNearbyChatBar* mNearbyChatBar; LLLayoutStack* mToolbarStack; - + LLMenuGL* mShowCamMoveCtrlsContextMenu; + LLPanel* mMovementPanel; + LLPanel* mCamPanel; }; #endif // LL_LLBOTTOMPANEL_H diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 1109d8174f..808fcde312 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -117,6 +117,10 @@ boost::signals2::connection LLNotificationChiclet::setClickCallback( return mButton->setClickedCallback(cb); } +void LLNotificationChiclet::setToggleState(BOOL toggled) { + mButton->setToggleState(toggled); +} + void LLNotificationChiclet::updateUreadIMNotifications() { mUreadIMNotifications = gIMMgr->getNumberOfUnreadIM(); @@ -235,6 +239,7 @@ LLIMP2PChiclet::Params::Params() avatar_icon.name("avatar_icon"); avatar_icon.rect(LLRect(0, 25, 25, 0)); + avatar_icon.mouse_opaque(false); unread_notifications.name("unread"); unread_notifications.rect(LLRect(25, 25, 45, 0)); @@ -242,6 +247,7 @@ LLIMP2PChiclet::Params::Params() unread_notifications.font_halign(LLFontGL::HCENTER); unread_notifications.v_pad(5); unread_notifications.text_color(LLColor4::white); + unread_notifications.mouse_opaque(false); speaker.name("speaker"); speaker.rect(LLRect(45, 25, 65, 0)); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index ba202515a8..f96dfb69ec 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -537,6 +537,7 @@ public: void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications + mUreadIMNotifications); } void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications + mUreadIMNotifications); } void updateUreadIMNotifications(); + void setToggleState(BOOL toggled); protected: LLNotificationChiclet(const Params& p); diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 7ad60232c7..a7f0a8ff9a 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -55,6 +55,7 @@ #include "llviewerinventory.h" #include "llviewermenu.h" #include "llviewermenu.h" +#include "lltooldraganddrop.h" static LLDefaultChildRegistry::Register<LLFavoritesBarCtrl> r("favorites_bar"); @@ -73,6 +74,7 @@ public: , mLoaded(false) {} void setLandmarkID(const LLUUID& id) { mLandmarkID = id; } + const LLUUID& getLandmarkId() const { return mLandmarkID; } const std::string& getSLURL() { @@ -130,8 +132,21 @@ public: msg = mUrlGetter.getSLURL(); return TRUE; } + + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) + { + LLFavoritesBarCtrl* fb = dynamic_cast<LLFavoritesBarCtrl*>(getParent()); + + if (fb) + { + fb->handleHover(x, y, mask); + } + + return LLButton::handleHover(x, y, mask); + } void setLandmarkID(const LLUUID& id){ mUrlGetter.setLandmarkID(id); } + const LLUUID& getLandmarkId() const { return mUrlGetter.getLandmarkId(); } protected: LLFavoriteLandmarkButton(const LLButton::Params& p) : LLButton(p) {} @@ -141,6 +156,33 @@ private: LLSLURLGetter mUrlGetter; }; +class LLFavoritesToggleableMenu : public LLToggleableMenu +{ +public: + virtual BOOL handleHover(S32 x, S32 y, MASK mask) + { + if (fb) + { + fb->handleHover(x, y, mask); + } + + return LLToggleableMenu::handleHover(x, y, mask); + } + + void initFavoritesBarPointer(LLFavoritesBarCtrl* fb) { this->fb = fb; } + +protected: + LLFavoritesToggleableMenu(const LLToggleableMenu::Params& p): + LLToggleableMenu(p) + { + } + + friend class LLUICtrlFactory; + +private: + LLFavoritesBarCtrl* fb; +}; + /** * This class is needed to override LLMenuItemCallGL default handleToolTip function and * show SLURL as button tooltip. @@ -164,6 +206,18 @@ public: void setLandmarkID(const LLUUID& id){ mUrlGetter.setLandmarkID(id); } + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) + { + mMouseDownSignal(this, x, y, mask); + return LLMenuItemCallGL::handleMouseDown(x, y, mask); + } + + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) + { + mMouseUpSignal(this, x, y, mask); + return LLMenuItemCallGL::handleMouseUp(x, y, mask); + } + protected: LLFavoriteLandmarkMenuItem(const LLMenuItemCallGL::Params& p) : LLMenuItemCallGL(p) {} @@ -181,6 +235,14 @@ struct LLFavoritesSort // TODO - made it customizible using gSavedSettings bool operator()(const LLViewerInventoryItem* const& a, const LLViewerInventoryItem* const& b) { + S32 sortField1 = a->getSortField(); + S32 sortField2 = b->getSortField(); + + if (!(sortField1 < 0 && sortField2 < 0)) + { + return sortField2 > sortField1; + } + time_t first_create = a->getCreationDate(); time_t second_create = b->getCreationDate(); if (first_create == second_create) @@ -239,29 +301,34 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, case DAD_LANDMARK: { // Copy the item into the favorites folder (if it's not already there). - LLInventoryItem *item = (LLInventoryItem *)cargo_data; - LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE); - if (item->getParentUUID() == favorites_id) + LLInventoryItem *item = (LLInventoryItem *)cargo_data; + + // check if we are dragging an existing item from the favorites bar + if (item && mDragItemId == item->getUUID()) { - llwarns << "Attemt to copy a favorite item into the same folder." << llendl; - break; + *accept = ACCEPT_YES_SINGLE; + + if (drop) + { + handleExistingFavoriteDragAndDrop(x, y); + } } + else + { + LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE); + if (item->getParentUUID() == favorites_id) + { + llwarns << "Attemt to copy a favorite item into the same folder." << llendl; + break; + } - *accept = ACCEPT_YES_COPY_SINGLE; + *accept = ACCEPT_YES_COPY_SINGLE; - if (drop) - { - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - favorites_id, - std::string(), - LLPointer<LLInventoryCallback>(NULL)); - - llinfos << "Copied inventory item #" << item->getUUID() << " to favorites." << llendl; + if (drop) + { + handleNewFavoriteDragAndDrop(item, favorites_id, x, y); + } } - } break; default: @@ -271,6 +338,61 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, return TRUE; } +void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y) +{ + LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(findChildByLocalCoords(x, y)); + + if (dest) + { + updateItemsOrder(mItems, mDragItemId, dest->getLandmarkId()); + } + else + { + mItems.push_back(gInventory.getItem(mDragItemId)); + } + + saveItemsOrder(mItems); + + LLFavoritesToggleableMenu* menu = (LLFavoritesToggleableMenu*) mPopupMenuHandle.get(); + + if (menu && menu->getVisible()) + { + menu->setVisible(FALSE); + showDropDownMenu(); + } + + mDragItemId = LLUUID::null; + getWindow()->setCursor(UI_CURSOR_ARROW); +} + +void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, const LLUUID& favorites_id, S32 x, S32 y) +{ + LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(findChildByLocalCoords(x, y)); + + if (dest) + { + insertBeforeItem(mItems, dest->getLandmarkId(), item->getUUID()); + } + else + { + mItems.push_back(gInventory.getItem(item->getUUID())); + } + + saveItemsOrder(mItems); + + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + favorites_id, + std::string(), + LLPointer<LLInventoryCallback>(NULL)); + + getWindow()->setCursor(UI_CURSOR_ARROW); + + llinfos << "Copied inventory item #" << item->getUUID() << " to favorites." << llendl; +} + //virtual void LLFavoritesBarCtrl::changed(U32 mask) { @@ -311,9 +433,9 @@ LLXMLNodePtr LLFavoritesBarCtrl::getButtonXMLNode() void LLFavoritesBarCtrl::updateButtons(U32 bar_width) { - LLInventoryModel::item_array_t items; + mItems.clear(); - if (!collectFavoriteItems(items)) + if (!collectFavoriteItems(mItems)) { return; } @@ -331,7 +453,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width) const S32 buttonVGap = 2; - S32 count = items.count(); + S32 count = mItems.count(); const S32 buttonHPad = LLUI::sSettingGroups["config"]->getS32("ButtonHPad"); const S32 chevron_button_width = mFont->getWidth(">>") + buttonHPad * 2; @@ -369,7 +491,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width) S32 i; for (i = 0; i < mFirstDropDownItem; ++i) { - if (mItemNamesCache.get(i) != items.get(i)->getName()) + if (mItemNamesCache.get(i) != mItems.get(i)->getName()) { break; } @@ -387,7 +509,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width) mItemNamesCache.clear(); for (S32 i = 0; i < mFirstDropDownItem; i++) { - mItemNamesCache.put(items.get(i)->getName()); + mItemNamesCache.put(mItems.get(i)->getName()); } // Rebuild the buttons only @@ -404,7 +526,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width) } } - createButtons(items, buttonXMLNode, buttonWidth, buttonHGap); + createButtons(mItems, buttonXMLNode, buttonWidth, buttonHGap); } // Chevron button @@ -467,9 +589,9 @@ void LLFavoritesBarCtrl::createButtons(const LLInventoryModel::item_array_t &ite { S32 curr_x = buttonHGap; // Adding buttons - for(S32 i = mFirstDropDownItem -1; i >= 0; i--) + for(S32 i = mFirstDropDownItem -1, j = 0; i >= 0; i--) { - LLInventoryItem* item = items.get(i); + LLViewerInventoryItem* item = items.get(j++); LLFavoriteLandmarkButton* fav_btn = LLUICtrlFactory::defaultBuilder<LLFavoriteLandmarkButton>(buttonXMLNode, this, NULL); if (NULL == fav_btn) @@ -488,6 +610,10 @@ void LLFavoritesBarCtrl::createButtons(const LLInventoryModel::item_array_t &ite fav_btn->setToolTip(item->getName()); fav_btn->setCommitCallback(boost::bind(&LLFavoritesBarCtrl::onButtonClick, this, item->getUUID())); fav_btn->setRightMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this, item->getUUID(), _1, _2, _3,_4 )); + + fav_btn->LLUICtrl::setMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseDown, this, item->getUUID(), _1, _2, _3, _4)); + fav_btn->LLUICtrl::setMouseUpCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseUp, this, item->getUUID(), _1, _2, _3, _4)); + sendChildToBack(fav_btn); curr_x += buttonWidth + buttonHGap; @@ -521,6 +647,15 @@ BOOL LLFavoritesBarCtrl::collectFavoriteItems(LLInventoryModel::item_array_t &it std::sort(items.begin(), items.end(), LLFavoritesSort()); + if (needToSaveItemsOrder(items)) + { + S32 sortField = 0; + for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) + { + (*i)->setSortField(++sortField); + } + } + return TRUE; } @@ -528,7 +663,7 @@ void LLFavoritesBarCtrl::showDropDownMenu() { if (mPopupMenuHandle.isDead()) { - LLToggleableMenu::Params menu_p; + LLFavoritesToggleableMenu::Params menu_p; menu_p.name("favorites menu"); menu_p.can_tear_off(false); menu_p.visible(false); @@ -536,26 +671,26 @@ void LLFavoritesBarCtrl::showDropDownMenu() menu_p.max_scrollable_items = 10; menu_p.preferred_width = DROP_DOWN_MENU_WIDTH; - LLToggleableMenu* menu = LLUICtrlFactory::create<LLToggleableMenu>(menu_p); - + LLFavoritesToggleableMenu* menu = LLUICtrlFactory::create<LLFavoritesToggleableMenu>(menu_p); + menu->initFavoritesBarPointer(this); mPopupMenuHandle = menu->getHandle(); } - LLToggleableMenu* menu = (LLToggleableMenu*)mPopupMenuHandle.get(); + LLFavoritesToggleableMenu* menu = (LLFavoritesToggleableMenu*)mPopupMenuHandle.get(); if(menu) { if (!menu->toggleVisibility()) return; - LLInventoryModel::item_array_t items; + mItems.clear(); - if (!collectFavoriteItems(items)) + if (!collectFavoriteItems(mItems)) { return; } - S32 count = items.count(); + S32 count = mItems.count(); // Check it there are changed items, since last call if (mItemNamesCache.size() == count) @@ -563,7 +698,7 @@ void LLFavoritesBarCtrl::showDropDownMenu() S32 i; for (i = mFirstDropDownItem; i < count; i++) { - if (mItemNamesCache.get(i) != items.get(i)->getName()) + if (mItemNamesCache.get(i) != mItems.get(i)->getName()) { break; } @@ -587,7 +722,7 @@ void LLFavoritesBarCtrl::showDropDownMenu() { for (S32 i = mFirstDropDownItem; i < count; i++) { - mItemNamesCache.put(items.get(i)->getName()); + mItemNamesCache.put(mItems.get(i)->getName()); } } @@ -598,17 +733,18 @@ void LLFavoritesBarCtrl::showDropDownMenu() for(S32 i = mFirstDropDownItem; i < count; i++) { - LLInventoryItem* item = items.get(i); + LLViewerInventoryItem* item = mItems.get(i); const std::string& item_name = item->getName(); - LLMenuItemCallGL::Params item_params; + LLFavoriteLandmarkMenuItem::Params item_params; item_params.name(item_name); item_params.label(item_name); item_params.on_click.function(boost::bind(&LLFavoritesBarCtrl::onButtonClick, this, item->getUUID())); LLFavoriteLandmarkMenuItem *menu_item = LLUICtrlFactory::create<LLFavoriteLandmarkMenuItem>(item_params); menu_item->setRightMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this,item->getUUID(),_1,_2,_3,_4)); - menu_item->setLandmarkID(item->getUUID()); + menu_item->LLUICtrl::setMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseDown, this, item->getUUID(), _1, _2, _3, _4)); + menu_item->LLUICtrl::setMouseUpCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseUp, this, item->getUUID(), _1, _2, _3, _4)); // Check whether item name wider than menu if (menu_item->getNominalWidth() > max_width) @@ -644,13 +780,6 @@ void LLFavoritesBarCtrl::showDropDownMenu() void LLFavoritesBarCtrl::onButtonClick(LLUUID item_id) { - LLInventoryModel::item_array_t items; - - if (!collectFavoriteItems(items)) - { - return; - } - // We only have one Inventory, gInventory. Some day this should be better abstracted. LLInvFVBridgeAction::doAction(item_id,&gInventory); } @@ -797,5 +926,135 @@ void LLFavoritesBarCtrl::pastFromClipboard() const } } +void LLFavoritesBarCtrl::onButtonMouseDown(LLUUID id, LLUICtrl* ctrl, S32 x, S32 y, MASK mask) +{ + mDragItemId = id; + mStartDrag = TRUE; + + S32 screenX, screenY; + localPointToScreen(x, y, &screenX, &screenY); + + LLToolDragAndDrop::getInstance()->setDragStart(screenX, screenY); +} + +void LLFavoritesBarCtrl::onButtonMouseUp(LLUUID id, LLUICtrl* ctrl, S32 x, S32 y, MASK mask) +{ + mDragItemId = LLUUID::null; +} + +BOOL LLFavoritesBarCtrl::handleHover(S32 x, S32 y, MASK mask) +{ + if (mDragItemId != LLUUID::null && mStartDrag) + { + S32 screenX, screenY; + localPointToScreen(x, y, &screenX, &screenY); + + if(LLToolDragAndDrop::getInstance()->isOverThreshold(screenX, screenY)) + { + LLToolDragAndDrop::getInstance()->beginDrag( + DAD_LANDMARK, mDragItemId, + LLToolDragAndDrop::SOURCE_LIBRARY); + + mStartDrag = FALSE; + + return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask); + } + } + + return TRUE; +} + +LLUICtrl* LLFavoritesBarCtrl::findChildByLocalCoords(S32 x, S32 y) +{ + LLUICtrl* ctrl = 0; + S32 screenX, screenY; + const child_list_t* list = getChildList(); + + localPointToScreen(x, y, &screenX, &screenY); + + // look for a child which contains the point (screenX, screenY) in it's rectangle + for (child_list_const_iter_t i = list->begin(); i != list->end(); ++i) + { + LLRect rect; + localRectToScreen((*i)->getRect(), &rect); + + if (rect.pointInRect(screenX, screenY)) + { + ctrl = dynamic_cast<LLUICtrl*>(*i); + break; + } + } + + return ctrl; +} + +BOOL LLFavoritesBarCtrl::needToSaveItemsOrder(const LLInventoryModel::item_array_t& items) +{ + BOOL result = FALSE; + + // if there is an item without sort order field set, we need to save items order + for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i) + { + if ((*i)->getSortField() < 0) + { + result = TRUE; + break; + } + } + + return result; +} + +void LLFavoritesBarCtrl::saveItemsOrder(LLInventoryModel::item_array_t& items) +{ + int sortField = 0; + + // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field + for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) + { + LLViewerInventoryItem* item = *i; + + item->setSortField(++sortField); + item->setComplete(TRUE); + item->updateServer(FALSE); + + gInventory.updateItem(item); + } + + gInventory.notifyObservers(); +} + +LLInventoryModel::item_array_t::iterator LLFavoritesBarCtrl::findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id) +{ + LLInventoryModel::item_array_t::iterator result = items.end(); + + for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) + { + if ((*i)->getUUID() == id) + { + result = i; + break; + } + } + + return result; +} + +void LLFavoritesBarCtrl::updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId) +{ + LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId); + LLViewerInventoryItem* destItem = gInventory.getItem(destItemId); + + items.erase(findItemByUUID(items, srcItem->getUUID())); + items.insert(findItemByUUID(items, destItem->getUUID()), srcItem); +} + +void LLFavoritesBarCtrl::insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, const LLUUID& insertedItemId) +{ + LLViewerInventoryItem* beforeItem = gInventory.getItem(beforeItemId); + LLViewerInventoryItem* insertedItem = gInventory.getItem(insertedItemId); + + items.insert(findItemByUUID(items, beforeItem->getUUID()), insertedItem); +} // EOF diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 824b396add..4cd92d1a58 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -60,6 +60,8 @@ public: EAcceptance* accept, std::string& tooltip_msg); + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); + // LLInventoryObserver observer trigger virtual void changed(U32 mask); virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); @@ -73,10 +75,12 @@ protected: void onButtonClick(LLUUID id); void onButtonRightClick(LLUUID id,LLView* button,S32 x,S32 y,MASK mask); + void onButtonMouseDown(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask); + void onButtonMouseUp(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask); + void doToSelected(const LLSD& userdata); BOOL isClipboardPasteable() const; void pastFromClipboard() const; - void showDropDownMenu(); @@ -94,8 +98,49 @@ protected: LLRect mChevronRect; std::string mChevronButtonToolTip; + +private: + /* + * Helper function to make code more readable. It handles all drag and drop + * operations of the existing favorites items on the favorites bar. + */ + void handleExistingFavoriteDragAndDrop(S32 x, S32 y); + + /* + * Helper function to make code more readable. It handles all drag and drop + * operations of the new landmark to the favorites bar. + */ + void handleNewFavoriteDragAndDrop(LLInventoryItem *item, const LLUUID& favorites_id, S32 x, S32 y); + + // finds a control under the specified LOCAL point + LLUICtrl* findChildByLocalCoords(S32 x, S32 y); + + // checks if the current order of the favorites items must be saved + BOOL needToSaveItemsOrder(const LLInventoryModel::item_array_t& items); + + // saves current order of the favorites items + void saveItemsOrder(LLInventoryModel::item_array_t& items); + + /* + * changes favorites items order by insertion of the item identified by srcItemId + * BEFORE the item identified by destItemId. both items must exist in items array. + */ + void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId); + + /* + * inserts an item identified by insertedItemId BEFORE an item identified by beforeItemId. + * this function assumes that an item identified by insertedItemId doesn't exist in items array. + */ + void insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, const LLUUID& insertedItemId); + + // finds an item by it's UUID in the items array + LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id); + + BOOL mSkipUpdate; + BOOL mStartDrag; + LLUUID mDragItemId; + LLInventoryModel::item_array_t mItems; }; #endif // LL_LLFAVORITESBARCTRL_H - diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index 0dee3a1e83..14fb93df61 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -47,7 +47,6 @@ #include "llconsole.h" #include "llfloateractivespeakers.h" #include "llfloaterchatterbox.h" -#include "llfloatermute.h" #include "llfloaterreg.h" #include "llfloaterscriptdebug.h" #include "llkeyboard.h" @@ -56,6 +55,7 @@ //#include "llresizehandle.h" #include "llchatbar.h" #include "llrecentpeople.h" +#include "llpanelblockedlist.h" #include "llstatusbar.h" #include "llviewertexteditor.h" #include "llviewergesture.h" // for triggering gestures @@ -280,7 +280,7 @@ void LLFloaterChat::onClickMute(void *data) LLMute mute(id); mute.setFromDisplayName(name); LLMuteList::getInstance()->add(mute); - LLFloaterReg::showInstance("mute"); + LLPanelBlockedList::showPanelAndSelect(mute.mID); } //static diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index c47c7b073c..d389cf06ec 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -61,6 +61,7 @@ #include "llnavigationbar.h" #include "llpanellogin.h" #include "llradiogroup.h" +#include "llsearchcombobox.h" #include "llsky.h" #include "llscrolllistctrl.h" #include "llscrolllistitem.h" @@ -214,6 +215,11 @@ bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response // flag client texture cache for clearing next time the client runs gSavedSettings.setBOOL("PurgeCacheOnNextStartup", TRUE); LLNotifications::instance().add("CacheWillClear"); + + LLSearchHistory::getInstance()->clearHistory(); + LLSearchHistory::getInstance()->save(); + LLSearchComboBox* search_ctrl = LLNavigationBar::getInstance()->getChild<LLSearchComboBox>("search_combo_box"); + search_ctrl->clearHistory(); } return false; diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp index bef5f094e3..97b7f3e9ad 100644 --- a/indra/newview/llfriendcard.cpp +++ b/indra/newview/llfriendcard.cpp @@ -173,6 +173,15 @@ bool LLFriendCardsManager::isCategoryInFriendFolder(const LLViewerInventoryCateg return TRUE == gInventory.isObjectDescendentOf(cat->getUUID(), findFriendFolderUUIDImpl()); } +bool LLFriendCardsManager::isAnyFriendCategory(const LLUUID& catID) const +{ + const LLUUID& friendFolderID = findFriendFolderUUIDImpl(); + if (catID == friendFolderID) + return true; + + return TRUE == gInventory.isObjectDescendentOf(catID, friendFolderID); +} + void LLFriendCardsManager::syncFriendsFolder() { //lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" if they are absent @@ -305,10 +314,12 @@ void LLFriendCardsManager::findMatchedFriendCards(const LLUUID& avatarID, LLInve LLInventoryModel::cat_array_t cats; LLUUID friendFolderUUID = findFriendFolderUUIDImpl(); - LLParticularBuddyCollector matchFunctor(avatarID); LLViewerInventoryCategory* friendFolder = gInventory.getCategory(friendFolderUUID); + if (NULL == friendFolder) + return; + LLParticularBuddyCollector matchFunctor(avatarID); LLInventoryModel::cat_array_t subFolders; subFolders.push_back(friendFolder); diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h index 18a6d0ab69..aa391ce2c1 100644 --- a/indra/newview/llfriendcard.h +++ b/indra/newview/llfriendcard.h @@ -77,6 +77,11 @@ public: bool isCategoryInFriendFolder(const LLViewerInventoryCategory* cat) const; /** + * Checks is the specified category is a Friend folder or any its subfolder + */ + bool isAnyFriendCategory(const LLUUID& catID) const; + + /** * Synchronizes content of the Calling Card/Friends/All Global Inventory folder with Agent's Friend List */ void syncFriendsFolder(); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 789e628b67..adc73111e0 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2420,8 +2420,14 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, drop); break; case DAD_CATEGORY: - accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, - drop); + if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID)) + { + accept = FALSE; + } + else + { + accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop); + } break; default: break; diff --git a/indra/newview/lllocationhistory.cpp b/indra/newview/lllocationhistory.cpp index c83cde9d83..d910dbf718 100644 --- a/indra/newview/lllocationhistory.cpp +++ b/indra/newview/lllocationhistory.cpp @@ -37,59 +37,41 @@ #include <iomanip> // for std::setw() #include "llui.h" - -const char LLLocationHistory::delimiter = '\t'; +#include "llsd.h" +#include "llsdserialize.h" LLLocationHistory::LLLocationHistory() : mFilename("typed_locations.txt") { } -void LLLocationHistory::addItem(const std::string & item, const std::string & tooltip) { +void LLLocationHistory::addItem(const LLLocationHistoryItem& item) { static LLUICachedControl<S32> max_items("LocationHistoryMaxSize", 100); // check if this item doesn't duplicate any existing one - std::vector<std::string>::iterator item_iter = std::find_if(mItems.begin(), mItems.end(), - boost::bind(&LLLocationHistory::equalByRegionParcel,this,_1,item)); + location_list_t::iterator item_iter = std::find(mItems.begin(), mItems.end(),item); if(item_iter != mItems.end()){ - /*replace duplicate. - * If an item's region and item's parcel are equal. - */ - mToolTips.erase(*item_iter); mItems.erase(item_iter); - } mItems.push_back(item); - mToolTips[item] = tooltip; - + // If the vector size exceeds the maximum, purge the oldest items. if ((S32)mItems.size() > max_items) { - for(std::vector<std::string>::iterator i = mItems.begin(); i != mItems.end()-max_items; ++i) { - mToolTips.erase(*i); - mItems.erase(i); + for(location_list_t::iterator i = mItems.begin(); i != mItems.end()-max_items; ++i) { + mItems.erase(i); } } } -/** - * check if the history item is equal. - * @return true - if region name and parcel is equal. +/* + * @brief Try to find item in history. + * If item has been founded, it will be places into end of history. + * @return true - item has founded */ -bool LLLocationHistory::equalByRegionParcel(const std::string& item, const std::string& newItem){ - - - S32 itemIndex = item.find('('); - S32 newItemIndex = newItem.find('('); - - std::string region_parcel = item.substr(0,itemIndex); - std::string new_region_parcel = newItem.substr(0,newItemIndex); - - return region_parcel == new_region_parcel; -} -bool LLLocationHistory::touchItem(const std::string & item) { +bool LLLocationHistory::touchItem(const LLLocationHistoryItem& item) { bool result = false; - std::vector<std::string>::iterator item_iter = std::find(mItems.begin(), mItems.end(), item); + location_list_t::iterator item_iter = std::find(mItems.begin(), mItems.end(), item); // the last used item should be the first in the history if (item_iter != mItems.end()) { @@ -104,13 +86,6 @@ bool LLLocationHistory::touchItem(const std::string & item) { void LLLocationHistory::removeItems() { mItems.clear(); - mToolTips.clear(); -} - -std::string LLLocationHistory::getToolTip(const std::string & item) const { - std::map<std::string, std::string>::const_iterator i = mToolTips.find(item); - - return i != mToolTips.end() ? i->second : ""; } bool LLLocationHistory::getMatchingItems(std::string substring, location_list_t& result) const @@ -123,7 +98,7 @@ bool LLLocationHistory::getMatchingItems(std::string substring, location_list_t& for (location_list_t::const_iterator it = mItems.begin(); it != mItems.end(); ++it) { - std::string haystack = *it; + std::string haystack = it->getLocation(); LLStringUtil::toLower(haystack); if (haystack.find(needle) != std::string::npos) @@ -139,7 +114,7 @@ void LLLocationHistory::dump() const int i = 0; for (location_list_t::const_iterator it = mItems.begin(); it != mItems.end(); ++it, ++i) { - llinfos << "#" << std::setw(2) << std::setfill('0') << i << ": " << *it << llendl; + llinfos << "#" << std::setw(2) << std::setfill('0') << i << ": " << it->getLocation() << llendl; } } @@ -158,11 +133,7 @@ void LLLocationHistory::save() const for (location_list_t::const_iterator it = mItems.begin(); it != mItems.end(); ++it) { - std::string tooltip = getToolTip(*it); - if(!tooltip.empty()) - { - file << (*it) << delimiter << tooltip << std::endl; - } + file << LLSDOStreamer<LLSDNotationFormatter>((*it).toLLSD()) << std::endl; } file.close(); @@ -186,16 +157,17 @@ void LLLocationHistory::load() // add each line in the file to the list std::string line; - + LLPointer<LLSDParser> parser = new LLSDNotationParser(); while (std::getline(file, line)) { - size_t dp = line.find(delimiter); - - if (dp != std::string::npos) { - const std::string reg_name = line.substr(0, dp); - const std::string tooltip = line.substr(dp + 1, std::string::npos); - - addItem(reg_name, tooltip); + LLSD s_item; + std::istringstream iss(line); + if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE) + { + llinfos<< "Parsing saved teleport history failed" << llendl; + break; } + + mItems.push_back(s_item); } file.close(); diff --git a/indra/newview/lllocationhistory.h b/indra/newview/lllocationhistory.h index 060a6b2fe8..5f9976f87a 100644 --- a/indra/newview/lllocationhistory.h +++ b/indra/newview/lllocationhistory.h @@ -40,21 +40,84 @@ #include <map> #include <boost/function.hpp> +class LLSD; + +enum ELocationType { + TYPED_REGION_SURL//region name or surl + ,LANDMARK // name of landmark + ,TELEPORT_HISTORY + }; +class LLLocationHistoryItem { + +public: + LLLocationHistoryItem(){} + LLLocationHistoryItem(std::string typed_location, + LLVector3d global_position, std::string tooltip,ELocationType type ): + mLocation(typed_location), + mGlobalPos(global_position), + mToolTip(tooltip), + mType(type) + {} + LLLocationHistoryItem(const LLLocationHistoryItem& item): + mGlobalPos(item.mGlobalPos), + mToolTip(item.mToolTip), + mLocation(item.mLocation), + mType(item.mType) + {} + LLLocationHistoryItem(const LLSD& data): + mLocation(data["location"]), + mGlobalPos(data["global_pos"]), + mToolTip(data["tooltip"]), + mType(ELocationType(data["item_type"].asInteger())) + {} + + bool operator==(const LLLocationHistoryItem& item) + { + // do not compare mGlobalPos, + // because of a rounding off , the history can contain duplicates + return mLocation == item.mLocation && (mType == item.mType); + } + bool operator!=(const LLLocationHistoryItem& item) + { + return ! (*this == item); + } + LLSD toLLSD() const + { + LLSD val; + val["location"]= mLocation; + val["global_pos"] = mGlobalPos.getValue(); + val["tooltip"] = mToolTip; + val["item_type"] = mType; + return val; + } + const std::string& getLocation() const { return mLocation; }; + const std::string& getToolTip() const { return mToolTip; }; + //static bool equalByRegionParcel(const LLLocationHistoryItem& item1, const LLLocationHistoryItem& item2); + static bool equalByLocation(const LLLocationHistoryItem& item1, const std::string& item_location) + { + return item1.getLocation() == item_location; + } + + LLVector3d mGlobalPos; // global position + std::string mToolTip;// SURL + std::string mLocation;// typed_location + ELocationType mType; +}; + class LLLocationHistory: public LLSingleton<LLLocationHistory> { LOG_CLASS(LLLocationHistory); public: - typedef std::vector<std::string> location_list_t; + typedef std::vector<LLLocationHistoryItem> location_list_t; typedef boost::function<void()> loaded_callback_t; typedef boost::signals2::signal<void()> loaded_signal_t; LLLocationHistory(); - void addItem(const std::string & item, const std::string & tooltip); - bool touchItem(const std::string & item); + void addItem(const LLLocationHistoryItem& item); + bool touchItem(const LLLocationHistoryItem& item); void removeItems(); - std::string getToolTip(const std::string & item) const; size_t getItemCount() const { return mItems.size(); } const location_list_t& getItems() const { return mItems; } bool getMatchingItems(std::string substring, location_list_t& result) const; @@ -65,10 +128,8 @@ public: void dump() const; private: - bool equalByRegionParcel(const std::string& item, const std::string& item_to_add); - const static char delimiter; - std::vector<std::string> mItems; - std::map<std::string, std::string> mToolTips; + + location_list_t mItems; std::string mFilename; /// File to store the history to. loaded_signal_t mLoadedSignal; }; diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index a8ec826e88..f54a614f62 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -48,6 +48,7 @@ #include "lllandmarkactions.h" #include "lllandmarklist.h" #include "lllocationhistory.h" +#include "llteleporthistory.h" #include "llsidetray.h" #include "llslurl.h" #include "lltrans.h" @@ -295,11 +296,19 @@ BOOL LLLocationInputCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* if (LLUICtrl::handleToolTip(x, y, msg, sticky_rect_screen) && !msg.empty()) { if (mList->getRect().pointInRect(x, y)) { - LLLocationHistory* lh = LLLocationHistory::getInstance(); - const std::string tooltip = lh->getToolTip(msg); - - if (!tooltip.empty()) { - msg = tooltip; + S32 loc_x, loc_y; + //x,y - contain coordinates related to the location input control, but without taking the expanded list into account + //So we have to convert it again into local coordinates of mList + localPointToOtherView(x,y,&loc_x,&loc_y,mList); + + LLScrollListItem* item = mList->hitItem(loc_x,loc_y); + if (item) + { + LLSD value = item->getValue(); + if (value.has("tooltip")) + { + msg = value["tooltip"].asString(); + } } } @@ -448,18 +457,58 @@ void LLLocationInputCtrl::onLocationPrearrange(const LLSD& data) rebuildLocationHistory(filter); //Let's add landmarks to the top of the list if any - if( filter.size() !=0 ) + if(!filter.empty() ) { LLInventoryModel::item_array_t landmark_items = LLLandmarkActions::fetchLandmarksByName(filter, TRUE); for(U32 i=0; i < landmark_items.size(); i++) { - mList->addSimpleElement(landmark_items[i]->getName(), ADD_TOP); + LLSD value; + //TODO:: DO we need tooltip for Landmark?? + + value["item_type"] = LANDMARK; + value["AssetUUID"] = landmark_items[i]->getAssetUUID(); + add(landmark_items[i]->getName(), value); + + } + //Let's add teleport history items + LLTeleportHistory* th = LLTeleportHistory::getInstance(); + LLTeleportHistory::slurl_list_t th_items = th->getItems(); + + std::set<std::string> new_item_titles;// duplicate control + LLTeleportHistory::slurl_list_t::iterator result = std::find_if( + th_items.begin(), th_items.end(), boost::bind( + &LLLocationInputCtrl::findTeleportItemsByTitle, this, + _1, filter)); + + while (result != th_items.end()) + { + //mTitile format - region_name[, parcel_name] + //mFullTitile format - region_name[, parcel_name] (local_x,local_y, local_z) + if (new_item_titles.insert(result->mFullTitle).second) + { + LLSD value; + value["item_type"] = TELEPORT_HISTORY; + value["global_pos"] = result->mGlobalPos.getValue(); + std::string region_name = result->mTitle.substr(0, result->mTitle.find(',')); + //TODO*: add Surl to teleportitem or parse region name from title + value["tooltip"] = LLSLURL::buildSLURLfromPosGlobal(region_name, + result->mGlobalPos, false); + add(result->getTitle(), value); + } + result = std::find_if(result + 1, th_items.end(), boost::bind( + &LLLocationInputCtrl::findTeleportItemsByTitle, this, + _1, filter)); } } + sortByName(); + mList->mouseOverHighlightNthItem(-1); // Clear highlight on the last selected item. } - +bool LLLocationInputCtrl::findTeleportItemsByTitle(const LLTeleportHistoryItem& item, const std::string& filter) +{ + return item.mTitle.find(filter) != std::string::npos; +} void LLLocationInputCtrl::onTextEditorRightClicked(S32 x, S32 y, MASK mask) { if (mLocationContextMenu) @@ -519,7 +568,12 @@ void LLLocationInputCtrl::rebuildLocationHistory(std::string filter) removeall(); for (LLLocationHistory::location_list_t::const_reverse_iterator it = itemsp->rbegin(); it != itemsp->rend(); it++) { - add(*it); + LLSD value; + value["tooltip"] = it->getToolTip(); + //location history can contain only typed locations + value["item_type"] = TYPED_REGION_SURL; + value["global_pos"] = it->mGlobalPos.getValue(); + add(it->getLocation(), value); } } diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h index d967df8257..3c43e1a321 100644 --- a/indra/newview/lllocationinputctrl.h +++ b/indra/newview/lllocationinputctrl.h @@ -41,6 +41,7 @@ class LLLandmark; class LLAddLandmarkObserver; class LLRemoveLandmarkObserver; class LLMenuGL; +class LLTeleportHistoryItem; /** * Location input control. @@ -103,6 +104,7 @@ private: void refresh(); void refreshLocation(); void rebuildLocationHistory(std::string filter = ""); + bool findTeleportItemsByTitle(const LLTeleportHistoryItem& item, const std::string& filter); void setText(const LLStringExplicit& text); void updateAddLandmarkButton(); void updateContextMenu(); diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index 28e9c93779..c283b3a05f 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -45,7 +45,7 @@ #include "lllocationhistory.h" #include "lllocationinputctrl.h" #include "llteleporthistory.h" -#include "llsearcheditor.h" +#include "llsearchcombobox.h" #include "llsidetray.h" #include "llslurl.h" #include "llurlsimstring.h" @@ -82,7 +82,6 @@ public: Mandatory<EType> item_type; Params() {} - Params(EType type, std::string title); }; /*virtual*/ void draw(); @@ -104,24 +103,21 @@ private: const std::string LLTeleportHistoryMenuItem::ICON_IMG_BACKWARD("teleport_history_backward.tga"); const std::string LLTeleportHistoryMenuItem::ICON_IMG_FORWARD("teleport_history_forward.tga"); -LLTeleportHistoryMenuItem::Params::Params(EType type, std::string title) -{ - item_type(type); - font.name("SANSSERIF"); - - if (type == TYPE_CURRENT) - font.style("BOLD"); - else - title = " " + title; - - name(title); - label(title); -} - LLTeleportHistoryMenuItem::LLTeleportHistoryMenuItem(const Params& p) : LLMenuItemCallGL(p), mArrowIcon(NULL) { + // Set appearance depending on the item type. + if (p.item_type == TYPE_CURRENT) + { + setFont(LLFontGL::getFontSansSerifBold()); + } + else + { + setFont(LLFontGL::getFontSansSerif()); + setLabel(std::string(" ") + std::string(p.label)); + } + LLIconCtrl::Params icon_params; icon_params.name("icon"); icon_params.rect(LLRect(0, ICON_HEIGHT, ICON_WIDTH, 0)); @@ -183,14 +179,11 @@ LLNavigationBar::LLNavigationBar() mBtnForward(NULL), mBtnHome(NULL), mCmbLocation(NULL), - mLeSearch(NULL), + mSearchComboBox(NULL), mPurgeTPHistoryItems(false) { setIsChrome(TRUE); - mParcelMgrConnection = LLViewerParcelMgr::getInstance()->setTeleportFinishedCallback( - boost::bind(&LLNavigationBar::onTeleportFinished, this, _1)); - LLUICtrlFactory::getInstance()->buildPanel(this, "panel_navigation_bar.xml"); // set a listener function for LoginComplete event @@ -202,8 +195,10 @@ LLNavigationBar::LLNavigationBar() LLNavigationBar::~LLNavigationBar() { - mParcelMgrConnection.disconnect(); + mTeleportFinishConnection.disconnect(); sInstance = 0; + + LLSearchHistory::getInstance()->save(); } BOOL LLNavigationBar::postBuild() @@ -213,10 +208,12 @@ BOOL LLNavigationBar::postBuild() mBtnHome = getChild<LLButton>("home_btn"); mCmbLocation= getChild<LLLocationInputCtrl>("location_combo"); - mLeSearch = getChild<LLSearchEditor>("search_input"); + mSearchComboBox = getChild<LLSearchComboBox>("search_combo_box"); + + fillSearchComboBox(); if (!mBtnBack || !mBtnForward || !mBtnHome || - !mCmbLocation || !mLeSearch) + !mCmbLocation || !mSearchComboBox) { llwarns << "Malformed navigation bar" << llendl; return FALSE; @@ -234,7 +231,7 @@ BOOL LLNavigationBar::postBuild() mCmbLocation->setSelectionCallback(boost::bind(&LLNavigationBar::onLocationSelection, this)); - mLeSearch->setCommitCallback(boost::bind(&LLNavigationBar::onSearchCommit, this)); + mSearchComboBox->setCommitCallback(boost::bind(&LLNavigationBar::onSearchCommit, this)); mDefaultNbRect = getRect(); mDefaultFpRect = getChild<LLFavoritesBarCtrl>("favorite")->getRect(); @@ -246,6 +243,25 @@ BOOL LLNavigationBar::postBuild() return TRUE; } +void LLNavigationBar::fillSearchComboBox() +{ + if(!mSearchComboBox) + { + return; + } + + LLSearchHistory::getInstance()->load(); + + LLSearchHistory::search_history_list_t search_list = + LLSearchHistory::getInstance()->getSearchHistoryList(); + LLSearchHistory::search_history_list_t::const_iterator it = search_list.begin(); + for( ; search_list.end() != it; ++it) + { + LLSearchHistory::LLSearchHistoryItem item = *it; + mSearchComboBox->add(item.search_query); + } +} + void LLNavigationBar::draw() { if(mPurgeTPHistoryItems) @@ -280,7 +296,12 @@ void LLNavigationBar::onHomeButtonClicked() void LLNavigationBar::onSearchCommit() { - invokeSearch(mLeSearch->getValue().asString()); + std::string search_query = mSearchComboBox->getValue().asString(); + if(!search_query.empty()) + { + LLSearchHistory::getInstance()->addEntry(search_query); + invokeSearch(mSearchComboBox->getValue().asString()); + } } void LLNavigationBar::onTeleportHistoryMenuItemClicked(const LLSD& userdata) @@ -299,69 +320,107 @@ void LLNavigationBar::onLocationSelection() if (typed_location.empty()) return; + LLSD value = mCmbLocation->getSelectedValue(); + + if(value.has("item_type")) + { + + switch(value["item_type"].asInteger()) + { + case LANDMARK: + + if(value.has("AssetUUID")) + { + + gAgent.teleportViaLandmark( LLUUID(value["AssetUUID"].asString())); + return; + } + else + { + LLInventoryModel::item_array_t landmark_items = + LLLandmarkActions::fetchLandmarksByName(typed_location, + FALSE); + if (!landmark_items.empty()) + { + gAgent.teleportViaLandmark( landmark_items[0]->getAssetUUID()); + return; + } + } + break; + + case TELEPORT_HISTORY: + //in case of teleport item was selected, teleport by position too. + case TYPED_REGION_SURL: + if(value.has("global_pos")) + { + gAgent.teleportViaLocation(LLVector3d(value["global_pos"])); + return; + } + break; + + default: + break; + } + } + //Let's parse surl or region name + std::string region_name; LLVector3 local_coords(128, 128, 0); S32 x = 0, y = 0, z = 0; - // Is the typed location a SLURL? if (LLSLURL::isSLURL(typed_location)) { // Yes. Extract region name and local coordinates from it. if (LLURLSimString::parse(LLSLURL::stripProtocol(typed_location), ®ion_name, &x, &y, &z)) - local_coords.set(x, y, z); + local_coords.set(x, y, z); else return; - } - else + }else { - //If it is not slurl let's look for landmarks - LLInventoryModel::item_array_t landmark_items = LLLandmarkActions::fetchLandmarksByName(typed_location, FALSE); - if ( !landmark_items.empty() ) - { - gAgent.teleportViaLandmark(landmark_items[0]->getAssetUUID()); - return; - } - //No landmark match, check if it is a region name - region_name = parseLocation(typed_location, &x, &y, &z); - if (region_name != typed_location) - local_coords.set(x, y, z); - - // Treat it as region name. - // region_name = typed_location; + // assume that an user has typed the {region name} or possible {region_name, parcel} + region_name = typed_location.substr(0,typed_location.find(',')); } - + // Resolve the region name to its global coordinates. // If resolution succeeds we'll teleport. LLWorldMap::url_callback_t cb = boost::bind( &LLNavigationBar::onRegionNameResponse, this, typed_location, region_name, local_coords, _1, _2, _3, _4); + // connect the callback each time, when user enter new location to get real location of agent after teleport + mTeleportFinishConnection = LLViewerParcelMgr::getInstance()-> + setTeleportFinishedCallback(boost::bind(&LLNavigationBar::onTeleportFinished, this, _1,typed_location)); + LLWorldMap::getInstance()->sendNamedRegionRequest(region_name, cb, std::string("unused"), false); } -void LLNavigationBar::onTeleportFinished(const LLVector3d& global_agent_pos) +void LLNavigationBar::onTeleportFinished(const LLVector3d& global_agent_pos, const std::string& typed_location) { // Location is valid. Add it to the typed locations history. LLLocationHistory* lh = LLLocationHistory::getInstance(); + //TODO*: do we need convert surl into readable format? std::string location; /*NOTE: * We can't use gAgent.getPositionAgent() in case of local teleport to build location. * At this moment gAgent.getPositionAgent() contains previous coordinates. * according to EXT-65 agent position is being reseted on each frame. */ - LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_WITHOUT_SIM, - gAgent.getPosAgentFromGlobal(global_agent_pos)); + LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_WITHOUT_SIM, + gAgent.getPosAgentFromGlobal(global_agent_pos)); + std::string tooltip (LLSLURL::buildSLURLfromPosGlobal(gAgent.getRegion()->getName(), global_agent_pos, false)); + LLLocationHistoryItem item (location, + global_agent_pos, tooltip,TYPED_REGION_SURL);// we can add into history only TYPED location //Touch it, if it is at list already, add new location otherwise - if ( !lh->touchItem(location) ) { - std::string tooltip = LLSLURL::buildSLURLfromPosGlobal( - gAgent.getRegion()->getName(), global_agent_pos, false); - - lh->addItem(location, tooltip); + if ( !lh->touchItem(item) ) { + lh->addItem(item); } - llinfos << "Saving after on teleport finish" << llendl; - lh->save(); + lh->save(); + + if(mTeleportFinishConnection.connected()) + mTeleportFinishConnection.disconnect(); + } void LLNavigationBar::onTeleportHistoryChanged() @@ -411,7 +470,9 @@ void LLNavigationBar::rebuildTeleportHistoryMenu() else type = LLTeleportHistoryMenuItem::TYPE_CURRENT; - LLTeleportHistoryMenuItem::Params item_params(type, hist_items[i].getTitle()); + LLTeleportHistoryMenuItem::Params item_params; + item_params.label = item_params.name = hist_items[i].getTitle(); + item_params.item_type = type; item_params.on_click.function(boost::bind(&LLNavigationBar::onTeleportHistoryMenuItemClicked, this, i)); LLTeleportHistoryMenuItem* new_itemp = LLUICtrlFactory::create<LLTeleportHistoryMenuItem>(item_params); //new_itemp->setFont() @@ -435,8 +496,8 @@ void LLNavigationBar::onRegionNameResponse( // Teleport to the location. LLVector3d region_pos = from_region_handle(region_handle); LLVector3d global_pos = region_pos + (LLVector3d) local_coords; - - llinfos << "Teleporting to: " << global_pos << llendl; + + llinfos << "Teleporting to: " << LLSLURL::buildSLURLfromPosGlobal(region_name, global_pos, false) << llendl; gAgent.teleportViaLocation(global_pos); } @@ -474,35 +535,6 @@ void LLNavigationBar::invokeSearch(std::string search_text) LLFloaterReg::showInstance("search", LLSD().insert("panel", "all").insert("id", LLSD(search_text))); } -std::string LLNavigationBar::parseLocation(const std::string & location, S32* x, S32* y, S32* z) { - /* - * This regular expression extracts numbers from the following string - * construct: "(num1, num2, num3)", where num1, num2 and num3 are decimal - * numbers. Leading and trailing spaces are also caught by the expression. - */ - const boost::regex re("\\s*\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)\\s*"); - - boost::smatch m; - if (boost::regex_search(location, m, re)) { - // string representations of parsed by regex++ numbers - std::string xstr(m[1].first, m[1].second); - std::string ystr(m[2].first, m[2].second); - std::string zstr(m[3].first, m[3].second); - - *x = atoi(xstr.c_str()); - *y = atoi(ystr.c_str()); - *z = atoi(zstr.c_str()); - //erase commas in coordinates - std::string region_parcel = boost::regex_replace(location, re, ""); - // cut region name - return region_parcel.substr(0, region_parcel.find_first_of(',')); - } - - *x = *y = *z = 0; - - return location; -} - void LLNavigationBar::clearHistoryCache() { mCmbLocation->removeall(); diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h index 6932847854..8a65cd24fa 100644 --- a/indra/newview/llnavigationbar.h +++ b/indra/newview/llnavigationbar.h @@ -41,6 +41,7 @@ class LLButton; class LLLocationInputCtrl; class LLMenuGL; class LLSearchEditor; +class LLSearchComboBox; /** * Web browser-like navigation bar. @@ -69,12 +70,6 @@ private: void rebuildTeleportHistoryMenu(); void showTeleportHistoryMenu(); void invokeSearch(std::string search_text); - - /** - * Get region name and local coordinates from typed location - */ - static std::string parseLocation(const std::string & location, S32* x, S32* y, S32* z); - // callbacks void onTeleportHistoryMenuItemClicked(const LLSD& userdata); void onTeleportHistoryChanged(); @@ -86,7 +81,7 @@ private: void onLocationSelection(); void onLocationPrearrange(const LLSD& data); void onSearchCommit(); - void onTeleportFinished(const LLVector3d& global_agent_pos); + void onTeleportFinished(const LLVector3d& global_agent_pos, const std::string& typed_location); void onRegionNameResponse( std::string typed_location, std::string region_name, @@ -94,17 +89,19 @@ private: U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport); + void fillSearchComboBox(); + static LLNavigationBar *sInstance; LLMenuGL* mTeleportHistoryMenu; LLButton* mBtnBack; LLButton* mBtnForward; LLButton* mBtnHome; - LLSearchEditor* mLeSearch; + LLSearchComboBox* mSearchComboBox; LLLocationInputCtrl* mCmbLocation; LLRect mDefaultNbRect; LLRect mDefaultFpRect; - boost::signals2::connection mParcelMgrConnection; + boost::signals2::connection mTeleportFinishConnection; bool mPurgeTPHistoryItems; }; diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index b2d606ab4d..fd3519bf4b 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -372,7 +372,6 @@ void LLPanelAvatarProfile::resetControls() childSetVisible("status_me_panel", false); childSetVisible("profile_me_buttons_panel", false); childSetVisible("account_actions_panel", false); - childSetVisible("partner_edit_link", false); } void LLPanelAvatarProfile::resetData() @@ -539,7 +538,7 @@ void LLPanelAvatarProfile::fillAccountStatus(const LLAvatarData* avatar_data) childSetValue("acc_status_text", caption_text); } -void LLPanelAvatarProfile::onUrlTextboxClicked(std::string url) +void LLPanelAvatarProfile::onUrlTextboxClicked(const std::string& url) { LLWeb::loadURL(url); } @@ -675,4 +674,3 @@ void LLPanelAvatarMeProfile::onStatusMessageChanged() { updateData(); } - diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index 4ee4cb6e87..1ed5fa4357 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -166,7 +166,7 @@ protected: */ virtual void fillAccountStatus(const LLAvatarData* avatar_data); - void onUrlTextboxClicked(std::string url); + void onUrlTextboxClicked(const std::string& url); void onHomepageTextboxClicked(); void onAddFriendButtonClick(); void onIMButtonClick(); diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp new file mode 100644 index 0000000000..60d0f07285 --- /dev/null +++ b/indra/newview/llpanelblockedlist.cpp @@ -0,0 +1,279 @@ +/** + * @file llpanelblockedlist.cpp + * @brief Container for blocked Residents & Objects list + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloater.h" +#include "llfloaterreg.h" +#include "llscrolllistctrl.h" + +#include "llpanelblockedlist.h" + +// project include +#include "llfloateravatarpicker.h" +#include "llsidetray.h" +#include "llsidetraypanelcontainer.h" + +static LLRegisterPanelClassWrapper<LLPanelBlockedList> t_panel_blocked_list("panel_block_list_sidetray"); + +// +// Constants +// +const std::string BLOCKED_PARAM_NAME = "blocked_to_select"; + +//----------------------------------------------------------------------------- +// LLPanelBlockedList() +//----------------------------------------------------------------------------- + +LLPanelBlockedList::LLPanelBlockedList() +: LLPanel() +{ + mCommitCallbackRegistrar.add("Block.ClickPick", boost::bind(&LLPanelBlockedList::onPickBtnClick, this)); + mCommitCallbackRegistrar.add("Block.ClickBlockByName", boost::bind(&LLPanelBlockedList::onBlockByNameClick, this)); + mCommitCallbackRegistrar.add("Block.ClickRemove", boost::bind(&LLPanelBlockedList::onRemoveBtnClick, this)); +} + +LLPanelBlockedList::~LLPanelBlockedList() +{ + LLMuteList::getInstance()->removeObserver(this); +} + +BOOL LLPanelBlockedList::postBuild() +{ + mBlockedList = getChild<LLScrollListCtrl>("blocked"); + mBlockedList->setCommitOnSelectionChange(TRUE); + + childSetCommitCallback("back", boost::bind(&LLPanelBlockedList::onBackBtnClick, this), NULL); + + LLMuteList::getInstance()->addObserver(this); + + refreshBlockedList(); + + return LLPanel::postBuild(); +} + +void LLPanelBlockedList::draw() +{ + updateButtons(); + LLPanel::draw(); +} + +void LLPanelBlockedList::onOpen(const LLSD& key) +{ + if (key.has(BLOCKED_PARAM_NAME) && key[BLOCKED_PARAM_NAME].asUUID().notNull()) + { + selectBlocked(key[BLOCKED_PARAM_NAME].asUUID()); + } +} + +void LLPanelBlockedList::selectBlocked(const LLUUID& mute_id) +{ + mBlockedList->selectByID(mute_id); +} + +void LLPanelBlockedList::showPanelAndSelect(const LLUUID& idToSelect) +{ + LLSideTray::getInstance()->showPanel("panel_block_list_sidetray", LLSD().insert(BLOCKED_PARAM_NAME, idToSelect)); +} + + +////////////////////////////////////////////////////////////////////////// +// Private Section +////////////////////////////////////////////////////////////////////////// +void LLPanelBlockedList::refreshBlockedList() +{ + mBlockedList->deleteAllItems(); + + std::vector<LLMute> mutes = LLMuteList::getInstance()->getMutes(); + std::vector<LLMute>::iterator it; + for (it = mutes.begin(); it != mutes.end(); ++it) + { + std::string display_name = it->getDisplayName(); + mBlockedList->addStringUUIDItem(display_name, it->mID, ADD_BOTTOM, TRUE); + } +} + +void LLPanelBlockedList::updateButtons() +{ + bool hasSelected = NULL != mBlockedList->getFirstSelected(); + childSetEnabled("Unblock", hasSelected); +} + + + +void LLPanelBlockedList::onBackBtnClick() +{ + LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent()); + if(parent) + { + parent->openPreviousPanel(); + } +} + +void LLPanelBlockedList::onRemoveBtnClick() +{ + std::string name = mBlockedList->getSelectedItemLabel(); + LLUUID id = mBlockedList->getStringUUIDSelectedItem(); + LLMute mute(id); + mute.setFromDisplayName(name); + // now mute.mName has the suffix trimmed off + + S32 last_selected = mBlockedList->getFirstSelectedIndex(); + if (LLMuteList::getInstance()->remove(mute)) + { + // Above removals may rebuild this dialog. + + if (last_selected == mBlockedList->getItemCount()) + { + // we were on the last item, so select the last item again + mBlockedList->selectNthItem(last_selected - 1); + } + else + { + // else select the item after the last item previously selected + mBlockedList->selectNthItem(last_selected); + } + } +} + +void LLPanelBlockedList::onPickBtnClick() +{ + const BOOL allow_multiple = FALSE; + const BOOL close_on_select = TRUE; + /*LLFloaterAvatarPicker* picker = */LLFloaterAvatarPicker::show(callbackBlockPicked, this, allow_multiple, close_on_select); + + // *TODO: mantipov: should LLFloaterAvatarPicker be closed when panel is closed? + // old Floater dependency is not enable in panel + // addDependentFloater(picker); +} + +void LLPanelBlockedList::onBlockByNameClick() +{ + LLFloaterGetBlockedObjectName::show(&LLPanelBlockedList::callbackBlockByName); +} + +//static +void LLPanelBlockedList::callbackBlockPicked(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* user_data) +{ + if (names.empty() || ids.empty()) return; + LLMute mute(ids[0], names[0], LLMute::AGENT); + LLMuteList::getInstance()->add(mute); + showPanelAndSelect(mute.mID); +} + +//static +void LLPanelBlockedList::callbackBlockByName(const std::string& text) +{ + if (text.empty()) return; + + LLMute mute(LLUUID::null, text, LLMute::BY_NAME); + BOOL success = LLMuteList::getInstance()->add(mute); + if (!success) + { + LLNotifications::instance().add("MuteByNameFailed"); + } +} + +////////////////////////////////////////////////////////////////////////// +// LLFloaterGetBlockedObjectName +////////////////////////////////////////////////////////////////////////// + +// Constructor/Destructor +LLFloaterGetBlockedObjectName::LLFloaterGetBlockedObjectName(const LLSD& key) +: LLFloater(key) +, mGetObjectNameCallback(NULL) +{ +} + +// Destroys the object +LLFloaterGetBlockedObjectName::~LLFloaterGetBlockedObjectName() +{ + gFocusMgr.releaseFocusIfNeeded( this ); +} + +BOOL LLFloaterGetBlockedObjectName::postBuild() +{ + getChild<LLButton>("OK")-> setCommitCallback(boost::bind(&LLFloaterGetBlockedObjectName::applyBlocking, this)); + getChild<LLButton>("Cancel")-> setCommitCallback(boost::bind(&LLFloaterGetBlockedObjectName::cancelBlocking, this)); + center(); + + return LLFloater::postBuild(); +} + +BOOL LLFloaterGetBlockedObjectName::handleKeyHere(KEY key, MASK mask) +{ + if (key == KEY_RETURN && mask == MASK_NONE) + { + applyBlocking(); + return TRUE; + } + else if (key == KEY_ESCAPE && mask == MASK_NONE) + { + cancelBlocking(); + return TRUE; + } + + return LLFloater::handleKeyHere(key, mask); +} + +// static +LLFloaterGetBlockedObjectName* LLFloaterGetBlockedObjectName::show(get_object_name_callback_t callback) +{ + LLFloaterGetBlockedObjectName* floater = LLFloaterReg::showTypedInstance<LLFloaterGetBlockedObjectName>("mute_object_by_name"); + + floater->mGetObjectNameCallback = callback; + + // *TODO: mantipov: should LLFloaterGetBlockedObjectName be closed when panel is closed? + // old Floater dependency is not enable in panel + // addDependentFloater(floater); + + return floater; +} + +////////////////////////////////////////////////////////////////////////// +// Private Section +void LLFloaterGetBlockedObjectName::applyBlocking() +{ + if (mGetObjectNameCallback) + { + const std::string& text = childGetValue("object_name").asString(); + mGetObjectNameCallback(text); + } + closeFloater(); +} + +void LLFloaterGetBlockedObjectName::cancelBlocking() +{ + closeFloater(); +} + +//EOF diff --git a/indra/newview/llpanelblockedlist.h b/indra/newview/llpanelblockedlist.h new file mode 100644 index 0000000000..52b74a184b --- /dev/null +++ b/indra/newview/llpanelblockedlist.h @@ -0,0 +1,115 @@ +/** + * @file llpanelblockedlist.h + * @brief Container for blocked Residents & Objects list + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELBLOCKEDLIST_H +#define LL_LLPANELBLOCKEDLIST_H + +#include "llpanel.h" +#include "llmutelist.h" +// #include <vector> + +// class LLButton; +// class LLLineEditor; +// class LLMessageSystem; +// class LLUUID; + class LLScrollListCtrl; + +class LLPanelBlockedList + : public LLPanel, public LLMuteListObserver +{ +public: + LLPanelBlockedList(); + ~LLPanelBlockedList(); + + virtual BOOL postBuild(); + virtual void draw(); + virtual void onOpen(const LLSD& key); + + void selectBlocked(const LLUUID& id); + + /** + * Shows current Panel in side tray and select passed blocked item. + * + * @param idToSelect - LLUUID of blocked Resident or Object to be selected. + * If it is LLUUID::null, nothing will be selected. + */ + static void showPanelAndSelect(const LLUUID& idToSelect); + + // LLMuteListObserver callback interface implementation. + /* virtual */ void onChange() { refreshBlockedList();} + +private: + void refreshBlockedList(); + void updateButtons(); + + // UI callbacks + void onBackBtnClick(); + void onRemoveBtnClick(); + void onPickBtnClick(); + void onBlockByNameClick(); + + static void callbackBlockPicked(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* user_data); + static void callbackBlockByName(const std::string& text); + +private: + LLScrollListCtrl* mBlockedList; +}; + +//----------------------------------------------------------------------------- +// LLFloaterGetBlockedObjectName() +//----------------------------------------------------------------------------- +// Class for handling mute object by name floater. +class LLFloaterGetBlockedObjectName : public LLFloater +{ + friend class LLFloaterReg; +public: + typedef boost::function<void (const std::string&)> get_object_name_callback_t; + + virtual BOOL postBuild(); + + virtual BOOL handleKeyHere(KEY key, MASK mask); + + static LLFloaterGetBlockedObjectName* show(get_object_name_callback_t callback); + +private: + LLFloaterGetBlockedObjectName(const LLSD& key); + virtual ~LLFloaterGetBlockedObjectName(); + + // UI Callbacks + void applyBlocking(); + void cancelBlocking(); + + get_object_name_callback_t mGetObjectNameCallback; +}; + + +#endif // LL_LLPANELBLOCKEDLIST_H diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 34d5ef8f86..42aa21c13e 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -43,12 +43,12 @@ // newview #include "llagent.h" +#include "llavataractions.h" #include "llavatarlist.h" #include "llcallingcard.h" // for LLAvatarTracker #include "llfloateravatarpicker.h" //#include "llfloaterminiinspector.h" #include "llfriendcard.h" -#include "llavataractions.h" #include "llgroupactions.h" #include "llgrouplist.h" #include "llrecentpeople.h" @@ -976,7 +976,6 @@ void LLPanelPeople::onRecentViewSortMenuItemClicked(const LLSD& userdata) } } - void LLPanelPeople::onCallButtonClicked() { // *TODO: not implemented yet diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index bd6ca4746c..c34038c672 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -54,6 +54,11 @@ static const std::string XML_BTN_INFO = "info_btn"; static const std::string XML_BTN_TELEPORT = "teleport_btn"; static const std::string XML_BTN_SHOW_ON_MAP = "show_on_map_btn"; +static const std::string PICK_ID("pick_id"); +static const std::string PICK_CREATOR_ID("pick_creator_id"); +static const std::string PICK_NAME("pick_name"); + + static LLRegisterPanelClassWrapper<LLPanelPicks> t_panel_picks("panel_picks"); //----------------------------------------------------------------------------- @@ -97,19 +102,8 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type) gCacheName->getName(getAvatarId(),name,second_name); childSetTextArg("pick_title", "[NAME]",name); - // to restore selection of the same item later - LLUUID pick_id_selected(LLUUID::null); - if (getSelectedPickItem()) pick_id_selected = getSelectedPickItem()->getPickId(); - mPicksList->clear(); - //*TODO move it somewhere else? - childSetEnabled(XML_BTN_NEW, false); - childSetEnabled(XML_BTN_DELETE, false); - childSetEnabled(XML_BTN_INFO, false); - childSetEnabled(XML_BTN_TELEPORT,!avatar_picks->picks_list.empty()); - childSetEnabled(XML_BTN_SHOW_ON_MAP,!avatar_picks->picks_list.empty()); - LLAvatarPicks::picks_list_t::const_iterator it = avatar_picks->picks_list.begin(); for(; avatar_picks->picks_list.end() != it; ++it) { @@ -124,12 +118,18 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type) LLAvatarPropertiesProcessor::instance().addObserver(getAvatarId(), picture); picture->update(); - mPicksList->addItem(picture); - if (pick_id_selected != LLUUID::null && - pick_id == pick_id_selected) mPicksList->toggleSelection(picture); + + LLSD pick_value = LLSD(); + pick_value.insert(PICK_ID, pick_id); + pick_value.insert(PICK_NAME, pick_name); + pick_value.insert(PICK_CREATOR_ID, getAvatarId()); + + mPicksList->addItem(picture, pick_value); picture->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickItem, this, _1)); picture->setRightMouseDownCallback(boost::bind(&LLPanelPicks::onRightMouseDownItem, this, _1, _2, _3, _4)); + picture->setRightMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); + picture->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); } LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this); @@ -140,10 +140,10 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type) LLPickItem* LLPanelPicks::getSelectedPickItem() { - std::list<LLPanel*> selected_items = mPicksList->getSelectedItems(); + LLPanel* selected_item = mPicksList->getSelectedItem(); + if (!selected_item) return NULL; - if (selected_items.empty()) return NULL; - return dynamic_cast<LLPickItem*>(selected_items.front()); + return dynamic_cast<LLPickItem*>(selected_item); } BOOL LLPanelPicks::postBuild() @@ -193,6 +193,10 @@ void LLPanelPicks::onOpen(const LLSD& key) { childSetVisible("pick_title", !self); childSetVisible("pick_title_agent", self); + + mPopupMenu->setItemVisible("pick_delete", TRUE); + mPopupMenu->setItemVisible("pick_edit", TRUE); + mPopupMenu->setItemVisible("pick_separator", TRUE); } LLPanelProfileTab::onOpen(key); @@ -201,11 +205,11 @@ void LLPanelPicks::onOpen(const LLSD& key) //static void LLPanelPicks::onClickDelete() { - LLPickItem* pick_item = getSelectedPickItem(); - if (!pick_item) return; + LLSD pick_value = mPicksList->getSelectedValue(); + if (pick_value.isUndefined()) return; LLSD args; - args["PICK"] = pick_item->getPickName(); + args["PICK"] = pick_value[PICK_NAME]; LLNotifications::instance().add("DeleteAvatarPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackDelete, this, _1, _2)); } @@ -213,12 +217,12 @@ bool LLPanelPicks::callbackDelete(const LLSD& notification, const LLSD& response { S32 option = LLNotification::getSelectedOption(notification, response); - LLPickItem* pick_item = getSelectedPickItem(); + LLSD pick_value = mPicksList->getSelectedValue(); if (0 == option) { - LLAvatarPropertiesProcessor::instance().sendPickDelete(pick_item->getPickId()); - mPicksList->removeItem(pick_item); + LLAvatarPropertiesProcessor::instance().sendPickDelete(pick_value[PICK_ID]); + mPicksList->removeItemByValue(pick_value); } updateButtons(); return false; @@ -265,32 +269,30 @@ void LLPanelPicks::onRightMouseDownItem(LLUICtrl* item, S32 x, S32 y, MASK mask) void LLPanelPicks::onDoubleClickItem(LLUICtrl* item) { - LLPickItem* pick_item = dynamic_cast<LLPickItem*>(item); - if (!pick_item) return; + LLSD pick_value = mPicksList->getSelectedValue(); + if (pick_value.isUndefined()) return; + LLSD args; - args["PICK"] = pick_item->getPickName(); + args["PICK"] = pick_value[PICK_NAME]; LLNotifications::instance().add("TeleportToPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackTeleport, this, _1, _2)); } void LLPanelPicks::updateButtons() { int picks_num = mPicksList->size(); - childSetEnabled(XML_BTN_INFO, picks_num > 0); + bool has_selected = mPicksList->numSelected(); + + childSetEnabled(XML_BTN_INFO, has_selected); if (getAvatarId() == gAgentID) { childSetEnabled(XML_BTN_NEW, picks_num < MAX_AVATAR_PICKS); - childSetEnabled(XML_BTN_DELETE, picks_num > 0); - - //*TODO move somewhere this calls - // we'd better set them up earlier when a panel was being constructed - mPopupMenu->setItemVisible("pick_delete", TRUE); - mPopupMenu->setItemVisible("pick_edit", TRUE); - mPopupMenu->setItemVisible("pick_separator", TRUE); + childSetEnabled(XML_BTN_DELETE, has_selected); } - //*TODO update buttons like Show on Map, Teleport etc. - + childSetEnabled(XML_BTN_INFO, has_selected); + childSetEnabled(XML_BTN_TELEPORT, has_selected); + childSetEnabled(XML_BTN_SHOW_ON_MAP, has_selected); } void LLPanelPicks::setProfilePanel(LLPanelProfile* profile_panel) @@ -318,12 +320,12 @@ void LLPanelPicks::onClickNew() void LLPanelPicks::onClickInfo() { - LLPickItem* pick = getSelectedPickItem(); - if (!pick) return; + LLSD selected_value = mPicksList->getSelectedValue(); + if (selected_value.isUndefined()) return; buildPickPanel(); mPickPanel->reset(); - mPickPanel->init(pick->getCreatorId(), pick->getPickId()); + mPickPanel->init(selected_value[PICK_CREATOR_ID], selected_value[PICK_ID]); getProfilePanel()->togglePanel(mPickPanel); } @@ -335,12 +337,12 @@ void LLPanelPicks::onClickBack() void LLPanelPicks::onClickMenuEdit() { //*TODO, refactor - most of that is similar to onClickInfo - LLPickItem* pick = getSelectedPickItem(); - if (!pick) return; + LLSD selected_value = mPicksList->getSelectedValue(); + if (selected_value.isUndefined()) return; buildPickPanel(); mPickPanel->reset(); - mPickPanel->init(pick->getCreatorId(), pick->getPickId()); + mPickPanel->init(selected_value[PICK_CREATOR_ID], selected_value[PICK_ID]); mPickPanel->setEditMode(TRUE); getProfilePanel()->togglePanel(mPickPanel); } @@ -470,3 +472,17 @@ void LLPanelPicks::onClose() getProfilePanel()->togglePanel(mPickPanel); } } + +BOOL LLPickItem::postBuild() +{ + setMouseEnterCallback(boost::bind(&LLPanelPick::childSetVisible, this, "hovered_icon", true)); + setMouseLeaveCallback(boost::bind(&LLPanelPick::childSetVisible, this, "hovered_icon", false)); + return TRUE; +} + +void LLPickItem::setValue(const LLSD& value) +{ + if (!value.isMap()) return;; + if (!value.has("selected")) return; + childSetVisible("selected_icon", value["selected"]); +} diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h index 5860354902..97e8e607c8 100644 --- a/indra/newview/llpanelpicks.h +++ b/indra/newview/llpanelpicks.h @@ -152,6 +152,11 @@ public: ~LLPickItem(); + /*virtual*/ BOOL postBuild(); + + /** setting on/off background icon to indicate selected state */ + /*virtual*/ void setValue(const LLSD& value); + protected: LLUUID mPickID; diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index 73e09a36f9..ec1c10d8c9 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -49,6 +49,7 @@ #include "lltextbox.h" #include "llaccordionctrl.h" +#include "llaccordionctrltab.h" #include "llagent.h" #include "llavatarpropertiesprocessor.h" #include "llfloaterworldmap.h" @@ -81,6 +82,8 @@ LLPanelPlaceInfo::~LLPanelPlaceInfo() { LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelID, this); } + + LLViewerParcelMgr::getInstance()->removeObserver(this); } BOOL LLPanelPlaceInfo::postBuild() @@ -98,26 +101,16 @@ BOOL LLPanelPlaceInfo::postBuild() mParcelName = getChild<LLTextBox>("parcel_title"); mDescEditor = getChild<LLTextEditor>("description"); - mMaturityRatingIcon = getChild<LLIconCtrl>("maturity"); mMaturityRatingText = getChild<LLTextBox>("maturity_value"); - mParcelOwner = getChild<LLTextBox>("owner_value"); - mLastVisited = getChild<LLTextBox>("last_visited_value"); - mRatingIcon = getChild<LLIconCtrl>("rating_icon"); mRatingText = getChild<LLTextBox>("rating_value"); - mVoiceIcon = getChild<LLIconCtrl>("voice_icon"); mVoiceText = getChild<LLTextBox>("voice_value"); - mFlyIcon = getChild<LLIconCtrl>("fly_icon"); mFlyText = getChild<LLTextBox>("fly_value"); - mPushIcon = getChild<LLIconCtrl>("push_icon"); mPushText = getChild<LLTextBox>("push_value"); - mBuildIcon = getChild<LLIconCtrl>("build_icon"); mBuildText = getChild<LLTextBox>("build_value"); - mScriptsIcon = getChild<LLIconCtrl>("scripts_icon"); mScriptsText = getChild<LLTextBox>("scripts_value"); - mDamageIcon = getChild<LLIconCtrl>("damage_icon"); mDamageText = getChild<LLTextBox>("damage_value"); mRegionNameText = getChild<LLTextBox>("region_name"); @@ -131,6 +124,16 @@ BOOL LLPanelPlaceInfo::postBuild() mEstateOwnerText = getChild<LLTextBox>("estate_owner"); mCovenantText = getChild<LLTextEditor>("covenant"); + mSalesPriceText = getChild<LLTextBox>("sales_price"); + mAreaText = getChild<LLTextBox>("area"); + mTrafficText = getChild<LLTextBox>("traffic"); + mPrimitivesText = getChild<LLTextBox>("primitives"); + mParcelScriptsText = getChild<LLTextBox>("parcel_scripts"); + mTerraformLimitsText = getChild<LLTextBox>("terraform_limits"); + mSubdivideText = getChild<LLTextEditor>("subdivide"); + mResaleText = getChild<LLTextEditor>("resale"); + mSaleToText = getChild<LLTextBox>("sale_to"); + mOwner = getChild<LLTextBox>("owner"); mCreator = getChild<LLTextBox>("creator"); mCreated = getChild<LLTextBox>("created"); @@ -253,7 +256,6 @@ void LLPanelPlaceInfo::resetLocation() mLandmarkID.setNull(); mPosRegion.clearVec(); std::string not_available = getString("not_available"); - mMaturityRatingIcon->setValue(not_available); mMaturityRatingText->setValue(not_available); mParcelOwner->setValue(not_available); mLastVisited->setValue(not_available); @@ -268,19 +270,12 @@ void LLPanelPlaceInfo::resetLocation() mSnapshotCtrl->setImageAssetID(LLUUID::null); mSnapshotCtrl->setFallbackImageName("default_land_picture.j2c"); - mRatingIcon->setValue(not_available); mRatingText->setText(not_available); - mVoiceIcon->setValue(not_available); mVoiceText->setText(not_available); - mFlyIcon->setValue(not_available); mFlyText->setText(not_available); - mPushIcon->setValue(not_available); mPushText->setText(not_available); - mBuildIcon->setValue(not_available); mBuildText->setText(not_available); - mScriptsIcon->setValue(not_available); - mScriptsText->setText(not_available); - mDamageIcon->setValue(not_available); + mParcelScriptsText->setText(not_available); mDamageText->setText(not_available); mRegionNameText->setValue(not_available); @@ -293,6 +288,16 @@ void LLPanelPlaceInfo::resetLocation() mEstateRatingText->setValue(not_available); mEstateOwnerText->setValue(not_available); mCovenantText->setValue(not_available); + + mSalesPriceText->setValue(not_available); + mAreaText->setValue(not_available); + mTrafficText->setValue(not_available); + mPrimitivesText->setValue(not_available); + mParcelScriptsText->setValue(not_available); + mTerraformLimitsText->setValue(not_available); + mSubdivideText->setValue(not_available); + mResaleText->setValue(not_available); + mSaleToText->setValue(not_available); } //virtual @@ -312,7 +317,6 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type) bool is_info_type_teleport_history = type == TELEPORT_HISTORY; getChild<LLTextBox>("maturity_label")->setVisible(!is_info_type_agent); - mMaturityRatingIcon->setVisible(!is_info_type_agent); mMaturityRatingText->setVisible(!is_info_type_agent); getChild<LLTextBox>("owner_label")->setVisible(is_info_type_agent); @@ -326,6 +330,8 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type) getChild<LLAccordionCtrl>("advanced_info_accordion")->setVisible(is_info_type_agent); + LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance(); + switch(type) { case CREATE_LANDMARK: @@ -333,6 +339,15 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type) break; case AGENT: + if (parcel_mgr) + { + // If information is requested for current agent location + // start using LLViewerParcelMgr for land selection. + parcel_mgr->addObserver(this); + parcel_mgr->selectParcelAt(gAgent.getPositionGlobal()); + } + + // Fall through to PLACE case case PLACE: mCurrentTitle = getString("title_place"); @@ -348,14 +363,22 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type) case TELEPORT_HISTORY: mCurrentTitle = getString("title_teleport_history"); - - // *TODO: Add last visited timestamp. - mLastVisited->setText(getString("unknown")); break; } + if (type != AGENT && parcel_mgr != NULL) + { + if (!parcel_mgr->selectionEmpty()) + { + parcel_mgr->deselectUnused(); + } + parcel_mgr->removeObserver(this); + } + if (type != PLACE) toggleMediaPanel(FALSE); + + mInfoType = type; } BOOL LLPanelPlaceInfo::isMediaPanelVisible() @@ -432,22 +455,16 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data) // HACK: Flag 0x2 == adult region, // Flag 0x1 == mature region, otherwise assume PG std::string rating = LLViewerRegion::accessToString(SIM_ACCESS_PG); - std::string rating_icon = "places_rating_pg.tga"; if (parcel_data.flags & 0x2) { rating = LLViewerRegion::accessToString(SIM_ACCESS_ADULT); - rating_icon = "places_rating_adult.tga"; } else if (parcel_data.flags & 0x1) { rating = LLViewerRegion::accessToString(SIM_ACCESS_MATURE); - rating_icon = "places_rating_mature.tga"; } - mMaturityRatingIcon->setValue(rating_icon); mMaturityRatingText->setValue(rating); - - mRatingIcon->setValue(rating_icon); mRatingText->setValue(rating); //update for_sale banner, here we should use DFQ_FOR_SALE instead of PF_FOR_SALE @@ -476,7 +493,7 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data) mRegionName->setText(name); } - if (mCurrentTitle != getString("title_landmark")) + if (mInfoType == CREATE_LANDMARK) { mTitleEditor->setText(parcel_data.name); mNotesEditor->setText(LLStringUtil::null); @@ -517,10 +534,10 @@ void LLPanelPlaceInfo::displayParcelInfo(const LLVector3& pos_region, void LLPanelPlaceInfo::displayAgentParcelInfo() { - mPosRegion = gAgent.getPositionAgent(); + mParcel = LLViewerParcelMgr::getInstance()->getFloatingParcelSelection(); - LLViewerRegion* region = gAgent.getRegion(); - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + LLParcel* parcel = mParcel->getParcel(); + LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); if (!region || !parcel) return; @@ -547,13 +564,6 @@ void LLPanelPlaceInfo::displayAgentParcelInfo() default: parcel_data.flags = 0; } - - // Adding "For Sale" flag in remote parcel response format. - if (parcel->getForSale()) - { - parcel_data.flags |= DFQ_FOR_SALE; - } - parcel_data.desc = parcel->getDesc(); parcel_data.name = parcel->getName(); parcel_data.sim_name = gAgent.getRegion()->getName(); @@ -563,75 +573,68 @@ void LLPanelPlaceInfo::displayAgentParcelInfo() parcel_data.global_y = global_pos.mdV[1]; parcel_data.global_z = global_pos.mdV[2]; + mPosRegion = gAgent.getPositionAgent(); + processParcelInfo(parcel_data); + std::string on = getString("on"); + std::string off = getString("off"); + // Processing parcel characteristics if (parcel->getParcelFlagAllowVoice()) { - mVoiceIcon->setValue("places_voice_on.tga"); - mVoiceText->setText(getString("on")); + mVoiceText->setText(on); } else { - mVoiceIcon->setValue("places_voice_off.tga"); - mVoiceText->setText(getString("off")); + mVoiceText->setText(off); } if (!region->getBlockFly() && parcel->getAllowFly()) { - mFlyIcon->setValue("places_fly_on.tga"); - mFlyText->setText(getString("on")); + mFlyText->setText(on); } else { - mFlyIcon->setValue("places_fly_off.tga"); - mFlyText->setText(getString("off")); + mFlyText->setText(off); } if (region->getRestrictPushObject() || parcel->getRestrictPushObject()) { - mPushIcon->setValue("places_push_off.tga"); - mPushText->setText(getString("off")); + mPushText->setText(off); } else { - mPushIcon->setValue("places_push_on.tga"); - mPushText->setText(getString("on")); + mPushText->setText(on); } if (parcel->getAllowModify()) { - mBuildIcon->setValue("places_build_on.tga"); - mBuildText->setText(getString("on")); + mBuildText->setText(on); } else { - mBuildIcon->setValue("places_build_off.tga"); - mBuildText->setText(getString("off")); + mBuildText->setText(off); } if((region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS) || (region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS) || !parcel->getAllowOtherScripts()) { - mScriptsIcon->setValue("places_scripts_off.tga"); - mScriptsText->setText(getString("off")); + mScriptsText->setText(off); } else { - mScriptsIcon->setValue("places_scripts_on.tga"); - mScriptsText->setText(getString("on")); + mScriptsText->setText(on); } if (region->getAllowDamage() || parcel->getAllowDamage()) { - mDamageIcon->setValue("places_damage_on.tga"); - mDamageText->setText(getString("on")); + mDamageText->setText(on); } else { - mDamageIcon->setValue("places_damage_off.tga"); - mDamageText->setText(getString("off")); + mDamageText->setText(off); } mRegionNameText->setText(region->getName()); @@ -656,7 +659,8 @@ void LLPanelPlaceInfo::displayAgentParcelInfo() gCacheName->get(parcel->getGroupID(), TRUE, boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, this, mRegionGroupText, _2, _3)); - mParcelOwner->setText(mRegionGroupText->getText()); + gCacheName->get(parcel->getGroupID(), TRUE, + boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, this, mParcelOwner, _2, _3)); } else { @@ -681,6 +685,98 @@ void LLPanelPlaceInfo::displayAgentParcelInfo() } mEstateRatingText->setText(region->getSimAccessString()); + + S32 area; + S32 claim_price; + S32 rent_price; + F32 dwell; + BOOL for_sale = parcel->getForSale(); + LLViewerParcelMgr::getInstance()->getDisplayInfo(&area, + &claim_price, + &rent_price, + &for_sale, + &dwell); + + if (for_sale) + { + // Adding "For Sale" flag in remote parcel response format. + parcel_data.flags |= DFQ_FOR_SALE; + + const LLUUID& auth_buyer_id = parcel->getAuthorizedBuyerID(); + if(auth_buyer_id.notNull()) + { + gCacheName->get(auth_buyer_id, TRUE, + boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, this, mSaleToText, _2, _3)); + + // Show sales info to a specific person or a group he belongs to. + if (auth_buyer_id != gAgent.getID() && !gAgent.isInGroup(auth_buyer_id)) + { + for_sale = FALSE; + } + } + else + { + mSaleToText->setText(getString("anyone")); + } + + const U8* sign = (U8*)getString("price_text").c_str(); + const U8* sqm = (U8*)getString("area_text").c_str(); + + mSalesPriceText->setText(llformat("%s%d ", sign, parcel->getSalePrice())); + mAreaText->setText(llformat("%d %s", area, sqm)); + mTrafficText->setText(llformat("%.0f", dwell)); + + // Can't have more than region max tasks, regardless of parcel + // object bonus factor. + S32 primitives = llmin(llround(parcel->getMaxPrimCapacity() * parcel->getParcelPrimBonus()), + (S32)region->getMaxTasks()); + + const U8* available = (U8*)getString("available").c_str(); + const U8* allocated = (U8*)getString("allocated").c_str(); + + mPrimitivesText->setText(llformat("%d %s, %d %s", primitives, available, parcel->getPrimCount(), allocated)); + + if (parcel->getAllowOtherScripts()) + { + mParcelScriptsText->setText(getString("all_residents_text")); + } + else if (parcel->getAllowGroupScripts()) + { + mParcelScriptsText->setText(getString("group_text")); + } + else + { + mParcelScriptsText->setText(off); + } + + mTerraformLimitsText->setText(parcel->getAllowTerraform() ? on : off); + + if (region->getRegionFlags() & REGION_FLAGS_ALLOW_PARCEL_CHANGES) + { + mSubdivideText->setText(getString("can_change")); + } + else + { + mSubdivideText->setText(getString("can_not_change")); + } + if (region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL) + { + mResaleText->setText(getString("can_not_resell")); + } + else + { + mResaleText->setText(getString("can_resell")); + } + } + + getChild<LLAccordionCtrlTab>("sales_tab")->setVisible(for_sale); +} + +// virtual +void LLPanelPlaceInfo::changed() +{ + resetLocation(); + displayAgentParcelInfo(); } void LLPanelPlaceInfo::updateEstateName(const std::string& name) @@ -698,6 +794,22 @@ void LLPanelPlaceInfo::updateCovenantText(const std::string &text) mCovenantText->setText(text); } +void LLPanelPlaceInfo::updateLastVisitedText(const LLDate &date) +{ + if (date.isNull()) + { + mLastVisited->setText(getString("unknown")); + } + else + { + std::string timeStr = getString("acquired_date"); + LLSD substitution; + substitution["datetime"] = (S32) date.secondsSinceEpoch(); + LLStringUtil::format (timeStr, substitution); + mLastVisited->setText(timeStr); + } +} + void LLPanelPlaceInfo::onCommitTitleOrNote(LANDMARK_INFO_TYPE type) { LLInventoryItem* item = gInventory.getItem(mLandmarkID); @@ -785,6 +897,7 @@ void LLPanelPlaceInfo::createPick(const LLVector3d& global_pos) LLAvatarPropertiesProcessor::instance().sendDataUpdate(&pick_data, APT_PICK_INFO); } +// virtual void LLPanelPlaceInfo::reshape(S32 width, S32 height, BOOL called_from_parent) { if (mMinHeight > 0 && mScrollingPanel != NULL) @@ -794,3 +907,22 @@ void LLPanelPlaceInfo::reshape(S32 width, S32 height, BOOL called_from_parent) LLView::reshape(width, height, called_from_parent); } + +// virtual +void LLPanelPlaceInfo::handleVisibilityChange (BOOL new_visibility) +{ + LLPanel::handleVisibilityChange(new_visibility); + + LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance(); + if (!parcel_mgr) + return; + + // Remove land selection when panel hides. + if (!new_visibility) + { + if (!parcel_mgr->selectionEmpty()) + { + parcel_mgr->deselectLand(); + } + } +} diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h index 0cdeaab2b7..60f35cd0c1 100644 --- a/indra/newview/llpanelplaceinfo.h +++ b/indra/newview/llpanelplaceinfo.h @@ -42,15 +42,17 @@ #include "llpanelmedia.h" #include "llremoteparcelrequest.h" +#include "llviewerparcelmgr.h" class LLButton; class LLInventoryItem; class LLLineEditor; +class LLParcelSelection; class LLTextBox; class LLTextEditor; class LLTextureCtrl; -class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver +class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver, LLParcelObserver { public: enum INFO_TYPE @@ -105,9 +107,13 @@ public: // without sending a request to the server. void displayAgentParcelInfo(); + // Called on parcel selection change by LLViewerParcelMgr. + /*virtual*/ void changed(); + void updateEstateName(const std::string& name); void updateEstateOwnerName(const std::string& name); void updateCovenantText(const std::string &text); + void updateLastVisitedText(const LLDate &date); void nameUpdatedCallback(LLTextBox* text, const std::string& first, @@ -115,6 +121,7 @@ public: /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + /*virtual*/ void handleVisibilityChange (BOOL new_visibility); private: enum LANDMARK_INFO_TYPE @@ -131,30 +138,23 @@ private: LLVector3 mPosRegion; std::string mCurrentTitle; S32 mMinHeight; + INFO_TYPE mInfoType; LLTextBox* mTitle; LLTextureCtrl* mSnapshotCtrl; LLTextBox* mRegionName; LLTextBox* mParcelName; LLTextEditor* mDescEditor; - LLIconCtrl* mMaturityRatingIcon; LLTextBox* mMaturityRatingText; LLTextBox* mParcelOwner; LLTextBox* mLastVisited; - LLIconCtrl* mRatingIcon; LLTextBox* mRatingText; - LLIconCtrl* mVoiceIcon; LLTextBox* mVoiceText; - LLIconCtrl* mFlyIcon; LLTextBox* mFlyText; - LLIconCtrl* mPushIcon; LLTextBox* mPushText; - LLIconCtrl* mBuildIcon; LLTextBox* mBuildText; - LLIconCtrl* mScriptsIcon; LLTextBox* mScriptsText; - LLIconCtrl* mDamageIcon; LLTextBox* mDamageText; LLTextBox* mRegionNameText; @@ -168,6 +168,16 @@ private: LLTextBox* mEstateOwnerText; LLTextEditor* mCovenantText; + LLTextBox* mSalesPriceText; + LLTextBox* mAreaText; + LLTextBox* mTrafficText; + LLTextBox* mPrimitivesText; + LLTextBox* mParcelScriptsText; + LLTextBox* mTerraformLimitsText; + LLTextEditor* mSubdivideText; + LLTextEditor* mResaleText; + LLTextBox* mSaleToText; + LLTextBox* mOwner; LLTextBox* mCreator; LLTextBox* mCreated; @@ -176,6 +186,8 @@ private: LLPanel* mScrollingPanel; LLPanel* mInfoPanel; LLMediaPanel* mMediaPanel; + + LLSafeHandle<LLParcelSelection> mParcel; }; #endif // LL_LLPANELPLACEINFO_H diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 2aebfdabfa..bc740bd865 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -51,6 +51,7 @@ #include "llpanellandmarks.h" #include "llpanelteleporthistory.h" #include "llsidetray.h" +#include "llteleporthistorystorage.h" #include "lltoggleablemenu.h" #include "llviewerinventory.h" #include "llviewermenu.h" @@ -172,8 +173,7 @@ void LLPanelPlaces::onOpen(const LLSD& key) if (mPlaceInfoType == AGENT_INFO_TYPE) { mPlaceInfo->setInfoType(LLPanelPlaceInfo::AGENT); - mPlaceInfo->displayAgentParcelInfo(); - + mPosGlobal = gAgent.getPositionGlobal(); } else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE) @@ -212,14 +212,15 @@ void LLPanelPlaces::onOpen(const LLSD& key) { S32 index = key["id"].asInteger(); - const LLTeleportHistory::slurl_list_t& hist_items = - LLTeleportHistory::getInstance()->getItems(); + const LLTeleportHistoryStorage::slurl_list_t& hist_items = + LLTeleportHistoryStorage::getInstance()->getItems(); mPosGlobal = hist_items[index].mGlobalPos; mPlaceInfo->setInfoType(LLPanelPlaceInfo::TELEPORT_HISTORY); + mPlaceInfo->updateLastVisitedText(hist_items[index].mDate); mPlaceInfo->displayParcelInfo(get_pos_local_from_global(mPosGlobal), - hist_items[index].mRegionID, + LLUUID(), mPosGlobal); } } diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 8b378c33e3..df48ee5d08 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -37,6 +37,7 @@ #include "llpanelteleporthistory.h" #include "llsidetray.h" #include "llworldmap.h" +#include "llteleporthistorystorage.h" // Not yet implemented; need to remove buildPanel() from constructor when we switch //static LLRegisterPanelClassWrapper<LLTeleportHistoryPanel> t_teleport_history("panel_teleport_history"); @@ -56,7 +57,7 @@ LLTeleportHistoryPanel::~LLTeleportHistoryPanel() BOOL LLTeleportHistoryPanel::postBuild() { - mTeleportHistory = LLTeleportHistory::getInstance(); + mTeleportHistory = LLTeleportHistoryStorage::getInstance(); if (mTeleportHistory) { mTeleportHistory->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryPanel::showTeleportHistory, this)); @@ -92,9 +93,7 @@ void LLTeleportHistoryPanel::onShowOnMap() S32 index = itemp->getColumn(LIST_INDEX)->getValue().asInteger(); - const LLTeleportHistory::slurl_list_t& hist_items = mTeleportHistory->getItems(); - - LLVector3d global_pos = hist_items[index].mGlobalPos; + LLVector3d global_pos = mTeleportHistory->getItems()[index].mGlobalPos; if (!global_pos.isExactlyZero()) { @@ -153,7 +152,7 @@ void LLTeleportHistoryPanel::updateVerbs() if (itemp) { index = itemp->getColumn(LIST_INDEX)->getValue().asInteger(); - cur_item = mTeleportHistory->getCurrentItemIndex(); + cur_item = mTeleportHistory->getItems().size() - 1; } mTeleportBtn->setEnabled(index != cur_item); @@ -162,13 +161,11 @@ void LLTeleportHistoryPanel::updateVerbs() void LLTeleportHistoryPanel::showTeleportHistory() { - const LLTeleportHistory::slurl_list_t& hist_items = mTeleportHistory->getItems(); + const LLTeleportHistoryStorage::slurl_list_t& hist_items = mTeleportHistory->getItems(); mHistoryItems->deleteAllItems(); - S32 cur_item = mTeleportHistory->getCurrentItemIndex(); - - for (LLTeleportHistory::slurl_list_t::const_iterator iter = hist_items.begin(); + for (LLTeleportHistoryStorage::slurl_list_t::const_iterator iter = hist_items.begin(); iter != hist_items.end(); ++iter) { std::string landmark_title = (*iter).mTitle; @@ -181,7 +178,6 @@ void LLTeleportHistoryPanel::showTeleportHistory() continue; S32 index = iter - hist_items.begin(); - LLSD row; row["id"] = index; @@ -201,14 +197,12 @@ void LLTeleportHistoryPanel::showTeleportHistory() index_column["value"] = index; mHistoryItems->addElement(row, ADD_TOP); - - if (cur_item == index) - { - LLScrollListItem* itemp = mHistoryItems->getItem(index); - ((LLScrollListText*)itemp->getColumn(LIST_ITEM_TITLE))->setFontStyle(LLFontGL::BOLD); - } } + // Consider last item (most recent) as current + LLScrollListItem* itemp = mHistoryItems->getItem((S32)hist_items.size() - 1); + ((LLScrollListText*)itemp->getColumn(LIST_ITEM_TITLE))->setFontStyle(LLFontGL::BOLD); + updateVerbs(); } diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h index 553385b37e..023b04c3fa 100644 --- a/indra/newview/llpanelteleporthistory.h +++ b/indra/newview/llpanelteleporthistory.h @@ -39,6 +39,8 @@ #include "llpanelplacestab.h" #include "llteleporthistory.h" +class LLTeleportHistoryStorage; + class LLTeleportHistoryPanel : public LLPanelPlacesTab { public: @@ -65,7 +67,7 @@ private: LIST_INDEX }; - LLTeleportHistory* mTeleportHistory; + LLTeleportHistoryStorage* mTeleportHistory; LLScrollListCtrl* mHistoryItems; std::string mFilterSubString; }; diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 68996673be..1fbe359295 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -88,9 +88,12 @@ void LLScreenChannel::reshape(S32 width, S32 height, BOOL called_from_parent) //-------------------------------------------------------------------------- void LLScreenChannel::addToast(LLToast::Params p) { - bool store_toast = !mShowToasts && p.can_be_stored && mCanStoreToasts; + bool store_toast = false, show_toast = false; - if(!mShowToasts && !store_toast) + show_toast = mShowToasts || p.force_show; + store_toast = !show_toast && p.can_be_stored && mCanStoreToasts; + + if(!show_toast && !store_toast) { mOnRejectToast(p); return; @@ -106,7 +109,7 @@ void LLScreenChannel::addToast(LLToast::Params p) new_toast_elem.toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2)); } - if(mShowToasts) + if(show_toast) { mToastList.push_back(new_toast_elem); showToasts(); diff --git a/indra/newview/llsearchcombobox.cpp b/indra/newview/llsearchcombobox.cpp new file mode 100644 index 0000000000..c903f40f3f --- /dev/null +++ b/indra/newview/llsearchcombobox.cpp @@ -0,0 +1,250 @@ +/** + * @file llsearchcombobox.cpp + * @brief Search Combobox implementation + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llsearchcombobox.h" + +#include "llkeyboard.h" +#include "lluictrlfactory.h" + +static LLDefaultChildRegistry::Register<LLSearchComboBox> r1("search_combo_box"); + +class LLSearchHistoryBuilder +{ +public: + LLSearchHistoryBuilder(LLSearchComboBox* combo_box, const std::string& filter); + + virtual void buildSearchHistory(); + + virtual ~LLSearchHistoryBuilder(){} + +protected: + + virtual bool filterSearchHistory(); + + LLSearchComboBox* mComboBox; + std::string mFilter; + LLSearchHistory::search_history_list_t mFilteredSearchHistory; +}; + +LLSearchComboBox::Params::Params() +: search_button("search_button") +, dropdown_button_visible("dropdown_button_visible", false) +{ +} + +LLSearchComboBox::LLSearchComboBox(const Params&p) +: LLComboBox(p) +{ + S32 btn_top = p.search_button.top_pad + p.search_button.rect.height; + S32 btn_right = p.search_button.rect.width + p.search_button.left_pad; + LLRect search_btn_rect(p.search_button.left_pad, btn_top, btn_right, p.search_button.top_pad); + + LLButton::Params button_params(p.search_button); + button_params.name(std::string("search_btn")); + button_params.rect(search_btn_rect) ; + button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP); + button_params.tab_stop(false); + button_params.click_callback.function(boost::bind(&LLSearchComboBox::onSelectionCommit, this)); + mSearchButton = LLUICtrlFactory::create<LLButton>(button_params); + mTextEntry->addChild(mSearchButton); + + setButtonVisible(p.dropdown_button_visible); + mTextEntry->setCommitCallback(boost::bind(&LLComboBox::onTextCommit, this, _2)); + mTextEntry->setKeystrokeCallback(boost::bind(&LLComboBox::onTextEntry, this, _1), NULL); + setSelectionCallback(boost::bind(&LLSearchComboBox::onSelectionCommit, this)); + setPrearrangeCallback(boost::bind(&LLSearchComboBox::onSearchPrearrange, this, _2)); +} + +void LLSearchComboBox::rebuildSearchHistory(const std::string& filter) +{ + LLSearchHistoryBuilder builder(this, filter); + builder.buildSearchHistory(); +} + +void LLSearchComboBox::onSearchPrearrange(const LLSD& data) +{ + std::string filter = data.asString(); + rebuildSearchHistory(filter); + + mList->mouseOverHighlightNthItem(-1); // Clear highlight on the last selected item. +} + +void LLSearchComboBox::onTextEntry(LLLineEditor* line_editor) +{ + KEY key = gKeyboard->currentKey(); + + if (line_editor->getText().empty()) + { + prearrangeList(); // resets filter + hideList(); + } + // Typing? (moving cursor should not affect showing the list) + else if (key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END) + { + prearrangeList(line_editor->getText()); + if (mList->getItemCount() != 0) + { + showList(); + focusTextEntry(); + } + else + { + // Hide the list if it's empty. + hideList(); + } + } + LLComboBox::onTextEntry(line_editor); +} + +void LLSearchComboBox::focusTextEntry() +{ + // We can't use "mTextEntry->setFocus(TRUE)" instead because + // if the "select_on_focus" parameter is true it places the cursor + // at the beginning (after selecting text), thus screwing up updateSelection(). + if (mTextEntry) + { + gFocusMgr.setKeyboardFocus(mTextEntry); + } +} + +void LLSearchComboBox::hideList() +{ + LLComboBox::hideList(); + if (mTextEntry && hasFocus()) + focusTextEntry(); +} + +LLSearchComboBox::~LLSearchComboBox() +{ +} + +void LLSearchComboBox::onSelectionCommit() +{ + std::string search_query = getSimple(); + LLStringUtil::trim(search_query); + if(search_query.empty()) + { + mTextEntry->setText(search_query); + setControlValue(search_query); + + return; + } + + remove(search_query); + add(search_query, ADD_TOP); + mTextEntry->setText(search_query); + setControlValue(search_query); + + LLUICtrl::onCommit(); +} + +BOOL LLSearchComboBox::remove(const std::string& name) +{ + BOOL found = mList->selectItemByLabel(name, FALSE); + + if (found) + { + LLScrollListItem* item = mList->getFirstSelected(); + if (item) + { + LLComboBox::remove(mList->getItemIndex(item)); + } + } + + return found; +} + +void LLSearchComboBox::clearHistory() +{ + removeall(); + setTextEntry(LLStringUtil::null); +} + +LLSearchHistoryBuilder::LLSearchHistoryBuilder(LLSearchComboBox* combo_box, const std::string& filter) +: mComboBox(combo_box) +, mFilter(filter) +{ +} + +bool LLSearchHistoryBuilder::filterSearchHistory() +{ + // *TODO: an STL algorithm would look nicer + mFilteredSearchHistory.clear(); + + std::string filter_copy = mFilter; + LLStringUtil::toLower(filter_copy); + + LLSearchHistory::search_history_list_t history = + LLSearchHistory::getInstance()->getSearchHistoryList(); + + LLSearchHistory::search_history_list_t::const_iterator it = history.begin(); + for ( ; it != history.end(); ++it) + { + std::string search_query = (*it).search_query; + LLStringUtil::toLower(search_query); + + if (search_query.find(filter_copy) != std::string::npos) + mFilteredSearchHistory.push_back(*it); + } + + return mFilteredSearchHistory.size(); +} + +void LLSearchHistoryBuilder::buildSearchHistory() +{ + mFilteredSearchHistory.clear(); + + LLSearchHistory::search_history_list_t filtered_items; + LLSearchHistory::search_history_list_t* itemsp = NULL; + LLSearchHistory* sh = LLSearchHistory::getInstance(); + + if (mFilter.empty()) + { + itemsp = &sh->getSearchHistoryList(); + } + else + { + filterSearchHistory(); + itemsp = &mFilteredSearchHistory; + itemsp->sort(); + } + + mComboBox->removeall(); + + LLSearchHistory::search_history_list_t::const_iterator it = itemsp->begin(); + for ( ; it != itemsp->end(); it++) + { + LLSearchHistory::LLSearchHistoryItem item = *it; + mComboBox->add(item.search_query); + } +} diff --git a/indra/newview/llsearchcombobox.h b/indra/newview/llsearchcombobox.h new file mode 100644 index 0000000000..38f9a5a26b --- /dev/null +++ b/indra/newview/llsearchcombobox.h @@ -0,0 +1,108 @@ +/** + * @file llsearchcombobox.h + * @brief LLSearchComboBox class definition + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLSEARCHCOMBOBOX_H +#define LL_LLSEARCHCOMBOBOX_H + +#include "llcombobox.h" +#include "llsearchhistory.h" + +/** + * Search control with text box for search queries and a drop down list + * with recent queries. Supports text auto-complete and filtering of drop down list + * according to typed text. + */ +class LLSearchComboBox : public LLComboBox +{ +public: + + struct Params : public LLInitParam::Block<Params, LLComboBox::Params> + { + Optional<LLButton::Params> search_button; + Optional<bool> dropdown_button_visible; + + Params(); + }; + + /** + * Removes an entry from combo box, case insensitive + */ + BOOL remove(const std::string& name); + + /** + * Clears search history + */ + void clearHistory(); + + ~LLSearchComboBox(); + +protected: + + LLSearchComboBox(const Params&p); + friend class LLUICtrlFactory; + + /** + * Handles typing in text box + */ + void onTextEntry(LLLineEditor* line_editor); + + /** + * Hides drop down list and focuses text box + */ + void hideList(); + + /** + * Rebuilds search history, case insensitive + * If filter is an empty string - whole history will be added to combo box + * if filter is valid string - only matching entries will be added + */ + virtual void rebuildSearchHistory(const std::string& filter); + + /** + * Callback for prearrange event + */ + void onSearchPrearrange(const LLSD& data); + + /** + * Callback for text box or combo box commit + */ + void onSelectionCommit(); + + /** + * Sets focus to text box + */ + void focusTextEntry(); + + LLButton* mSearchButton; +}; + +#endif //LL_LLSEARCHCOMBOBOX_H diff --git a/indra/newview/llsearchhistory.cpp b/indra/newview/llsearchhistory.cpp new file mode 100644 index 0000000000..d45a1efa0e --- /dev/null +++ b/indra/newview/llsearchhistory.cpp @@ -0,0 +1,154 @@ +/** + * @file llsearchhistory.cpp + * @brief Search history container implementation + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llsearchhistory.h" + +#include "llfile.h" +#include "llsdserialize.h" +#include "llxmlnode.h" + +std::string LLSearchHistory::SEARCH_QUERY = "search_query"; +std::string LLSearchHistory::SEARCH_HISTORY_FILE_NAME = "search_history.txt"; + +LLSearchHistory::LLSearchHistory() +{ + +} + +bool LLSearchHistory::load() +{ + // build filename for each user + std::string resolved_filename = getHistoryFilePath(); + llifstream file(resolved_filename); + if (!file.is_open()) + { + return false; + } + + clearHistory(); + + // add each line in the file to the list + std::string line; + LLPointer<LLSDParser> parser = new LLSDNotationParser(); + while (std::getline(file, line)) + { + LLSD s_item; + std::istringstream iss(line); + if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE) + { + break; + } + + mSearchHistory.push_back(s_item); + } + + file.close(); + + return true; +} + +bool LLSearchHistory::save() +{ + // build filename for each user + std::string resolved_filename = getHistoryFilePath(); + // open a file for writing + llofstream file (resolved_filename); + if (!file.is_open()) + { + return false; + } + + search_history_list_t::const_iterator it = mSearchHistory.begin(); + for (; mSearchHistory.end() != it; ++it) + { + file << LLSDOStreamer<LLSDNotationFormatter>((*it).toLLSD()) << std::endl; + } + + file.close(); + return true; +} + +std::string LLSearchHistory::getHistoryFilePath() +{ + return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SEARCH_HISTORY_FILE_NAME); +} + +void LLSearchHistory::addEntry(const std::string& search_query) +{ + if(search_query.empty()) + { + return; + } + + search_history_list_t::iterator it = + find(mSearchHistory.begin(), mSearchHistory.end(), search_query); + + if(mSearchHistory.end() != it) + { + mSearchHistory.erase(it); + } + + LLSearchHistoryItem item(search_query); + mSearchHistory.push_front(item); +} + +bool LLSearchHistory::LLSearchHistoryItem::operator < (const LLSearchHistory::LLSearchHistoryItem& right) +{ + S32 result = LLStringUtil::compareInsensitive(search_query, right.search_query); + + return result < 0; +} + +bool LLSearchHistory::LLSearchHistoryItem::operator > (const LLSearchHistory::LLSearchHistoryItem& right) +{ + S32 result = LLStringUtil::compareInsensitive(search_query, right.search_query); + + return result > 0; +} + +bool LLSearchHistory::LLSearchHistoryItem::operator==(const LLSearchHistory::LLSearchHistoryItem& right) +{ + return 0 == LLStringUtil::compareInsensitive(search_query, right.search_query); +} + +bool LLSearchHistory::LLSearchHistoryItem::operator==(const std::string& right) +{ + return 0 == LLStringUtil::compareInsensitive(search_query, right); +} + +LLSD LLSearchHistory::LLSearchHistoryItem::toLLSD() const +{ + LLSD ret; + ret[SEARCH_QUERY] = search_query; + return ret; +} diff --git a/indra/newview/llsearchhistory.h b/indra/newview/llsearchhistory.h new file mode 100644 index 0000000000..253ef21e9e --- /dev/null +++ b/indra/newview/llsearchhistory.h @@ -0,0 +1,138 @@ +/** + * @file llsearchhistory.h + * @brief Search history container definition + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLSEARCHHISTORY_H +#define LL_LLSEARCHHISTORY_H + +#include "llsingleton.h" +/** + * Search history container able to save and load history from file. + * History is stored in chronological order, most recent at the beginning. + */ +class LLSearchHistory : public LLSingleton<LLSearchHistory> +{ +public: + + // Forward declaration + class LLSearchHistoryItem; + + // Search history container + typedef std::list<LLSearchHistoryItem> search_history_list_t; + + /** + * Saves search history to file + */ + bool save(); + + /** + * loads search history from file + */ + bool load(); + + /** + * Returns search history list + */ + search_history_list_t& getSearchHistoryList() { return mSearchHistory; } + + /** + * Deletes all search history queries from list. + */ + void clearHistory() { mSearchHistory.clear(); } + + /** + * Adds unique entry to front of search history list, case insensitive + * If entry is already in list, it will be deleted and added to front. + */ + void addEntry(const std::string& search_text); + + LLSearchHistory(); + + /** + * Class for storing data about single search request. + */ + class LLSearchHistoryItem + { + public: + + LLSearchHistoryItem() + {} + + LLSearchHistoryItem(const std::string& query) + : search_query(query) + {} + + LLSearchHistoryItem(const LLSD& item) + { + if(item.has(SEARCH_QUERY)) + search_query = item[SEARCH_QUERY].asString(); + } + + std::string search_query; + + /** + * Allows std::list sorting + */ + bool operator < (const LLSearchHistory::LLSearchHistoryItem& right); + + /** + * Allows std::list sorting + */ + bool operator > (const LLSearchHistory::LLSearchHistoryItem& right); + + bool operator==(const LLSearchHistoryItem& right); + + bool operator==(const std::string& right); + + /** + * Serializes search history item to LLSD + */ + LLSD toLLSD() const; + }; + +protected: + + /** + * Returns path to search history file. + */ + std::string getHistoryFilePath(); + + static std::string SEARCH_HISTORY_FILE_NAME; + static std::string SEARCH_QUERY; + +private: + + search_history_list_t mSearchHistory; +}; + +class LLSearchComboBox; + +#endif //LL_LLSEARCHHISTORY_H diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index afa8e5f072..381e63f020 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -241,6 +241,13 @@ LLSideTray::LLSideTray(Params& params) ,mMaxBarWidth(params.rect.width) { mCollapsed=params.collapsed; + + + LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar(); + + // register handler function to process data from the xml. + // panel_name should be specified via "parameter" attribute. + commit.add("SideTray.ShowPanel", boost::bind(&LLSideTray::showPanel, this, _2, LLUUID::null)); } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 6c0481feaa..8fb0f201cb 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -899,6 +899,10 @@ bool idle_startup() if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState()) { + // Move the progress view in front of the UI immediately when login is performed + // this allows not to see main menu after Alt+Tab was pressed while login. EXT-744. + gViewerWindow->moveProgressViewToFront(); + //reset the values that could have come in from a slurl if (!gLoginHandler.getWebLoginKey().isNull()) { diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 15d77dbf88..7ddbf0a744 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -38,9 +38,9 @@ #include "llviewercontrol.h" #include "llviewerwindow.h" +#include "llchiclet.h" //--------------------------------------------------------------------------------- -LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLFloater(LLSD()), - mSysWell(NULL), +LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key), mChannel(NULL), mScrollContainer(NULL), mNotificationList(NULL) @@ -57,13 +57,9 @@ BOOL LLSysWellWindow::postBuild() mNotificationList = getChild<LLScrollingPanelList>("notification_list"); mIMRowList = getChild<LLScrollingPanelList>("im_row_panel_list"); - gViewerWindow->setOnBottomTrayWidthChanged(boost::bind(&LLSysWellWindow::adjustWindowPosition, this)); // *TODO: won't be necessary after docking is realized mScrollContainer->setBorderVisible(FALSE); - mDockTongue = LLUI::getUIImage("windows/Flyout_Pointer.png"); - - - return TRUE; + return LLDockableFloater::postBuild(); } //--------------------------------------------------------------------------------- @@ -82,7 +78,6 @@ void LLSysWellWindow::addItem(LLSysWellItem::Params p) LLSysWellItem* new_item = new LLSysWellItem(p); mNotificationList->addPanel(dynamic_cast<LLScrollingPanel*>(new_item)); reshapeWindow(); - adjustWindowPosition(); // *TODO: won't be necessary after docking is realized new_item->setOnItemCloseCallback(boost::bind(&LLSysWellWindow::onItemClose, this, _1)); new_item->setOnItemClickCallback(boost::bind(&LLSysWellWindow::onItemClick, this, _1)); @@ -127,10 +122,6 @@ void LLSysWellWindow::removeItemByID(const LLUUID& id) return; reshapeWindow(); - adjustWindowPosition(); // *TODO: won't be necessary after docking is realized - - // hide chiclet window if there are no items left - setVisible(!isWindowEmpty()); } //--------------------------------------------------------------------------------- @@ -148,11 +139,20 @@ void LLSysWellWindow::onItemClose(LLSysWellItem* item) removeItemByID(id); if(mChannel) mChannel->killToastByNotificationID(id); + + // hide chiclet window if there are no items left + setVisible(!isWindowEmpty()); } //--------------------------------------------------------------------------------- void LLSysWellWindow::toggleWindow() { + if (getDockControl() == NULL) + { + setDockControl(new LLDockControl( + LLBottomTray::getInstance()->getSysWell(), this, + getDockTongue(), LLDockControl::TOP, isDocked())); + } setVisible(!getVisible()); } @@ -162,12 +162,20 @@ void LLSysWellWindow::setVisible(BOOL visible) // on Show adjust position of SysWell chiclet's window if(visible) { + if (LLBottomTray::instanceExists()) + { + LLBottomTray::getInstance()->getSysWell()->setToggleState(TRUE); + } if(mChannel) mChannel->removeAndStoreAllVisibleToasts(); - - adjustWindowPosition(); // *TODO: won't be necessary after docking is realized } - + else + { + if (LLBottomTray::instanceExists()) + { + LLBottomTray::getInstance()->getSysWell()->setToggleState(FALSE); + } + } if(mChannel) mChannel->setShowToasts(!visible); @@ -175,16 +183,6 @@ void LLSysWellWindow::setVisible(BOOL visible) } //--------------------------------------------------------------------------------- -void LLSysWellWindow::adjustWindowPosition() // *TODO: won't be necessary after docking is realized -{ - const S32 WINDOW_MARGIN = 5; - - LLRect btm_rect = LLBottomTray::getInstance()->getRect(); - LLRect this_rect = getRect(); - setOrigin(btm_rect.mRight - this_rect.getWidth() - WINDOW_MARGIN, WINDOW_MARGIN); -} - -//--------------------------------------------------------------------------------- void LLSysWellWindow::reshapeWindow() { // Get size for scrollbar and floater's header @@ -272,7 +270,6 @@ void LLSysWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter, { mIMRowList->addPanel(new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId)); - adjustWindowPosition(); // *TODO: won't be necessary after docking is realized } //--------------------------------------------------------------------------------- @@ -286,14 +283,12 @@ void LLSysWellWindow::delIMRow(const LLUUID& sessionId) // hide chiclet window if there are no items left setVisible(!isWindowEmpty()); - - adjustWindowPosition(); // *TODO: won't be necessary after docking is realized } //--------------------------------------------------------------------------------- bool LLSysWellWindow::isWindowEmpty() { - if(mIMRowList->getPanelList().size() == 0 && mNotificationList->getPanelList().size() == 0) + if(mIMRowList->getPanelList().size() == 0 && LLBottomTray::getInstance()->getSysWell()->getCounter() == 0) { return true; } @@ -328,7 +323,7 @@ void LLSysWellWindow::sessionRemoved(const LLUUID& sessionId) { delIMRow(sessionId); reshapeWindow(); - mSysWell->updateUreadIMNotifications(); + LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications(); } //--------------------------------------------------------------------------------- @@ -396,5 +391,3 @@ void LLSysWellWindow::RowPanel::updatePanel(BOOL allow_modify) } //--------------------------------------------------------------------------------- - - diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index d9fdf77a04..ef0974b428 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -35,7 +35,7 @@ #include "llsyswellitem.h" -#include "llfloater.h" +#include "lldockablefloater.h" #include "llbutton.h" #include "llscreenchannel.h" #include "llscrollcontainer.h" @@ -46,7 +46,7 @@ -class LLSysWellWindow : public LLFloater, LLIMSessionObserver +class LLSysWellWindow : public LLDockableFloater, LLIMSessionObserver { public: LLSysWellWindow(const LLSD& key); @@ -58,7 +58,6 @@ public: // change attributes void setChannel(LLNotificationsUI::LLScreenChannel* channel) {mChannel = channel;} - void setSysWell(LLNotificationChiclet* sys_well) {mSysWell = sys_well;} // Operating with items void addItem(LLSysWellItem::Params p); @@ -93,9 +92,6 @@ private: // pointer to a corresponding channel's instance LLNotificationsUI::LLScreenChannel* mChannel; - - LLNotificationChiclet* mSysWell; - LLUIImagePtr mDockTongue; LLPanel* mTwinListPanel; LLScrollContainer* mScrollContainer; LLScrollingPanelList* mIMRowList; diff --git a/indra/newview/llteleporthistorystorage.cpp b/indra/newview/llteleporthistorystorage.cpp index b31edf1e5d..0bb5a727e0 100644 --- a/indra/newview/llteleporthistorystorage.cpp +++ b/indra/newview/llteleporthistorystorage.cpp @@ -37,8 +37,11 @@ #include "llsd.h" #include "llsdserialize.h" #include "lldir.h" +#include "llteleporthistory.h" +#include "llagent.h" -static LLTeleportHistoryStorage tpstorage; +// Max offset for two global positions to consider them as equal +const F64 MAX_GLOBAL_POS_OFFSET = 5.0f; LLTeleportHistoryPersistentItem::LLTeleportHistoryPersistentItem(const LLSD& val) { @@ -58,15 +61,42 @@ LLSD LLTeleportHistoryPersistentItem::toLLSD() const return val; } +struct LLSortItemsByDate +{ + bool operator()(const LLTeleportHistoryPersistentItem& a, const LLTeleportHistoryPersistentItem& b) + { + return a.mDate < b.mDate; + } +}; + LLTeleportHistoryStorage::LLTeleportHistoryStorage() : mFilename("teleport_history.txt") { + LLTeleportHistory *th = LLTeleportHistory::getInstance(); + if (th) + th->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryStorage::onTeleportHistoryChange, this)); + + load(); } LLTeleportHistoryStorage::~LLTeleportHistoryStorage() { } +void LLTeleportHistoryStorage::onTeleportHistoryChange() +{ + LLTeleportHistory *th = LLTeleportHistory::getInstance(); + if (!th) + return; + + const LLTeleportHistoryItem &item = th->getItems()[th->getCurrentItemIndex()]; + + addItem(item.mTitle, item.mGlobalPos); + save(); + + mHistoryChangedSignal(); +} + void LLTeleportHistoryStorage::purgeItems() { mItems.clear(); @@ -74,12 +104,45 @@ void LLTeleportHistoryStorage::purgeItems() void LLTeleportHistoryStorage::addItem(const std::string title, const LLVector3d& global_pos) { - mItems.push_back(LLTeleportHistoryPersistentItem(title, global_pos)); + addItem(title, global_pos, LLDate::now()); +} + + +bool LLTeleportHistoryStorage::compareByTitleAndGlobalPos(const LLTeleportHistoryPersistentItem& a, const LLTeleportHistoryPersistentItem& b) +{ + return a.mTitle == b.mTitle && (a.mGlobalPos - b.mGlobalPos).length() < MAX_GLOBAL_POS_OFFSET; } void LLTeleportHistoryStorage::addItem(const std::string title, const LLVector3d& global_pos, const LLDate& date) { - mItems.push_back(LLTeleportHistoryPersistentItem(title, global_pos, date)); + + LLTeleportHistoryPersistentItem item(title, global_pos, date); + + slurl_list_t::iterator item_iter = std::find_if(mItems.begin(), mItems.end(), + boost::bind(&LLTeleportHistoryStorage::compareByTitleAndGlobalPos, this, _1, item)); + + // If there is such item already, remove it, since new item is more recent + if (item_iter != mItems.end()) + { + mItems.erase(item_iter); + } + + mItems.push_back(item); + + // Check whether sorting is needed + if (mItems.size() > 1) + { + item_iter = mItems.end(); + + item_iter--; + item_iter--; + + // If second to last item is more recent than last, then resort items + if (item_iter->mDate > item.mDate) + { + std::sort(mItems.begin(), mItems.end(), LLSortItemsByDate()); + } + } } void LLTeleportHistoryStorage::removeItem(S32 idx) @@ -145,6 +208,8 @@ void LLTeleportHistoryStorage::load() } file.close(); + + std::sort(mItems.begin(), mItems.end(), LLSortItemsByDate()); } void LLTeleportHistoryStorage::dump() const @@ -162,3 +227,30 @@ void LLTeleportHistoryStorage::dump() const } } +boost::signals2::connection LLTeleportHistoryStorage::setHistoryChangedCallback(history_callback_t cb) +{ + return mHistoryChangedSignal.connect(cb); +} + +void LLTeleportHistoryStorage::goToItem(S32 idx) + +{ + // Validate specified index. + if (idx < 0 || idx >= (S32)mItems.size()) + { + llwarns << "Invalid teleport history index (" << idx << ") specified" << llendl; + dump(); + return; + } + + if (idx == (S32)mItems.size() - 1) + { + llwarns << "Will not teleport to the same location." << llendl; + dump(); + return; + } + + // Attempt to teleport to the requested item. + gAgent.teleportViaLocation(mItems[idx].mGlobalPos); +} + diff --git a/indra/newview/llteleporthistorystorage.h b/indra/newview/llteleporthistorystorage.h index fa836c0326..f67c4e2fb9 100644 --- a/indra/newview/llteleporthistorystorage.h +++ b/indra/newview/llteleporthistorystorage.h @@ -78,7 +78,10 @@ class LLTeleportHistoryStorage: public LLSingleton<LLTeleportHistoryStorage> public: - typedef std::vector<LLTeleportHistoryPersistentItem> item_list_list_t; + typedef std::vector<LLTeleportHistoryPersistentItem> slurl_list_t; + + typedef boost::function<void()> history_callback_t; + typedef boost::signals2::signal<void()> history_signal_t; LLTeleportHistoryStorage(); ~LLTeleportHistoryStorage(); @@ -86,7 +89,7 @@ public: /** * @return history items. */ - const item_list_list_t& getItems() const { return mItems; } + const slurl_list_t& getItems() const { return mItems; } void purgeItems(); void addItem(const std::string title, const LLVector3d& global_pos); @@ -99,10 +102,34 @@ public: void dump() const; + /** + * Set a callback to be called upon history changes. + * + * Multiple callbacks can be set. + */ + boost::signals2::connection setHistoryChangedCallback(history_callback_t cb); + + /** + * Go to specific item in the history. + * + * The item is specified by its index (starting from 0). + */ + void goToItem(S32 idx); + private: - item_list_list_t mItems; - std::string mFilename; + void onTeleportHistoryChange(); + bool compareByTitleAndGlobalPos(const LLTeleportHistoryPersistentItem& a, const LLTeleportHistoryPersistentItem& b); + + slurl_list_t mItems; + std::string mFilename; + + /** + * Signal emitted when the history gets changed. + * + * Invokes callbacks set with setHistoryChangedCallback(). + */ + history_signal_t mHistoryChangedSignal; }; #endif //LL_LLTELEPORTHISTORYSTORAGE_H diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index 969f3fd1cb..05e63a60c5 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -70,12 +70,16 @@ public: bool enable_hide_btn; bool is_modal; bool is_tip; + bool force_show; + bool force_store; Params() : can_fade(true), can_be_stored(true), is_modal(false), is_tip(false), enable_hide_btn(true), + force_show(false), + force_store(false), panel(NULL), timer_period(gSavedSettings.getS32("NotificationToastTime")) diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index 6f26b4077c..6f373a74bd 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -40,7 +40,7 @@ #include "lliconctrl.h" #include "llnotify.h" #include "lltextbox.h" -#include "lltexteditor.h" + #include "lluiconstants.h" #include "llui.h" #include "llviewercontrol.h" @@ -53,6 +53,8 @@ #include "llfloaterinventory.h" #include "llinventorytype.h" +const S32 LLToastGroupNotifyPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 4; + LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification) : LLToastPanel(notification), mInventoryOffer(NULL) @@ -65,8 +67,6 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification llwarns << "Group notice for unkown group: " << payload["group_id"].asUUID() << llendl; } - static const LLUIColor textColor = LLUIColorTable::instance().getColor("GroupNotifyTextColor"); - //group icon LLIconCtrl* pGroupIcon = getChild<LLIconCtrl>("group_icon", TRUE); pGroupIcon->setValue(groupData.mInsigniaID); @@ -78,23 +78,16 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification LLTextBox* pTitleText = getChild<LLTextBox>("title"); pTitleText->setValue(from.str()); - //message body + //message subject const std::string& subject = payload["subject"].asString(); + //message body const std::string& message = payload["message"].asString(); - LLTextEditor* pMessageText = getChild<LLTextEditor>("message"); - pMessageText->setValue(""); - pMessageText->setEnabled(FALSE); - LLStyle::Params date_style; - date_style.color = textColor; - date_style.font.name = "SANSSERIF"; - - LLStyle::Params header_style_params; - header_style_params.color = textColor; - header_style_params.font = LLFontGL::getFontSansSerifBig(); - pMessageText->appendStyledText(subject + "\n",false,false,header_style_params); + LLTextBox* pSubjectText = getChild<LLTextBox>("subject"); + pSubjectText->setValue(subject); + LLTextBox* pDateTimeText = getChild<LLTextBox>("datetime"); std::string timeStr = "["+LLTrans::getString("UTCTimeWeek")+"],[" +LLTrans::getString("UTCTimeDay")+"] [" +LLTrans::getString("UTCTimeMth")+"] [" @@ -108,25 +101,38 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification LLSD substitution; substitution["datetime"] = (S32) notice_date.secondsSinceEpoch(); LLStringUtil::format(timeStr, substitution); - LLStyle::Params date_style_params; - date_style_params.color = textColor; - date_style_params.font = LLFontGL::getFontMonospace(); - pMessageText->appendStyledText(timeStr, false, false, date_style); - pMessageText->appendColoredText(std::string("\n\n") + message, false, - false, textColor); + pDateTimeText->setValue(timeStr); + + LLTextBox* pMessageText = getChild<LLTextBox>("message"); + + //If message is empty let it be invisible and not take place at the panel + if(message.size() != 0) + { + pMessageText->setVisible(TRUE); + pMessageText->setValue(message); + } + else + { + pMessageText->setVisible(FALSE); + } //attachment BOOL hasInventory = payload["inventory_offer"].isDefined(); + + //attachment text LLTextBox * pAttachLink = getChild<LLTextBox>("attachment"); + //attachment icon + LLIconCtrl* pAttachIcon = getChild<LLIconCtrl>("attachment_icon", TRUE); + + //If attachment is empty let it be invisible and not take place at the panel pAttachLink->setVisible(hasInventory); + pAttachIcon->setVisible(hasInventory); if (hasInventory) { pAttachLink->setValue(payload["inventory_name"]); mInventoryOffer = new LLOfferInfo(payload["inventory_offer"]); childSetActionTextbox("attachment", boost::bind( &LLToastGroupNotifyPanel::onClickAttachment, this)); - //attachment icon - LLIconCtrl* pAttachIcon = getChild<LLIconCtrl>("attachment_icon", TRUE); LLUIImagePtr attachIconImg = get_item_icon(mInventoryOffer->mType, LLInventoryType::IT_TEXTURE, 0, FALSE); @@ -137,8 +143,15 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification LLButton* pOkBtn = getChild<LLButton>("btn_ok"); pOkBtn->setClickedCallback((boost::bind(&LLToastGroupNotifyPanel::onClickOk, this))); setDefaultBtn(pOkBtn); -} + S32 maxLinesCount; + std::istringstream ss( getString("message_max_lines_count") ); + if (!(ss >> maxLinesCount)) + { + maxLinesCount = DEFAULT_MESSAGE_MAX_LINE_COUNT; + } + snapToMessageHeight(pMessageText, maxLinesCount); +} // virtual LLToastGroupNotifyPanel::~LLToastGroupNotifyPanel() diff --git a/indra/newview/lltoastgroupnotifypanel.h b/indra/newview/lltoastgroupnotifypanel.h index ba98531251..e3d0ef45cb 100644 --- a/indra/newview/lltoastgroupnotifypanel.h +++ b/indra/newview/lltoastgroupnotifypanel.h @@ -68,6 +68,8 @@ protected: private: static bool isAttachmentOpenable(LLAssetType::EType); + static const S32 DEFAULT_MESSAGE_MAX_LINE_COUNT; + LLButton* mSaveInventoryBtn; LLUUID mGroupID; diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp index e41181c9e1..913e46e05e 100644 --- a/indra/newview/lltoastimpanel.cpp +++ b/indra/newview/lltoastimpanel.cpp @@ -34,9 +34,7 @@ #include "lltoastimpanel.h" #include "llimpanel.h" -const S32 LLToastIMPanel::MAX_MESSAGE_HEIGHT = 50; -const S32 LLToastIMPanel::CAPTION_HEIGHT = 30; -const S32 LLToastIMPanel::TOP_PAD = 5; +const S32 LLToastIMPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 6; //-------------------------------------------------------------------------- LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notification), @@ -60,7 +58,13 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif mReplyBtn->setClickedCallback(boost::bind(&LLToastIMPanel::onClickReplyBtn, this)); - snapToMessageHeight(); + S32 maxLinesCount; + std::istringstream ss( getString("message_max_lines_count") ); + if (!(ss >> maxLinesCount)) + { + maxLinesCount = DEFAULT_MESSAGE_MAX_LINE_COUNT; + } + snapToMessageHeight(mMessage, maxLinesCount); } //-------------------------------------------------------------------------- @@ -69,22 +73,6 @@ LLToastIMPanel::~LLToastIMPanel() } //-------------------------------------------------------------------------- -void LLToastIMPanel::snapToMessageHeight() -{ - S32 required_text_height = mMessage->getTextPixelHeight(); - S32 text_height = llmin(required_text_height, MAX_MESSAGE_HEIGHT); - LLRect text_rect = mMessage->getRect(); - LLRect btn_rect = mReplyBtn->getRect(); - - - mMessage->reshape( text_rect.getWidth(), text_height, TRUE); - mMessage->setValue(mMessage->getText()); - - S32 panel_height = CAPTION_HEIGHT + text_height + btn_rect.getHeight() + TOP_PAD*5; - reshape( getRect().getWidth(), panel_height, TRUE); -} - -//-------------------------------------------------------------------------- void LLToastIMPanel::onClickReplyBtn() { LLIMFloater::toggle(mSessionID); diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h index 7f5d6eca1d..11f489c12f 100644 --- a/indra/newview/lltoastimpanel.h +++ b/indra/newview/lltoastimpanel.h @@ -59,12 +59,9 @@ public: virtual ~LLToastIMPanel(); private: - static const S32 MAX_MESSAGE_HEIGHT; - static const S32 CAPTION_HEIGHT; - static const S32 TOP_PAD; + static const S32 DEFAULT_MESSAGE_MAX_LINE_COUNT; void onClickReplyBtn(); - void snapToMessageHeight(); LLUUID mSessionID; LLAvatarIconCtrl* mAvatar; diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index 28052a33be..e884d89ce4 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -49,5 +49,36 @@ std::string LLToastPanel::getTitle() return mNotification->getMessage(); } +//snap to the message height if it is visible +void LLToastPanel::snapToMessageHeight(LLTextBox* message, S32 maxLineCount) +{ + //Add message height if it is visible + if (message->getVisible()) + { + S32 heightDelta = 0; + S32 maxTextHeight = (S32)(message->getFont()->getLineHeight() * maxLineCount); + + LLRect messageRect = message->getRect(); + S32 oldTextHeight = messageRect.getHeight(); + + //Reshape the toast to give the message max height. + //This needed to calculate lines count according to specified text + heightDelta = maxTextHeight - oldTextHeight; + reshape( getRect().getWidth(), getRect().getHeight() + heightDelta); + message->setValue(message->getText()); + + //Knowing the height is set to max allowed, getTextPixelHeight returns needed text height + //Perhaps we need to pass maxLineCount as parameter to getTextPixelHeight to avoid previous reshape. + S32 requiredTextHeight = message->getTextPixelHeight(); + S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); + //Calculate last delta height deducting previous heightDelta + heightDelta = newTextHeight - oldTextHeight - heightDelta; + + //reshape the panel with new height + reshape( getRect().getWidth(), getRect().getHeight() + heightDelta); + message->setValue(message->getText()); + } + +} diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h index 2258eca273..bc9888f4b4 100644 --- a/indra/newview/lltoastpanel.h +++ b/indra/newview/lltoastpanel.h @@ -34,6 +34,7 @@ #define LL_LLTOASTPANEL_H #include "llpanel.h" +#include "lltextbox.h" #include "llnotifications.h" #include <string> @@ -53,6 +54,7 @@ public: virtual const LLUUID& getID() { return mNotification->id();} protected: LLNotificationPtr mNotification; + void snapToMessageHeight(LLTextBox* message, S32 maxLineCount); }; #endif /* LL_TOASTPANEL_H */ diff --git a/indra/newview/lltoolbar.cpp b/indra/newview/lltoolbar.cpp index acd6856061..c7c9f07504 100644 --- a/indra/newview/lltoolbar.cpp +++ b/indra/newview/lltoolbar.cpp @@ -60,6 +60,7 @@ #include "llui.h" #include "llviewermenu.h" #include "llfirstuse.h" +#include "llpanelblockedlist.h" #include "llscrolllistctrl.h" #include "llscrolllistitem.h" #include "llscrolllistcell.h" @@ -69,7 +70,6 @@ #include "lltoolgrab.h" #include "llcombobox.h" #include "llfloaterchat.h" -#include "llfloatermute.h" #include "llimpanel.h" #include "lllayoutstack.h" @@ -297,11 +297,8 @@ void LLToolBar::updateCommunicateList() communicate_button->addSeparator(ADD_TOP); communicate_button->add(getString("Redock Windows"), LLSD("redock"), ADD_TOP); communicate_button->addSeparator(ADD_TOP); - LLFloaterMute* mute_instance = LLFloaterReg::getTypedInstance<LLFloaterMute>("mute"); - if(mute_instance) - { - communicate_button->add(mute_instance->getShortTitle(), LLSD("mute list"), ADD_TOP); - } + communicate_button->add(getString("Blocked List"), LLSD("mute list"), ADD_TOP); + std::set<LLHandle<LLFloater> >::const_iterator floater_handle_it; if (gIMMgr->getIMFloaterHandles().size() > 0) @@ -379,7 +376,7 @@ void LLToolBar::onClickCommunicate(LLUICtrl* ctrl, const LLSD& user_data) } else if (selected_option.asString() == "mute list") { - LLFloaterReg::showInstance("mute"); + LLPanelBlockedList::showPanelAndSelect(LLUUID::null); } else if (selected_option.isUndefined()) // user just clicked the communicate button, treat as toggle { diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index b85dc30e72..c8f2e03903 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -78,7 +78,6 @@ #include "llfloaterlandholdings.h" #include "llfloatermap.h" #include "llfloatermemleak.h" -#include "llfloatermute.h" #include "llfloaternamedesc.h" #include "llfloaternotificationsconsole.h" #include "llfloateropenobject.h" @@ -110,6 +109,7 @@ #include "llmediaremotectrl.h" #include "llmoveview.h" #include "llnearbychat.h" +#include "llpanelblockedlist.h" #include "llpreviewanim.h" #include "llpreviewgesture.h" #include "llpreviewnotecard.h" @@ -177,8 +177,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("message_critical", "floater_critical.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>); LLFloaterReg::add("message_tos", "floater_tos.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>); LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMove>); - LLFloaterReg::add("mute", "floater_mute.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMute>); - LLFloaterReg::add("mute_object", "floater_mute_object.xml", &LLFloaterMute::buildFloaterMuteObjectUI); + LLFloaterReg::add("mute_object_by_name", "floater_mute_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGetBlockedObjectName>); LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMap>); LLFloaterReg::add("syswell_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLSysWellWindow>); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 95ab40f9bf..ec20af46a1 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -120,6 +120,41 @@ LLViewerInventoryItem::~LLViewerInventoryItem() { } +BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(S32* sortField, std::string* displayName) const +{ + using std::string; + using std::stringstream; + + const char separator = getSeparator(); + const string::size_type separatorPos = mName.find(separator, 0); + + BOOL result = FALSE; + + if (separatorPos < string::npos) + { + if (sortField) + { + /* + * The conversion from string to S32 is made this way instead of old plain + * atoi() to ensure portability. If on some other platform S32 will not be + * defined to be signed int, this conversion will still work because of + * operators overloading, but atoi() may fail. + */ + stringstream ss(mName.substr(0, separatorPos)); + ss >> *sortField; + } + + if (displayName) + { + *displayName = mName.substr(separatorPos + 1, string::npos); + } + + result = TRUE; + } + + return result; +} + void LLViewerInventoryItem::copyViewerItem(const LLViewerInventoryItem* other) { LLInventoryItem::copyItem(other); @@ -1102,7 +1137,70 @@ const std::string& LLViewerInventoryItem::getName() const return linked_category->getName(); } - return LLInventoryItem::getName(); + return getDisplayName(); +} + +const std::string& LLViewerInventoryItem::getDisplayName() const +{ + std::string result; + BOOL hasSortField = extractSortFieldAndDisplayName(0, &result); + + return mDisplayName = hasSortField ? result : LLInventoryItem::getName(); +} + +S32 LLViewerInventoryItem::getSortField() const +{ + S32 result; + BOOL hasSortField = extractSortFieldAndDisplayName(&result, 0); + + return hasSortField ? result : -1; +} + +void LLViewerInventoryItem::setSortField(S32 sortField) +{ + using std::string; + + std::stringstream ss; + ss << sortField; + + string newSortField = ss.str(); + + const char separator = getSeparator(); + const string::size_type separatorPos = mName.find(separator, 0); + + if (separatorPos < string::npos) + { + // the name of the LLViewerInventoryItem already consists of sort field and display name. + mName = newSortField + separator + mName.substr(separatorPos + 1, string::npos); + } + else + { + // there is no sort field in the name of LLViewerInventoryItem, we should add it + mName = newSortField + separator + mName; + } +} + +void LLViewerInventoryItem::rename(const std::string& n) +{ + using std::string; + + string new_name(n); + LLStringUtil::replaceNonstandardASCII(new_name, ' '); + LLStringUtil::replaceChar(new_name, '|', ' '); + LLStringUtil::trim(new_name); + LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN); + + const char separator = getSeparator(); + const string::size_type separatorPos = mName.find(separator, 0); + + if (separatorPos < string::npos) + { + mName.replace(separatorPos + 1, string::npos, new_name); + } + else + { + mName = new_name; + } } const LLPermissions& LLViewerInventoryItem::getPermissions() const diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 0bfb37f7e8..c4ff30bbfc 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -55,11 +55,18 @@ public: protected: ~LLViewerInventoryItem( void ); // ref counted + BOOL extractSortFieldAndDisplayName(S32* sortField, std::string* displayName) const; + static char getSeparator() { return '@'; } + mutable std::string mDisplayName; public: virtual LLAssetType::EType getType() const; virtual const LLUUID& getAssetUUID() const; virtual const std::string& getName() const; + virtual const std::string& getDisplayName() const; + virtual S32 getSortField() const; + virtual void setSortField(S32 sortField); + virtual void rename(const std::string& new_name); virtual const LLPermissions& getPermissions() const; virtual const LLUUID& getCreatorUUID() const; virtual const std::string& getDescription() const; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 8a5928f4e9..5536951ce6 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -113,7 +113,6 @@ #include "llfloaterland.h" #include "llfloaterlandholdings.h" #include "llfloatermap.h" -#include "llfloatermute.h" #include "llfloateropenobject.h" #include "llfloaterperms.h" #include "llfloaterpostprocess.h" @@ -147,6 +146,7 @@ #include "llfloaterinventory.h" #include "llkeyboard.h" #include "llpanellogin.h" +#include "llpanelblockedlist.h" #include "llmenucommands.h" #include "llmenugl.h" #include "llmimetypes.h" @@ -2896,7 +2896,7 @@ class LLObjectMute : public view_listener_t else { LLMuteList::getInstance()->add(mute); - LLFloaterReg::showInstance("mute"); + LLPanelBlockedList::showPanelAndSelect(mute.mID); } return true; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index dfb1c330e5..177c987bc0 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -82,7 +82,6 @@ #include "llfloaterregioninfo.h" #include "llfloaterlandholdings.h" #include "llurldispatcher.h" -#include "llfloatermute.h" #include "llfloaterpostcard.h" #include "llfloaterpreference.h" #include "llfollowcam.h" @@ -138,6 +137,7 @@ #include "llgroupactions.h" #include "llagentui.h" #include "llsidetray.h" +#include "llpanelblockedlist.h" #include "llpanelplaceinfo.h" #include <boost/tokenizer.hpp> @@ -1001,9 +1001,7 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id, LLMute mute(blocked_id, from_name, type); if (LLMuteList::getInstance()->add(mute)) { - LLFloaterReg::showInstance("mute"); - LLFloaterMute* mute_instance = LLFloaterReg::getTypedInstance<LLFloaterMute>("mute"); - if(mute_instance) mute_instance->selectMute(blocked_id); + LLPanelBlockedList::showPanelAndSelect(blocked_id); } // purge the message queue of any previously queued inventory offers from the same source. @@ -5576,7 +5574,7 @@ void process_covenant_reply(LLMessageSystem* msg, void**) LLPanelLandCovenant::updateEstateName(estate_name); LLFloaterBuyLand::updateEstateName(estate_name); - LLPanelPlaceInfo* panel = dynamic_cast<LLPanelPlaceInfo*>(LLSideTray::getInstance()->showPanel("panel_place_info", LLSD())); + LLPanelPlaceInfo* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceInfo>("panel_place_info"); if (panel) { panel->updateEstateName(estate_name); @@ -5660,7 +5658,7 @@ void callbackCacheEstateOwnerName(const LLUUID& id, LLPanelLandCovenant::updateEstateOwnerName(name); LLFloaterBuyLand::updateEstateOwnerName(name); - LLPanelPlaceInfo* panel = dynamic_cast<LLPanelPlaceInfo*>(LLSideTray::getInstance()->showPanel("panel_place_info", LLSD())); + LLPanelPlaceInfo* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceInfo>("panel_place_info"); if (panel) { panel->updateEstateOwnerName(name); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 607c5d9ae8..241c6fd511 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1596,8 +1596,6 @@ void LLViewerWindow::initWorldUI() gFloaterView->setRect(floater_view_rect); gNotifyBoxView->setRect(notify_view_rect); - // *Note: this is where gFloaterMute used to be initialized. - LLWorldMapView::initClass(); // Force gFloaterWorldMap to initialize @@ -1636,6 +1634,11 @@ void LLViewerWindow::initWorldUI() navbar->showFavoritesPanel(FALSE); } + if (!gSavedSettings.getBOOL("ShowCameraAndMoveControls")) + { + LLBottomTray::getInstance()->showCameraAndMoveControls(FALSE); + } + getRootView()->addChild(gStatusBar); getRootView()->addChild(navbar); @@ -1668,6 +1671,9 @@ void LLViewerWindow::initWorldUI() // put behind everything else in the UI getRootView()->addChildInBack(gHUDView); } + + // this allows not to see UI elements created while UI initializing after Alt+Tab was pressed during login. EXT-744. + moveProgressViewToFront(); } // Destroy the UI @@ -4417,8 +4423,7 @@ void LLViewerWindow::moveProgressViewToFront() { if( mProgressView && mRootView ) { - mRootView->removeChild( mProgressView ); - mRootView->addChild( mProgressView ); + mRootView->sendChildToFront(mProgressView); } } diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 0bd5f114ed..e32ea0944e 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -93,6 +93,7 @@ <texture name="Info_Press" file_name="navbar/Info_Press.png" preload="false"/> <texture name="ListItem_Select" file_name="widgets/ListItem_Select.png" preload="true" /> + <texture name="ListItem_Over" file_name="widgets/ListItem_Over.png" preload="true" /> <texture name="menu_separator" file_name="navbar/FileMenu_Divider.png" scale.left="4" scale.top="166" scale.right="0" scale.bottom="0" /> diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml index bb5a4e51f7..6ef1eb9513 100644 --- a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml @@ -15,4 +15,8 @@ <menu_item_call name="organize_offline" label="Organize Offline Friends"> <menu_item_call.on_click function="People.Friends.ViewSort.Action" userdata="organize_offline" /> </menu_item_call> + <menu_item_separator layout="topleft" /> + <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> + <menu_item_call.on_click function="SideTray.ShowPanel" parameter="panel_block_list_sidetray" /> + </menu_item_call> </menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml index 8c2c5e8c9e..2b0f029016 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml @@ -15,4 +15,8 @@ <menu_item_call name="view_icons" label="View People Icons"> <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="view_icons" /> </menu_item_call> + <menu_item_separator layout="topleft" /> + <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> + <menu_item_call.on_click function="SideTray.ShowPanel" userdata="panel_block_list_sidetray" /> + </menu_item_call> </menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml index 00cf443cc6..88b0528e53 100644 --- a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml @@ -12,4 +12,8 @@ <menu_item_call name="view_icons" label="View People Icons"> <menu_item_call.on_click function="People.Recent.ViewSort.Action" userdata="view_icons" /> </menu_item_call> + <menu_item_separator layout="topleft" /> + <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> + <menu_item_call.on_click function="SideTray.ShowPanel" userdata="panel_block_list_sidetray" /> + </menu_item_call> </menu> diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml new file mode 100644 index 0000000000..5c8a8ee208 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + background_visible="true" + follows="left|top|right|bottom" + height="305" + layout="topleft" + name="block_list_panel" + min_height="350" + min_width="240" + width="280"> + <text + follows="top|left|right" + font="SansSerifHugeBold" + height="20" + layout="topleft" + left="10" + name="title_text" + text_color="white" + top="0" + width="250"> + Blocked List + </text> + <button + follows="top|right" + height="25" + image_overlay="BackArrow_Off" + layout="topleft" + name="back" + right="-9" + tab_stop="false" + top="0" + width="25"/> + <scroll_list + follows="left|top|right|bottom" + height="200" + layout="topleft" + left="5" + name="blocked" + tool_tip="List of currently blocked residents" + top="30" + width="270" /> + <button + follows="left|bottom" + height="20" + label="Block Resident..." + label_selected="Block Resident..." + layout="topleft" + left_delta="0" + name="Block resident..." + tool_tip="Pick a resident to block" + top_pad="4" + width="210"> + <button.commit_callback + function="Block.ClickPick" /> + </button> + <button + follows="left|bottom" + height="20" + label="Block object by name..." + label_selected="Block object by name..." + layout="topleft" + left_delta="0" + name="Block object by name..." + top_pad="4" + width="210" > + <button.commit_callback + function="Block.ClickBlockByName" /> + </button> + <button + enabled="false" + follows="left|bottom" + height="20" + label="Unblock" + label_selected="Unblock" + layout="topleft" + left_delta="0" + name="Unblock" + tool_tip="Remove resident or object from blocked list" + top_pad="4" + width="210" > + <button.commit_callback + function="Block.ClickRemove" /> + </button> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 8fc029bea6..79ca839f28 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -266,7 +266,7 @@ top="2" width="48"> <button - image_selected="bottom_tray_sys_notifications.tga" + image_selected="bottom_tray_sys_notifications_selected.tga" image_unselected="bottom_tray_sys_notifications.tga"/> <unread_notifications width="20" diff --git a/indra/newview/skins/default/xui/en/panel_edit_profile.xml b/indra/newview/skins/default/xui/en/panel_edit_profile.xml index fa02cdb4b2..0d6d8ba97d 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml @@ -13,10 +13,44 @@ top="10" width="255"> <string + name="CaptionTextAcctInfo"> + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + </string> + <string + name="AcctTypeResident" + value="Resident" /> + <string + name="AcctTypeTrial" + value="Trial" /> + <string + name="AcctTypeCharterMember" + value="Charter Member" /> + <string + name="AcctTypeEmployee" + value="Linden Lab Employee" /> + <string + name="PaymentInfoUsed" + value="Payment Info Used" /> + <string + name="PaymentInfoOnFile" + value="Payment Info On File" /> + <string + name="NoPaymentInfoOnFile" + value="No Payment Info On File" /> + <string + name="AgeVerified" + value="Age-verified" /> + <string + name="NotAgeVerified" + value="Not Age-verified" /> + <string name="partner_edit_link_url"> http://www.secondlife.com/account/partners.php?lang=en </string> - <scroll_container + <string + name="no_partner_text" + value="None" /> + <scroll_container color="DkGray2" follows="left|top|right|bottom" height="300" @@ -38,7 +72,7 @@ background_visible="true" bg_alpha_color="DkGray2" follows="left|top|right|bottom" - height="620" + height="750" layout="topleft" left="0" name="data_panel" diff --git a/indra/newview/skins/default/xui/en/panel_group_notify.xml b/indra/newview/skins/default/xui/en/panel_group_notify.xml index 8ebf1b69a7..f97daf922f 100644 --- a/indra/newview/skins/default/xui/en/panel_group_notify.xml +++ b/indra/newview/skins/default/xui/en/panel_group_notify.xml @@ -1,8 +1,12 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel background_visible="true" bevel_style="in" bg_alpha_color="0 0 0 0" - height="200" label="instant_message" layout="topleft" left="0" + height="155" label="instant_message" layout="topleft" left="0" name="panel_group_notify" top="0" width="350"> - <panel background_visible="true" bevel_style="in" bg_alpha_color="black" + <string + name="message_max_lines_count"> + 4 + </string> + <panel follows="top" background_visible="true" bevel_style="in" bg_alpha_color="black" height="50" label="header" layout="topleft" left="0" name="header" top="0" width="350"> <icon follows="left|top|right|bottom" height="40" width="40" layout="topleft" @@ -13,21 +17,61 @@ Sender Name / Group Name </text> </panel> - <text_editor type="string" length="1" bg_readonly_color="0 0 0 0" - follows="left|top|right|bottom" height="70" hide_scrollbar="true" - hide_border="true" layout="topleft" top="55" left="25" name="message" - text_color="GroupNotifyTextColor" text_readonly_color="GroupNotifyTextColor" width="300" word_wrap="true"> - Message - Body - </text_editor> - <icon follows="left|top|right|bottom" height="16" width="16" - layout="topleft" top="135" left="25" mouse_opaque="true" name="attachment_icon" /> + <text + follows="top" + height="20" + layout="topleft" + left="25" + name="subject" + text_color="GroupNotifyTextColor" + font="SansSerifBig" + top="60" + use_ellipses="true" + value="subject" + width="300" + word_wrap="true"> + subject + </text> + <text + follows="top" + height="20" + layout="topleft" + left="25" + name="datetime" + text_color="GroupNotifyTextColor" + font="SansSerif" + top="80" + use_ellipses="true" + value="datetime" + width="300" + word_wrap="true"> + datetime + </text> + <text + follows="left|top|bottom|right" + height="0" + layout="topleft" + left="25" + name="message" + text_color="GroupNotifyTextColor" + top="100" + use_ellipses="true" + value="message" + width="300" + word_wrap="true" + visible="true" > + </text> + <icon + follows="left|bottom|right" height="15" width="15" + layout="topleft" bottom="122" left="25" mouse_opaque="true" name="attachment_icon" visible="true" + /> <text font="SansSerif" font.style="UNDERLINE" font_shadow="hard" - type="string" length="1" follows="left|top|right|bottom" layout="topleft" - left="45" top="135" height="15" width="280" name="attachment" - text_color="GroupNotifyTextColor"> + type="string" length="1" follows="left|bottom|right" layout="topleft" + left="45" bottom="122" height="15" width="280" name="attachment" + text_color="GroupNotifyTextColor" visible="true"> Attachment - </text> - <button label="OK" layout="topleft" top="170" left="140" height="20" - width="70" name="btn_ok" /> -</panel> + </text> + + <button label="OK" layout="topleft" bottom="145" left="140" height="20" + width="70" name="btn_ok" follows="bottom" /> +</panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_instant_message.xml b/indra/newview/skins/default/xui/en/panel_instant_message.xml index 169fde7b47..ace456918c 100644 --- a/indra/newview/skins/default/xui/en/panel_instant_message.xml +++ b/indra/newview/skins/default/xui/en/panel_instant_message.xml @@ -10,6 +10,10 @@ name="im_panel" top="0" width="350"> + <string + name="message_max_lines_count"> + 6 + </string> <panel background_visible="true" bevel_style="in" @@ -56,7 +60,7 @@ width="50" /> </panel> <text - follows="left|bottom|right" + follows="left|top|bottom|right" height="60" layout="topleft" left="10" diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml index dee911a45d..80dca8c0c1 100644 --- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml @@ -107,8 +107,8 @@ <!-- picture_style="true" --> <!-- top_delta="0" --> <!-- width="168" /> --> - - <search_editor + + <search_combo_box bevel_style="none" border_style="line" border.border_thickness="0" @@ -118,12 +118,15 @@ height="22" label="Search" layout="topleft" - left_pad="7" + right="-10" mouse_opaque="false" - name="search_input" + name="search_combo_box" tool_tip="Search" top_delta="0" - width="200" /> + width="200" > + <combo_editor + label="Search" /> + </search_combo_box> </panel> <favorites_bar diff --git a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml index 6f4110067b..4c8c4efbe7 100644 --- a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml @@ -8,6 +8,26 @@ name="picture_item" top="0" width="275"> + <icon + height="120" + image_name="ListItem_Over" + left="0" + mouse_opaque="false" + name="hovered_icon" + top="0" + scale_image="true" + visible="false" + width="270"/> + <icon + height="120" + image_name="ListItem_Select" + left="0" + mouse_opaque="false" + name="selected_icon" + top="0" + scale_image="true" + visible="false" + width="270"/> <texture_picker allow_no_texture="true" default_image_name="None" diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml index e9eac2c9dc..e166675364 100644 --- a/indra/newview/skins/default/xui/en/panel_side_tray.xml +++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml @@ -57,6 +57,13 @@ label="Group Info" border="true" /> + <panel + class="panel_block_list_sidetray" + name="panel_block_list_sidetray" + filename="panel_block_list_sidetray.xml" + label="Blocked Residents & Objects" + border="true" + /> </panel_container> </sidetray_tab> diff --git a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml new file mode 100644 index 0000000000..eabacbecb2 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<accordion_tab + header_collapse_img="accordion_collapsed.tga" + header_collapse_img_pressed="accordion_collapsed.tga" + header_expand_img="accordion_expanded.tga" + header_expand_img_pressed="accordion_expanded.tga" /> diff --git a/indra/newview/skins/default/xui/en/widgets/list.xml b/indra/newview/skins/default/xui/en/widgets/list.xml index 8c264205d5..4a59716464 100644 --- a/indra/newview/skins/default/xui/en/widgets/list.xml +++ b/indra/newview/skins/default/xui/en/widgets/list.xml @@ -6,4 +6,5 @@ background_visible="false" background_opaque="false" item_pad="5" + keep_one_selected="true" multi_select="false" />
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/location_input.xml b/indra/newview/skins/default/xui/en/widgets/location_input.xml index 8f4d0edf95..297a3762f6 100644 --- a/indra/newview/skins/default/xui/en/widgets/location_input.xml +++ b/indra/newview/skins/default/xui/en/widgets/location_input.xml @@ -43,7 +43,7 @@ label="" pad_right="0" tool_tip="My Location History"/> - <combo_list bg_writeable_color="MenuDefaultBgColor"/> + <combo_list bg_writeable_color="MenuDefaultBgColor" page_lines="10"/> <combo_editor name="Combo Text Entry" text_pad_left="20" select_on_focus="false" diff --git a/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml b/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml new file mode 100644 index 0000000000..1d43b25f1d --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<search_combo_box + allow_text_entry="true" + list_position="BELOW" + show_text_as_tentative="false" + dropdown_button_visible="false" + background_image="TextField_Search_Off" + background_image_disabled="TextField_Search_Disabled" + background_image_focused="TextField_Search_Active"> + <combo_editor + select_on_focus="true" + text_pad_left="20" + background_image="TextField_Search_Off" + background_image_disabled="TextField_Search_Disabled" + background_image_focused="TextField_Search_Active"/> + <combo_list + multi_select="false" + page_lines="10" /> + <search_button label="" + top_pad="4" + left_pad="4" + width="13" + height="13" + image_unselected="Search" + image_selected="Search" /> +</search_combo_box>
\ No newline at end of file |