diff options
Diffstat (limited to 'indra')
73 files changed, 1467 insertions, 1148 deletions
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index d7d411dee6..0a284f0088 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -85,6 +85,7 @@ set(llui_SOURCE_FILES lltextbox.cpp lltexteditor.cpp lltextparser.cpp + lltransientfloatermgr.cpp lltransutil.cpp lltooltip.cpp llui.cpp @@ -171,6 +172,7 @@ set(llui_HEADER_FILES lltexteditor.h lltextparser.h lltooltip.h + lltransientfloatermgr.h lltransutil.h lluicolortable.h lluiconstants.h diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp index 93d62fd7c2..4525f0a45b 100644 --- a/indra/llui/lldockablefloater.cpp +++ b/indra/llui/lldockablefloater.cpp @@ -71,9 +71,9 @@ void LLDockableFloater::resetInstance() if (sInstanceHandle.get() != NULL && sInstanceHandle.get()->isDocked()) { sInstanceHandle.get()->setVisible(FALSE); - } + } sInstanceHandle = getHandle(); - } + } } void LLDockableFloater::setVisible(BOOL visible) @@ -105,11 +105,11 @@ void LLDockableFloater::setDocked(bool docked, bool pop_on_undock) mDockControl.get()->off(); } - if (!docked && pop_on_undock) - { - // visually pop up a little bit to emphasize the undocking - translate(0, UNDOCK_LEAP_HEIGHT); - } + if (!docked && pop_on_undock) + { + // visually pop up a little bit to emphasize the undocking + translate(0, UNDOCK_LEAP_HEIGHT); + } } else { @@ -126,8 +126,8 @@ void LLDockableFloater::draw() mDockControl.get()->repositionDockable(); if (isDocked()) { - mDockControl.get()->drawToungue(); - } + mDockControl.get()->drawToungue(); + } } LLFloater::draw(); } diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp index 0b16b2554c..146c7a969a 100644 --- a/indra/llui/lldockcontrol.cpp +++ b/indra/llui/lldockcontrol.cpp @@ -35,7 +35,7 @@ #include "lldockcontrol.h" LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, - const LLUIImagePtr& dockTongue, DocAt dockAt, get_rect_callback_t get_rect_callback) : + const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) : mDockWidget(dockWidget), mDockableFloater(dockableFloater), mDockTongue(dockTongue) { mDockAt = dockAt; @@ -49,13 +49,13 @@ LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, off(); } - if (!(get_rect_callback)) + if (!(get_allowed_rect_callback)) { - mGetRectCallback = boost::bind(&LLDockControl::getEnabledRect, this, _1); + mGetAllowedRectCallback = boost::bind(&LLDockControl::getAllowedRect, this, _1); } else { - mGetRectCallback = get_rect_callback; + mGetAllowedRectCallback = get_allowed_rect_callback; } if (dockWidget != NULL) @@ -77,7 +77,7 @@ void LLDockControl::setDock(LLView* dockWidget) } } -void LLDockControl::getEnabledRect(LLRect& rect) +void LLDockControl::getAllowedRect(LLRect& rect) { rect = mDockableFloater->getRootView()->getRect(); } @@ -86,7 +86,7 @@ void LLDockControl::repositionDockable() { LLRect dockRect = mDockWidget->calcScreenRect(); LLRect rootRect; - mGetRectCallback(rootRect); + mGetAllowedRectCallback(rootRect); static BOOL prev_visibility = !mDockWidget->getVisible(); // recalculate dockable position if dock position changed, dock visibility changed, @@ -100,7 +100,7 @@ void LLDockControl::repositionDockable() mDockableFloater->setDocked(false); // force off() since dockable may not have dockControll at this time off(); - } + } else { moveDockable(); @@ -123,10 +123,10 @@ bool LLDockControl::isDockVisible() res = mDockWidget->isInVisibleChain(); if (res) { - LLRect dockRect = mDockWidget->calcScreenRect(); + LLRect dockRect = mDockWidget->calcScreenRect(); switch (mDockAt) - { + { case TOP: // check is dock inside parent rect LLRect dockParentRect = @@ -149,25 +149,25 @@ void LLDockControl::moveDockable() // calculate new dockable position LLRect dockRect = mDockWidget->calcScreenRect(); LLRect rootRect; - mGetRectCallback(rootRect); + mGetAllowedRectCallback(rootRect); - LLRect dockableRect = mDockableFloater->calcScreenRect(); - S32 x = 0; - S32 y = 0; - switch (mDockAt) - { - case TOP: - x = dockRect.getCenterX() - dockableRect.getWidth() / 2; + LLRect dockableRect = mDockableFloater->calcScreenRect(); + S32 x = 0; + S32 y = 0; + switch (mDockAt) + { + case TOP: + x = dockRect.getCenterX() - dockableRect.getWidth() / 2; y = dockRect.mTop + mDockTongue->getHeight() + dockableRect.getHeight(); // check is dockable inside root view rect - if (x < rootRect.mLeft) - { - x = rootRect.mLeft; - } - if (x + dockableRect.getWidth() > rootRect.mRight) - { - x = rootRect.mRight - dockableRect.getWidth(); - } + if (x < rootRect.mLeft) + { + x = rootRect.mLeft; + } + if (x + dockableRect.getWidth() > rootRect.mRight) + { + x = rootRect.mRight - dockableRect.getWidth(); + } // calculate dock tongue position @@ -185,21 +185,21 @@ void LLDockControl::moveDockable() { mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2; } - mDockTongueY = dockRect.mTop; + mDockTongueY = dockRect.mTop; - break; - } + break; + } // move dockable - dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(), - dockableRect.getHeight()); - LLRect localDocableParentRect; - mDockableFloater->getParent()->screenRectToLocal(dockableRect, - &localDocableParentRect); - mDockableFloater->setRect(localDocableParentRect); + dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(), + dockableRect.getHeight()); + LLRect localDocableParentRect; + mDockableFloater->getParent()->screenRectToLocal(dockableRect, + &localDocableParentRect); + mDockableFloater->setRect(localDocableParentRect); - mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY, - &mDockTongueX, &mDockTongueY); + mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY, + &mDockTongueX, &mDockTongueY); } @@ -207,9 +207,9 @@ void LLDockControl::on() { if (isDockVisible()) { - mDockableFloater->setCanDrag(false); - mEnabled = true; - mRecalculateDocablePosition = true; + mDockableFloater->setCanDrag(false); + mEnabled = true; + mRecalculateDocablePosition = true; } } diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h index 219ddfd092..e8ffcac0ac 100644 --- a/indra/llui/lldockcontrol.h +++ b/indra/llui/lldockcontrol.h @@ -52,11 +52,11 @@ public: public: // callback for a function getting a rect valid for control's position - typedef boost::function<void (LLRect& )> get_rect_callback_t; + typedef boost::function<void (LLRect& )> get_allowed_rect_callback_t; LOG_CLASS(LLDockControl); LLDockControl(LLView* dockWidget, LLFloater* dockableFloater, - const LLUIImagePtr& dockTongue, DocAt dockAt, get_rect_callback_t get_rect_callback = NULL); + const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_rect_callback = NULL); virtual ~LLDockControl(); public: @@ -67,13 +67,13 @@ public: void drawToungue(); bool isDockVisible(); - // gets a rect that bounds possible positions for a dockable control - void getEnabledRect(LLRect& rect); + // gets a rect that bounds possible positions for a dockable control (EXT-1111) + void getAllowedRect(LLRect& rect); private: virtual void moveDockable(); private: - get_rect_callback_t mGetRectCallback; + get_allowed_rect_callback_t mGetAllowedRectCallback; bool mEnabled; bool mRecalculateDocablePosition; DocAt mDockAt; diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 9fcd386c19..e9df361472 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -39,8 +39,8 @@ static const LLDefaultChildRegistry::Register<LLFlatListView> flat_list_view("flat_list_view"); -const LLSD SELECTED_EVENT = LLSD().insert("selected", true); -const LLSD UNSELECTED_EVENT = LLSD().insert("selected", false); +const LLSD SELECTED_EVENT = LLSD().insert("selected", true); +const LLSD UNSELECTED_EVENT = LLSD().insert("selected", false); static const std::string COMMENT_TEXTBOX = "comment_text"; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 8d5f277b59..39f09b297f 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -2001,6 +2001,8 @@ void LLTextEditor::cut() deleteSelection( FALSE ); needsReflow(); + + onKeyStroke(); } BOOL LLTextEditor::canCopy() const @@ -2105,6 +2107,8 @@ void LLTextEditor::pasteHelper(bool is_primary) deselect(); needsReflow(); + + onKeyStroke(); } @@ -2492,6 +2496,8 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask ) if(text_may_have_changed) { needsReflow(); + + onKeyStroke(); } needsScroll(); } @@ -2534,6 +2540,8 @@ BOOL LLTextEditor::handleUnicodeCharHere(llwchar uni_char) deselect(); needsReflow(); + + onKeyStroke(); } return handled; @@ -2588,6 +2596,8 @@ void LLTextEditor::doDelete() setCursorPos(mCursorPos + 1); removeChar(); } + + onKeyStroke(); } needsReflow(); @@ -2634,6 +2644,8 @@ void LLTextEditor::undo() setCursorPos(pos); needsReflow(); + + onKeyStroke(); } BOOL LLTextEditor::canRedo() const @@ -2676,6 +2688,8 @@ void LLTextEditor::redo() setCursorPos(pos); needsReflow(); + + onKeyStroke(); } void LLTextEditor::onFocusReceived() @@ -4402,6 +4416,8 @@ void LLTextEditor::updatePreedit(const LLWString &preedit_string, // Update of the preedit should be caused by some key strokes. mKeystrokeTimer.reset(); + + onKeyStroke(); } BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const @@ -4648,3 +4664,30 @@ void LLInlineViewSegment::linkToDocument(LLTextBase* editor) ed->addDocumentChild(mView); } } + +BOOL LLTextEditor::isDirty() const +{ + if(mReadOnly) + { + return FALSE; + } + + if( mPristineCmd ) + { + return ( mPristineCmd == mLastCmd ); + } + else + { + return ( NULL != mLastCmd ); + } +} + +void LLTextEditor::setKeystrokeCallback(const keystroke_signal_t::slot_type& callback) +{ + mKeystrokeSignal.connect(callback); +} + +void LLTextEditor::onKeyStroke() +{ + mKeystrokeSignal(this); +} diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 68b8f2c3b1..a04261c4be 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -139,6 +139,10 @@ public: virtual ~LLTextEditor(); + typedef boost::signals2::signal<void (LLTextEditor* caller)> keystroke_signal_t; + + void setKeystrokeCallback(const keystroke_signal_t::slot_type& callback); + void setParseHighlights(BOOL parsing) {mParseHighlights=parsing;} // mousehandler overrides @@ -169,7 +173,7 @@ public: virtual void clear(); virtual void setFocus( BOOL b ); virtual BOOL acceptsTextInput() const; - virtual BOOL isDirty() const { return isPristine(); } + virtual BOOL isDirty() const; virtual void setValue(const LLSD& value); // LLEditMenuHandler interface @@ -503,6 +507,8 @@ private: S32 getFirstVisibleLine() const; + void onKeyStroke(); + // // Data // @@ -568,6 +574,8 @@ private: BOOL mHandleEditKeysDirectly; LLCoordGL mLastIMEPosition; // Last position of the IME editor + + keystroke_signal_t mKeystrokeSignal; }; // end class LLTextEditor diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index ee14a2ff86..36f9780ad0 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -41,6 +41,10 @@ static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list"); +// Maximum number of avatars that can be added to a list in one pass. +// Used to limit time spent for avatar list update per frame. +static const unsigned ADD_LIMIT = 50; + static bool findInsensitive(std::string haystack, const std::string& needle_upper) { LLStringUtil::toUpper(haystack); @@ -65,6 +69,7 @@ LLAvatarList::LLAvatarList(const Params& p) : LLFlatListView(p) , mOnlineGoFirst(p.online_go_first) , mContextMenu(NULL) +, mDirty(true) // to force initial update { setCommitOnSelectionChange(true); @@ -72,44 +77,40 @@ LLAvatarList::LLAvatarList(const Params& p) setComparator(&NAME_COMPARATOR); } -void LLAvatarList::computeDifference( - const std::vector<LLUUID>& vnew_unsorted, - std::vector<LLUUID>& vadded, - std::vector<LLUUID>& vremoved) +// virtual +void LLAvatarList::draw() { - std::vector<LLUUID> vcur; - std::vector<LLUUID> vnew = vnew_unsorted; + if (mDirty) + refresh(); - // Convert LLSDs to LLUUIDs. - { - std::vector<LLSD> vcur_values; - getValues(vcur_values); + LLFlatListView::draw(); +} - for (size_t i=0; i<vcur_values.size(); i++) - vcur.push_back(vcur_values[i].asUUID()); +void LLAvatarList::setNameFilter(const std::string& filter) +{ + if (mNameFilter != filter) + { + mNameFilter = filter; + setDirty(); } +} - std::sort(vcur.begin(), vcur.end()); - std::sort(vnew.begin(), vnew.end()); - - std::vector<LLUUID>::iterator it; - size_t maxsize = llmax(vcur.size(), vnew.size()); - vadded.resize(maxsize); - vremoved.resize(maxsize); - - // what to remove - it = set_difference(vcur.begin(), vcur.end(), vnew.begin(), vnew.end(), vremoved.begin()); - vremoved.erase(it, vremoved.end()); - - // what to add - it = set_difference(vnew.begin(), vnew.end(), vcur.begin(), vcur.end(), vadded.begin()); - vadded.erase(it, vadded.end()); +void LLAvatarList::sortByName() +{ + setComparator(&NAME_COMPARATOR); + sort(); } -BOOL LLAvatarList::update(const std::vector<LLUUID>& all_buddies, const std::string& name_filter) +////////////////////////////////////////////////////////////////////////// +// PROTECTED SECTION +////////////////////////////////////////////////////////////////////////// + +void LLAvatarList::refresh() { - BOOL have_names = TRUE; - bool have_filter = name_filter != LLStringUtil::null; + bool have_names = TRUE; + bool add_limit_exceeded = false; + bool modified = false; + bool have_filter = !mNameFilter.empty(); // Save selection. std::vector<LLUUID> selected_ids; @@ -118,22 +119,36 @@ BOOL LLAvatarList::update(const std::vector<LLUUID>& all_buddies, const std::str // Determine what to add and what to remove. std::vector<LLUUID> added, removed; - LLAvatarList::computeDifference(all_buddies, added, removed); + LLAvatarList::computeDifference(getIDs(), added, removed); // Handle added items. + unsigned nadded = 0; for (std::vector<LLUUID>::const_iterator it=added.begin(); it != added.end(); it++) { std::string name; const LLUUID& buddy_id = *it; - have_names &= gCacheName->getFullName(buddy_id, name); - if (!have_filter || findInsensitive(name, name_filter)) - addNewItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id)); + have_names &= (bool)gCacheName->getFullName(buddy_id, name); + if (!have_filter || findInsensitive(name, mNameFilter)) + { + if (nadded >= ADD_LIMIT) + { + add_limit_exceeded = true; + break; + } + else + { + addNewItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id)); + modified = true; + nadded++; + } + } } // Handle removed items. for (std::vector<LLUUID>::const_iterator it=removed.begin(); it != removed.end(); it++) { removeItemByUUID(*it); + modified = true; } // Handle filter. @@ -146,9 +161,12 @@ BOOL LLAvatarList::update(const std::vector<LLUUID>& all_buddies, const std::str { std::string name; const LLUUID& buddy_id = it->asUUID(); - have_names &= gCacheName->getFullName(buddy_id, name); - if (!findInsensitive(name, name_filter)) + have_names &= (bool)gCacheName->getFullName(buddy_id, name); + if (!findInsensitive(name, mNameFilter)) + { removeItemByUUID(buddy_id); + modified = true; + } } } @@ -167,18 +185,15 @@ BOOL LLAvatarList::update(const std::vector<LLUUID>& all_buddies, const std::str // // Otherwise, if we have no filter then no need to update again // because the items will update their names. - return !have_filter || have_names; -} + bool dirty = add_limit_exceeded || (have_filter && !have_names); + setDirty(dirty); -void LLAvatarList::sortByName() -{ - setComparator(&NAME_COMPARATOR); - sort(); + // Commit if we've added/removed items. + if (modified) + onCommit(); } -////////////////////////////////////////////////////////////////////////// -// PROTECTED SECTION -////////////////////////////////////////////////////////////////////////// + void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos) { LLAvatarListItem* item = new LLAvatarListItem(); @@ -194,8 +209,39 @@ void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is addItem(item, id, pos); } +void LLAvatarList::computeDifference( + const std::vector<LLUUID>& vnew_unsorted, + std::vector<LLUUID>& vadded, + std::vector<LLUUID>& vremoved) +{ + std::vector<LLUUID> vcur; + std::vector<LLUUID> vnew = vnew_unsorted; + // Convert LLSDs to LLUUIDs. + { + std::vector<LLSD> vcur_values; + getValues(vcur_values); + for (size_t i=0; i<vcur_values.size(); i++) + vcur.push_back(vcur_values[i].asUUID()); + } + + std::sort(vcur.begin(), vcur.end()); + std::sort(vnew.begin(), vnew.end()); + + std::vector<LLUUID>::iterator it; + size_t maxsize = llmax(vcur.size(), vnew.size()); + vadded.resize(maxsize); + vremoved.resize(maxsize); + + // what to remove + it = set_difference(vcur.begin(), vcur.end(), vnew.begin(), vnew.end(), vremoved.begin()); + vremoved.erase(it, vremoved.end()); + + // what to add + it = set_difference(vnew.begin(), vnew.end(), vcur.begin(), vcur.end(), vadded.begin()); + vadded.erase(it, vadded.end()); +} bool LLAvatarItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const { diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index 8d79e073d2..ec801645fe 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -37,10 +37,22 @@ #include "llavatarlistitem.h" +/** + * Generic list of avatars. + * + * Updates itself when it's dirty, using optional name filter. + * To initiate update, modify the UUID list and call setDirty(). + * + * @see getIDs() + * @see setDirty() + * @see setNameFilter() + */ class LLAvatarList : public LLFlatListView { LOG_CLASS(LLAvatarList); public: + typedef std::vector<LLUUID> uuid_vector_t; + struct Params : public LLInitParam::Block<Params, LLFlatListView::Params> { Optional<S32> volume_column_width; @@ -51,14 +63,19 @@ public: LLAvatarList(const Params&); virtual ~LLAvatarList() {} - BOOL update(const std::vector<LLUUID>& all_buddies, - const std::string& name_filter = LLStringUtil::null); + virtual void draw(); // from LLView + + void setNameFilter(const std::string& filter); + void setDirty(bool val = true) { mDirty = val; } + uuid_vector_t& getIDs() { return mIDs; } void setContextMenu(LLAvatarListItem::ContextMenu* menu) { mContextMenu = menu; } void sortByName(); protected: + void refresh(); + void addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos = ADD_BOTTOM); void computeDifference( const std::vector<LLUUID>& vnew, @@ -68,6 +85,10 @@ protected: private: bool mOnlineGoFirst; + bool mDirty; + + std::string mNameFilter; + uuid_vector_t mIDs; LLAvatarListItem::ContextMenu* mContextMenu; }; diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 46151b469f..8771611b1c 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -133,6 +133,7 @@ LLIMChiclet* LLBottomTray::createIMChiclet(const LLUUID& session_id) case LLIMChiclet::TYPE_IM: return getChicletPanel()->createChiclet<LLIMP2PChiclet>(session_id); case LLIMChiclet::TYPE_GROUP: + case LLIMChiclet::TYPE_AD_HOC: return getChicletPanel()->createChiclet<LLIMGroupChiclet>(session_id); case LLIMChiclet::TYPE_UNKNOWN: break; @@ -231,7 +232,7 @@ void LLBottomTray::showBottomTrayContextMenu(S32 x, S32 y, MASK mask) mBottomTrayContextMenu->updateParent(LLMenuGL::sMenuContainer); LLMenuGL::showPopup(this, mBottomTrayContextMenu, x, y); - } + } } void LLBottomTray::showGestureButton(BOOL visible) @@ -243,7 +244,7 @@ void LLBottomTray::showGestureButton(BOOL visible) mGestureCombo->setVisible(visible); if (!visible) - { + { LLFloaterReg::hideFloaterInstance("gestures"); r.mRight -= mGestureCombo->getRect().getWidth(); } diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index 7ae9976338..b4b680416c 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -77,7 +77,7 @@ LLScreenChannel* LLChannelManager::createNotificationChannel() p.channel_align = CA_RIGHT; // Getting a Channel for our notifications - return LLChannelManager::getInstance()->getChannel(p); + return dynamic_cast<LLScreenChannel*> (LLChannelManager::getInstance()->createChannel(p)); } //-------------------------------------------------------------------------- @@ -113,7 +113,7 @@ void LLChannelManager::onLoginCompleted() LLChannelManager::Params p; p.id = LLUUID(gSavedSettings.getString("StartUpChannelUUID")); p.channel_align = CA_RIGHT; - mStartUpChannel = getChannel(p); + mStartUpChannel = createChannel(p); if(!mStartUpChannel) { @@ -147,22 +147,32 @@ void LLChannelManager::onStartUpToastClose() LLScreenChannel::setStartUpToastShown(); // force NEARBY CHAT CHANNEL to repost all toasts if present - LLScreenChannel* nearby_channel = findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); - nearby_channel->loadStoredToastsToChannel(); - nearby_channel->setCanStoreToasts(false); + //LLScreenChannelBase* nearby_channel = findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); + //!!!!!!!!!!!!!! + //FIXME + //nearby_channel->loadStoredToastsToChannel(); + //nearby_channel->setCanStoreToasts(false); } //-------------------------------------------------------------------------- -LLScreenChannel* LLChannelManager::getChannel(LLChannelManager::Params& p) + +LLScreenChannelBase* LLChannelManager::addChannel(LLScreenChannelBase* channel) { - LLScreenChannel* new_channel = NULL; + if(!channel) + return 0; - new_channel = findChannelByID(p.id); + ChannelElem new_elem; + new_elem.id = channel->getChannelID(); + new_elem.channel = channel; - if(new_channel) - return new_channel; + mChannelList.push_back(new_elem); - new_channel = new LLScreenChannel(p.id); + return channel; +} + +LLScreenChannel* LLChannelManager::createChannel(LLChannelManager::Params& p) +{ + LLScreenChannel* new_channel = new LLScreenChannel(p.id); if(!new_channel) { @@ -172,20 +182,26 @@ LLScreenChannel* LLChannelManager::getChannel(LLChannelManager::Params& p) { new_channel->setToastAlignment(p.toast_align); new_channel->setChannelAlignment(p.channel_align); - new_channel->setDisplayToastsAlways(p.display_toasts_always); - - ChannelElem new_elem; - new_elem.id = p.id; - new_elem.channel = new_channel; + new_channel->setDisplayToastsAlways(p.display_toasts_always); - mChannelList.push_back(new_elem); + addChannel(new_channel); } - return new_channel; } +LLScreenChannelBase* LLChannelManager::getChannel(LLChannelManager::Params& p) +{ + LLScreenChannelBase* new_channel = findChannelByID(p.id); + + if(new_channel) + return new_channel; + + return createChannel(p); + +} + //-------------------------------------------------------------------------- -LLScreenChannel* LLChannelManager::findChannelByID(const LLUUID id) +LLScreenChannelBase* LLChannelManager::findChannelByID(const LLUUID id) { std::vector<ChannelElem>::iterator it = find(mChannelList.begin(), mChannelList.end(), id); if(it != mChannelList.end()) diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h index 811fa06d2b..b927d369cd 100644 --- a/indra/newview/llchannelmanager.h +++ b/indra/newview/llchannelmanager.h @@ -52,8 +52,8 @@ class LLChannelManager : public LLSingleton<LLChannelManager> public: struct Params { - LLUUID id; - bool display_toasts_always; + LLUUID id; + bool display_toasts_always; EToastAlignment toast_align; EChannelAlignment channel_align; @@ -64,7 +64,7 @@ public: struct ChannelElem { LLUUID id; - LLScreenChannel* channel; + LLScreenChannelBase* channel; ChannelElem() : id(LLUUID("")), channel(NULL) { } @@ -89,19 +89,23 @@ public: void onStartUpToastClose(); // creates a new ScreenChannel according to the given parameters or returns existing if present - LLScreenChannel* getChannel(LLChannelManager::Params& p); + LLScreenChannelBase* getChannel(LLChannelManager::Params& p); + + LLScreenChannelBase* addChannel(LLScreenChannelBase* channel); // returns a channel by its ID - LLScreenChannel* findChannelByID(const LLUUID id); + LLScreenChannelBase* findChannelByID(const LLUUID id); // creator of the Notification channel, that is used in more than one handler - LLScreenChannel* createNotificationChannel(); + LLScreenChannel* createNotificationChannel(); // remove channel methods void removeChannelByID(const LLUUID id); private: + LLScreenChannel* createChannel(LLChannelManager::Params& p); + LLScreenChannel* mStartUpChannel; std::vector<ChannelElem> mChannelList; }; diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 6fb6552f2d..c2d7e0d935 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -44,6 +44,7 @@ #include "llviewercontrol.h" #include "llagentdata.h" +/* static const S32 BORDER_MARGIN = 2; static const S32 PARENT_BORDER_MARGIN = 0; @@ -53,33 +54,27 @@ static const F32 MIN_AUTO_SCROLL_RATE = 120.f; static const F32 MAX_AUTO_SCROLL_RATE = 500.f; static const F32 AUTO_SCROLL_RATE_ACCEL = 120.f; -static const S32 msg_left_offset = 30; -static const S32 msg_right_offset = 10; - #define MAX_CHAT_HISTORY 100 +*/ +static const S32 msg_left_offset = 30; +static const S32 msg_right_offset = 10; -static LLDefaultChildRegistry::Register<LLChatItemsContainerCtrl> t2("chat_items_container"); - - +//static LLDefaultChildRegistry::Register<LLChatItemsContainerCtrl> t2("chat_items_container"); //******************************************************************************************************************* //LLChatItemCtrl //******************************************************************************************************************* -LLChatItemCtrl* LLChatItemCtrl::createInstance() +LLNearbyChatToastPanel* LLNearbyChatToastPanel::createInstance() { - LLChatItemCtrl* item = new LLChatItemCtrl(); + LLNearbyChatToastPanel* item = new LLNearbyChatToastPanel(); LLUICtrlFactory::getInstance()->buildPanel(item, "panel_chat_item.xml"); + item->setFollows(FOLLOWS_NONE); return item; } -void LLChatItemCtrl::draw() -{ - LLPanel::draw(); -} - -void LLChatItemCtrl::reshape (S32 width, S32 height, BOOL called_from_parent ) +void LLNearbyChatToastPanel::reshape (S32 width, S32 height, BOOL called_from_parent ) { LLPanel::reshape(width, height,called_from_parent); @@ -101,13 +96,13 @@ void LLChatItemCtrl::reshape (S32 width, S32 height, BOOL called_from_parent ) } } -BOOL LLChatItemCtrl::postBuild() +BOOL LLNearbyChatToastPanel::postBuild() { return LLPanel::postBuild(); } -std::string LLChatItemCtrl::appendTime() +std::string LLNearbyChatToastPanel::appendTime() { time_t utc_time; utc_time = time_corrected(); @@ -124,48 +119,63 @@ std::string LLChatItemCtrl::appendTime() -void LLChatItemCtrl::addText (const std::string& message) +void LLNearbyChatToastPanel::addText (const std::string& message) { LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text", false); msg_text->addText(message); mMessages.push_back(message); } -void LLChatItemCtrl::setMessage (const LLChat& msg) +void LLNearbyChatToastPanel::init(LLSD& notification) { LLPanel* caption = getChild<LLPanel>("msg_caption", false); + mText = notification["message"].asString(); // UTF-8 line of text + mFromName = notification["from"].asString(); // agent or object name + mFromID = notification["from_id"].asUUID(); // agent id or object id + int sType = notification["source"].asInteger(); + mSourceType = (EChatSourceType)sType; + std::string str_sender; - - if(gAgentID != msg.mFromID) - str_sender = msg.mFromName; + if(gAgentID != mFromID) + str_sender = mFromName; else str_sender = LLTrans::getString("You");; caption->getChild<LLTextBox>("sender_name", false)->setText(str_sender); - std::string tt = appendTime(); - - caption->getChild<LLTextBox>("msg_time", false)->setText(tt); - - - caption->getChild<LLAvatarIconCtrl>("avatar_icon", false)->setValue(msg.mFromID); + caption->getChild<LLTextBox>("msg_time", false)->setText(appendTime()); - mOriginalMessage = msg; LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text", false); - msg_text->setText(msg.mText); + msg_text->setText(mText); LLUICtrl* msg_inspector = caption->getChild<LLUICtrl>("msg_inspector"); - if(mOriginalMessage.mSourceType != CHAT_SOURCE_AGENT) + if(mSourceType != CHAT_SOURCE_AGENT) msg_inspector->setVisible(false); mMessages.clear(); + snapToMessageHeight (); + + mIsDirty = true;//will set Avatar Icon in draw +} + +void LLNearbyChatToastPanel::setMessage (const LLChat& chat_msg) +{ + LLSD notification; + notification["message"] = chat_msg.mText; + notification["from"] = chat_msg.mFromName; + notification["from_id"] = chat_msg.mFromID; + notification["time"] = chat_msg.mTime; + notification["source"] = (S32)chat_msg.mSourceType; + + init(notification); + } -void LLChatItemCtrl::snapToMessageHeight () +void LLNearbyChatToastPanel::snapToMessageHeight () { LLChatMsgBox* text_box = getChild<LLChatMsgBox>("msg_text", false); S32 new_height = text_box->getTextPixelHeight(); @@ -184,14 +194,14 @@ void LLChatItemCtrl::snapToMessageHeight () } -void LLChatItemCtrl::setWidth(S32 width) +void LLNearbyChatToastPanel::setWidth(S32 width) { LLChatMsgBox* text_box = getChild<LLChatMsgBox>("msg_text", false); text_box->reshape(width - msg_left_offset - msg_right_offset,100/*its not magic number, we just need any number*/); LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text", false); - if(mOriginalMessage.mText.length()) - msg_text->setText(mOriginalMessage.mText); + if(mText.length()) + msg_text->setText(mText); for(size_t i=0;i<mMessages.size();++i) msg_text->addText(mMessages[i]); @@ -200,25 +210,25 @@ void LLChatItemCtrl::setWidth(S32 width) snapToMessageHeight (); } -void LLChatItemCtrl::onMouseLeave (S32 x, S32 y, MASK mask) +void LLNearbyChatToastPanel::onMouseLeave (S32 x, S32 y, MASK mask) { LLPanel* caption = getChild<LLPanel>("msg_caption", false); LLUICtrl* msg_inspector = caption->getChild<LLUICtrl>("msg_inspector"); msg_inspector->setVisible(false); } -void LLChatItemCtrl::onMouseEnter (S32 x, S32 y, MASK mask) +void LLNearbyChatToastPanel::onMouseEnter (S32 x, S32 y, MASK mask) { - if(mOriginalMessage.mSourceType != CHAT_SOURCE_AGENT) + if(mSourceType != CHAT_SOURCE_AGENT) return; LLPanel* caption = getChild<LLPanel>("msg_caption", false); LLUICtrl* msg_inspector = caption->getChild<LLUICtrl>("msg_inspector"); msg_inspector->setVisible(true); } -BOOL LLChatItemCtrl::handleMouseDown (S32 x, S32 y, MASK mask) +BOOL LLNearbyChatToastPanel::handleMouseDown (S32 x, S32 y, MASK mask) { - if(mOriginalMessage.mSourceType != CHAT_SOURCE_AGENT) + if(mSourceType != CHAT_SOURCE_AGENT) return LLPanel::handleMouseDown(x,y,mask); LLPanel* caption = getChild<LLPanel>("msg_caption", false); LLUICtrl* msg_inspector = caption->getChild<LLUICtrl>("msg_inspector"); @@ -226,12 +236,16 @@ BOOL LLChatItemCtrl::handleMouseDown (S32 x, S32 y, MASK mask) S32 local_y = y - msg_inspector->getRect().mBottom - caption->getRect().mBottom; if(msg_inspector->pointInView(local_x, local_y)) { - LLFloaterReg::showInstance("inspect_avatar", mOriginalMessage.mFromID); + LLFloaterReg::showInstance("inspect_avatar", mFromID); + } + else + { + LLFloaterReg::showInstance("nearby_chat",LLSD()); } return LLPanel::handleMouseDown(x,y,mask); } -void LLChatItemCtrl::setHeaderVisibility(EShowItemHeader e) +void LLNearbyChatToastPanel::setHeaderVisibility(EShowItemHeader e) { LLPanel* caption = getChild<LLPanel>("msg_caption", false); @@ -243,7 +257,7 @@ void LLChatItemCtrl::setHeaderVisibility(EShowItemHeader e) } -bool LLChatItemCtrl::canAddText () +bool LLNearbyChatToastPanel::canAddText () { LLChatMsgBox* msg_text = findChild<LLChatMsgBox>("msg_text"); if(!msg_text) @@ -251,7 +265,7 @@ bool LLChatItemCtrl::canAddText () return msg_text->getTextLinesNum()<10; } -BOOL LLChatItemCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) +BOOL LLNearbyChatToastPanel::handleRightMouseDown(S32 x, S32 y, MASK mask) { LLPanel* caption = getChild<LLPanel>("msg_caption", false); LLUICtrl* avatar_icon = caption->getChild<LLUICtrl>("avatar_icon", false); @@ -260,296 +274,20 @@ BOOL LLChatItemCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) S32 local_y = y - avatar_icon->getRect().mBottom - caption->getRect().mBottom; //eat message for avatar icon if msg was from object - if(avatar_icon->pointInView(local_x, local_y) && mOriginalMessage.mSourceType != CHAT_SOURCE_AGENT) + if(avatar_icon->pointInView(local_x, local_y) && mSourceType != CHAT_SOURCE_AGENT) return TRUE; return LLPanel::handleRightMouseDown(x,y,mask); } - - -//******************************************************************************************************************* -//LLChatItemsContainerCtrl -//******************************************************************************************************************* - -LLChatItemsContainerCtrl::LLChatItemsContainerCtrl(const Params& params):LLPanel(params) -{ - mEShowItemHeader = CHATITEMHEADER_SHOW_BOTH; -} - - -void LLChatItemsContainerCtrl::addMessage(const LLChat& msg) -{ - /* - if(msg.mChatType == CHAT_TYPE_DEBUG_MSG) - return; - */ - if(mItems.size() >= MAX_CHAT_HISTORY) - { - LLChatItemCtrl* item = mItems[0]; - removeChild(item); - delete item; - mItems.erase(mItems.begin()); - } - - - if(mItems.size() > 0 - && msg.mFromID == mItems[mItems.size()-1]->getMessage().mFromID - && (msg.mTime-mItems[mItems.size()-1]->getMessage().mTime)<60 - && mItems[mItems.size()-1]->canAddText() - ) - { - mItems[mItems.size()-1]->addText(msg.mText); - mItems[mItems.size()-1]->snapToMessageHeight(); - } - else - { - LLChatItemCtrl* item = LLChatItemCtrl::createInstance(); - mItems.push_back(item); - addChild(item,0); - item->setWidth(getRect().getWidth() - 16); - item->setMessage(msg); - item->snapToMessageHeight(); - - item->setHeaderVisibility((EShowItemHeader)gSavedSettings.getS32("nearbychat_showicons_and_names")); - - item->setVisible(true); - } - - arrange(getRect().getWidth(),getRect().getHeight()); - updateLayout(getRect().getWidth(),getRect().getHeight()); - scrollToBottom(); -} - -void LLChatItemsContainerCtrl::scrollToBottom () -{ - if(mScrollbar->getVisible()) - { - mScrollbar->setDocPos(mScrollbar->getDocPosMax()); - onScrollPosChangeCallback(0,0); - } -} - -void LLChatItemsContainerCtrl::draw() -{ - LLLocalClipRect clip(getRect()); - LLPanel::draw(); -} - -void LLChatItemsContainerCtrl::reshape (S32 width, S32 height, BOOL called_from_parent ) -{ - S32 delta_width = width - getRect().getWidth(); - S32 delta_height = height - getRect().getHeight(); - - if (delta_width || delta_height || sForceReshape) - { - arrange(width, height); - } - - updateBoundingRect(); -} - -void LLChatItemsContainerCtrl::arrange (S32 width, S32 height) +void LLNearbyChatToastPanel::draw() { - S32 delta_width = width - getRect().getWidth(); - if(delta_width)//width changed...too bad. now we need to reformat all items - reformatHistoryScrollItems(width); - - calcRecuiredHeight(); - - show_hide_scrollbar(width,height); - - updateLayout(width,height); -} - -void LLChatItemsContainerCtrl::reformatHistoryScrollItems(S32 width) -{ - for(std::vector<LLChatItemCtrl*>::iterator it = mItems.begin(); it != mItems.end();++it) - { - (*it)->setWidth(width); - } -} - -S32 LLChatItemsContainerCtrl::calcRecuiredHeight () -{ - S32 rec_height = 0; - - std::vector<LLChatItemCtrl*>::iterator it; - for(it=mItems.begin(); it!=mItems.end(); ++it) - { - rec_height += (*it)->getRect().getHeight(); - } - - mInnerRect.setLeftTopAndSize(0,rec_height + BORDER_MARGIN*2,getRect().getWidth(),rec_height + BORDER_MARGIN); - - return mInnerRect.getHeight(); -} - - -void LLChatItemsContainerCtrl::updateLayout (S32 width, S32 height) -{ - S32 panel_top = height - BORDER_MARGIN ; - S32 panel_width = width; - if(mScrollbar->getVisible()) - { - static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); - - panel_top+=mScrollbar->getDocPos(); - panel_width-=scrollbar_size; - } - - - //set sizes for first panels and dragbars - for(size_t i=0;i<mItems.size();++i) - { - LLRect panel_rect = mItems[i]->getRect(); - panelSetLeftTopAndSize(mItems[i],panel_rect.mLeft,panel_top,panel_width,panel_rect.getHeight()); - panel_top-=panel_rect.getHeight(); - } -} - -void LLChatItemsContainerCtrl::show_hide_scrollbar (S32 width, S32 height) -{ - calcRecuiredHeight(); - if(getRecuiredHeight() > height ) - showScrollbar(width, height); - else - hideScrollbar(width, height); -} - -void LLChatItemsContainerCtrl::showScrollbar (S32 width, S32 height) -{ - bool was_visible = mScrollbar->getVisible(); - - mScrollbar->setVisible(true); - - static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); - - panelSetLeftTopAndSize(mScrollbar,width-scrollbar_size - ,height-PARENT_BORDER_MARGIN,scrollbar_size,height-2*PARENT_BORDER_MARGIN); - - mScrollbar->setPageSize(height); - mScrollbar->setDocParams(mInnerRect.getHeight(),mScrollbar->getDocPos()); - - if(was_visible) - { - S32 scroll_pos = llmin(mScrollbar->getDocPos(), getRecuiredHeight() - height - 1); - mScrollbar->setDocPos(scroll_pos); - updateLayout(width,height); - return; - } -} - -void LLChatItemsContainerCtrl::hideScrollbar (S32 width, S32 height) -{ - if(mScrollbar->getVisible() == false) - return; - mScrollbar->setVisible(false); - - mScrollbar->setDocPos(0); - - if(mItems.size()>0) - { - S32 panel_top = height - BORDER_MARGIN; // Top coordinate of the first panel - S32 diff = panel_top - mItems[0]->getRect().mTop; - shiftPanels(diff); - } -} - -//--------------------------------------------------------------------------------- -void LLChatItemsContainerCtrl::panelSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height) -{ - if(!panel) - return; - LLRect panel_rect = panel->getRect(); - panel_rect.setLeftTopAndSize( left, top, width, height); - panel->reshape( width, height, 1); - panel->setRect(panel_rect); -} - -void LLChatItemsContainerCtrl::panelShiftVertical(LLView* panel,S32 delta) -{ - if(!panel) - return; - panel->translate(0,delta); -} - -void LLChatItemsContainerCtrl::shiftPanels(S32 delta) -{ - //Arrange panels - for(std::vector<LLChatItemCtrl*>::iterator it = mItems.begin(); it != mItems.end();++it) - { - panelShiftVertical((*it),delta); - } - -} - -//--------------------------------------------------------------------------------- - -void LLChatItemsContainerCtrl::onScrollPosChangeCallback(S32, LLScrollbar*) -{ - updateLayout(getRect().getWidth(),getRect().getHeight()); -} - -BOOL LLChatItemsContainerCtrl::postBuild() -{ - static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); - - LLRect scroll_rect; - scroll_rect.setOriginAndSize( - getRect().getWidth() - scrollbar_size, - 1, - scrollbar_size, - getRect().getHeight() - 1); - - - LLScrollbar::Params sbparams; - sbparams.name("scrollable vertical"); - sbparams.rect(scroll_rect); - sbparams.orientation(LLScrollbar::VERTICAL); - sbparams.doc_size(mInnerRect.getHeight()); - sbparams.doc_pos(0); - sbparams.page_size(mInnerRect.getHeight()); - sbparams.step_size(VERTICAL_MULTIPLE); - sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); - sbparams.change_callback(boost::bind(&LLChatItemsContainerCtrl::onScrollPosChangeCallback, this, _1, _2)); - - mScrollbar = LLUICtrlFactory::create<LLScrollbar> (sbparams); - LLView::addChild( mScrollbar ); - mScrollbar->setVisible( true ); - mScrollbar->setFollowsRight(); - mScrollbar->setFollowsTop(); - mScrollbar->setFollowsBottom(); - - reformatHistoryScrollItems(getRect().getWidth()); - arrange(getRect().getWidth(),getRect().getHeight()); - - return LLPanel::postBuild(); -} -BOOL LLChatItemsContainerCtrl::handleMouseDown (S32 x, S32 y, MASK mask) -{ - return LLPanel::handleMouseDown(x,y,mask); -} -BOOL LLChatItemsContainerCtrl::handleKeyHere (KEY key, MASK mask) -{ - if( mScrollbar->getVisible() && mScrollbar->handleKeyHere( key,mask ) ) - return TRUE; - return LLPanel::handleKeyHere(key,mask); -} -BOOL LLChatItemsContainerCtrl::handleScrollWheel ( S32 x, S32 y, S32 clicks ) -{ - if( mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) ) - return TRUE; - return false; -} - -void LLChatItemsContainerCtrl::setHeaderVisibility(EShowItemHeader e) -{ - if(e == mEShowItemHeader) - return; - mEShowItemHeader = e; - for(std::vector<LLChatItemCtrl*>::iterator it = mItems.begin(); it != mItems.end();++it) + if(mIsDirty) { - (*it)->setHeaderVisibility(e); + LLPanel* caption = findChild<LLPanel>("msg_caption", false); + if(caption) + caption->getChild<LLAvatarIconCtrl>("avatar_icon", false)->setValue(mFromID); + mIsDirty = false; } + LLToastPanelBase::draw(); } diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h index de16cf9505..8fb045b6d9 100644 --- a/indra/newview/llchatitemscontainerctrl.h +++ b/indra/newview/llchatitemscontainerctrl.h @@ -37,6 +37,7 @@ #include "llscrollbar.h" #include "string" #include "llchat.h" +#include "lltoastpanel.h" typedef enum e_show_item_header { @@ -45,20 +46,18 @@ typedef enum e_show_item_header CHATITEMHEADER_SHOW_BOTH } EShowItemHeader; -class LLChatItemCtrl: public LLPanel +class LLNearbyChatToastPanel: public LLToastPanelBase { protected: - LLChatItemCtrl(){}; + LLNearbyChatToastPanel():mIsDirty(false){}; public: - ~LLChatItemCtrl(){} + ~LLNearbyChatToastPanel(){} - static LLChatItemCtrl* createInstance(); + static LLNearbyChatToastPanel* createInstance(); - void draw(); - - const LLChat& getMessage() const { return mOriginalMessage;} + const LLUUID& getFromID() const { return mFromID;} void addText (const std::string& message); void setMessage (const LLChat& msg); @@ -77,78 +76,27 @@ public: void setHeaderVisibility(EShowItemHeader e); BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); -private: - - std::string appendTime (); - -private: - LLChat mOriginalMessage; - - std::vector<std::string> mMessages; -}; - -class LLChatItemsContainerCtrl: public LLPanel -{ -public: - struct Params - : public LLInitParam::Block<Params, LLPanel::Params> - { - Params(){}; - }; - - LLChatItemsContainerCtrl(const Params& params); - - - ~LLChatItemsContainerCtrl(){} - - void addMessage (const LLChat& msg); - - void draw(); - - void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE); - - void onScrollPosChangeCallback(S32, LLScrollbar*); - - virtual BOOL postBuild(); - - BOOL handleMouseDown (S32 x, S32 y, MASK mask); - BOOL handleKeyHere (KEY key, MASK mask); - BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); - - void scrollToBottom (); - - void setHeaderVisibility(EShowItemHeader e); - EShowItemHeader getHeaderVisibility() const { return mEShowItemHeader;}; + virtual void init(LLSD& data); + virtual void draw(); private: - void reformatHistoryScrollItems(S32 width); - void arrange (S32 width, S32 height); - - S32 calcRecuiredHeight (); - S32 getRecuiredHeight () const { return mInnerRect.getHeight(); } - - void updateLayout (S32 width, S32 height); - - void show_hide_scrollbar (S32 width, S32 height); - - void showScrollbar (S32 width, S32 height); - void hideScrollbar (S32 width, S32 height); - - void panelSetLeftTopAndSize (LLView* panel, S32 left, S32 top, S32 width, S32 height); - void panelShiftVertical (LLView* panel,S32 delta); - void shiftPanels (S32 delta); + + std::string appendTime (); private: - std::vector<LLChatItemCtrl*> mItems; + std::string mText; // UTF-8 line of text + std::string mFromName; // agent or object name + LLUUID mFromID; // agent id or object id + EChatSourceType mSourceType; - EShowItemHeader mEShowItemHeader; - LLRect mInnerRect; - LLScrollbar* mScrollbar; + std::vector<std::string> mMessages; + bool mIsDirty; }; + #endif diff --git a/indra/newview/llchatmsgbox.cpp b/indra/newview/llchatmsgbox.cpp index e6398dd47a..bd0c36b44a 100644 --- a/indra/newview/llchatmsgbox.cpp +++ b/indra/newview/llchatmsgbox.cpp @@ -102,7 +102,7 @@ void LLChatMsgBox::drawText(S32 x, S32 y, const LLWString &text, const LLColor4 // iterate through each block of text that has been added y -= mLineSpacing; - for (std::vector<S32>::iterator it = mSeparatorOffset.begin(); true ;) + for (std::vector<S32>::iterator it = mSeparatorOffset.begin(); it != mSeparatorOffset.end() ;) { // display the text for this block S32 num_chars = *it - start; diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 20c44d5b11..98e492cada 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -49,6 +49,7 @@ #include "llvoicecontrolpanel.h" #include "llgroupmgr.h" #include "llnotificationmanager.h" +#include "lltransientfloatermgr.h" static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel"); static LLDefaultChildRegistry::Register<LLTalkButton> t2("chiclet_talk"); @@ -243,26 +244,36 @@ void LLIMChiclet::draw() LLIMChiclet::EType LLIMChiclet::getIMSessionType(const LLUUID& session_id) { EType type = TYPE_UNKNOWN; - LLFloaterIMPanel* im = NULL; if(session_id.isNull()) return type; - if (!(im = LLIMMgr::getInstance()->findFloaterBySession(session_id))) + EInstantMessage im_type = LLIMModel::getInstance()->getType(session_id); + if (IM_COUNT == im_type) { llassert_always(0 && "IM session not found"); // should never happen return type; } - switch(im->getDialogType()) + switch(im_type) { case IM_NOTHING_SPECIAL: + case IM_SESSION_P2P_INVITE: type = TYPE_IM; break; case IM_SESSION_GROUP_START: case IM_SESSION_INVITE: - type = TYPE_GROUP; + if (gAgent.isInGroup(session_id)) + { + type = TYPE_GROUP; + } + else + { + type = TYPE_AD_HOC; + } break; + case IM_SESSION_CONFERENCE_START: + type = TYPE_AD_HOC; default: break; } @@ -285,6 +296,11 @@ LLIMP2PChiclet::Params::Params() avatar_icon.name("avatar_icon"); avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM); + + // *NOTE dzaporozhan + // Changed icon height from 25 to 24 to fix ticket EXT-794. + // In some cases(after changing UI scale) 25 pixel height icon was + // drawn incorrectly, i'm not sure why. avatar_icon.rect(LLRect(0, 24, 25, 0)); avatar_icon.mouse_opaque(false); @@ -458,6 +474,11 @@ LLIMGroupChiclet::Params::Params() rect(LLRect(0, 25, 45, 0)); group_icon.name("group_icon"); + + // *NOTE dzaporozhan + // Changed icon height from 25 to 24 to fix ticket EXT-794. + // In some cases(after changing UI scale) 25 pixel height icon was + // drawn incorrectly, i'm not sure why. group_icon.rect(LLRect(0, 24, 25, 0)); unread_notifications.name("unread"); @@ -1164,6 +1185,7 @@ LLTalkButton::LLTalkButton(const Params& p) speak_params.rect(speak_rect); mSpeakBtn = LLUICtrlFactory::create<LLButton>(speak_params); addChild(mSpeakBtn); + LLTransientFloaterMgr::getInstance()->addControlView(mSpeakBtn); mSpeakBtn->setClickedCallback(boost::bind(&LLTalkButton::onClick_SpeakBtn, this)); mSpeakBtn->setToggleState(FALSE); @@ -1172,6 +1194,7 @@ LLTalkButton::LLTalkButton(const Params& p) show_params.rect(show_rect); mShowBtn = LLUICtrlFactory::create<LLButton>(show_params); addChild(mShowBtn); + LLTransientFloaterMgr::getInstance()->addControlView(mShowBtn); mShowBtn->setClickedCallback(boost::bind(&LLTalkButton::onClick_ShowBtn, this)); mShowBtn->setToggleState(FALSE); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 316348cf1d..ef47b54333 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -275,7 +275,8 @@ public: enum EType { TYPE_UNKNOWN, TYPE_IM, - TYPE_GROUP + TYPE_GROUP, + TYPE_AD_HOC }; /*virtual*/ ~LLIMChiclet() {}; diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 6b18984f88..ea947a5565 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -934,6 +934,17 @@ void LLFavoritesBarCtrl::onButtonRightClick( LLUUID item_id,LLView* fav_button,S LLMenuGL::showPopup(fav_button, menu, x, y); } +BOOL LLFavoritesBarCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + BOOL handled = childrenHandleRightMouseDown( x, y, mask) != NULL; + if(!handled && !gMenuHolder->hasVisibleMenu()) + { + show_navbar_context_menu(this,x,y); + handled = true; + } + + return handled; +} void copy_slurl_to_clipboard_cb(std::string& slurl) { gClipboard.copyFromString(utf8str_to_wstring(slurl)); diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 0be8de29a9..97117c3b4a 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -62,7 +62,7 @@ public: std::string& tooltip_msg); /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); - + /*virtual*/ BOOL handleRightMouseDown(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); diff --git a/indra/newview/llfloaterchatterbox.cpp b/indra/newview/llfloaterchatterbox.cpp index 05ea800d0e..dea656b0e4 100644 --- a/indra/newview/llfloaterchatterbox.cpp +++ b/indra/newview/llfloaterchatterbox.cpp @@ -363,7 +363,8 @@ LLFloater* LLFloaterChatterBox::getCurrentVoiceFloater() { // only LLFloaterIMPanels are called "im_floater" LLFloaterIMPanel* im_floaterp = (LLFloaterIMPanel*)panelp; - if (im_floaterp->getVoiceChannel() == LLVoiceChannel::getCurrentVoiceChannel()) + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(im_floaterp->getSessionID()); + if (voice_channel == LLVoiceChannel::getCurrentVoiceChannel()) { return im_floaterp; } diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index d3b013237b..905857f393 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -73,7 +73,11 @@ LLGroupList::Params::Params() LLGroupList::LLGroupList(const Params& p) : LLFlatListView(p) + , mDirty(true) // to force initial update { + // Listen for agent group changes. + gAgent.addListener(this, "new group"); + mShowIcons = gSavedSettings.getBOOL("GroupListShowIcons"); setCommitOnSelectionChange(true); // TODO: implement context menu @@ -84,17 +88,41 @@ LLGroupList::LLGroupList(const Params& p) setComparator(&GROUP_COMPARATOR); } +LLGroupList::~LLGroupList() +{ + gAgent.removeListener(this); +} + +// virtual +void LLGroupList::draw() +{ + if (mDirty) + refresh(); + + LLFlatListView::draw(); +} + +void LLGroupList::setNameFilter(const std::string& filter) +{ + if (mNameFilter != filter) + { + mNameFilter = filter; + setDirty(); + } +} + static bool findInsensitive(std::string haystack, const std::string& needle_upper) { LLStringUtil::toUpper(haystack); return haystack.find(needle_upper) != std::string::npos; } -BOOL LLGroupList::update(const std::string& name_filter) +void LLGroupList::refresh() { const LLUUID& highlight_id = gAgent.getGroupID(); S32 count = gAgent.mGroups.count(); LLUUID id; + bool have_filter = !mNameFilter.empty(); clear(); @@ -102,7 +130,7 @@ BOOL LLGroupList::update(const std::string& name_filter) { id = gAgent.mGroups.get(i).mID; const LLGroupData& group_data = gAgent.mGroups.get(i); - if (name_filter != LLStringUtil::null && !findInsensitive(group_data.mName, name_filter)) + if (have_filter && !findInsensitive(group_data.mName, mNameFilter)) continue; addNewItem(id, group_data.mName, group_data.mInsigniaID, highlight_id == id, ADD_BOTTOM); } @@ -113,13 +141,14 @@ BOOL LLGroupList::update(const std::string& name_filter) // add "none" to list at top { std::string loc_none = LLTrans::getString("GroupsNone"); - if (name_filter == LLStringUtil::null || findInsensitive(loc_none, name_filter)) + if (have_filter || findInsensitive(loc_none, mNameFilter)) addNewItem(LLUUID::null, loc_none, LLUUID::null, highlight_id.isNull(), ADD_TOP); } selectItemByUUID(highlight_id); - return TRUE; + setDirty(false); + onCommit(); } void LLGroupList::toggleIcons() @@ -158,6 +187,18 @@ void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LL // setCommentVisible(false); } +// virtual +bool LLGroupList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) +{ + // Why is "new group" sufficient? + if (event->desc() == "new group") + { + setDirty(); + return true; + } + + return false; +} /************************************************************************/ /* LLGroupListItem implementation */ diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index 7708b58de6..9c3ab88901 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -33,10 +33,19 @@ #ifndef LL_LLGROUPLIST_H #define LL_LLGROUPLIST_H +#include "llevent.h" #include "llflatlistview.h" #include "llpanel.h" +#include "llpointer.h" -class LLGroupList: public LLFlatListView +/** + * Auto-updating list of agent groups. + * + * Can use optional group name filter. + * + * @see setNameFilter() + */ +class LLGroupList: public LLFlatListView, public LLOldEvents::LLSimpleListener { LOG_CLASS(LLGroupList); public: @@ -46,14 +55,23 @@ public: }; LLGroupList(const Params& p); - BOOL update(const std::string& name_filter = LLStringUtil::null); + virtual ~LLGroupList(); + + virtual void draw(); // from LLView + + void setNameFilter(const std::string& filter); void toggleIcons(); bool getIconsVisible() const { return mShowIcons; } - + private: + void setDirty(bool val = true) { mDirty = val; } + void refresh(); void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, BOOL is_bold, EAddPosition pos = ADD_BOTTOM); + bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); // called on agent group list changes bool mShowIcons; + bool mDirty; + std::string mNameFilter; }; class LLButton; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 254e16e1fb..1c144b11b0 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -48,6 +48,7 @@ #include "lltrans.h" #include "llviewertexteditor.h" #include "llviewerwindow.h" +#include "lltransientfloatermgr.h" @@ -62,33 +63,46 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mInputEditor(NULL), mPositioned(false) { - LLIMModel::LLIMSession* session = get_if_there(LLIMModel::instance().sSessionsMap, mSessionID, (LLIMModel::LLIMSession*)NULL); - if(session) + EInstantMessage type = LLIMModel::getInstance()->getType(session_id); + if(IM_COUNT != type) { - mDialog = session->mType; - } + mDialog = type; - if (mDialog == IM_NOTHING_SPECIAL) - { - mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this); - } - else - { - mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); + if (IM_NOTHING_SPECIAL == mDialog || IM_SESSION_P2P_INVITE == mDialog) + { + mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this); + } + else + { + mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); + } } -// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_im_session.xml"); LLUI::getRootView()->setFocusLostCallback(boost::bind(&LLIMFloater::focusChangeCallback, this)); mCloseSignal.connect(boost::bind(&LLIMFloater::onClose, this)); + + LLTransientFloaterMgr::getInstance()->registerTransientFloater(this); } void LLIMFloater::onClose() { LLIMModel::instance().sendLeaveSession(mSessionID, mOtherParticipantUUID); + + //*TODO - move to the IMModel::sendLeaveSession() for the integrity (IB) gIMMgr->removeSession(mSessionID); } +void LLIMFloater::setMinimized(BOOL minimize) +{ + if(!isDocked()) + { + setVisible(!minimize); + } + + LLFloater::setMinimized(minimize); +} + /* static */ void LLIMFloater::newIMCallback(const LLSD& data){ @@ -152,16 +166,17 @@ void LLIMFloater::sendMsg() LLIMFloater::~LLIMFloater() { + LLTransientFloaterMgr::getInstance()->unregisterTransientFloater(this); } //virtual BOOL LLIMFloater::postBuild() { - LLIMModel::LLIMSession* session = get_if_there(LLIMModel::instance().sSessionsMap, mSessionID, (LLIMModel::LLIMSession*)NULL); - if(session) + const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID); + if (other_party_id.notNull()) { - mOtherParticipantUUID = session->mOtherParticipantID; - mControlPanel->setID(session->mOtherParticipantID); + mOtherParticipantUUID = other_party_id; + mControlPanel->setID(mOtherParticipantUUID); } LLButton* slide_left = getChild<LLButton>("slide_left_btn"); @@ -216,17 +231,6 @@ void* LLIMFloater::createPanelGroupControl(void* userdata) return self->mControlPanel; } - - -void LLIMFloater::focusChangeCallback() -{ - // hide docked floater if user clicked inside in-world area - if (isDocked()) - { - setVisible(false); - } -} - void LLIMFloater::onSlide() { LLPanel* im_control_panel = getChild<LLPanel>("panel_im_control_panel"); @@ -271,13 +275,13 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) } floater->setDockControl(new LLDockControl(chiclet, floater, floater->getDockTongue(), - LLDockControl::TOP, boost::bind(&LLIMFloater::getEnabledRect, floater, _1))); + LLDockControl::TOP, boost::bind(&LLIMFloater::getAllowedRect, floater, _1))); } return floater; } -void LLIMFloater::getEnabledRect(LLRect& rect) +void LLIMFloater::getAllowedRect(LLRect& rect) { rect = gViewerWindow->getWorldViewRect(); } @@ -285,8 +289,10 @@ void LLIMFloater::getEnabledRect(LLRect& rect) void LLIMFloater::setDocked(bool docked, bool pop_on_undock) { // update notification channel state - LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))); + LLNotificationsUI::LLScreenChannel* channel = dynamic_cast<LLNotificationsUI::LLScreenChannel*> + (LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + LLDockableFloater::setDocked(docked, pop_on_undock); // update notification channel state @@ -298,8 +304,9 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock) void LLIMFloater::setVisible(BOOL visible) { - LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))); + LLNotificationsUI::LLScreenChannel* channel = dynamic_cast<LLNotificationsUI::LLScreenChannel*> + (LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); LLDockableFloater::setVisible(visible); // update notification channel state diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 276f38e829..a183212f04 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -57,6 +57,8 @@ public: // LLFloater overrides /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); + // override LLFloater's minimization according to EXT-1216 + /*virtual*/ void setMinimized(BOOL minimize); // Make IM conversion visible and update the message history static LLIMFloater* show(const LLUUID& session_id); @@ -90,8 +92,8 @@ private: void onSlide(); static void* createPanelIMControl(void* userdata); static void* createPanelGroupControl(void* userdata); - void focusChangeCallback(); - void getEnabledRect(LLRect& rect); + // gets a rect that bounds possible positions for the LLIMFloater on a screen (EXT-1111) + void getAllowedRect(LLRect& rect); LLPanelChatControlPanel* mControlPanel; LLUUID mSessionID; diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index 46067c081f..74971f3fd8 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -109,7 +109,9 @@ bool LLIMHandler::processNotification(const LLSD& notify) p.panel = im_box; p.can_be_stored = false; p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1); - mChannel->addToast(p); + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) + channel->addToast(p); // send a signal to the counter manager; mNewNotificationSignal(); diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index aa2beabf3d..abd3cd4def 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -940,7 +940,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, mHistoryEditor(NULL), mSessionUUID(session_id), mSessionLabel(session_label), - mVoiceChannel(NULL), mSessionInitialized(FALSE), mSessionStartMsgPos(0), mOtherParticipantUUID(other_participant_id), @@ -956,7 +955,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, mTextIMPossible(TRUE), mProfileButtonEnabled(TRUE), mCallBackEnabled(TRUE), - mSpeakers(NULL), mSpeakerPanel(NULL), mFirstKeystrokeTimer(), mLastKeystrokeTimer() @@ -967,7 +965,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, case IM_SESSION_GROUP_START: mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this); xml_filename = "floater_instant_message_group.xml"; - mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel); break; case IM_SESSION_INVITE: mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this); @@ -979,16 +976,13 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, { xml_filename = "floater_instant_message_ad_hoc.xml"; } - mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel); break; case IM_SESSION_P2P_INVITE: xml_filename = "floater_instant_message.xml"; - mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, mSessionLabel, mOtherParticipantUUID); break; case IM_SESSION_CONFERENCE_START: mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this); xml_filename = "floater_instant_message_ad_hoc.xml"; - mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel); break; // just received text from another user case IM_NOTHING_SPECIAL: @@ -998,8 +992,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, mTextIMPossible = LLVoiceClient::getInstance()->isSessionTextIMPossible(mSessionUUID); mProfileButtonEnabled = LLVoiceClient::getInstance()->isParticipantAvatar(mSessionUUID); mCallBackEnabled = LLVoiceClient::getInstance()->isSessionCallBackPossible(mSessionUUID); - - mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, mSessionLabel, mOtherParticipantUUID); break; default: llwarns << "Unknown session type" << llendl; @@ -1007,10 +999,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, break; } - mSpeakers = new LLIMSpeakerMgr(mVoiceChannel); - // All participants will be added to the list of people we've recently interacted with. - mSpeakers->addListener(&LLRecentPeople::instance(), "add"); - LLUICtrlFactory::getInstance()->buildFloater(this, xml_filename, NULL); setTitle(mSessionLabel); @@ -1058,33 +1046,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, LLFloaterIMPanel::~LLFloaterIMPanel() { - delete mSpeakers; - mSpeakers = NULL; - - // End the text IM session if necessary - if(gVoiceClient && mOtherParticipantUUID.notNull()) - { - switch(mDialog) - { - case IM_NOTHING_SPECIAL: - case IM_SESSION_P2P_INVITE: - gVoiceClient->endUserIMSession(mOtherParticipantUUID); - break; - - default: - // Appease the compiler - break; - } - } - - //kicks you out of the voice channel if it is currently active - - // HAVE to do this here -- if it happens in the LLVoiceChannel destructor it will call the wrong version (since the object's partially deconstructed at that point). - mVoiceChannel->deactivate(); - - delete mVoiceChannel; - mVoiceChannel = NULL; - //delete focus lost callback mFocusCallbackConnection.disconnect(); } @@ -1152,7 +1113,8 @@ BOOL LLFloaterIMPanel::postBuild() void* LLFloaterIMPanel::createSpeakersPanel(void* data) { LLFloaterIMPanel* floaterp = (LLFloaterIMPanel*)data; - floaterp->mSpeakerPanel = new LLPanelActiveSpeakers(floaterp->mSpeakers, TRUE); + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(floaterp->mSessionUUID); + floaterp->mSpeakerPanel = new LLPanelActiveSpeakers(speaker_mgr, TRUE); return floaterp->mSpeakerPanel; } @@ -1198,12 +1160,14 @@ void LLFloaterIMPanel::draw() && mCallBackEnabled; // hide/show start call and end call buttons - childSetVisible("end_call_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() >= LLVoiceChannel::STATE_CALL_STARTED); - childSetVisible("start_call_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() < LLVoiceChannel::STATE_CALL_STARTED); + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionUUID); + childSetVisible("end_call_btn", LLVoiceClient::voiceEnabled() && voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED); + childSetVisible("start_call_btn", LLVoiceClient::voiceEnabled() && voice_channel->getState() < LLVoiceChannel::STATE_CALL_STARTED); childSetEnabled("start_call_btn", enable_connect); childSetEnabled("send_btn", !childGetValue("chat_editor").asString().empty()); - LLPointer<LLSpeaker> self_speaker = mSpeakers->findSpeaker(gAgent.getID()); + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionUUID); + LLPointer<LLSpeaker> self_speaker = speaker_mgr->findSpeaker(gAgent.getID()); if(!mTextIMPossible) { mInputEditor->setEnabled(FALSE); @@ -1227,7 +1191,7 @@ void LLFloaterIMPanel::draw() } // show speakers window when voice first connects - if (mShowSpeakersOnConnect && mVoiceChannel->isActive()) + if (mShowSpeakersOnConnect && voice_channel->isActive()) { childSetVisible("active_speakers_panel", TRUE); mShowSpeakersOnConnect = FALSE; @@ -1263,11 +1227,11 @@ void LLFloaterIMPanel::draw() else { // refresh volume and mute checkbox - childSetVisible("speaker_volume", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive()); + childSetVisible("speaker_volume", LLVoiceClient::voiceEnabled() && voice_channel->isActive()); childSetValue("speaker_volume", gVoiceClient->getUserVolume(mOtherParticipantUUID)); childSetValue("mute_btn", LLMuteList::getInstance()->isMuted(mOtherParticipantUUID, LLMute::flagVoiceChat)); - childSetVisible("mute_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive()); + childSetVisible("mute_btn", LLVoiceClient::voiceEnabled() && voice_channel->isActive()); } LLFloater::draw(); } @@ -1403,12 +1367,6 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4 { mNumUnreadMessages++; } - - if (source != LLUUID::null) - { - mSpeakers->speakerChatted(source); - mSpeakers->setSpeakerTyping(source, FALSE); - } } @@ -1589,7 +1547,7 @@ void LLFloaterIMPanel::onClickStartCall(void* userdata) { LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; - self->mVoiceChannel->activate(); + LLIMModel::getInstance()->getVoiceChannel(self->mSessionUUID)->activate(); } // static @@ -1597,7 +1555,7 @@ void LLFloaterIMPanel::onClickEndCall(void* userdata) { LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; - self->getVoiceChannel()->deactivate(); + LLIMModel::getInstance()->getVoiceChannel(self->mSessionUUID)->deactivate(); } // static @@ -1671,7 +1629,8 @@ void LLFloaterIMPanel::onVisibilityChange(const LLSD& new_visibility) mNumUnreadMessages = 0; } - if (new_visibility.asBoolean() && mVoiceChannel->getState() == LLVoiceChannel::STATE_CONNECTED) + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionUUID); + if (new_visibility.asBoolean() && voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED) LLFloaterReg::showInstance("voice_call", mSessionUUID); else LLFloaterReg::hideInstance("voice_call", mSessionUUID); @@ -1723,11 +1682,6 @@ void LLFloaterIMPanel::sendMsg() mSentTypingState = TRUE; } -void LLFloaterIMPanel::updateSpeakersList(const LLSD& speaker_updates) -{ - mSpeakers->updateSpeakers(speaker_updates); -} - void LLFloaterIMPanel::processSessionUpdate(const LLSD& session_update) { if ( @@ -1751,15 +1705,9 @@ void LLFloaterIMPanel::processSessionUpdate(const LLSD& session_update) } } -void LLFloaterIMPanel::setSpeakers(const LLSD& speaker_list) -{ - mSpeakers->setSpeakers(speaker_list); -} - void LLFloaterIMPanel::sessionInitReplyReceived(const LLUUID& session_id) { mSessionUUID = session_id; - mVoiceChannel->updateSessionID(session_id); mSessionInitialized = TRUE; //we assume the history editor hasn't moved at all since @@ -1790,6 +1738,7 @@ void LLFloaterIMPanel::requestAutoConnect() void LLFloaterIMPanel::setTyping(BOOL typing) { + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionUUID); if (typing) { // Every time you type something, reset this timer @@ -1804,7 +1753,7 @@ void LLFloaterIMPanel::setTyping(BOOL typing) mSentTypingState = FALSE; } - mSpeakers->setSpeakerTyping(gAgent.getID(), TRUE); + speaker_mgr->setSpeakerTyping(gAgent.getID(), TRUE); } else { @@ -1814,7 +1763,7 @@ void LLFloaterIMPanel::setTyping(BOOL typing) sendTypingState(FALSE); mSentTypingState = TRUE; } - mSpeakers->setSpeakerTyping(gAgent.getID(), FALSE); + speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE); } mTyping = typing; @@ -1874,7 +1823,7 @@ void LLFloaterIMPanel::removeTypingIndicator(const LLIMInfo* im_info) mHistoryEditor->removeTextFromEnd(chars_to_remove); if (im_info) { - mSpeakers->setSpeakerTyping(im_info->mFromID, FALSE); + LLIMModel::getInstance()->getSpeakerManager(mSessionUUID)->setSpeakerTyping(im_info->mFromID, FALSE); } } } diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index fd1134ee5e..fb9b28ad16 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -33,6 +33,7 @@ #ifndef LL_IMPANEL_H #define LL_IMPANEL_H +#include "llimview.h" //for LLIMModel #include "lldockablefloater.h" #include "lllogchat.h" #include "lluuid.h" @@ -245,11 +246,7 @@ public: const LLUUID& getSessionID() const { return mSessionUUID; } const LLUUID& getOtherParticipantID() const { return mOtherParticipantUUID; } - LLIMSpeakerMgr* getSpeakerManager() const { return mSpeakers; } - void updateSpeakersList(const LLSD& speaker_updates); void processSessionUpdate(const LLSD& update); - void setSpeakers(const LLSD& speaker_list); - LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; } EInstantMessage getDialogType() const { return mDialog; } void setDialogType(EInstantMessage dialog) { mDialog = dialog; } @@ -305,7 +302,6 @@ private: LLUUID mSessionUUID; std::string mSessionLabel; - LLVoiceChannel* mVoiceChannel; BOOL mSessionInitialized; LLSD mQueuedMsgsForInit; @@ -346,7 +342,6 @@ private: BOOL mProfileButtonEnabled; BOOL mCallBackEnabled; - LLIMSpeakerMgr* mSpeakers; LLPanelActiveSpeakers* mSpeakerPanel; // Optimization: Don't send "User is typing..." until the diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 3cf78f957b..556eb5ffd7 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -114,10 +114,84 @@ void toast_callback(const LLSD& msg){ LLIMModel::LLIMModel() { - addChangedCallback(toast_callback); addChangedCallback(LLIMFloater::newIMCallback); + addChangedCallback(toast_callback); +} + + +LLIMModel::LLIMSession::LLIMSession( const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id ) +: mSessionID(session_id), + mName(name), + mType(type), + mNumUnread(0), + mOtherParticipantID(other_participant_id), + mVoiceChannel(NULL), + mSpeakers(NULL) +{ + if (IM_NOTHING_SPECIAL == type || IM_SESSION_P2P_INVITE == type) + { + mVoiceChannel = new LLVoiceChannelP2P(session_id, name, other_participant_id); + } + else + { + mVoiceChannel = new LLVoiceChannelGroup(session_id, name); + } + mSpeakers = new LLIMSpeakerMgr(mVoiceChannel); + + // All participants will be added to the list of people we've recently interacted with. + mSpeakers->addListener(&LLRecentPeople::instance(), "add"); +} + +LLIMModel::LLIMSession::~LLIMSession() +{ + delete mSpeakers; + mSpeakers = NULL; + + // End the text IM session if necessary + if(gVoiceClient && mOtherParticipantID.notNull()) + { + switch(mType) + { + case IM_NOTHING_SPECIAL: + case IM_SESSION_P2P_INVITE: + gVoiceClient->endUserIMSession(mOtherParticipantID); + break; + + default: + // Appease the linux compiler + break; + } + } + + // HAVE to do this here -- if it happens in the LLVoiceChannel destructor it will call the wrong version (since the object's partially deconstructed at that point). + mVoiceChannel->deactivate(); + + delete mVoiceChannel; + mVoiceChannel = NULL; } +LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const +{ + return get_if_there(LLIMModel::instance().sSessionsMap, session_id, + (LLIMModel::LLIMSession*) NULL); +} + +void LLIMModel::updateSessionID(const LLUUID& old_session_id, const LLUUID& new_session_id) +{ + if (new_session_id == old_session_id) return; + + LLIMSession* session = findIMSession(old_session_id); + if (session) + { + session->mSessionID = new_session_id; + session->mVoiceChannel->updateSessionID(new_session_id); + + //*TODO set session initialized flag here? (IB) + + sSessionsMap.erase(old_session_id); + sSessionsMap[new_session_id] = session; + } +} void LLIMModel::testMessages() { @@ -153,7 +227,7 @@ bool LLIMModel::newSession(LLUUID session_id, std::string name, EInstantMessage return false; } - LLIMSession* session = new LLIMSession(name, type, other_participant_id); + LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id); sSessionsMap[session_id] = session; LLIMMgr::getInstance()->notifyObserverSessionAdded(session_id, name, other_participant_id); @@ -170,12 +244,12 @@ bool LLIMModel::clearSession(LLUUID session_id) return true; } +//*TODO remake it, instead of returing the list pass it as as parameter (IB) std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index) { std::list<LLSD> return_list; - LLIMSession* session = get_if_there(sSessionsMap, session_id, (LLIMSession*)NULL); - + LLIMSession* session = findIMSession(session_id); if (!session) { llwarns << "session " << session_id << "does not exist " << llendl; @@ -202,13 +276,14 @@ std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index) mChangedSignal(arg); // TODO: in the future is there a more efficient way to return these + //of course there is - return as parameter (IB) return return_list; } bool LLIMModel::addToHistory(LLUUID session_id, std::string from, std::string utf8_text) { - LLIMSession* session = get_if_there(sSessionsMap, session_id, (LLIMSession*)NULL); + LLIMSession* session = findIMSession(session_id); if (!session) { @@ -231,7 +306,7 @@ bool LLIMModel::addToHistory(LLUUID session_id, std::string from, std::string ut bool LLIMModel::addMessage(LLUUID session_id, std::string from, LLUUID from_id, std::string utf8_text) { - LLIMSession* session = get_if_there(sSessionsMap, session_id, (LLIMSession*)NULL); + LLIMSession* session = findIMSession(session_id); if (!session) { @@ -260,9 +335,9 @@ bool LLIMModel::addMessage(LLUUID session_id, std::string from, LLUUID from_id, } -const std::string& LLIMModel::getName(LLUUID session_id) +const std::string& LLIMModel::getName(const LLUUID& session_id) const { - LLIMSession* session = get_if_there(sSessionsMap, session_id, (LLIMSession*)NULL); + LLIMSession* session = findIMSession(session_id); if (!session) { @@ -273,6 +348,66 @@ const std::string& LLIMModel::getName(LLUUID session_id) return session->mName; } +const S32 LLIMModel::getNumUnread(const LLUUID& session_id) const +{ + LLIMSession* session = findIMSession(session_id); + if (!session) + { + llwarns << "session " << session_id << "does not exist " << llendl; + return -1; + } + + return session->mNumUnread; +} + +const LLUUID& LLIMModel::getOtherParticipantID(const LLUUID& session_id) const +{ + LLIMSession* session = findIMSession(session_id); + if (!session) + { + llwarns << "session " << session_id << "does not exist " << llendl; + return LLUUID::null; + } + + return session->mOtherParticipantID; +} + +EInstantMessage LLIMModel::getType(const LLUUID& session_id) const +{ + LLIMSession* session = findIMSession(session_id); + if (!session) + { + llwarns << "session " << session_id << "does not exist " << llendl; + return IM_COUNT; + } + + return session->mType; +} + +LLVoiceChannel* LLIMModel::getVoiceChannel( const LLUUID& session_id ) const +{ + LLIMSession* session = findIMSession(session_id); + if (!session) + { + llwarns << "session " << session_id << "does not exist " << llendl; + return NULL; + } + + return session->mVoiceChannel; +} + +LLIMSpeakerMgr* LLIMModel::getSpeakerManager( const LLUUID& session_id ) const +{ + LLIMSession* session = findIMSession(session_id); + if (!session) + { + llwarns << "session " << session_id << "does not exist " << llendl; + return NULL; + } + + return session->mSpeakers; +} + // TODO get rid of other participant ID void LLIMModel::sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing) @@ -316,7 +451,7 @@ void LLIMModel::sendLeaveSession(LLUUID session_id, LLUUID other_participant_id) } - +//*TODO update list of messages in a LLIMSession (IB) void LLIMModel::sendMessage(const std::string& utf8_text, const LLUUID& im_session_id, const LLUUID& other_participant_id, @@ -415,9 +550,16 @@ void LLIMModel::sendMessage(const std::string& utf8_text, LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(im_session_id); if (floater) floater->addHistoryLine(history_echo, LLUIColorTable::instance().getColor("IMChatColor"), true, gAgent.getID()); + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(im_session_id); + if (speaker_mgr) + { + speaker_mgr->speakerChatted(gAgentID); + speaker_mgr->setSpeakerTyping(gAgentID, FALSE); + } } // Add the recipient to the recent people list. + //*TODO should be deleted, because speaker manager updates through callback the recent list LLRecentPeople::instance().add(other_participant_id); } @@ -633,10 +775,8 @@ public: { if ( gIMMgr) { - LLFloaterIMPanel* floaterp = - gIMMgr->findFloaterBySession(mSessionID); - - if (floaterp) + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) { //we've accepted our invitation //and received a list of agents that were @@ -650,15 +790,20 @@ public: //but unfortunately, our base that we are receiving here //may not be the most up to date. It was accurate at //some point in time though. - floaterp->setSpeakers(content); + speaker_mgr->setSpeakers(content); //we now have our base of users in the session //that was accurate at some point, but maybe not now //so now we apply all of the udpates we've received //in case of race conditions - floaterp->updateSpeakersList( - gIMMgr->getPendingAgentListUpdates(mSessionID)); + speaker_mgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(mSessionID)); + } + + LLFloaterIMPanel* floaterp = + gIMMgr->findFloaterBySession(mSessionID); + if (floaterp) + { if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE ) { floaterp->requestAutoConnect(); @@ -1104,6 +1249,12 @@ void LLIMMgr::addMessage( //no session ID...compute new one new_session_id = computeSessionID(dialog, other_participant_id); } + + if (!LLIMModel::getInstance()->findIMSession(new_session_id)) + { + LLIMModel::instance().newSession(session_id, session_name, dialog, other_participant_id); + } + floater = findFloaterBySession(new_session_id); if (!floater) { @@ -1169,6 +1320,14 @@ void LLIMMgr::addMessage( else { floater->addHistoryLine(msg, color, true, other_participant_id, from); // Insert linked name to front of message + + //*TODO consider moving that speaker management stuff into model (IB) + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(new_session_id); + if (speaker_mgr) + { + speaker_mgr->speakerChatted(gAgentID); + speaker_mgr->setSpeakerTyping(gAgentID, FALSE); + } } LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg); @@ -1273,11 +1432,10 @@ LLUUID LLIMMgr::addP2PSession(const std::string& name, { LLUUID session_id = addSession(name, IM_NOTHING_SPECIAL, other_participant_id); - LLFloaterIMPanel* floater = findFloaterBySession(session_id); - if(floater) + LLVoiceChannelP2P* voice_channel = (LLVoiceChannelP2P*) LLIMModel::getInstance()->getSpeakerManager(session_id); + if (voice_channel) { - LLVoiceChannelP2P* voice_channelp = (LLVoiceChannelP2P*)floater->getVoiceChannel(); - voice_channelp->setSessionHandle(voice_session_handle, caller_uri); + voice_channel->setSessionHandle(voice_session_handle, caller_uri); } return session_id; @@ -1312,6 +1470,11 @@ LLUUID LLIMMgr::addSession( LLUUID session_id = computeSessionID(dialog,other_participant_id); + if (!LLIMModel::getInstance()->findIMSession(session_id)) + { + LLIMModel::instance().newSession(session_id, name, dialog, other_participant_id); + } + LLFloaterIMPanel* floater = findFloaterBySession(session_id); if(!floater) { @@ -1335,17 +1498,10 @@ LLUUID LLIMMgr::addSession( noteMutedUsers(floater, ids); } } - else - { - // *TODO: Remove this? Otherwise old communicate window opens on - // second initiation of IM session from People panel? - // floater->openFloater(); - } - //mTabContainer->selectTabPanel(panel); floater->setInputFocus(TRUE); LLIMFloater::show(session_id); - notifyObserverSessionAdded(floater->getSessionID(), name, other_participant_id); - return floater->getSessionID(); + + return session_id; } // This removes the panel referenced by the uuid, and then restores @@ -1705,7 +1861,6 @@ LLFloaterIMPanel* LLIMMgr::createFloater( LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; LLFloaterChatterBox::getInstance()->addFloater(floater, FALSE, i_pt); mFloaters.insert(floater->getHandle()); - LLIMModel::instance().newSession(session_id, session_label, dialog, other_participant_id); return floater; } @@ -1825,24 +1980,25 @@ public: gIMMgr->updateFloaterSessionID( temp_session_id, session_id); + + LLIMModel::getInstance()->updateSessionID(temp_session_id, session_id); + + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); + if (speaker_mgr) + { + speaker_mgr->setSpeakers(body); + speaker_mgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(session_id)); + } + LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id); if (floaterp) { - floaterp->setSpeakers(body); - - //apply updates we've possibly received previously - floaterp->updateSpeakersList( - gIMMgr->getPendingAgentListUpdates(session_id)); - if ( body.has("session_info") ) { floaterp->processSessionUpdate(body["session_info"]); } - - //aply updates we've possibly received previously - floaterp->updateSpeakersList( - gIMMgr->getPendingAgentListUpdates(session_id)); } + gIMMgr->clearPendingAgentListUpdates(session_id); } else @@ -1932,15 +2088,15 @@ public: const LLSD& context, const LLSD& input) const { - LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID()); - if (floaterp) + const LLUUID& session_id = input["body"]["session_id"].asUUID(); + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); + if (speaker_mgr) { - floaterp->updateSpeakersList( - input["body"]); + speaker_mgr->updateSpeakers(input["body"]); } else { - //we don't have a floater yet..something went wrong + //we don't have a speaker manager yet..something went wrong //we are probably receiving an update here before //a start or an acceptance of an invitation. Race condition. gIMMgr->addPendingAgentListUpdates( diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 219af0705d..9a94d01bb2 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -34,6 +34,8 @@ #define LL_LLIMVIEW_H #include "lldarray.h" +#include "llfloateractivespeakers.h" //for LLIMSpeakerMgr +#include "llimpanel.h" //for voice channels #include "llmodaldialog.h" #include "llinstantmessage.h" #include "lluuid.h" @@ -50,21 +52,40 @@ public: struct LLIMSession { - LLIMSession(std::string name, EInstantMessage type, LLUUID other_participant_id) - :mName(name), mType(type), mNumUnread(0), mOtherParticipantID(other_participant_id) {} - + LLIMSession(const LLUUID& session_id, const std::string& name, + const EInstantMessage& type, const LLUUID& other_participant_id); + virtual ~LLIMSession(); + + LLUUID mSessionID; std::string mName; EInstantMessage mType; LLUUID mOtherParticipantID; S32 mNumUnread; std::list<LLSD> mMsgs; + + LLVoiceChannel* mVoiceChannel; + LLIMSpeakerMgr* mSpeakers; }; LLIMModel(); + //*TODO make it non-static as LLIMMOdel is a singleton (IB) static std::map<LLUUID, LLIMSession*> sSessionsMap; //mapping session_id to session + boost::signals2::signal<void(const LLSD&)> mChangedSignal; + + /** + * Find an IM Session corresponding to session_id + * Returns NULL if the session does not exist + */ + LLIMSession* findIMSession(const LLUUID& session_id) const; + + /** + * Rebind session data to a new session id. + */ + void updateSessionID(const LLUUID& old_session_id, const LLUUID& new_session_id); + boost::signals2::connection addChangedCallback( boost::function<void (const LLSD& data)> cb ); bool newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id); @@ -72,10 +93,42 @@ public: std::list<LLSD> getMessages(LLUUID session_id, int start_index = 0); bool addMessage(LLUUID session_id, std::string from, LLUUID other_participant_id, std::string utf8_text); bool addToHistory(LLUUID session_id, std::string from, std::string utf8_text); - //used to get the name of the session, for use as the title - //currently just the other avatar name - const std::string& getName(LLUUID session_id); - + //used to get the name of the session, for use as the title + //currently just the other avatar name + const std::string& getName(const LLUUID& session_id) const; + + /** + * Get number of unread messages in a session with session_id + * Returns -1 if the session with session_id doesn't exist + */ + const S32 getNumUnread(const LLUUID& session_id) const; + + /** + * Get uuid of other participant in a session with session_id + * Returns LLUUID::null if the session doesn't exist + * + * *TODO what to do with other participants in ad-hoc and group chats? + */ + const LLUUID& getOtherParticipantID(const LLUUID& session_id) const; + + /** + * Get type of a session specified by session_id + * Returns EInstantMessage::IM_COUNT if the session does not exist + */ + EInstantMessage getType(const LLUUID& session_id) const; + + /** + * Get voice channel for the session specified by session_id + * Returns NULL if the session does not exist + */ + LLVoiceChannel* getVoiceChannel(const LLUUID& session_id) const; + + /** + * Get im speaker manager for the session specified by session_id + * Returns NULL if the session does not exist + */ + LLIMSpeakerMgr* getSpeakerManager(const LLUUID& session_id) const; + static void sendLeaveSession(LLUUID session_id, LLUUID other_participant_id); static bool sendStartSession(const LLUUID& temp_session_id, const LLUUID& other_participant_id, const std::vector<LLUUID>& ids, EInstantMessage dialog); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index b53bb586f3..8430937933 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -65,6 +65,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& key) : mChatCaptionPanel(NULL), mChatHistoryEditor(NULL) { + m_isDirty = false; } LLNearbyChat::~LLNearbyChat() @@ -181,7 +182,7 @@ LLColor4 nearbychat_get_text_color(const LLChat& chat) return text_color; } -void nearbychat_add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4& color) +void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& color) { std::string line = chat.mText; @@ -194,25 +195,28 @@ void nearbychat_add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, cons bool prepend_newline = true; if (gSavedSettings.getBOOL("ChatShowTimestamps")) { - edit->appendTime(prepend_newline); + mChatHistoryEditor->appendTime(prepend_newline); prepend_newline = false; } // If the msg is from an agent (not yourself though), // extract out the sender name and replace it with the hotlinked name. + + std::string str_URL = chat.mURL; + if (chat.mSourceType == CHAT_SOURCE_AGENT && chat.mFromID != LLUUID::null) { - chat.mURL = llformat("secondlife:///app/agent/%s/about",chat.mFromID.asString().c_str()); + str_URL = llformat("secondlife:///app/agent/%s/about",chat.mFromID.asString().c_str()); } // If the chat line has an associated url, link it up to the name. - if (!chat.mURL.empty() + if (!str_URL.empty() && (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0)) { std::string start_line = line.substr(0, chat.mFromName.length() + 1); line = line.substr(chat.mFromName.length() + 1); - edit->appendStyledText(start_line, false, prepend_newline, LLStyleMap::instance().lookup(chat.mFromID,chat.mURL)); + mChatHistoryEditor->appendStyledText(start_line, false, prepend_newline, LLStyleMap::instance().lookup(chat.mFromID,str_URL)); prepend_newline = false; } @@ -225,11 +229,9 @@ void nearbychat_add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, cons else if (2 == font_size) font_name = "sansserifbig"; - edit->appendColoredText(line, false, prepend_newline, color, font_name); + mChatHistoryEditor->appendColoredText(line, false, prepend_newline, color, font_name); } - - void LLNearbyChat::addMessage(const LLChat& chat) { LLColor4 color = nearbychat_get_text_color(chat); @@ -254,7 +256,7 @@ void LLNearbyChat::addMessage(const LLChat& chat) mChatHistoryEditor->setParseHighlights(TRUE); if (!chat.mMuted) - nearbychat_add_timestamped_line(mChatHistoryEditor, chat, color); + add_timestamped_line(chat, color); } void LLNearbyChat::onNearbySpeakers() @@ -482,9 +484,16 @@ BOOL LLNearbyChat::handleRightMouseDown(S32 x, S32 y, MASK mask) void LLNearbyChat::onOpen(const LLSD& key ) { - LLNotificationsUI::LLScreenChannel* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); + LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); if(chat_channel) { chat_channel->removeToastsFromChannel(); } } + +void LLNearbyChat::draw () +{ + LLFloater::draw(); +} + + diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index efa2e479e6..599e6b6859 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -76,7 +76,10 @@ public: virtual void onOpen (const LLSD& key); + virtual void draw (); + private: + void add_timestamped_line(const LLChat& chat, const LLColor4& color); void pinn_panel(); void float_panel(); @@ -86,10 +89,11 @@ private: S32 mStart_X; S32 mStart_Y; - //LLResizeBar* mResizeBar[RESIZE_BAR_COUNT]; LLHandle<LLView> mPopupMenuHandle; LLPanel* mChatCaptionPanel; LLViewerTextEditor* mChatHistoryEditor; + + bool m_isDirty; }; #endif diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 7eb5d91e53..eb42e83994 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -41,30 +41,227 @@ #include "llviewercontrol.h" #include "llfloaterreg.h"//for LLFloaterReg::getTypedInstance +#include "llviewerwindow.h"//for screen channel position //add LLNearbyChatHandler to LLNotificationsUI namespace -namespace LLNotificationsUI{ +using namespace LLNotificationsUI; +//----------------------------------------------------------------------------------------------- +//LLNearbyChatScreenChannel +//----------------------------------------------------------------------------------------------- +LLToastPanelBase* createToastPanel() +{ + LLNearbyChatToastPanel* item = LLNearbyChatToastPanel::createInstance(); + static S32 chat_item_width = 304; + item->setWidth(chat_item_width); + return item; +} + + +class LLNearbyChatScreenChannel: public LLScreenChannelBase +{ +public: + LLNearbyChatScreenChannel(const LLUUID& id):LLScreenChannelBase(id) { mActiveMessages = 0;}; + void init (S32 channel_left, S32 channel_right); + + void addNotification (LLSD& notification); + void arrangeToasts (); + void showToastsBottom (); + + typedef boost::function<LLToastPanelBase* (void )> create_toast_panel_callback_t; + void setCreatePanelCallback(create_toast_panel_callback_t value) { m_create_toast_panel_callback_t = value;} + + void onToastDestroyed (LLToast* toast); + void onToastFade (LLToast* toast); + + // hide all toasts from screen, but not remove them from a channel + virtual void hideToastsFromScreen() + { + }; + // removes all toasts from a channel + virtual void removeToastsFromChannel() + { + for(std::vector<LLToast*>::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it) + { + LLToast* toast = (*it); + toast->setVisible(FALSE); + toast->stopTimer(); + m_toast_pool.push_back(toast); + + } + m_active_toasts.clear(); + }; + +protected: + void createOverflowToast(S32 bottom, F32 timer); + + create_toast_panel_callback_t m_create_toast_panel_callback_t; + + bool createPoolToast(); + + std::vector<LLToast*> m_active_toasts; + std::list<LLToast*> m_toast_pool; + + S32 mActiveMessages; +}; + +void LLNearbyChatScreenChannel::init(S32 channel_left, S32 channel_right) +{ + S32 channel_top = gViewerWindow->getWorldViewRect().getHeight(); + S32 channel_bottom = gViewerWindow->getWorldViewRect().mBottom; + setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom)); + setVisible(TRUE); +} + + +void LLNearbyChatScreenChannel::createOverflowToast(S32 bottom, F32 timer) +{ + //we don't need overflow toast in nearby chat +} + +void LLNearbyChatScreenChannel::onToastDestroyed(LLToast* toast) +{ +} + +void LLNearbyChatScreenChannel::onToastFade(LLToast* toast) +{ + //fade mean we put toast to toast pool + if(!toast) + return; + m_toast_pool.push_back(toast); + + std::vector<LLToast*>::iterator pos = std::find(m_active_toasts.begin(),m_active_toasts.end(),toast); + if(pos!=m_active_toasts.end()) + m_active_toasts.erase(pos); + + arrangeToasts(); +} + + +bool LLNearbyChatScreenChannel::createPoolToast() +{ + LLToastPanelBase* panel= m_create_toast_panel_callback_t(); + if(!panel) + return false; + + LLToast::Params p; + p.panel = panel; + + LLToast* toast = new LLToast(p); + + + toast->setOnFadeCallback(boost::bind(&LLNearbyChatScreenChannel::onToastFade, this, _1)); + toast->setOnToastDestroyedCallback(boost::bind(&LLNearbyChatScreenChannel::onToastDestroyed, this, _1)); + + m_toast_pool.push_back(toast); + return true; +} + +void LLNearbyChatScreenChannel::addNotification(LLSD& notification) +{ + //look in pool. if there is any message + + + if(m_toast_pool.empty()) + { + //"pool" is empty - create one more panel + if(!createPoolToast())//created toast will go to pool. so next call will find it + return; + addNotification(notification); + return; + } + + //take 1st element from pool, (re)initialize it, put it in active toasts + + LLToast* toast = m_toast_pool.back(); + + m_toast_pool.pop_back(); + + + LLToastPanelBase* panel = dynamic_cast<LLToastPanelBase*>(toast->getPanel()); + if(!panel) + return; + panel->init(notification); + + toast->reshapeToPanel(); + toast->resetTimer(); + + m_active_toasts.insert(m_active_toasts.begin(),toast); + + arrangeToasts(); +} + +void LLNearbyChatScreenChannel::arrangeToasts() +{ + if(m_active_toasts.size() == 0 || mIsHovering) + return; + + hideToastsFromScreen(); + + showToastsBottom(); +} + +void LLNearbyChatScreenChannel::showToastsBottom() +{ + LLRect rect = getRect(); + + LLRect toast_rect; + S32 bottom = getRect().mBottom; + + for(std::vector<LLToast*>::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it) + { + LLToast* toast = (*it); + toast_rect = toast->getRect(); + toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastMargin"), toast_rect.getWidth() ,toast_rect.getHeight()); + + toast->setRect(toast_rect); + + if(toast->getRect().mTop > getRect().getHeight()) + { + while(it!=m_active_toasts.end()) + { + (*it)->setVisible(FALSE); + (*it)->stopTimer(); + m_toast_pool.push_back(*it); + it=m_active_toasts.erase(it); + } + break; + } + toast->setVisible(TRUE); + bottom = toast->getRect().mTop; + } +} + + +//----------------------------------------------------------------------------------------------- +//LLNearbyChatHandler +//----------------------------------------------------------------------------------------------- LLNearbyChatHandler::LLNearbyChatHandler(e_notification_type type, const LLSD& id) { mType = type; - LLChannelManager::Params p; - p.id = LLUUID(gSavedSettings.getString("NearByChatChannelUUID")); // Getting a Channel for our notifications - mChannel = LLChannelManager::getInstance()->getChannel(p); + LLNearbyChatScreenChannel* channel = new LLNearbyChatScreenChannel(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); + + LLNearbyChatScreenChannel::create_toast_panel_callback_t callback = createToastPanel; + + channel->setCreatePanelCallback(callback); + + mChannel = LLChannelManager::getInstance()->addChannel(channel); mChannel->setOverflowFormatString("You have %d unread nearby chat messages"); } + LLNearbyChatHandler::~LLNearbyChatHandler() { } + void LLNearbyChatHandler::initChannel() { LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD()); S32 channel_right_bound = nearby_chat->getRect().mRight; - S32 channel_width = nearby_chat->getRect().mRight - 16; //HACK: 16 - ? + S32 channel_width = nearby_chat->getRect().mRight; mChannel->init(channel_right_bound - channel_width, channel_right_bound); } @@ -77,41 +274,42 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg) if(chat_msg.mText.empty()) return;//don't process empty messages - + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD()); nearby_chat->addMessage(chat_msg); if(nearby_chat->getVisible()) return;//no need in toast if chat is visible - + // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } - + LLUUID id; id.generate(); - LLChatItemCtrl* item = LLChatItemCtrl::createInstance(); - - item->setMessage(chat_msg); - //static S32 chat_item_width = nearby_chat->getRect().getWidth() - 16; - static S32 chat_item_width = 304; - item->setWidth(chat_item_width); - item->setHeaderVisibility((EShowItemHeader)gSavedSettings.getS32("nearbychat_showicons_and_names")); + LLNearbyChatScreenChannel* channel = dynamic_cast<LLNearbyChatScreenChannel*>(mChannel); - item->setVisible(true); - LLToast::Params p; - p.notif_id = id; - p.panel = item; - p.on_delete_toast = boost::bind(&LLNearbyChatHandler::onDeleteToast, this, _1); - mChannel->addToast(p); + if(channel) + { + LLSD notification; + notification["id"] = id; + notification["message"] = chat_msg.mText; + notification["from"] = chat_msg.mFromName; + notification["from_id"] = chat_msg.mFromID; + notification["time"] = chat_msg.mTime; + notification["source"] = (S32)chat_msg.mSourceType; + + channel->addNotification(notification); + } + } void LLNearbyChatHandler::onDeleteToast(LLToast* toast) { } -} + diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index 3893eaa0d4..755f1235a6 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -100,16 +100,23 @@ bool LLAlertHandler::processNotification(const LLSD& notify) p.can_fade = false; p.is_modal = mIsModal; p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); - mChannel->addToast(p); + + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) + channel->addToast(p); } else if (notify["sigtype"].asString() == "change") { LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); - mChannel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog); + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) + channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog); } else { - mChannel->killToastByNotificationID(notification->getID()); + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) + channel->killToastByNotificationID(notification->getID()); } return true; } diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index c488d37ea5..ffa92b543c 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -89,7 +89,10 @@ bool LLGroupHandler::processNotification(const LLSD& notify) p.notification = notification; p.panel = notify_box; p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1); - mChannel->addToast(p); + + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) + channel->addToast(p); // send a signal to the counter manager mNewNotificationSignal(); diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 90ff5fbaac..cd4e640ec4 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -104,8 +104,8 @@ protected: // at the moment, when a handlers creates a channel. virtual void initChannel()=0; - LLScreenChannel* mChannel; - e_notification_type mType; + LLScreenChannelBase* mChannel; + e_notification_type mType; }; diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 72855ac0fd..070af432d6 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -48,7 +48,11 @@ LLScriptHandler::LLScriptHandler(e_notification_type type, const LLSD& id) // Getting a Channel for our notifications mChannel = LLChannelManager::getInstance()->createNotificationChannel(); mChannel->setControlHovering(true); - mChannel->setOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1)); + + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) + channel->setOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1)); + } //-------------------------------------------------------------------------- @@ -92,7 +96,10 @@ bool LLScriptHandler::processNotification(const LLSD& notify) p.notification = notification; p.panel = notify_box; p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); - mChannel->addToast(p); + + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) + channel->addToast(p); // send a signal to the counter manager mNewNotificationSignal(); diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 740acb6365..5186a93569 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -93,8 +93,9 @@ bool LLTipHandler::processNotification(const LLSD& notify) p.is_tip = true; p.can_be_stored = false; - mChannel->addToast(p); - + LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel); + if(channel) + channel->addToast(p); } else if (notify["sigtype"].asString() == "delete") { diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 649697e091..7ccff73080 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -313,7 +313,7 @@ void LLPanelProfileTab::scrollToTop() { LLScrollContainer* scrollContainer = findChild<LLScrollContainer>("profile_scroll"); if (scrollContainer) - scrollContainer->goToTop(); + scrollContainer->goToTop(); } ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index 490c845c94..2b584910a3 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -195,7 +195,7 @@ BOOL LLPanelGroup::postBuild() if(panel_land) mTabs.push_back(panel_land); if(panel_general) - panel_general->setupCtrls(this); + panel_general->setupCtrls(this); return TRUE; } @@ -206,8 +206,8 @@ void LLPanelGroup::reposButton(const std::string& name) if(!button) return; LLRect btn_rect = button->getRect(); - btn_rect.setLeftTopAndSize( btn_rect.mLeft, btn_rect.getHeight() + 2, btn_rect.getWidth(), btn_rect.getHeight()); - button->setRect(btn_rect); + btn_rect.setLeftTopAndSize( btn_rect.mLeft, btn_rect.getHeight() + 2, btn_rect.getWidth(), btn_rect.getHeight()); + button->setRect(btn_rect); } void LLPanelGroup::reshape(S32 width, S32 height, BOOL called_from_parent ) @@ -235,7 +235,14 @@ void LLPanelGroup::onBtnCreate() if(!panel_general) return; std::string apply_mesg; - panel_general->apply(apply_mesg);//yes yes you need to call apply to create... + if(panel_general->apply(apply_mesg))//yes yes you need to call apply to create... + return; + if ( !apply_mesg.empty() ) + { + LLSD args; + args["MESSAGE"] = apply_mesg; + LLNotifications::instance().add("GenericAlert", args); + } } void LLPanelGroup::onBtnRefresh(void* user_data) diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 5eb7b8f5f5..2e1d971995 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -835,6 +835,7 @@ void LLPanelGroupGeneral::reset() { std::string empty_str = ""; mEditCharter->setText(empty_str); + mGroupNameEditor->setText(empty_str); } { @@ -850,6 +851,7 @@ void LLPanelGroupGeneral::reset() { mComboMature->setEnabled(true); mComboMature->setVisible( !gAgent.isTeen() ); + mComboMature->selectFirstItem(); } diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 6a41b6feb9..b2a0a01005 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -60,11 +60,8 @@ #include "llvoiceclient.h" #include "llworld.h" -using namespace LLOldEvents; - #define FRIEND_LIST_UPDATE_TIMEOUT 0.5 #define NEARBY_LIST_UPDATE_INTERVAL 1 -#define RECENT_LIST_UPDATE_DELAY 1 static const std::string NEARBY_TAB_NAME = "nearby_panel"; static const std::string FRIENDS_TAB_NAME = "friends_panel"; @@ -102,7 +99,7 @@ static LLRegisterPanelClassWrapper<LLPanelPeople> t_people("panel_people"); class LLPanelPeople::Updater { public: - typedef boost::function<bool(U32)> callback_t; + typedef boost::function<void()> callback_t; Updater(callback_t cb) : mCallback(cb) { @@ -113,16 +110,6 @@ public: } /** - * Force the list updates. - * - * This may start repeated updates until all names are complete. - */ - virtual void forceUpdate() - { - updateList(); - } - - /** * Activate/deactivate updater. * * This may start/stop regular updates. @@ -130,9 +117,9 @@ public: virtual void setActive(bool) {} protected: - bool updateList(U32 mask = 0) + void updateList() { - return mCallback(mask); + mCallback(); } callback_t mCallback; @@ -147,6 +134,11 @@ public: { mEventTimer.stop(); } + + virtual BOOL tick() // from LLEventTimer + { + return FALSE; + } }; /** @@ -178,13 +170,6 @@ public: LLAvatarTracker::instance().removeObserver(this); } - /*virtual*/ void forceUpdate() - { - // Perform updates until all names are loaded. - if (!updateList(LLFriendObserver::ADD)) - changed(LLFriendObserver::ADD); - } - /*virtual*/ void changed(U32 mask) { // events can arrive quickly in bulk - we need not process EVERY one of them - @@ -198,12 +183,12 @@ public: /*virtual*/ BOOL tick() { - if (updateList(mMask)) - { - // Got all names, stop updates. - mEventTimer.stop(); - mMask = 0; - } + if (mMask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE)) + updateList(); + + // Stop updates. + mEventTimer.stop(); + mMask = 0; return FALSE; } @@ -329,68 +314,9 @@ class LLRecentListUpdater : public LLAvatarListUpdater, public boost::signals2:: public: LLRecentListUpdater(callback_t cb) - : LLAvatarListUpdater(cb, RECENT_LIST_UPDATE_DELAY) - { - LLRecentPeople::instance().setChangedCallback(boost::bind(&LLRecentListUpdater::onRecentPeopleChanged, this)); - } - -private: - /*virtual*/ void forceUpdate() - { - onRecentPeopleChanged(); - } - - /*virtual*/ BOOL tick() - { - // Update the list until we get all the names. - if (updateList()) - { - // Got all names, stop updates. - mEventTimer.stop(); - } - - return FALSE; - } - - void onRecentPeopleChanged() - { - if (!updateList()) - { - // Some names are incomplete, schedule another update. - mEventTimer.start(); - } - } -}; - -/** - * Updates the group list on events from LLAgent. - */ -class LLGroupListUpdater : public LLPanelPeople::Updater, public LLSimpleListener -{ - LOG_CLASS(LLGroupListUpdater); - -public: - LLGroupListUpdater(callback_t cb) - : LLPanelPeople::Updater(cb) - { - gAgent.addListener(this, "new group"); - } - - ~LLGroupListUpdater() + : LLAvatarListUpdater(cb, 0) { - gAgent.removeListener(this); - } - - /*virtual*/ bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) - { - // Why is "new group" sufficient? - if (event->desc() == "new group") - { - updateList(); - return true; - } - - return false; + LLRecentPeople::instance().setChangedCallback(boost::bind(&LLRecentListUpdater::updateList, this)); } }; @@ -404,12 +330,12 @@ LLPanelPeople::LLPanelPeople() mOnlineFriendList(NULL), mAllFriendList(NULL), mNearbyList(NULL), - mRecentList(NULL) + mRecentList(NULL), + mGroupList(NULL) { - mFriendListUpdater = new LLFriendListUpdater(boost::bind(&LLPanelPeople::onFriendListUpdate,this, _1)); + mFriendListUpdater = new LLFriendListUpdater(boost::bind(&LLPanelPeople::updateFriendList, this)); mNearbyListUpdater = new LLNearbyListUpdater(boost::bind(&LLPanelPeople::updateNearbyList, this)); mRecentListUpdater = new LLRecentListUpdater(boost::bind(&LLPanelPeople::updateRecentList, this)); - mGroupListUpdater = new LLGroupListUpdater (boost::bind(&LLPanelPeople::updateGroupList, this)); } LLPanelPeople::~LLPanelPeople() @@ -417,7 +343,6 @@ LLPanelPeople::~LLPanelPeople() delete mNearbyListUpdater; delete mFriendListUpdater; delete mRecentListUpdater; - delete mGroupListUpdater; LLView::deleteViewByHandle(mGroupPlusMenuHandle); LLView::deleteViewByHandle(mNearbyViewSortMenuHandle); @@ -512,7 +437,7 @@ BOOL LLPanelPeople::postBuild() buttonSetAction("share_btn", boost::bind(&LLPanelPeople::onShareButtonClicked, this)); getChild<LLPanel>(NEARBY_TAB_NAME)->childSetAction("nearby_view_sort_btn",boost::bind(&LLPanelPeople::onNearbyViewSortButtonClicked, this)); - getChild<LLPanel>(RECENT_TAB_NAME)->childSetAction("recent_viewsort_btn",boost::bind(&LLPanelPeople::onRecentViewSortButtonClicked, this)); + getChild<LLPanel>(RECENT_TAB_NAME)->childSetAction("recent_viewsort_btn",boost::bind(&LLPanelPeople::onRecentViewSortButtonClicked, this)); getChild<LLPanel>(FRIENDS_TAB_NAME)->childSetAction("friends_viewsort_btn",boost::bind(&LLPanelPeople::onFriendsViewSortButtonClicked, this)); getChild<LLPanel>(GROUP_TAB_NAME)->childSetAction("groups_viewsort_btn",boost::bind(&LLPanelPeople::onGroupsViewSortButtonClicked, this)); @@ -547,137 +472,71 @@ BOOL LLPanelPeople::postBuild() if(recent_view_sort) mRecentViewSortMenuHandle = recent_view_sort->getHandle(); - - - // Perform initial update. - mFriendListUpdater->forceUpdate(); - mNearbyListUpdater->forceUpdate(); - mGroupListUpdater->forceUpdate(); - mRecentListUpdater->forceUpdate(); - // call this method in case some list is empty and buttons can be in inconsistent state updateButtons(); return TRUE; } -void LLPanelPeople::applyFilterToTab(const std::string& tab_name) -{ - if (tab_name == FRIENDS_TAB_NAME) // this tab has two lists - filterFriendList(); - else if (tab_name == NEARBY_TAB_NAME) - filterNearbyList(); - else if (tab_name == RECENT_TAB_NAME) - filterRecentList(); - else if (tab_name == GROUP_TAB_NAME) - updateGroupList(); -} - -bool LLPanelPeople::updateFriendList(U32 changed_mask) +void LLPanelPeople::updateFriendList() { - // Refresh names. - if (changed_mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE)) - { - // get all buddies we know about - const LLAvatarTracker& av_tracker = LLAvatarTracker::instance(); - LLAvatarTracker::buddy_map_t all_buddies; - av_tracker.copyBuddyList(all_buddies); - - // *TODO: it's suboptimal to rebuild the whole lists on online status change. + if (!mOnlineFriendList || !mAllFriendList) + return; - // save them to the online and all friends vectors - mOnlineFriendVec.clear(); - mAllFriendVec.clear(); + // get all buddies we know about + const LLAvatarTracker& av_tracker = LLAvatarTracker::instance(); + LLAvatarTracker::buddy_map_t all_buddies; + av_tracker.copyBuddyList(all_buddies); - LLFriendCardsManager::folderid_buddies_map_t listMap; + // save them to the online and all friends vectors + LLAvatarList::uuid_vector_t& online_friendsp = mOnlineFriendList->getIDs(); + LLAvatarList::uuid_vector_t& all_friendsp = mAllFriendList->getIDs(); - // *NOTE: For now collectFriendsLists returns data only for Friends/All folder. EXT-694. - LLFriendCardsManager::instance().collectFriendsLists(listMap); - if (listMap.size() > 0) - { - lldebugs << "Friends Cards were found, count: " << listMap.begin()->second.size() << llendl; - mAllFriendVec = listMap.begin()->second; - } - else - { - lldebugs << "Friends Cards were not found" << llendl; - } + all_friendsp.clear(); + online_friendsp.clear(); - LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin(); - for (; buddy_it != all_buddies.end(); ++buddy_it) - { - LLUUID buddy_id = buddy_it->first; - if (av_tracker.isBuddyOnline(buddy_id)) - mOnlineFriendVec.push_back(buddy_id); - } + LLFriendCardsManager::folderid_buddies_map_t listMap; - return filterFriendList(); + // *NOTE: For now collectFriendsLists returns data only for Friends/All folder. EXT-694. + LLFriendCardsManager::instance().collectFriendsLists(listMap); + if (listMap.size() > 0) + { + lldebugs << "Friends Cards were found, count: " << listMap.begin()->second.size() << llendl; + all_friendsp = listMap.begin()->second; + } + else + { + lldebugs << "Friends Cards were not found" << llendl; } - return true; -} - -bool LLPanelPeople::updateNearbyList() -{ - LLWorld::getInstance()->getAvatars(&mNearbyVec, NULL, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); - filterNearbyList(); - - return true; -} - -bool LLPanelPeople::updateRecentList() -{ - LLRecentPeople::instance().get(mRecentVec); - filterRecentList(); - - return true; -} - -bool LLPanelPeople::updateGroupList() -{ - if (!mGroupList) - return true; // there's no point in further updates + LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin(); + for (; buddy_it != all_buddies.end(); ++buddy_it) + { + LLUUID buddy_id = buddy_it->first; + if (av_tracker.isBuddyOnline(buddy_id)) + online_friendsp.push_back(buddy_id); + } - bool have_names = mGroupList->update(mFilterSubString); - updateButtons(); - return have_names; + mOnlineFriendList->setDirty(); + mAllFriendList->setDirty(); } -bool LLPanelPeople::filterFriendList() +void LLPanelPeople::updateNearbyList() { - if (!mOnlineFriendList || !mAllFriendList) - return true; // there's no point in further updates - - // We must always update Friends list to clear the latest removed friend. - bool have_names = - mOnlineFriendList->update(mOnlineFriendVec, mFilterSubString) & - mAllFriendList->update(mAllFriendVec, mFilterSubString); - - - updateButtons(); - return have_names; -} + if (!mNearbyList) + return; -bool LLPanelPeople::filterNearbyList() -{ - bool have_names = mNearbyList->update(mNearbyVec, mFilterSubString); - updateButtons(); - return have_names; + LLWorld::getInstance()->getAvatars(&mNearbyList->getIDs(), NULL, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); + mNearbyList->setDirty(); } -bool LLPanelPeople::filterRecentList() +void LLPanelPeople::updateRecentList() { if (!mRecentList) - return true; - - if (mRecentVec.size() > 0) - { - bool updated = mRecentList->update(mRecentVec, mFilterSubString); - updateButtons(); - return updated; - } + return; - return true; + LLRecentPeople::instance().get(mRecentList->getIDs()); + mRecentList->setDirty(); } void LLPanelPeople::buttonSetVisible(std::string btn_name, BOOL visible) @@ -846,16 +705,19 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string) LLStringUtil::toUpper(mFilterSubString); LLStringUtil::trimHead(mFilterSubString); - // Apply new filter to current tab. - applyFilterToTab(getActiveTabName()); + // Apply new filter. + mNearbyList->setNameFilter(mFilterSubString); + mOnlineFriendList->setNameFilter(mFilterSubString); + mAllFriendList->setNameFilter(mFilterSubString); + mRecentList->setNameFilter(mFilterSubString); + mGroupList->setNameFilter(mFilterSubString); } void LLPanelPeople::onTabSelected(const LLSD& param) { std::string tab_name = getChild<LLPanel>(param.asString())->getName(); mNearbyListUpdater->setActive(tab_name == NEARBY_TAB_NAME); - applyFilterToTab(tab_name); - // No need to call updateButtons() because applyFilterToTab() does that. + updateButtons(); if (GROUP_TAB_NAME == tab_name) mFilterEditor->setLabel(getString("groups_filter_label")); @@ -960,17 +822,6 @@ void LLPanelPeople::onAvatarPicked( LLAvatarActions::requestFriendshipDialog(ids[0], names[0]); } -bool LLPanelPeople::onFriendListUpdate(U32 changed_mask) -{ - bool have_names = updateFriendList(changed_mask); - - // Update online status in the Recent tab. - // *TODO: isn't it too much to update the whole list? -// updateRecentList(); // mantipov: seems online status should be supported by LLAvatarListItem itself. - - return have_names; -} - void LLPanelPeople::onGroupPlusButtonClicked() { LLMenuGL* plus_menu = (LLMenuGL*)mGroupPlusMenuHandle.get(); diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 8cd3cc7feb..de27814388 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -58,15 +58,10 @@ public: private: // methods indirectly called by the updaters - bool updateFriendList(U32 changed_mask); - bool updateNearbyList(); - bool updateRecentList(); - bool updateGroupList(); - - bool filterFriendList(); - bool filterNearbyList(); - bool filterRecentList(); - void applyFilterToTab(const std::string& tab_name); + void updateFriendList(); + void updateNearbyList(); + void updateRecentList(); + void updateButtons(); const std::string& getActiveTabName() const; LLUUID getCurrentItemID() const; @@ -110,7 +105,6 @@ private: void onRecentViewSortMenuItemClicked(const LLSD& userdata); // misc callbacks - bool onFriendListUpdate(U32 changed_mask); static void onAvatarPicked( const std::vector<std::string>& names, const std::vector<LLUUID>& ids, @@ -135,21 +129,8 @@ private: Updater* mFriendListUpdater; Updater* mNearbyListUpdater; Updater* mRecentListUpdater; - Updater* mGroupListUpdater; std::string mFilterSubString; - - // The vectors below contain up-to date avatar lists - // for the corresponding tabs. - // When the user enters a filter, it gets applied - // to all the vectors and the result is shown in the tabs. - // We don't need to have such a vector for the groups tab - // since re-fetching the groups list is always fast. - typedef std::vector<LLUUID> uuid_vector_t; - uuid_vector_t mNearbyVec; - uuid_vector_t mOnlineFriendVec; - uuid_vector_t mAllFriendVec; - uuid_vector_t mRecentVec; }; #endif //LL_LLPANELPEOPLE_H diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index 42185d28e5..5df3d4f1d6 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -39,8 +39,10 @@ #include "message.h" #include "llagent.h" #include "llbutton.h" +#include "lllineeditor.h" #include "llparcel.h" #include "llviewerparcelmgr.h" +#include "lltexteditor.h" #include "lltexturectrl.h" #include "lluiconstants.h" #include "llworldmap.h" @@ -73,7 +75,8 @@ LLPanelPick::LLPanelPick(BOOL edit_mode/* = FALSE */) mPickId(LLUUID::null), mCreatorId(LLUUID::null), mDataReceived(FALSE), - mIsPickNew(false) + mIsPickNew(false), + mLocationChanged(false) { if (edit_mode) { @@ -123,6 +126,16 @@ BOOL LLPanelPick::postBuild() if (mEditMode) { + enableSaveButton(FALSE); + + mSnapshotCtrl->setOnSelectCallback(boost::bind(&LLPanelPick::onPickChanged, this, _1)); + + LLLineEditor* line_edit = getChild<LLLineEditor>("pick_name"); + line_edit->setKeystrokeCallback(boost::bind(&LLPanelPick::onPickChanged, this, _1), NULL); + + LLTextEditor* text_edit = getChild<LLTextEditor>("pick_desc"); + text_edit->setKeystrokeCallback(boost::bind(&LLPanelPick::onPickChanged, this, _1)); + childSetAction("cancel_btn", boost::bind(&LLPanelPick::onClickCancel, this)); childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelPick::onClickSet, this)); childSetAction(XML_BTN_SAVE, boost::bind(&LLPanelPick::onClickSave, this)); @@ -287,6 +300,26 @@ void LLPanelPick::setEditMode( BOOL edit_mode ) updateButtons(); } +void LLPanelPick::onPickChanged(LLUICtrl* ctrl) +{ + if(mLocationChanged) + { + // Pick was enabled in onClickSet + return; + } + + if( mSnapshotCtrl->isDirty() + || getChild<LLLineEditor>("pick_name")->isDirty() + || getChild<LLTextEditor>("pick_desc")->isDirty() ) + { + enableSaveButton(TRUE); + } + else + { + enableSaveButton(FALSE); + } +} + ////////////////////////////////////////////////////////////////////////// // PROTECTED AREA ////////////////////////////////////////////////////////////////////////// @@ -466,6 +499,9 @@ void LLPanelPick::onClickSet() mSimName = parcel->getName(); } setPickLocation(createLocationText(std::string(""), SET_LOCATION_NOTICE, mSimName, mPosGlobal)); + + mLocationChanged = true; + enableSaveButton(TRUE); } // static @@ -552,3 +588,12 @@ void LLPanelPick::processParcelInfo(const LLParcelData& parcel_data) //*NOTE we don't removeObserver(...) ourselves cause LLRemoveParcelProcessor does it for us } + +void LLPanelPick::enableSaveButton(bool enable) +{ + if(!mEditMode) + { + return; + } + childSetEnabled(XML_BTN_SAVE, enable); +} diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h index 7ce58b59af..82cba72bc4 100644 --- a/indra/newview/llpanelpick.h +++ b/indra/newview/llpanelpick.h @@ -74,6 +74,8 @@ public: // switches the panel to either View or Edit mode void setEditMode(BOOL edit_mode); + void onPickChanged(LLUICtrl* ctrl); + // because this panel works in two modes (edit/view) we are // free from managing two panel for editing and viewing picks and so // are free from controlling switching between them in the parent panel (e.g. Me Profile) @@ -128,6 +130,8 @@ protected: void onClickSave(); void onClickCancel(); + void enableSaveButton(bool enable); + protected: BOOL mEditMode; LLTextureCtrl* mSnapshotCtrl; @@ -146,6 +150,7 @@ protected: std::string mLocation; commit_callback_t mBackCb; + bool mLocationChanged; }; #endif // LL_LLPANELPICK_H diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index 93317e613f..e74afba25a 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -126,8 +126,7 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type) 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->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4)); picture->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); } @@ -260,8 +259,10 @@ void LLPanelPicks::onClickMap() } -void LLPanelPicks::onRightMouseDownItem(LLUICtrl* item, S32 x, S32 y, MASK mask) +void LLPanelPicks::onRightMouseUpItem(LLUICtrl* item, S32 x, S32 y, MASK mask) { + updateButtons(); + if (mPopupMenu) { mPopupMenu->buildDrawLabels(); diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h index 27a21305b3..7ebdc3089c 100644 --- a/indra/newview/llpanelpicks.h +++ b/indra/newview/llpanelpicks.h @@ -100,7 +100,7 @@ private: void updateButtons(); virtual void onDoubleClickItem(LLUICtrl* item); - virtual void onRightMouseDownItem(LLUICtrl* item, S32 x, S32 y, MASK mask); + virtual void onRightMouseUpItem(LLUICtrl* item, S32 x, S32 y, MASK mask); LLPanelProfile* getProfilePanel(); diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 4e070df7eb..80ecc95afb 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -337,7 +337,7 @@ void LLPanelPlaces::onFilterEdit(const std::string& search_string) LLStringUtil::trimHead(mFilterSubString); if (mActivePanel) - mActivePanel->onSearchEdit(mFilterSubString); + mActivePanel->onSearchEdit(mFilterSubString); } } @@ -386,7 +386,7 @@ void LLPanelPlaces::onTeleportButtonClicked() else { if (mActivePanel) - mActivePanel->onTeleport(); + mActivePanel->onTeleport(); } } @@ -432,7 +432,7 @@ void LLPanelPlaces::onShowOnMapButtonClicked() else { if (mActivePanel) - mActivePanel->onShowOnMap(); + mActivePanel->onShowOnMap(); } } @@ -510,7 +510,7 @@ void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param) addChild(mPickPanel); mPickPanel->setExitCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE)); - } + } togglePickPanel(TRUE); @@ -733,7 +733,7 @@ void LLPanelPlaces::updateVerbs() else { if (mActivePanel) - mActivePanel->updateVerbs(); + mActivePanel->updateVerbs(); } } diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index f6672d9c8b..32cccc4ac0 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -306,12 +306,12 @@ void LLTeleportHistoryPanel::showTeleportHistory() if (curr_tab <= tabs_cnt - 4) { - curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() - seconds_in_day); + curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() - seconds_in_day); } else if (curr_tab == tabs_cnt - 3) // 6 day and older, low boundary is 1 month { curr_date = LLDate::now(); - curr_date.split(&curr_year, &curr_month, &curr_day); + curr_date.split(&curr_year, &curr_month, &curr_day); curr_month--; if (0 == curr_month) { @@ -376,7 +376,7 @@ void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected) S32 tabs_cnt = mItemContainers.size(); for (S32 n = 0; n < tabs_cnt; n++) - { + { LLAccordionCtrlTab* tab = mItemContainers.get(n); if (!tab->getVisible()) @@ -390,7 +390,7 @@ void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected) continue; flv->resetSelection(true); - } + } updateVerbs(); } diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 082bba027f..06bdf64b19 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -55,36 +55,30 @@ using namespace LLNotificationsUI; bool LLScreenChannel::mWasStartUpToastShown = false; //-------------------------------------------------------------------------- -LLScreenChannel::LLScreenChannel(LLUUID& id): mOverflowToastPanel(NULL), mStartUpToastPanel(NULL), - mToastAlignment(NA_BOTTOM), mCanStoreToasts(true), - mHiddenToastsNum(0), mOverflowToastHidden(false), - mIsHovering(false), mControlHovering(false), - mShowToasts(true) +////////////////////// +// LLScreenChannelBase +////////////////////// +LLScreenChannelBase::LLScreenChannelBase(const LLUUID& id) : + mOverflowToastPanel(NULL) + ,mToastAlignment(NA_BOTTOM) + ,mCanStoreToasts(true) + ,mHiddenToastsNum(0) + ,mOverflowToastHidden(false) + ,mIsHovering(false) + ,mControlHovering(false) + ,mShowToasts(false) { mID = id; mOverflowFormatString = LLTrans::getString("OverflowInfoChannelString"); - mWorldViewRectConnection = gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLScreenChannel::updatePositionAndSize, this, _1, _2)); + mWorldViewRectConnection = gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLScreenChannelBase::updatePositionAndSize, this, _1, _2)); setMouseOpaque( false ); setVisible(FALSE); } - -//-------------------------------------------------------------------------- -void LLScreenChannel::init(S32 channel_left, S32 channel_right) -{ - S32 channel_top = gViewerWindow->getWorldViewRect().getHeight(); - S32 channel_bottom = gViewerWindow->getWorldViewRect().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin"); - setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom)); - setVisible(TRUE); -} - -//-------------------------------------------------------------------------- -LLScreenChannel::~LLScreenChannel() +LLScreenChannelBase::~LLScreenChannelBase() { mWorldViewRectConnection.disconnect(); } - -//-------------------------------------------------------------------------- -void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect) +void LLScreenChannelBase::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect) { S32 top_delta = old_world_rect.mTop - new_world_rect.mTop; S32 right_delta = old_world_rect.mRight - new_world_rect.mRight; @@ -105,6 +99,42 @@ void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_wo } setRect(this_rect); redrawToasts(); + +} + +void LLScreenChannelBase::init(S32 channel_left, S32 channel_right) +{ + S32 channel_top = gViewerWindow->getWorldViewRect().getHeight(); + S32 channel_bottom = gViewerWindow->getWorldViewRect().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin"); + setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom)); + setVisible(TRUE); +} + +//-------------------------------------------------------------------------- +////////////////////// +// LLScreenChannel +////////////////////// +//-------------------------------------------------------------------------- +LLScreenChannel::LLScreenChannel(LLUUID& id): LLScreenChannelBase(id) +{ +} + +//-------------------------------------------------------------------------- +void LLScreenChannel::init(S32 channel_left, S32 channel_right) +{ + LLScreenChannelBase::init(channel_left, channel_right); +} + +//-------------------------------------------------------------------------- +LLScreenChannel::~LLScreenChannel() +{ + +} + +//-------------------------------------------------------------------------- +void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect) +{ + LLScreenChannelBase::updatePositionAndSize(old_world_rect, new_world_rect); } //-------------------------------------------------------------------------- @@ -561,7 +591,7 @@ void LLScreenChannel::removeAndStoreAllStorableToasts() else { ++it; - } + } } redrawToasts(); } diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index f1ef6bd64d..459c28ac7c 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -55,10 +55,95 @@ typedef enum e_channel_alignment CA_RIGHT, } EChannelAlignment; +class LLScreenChannelBase : public LLUICtrl +{ + friend class LLChannelManager; +public: + LLScreenChannelBase(const LLUUID& id); + ~LLScreenChannelBase(); + + // Channel's outfit-functions + // update channel's size and position in the World View + virtual void updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect); + // initialization of channel's shape and position + virtual void init(S32 channel_left, S32 channel_right); + + + virtual void setToastAlignment(EToastAlignment align) {mToastAlignment = align;} + + virtual void setChannelAlignment(EChannelAlignment align) {mChannelAlignment = align;} + virtual void setOverflowFormatString ( const std::string& str) { mOverflowFormatString = str; } + + // kill or modify a toast by its ID + virtual void killToastByNotificationID(LLUUID id) {}; + virtual void modifyToastNotificationByID(LLUUID id, LLSD data) {}; + + // hide all toasts from screen, but not remove them from a channel + virtual void hideToastsFromScreen() {}; + // removes all toasts from a channel + virtual void removeToastsFromChannel() {}; + + // show all toasts in a channel + virtual void redrawToasts() {}; + + virtual void closeOverflowToastPanel() {}; + virtual void hideOverflowToastPanel() {}; + + + // Channel's behavior-functions + // set whether a channel will control hovering inside itself or not + virtual void setControlHovering(bool control) { mControlHovering = control; } + // set Hovering flag for a channel + virtual void setHovering(bool hovering) { mIsHovering = hovering; } + + void setCanStoreToasts(bool store) { mCanStoreToasts = store; } + + void setDisplayToastsAlways(bool display_toasts) { mDisplayToastsAlways = display_toasts; } + bool getDisplayToastsAlways() { return mDisplayToastsAlways; } + + // get number of hidden notifications from a channel + S32 getNumberOfHiddenToasts() { return mHiddenToastsNum;} + + + void setShowToasts(bool show) { mShowToasts = show; } + bool getShowToasts() { return mShowToasts; } + + // get toast allignment preset for a channel + e_notification_toast_alignment getToastAlignment() {return mToastAlignment;} + + // get ID of a channel + LLUUID getChannelID() { return mID; } + +protected: + // Channel's flags + bool mControlHovering; + bool mIsHovering; + bool mCanStoreToasts; + bool mDisplayToastsAlways; + bool mOverflowToastHidden; + // controls whether a channel shows toasts or not + bool mShowToasts; + // + EToastAlignment mToastAlignment; + EChannelAlignment mChannelAlignment; + + // attributes for the Overflow Toast + S32 mHiddenToastsNum; + LLToast* mOverflowToastPanel; + std::string mOverflowFormatString; + + // channel's ID + LLUUID mID; + + // store a connection to prevent futher crash that is caused by sending a signal to a destroyed channel + boost::signals2::connection mWorldViewRectConnection; +}; + + /** * Screen channel manages toasts visibility and positioning on the screen. */ -class LLScreenChannel : public LLUICtrl +class LLScreenChannel : public LLScreenChannelBase { friend class LLChannelManager; public: @@ -70,12 +155,6 @@ public: void updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect); // initialization of channel's shape and position void init(S32 channel_left, S32 channel_right); - // set allignment of toasts inside a channel - void setToastAlignment(EToastAlignment align) {mToastAlignment = align;} - // set allignment of channel inside a world view - void setChannelAlignment(EChannelAlignment align) {mChannelAlignment = align;} - // set a template for a string in the OverflowToast - void setOverflowFormatString ( std::string str) { mOverflowFormatString = str; } // Operating with toasts // add a toast to a channel @@ -104,37 +183,17 @@ public: // close the StartUp Toast void closeStartUpToast(); - // Channel's behavior-functions - // set whether a channel will control hovering inside itself or not - void setControlHovering(bool control) { mControlHovering = control; } - // set Hovering flag for a channel - void setHovering(bool hovering) { mIsHovering = hovering; } - // set whether a channel will store faded toasts or not - void setCanStoreToasts(bool store) { mCanStoreToasts = store; } - // tell all channels that the StartUp toast was shown and allow them showing of toasts - static void setStartUpToastShown() { mWasStartUpToastShown = true; } // get StartUp Toast's state static bool getStartUpToastShown() { return mWasStartUpToastShown; } - // set mode for dislaying of toasts - void setDisplayToastsAlways(bool display_toasts) { mDisplayToastsAlways = display_toasts; } - // get mode for dislaying of toasts - bool getDisplayToastsAlways() { return mDisplayToastsAlways; } - // tell a channel to show toasts or not - void setShowToasts(bool show) { mShowToasts = show; } - // determine whether channel shows toasts or not - bool getShowToasts() { return mShowToasts; } + // tell all channels that the StartUp toast was shown and allow them showing of toasts + static void setStartUpToastShown() { mWasStartUpToastShown = true; } // let a channel update its ShowToast flag void updateShowToastsState(); + // Channel's other interface functions functions - // get number of hidden notifications from a channel - S32 getNumberOfHiddenToasts() { return mHiddenToastsNum;} // update number of notifications in the StartUp Toast void updateStartUpString(S32 num); - // get toast allignment preset for a channel - e_notification_toast_alignment getToastAlignment() {return mToastAlignment;} - // get ID of a channel - LLUUID getChannelID() { return mID; } // Channel's signals // signal on storing of faded toasts event @@ -201,30 +260,10 @@ private: // Channel's flags static bool mWasStartUpToastShown; - bool mControlHovering; - bool mIsHovering; - bool mCanStoreToasts; - bool mDisplayToastsAlways; - bool mOverflowToastHidden; - // controls whether a channel shows toasts or not - bool mShowToasts; - // - EToastAlignment mToastAlignment; - EChannelAlignment mChannelAlignment; - - // attributes for the Overflow Toast - S32 mHiddenToastsNum; - LLToast* mOverflowToastPanel; - std::string mOverflowFormatString; // attributes for the StartUp Toast LLToast* mStartUpToastPanel; - // channel's ID - LLUUID mID; - - // store a connection to prevent futher crash that is caused by sending a signal to a destroyed channel - boost::signals2::connection mWorldViewRectConnection; std::vector<ToastElem> mToastList; std::vector<ToastElem> mStoredToastList; diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 381e63f020..2be0aa40d2 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -48,6 +48,7 @@ #include "lliconctrl.h"//for Home tab icon #include "llsidetraypanelcontainer.h" #include "llwindow.h"//for SetCursor +#include "lltransientfloatermgr.h" //#include "llscrollcontainer.h" @@ -248,6 +249,7 @@ LLSideTray::LLSideTray(Params& params) // 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)); + LLTransientFloaterMgr::getInstance()->addControlView(this); } @@ -448,13 +450,17 @@ void LLSideTray::reflectCollapseChange() setPanelRect(); if(mCollapsed) + { gFloaterView->setSnapOffsetRight(0); + setFocus(FALSE); + } else + { gFloaterView->setSnapOffsetRight(mMaxBarWidth); + setFocus(TRUE); + } gFloaterView->refresh(); - - setFocus( FALSE ); } void LLSideTray::arrange () diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index d7df258750..b0930cd86d 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -225,22 +225,14 @@ void LLStatusBar::draw() BOOL LLStatusBar::handleRightMouseDown(S32 x, S32 y, MASK mask) { - if (mHideNavbarContextMenu) - { - mHideNavbarContextMenu->buildDrawLabels(); - mHideNavbarContextMenu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, mHideNavbarContextMenu, x, y); - } - + show_navbar_context_menu(this,x,y); return TRUE; } BOOL LLStatusBar::postBuild() { - mHideNavbarContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_hide_navbar.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - gMenuHolder->addChild(mHideNavbarContextMenu); - gMenuBarView->setRightMouseDownCallback(boost::bind(&LLStatusBar::onMainMenuRightClicked, this, _1, _2, _3, _4)); + gMenuBarView->setRightMouseDownCallback(boost::bind(&show_navbar_context_menu, _1, _2, _3)); return TRUE; } @@ -560,11 +552,6 @@ void LLStatusBar::setupDate() } } -void LLStatusBar::onMainMenuRightClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask) -{ - handleRightMouseDown(x, y, mask); -} - // static void LLStatusBar::onClickStatGraph(void* data) { diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index 81a69e9590..d5629e6f1e 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -91,7 +91,6 @@ private: // simple method to setup the part that holds the date void setupDate(); - void onMainMenuRightClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask); static void onCommitSearch(LLUICtrl*, void* data); static void onClickSearch(void* data); static void onClickStatGraph(void* data); @@ -111,8 +110,7 @@ private: S32 mSquareMetersCommitted; LLFrameTimer* mBalanceTimer; LLFrameTimer* mHealthTimer; - LLMenuGL* mHideNavbarContextMenu; - + static std::vector<std::string> sDays; static std::vector<std::string> sMonths; static const U32 MAX_DATE_STRING_LENGTH; diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index c1eecf4c12..2206e79c6f 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -109,6 +109,14 @@ BOOL LLSysWellWindow::postBuild() } //--------------------------------------------------------------------------------- +void LLSysWellWindow::setMinimized(BOOL minimize) +{ + setVisible(!minimize); + + LLFloater::setMinimized(minimize); +} + +//--------------------------------------------------------------------------------- void LLSysWellWindow::connectListUpdaterToSignal(std::string notification_type) { LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); @@ -155,10 +163,10 @@ void LLSysWellWindow::addItem(LLSysWellItem::Params p) { handleItemAdded(IT_NOTIFICATION); - reshapeWindow(); + reshapeWindow(); - new_item->setOnItemCloseCallback(boost::bind(&LLSysWellWindow::onItemClose, this, _1)); - new_item->setOnItemClickCallback(boost::bind(&LLSysWellWindow::onItemClick, this, _1)); + new_item->setOnItemCloseCallback(boost::bind(&LLSysWellWindow::onItemClose, this, _1)); + new_item->setOnItemClickCallback(boost::bind(&LLSysWellWindow::onItemClick, this, _1)); } else { @@ -226,11 +234,11 @@ void LLSysWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id) //--------------------------------------------------------------------------------- void LLSysWellWindow::initChannel() { - LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID( + LLNotificationsUI::LLScreenChannelBase* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID( LLUUID(gSavedSettings.getString("NotificationChannelUUID"))); - if(channel) + mChannel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>(channel); + if(mChannel) { - mChannel = channel; mChannel->setOnStoreToastCallback(boost::bind(&LLSysWellWindow::onStoreToast, this, _1, _2)); } else @@ -240,7 +248,7 @@ void LLSysWellWindow::initChannel() } //--------------------------------------------------------------------------------- -void LLSysWellWindow::getEnabledRect(LLRect& rect) +void LLSysWellWindow::getAllowedRect(LLRect& rect) { rect = gViewerWindow->getWorldViewRect(); } @@ -252,7 +260,7 @@ void LLSysWellWindow::toggleWindow() { setDockControl(new LLDockControl( LLBottomTray::getInstance()->getSysWell(), this, - getDockTongue(), LLDockControl::TOP, boost::bind(&LLSysWellWindow::getEnabledRect, this, _1))); + getDockTongue(), LLDockControl::TOP, boost::bind(&LLSysWellWindow::getAllowedRect, this, _1))); } if(!getVisible()) @@ -404,20 +412,18 @@ bool LLSysWellWindow::isWindowEmpty() //--------------------------------------------------------------------------------- //virtual -void LLSysWellWindow::sessionAdded(const LLUUID& sessionId, - const std::string& name, const LLUUID& otherParticipantId) +void LLSysWellWindow::sessionAdded(const LLUUID& session_id, + const std::string& name, const LLUUID& other_participant_id) { - if (mMessageList->getItemByValue(get_session_value(sessionId)) == NULL) + //*TODO get rid of get_session_value, session_id's are unique, cause performance degradation with lots chiclets (IB) + if (mMessageList->getItemByValue(get_session_value(session_id)) == NULL) { - S32 chicletCounter = 0; - LLIMModel::LLIMSession* session = get_if_there(LLIMModel::sSessionsMap, - sessionId, (LLIMModel::LLIMSession*) NULL); - if (session != NULL) + S32 chicletCounter = LLIMModel::getInstance()->getNumUnread(session_id); + if (chicletCounter > -1) { - chicletCounter = session->mNumUnread; + addIMRow(session_id, chicletCounter, name, other_participant_id); + reshapeWindow(); } - addIMRow(sessionId, chicletCounter, name, otherParticipantId); - reshapeWindow(); } } @@ -491,6 +497,7 @@ LLSysWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& switch (im_chiclet_type) { case LLIMChiclet::TYPE_GROUP: + case LLIMChiclet::TYPE_AD_HOC: mChiclet = getChild<LLIMChiclet>("group_chiclet"); childSetVisible("p2p_chiclet", false); break; diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 37a2690a82..203b949715 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -68,6 +68,8 @@ public: void toggleWindow(); /*virtual*/ BOOL canClose() { return FALSE; } /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); + // override LLFloater's minimization according to EXT-1216 + /*virtual*/ void setMinimized(BOOL minimize); // Handlers void onItemClick(LLSysWellItem* item); @@ -86,8 +88,8 @@ private: IT_INSTANT_MESSAGE }EItemType; - // gets a rect valid for SysWellWindow's position on a screen (EXT-1111) - void getEnabledRect(LLRect& rect); + // gets a rect that bounds possible positions for the SysWellWindow on a screen (EXT-1111) + void getAllowedRect(LLRect& rect); // connect counter and list updaters to the corresponding signals void connectListUpdaterToSignal(std::string notification_type); // init Window's channel diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 97a15759bf..ecaf4fb150 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -167,15 +167,30 @@ void LLToast::tick() } //-------------------------------------------------------------------------- -void LLToast::insertPanel(LLPanel* panel) + +void LLToast::reshapeToPanel() { - LLRect panel_rect, toast_rect; + LLPanel* panel = getPanel(); + if(!panel) + return; + + LLRect panel_rect; panel_rect = panel->getRect(); reshape(panel_rect.getWidth(), panel_rect.getHeight()); panel_rect.setLeftTopAndSize(0, panel_rect.getHeight(), panel_rect.getWidth(), panel_rect.getHeight()); panel->setRect(panel_rect); + + LLRect toast_rect = getRect(); + toast_rect.setLeftTopAndSize(toast_rect.mLeft,toast_rect.mTop,panel_rect.getWidth(), panel_rect.getHeight()); + setRect(toast_rect); + +} + +void LLToast::insertPanel(LLPanel* panel) +{ addChild(panel); + reshapeToPanel(); } //-------------------------------------------------------------------------- diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index 9248747c43..2166351fd0 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -99,6 +99,9 @@ public: // Operating with toasts // insert a panel to a toast void insertPanel(LLPanel* panel); + + void reshapeToPanel(); + // get toast's panel LLPanel* getPanel() { return mPanel; } // enable/disable Toast's Hide button diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h index bc9888f4b4..418373e8c6 100644 --- a/indra/newview/lltoastpanel.h +++ b/indra/newview/lltoastpanel.h @@ -39,6 +39,12 @@ #include <string> +class LLToastPanelBase: public LLPanel +{ +public: + virtual void init(LLSD& data){}; +}; + /** * Base class for all panels that can be added to the toast. * All toast panels should contain necessary logic for representing certain notification diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 671a62962b..12253455a3 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7666,6 +7666,19 @@ class LLHelpShowFirstTimeTip : public view_listener_t } }; +void show_navbar_context_menu(LLView* ctrl, S32 x, S32 y) +{ + static LLMenuGL* show_navbar_context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_hide_navbar.xml", + gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if(gMenuHolder->hasVisibleMenu()) + { + gMenuHolder->hideMenus(); + } + show_navbar_context_menu->buildDrawLabels(); + show_navbar_context_menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(ctrl, show_navbar_context_menu, x, y); +} + void initialize_menus() { // A parameterized event handler used as ctrl-8/9/0 zoom controls below. diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index cf482266d6..dd6aac2dd3 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -52,6 +52,7 @@ void show_debug_menus(); // checks for if menus should be shown first. void toggle_debug_menus(void*); void show_context_menu( S32 x, S32 y, MASK mask ); void show_build_mode_context_menu(S32 x, S32 y, MASK mask); +void show_navbar_context_menu(LLView* ctrl, S32 x, S32 y); BOOL enable_save_into_inventory(void*); void handle_reset_view(); void handle_cut(void*); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index d23f10f880..4a0efbaddc 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -3223,9 +3223,9 @@ LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_trans // assume that pickAsync put the results in the back of the mPicks list if(mPicks.size() != 0) { - mLastPick = mPicks.back(); - mLastPick.fetchResults(); - mPicks.pop_back(); + mLastPick = mPicks.back(); + mLastPick.fetchResults(); + mPicks.pop_back(); } else { diff --git a/indra/newview/skins/default/xui/en/floater_sys_well.xml b/indra/newview/skins/default/xui/en/floater_sys_well.xml index 30406cad63..aef5707fd4 100644 --- a/indra/newview/skins/default/xui/en/floater_sys_well.xml +++ b/indra/newview/skins/default/xui/en/floater_sys_well.xml @@ -12,7 +12,7 @@ width="320" min_width="320" height="23" - can_minimize="false" + can_minimize="true" can_tear_off="false" can_resize="false" can_drag_on_left="false" @@ -22,10 +22,10 @@ <flat_list_view color="FloaterDefaultBackgroundColor" follows="all" - layout="topleft" - name="notification_list" - left="1" + layout="topleft" + name="notification_list" + left="1" top="20" - height="0" - width="318"/> + height="0" + width="318"/> </floater> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 648c3458e0..2c77f61da6 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -128,13 +128,13 @@ function="World.SetAway" /> </menu_item_call> <menu_item_separator - layout="topleft"/> + layout="topleft"/> <menu_item_call label="Set Busy" layout="topleft" name="Set Busy"> <menu_item_call.on_click - function="World.SetBusy"/> + function="World.SetBusy"/> </menu_item_call> </menu> <menu_item_separator diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 90b331a39f..cd7e340ff1 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -79,7 +79,6 @@ label="Move" layout="topleft" name="movement_btn" - tab_stop="false" tool_tip="Shows/Hide Movement controls" top="6" width="70"> @@ -117,7 +116,6 @@ label="View" layout="topleft" left="0" - tab_stop="false" tool_tip="Shows/Hide Camera controls" top="6" name="camera_btn" @@ -133,7 +131,6 @@ height="20" width="20" left_pad="0" - tab_stop="false" is_toggle="true" picture_style="true" image_selected="toggle_button_selected" diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml index c4c8aa24c4..fb4ce436e8 100644 --- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml @@ -28,7 +28,7 @@ width="25" height="25" label="" - follows="top|left" + follows="top|right" image_overlay="BackArrow_Off" tab_stop="false" /> <text @@ -41,6 +41,7 @@ text_color="white" follows="top|left|right" mouse_opaque="true" + use_ellipses="true" name="group_name">(Loading...)</text> <line_editor follows="left|top" diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml index 683a54b366..4088d96ebf 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml @@ -35,6 +35,8 @@ follows="right" height="20" speak_button.font="SansSerifMedium" + speak_button.tab_stop="true" + show_button.tab_stop="true" layout="topleft" left_pad="5" name="talk" diff --git a/indra/newview/skins/default/xui/en/panel_notes.xml b/indra/newview/skins/default/xui/en/panel_notes.xml index 58ebac2a84..2056ec14d5 100644 --- a/indra/newview/skins/default/xui/en/panel_notes.xml +++ b/indra/newview/skins/default/xui/en/panel_notes.xml @@ -2,7 +2,7 @@ <panel bevel_style="in" follows="left|top|right|bottom" - height="420" + height="460" label="Notes & Privacy" layout="topleft" left="0" @@ -16,7 +16,7 @@ layout="topleft" left="0" top="0" - height="420" + height="430" width="313" border_size="0"> <panel diff --git a/indra/newview/skins/default/xui/en/panel_picks.xml b/indra/newview/skins/default/xui/en/panel_picks.xml index d0bde77cf2..1bd1953397 100644 --- a/indra/newview/skins/default/xui/en/panel_picks.xml +++ b/indra/newview/skins/default/xui/en/panel_picks.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel follows="left|top|right|bottom" - height="515" + height="555" label="Picks" layout="topleft" left="0" @@ -11,7 +11,7 @@ <flat_list_view color="DkGray2" follows="left|top|right|bottom" - height="495" + height="465" layout="topleft" left="0" name="picks_list" diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml index 56ba5970f2..02d179d503 100644 --- a/indra/newview/skins/default/xui/en/panel_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_profile.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel follows="all" - height="515" + height="560" label="Profile" layout="topleft" left="0" @@ -25,7 +25,7 @@ <scroll_container color="DkGray2" follows="left|top|right|bottom" - height="515" + height="500" min_height="300" layout="topleft" name="profile_scroll" @@ -265,6 +265,7 @@ left="0" name="profile_buttons_panel" top_pad="0" + height="25" width="313"> <button follows="bottom|left" @@ -316,6 +317,7 @@ name="profile_me_buttons_panel" top_pad="0" visible="false" + height="25" width="313"> <button follows="bottom|left" diff --git a/indra/newview/skins/default/xui/en/panel_profile_view.xml b/indra/newview/skins/default/xui/en/panel_profile_view.xml index cbe646f3cc..606535115d 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_view.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml @@ -2,7 +2,7 @@ <panel background_visible="true" follows="all" - height="660" + height="570" layout="topleft" min_height="350" min_width="240" @@ -50,7 +50,7 @@ width="25" /> <tab_container follows="left|top|right|bottom" - height="660" + height="560" layout="topleft" left="10" name="tabs" diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history.xml b/indra/newview/skins/default/xui/en/panel_teleport_history.xml index a0fc986423..aa95a2baef 100644 --- a/indra/newview/skins/default/xui/en/panel_teleport_history.xml +++ b/indra/newview/skins/default/xui/en/panel_teleport_history.xml @@ -111,7 +111,7 @@ width="380"> </flat_list_view> </accordion_tab> - + <accordion_tab can_resize="false" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_list.xml b/indra/newview/skins/default/xui/en/widgets/scroll_list.xml index cb876da8d8..824a815a99 100644 --- a/indra/newview/skins/default/xui/en/widgets/scroll_list.xml +++ b/indra/newview/skins/default/xui/en/widgets/scroll_list.xml @@ -10,9 +10,9 @@ highlighted_color="ScrollHighlightedColor" column_padding="5" draw_stripes="true" + scroll_bar_bg_visible="false" + scroll_bar_bg_color="black" background_visible="false" heading_height="23" draw_border="false" - draw_heading="false" - scroll_bar_bg_visible="false" - scroll_bar_bg_color="black" /> + draw_heading="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 index 6e73e997e0..e998635d20 100644 --- a/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml +++ b/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml @@ -12,17 +12,20 @@ <combo_editor select_on_focus="true" text_pad_left="20" + tool_tip="Search" 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" /> + page_lines="10" + scroll_bar_bg_visible="true" /> <search_button label="" top_pad="4" left_pad="4" width="13" height="13" + tool_tip="Search" image_unselected="Search" image_selected="Search" /> </search_combo_box>
\ No newline at end of file |