diff options
author | Steven Bennetts <steve@lindenlab.com> | 2009-07-30 23:22:41 +0000 |
---|---|---|
committer | Steven Bennetts <steve@lindenlab.com> | 2009-07-30 23:22:41 +0000 |
commit | e97f7728a90dd66014f6b3f0cd5e8d4c71f48691 (patch) | |
tree | 4be178df6b50a3395105cdd3ac0044d6467a9fa3 /indra | |
parent | d5aa10143a0e6457b3326ba839c81b7c956a015e (diff) |
merge https://svn.aws.productengine.com/secondlife/export-from-ll/viewer-2-0/indra@1170 https://svn.aws.productengine.com/secondlife/pe/stable-1/indra@1187 -> viewer-2.0.0-3
Diffstat (limited to 'indra')
97 files changed, 2625 insertions, 1388 deletions
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index fdb4bdd5c1..ad2d8afe45 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -793,6 +793,16 @@ BOOL LLMenuItemCallGL::handleAcceleratorKey( KEY key, MASK mask ) return FALSE; } +BOOL LLMenuItemCallGL::handleRightMouseUp(S32 x, S32 y, MASK mask) +{ + if (pointInView(x, y)) + { + mRightClickSignal(this, getValue()); + } + + return TRUE; +} + ///============================================================================ /// Class LLMenuItemCheckGL ///============================================================================ diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 262f75f1e1..f786c891d7 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -283,6 +283,7 @@ public: virtual BOOL handleAcceleratorKey(KEY key, MASK mask); virtual BOOL handleKeyHere(KEY key, MASK mask); + virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); //virtual void draw(); @@ -295,6 +296,11 @@ public: { return mEnableSignal.connect(cb); } + + boost::signals2::connection setRightClickedCallback( const commit_signal_t::slot_type& cb ) + { + return mRightClickSignal.connect(cb); + } private: enable_signal_t mEnableSignal; diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 2b6ae1f67e..9845b7e2ce 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -710,6 +710,15 @@ LLBoundListener LLNotificationChannelBase::connectChangedImpl(const LLEventListe return mChanged.connect(slot); } +LLBoundListener LLNotificationChannelBase::connectAtFrontChangedImpl(const LLEventListener& slot) +{ + for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it) + { + slot(LLSD().insert("sigtype", "load").insert("id", (*it)->id())); + } + return mChanged.connect(slot, boost::signals2::at_front); +} + LLBoundListener LLNotificationChannelBase::connectPassedFilterImpl(const LLEventListener& slot) { // these two filters only fire for notifications added after the current one, because @@ -1076,10 +1085,13 @@ void LLNotifications::createDefaultChannels() // connect action methods to these channels LLNotifications::instance().getChannel("Expiration")-> connectChanged(boost::bind(&LLNotifications::expirationHandler, this, _1)); + // uniqueHandler slot should be added as first slot of the signal due to + // usage LLStopWhenHandled combiner in LLStandardSignal LLNotifications::instance().getChannel("Unique")-> - connectChanged(boost::bind(&LLNotifications::uniqueHandler, this, _1)); - LLNotifications::instance().getChannel("Unique")-> - connectFailedFilter(boost::bind(&LLNotifications::failedUniquenessTest, this, _1)); + connectAtFrontChanged(boost::bind(&LLNotifications::uniqueHandler, this, _1)); +// failedUniquenessTest slot isn't necessary +// LLNotifications::instance().getChannel("Unique")-> +// connectFailedFilter(boost::bind(&LLNotifications::failedUniquenessTest, this, _1)); LLNotifications::instance().getChannel("Ignore")-> connectFailedFilter(&handleIgnoredNotification); } diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 63eae7278f..4da121c9c5 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -693,6 +693,14 @@ public: this, _1)); } + template <typename LISTENER> + LLBoundListener connectAtFrontChanged(const LISTENER& slot) + { + return LLEventDetail::visit_and_connect(slot, + boost::bind(&LLNotificationChannelBase::connectAtFrontChangedImpl, + this, + _1)); + } template <typename LISTENER> LLBoundListener connectPassedFilter(const LISTENER& slot) { @@ -718,6 +726,7 @@ public: protected: LLBoundListener connectChangedImpl(const LLEventListener& slot); + LLBoundListener connectAtFrontChangedImpl(const LLEventListener& slot); LLBoundListener connectPassedFilterImpl(const LLEventListener& slot); LLBoundListener connectFailedFilterImpl(const LLEventListener& slot); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 2e29a56e79..9a0c9d9c7b 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -243,6 +243,7 @@ set(viewer_SOURCE_FILES llinventoryfilter.cpp llinventorymodel.cpp lljoystickbutton.cpp + lllandmarkactions.cpp lllandmarklist.cpp lllistbrowser.cpp lllistview.cpp @@ -269,6 +270,7 @@ set(viewer_SOURCE_FILES llnamelistctrl.cpp llnavigationbar.cpp llnearbychat.cpp + llnearbychatbar.cpp llnearbychathandler.cpp llnetmap.cpp llnotificationalerthandler.cpp @@ -680,6 +682,7 @@ set(viewer_HEADER_FILES llinventoryfilter.h llinventorymodel.h lljoystickbutton.h + lllandmarkactions.h lllandmarklist.h lllightconstants.h lllistbrowser.h @@ -707,6 +710,7 @@ set(viewer_HEADER_FILES llnamelistctrl.h llnavigationbar.h llnearbychat.h + llnearbychatbar.h llnearbychathandler.h llnetmap.h llnotificationhandler.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ab9b018150..edcd288b7d 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4749,6 +4749,83 @@ <key>Value</key> <integer>350</integer> </map> + <key>NotificationToastTime</key> + <map> + <key>Comment</key> + <string>Width of notification messages</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>5</integer> + </map> + <key>StartUpToastTime</key> + <map> + <key>Comment</key> + <string>Width of notification messages</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>10</integer> + </map> + <key>ToastMargin</key> + <map> + <key>Comment</key> + <string>Width of notification messages</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>5</integer> + </map> + <key>ChannelBottomPanelMargin</key> + <map> + <key>Comment</key> + <string>Width of notification messages</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>35</integer> + </map> + <key>NotificationChannelRightMargin</key> + <map> + <key>Comment</key> + <string>Width of notification messages</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>10</integer> + </map> + <key>NavBarMargin</key> + <map> + <key>Comment</key> + <string>Width of notification messages</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>60</integer> + </map> + <key>OverflowToastHeight</key> + <map> + <key>Comment</key> + <string>Width of notification messages</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>72</integer> + </map> <key>NotifyMoneyChange</key> <map> <key>Comment</key> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index afad88770e..f527719a7a 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -98,6 +98,7 @@ #include "pipeline.h" #include "lltrans.h" #include "llbottomtray.h" +#include "llnearbychatbar.h" #include "stringize.h" #include "llcapabilitylistener.h" @@ -2721,7 +2722,7 @@ void LLAgent::startTyping() { sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START); } - LLBottomTray::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE); + LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE); } //----------------------------------------------------------------------------- @@ -2733,7 +2734,7 @@ void LLAgent::stopTyping() { clearRenderState(AGENT_STATE_TYPING); sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP); - LLBottomTray::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); + LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); } } @@ -6575,49 +6576,6 @@ void LLAgent::parseTeleportMessages(const std::string& xml_filename) }//end for (all message sets in xml file) } -// static -void LLAgent::createLandmarkHere() -{ - std::string landmark_name, landmark_desc; - - gAgent.buildLocationString(landmark_name, LLAgent::LOCATION_FORMAT_LANDMARK); - gAgent.buildLocationString(landmark_desc, LLAgent::LOCATION_FORMAT_FULL); - LLUUID folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK); - - createLandmarkHere(landmark_name, landmark_desc, folder_id); -} - -// static -void LLAgent::createLandmarkHere(const std::string& name, const std::string& desc, const LLUUID& folder_id) -{ - LLViewerRegion* agent_region = gAgent.getRegion(); - if(!agent_region) - { - llwarns << "No agent region" << llendl; - return; - } - LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if (!agent_parcel) - { - llwarns << "No agent parcel" << llendl; - return; - } - if (!agent_parcel->getAllowLandmark() - && !LLViewerParcelMgr::isParcelOwnedByAgent(agent_parcel, GP_LAND_ALLOW_LANDMARK)) - { - LLNotifications::instance().add("CannotCreateLandmarkNotOwner"); - return; - } - - create_inventory_item(gAgent.getID(), gAgent.getSessionID(), - folder_id, LLTransactionID::tnull, - name, desc, - LLAssetType::AT_LANDMARK, - LLInventoryType::IT_LANDMARK, - NOT_WEARABLE, PERM_ALL, - NULL); -} - void LLAgent::sendAgentUpdateUserInfo(bool im_via_email, const std::string& directory_visibility ) { gMessageSystem->newMessageFast(_PREHASH_UpdateUserInfo); diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 22b3790c6b..e25bb0a578 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -263,8 +263,6 @@ public: std::string getSLURL() const; BOOL inPrelude(); BOOL buildLocationString(std::string& str, ELocationFormat fmt = LOCATION_FORMAT_LANDMARK); // Utility to build a location string - static void createLandmarkHere(); - static void createLandmarkHere(const std::string& name, const std::string& desc, const LLUUID& folder_id); private: LLViewerRegion *mRegionp; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 2299a439e6..245e358d80 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -4034,5 +4034,8 @@ void LLAppViewer::handleLoginComplete() { gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState(); } + + mOnLoginCompleted(); + writeDebugInfo(); } diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index bbc2b646c4..646b677264 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -161,6 +161,11 @@ public: LLAllocator & getAllocator() { return mAlloc; } + // On LoginCompleted callback + typedef boost::signals2::signal<void (void)> login_completed_signal_t; + login_completed_signal_t mOnLoginCompleted; + boost::signals2::connection setOnLoginCompletedCallback( const login_completed_signal_t::slot_type& cb ) { return mOnLoginCompleted.connect(cb); } + void purgeCache(); // Clear the local cache. protected: diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 2cf7298569..281d73b18b 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -73,6 +73,9 @@ void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::strin { LLNotifications::instance().add("AddFriendWithMessage", args, payload, &callbackAddFriendWithMessage); } + + // add friend to recent people list + LLRecentPeople::instance().add(id); } // static diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index a3b8f6726d..f6eb7f6494 100644 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -42,12 +42,15 @@ #include "lluictrlfactory.h" #include "llcachename.h" +#include "llagentdata.h" #define MENU_ITEM_VIEW_PROFILE 0 #define MENU_ITEM_SEND_IM 1 static LLDefaultChildRegistry::Register<LLAvatarIconCtrl> r("avatar_icon"); +LLAvatarIconCtrl::avatar_image_map_t LLAvatarIconCtrl::sImagesCache; + LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p) : LLIconCtrl(p), mDrawTooltip(p.draw_tooltip) @@ -137,7 +140,17 @@ void LLAvatarIconCtrl::setValue(const LLSD& value) LLAvatarPropertiesProcessor::getInstance()->addObserver(value.asUUID(), this); LLAvatarPropertiesProcessor::getInstance()->sendDataRequest(value.asUUID(),APT_PROPERTIES); mAvatarId = value.asUUID(); + + // Check if cache already contains image_id for that avatar + avatar_image_map_t::iterator it; + + it = sImagesCache.find(mAvatarId); + if (it != sImagesCache.end()) + { + updateFromCache(it->second); + } } + } else { @@ -147,6 +160,37 @@ void LLAvatarIconCtrl::setValue(const LLSD& value) gCacheName->get(mAvatarId, FALSE, boost::bind(&LLAvatarIconCtrl::nameUpdatedCallback, this, _1, _2, _3, _4)); } +void LLAvatarIconCtrl::updateFromCache(LLAvatarIconCtrl::LLImagesCacheItem data) +{ + // Update the avatar + if (data.image_id.notNull()) + { + LLIconCtrl::setValue(data.image_id); + } + else + { + LLIconCtrl::setValue("default_profile_picture.j2c"); + } + + // Update color of status symbol and tool tip + if (data.flags & AVATAR_ONLINE) + { + mStatusSymbol->setColor(LLColor4::green); + if (mDrawTooltip) + { + setToolTip((LLStringExplicit)"Online"); + } + } + else + { + mStatusSymbol->setColor(LLColor4::grey); + if (mDrawTooltip) + { + setToolTip((LLStringExplicit)"Offline"); + } + } +} + //virtual void LLAvatarIconCtrl::processProperties(void* data, EAvatarProcessorType type) { @@ -160,33 +204,10 @@ void LLAvatarIconCtrl::processProperties(void* data, EAvatarProcessorType type) return; } - // Update the avatar - if (avatar_data->image_id.notNull()) - { - LLIconCtrl::setValue(avatar_data->image_id); - } - else - { - LLIconCtrl::setValue("default_profile_picture.j2c"); - } + LLAvatarIconCtrl::LLImagesCacheItem data(avatar_data->image_id, avatar_data->flags); - // Update color of status symbol and tool tip - if (avatar_data->flags & AVATAR_ONLINE) - { - mStatusSymbol->setColor(LLColor4::green); - if (mDrawTooltip) - { - setToolTip((LLStringExplicit)"Online"); - } - } - else - { - mStatusSymbol->setColor(LLColor4::grey); - if (mDrawTooltip) - { - setToolTip((LLStringExplicit)"Offline"); - } - } + updateFromCache(data); + sImagesCache.insert(std::pair<LLUUID, LLAvatarIconCtrl::LLImagesCacheItem>(mAvatarId, data)); } } } @@ -198,10 +219,17 @@ BOOL LLAvatarIconCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) if(menu) { bool is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarId) != NULL; - + menu->setItemEnabled("Add Friend", !is_friend); menu->setItemEnabled("Remove Friend", is_friend); + if(gAgentID == mAvatarId) + { + menu->setItemEnabled("Add Friend", false); + menu->setItemEnabled("Send IM", false); + menu->setItemEnabled("Remove Friend", false); + } + menu->buildDrawLabels(); menu->updateParent(LLMenuGL::sMenuContainer); LLMenuGL::showPopup(this, menu, x, y); diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h index e34f2ff474..10ce827d6d 100644 --- a/indra/newview/llavatariconctrl.h +++ b/indra/newview/llavatariconctrl.h @@ -85,6 +85,20 @@ protected: std::string mLastName; LLHandle<LLView> mPopupMenuHandle; bool mDrawTooltip; + + struct LLImagesCacheItem + { + LLUUID image_id; + U32 flags; + + LLImagesCacheItem(LLUUID image_id_, U32 flags_) : image_id(image_id_), flags(flags_) {} + }; + + typedef std::map<LLUUID, LLAvatarIconCtrl::LLImagesCacheItem> avatar_image_map_t; + + static avatar_image_map_t sImagesCache; + + void updateFromCache(LLAvatarIconCtrl::LLImagesCacheItem data); }; #endif // LL_LLAVATARICONCTRL_H diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 7b5ce765d3..a85f8710c7 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -37,24 +37,40 @@ // newview #include "llcallingcard.h" // for LLAvatarTracker #include "llcachename.h" +#include "lloutputmonitorctrl.h" +#include "llvoiceclient.h" static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list"); LLAvatarList::Params::Params() +: + volume_column_width("volume_column_width", 0) + , online_go_first("online_go_first", true) { draw_heading = true; draw_stripes = false; multi_select = false; column_padding = 0; - search_column = LIST_NAME; - sort_column = LIST_NAME; + search_column = COL_NAME; + sort_column = COL_NAME; } LLAvatarList::LLAvatarList(const Params& p) : LLScrollListCtrl(p) + , mHaveVolumeColumn(p.volume_column_width > 0) + , mOnlineGoFirst(p.online_go_first) { setCommitOnSelectionChange(TRUE); // there's no such param in LLScrollListCtrl::Params + // "volume" column + { + LLScrollListColumn::Params col_params; + col_params.name = "volume"; + col_params.header.label = "Volume"; // *TODO: localize or remove the header + col_params.width.pixel_width = p.volume_column_width; + addColumn(col_params); + } + // "name" column { LLScrollListColumn::Params col_params; @@ -63,18 +79,42 @@ LLAvatarList::LLAvatarList(const Params& p) col_params.width.dynamic_width = true; addColumn(col_params); } + + // "online status" column + { + LLScrollListColumn::Params col_params; + col_params.name = "online"; + col_params.header.label = "Online"; // *TODO: localize or remove the header + col_params.width.pixel_width = 0; // invisible column + addColumn(col_params); + } + // invisible "id" column { LLScrollListColumn::Params col_params; col_params.name = "id"; + col_params.header.label = "ID"; // *TODO: localize or remove the header col_params.width.pixel_width = 0; addColumn(col_params); } - // The corresponding parameters don't work because we create columns dynamically. - sortByColumnIndex(LIST_NAME, TRUE); - setSearchColumn(LIST_NAME); + // Primary sort = online status, secondary sort = name + // The corresponding parameters don't work because we create columns dynamically. + sortByColumnIndex(COL_NAME, TRUE); + if (mOnlineGoFirst) + sortByColumnIndex(COL_ONLINE, FALSE); + setSearchColumn(COL_NAME); +} + +// virtual +void LLAvatarList::draw() +{ + LLScrollListCtrl::draw(); + if (mHaveVolumeColumn) + { + updateVolume(); + } } std::vector<LLUUID> LLAvatarList::getSelectedIDs() @@ -97,17 +137,30 @@ void LLAvatarList::addItem(const LLUUID& id, const std::string& name, BOOL is_bo LLSD element; element["id"] = id; - LLSD& friend_column = element["columns"][LIST_NAME]; + // Update volume column (if we have one) + { + std::string icon = mHaveVolumeColumn ? getVolumeIcon(id) : ""; + LLSD& volume_column = element["columns"][COL_VOLUME]; + volume_column["column"] = "volume"; + volume_column["type"] = "icon"; + volume_column["value"] = icon; + } + + LLSD& friend_column = element["columns"][COL_NAME]; friend_column["column"] = "name"; friend_column["value"] = name; + LLSD& online_column = element["columns"][COL_ONLINE]; + online_column["column"] = "online"; + online_column["value"] = is_bold ? "1" : "0"; + LLScrollListItem* new_itemp = addElement(element, pos); // Indicate buddy online status. // (looks like parsing font parameters from LLSD is broken) if (is_bold) { - LLScrollListText* name_textp = dynamic_cast<LLScrollListText*>(new_itemp->getColumn(LIST_NAME)); + LLScrollListText* name_textp = dynamic_cast<LLScrollListText*>(new_itemp->getColumn(COL_NAME)); if (name_textp) name_textp->setFontStyle(LLFontGL::BOLD); else @@ -169,3 +222,70 @@ BOOL LLAvatarList::update(const std::vector<LLUUID>& all_buddies, const std::str return have_names; } + +// static +std::string LLAvatarList::getVolumeIcon(const LLUUID& id) +{ + // + // Determine icon appropriate for the current avatar volume. + // + // *TODO: remove this in favor of LLOutputMonitorCtrl + // when ListView widget is implemented + // which is capable of containing arbitrary widgets. + // + static LLOutputMonitorCtrl::Params default_monitor_params(LLUICtrlFactory::getDefaultParams<LLOutputMonitorCtrl>()); + bool muted = gVoiceClient->getIsModeratorMuted(id) || gVoiceClient->getOnMuteList(id); + F32 power = gVoiceClient->getCurrentPower(id); + std::string icon; + + if (muted) + { + icon = default_monitor_params.image_mute.name; + } + else if (power == 0.f) + { + icon = default_monitor_params.image_off.name; + } + else if (power < LLVoiceClient::OVERDRIVEN_POWER_LEVEL) + { + S32 icon_image_idx = llmin(2, llfloor((power / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 3.f)); + switch(icon_image_idx) + { + default: + case 0: + icon = default_monitor_params.image_on.name; + break; + case 1: + icon = default_monitor_params.image_level_1.name; + break; + case 2: + icon = default_monitor_params.image_level_2.name; + break; + } + } + else + { + // overdriven + icon = default_monitor_params.image_level_3.name; + } + + return icon; +} + +// Update volume column for all list rows. +void LLAvatarList::updateVolume() +{ + item_list& items = getItemList(); + + for (item_list::iterator item_it = items.begin(); + item_it != items.end(); + ++item_it) + { + LLScrollListItem* itemp = (*item_it); + LLUUID speaker_id = itemp->getUUID(); + + LLScrollListCell* icon_cell = itemp->getColumn(COL_VOLUME); + if (icon_cell) + icon_cell->setValue(getVolumeIcon(speaker_id)); + } +} diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index 9dba719fee..8b419dbb57 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -42,23 +42,37 @@ class LLAvatarList : public LLScrollListCtrl public: struct Params : public LLInitParam::Block<Params, LLScrollListCtrl::Params> { + Optional<S32> volume_column_width; + Optional<bool> online_go_first; Params(); }; - enum AVATAR_LIST_COLUMN_ORDER + enum EColumnOrder { - LIST_NAME, + COL_VOLUME, + COL_NAME, + COL_ONLINE, + COL_ID, }; LLAvatarList(const Params&); virtual ~LLAvatarList() {} + /*virtual*/ void draw(); + BOOL update(const std::vector<LLUUID>& all_buddies, const std::string& name_filter = LLStringUtil::null); protected: std::vector<LLUUID> getSelectedIDs(); void addItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos = ADD_BOTTOM); + +private: + static std::string getVolumeIcon(const LLUUID& id); /// determine volume icon from current avatar volume + void updateVolume(); // update volume for all avatars + + bool mHaveVolumeColumn; + bool mOnlineGoFirst; }; #endif // LL_LLAVATARLIST_H diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 963946e888..1781e6b3f1 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -37,174 +37,30 @@ #include "llchiclet.h" #include "llfloaterreg.h" #include "llflyoutbutton.h" -#include "llimpanel.h" -#include "llkeyboard.h" -#include "lllineeditor.h" -#include "llgesturemgr.h" -#include "llanimationstates.h" -#include "llmultigesture.h" -#include "llviewerstats.h" -#include "llcommandhandler.h" +#include "llnearbychatbar.h" //FIXME: temporary, for stand up proto #include "llselectmgr.h" #include "llvoavatarself.h" -S32 LLBottomTray::sLastSpecialChatChannel = 0; - -// legacy calllback glue -void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); - -static LLDefaultChildRegistry::Register<LLGestureComboBox> r("gesture_combo_box"); - -LLGestureComboBox::LLGestureComboBox(const LLComboBox::Params& p) - : LLComboBox(p) - , mGestureLabelTimer() -{ - setCommitCallback(boost::bind(&LLGestureComboBox::onCommitGesture, this, _1)); - - // now register us as observer since we have a place to put the results - gGestureManager.addObserver(this); - - // refresh list from current active gestures - refreshGestures(); -} - -LLGestureComboBox::~LLGestureComboBox() -{ - gGestureManager.removeObserver(this); -} - -void LLGestureComboBox::refreshGestures() -{ - //store current selection so we can maintain it - std::string cur_gesture = getValue().asString(); - selectFirstItem(); - std::string label = getValue().asString();; - // clear - clearRows(); - - // collect list of unique gestures - std::map <std::string, BOOL> unique; - LLGestureManager::item_map_t::iterator it; - for (it = gGestureManager.mActive.begin(); it != gGestureManager.mActive.end(); ++it) - { - LLMultiGesture* gesture = (*it).second; - if (gesture) - { - if (!gesture->mTrigger.empty()) - { - unique[gesture->mTrigger] = TRUE; - } - } - } - - // add unique gestures - std::map <std::string, BOOL>::iterator it2; - for (it2 = unique.begin(); it2 != unique.end(); ++it2) - { - addSimpleElement((*it2).first); - } - - sortByName(); - // Insert label after sorting, at top, with separator below it - addSeparator(ADD_TOP); - //FIXME: get it from xml - addSimpleElement("Gestures", ADD_TOP); - - if (!cur_gesture.empty()) - { - selectByValue(LLSD(cur_gesture)); - } - else - { - selectFirstItem(); - } -} - -void LLGestureComboBox::onCommitGesture(LLUICtrl* ctrl) -{ - LLCtrlListInterface* gestures = getListInterface(); - if (gestures) - { - S32 index = gestures->getFirstSelectedIndex(); - if (index == 0) - { - return; - } - const std::string& trigger = gestures->getSelectedValue().asString(); - - // pretend the user chatted the trigger string, to invoke - // substitution and logging. - std::string text(trigger); - std::string revised_text; - gGestureManager.triggerAndReviseString(text, &revised_text); - - revised_text = utf8str_trim(revised_text); - if (!revised_text.empty()) - { - // Don't play nodding animation - LLBottomTray::sendChatFromViewer(revised_text, CHAT_TYPE_NORMAL, FALSE); - } - } - - mGestureLabelTimer.start(); - // free focus back to chat bar - setFocus(FALSE); -} - -//virtual -void LLGestureComboBox::draw() -{ - // HACK: Leave the name of the gesture in place for a few seconds. - const F32 SHOW_GESTURE_NAME_TIME = 2.f; - if (mGestureLabelTimer.getStarted() && mGestureLabelTimer.getElapsedTimeF32() > SHOW_GESTURE_NAME_TIME) - { - LLCtrlListInterface* gestures = getListInterface(); - if (gestures) gestures->selectFirstItem(); - mGestureLabelTimer.stop(); - } - - LLComboBox::draw(); -} - LLBottomTray::LLBottomTray(const LLSD&) - : mChatBox(NULL) - , mChicletPanel(NULL) + : mChicletPanel(NULL) , mIMWell(NULL) , mSysWell(NULL) , mTalkBtn(NULL) - , mGestureCombo(NULL) , mStandUpBtn(NULL) ////FIXME: temporary, for stand up proto + , mNearbyChatBar(NULL) { + mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL); + LLUICtrlFactory::getInstance()->buildPanel(this,"panel_bottomtray.xml"); mChicletPanel = getChild<LLChicletPanel>("chiclet_list",TRUE,FALSE); mIMWell = getChild<LLNotificationChiclet>("im_well",TRUE,FALSE); mSysWell = getChild<LLNotificationChiclet>("sys_well",TRUE,FALSE); - mChatBox = getChild<LLLineEditor>("chat_box",TRUE,FALSE); mChicletPanel->setChicletClickedCallback(boost::bind(&LLBottomTray::onChicletClick,this,_1)); - if (mChatBox) - { - mChatBox->setCommitCallback(boost::bind(&LLBottomTray::onChatBoxCommit, this)); - mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this); - mChatBox->setFocusLostCallback(&onChatBoxFocusLost, this); - - mChatBox->setIgnoreArrowKeys(TRUE); - mChatBox->setCommitOnFocusLost( FALSE ); - mChatBox->setRevertOnEsc( FALSE ); - mChatBox->setIgnoreTab(TRUE); - mChatBox->setPassDelete(TRUE); - mChatBox->setReplaceNewlinesWithSpaces(FALSE); - mChatBox->setMaxTextLength(1023); - mChatBox->setEnableLineHistory(TRUE); - - } - - mGestureCombo = getChild<LLGestureComboBox>( "Gesture", TRUE, FALSE); - ////FIXME: temporary, for stand up proto mStandUpBtn = getChild<LLButton> ("stand", TRUE, FALSE); if (mStandUpBtn) @@ -246,156 +102,15 @@ void LLBottomTray::onChicletClick(LLUICtrl* ctrl) } } -void LLBottomTray::onChatBoxCommit() -{ - if (mChatBox && mChatBox->getText().length() > 0) - { - sendChat(CHAT_TYPE_NORMAL); - } - - gAgent.stopTyping(); -} - -void LLBottomTray::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate) -{ - sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate); -} - -void LLBottomTray::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate) -{ - // Look for "/20 foo" channel chats. - S32 channel = 0; - LLWString out_text = stripChannelNumber(wtext, &channel); - std::string utf8_out_text = wstring_to_utf8str(out_text); - std::string utf8_text = wstring_to_utf8str(wtext); - - utf8_text = utf8str_trim(utf8_text); - if (!utf8_text.empty()) - { - utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1); - } - - // Don't animate for chats people can't hear (chat to scripts) - if (animate && (channel == 0)) - { - if (type == CHAT_TYPE_WHISPER) - { - lldebugs << "You whisper " << utf8_text << llendl; - gAgent.sendAnimationRequest(ANIM_AGENT_WHISPER, ANIM_REQUEST_START); - } - else if (type == CHAT_TYPE_NORMAL) - { - lldebugs << "You say " << utf8_text << llendl; - gAgent.sendAnimationRequest(ANIM_AGENT_TALK, ANIM_REQUEST_START); - } - else if (type == CHAT_TYPE_SHOUT) - { - lldebugs << "You shout " << utf8_text << llendl; - gAgent.sendAnimationRequest(ANIM_AGENT_SHOUT, ANIM_REQUEST_START); - } - else - { - llinfos << "send_chat_from_viewer() - invalid volume" << llendl; - return; - } - } - else - { - if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP) - { - lldebugs << "Channel chat: " << utf8_text << llendl; - } - } - - send_chat_from_viewer(utf8_out_text, type, channel); -} - -// static -void LLBottomTray::onChatBoxKeystroke(LLLineEditor* caller, void* userdata) -{ - LLBottomTray* self = (LLBottomTray *)userdata; - - LLWString raw_text; - if (self->getChatBox()) raw_text = self->getChatBox()->getWText(); - - // Can't trim the end, because that will cause autocompletion - // to eat trailing spaces that might be part of a gesture. - LLWStringUtil::trimHead(raw_text); - - S32 length = raw_text.length(); - - if( (length > 0) && (raw_text[0] != '/') ) // forward slash is used for escape (eg. emote) sequences - { - gAgent.startTyping(); - } - else - { - gAgent.stopTyping(); - } - - /* Doesn't work -- can't tell the difference between a backspace - that killed the selection vs. backspace at the end of line. - if (length > 1 - && text[0] == '/' - && key == KEY_BACKSPACE) - { - // the selection will already be deleted, but we need to trim - // off the character before - std::string new_text = raw_text.substr(0, length-1); - self->mInputEditor->setText( new_text ); - self->mInputEditor->setCursorToEnd(); - length = length - 1; - } - */ - - KEY key = gKeyboard->currentKey(); - - // Ignore "special" keys, like backspace, arrows, etc. - if (length > 1 - && raw_text[0] == '/' - && key < KEY_SPECIAL) - { - // we're starting a gesture, attempt to autocomplete - - std::string utf8_trigger = wstring_to_utf8str(raw_text); - std::string utf8_out_str(utf8_trigger); - - if (gGestureManager.matchPrefix(utf8_trigger, &utf8_out_str)) - { - if (self->getChatBox()) - { - std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); - self->getChatBox()->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part - S32 outlength = self->getChatBox()->getLength(); // in characters - - // Select to end of line, starting from the character - // after the last one the user typed. - self->getChatBox()->setSelection(length, outlength); - } - } - - //llinfos << "GESTUREDEBUG " << trigger - // << " len " << length - // << " outlen " << out_str.getLength() - // << llendl; - } -} - -// static -void LLBottomTray::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata) +void* LLBottomTray::createNearbyChatBar(void* userdata) { - // stop typing animation - gAgent.stopTyping(); -} + LLBottomTray *bt = LLBottomTray::getInstance(); + if (!bt) + return NULL; -BOOL LLBottomTray::inputEditorHasFocus() -{ - return mChatBox && mChatBox->hasFocus(); -} + bt->mNearbyChatBar = new LLNearbyChatBar(); -std::string LLBottomTray::getCurrentChat() -{ - return mChatBox ? mChatBox->getText() : LLStringUtil::null; + return bt->mNearbyChatBar; } //virtual @@ -440,14 +155,9 @@ void LLBottomTray::sessionAdded(const LLUUID& session_id, const std::string& nam } else { - LLIMChiclet* chicklet = getChicletPanel()->createChiclet<LLIMChiclet>(session_id); - chicklet->setIMSessionName(name); - chicklet->setOtherParticipantId(other_participant_id); - - if(getChicletPanel()->getChicletCount()) - { - setChicletPanelVisible(true); - } + LLIMChiclet* chiclet = getChicletPanel()->createChiclet<LLIMChiclet>(session_id); + chiclet->setIMSessionName(name); + chiclet->setOtherParticipantId(other_participant_id); } } } @@ -458,27 +168,6 @@ void LLBottomTray::sessionRemoved(const LLUUID& session_id) if(getChicletPanel()) { getChicletPanel()->removeChiclet(session_id); - - if(0 == getChicletPanel()->getChicletCount()) - { - setChicletPanelVisible(false); - } - } -} - -void LLBottomTray::setChicletPanelVisible(bool visible) -{ - // Chiclet panel is placed in layout_panel, which is child of layout_stack. - // To gide chiclet panel we need to also hide layout_panel to make layout_stack resize its - // content. - getChicletPanel()->getParent()->setVisible(visible); - if(visible) - { - // Reshape layout stack after making chiclet panel visible - LLView* layout = getChild<LLView>("toolbar_stack"); - LLRect rc = layout->getRect(); - layout->reshape(rc.getWidth(), rc.getHeight()); - layout->setRect(rc); } } @@ -491,22 +180,6 @@ void LLBottomTray::onFocusLost() } } -// virtual -BOOL LLBottomTray::handleKeyHere( KEY key, MASK mask ) -{ - BOOL handled = FALSE; - - // ALT-RETURN is reserved for windowed/fullscreen toggle - if( KEY_RETURN == key && mask == MASK_CONTROL) - { - // shout - sendChat(CHAT_TYPE_SHOUT); - handled = TRUE; - } - - return handled; -} - //virtual // setVisible used instead of onVisibilityChange, since LLAgent calls it on entering/leaving mouselook mode. // If bottom tray is already visible in mouselook mode, then onVisibilityChange will not be called from setVisible(true), @@ -514,192 +187,22 @@ void LLBottomTray::setVisible(BOOL visible) { LLPanel::setVisible(visible); - - BOOL visibility = gAgent.cameraMouselook() ? false : true; + LLView* stack = getChild<LLView>("toolbar_stack",TRUE,FALSE); - LLViewBorder* separator = getChild<LLViewBorder>("well_separator",TRUE,FALSE); - - if (separator && separator->getVisible() == visibility) - return; - - if (separator) - separator->setVisible(visibility); - - LLPanel* p = getChild<LLPanel>("chiclet_list_panel",TRUE,FALSE); - if (p) - p->setVisible(visibility); - - p = getChild<LLPanel>("im_well_panel",TRUE,FALSE); - if (p) - p->setVisible(visibility); - - p = getChild<LLPanel>("sys_well_panel",TRUE,FALSE); - if (p) - p->setVisible(visibility); - -} - -// static -void LLBottomTray::startChat(const char* line) -{ - LLBottomTray *bt = LLBottomTray::getInstance(); - - if(bt && bt->getChatBox()) + if (stack) { - bt->setVisible(TRUE); - bt->getChatBox()->setFocus(TRUE); + BOOL visibility = gAgent.cameraMouselook() ? false : true; - if (line) + for ( child_list_const_iter_t child_it = stack->getChildList()->begin(); child_it != stack->getChildList()->end(); child_it++) { - std::string line_string(line); - bt->getChatBox()->setText(line_string); - } - - bt->getChatBox()->setCursorToEnd(); - } -} - -// Exit "chat mode" and do the appropriate focus changes -// static -void LLBottomTray::stopChat() -{ - LLBottomTray *bt = LLBottomTray::getInstance(); - - if(bt && bt->getChatBox()) - { - bt->getChatBox()->setFocus(FALSE); - } - - // stop typing animation - gAgent.stopTyping(); -} - -void LLBottomTray::sendChat( EChatType type ) -{ - if (mChatBox) - { - LLWString text = mChatBox->getConvertedText(); - if (!text.empty()) - { - // store sent line in history, duplicates will get filtered - mChatBox->updateHistory(); - // Check if this is destined for another channel - S32 channel = 0; - stripChannelNumber(text, &channel); + LLView* viewp = *child_it; - std::string utf8text = wstring_to_utf8str(text); - // Try to trigger a gesture, if not chat to a script. - std::string utf8_revised_text; - if (0 == channel) - { - // discard returned "found" boolean - gGestureManager.triggerAndReviseString(utf8text, &utf8_revised_text); - } - else - { - utf8_revised_text = utf8text; - } - - utf8_revised_text = utf8str_trim(utf8_revised_text); - - if (!utf8_revised_text.empty()) + if ("chat_bar" == viewp->getName()) + continue; + else { - // Chat with animation - sendChatFromViewer(utf8_revised_text, type, TRUE); + viewp->setVisible(visibility); } } - - mChatBox->setText(LLStringExplicit("")); } - - gAgent.stopTyping(); } - -// If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20. -// Otherwise returns input and channel 0. -LLWString LLBottomTray::stripChannelNumber(const LLWString &mesg, S32* channel) -{ - if (mesg[0] == '/' - && mesg[1] == '/') - { - // This is a "repeat channel send" - *channel = sLastSpecialChatChannel; - return mesg.substr(2, mesg.length() - 2); - } - else if (mesg[0] == '/' - && mesg[1] - && LLStringOps::isDigit(mesg[1])) - { - // This a special "/20" speak on a channel - S32 pos = 0; - - // Copy the channel number into a string - LLWString channel_string; - llwchar c; - do - { - c = mesg[pos+1]; - channel_string.push_back(c); - pos++; - } - while(c && pos < 64 && LLStringOps::isDigit(c)); - - // Move the pointer forward to the first non-whitespace char - // Check isspace before looping, so we can handle "/33foo" - // as well as "/33 foo" - while(c && iswspace(c)) - { - c = mesg[pos+1]; - pos++; - } - - sLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10); - *channel = sLastSpecialChatChannel; - return mesg.substr(pos, mesg.length() - pos); - } - else - { - // This is normal chat. - *channel = 0; - return mesg; - } -} - -void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) -{ - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_ChatFromViewer); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ChatData); - msg->addStringFast(_PREHASH_Message, utf8_out_text); - msg->addU8Fast(_PREHASH_Type, type); - msg->addS32("Channel", channel); - - gAgent.sendReliableMessage(); - - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT); -} - -class LLChatHandler : public LLCommandHandler -{ -public: - // not allowed from outside the app - LLChatHandler() : LLCommandHandler("chat", true) { } - - // Your code here - bool handle(const LLSD& tokens, const LLSD& query_map, - LLWebBrowserCtrl* web) - { - if (tokens.size() < 2) return false; - S32 channel = tokens[0].asInteger(); - std::string mesg = tokens[1].asString(); - send_chat_from_viewer(mesg, CHAT_TYPE_NORMAL, channel); - return true; - } -}; - -// Creating the object registers with the dispatcher. -LLChatHandler gChatHandler; - diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 08f5cb91d8..e5848f72dc 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -35,35 +35,12 @@ #include "llpanel.h" #include "llimview.h" -#include "llchat.h" -#include "llgesturemgr.h" -#include "llcombobox.h" class LLChicletPanel; class LLLineEditor; class LLNotificationChiclet; class LLTalkButton; - -class LLGestureComboBox - : public LLComboBox - , public LLGestureManagerObserver -{ -protected: - LLGestureComboBox(const LLComboBox::Params&); - friend class LLUICtrlFactory; -public: - ~LLGestureComboBox(); - - void refreshGestures(); - void onCommitGesture(LLUICtrl* ctrl); - virtual void draw(); - - // LLGestureManagerObserver trigger - virtual void changed() { refreshGestures(); } - -protected: - LLFrameTimer mGestureLabelTimer; -}; +class LLNearbyChatBar; class LLBottomTray : public LLUISingleton<LLBottomTray> @@ -74,19 +51,10 @@ class LLBottomTray public: ~LLBottomTray(); - LLLineEditor* getChatBox() {return mChatBox;} LLChicletPanel* getChicletPanel() {return mChicletPanel;} LLNotificationChiclet* getIMWell() {return mIMWell;} LLNotificationChiclet* getSysWell() {return mSysWell;} - - void onChatBoxCommit(); - static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate); - static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); - static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata); - static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata); - - BOOL inputEditorHasFocus(); - std::string getCurrentChat(); + LLNearbyChatBar* getNearbyChatBar() {return mNearbyChatBar;} /*virtual*/void draw(); void refreshStandUp(); @@ -100,33 +68,22 @@ public: virtual void sessionRemoved(const LLUUID& session_id); virtual void onFocusLost(); - virtual BOOL handleKeyHere(KEY key, MASK mask); virtual void setVisible(BOOL visible); - static void startChat(const char* line); - static void stopChat(); - protected: LLBottomTray(const LLSD& key = LLSD()); - void sendChat( EChatType type ); - static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); - void onChicletClick(LLUICtrl* ctrl); - void setChicletPanelVisible(bool visible); - - // Which non-zero channel did we last chat on? - static S32 sLastSpecialChatChannel; + static void* createNearbyChatBar(void* userdata); - LLLineEditor* mChatBox; LLChicletPanel* mChicletPanel; LLNotificationChiclet* mIMWell; LLNotificationChiclet* mSysWell; LLTalkButton* mTalkBtn; - LLGestureComboBox* mGestureCombo; LLButton* mStandUpBtn; + LLNearbyChatBar* mNearbyChatBar; }; #endif // LL_LLBOTTOMPANEL_H diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index 723bf2a248..0eb0801a2c 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -34,6 +34,9 @@ #include "llchannelmanager.h" +#include "llappviewer.h" +#include "llviewercontrol.h" + #include <algorithm> using namespace LLNotificationsUI; @@ -41,6 +44,7 @@ using namespace LLNotificationsUI; //-------------------------------------------------------------------------- LLChannelManager::LLChannelManager() { + LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLChannelManager::onLoginCompleted, this)); } //-------------------------------------------------------------------------- @@ -50,6 +54,45 @@ LLChannelManager::~LLChannelManager() } //-------------------------------------------------------------------------- +void LLChannelManager::onLoginCompleted() +{ + S32 hidden_notifications = 0; + + for(std::vector<ChannelElem>::iterator it = mChannelList.begin(); it != mChannelList.end(); ++it) + { + //(*it).channel->showToasts(); + hidden_notifications +=(*it).channel->getNumberOfHiddenToasts(); + } + + if(!hidden_notifications) + { + LLScreenChannel::setStartUpToastShown(); + return; + } + + LLChannelManager::Params p; + p.id = LLUUID(STARTUP_CHANNEL_ID); + p.channel_right_bound = getRootView()->getRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); + p.channel_width = gSavedSettings.getS32("NotifyBoxWidth"); + mStartUpChannel = NULL; + mStartUpChannel = createChannel(p); + + if(!mStartUpChannel) + return; + + static_cast<LLUICtrl*>(mStartUpChannel)->setCommitCallback(boost::bind(&LLChannelManager::enableShowToasts, this)); + mStartUpChannel->setNumberOfHiddenToasts(hidden_notifications); + mStartUpChannel->createOverflowToast(gSavedSettings.getS32("ChannelBottomPanelMargin"), gSavedSettings.getS32("StartUpToastTime")); +} + +//-------------------------------------------------------------------------- +void LLChannelManager::enableShowToasts() +{ + LLScreenChannel::setStartUpToastShown(); + delete mStartUpChannel; +} + +//-------------------------------------------------------------------------- LLScreenChannel* LLChannelManager::createChannel(LLChannelManager::Params& p) { LLScreenChannel* new_channel = NULL; @@ -67,7 +110,8 @@ LLScreenChannel* LLChannelManager::createChannel(LLChannelManager::Params& p) return new_channel; new_channel = new LLScreenChannel(); - new_channel->init(p.channel_right_bound - p.channel_width, getRootView()); + getRootView()->addChild(new_channel); + new_channel->init(p.channel_right_bound - p.channel_width, p.channel_right_bound); new_channel->setToastAlignment(p.align); ChannelElem new_elem; diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h index 564535ff24..3914d20ebc 100644 --- a/indra/newview/llchannelmanager.h +++ b/indra/newview/llchannelmanager.h @@ -45,6 +45,8 @@ namespace LLNotificationsUI { +#define STARTUP_CHANNEL_ID "AEED3193-8709-4693-8558-7452CCA97AE5" + /** * Manager for screen channels. * Responsible for instantiating and retrieving screen channels. @@ -98,6 +100,10 @@ public: LLChannelManager(); virtual ~LLChannelManager(); + // On LoginCompleted - show StartUp toast + void onLoginCompleted(); + void enableShowToasts(); + //TODO: make protected? in order to be shure that channels are created only by notification handlers LLScreenChannel* createChannel(LLChannelManager::Params& p); @@ -108,6 +114,7 @@ public: private: + LLScreenChannel* mStartUpChannel; std::vector<ChannelElem> mChannelList; }; diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index bb31b7f2e8..2b455485ca 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -41,6 +41,7 @@ #include "lltrans.h" #include "llviewercontrol.h" +#include "llagentdata.h" static const S32 BORDER_MARGIN = 2; static const S32 PARENT_BORDER_MARGIN = 0; @@ -51,6 +52,9 @@ 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 @@ -89,8 +93,8 @@ void LLChatItemCtrl::reshape (S32 width, S32 height, BOOL called_from_parent ) LLRect msg_text_rect = msg_text->getRect(); - msg_text_rect.setLeftTopAndSize( 10, height - caption_rect.getHeight() , width - 20, height - caption_rect.getHeight()); - msg_text->reshape( width - 20, height - caption_rect.getHeight(), 1); + msg_text_rect.setLeftTopAndSize( msg_left_offset, height - caption_rect.getHeight() , width - msg_left_offset - msg_right_offset, height - caption_rect.getHeight()); + msg_text->reshape( width - msg_left_offset - msg_right_offset, height - caption_rect.getHeight(), 1); msg_text->setRect(msg_text_rect); } @@ -132,11 +136,22 @@ void LLChatItemCtrl::setMessage (const LLChat& msg) LLPanel* caption = getChild<LLPanel>("msg_caption",false,false); if(!caption) return; - caption->getChild<LLTextBox>("sender_name",false,false)->setText(msg.mFromName); + + std::string str_sender; + + + if(gAgentID != msg.mFromID) + str_sender = msg.mFromName; + else + str_sender = LLTrans::getString("You");; + + caption->getChild<LLTextBox>("sender_name",false,false)->setText(str_sender); + std::string tt = appendTime(); caption->getChild<LLTextBox>("msg_time",false,false)->setText(tt); + caption->getChild<LLAvatarIconCtrl>("avatar_icon",false,false)->setValue(msg.mFromID); mOriginalMessage = msg; @@ -153,6 +168,28 @@ void LLChatItemCtrl::setMessage (const LLChat& msg) } +void LLChatItemCtrl::snapToMessageHeight () +{ + LLChatMsgBox* text_box = getChild<LLChatMsgBox>("msg_text",false,false); + if(!text_box) + return;///actually assert fits better + S32 new_height = text_box->getTextPixelHeight(); + LLRect panel_rect = getRect(); + + S32 caption_height = 0; + LLPanel* caption = getChild<LLPanel>("msg_caption",false,false); + if(caption) + caption_height = caption->getRect().getHeight(); + + + panel_rect.setLeftTopAndSize( panel_rect.mLeft, panel_rect.mTop, panel_rect.getWidth() , caption_height + new_height); + + reshape( getRect().getWidth(), caption_height + new_height, 1); + + setRect(panel_rect); + +} + void LLChatItemCtrl::setWidth(S32 width) { @@ -160,7 +197,7 @@ void LLChatItemCtrl::setWidth(S32 width) if(!text_box) return;///actually assert fits better - text_box->reshape(width - 20,100/*its not magic number, we just need any number*/); + 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,false); if(msg_text && mOriginalMessage.mText.length()) @@ -169,13 +206,8 @@ void LLChatItemCtrl::setWidth(S32 width) for(size_t i=0;i<mMessages.size();++i) msg_text->addText(mMessages[i]); - S32 new_height = text_box->getTextPixelHeight(); - LLRect panel_rect = getRect(); - panel_rect.setLeftTopAndSize( panel_rect.mLeft, panel_rect.mTop, width , 35 + new_height); - - reshape( width, panel_rect.getHeight(), 1); - - setRect(panel_rect); + setRect(LLRect(getRect().mLeft, getRect().mTop, getRect().mLeft + width , getRect().mBottom)); + snapToMessageHeight (); } void LLChatItemCtrl::onMouseLeave (S32 x, S32 y, MASK mask) @@ -190,6 +222,8 @@ void LLChatItemCtrl::onMouseLeave (S32 x, S32 y, MASK mask) } void LLChatItemCtrl::onMouseEnter (S32 x, S32 y, MASK mask) { + if(mOriginalMessage.mSourceType != CHAT_SOURCE_AGENT) + return; LLPanel* caption = getChild<LLPanel>("msg_caption",false,false); if(!caption) return; @@ -200,8 +234,10 @@ void LLChatItemCtrl::onMouseEnter (S32 x, S32 y, MASK mask) BOOL LLChatItemCtrl::handleMouseDown (S32 x, S32 y, MASK mask) { + if(mOriginalMessage.mSourceType != CHAT_SOURCE_AGENT) + return LLPanel::handleMouseDown(x,y,mask); LLPanel* caption = getChild<LLPanel>("msg_caption",false,false); - if(mOriginalMessage.mSourceType == CHAT_SOURCE_AGENT && caption) + if(caption) { LLUICtrl* msg_inspector = caption->getChild<LLUICtrl>("msg_inspector"); if(msg_inspector) @@ -242,6 +278,23 @@ bool LLChatItemCtrl::canAddText () return msg_text->getTextLinesNum()<10; } +BOOL LLChatItemCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + LLPanel* caption = getChild<LLPanel>("msg_caption",false,false); + if(!caption) + return LLPanel::handleRightMouseDown(x,y,mask); + LLUICtrl* avatar_icon = caption->getChild<LLUICtrl>("avatar_icon",false,false); + if(!avatar_icon) + return LLPanel::handleRightMouseDown(x,y,mask); + S32 local_x = x - avatar_icon->getRect().mLeft - caption->getRect().mLeft; + 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) + return TRUE; + return LLPanel::handleRightMouseDown(x,y,mask); +} + //******************************************************************************************************************* //LLChatItemsContainerCtrl @@ -264,13 +317,18 @@ void LLChatItemsContainerCtrl::addMessage(const LLChat& msg) LLChatItemCtrl* item = mItems[0]; removeChild(item); delete item; + mItems.erase(mItems.begin()); } - if(mItems.size() > 0 && msg.mFromID == mItems[mItems.size()-1]->getMessage().mFromID && mItems[mItems.size()-1]->canAddText()) + 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]->setWidth(getRect().getWidth() - 16); + mItems[mItems.size()-1]->snapToMessageHeight(); } else { @@ -279,6 +337,8 @@ void LLChatItemsContainerCtrl::addMessage(const LLChat& msg) 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); diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h index f5791078aa..de16cf9505 100644 --- a/indra/newview/llchatitemscontainerctrl.h +++ b/indra/newview/llchatitemscontainerctrl.h @@ -63,6 +63,7 @@ public: void addText (const std::string& message); void setMessage (const LLChat& msg); void setWidth (S32 width); + void snapToMessageHeight (); bool canAddText (); @@ -75,6 +76,7 @@ public: void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE); void setHeaderVisibility(EShowItemHeader e); + BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); private: std::string appendTime (); diff --git a/indra/newview/llchatmsgbox.cpp b/indra/newview/llchatmsgbox.cpp index 8fb4b78cb8..933d9b8771 100644 --- a/indra/newview/llchatmsgbox.cpp +++ b/indra/newview/llchatmsgbox.cpp @@ -51,9 +51,8 @@ LLChatMsgBox::Params::Params() disabled_color("disabled_color"), background_color("background_color"), border_color("border_color"), - v_pad("v_pad", 0), - h_pad("h_pad", 0), - line_spacing("line_spacing", 0), + line_spacing("line_spacing", 4), + block_spacing("block_spacing",10), text("text"), font_shadow("font_shadow", LLFontGL::NO_SHADOW) {} @@ -68,8 +67,6 @@ LLChatMsgBox::LLChatMsgBox(const LLChatMsgBox::Params& p) mShadowType( p.font_shadow ), mBorderDropShadowVisible( p.border_drop_shadow_visible ), mUseEllipses( p.use_ellipses ), - mHPad(p.h_pad), - mVPad(p.v_pad), mVAlign( LLFontGL::TOP ), mClickedCallback(NULL), mTextColor(p.text_color()), @@ -79,6 +76,7 @@ LLChatMsgBox::LLChatMsgBox(const LLChatMsgBox::Params& p) mHoverColor(p.hover_color()), mHAlign(p.font_halign), mLineSpacing(p.line_spacing), + mBlockSpasing(p.block_spacing), mWordWrap( p.word_wrap ), mFontStyle(LLFontGL::getStyleFromString(p.font.style)) { @@ -271,7 +269,7 @@ S32 LLChatMsgBox::getTextLinesNum() S32 LLChatMsgBox::getTextPixelHeight() { S32 num_lines = getTextLinesNum(); - return (S32)(num_lines * mFontGL->getLineHeight() + (num_lines-1)*4); + return (S32)(num_lines * mFontGL->getLineHeight() + (num_lines-1)*mLineSpacing + mBlockSpasing*(mTextStrings.size()-1) + 2*mLineSpacing);//some extra space } void LLChatMsgBox::setValue(const LLSD& value ) @@ -305,17 +303,16 @@ void LLChatMsgBox::draw() switch( mHAlign ) { case LLFontGL::LEFT: - text_x = mHPad; break; case LLFontGL::HCENTER: text_x = getRect().getWidth() / 2; break; case LLFontGL::RIGHT: - text_x = getRect().getWidth() - mHPad; + text_x = getRect().getWidth() ; break; } - S32 text_y = getRect().getHeight() - mVPad; + S32 text_y = getRect().getHeight() ; if ( getEnabled() ) { @@ -358,6 +355,7 @@ void LLChatMsgBox::reshape(S32 width, S32 height, BOOL called_from_parent) void LLChatMsgBox::drawText( S32 x, S32 y, const LLColor4& color ) { S32 width = getRect().getWidth()-10; + for(std::vector< boost::shared_ptr<text_block> >::iterator it = mTextStrings.begin(); it!=mTextStrings.end();++it) @@ -383,8 +381,9 @@ void LLChatMsgBox::drawText( S32 x, S32 y, const LLColor4& color ) if(next == mTextStrings.end()) break; //separator - gl_line_2d(5,y-2,width,y-2,LLColor4::grey); - y-=4; + gl_line_2d(5,y-mBlockSpasing/2,width,y-mBlockSpasing/2,LLColor4::grey); + y-=mBlockSpasing; } + } diff --git a/indra/newview/llchatmsgbox.h b/indra/newview/llchatmsgbox.h index c0e1964afa..61035499c7 100644 --- a/indra/newview/llchatmsgbox.h +++ b/indra/newview/llchatmsgbox.h @@ -71,9 +71,9 @@ public: background_color, border_color; - Optional<S32> v_pad, - h_pad, - line_spacing; + Optional<S32> line_spacing; + + Optional<S32> block_spacing; Params(); }; @@ -104,8 +104,6 @@ public: void setBackgroundVisible(BOOL visible) { mBackgroundVisible = visible; } void setBorderVisible(BOOL visible) { mBorderVisible = visible; } void setBorderDropshadowVisible(BOOL visible){ mBorderDropShadowVisible = visible; } - void setHPad(S32 pixels) { mHPad = pixels; } - void setVPad(S32 pixels) { mVPad = pixels; } void setRightAlign() { mHAlign = LLFontGL::RIGHT; } void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; } void setClickedCallback( boost::function<void (void*)> cb, void* userdata = NULL ){ mClickedCallback = boost::bind(cb, userdata); } // mouse down and up within button @@ -145,9 +143,8 @@ private: BOOL mUseEllipses; S32 mLineSpacing; + S32 mBlockSpasing; - S32 mHPad; - S32 mVPad; LLFontGL::HAlign mHAlign; LLFontGL::VAlign mVAlign; diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index bfa4e06d2e..f71ea9f8ad 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -428,9 +428,11 @@ LLChicletPanel::Params::Params() , scrolling_offset("scrolling_offset") , left_scroll_button("left_scroll_button") , right_scroll_button("right_scroll_button") +, min_width("min_width") { chiclet_padding = 3; scrolling_offset = 40; + min_width = 70; LLRect scroll_button_rect(0, 25, 19, 5); @@ -458,6 +460,8 @@ LLChicletPanel::LLChicletPanel(const Params&p) , mRightScrollButton(NULL) , mChicletPadding(p.chiclet_padding) , mScrollingOffset(p.scrolling_offset) +, mMinWidth(p.min_width) +, mShowControls(true) { LLButton::Params scroll_button_params = p.left_scroll_button; @@ -660,6 +664,9 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent ) mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD, height + 7, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0)); + mShowControls = width > mMinWidth; + mScrollArea->setVisible(mShowControls); + trimChiclets(); showScrollButtonsIfNeeded(); @@ -719,7 +726,7 @@ void LLChicletPanel::showScrollButtonsIfNeeded() mLeftScrollButton->setEnabled(can_scroll_left); mRightScrollButton->setEnabled(can_scroll_right); - bool show_scroll_buttons = can_scroll_left || can_scroll_right; + bool show_scroll_buttons = (can_scroll_left || can_scroll_right) && mShowControls; mLeftScrollButton->setVisible(show_scroll_buttons); mRightScrollButton->setVisible(show_scroll_buttons); @@ -950,6 +957,11 @@ void LLTalkButton::draw() LLUICtrl::draw(); } +void LLTalkButton::setSpeakBtnToggleState(bool state) +{ + mSpeakBtn->setToggleState(state); +} + void LLTalkButton::onClick_SpeakBtn() { bool speaking = mSpeakBtn->getToggleState(); @@ -1012,7 +1024,14 @@ void LLChicletNotificationCounterCtrl::setCounter(S32 counter) std::stringstream stream; stream << getCounter(); - setText(stream.str()); + if(mCounter != 0) + { + setText(stream.str()); + } + else + { + setText(std::string("")); + } } LLRect LLChicletNotificationCounterCtrl::getRequiredRect() diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 415ae59ca2..c20c81e052 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -390,6 +390,8 @@ public: Optional<LLButton::Params> left_scroll_button, right_scroll_button; + Optional<S32> min_width; + Params(); }; @@ -558,6 +560,8 @@ protected: S32 mChicletPadding; S32 mScrollingOffset; + S32 mMinWidth; + bool mShowControls; }; /* @@ -580,6 +584,7 @@ public: /*virtual*/ ~LLTalkButton(); /*virtual*/ void draw(); + void setSpeakBtnToggleState(bool state); protected: friend class LLUICtrlFactory; diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 00d4f80054..72bfac70fc 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -216,6 +216,8 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width) } } + bool recreate_buttons = true; + // If inventory items are not changed up to mFirstDropDownItem, no need to recreate them if (mFirstDropDownItem == first_drop_down_item && (mItemNamesCache.size() == count || mItemNamesCache.size() == mFirstDropDownItem)) { @@ -229,97 +231,113 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width) } if (i == mFirstDropDownItem) { - // Chevron button should stay right aligned - LLView *chevron_button = getChildView(std::string(">>"), FALSE, FALSE); - if (chevron_button) + recreate_buttons = false; + } + } + + if (recreate_buttons) + { + mFirstDropDownItem = first_drop_down_item; + + mItemNamesCache.clear(); + for (S32 i = 0; i < mFirstDropDownItem; i++) + { + mItemNamesCache.put(items.get(i)->getName()); + } + + // Rebuild the buttons only + // child_list_t is a linked list, so safe to erase from the middle if we pre-incrament the iterator + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ) + { + child_list_const_iter_t cur_it = child_it++; + LLView* viewp = *cur_it; + LLButton* button = dynamic_cast<LLButton*>(viewp); + if (button) { - LLRect rect; - rect.setOriginAndSize(bar_width - chevron_button_width - buttonHGap, buttonVGap, chevron_button_width, getRect().getHeight()-buttonVGap); - chevron_button->setRect(rect); - mChevronRect = rect; + removeChild(button); + delete button; } - return; } - } - mFirstDropDownItem = first_drop_down_item; + // Adding buttons + for(S32 i = mFirstDropDownItem -1; i >= 0; i--) + { - mItemNamesCache.clear(); - for (S32 i = 0; i < mFirstDropDownItem; i++) - { - mItemNamesCache.put(items.get(i)->getName()); - } + LLInventoryItem* item = items.get(i); - // Rebuild the buttons only - // child_list_t is a linked list, so safe to erase from the middle if we pre-incrament the iterator - for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ) - { - child_list_const_iter_t cur_it = child_it++; - LLView* viewp = *cur_it; - LLButton* button = dynamic_cast<LLButton*>(viewp); - if (button) - { - removeChild(button); - delete button; - } - } - - // Adding buttons - for(S32 i = 0; i < mFirstDropDownItem; i++) - { - - LLInventoryItem* item = items.get(i); - - S32 buttonWidth = mFont->getWidth(item->getName()) + buttonHPad * 2; - - LLRect rect; - rect.setOriginAndSize(curr_x, buttonVGap, buttonWidth, getRect().getHeight()-buttonVGap); - - LLButton::Params bparams; - bparams.image_unselected.name(flat_icon); - bparams.image_disabled.name(flat_icon); - bparams.image_selected.name(hover_icon_selected); - bparams.image_hover_selected.name(hover_icon_selected); - bparams.image_disabled_selected.name(hover_icon_selected); - bparams.image_hover_unselected.name(hover_icon); - bparams.follows.flags (FOLLOWS_LEFT | FOLLOWS_BOTTOM); - bparams.rect (rect); - bparams.tab_stop(false); - bparams.font(mFont); - bparams.name(item->getName()); - bparams.tool_tip(item->getName()); - bparams.click_callback.function(boost::bind(&LLFavoritesBarCtrl::onButtonClick, this, item->getUUID())); - bparams.rightclick_callback.function(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this, item->getUUID())); - - addChildInBack(LLUICtrlFactory::create<LLButton> (bparams)); - - curr_x += buttonWidth + buttonHGap; + S32 buttonWidth = mFont->getWidth(item->getName()) + buttonHPad * 2; + + LLRect rect; + rect.setOriginAndSize(curr_x, buttonVGap, buttonWidth, getRect().getHeight()-buttonVGap); + + LLButton::Params bparams; + bparams.image_unselected.name(flat_icon); + bparams.image_disabled.name(flat_icon); + bparams.image_selected.name(hover_icon_selected); + bparams.image_hover_selected.name(hover_icon_selected); + bparams.image_disabled_selected.name(hover_icon_selected); + bparams.image_hover_unselected.name(hover_icon); + bparams.follows.flags (FOLLOWS_LEFT | FOLLOWS_BOTTOM); + bparams.rect (rect); + bparams.tab_stop(false); + bparams.font(mFont); + bparams.name(item->getName()); + bparams.tool_tip(item->getName()); + bparams.click_callback.function(boost::bind(&LLFavoritesBarCtrl::onButtonClick, this, item->getUUID())); + bparams.rightclick_callback.function(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this, item->getUUID())); + + addChildInBack(LLUICtrlFactory::create<LLButton> (bparams)); + + curr_x += buttonWidth + buttonHGap; + } } // Chevron button if (mFirstDropDownItem != count) { - LLButton::Params bparams; - - LLRect rect; - rect.setOriginAndSize(bar_width - chevron_button_width - buttonHGap, buttonVGap, chevron_button_width, getRect().getHeight()-buttonVGap); - - bparams.follows.flags (FOLLOWS_LEFT | FOLLOWS_BOTTOM); - bparams.image_unselected.name(flat_icon); - bparams.image_disabled.name(flat_icon); - bparams.image_selected.name(hover_icon_selected); - bparams.image_hover_selected.name(hover_icon_selected); - bparams.image_disabled_selected.name(hover_icon_selected); - bparams.image_hover_unselected.name(hover_icon); - bparams.rect (rect); - bparams.tab_stop(false); - bparams.font(mFont); - bparams.name(">>"); - bparams.click_callback.function(boost::bind(&LLFavoritesBarCtrl::showDropDownMenu, this)); - - addChildInBack(LLUICtrlFactory::create<LLButton> (bparams)); - - mChevronRect = rect; + // Chevron button should stay right aligned + LLView *chevron_button = getChildView(std::string(">>"), FALSE, FALSE); + if (chevron_button) + { + LLRect rect; + rect.setOriginAndSize(bar_width - chevron_button_width - buttonHGap, buttonVGap, chevron_button_width, getRect().getHeight()-buttonVGap); + chevron_button->setRect(rect); + chevron_button->setVisible(TRUE); + mChevronRect = rect; + } + else + { + LLButton::Params bparams; + + LLRect rect; + rect.setOriginAndSize(bar_width - chevron_button_width - buttonHGap, buttonVGap, chevron_button_width, getRect().getHeight()-buttonVGap); + + bparams.follows.flags (FOLLOWS_LEFT | FOLLOWS_BOTTOM); + bparams.image_unselected.name(flat_icon); + bparams.image_disabled.name(flat_icon); + bparams.image_selected.name(hover_icon_selected); + bparams.image_hover_selected.name(hover_icon_selected); + bparams.image_disabled_selected.name(hover_icon_selected); + bparams.image_hover_unselected.name(hover_icon); + bparams.rect (rect); + bparams.tab_stop(false); + bparams.font(mFont); + bparams.name(">>"); + bparams.click_callback.function(boost::bind(&LLFavoritesBarCtrl::showDropDownMenu, this)); + + addChildInBack(LLUICtrlFactory::create<LLButton> (bparams)); + + mChevronRect = rect; + } + } + else + { + // Hide chevron button if all items are visible on bar + LLView *chevron_button = getChildView(std::string(">>"), FALSE, FALSE); + if (chevron_button) + { + chevron_button->setVisible(FALSE); + } } } @@ -444,6 +462,7 @@ void LLFavoritesBarCtrl::showDropDownMenu() item_params.label(item_name); item_params.on_click.function(boost::bind(&LLFavoritesBarCtrl::onButtonClick, this, item->getUUID())); + item_params.rightclick_callback.function(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this, item->getUUID())); LLMenuItemCallGL *menu_item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params); diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp index aba2402b0c..6cae4b8abc 100644 --- a/indra/newview/llfloaterbuy.cpp +++ b/indra/newview/llfloaterbuy.cpp @@ -276,7 +276,7 @@ void LLFloaterBuy::inventoryChanged(LLViewerObject* obj, std::string text = obj->getName(); if (!(next_owner_mask & PERM_COPY)) { - text.append(getString("no_copy")); + text.append(LLTrans::getString("no_copy")); } if (!(next_owner_mask & PERM_MODIFY)) { diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 8ec9eac196..eb2c6768f3 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -56,7 +56,7 @@ #include "llviewermessage.h" #include "llvoavatarself.h" #include "llviewerstats.h" -#include "llbottomtray.h" +#include "llnearbychatbar.h" LLGestureManager gGestureManager; @@ -871,7 +871,7 @@ void LLGestureManager::runStep(LLMultiGesture* gesture, LLGestureStep* step) const BOOL animate = FALSE; - LLBottomTray::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); + LLNearbyChatBar::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); gesture->mCurrentStep++; break; diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 85da2eb2e3..278fd5b9f6 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -42,6 +42,12 @@ static LLDefaultChildRegistry::Register<LLGroupList> r("group_list"); +LLGroupList::Params::Params() +{ + // Prevent the active group from being always first in the list. + online_go_first = false; +} + LLGroupList::LLGroupList(const Params& p) : LLAvatarList(p) { diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index a246650822..e893313f4b 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -44,6 +44,7 @@ class LLGroupList: public LLAvatarList public: struct Params : public LLInitParam::Block<Params, LLAvatarList::Params> { + Params(); }; LLGroupList(const Params&); diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp new file mode 100644 index 0000000000..b51064f226 --- /dev/null +++ b/indra/newview/lllandmarkactions.cpp @@ -0,0 +1,141 @@ +/** +* @file lllandmarkactions.cpp +* @brief LLLandmarkActions class implementation +* +* $LicenseInfo:firstyear=2001&license=viewergpl$ +* +* Copyright (c) 2001-2009, Linden Research, Inc. +* +* Second Life Viewer Source Code +* The source code in this file ("Source Code") is provided by Linden Lab +* to you under the terms of the GNU General Public License, version 2.0 +* ("GPL"), unless you have obtained a separate licensing agreement +* ("Other License"), formally executed by you and Linden Lab. Terms of +* the GPL can be found in doc/GPL-license.txt in this distribution, or +* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +* +* There are special exceptions to the terms and conditions of the GPL as +* it is applied to this Source Code. View the full text of the exception +* in the file doc/FLOSS-exception.txt in this software distribution, or +* online at +* http://secondlifegrid.net/programs/open_source/licensing/flossexception +* +* By copying, modifying or distributing this software, you acknowledge +* that you have read and understood your obligations described above, +* and agree to abide by those obligations. +* +* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +* COMPLETENESS OR PERFORMANCE. +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" +#include "lllandmarkactions.h" + +#include "llagent.h" +#include "llinventory.h" +#include "llinventorymodel.h" +#include "lllandmark.h" +#include "lllandmarklist.h" +#include "llnotifications.h" +#include "llparcel.h" +#include "llviewerinventory.h" +#include "llviewerparcelmgr.h" +#include "roles_constants.h" + +// Returns true if the given inventory item is a landmark pointing to the current parcel. +// Used to filter inventory items. +class LLIsAgentParcelLandmark : public LLInventoryCollectFunctor +{ +public: + /*virtual*/ bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) + { + if (!item || item->getType() != LLAssetType::AT_LANDMARK) + return false; + + LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID()); + if (!landmark) // the landmark not been loaded yet + return false; + + LLVector3d landmark_global_pos; + if (!landmark->getGlobalPos(landmark_global_pos)) + return false; + + return LLViewerParcelMgr::getInstance()->inAgentParcel(landmark_global_pos); + } +}; + +bool LLLandmarkActions::landmarkAlreadyExists() +{ + // Determine whether there are landmarks pointing to the current parcel. + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLIsAgentParcelLandmark is_current_parcel_landmark; + gInventory.collectDescendentsIf(gInventory.getRootFolderID(), + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + is_current_parcel_landmark); + + return !items.empty(); +} + +bool LLLandmarkActions::canCreateLandmarkHere() +{ + LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if(!agent_parcel) + { + llwarns << "No agent region" << llendl; + return false; + } + if (agent_parcel->getAllowLandmark() + || LLViewerParcelMgr::isParcelOwnedByAgent(agent_parcel, GP_LAND_ALLOW_LANDMARK)) + { + return true; + } + + return false; +} + +void LLLandmarkActions::createLandmarkHere( + const std::string& name, + const std::string& desc, + const LLUUID& folder_id) +{ + if(!gAgent.getRegion()) + { + llwarns << "No agent region" << llendl; + return; + } + LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (!agent_parcel) + { + llwarns << "No agent parcel" << llendl; + return; + } + if (!canCreateLandmarkHere()) + { + LLNotifications::instance().add("CannotCreateLandmarkNotOwner"); + return; + } + + create_inventory_item(gAgent.getID(), gAgent.getSessionID(), + folder_id, LLTransactionID::tnull, + name, desc, + LLAssetType::AT_LANDMARK, + LLInventoryType::IT_LANDMARK, + NOT_WEARABLE, PERM_ALL, + NULL); +} + +void LLLandmarkActions::createLandmarkHere() +{ + std::string landmark_name, landmark_desc; + + gAgent.buildLocationString(landmark_name, LLAgent::LOCATION_FORMAT_LANDMARK); + gAgent.buildLocationString(landmark_desc, LLAgent::LOCATION_FORMAT_FULL); + LLUUID folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK); + + createLandmarkHere(landmark_name, landmark_desc, folder_id); +} diff --git a/indra/newview/lllandmarkactions.h b/indra/newview/lllandmarkactions.h new file mode 100644 index 0000000000..e1e94edb75 --- /dev/null +++ b/indra/newview/lllandmarkactions.h @@ -0,0 +1,68 @@ +/** +* @file lllandmarkactions.h +* @brief LLLandmark class declaration +* +* $LicenseInfo:firstyear=2000&license=viewergpl$ +* +* Copyright (c) 2000-2009, Linden Research, Inc. +* +* Second Life Viewer Source Code +* The source code in this file ("Source Code") is provided by Linden Lab +* to you under the terms of the GNU General Public License, version 2.0 +* ("GPL"), unless you have obtained a separate licensing agreement +* ("Other License"), formally executed by you and Linden Lab. Terms of +* the GPL can be found in doc/GPL-license.txt in this distribution, or +* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +* +* There are special exceptions to the terms and conditions of the GPL as +* it is applied to this Source Code. View the full text of the exception +* in the file doc/FLOSS-exception.txt in this software distribution, or +* online at +* http://secondlifegrid.net/programs/open_source/licensing/flossexception +* +* By copying, modifying or distributing this software, you acknowledge +* that you have read and understood your obligations described above, +* and agree to abide by those obligations. +* +* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +* COMPLETENESS OR PERFORMANCE. +* $/LicenseInfo$ +*/ + +#ifndef LL_LLLANDMARKACTIONS_H +#define LL_LLLANDMARKACTIONS_H + +/** +* @brief Provides helper functions to manage landmarks +*/ +class LLLandmarkActions +{ +public: + + /** + * @brief Checks whether landmark exists for current parcel. + */ + static bool landmarkAlreadyExists(); + + /** + * @brief Checks whether agent has rights to create landmark for current parcel. + */ + static bool canCreateLandmarkHere(); + + /** + * @brief Creates landmark for current parcel. + */ + static void createLandmarkHere(); + + /** + * @brief Creates landmark for current parcel. + */ + static void createLandmarkHere( + const std::string& name, + const std::string& desc, + const LLUUID& folder_id); + +}; + +#endif //LL_LLLANDMARKACTIONS_H diff --git a/indra/newview/lllocationhistory.cpp b/indra/newview/lllocationhistory.cpp index ed56e3e195..471a0868bc 100644 --- a/indra/newview/lllocationhistory.cpp +++ b/indra/newview/lllocationhistory.cpp @@ -39,8 +39,7 @@ #include "llui.h" LLLocationHistory::LLLocationHistory() : - mFilename("typed_locations.txt"), - mLoadedCallback(NULL) + mFilename("typed_locations.txt") { } @@ -134,6 +133,5 @@ void LLLocationHistory::load() file.close(); - if (mLoadedCallback) - mLoadedCallback(); + mLoadedSignal(); } diff --git a/indra/newview/lllocationhistory.h b/indra/newview/lllocationhistory.h index b6552c12ca..19032686c1 100644 --- a/indra/newview/lllocationhistory.h +++ b/indra/newview/lllocationhistory.h @@ -46,6 +46,7 @@ class LLLocationHistory: public LLSingleton<LLLocationHistory> public: typedef std::vector<std::string> location_list_t; typedef boost::function<void()> loaded_callback_t; + typedef boost::signals2::signal<void()> loaded_signal_t; LLLocationHistory(); @@ -54,7 +55,7 @@ public: size_t getItemCount() const { return mItems.size(); } const location_list_t& getItems() const { return mItems; } bool getMatchingItems(std::string substring, location_list_t& result) const; - void setLoadedCallback(loaded_callback_t cb) { mLoadedCallback = cb; } + boost::signals2::connection setLoadedCallback(loaded_callback_t cb) { return mLoadedSignal.connect(cb); } void save() const; void load(); @@ -63,7 +64,7 @@ public: private: std::vector<std::string> mItems; std::string mFilename; /// File to store the history to. - loaded_callback_t mLoadedCallback; + loaded_signal_t mLoadedSignal; }; #endif diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 99f6823ba1..94abd128c4 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -48,6 +48,7 @@ #include "llagent.h" #include "llfloaterland.h" #include "llinventorymodel.h" +#include "lllandmarkactions.h" #include "lllandmarklist.h" #include "lllocationhistory.h" #include "llsidetray.h" @@ -83,28 +84,6 @@ * and choose the appropriate image for the "Add landmark" button. */ -// Returns true if the given inventory item is a landmark pointing to the current parcel. -// Used to filter inventory items. -class LLIsAgentParcelLandmark : public LLInventoryCollectFunctor -{ -public: - /*virtual*/ bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) - { - if (!item || item->getType() != LLAssetType::AT_LANDMARK) - return false; - - LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID()); - if (!landmark) // the landmark not been loaded yet - return false; - - LLVector3d landmark_global_pos; - if (!landmark->getGlobalPos(landmark_global_pos)) - return false; - - return LLViewerParcelMgr::getInstance()->inAgentParcel(landmark_global_pos); - } -}; - /** * Initiates loading the landmarks that have been just added. * @@ -213,10 +192,10 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p) // - Make the "Add landmark" button updated when either current parcel gets changed // or a landmark gets created or removed from the inventory. // - Update the location string on parcel change. - LLViewerParcelMgr::getInstance()->setAgentParcelChangedCallback( + mParcelMgrConnection = LLViewerParcelMgr::getInstance()->setAgentParcelChangedCallback( boost::bind(&LLLocationInputCtrl::onAgentParcelChange, this)); - LLLocationHistory::getInstance()->setLoadedCallback( + mLocationHistoryConnection = LLLocationHistory::getInstance()->setLoadedCallback( boost::bind(&LLLocationInputCtrl::onLocationHistoryLoaded, this)); mRemoveLandmarkObserver = new LLRemoveLandmarkObserver(this); @@ -231,6 +210,9 @@ LLLocationInputCtrl::~LLLocationInputCtrl() gInventory.removeObserver(mAddLandmarkObserver); delete mRemoveLandmarkObserver; delete mAddLandmarkObserver; + + mParcelMgrConnection.disconnect(); + mLocationHistoryConnection.disconnect(); } void LLLocationInputCtrl::setEnabled(BOOL enabled) @@ -356,6 +338,10 @@ void LLLocationInputCtrl::onInfoButtonClicked() void LLLocationInputCtrl::onAddLandmarkButtonClicked() { + LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark")); + + // Floater "Add Landmark" functionality moved to Side Tray + // TODO* Disable floater "Add Landmark" call LLFloaterReg::showInstance("add_landmark"); } @@ -450,19 +436,7 @@ void LLLocationInputCtrl::enableAddLandmarkButton(bool val) // depending on whether current parcel has been landmarked. void LLLocationInputCtrl::updateAddLandmarkButton() { - bool cur_parcel_landmarked = false; - // Determine whether there are landmarks pointing to the current parcel. - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLIsAgentParcelLandmark is_current_parcel_landmark; - gInventory.collectDescendentsIf(gInventory.getRootFolderID(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - is_current_parcel_landmark); - cur_parcel_landmarked = !items.empty(); - - enableAddLandmarkButton(!cur_parcel_landmarked); + enableAddLandmarkButton(!LLLandmarkActions::landmarkAlreadyExists()); } void LLLocationInputCtrl::updateWidgetlayout() diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h index 0a863f6dd8..2cc63a33b7 100644 --- a/indra/newview/lllocationinputctrl.h +++ b/indra/newview/lllocationinputctrl.h @@ -112,6 +112,9 @@ private: LLAddLandmarkObserver* mAddLandmarkObserver; LLRemoveLandmarkObserver* mRemoveLandmarkObserver; + + boost::signals2::connection mParcelMgrConnection; + boost::signals2::connection mLocationHistoryConnection; }; #endif diff --git a/indra/newview/llmenucommands.cpp b/indra/newview/llmenucommands.cpp index cfcb331912..efa15e05da 100644 --- a/indra/newview/llmenucommands.cpp +++ b/indra/newview/llmenucommands.cpp @@ -67,7 +67,7 @@ #include "llworld.h" #include "llworldmap.h" #include "llfocusmgr.h" -#include "llbottomtray.h" +#include "llnearbychatbar.h" void handle_pay_by_id(const LLUUID& agent_id) { @@ -85,13 +85,13 @@ void handle_chat(void*) { // give focus to chatbar if it's open but not focused if (gSavedSettings.getBOOL("ChatVisible") && - gFocusMgr.childHasKeyboardFocus(LLBottomTray::getInstance()->getChatBox())) + gFocusMgr.childHasKeyboardFocus(LLNearbyChatBar::getInstance()->getChatBox())) { - LLBottomTray::stopChat(); + LLNearbyChatBar::stopChat(); } else { - LLBottomTray::startChat(NULL); + LLNearbyChatBar::startChat(NULL); } } @@ -107,5 +107,5 @@ void handle_slash_key(void*) // menu accelerators that put input focus into a field. And Mac works // the same way. JC - LLBottomTray::startChat(NULL); + LLNearbyChatBar::startChat(NULL); } diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index c0bddd101e..58ec2d24a8 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -42,6 +42,7 @@ #include "llagent.h" #include "llfloaterhtmlhelp.h" +#include "lllandmarkactions.h" #include "lllocationhistory.h" #include "lllocationinputctrl.h" #include "llteleporthistory.h" @@ -175,7 +176,6 @@ LLNavigationBar::LLNavigationBar() mBtnBack(NULL), mBtnForward(NULL), mBtnHome(NULL), - mBtnHelp(NULL), mCmbLocation(NULL), mLeSearch(NULL), mPurgeTPHistoryItems(false) @@ -202,12 +202,11 @@ BOOL LLNavigationBar::postBuild() mBtnBack = getChild<LLButton>("back_btn"); mBtnForward = getChild<LLButton>("forward_btn"); mBtnHome = getChild<LLButton>("home_btn"); - mBtnHelp = getChild<LLButton>("help_btn"); mCmbLocation= getChild<LLLocationInputCtrl>("location_combo"); mLeSearch = getChild<LLSearchEditor>("search_input"); - if (!mBtnBack || !mBtnForward || !mBtnHome || !mBtnHelp || + if (!mBtnBack || !mBtnForward || !mBtnHome || !mCmbLocation || !mLeSearch) { llwarns << "Malformed navigation bar" << llendl; @@ -223,7 +222,6 @@ BOOL LLNavigationBar::postBuild() mBtnForward->setHeldDownCallback(boost::bind(&LLNavigationBar::onBackOrForwardButtonHeldDown, this, _2)); mBtnHome->setClickedCallback(boost::bind(&LLNavigationBar::onHomeButtonClicked, this)); - mBtnHelp->setClickedCallback(boost::bind(&LLNavigationBar::onHelpButtonClicked, this)); mCmbLocation->setSelectionCallback(boost::bind(&LLNavigationBar::onLocationSelection, this)); @@ -297,11 +295,6 @@ void LLNavigationBar::onHomeButtonClicked() gAgent.teleportHome(); } -void LLNavigationBar::onHelpButtonClicked() -{ - gViewerHtmlHelp.show(); -} - void LLNavigationBar::onSearchCommit() { invokeSearch(mLeSearch->getValue().asString()); @@ -523,6 +516,10 @@ bool LLNavigationBar::onLocationContextMenuItemEnabled(const LLSD& userdata) { return location_entry->canSelectAll(); } + else if(item == std::string("can_landmark")) + { + return !LLLandmarkActions::landmarkAlreadyExists(); + } return false; } diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h index a82dfc73ff..a46c59306d 100644 --- a/indra/newview/llnavigationbar.h +++ b/indra/newview/llnavigationbar.h @@ -80,7 +80,6 @@ private: void onHelpButtonClicked(); void onLocationSelection(); void onLocationPrearrange(const LLSD& data); - void onLocationHistoryLoaded(); void onSearchCommit(); void onRegionNameResponse( std::string typed_location, @@ -96,7 +95,6 @@ private: LLButton* mBtnBack; LLButton* mBtnForward; LLButton* mBtnHome; - LLButton* mBtnHelp; LLSearchEditor* mLeSearch; LLLocationInputCtrl* mCmbLocation; bool mPurgeTPHistoryItems; diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 411aa72690..847262ddfd 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -36,7 +36,7 @@ #include "llviewercontrol.h" #include "llviewerwindow.h" #include "llrootview.h" -#include "llchatitemscontainerctrl.h" +//#include "llchatitemscontainerctrl.h" #include "lliconctrl.h" #include "llsidetray.h" #include "llfocusmgr.h" @@ -45,6 +45,9 @@ #include "llmenugl.h" #include "llviewermenu.h"//for gMenuHolder +#include "llnearbychathandler.h" +#include "llchannelmanager.h" + static const S32 RESIZE_BAR_THICKNESS = 3; LLNearbyChat::LLNearbyChat(const LLSD& key) : @@ -66,6 +69,11 @@ BOOL LLNearbyChat::postBuild() mResizeBar[LLResizeBar::LEFT]->setVisible(false); mResizeBar[LLResizeBar::RIGHT]->setVisible(false); + mResizeBar[LLResizeBar::BOTTOM]->setResizeLimits(120,500); + mResizeBar[LLResizeBar::TOP]->setResizeLimits(120,500); + mResizeBar[LLResizeBar::LEFT]->setResizeLimits(220,600); + mResizeBar[LLResizeBar::RIGHT]->setResizeLimits(220,600); + mResizeHandle[0]->setVisible(false); mResizeHandle[1]->setVisible(false); mResizeHandle[2]->setVisible(false); @@ -86,24 +94,160 @@ BOOL LLNearbyChat::postBuild() gSavedSettings.declareS32("nearbychat_showicons_and_names",2,"NearByChat header settings",true); + /* LLChatItemsContainerCtrl* panel = getChild<LLChatItemsContainerCtrl>("chat_history",false,false); if(panel) { panel->setHeaderVisibility((EShowItemHeader)gSavedSettings.getS32("nearbychat_showicons_and_names")); } + */ reshape(getRect().getWidth(), getRect().getHeight(), FALSE); return LLFloater::postBuild(); } -void LLNearbyChat::addMessage(const LLChat& message) +#include "llagent.h" // gAgent +#include "llfloaterscriptdebug.h" +#include "llviewertexteditor.h" +#include "llstylemap.h" + +LLColor4 nearbychat_get_text_color(const LLChat& chat) +{ + LLColor4 text_color; + + if(chat.mMuted) + { + text_color.setVec(0.8f, 0.8f, 0.8f, 1.f); + } + else + { + switch(chat.mSourceType) + { + case CHAT_SOURCE_SYSTEM: + text_color = LLUIColorTable::instance().getColor("SystemChatColor"); + break; + case CHAT_SOURCE_AGENT: + if (chat.mFromID.isNull()) + { + text_color = LLUIColorTable::instance().getColor("SystemChatColor"); + } + else + { + if(gAgentID == chat.mFromID) + { + text_color = LLUIColorTable::instance().getColor("UserChatColor"); + } + else + { + text_color = LLUIColorTable::instance().getColor("AgentChatColor"); + } + } + break; + case CHAT_SOURCE_OBJECT: + if (chat.mChatType == CHAT_TYPE_DEBUG_MSG) + { + text_color = LLUIColorTable::instance().getColor("ScriptErrorColor"); + } + else if ( chat.mChatType == CHAT_TYPE_OWNER ) + { + text_color = LLUIColorTable::instance().getColor("llOwnerSayChatColor"); + } + else + { + text_color = LLUIColorTable::instance().getColor("ObjectChatColor"); + } + break; + default: + text_color.setToWhite(); + } + + if (!chat.mPosAgent.isExactlyZero()) + { + LLVector3 pos_agent = gAgent.getPositionAgent(); + F32 distance = dist_vec(pos_agent, chat.mPosAgent); + if (distance > gAgent.getNearChatRadius()) + { + // diminish far-off chat + text_color.mV[VALPHA] = 0.8f; + } + } + } + + return text_color; +} + +void nearbychat_add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4& color) +{ + std::string line = chat.mFromName; + line +=": "; + line +=chat.mText; + + bool prepend_newline = true; + if (gSavedSettings.getBOOL("ChatShowTimestamps")) + { + edit->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. + if (chat.mSourceType == CHAT_SOURCE_AGENT && + chat.mFromID != LLUUID::null) + { + chat.mURL = 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() + && (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); + const LLStyleSP &sourceStyle = LLStyleMap::instance().lookup(chat.mFromID,chat.mURL); + edit->appendStyledText(start_line, false, prepend_newline, sourceStyle); + prepend_newline = false; + } + edit->appendColoredText(line, false, prepend_newline, color); +} + + + +void LLNearbyChat::addMessage(const LLChat& chat) { + /* LLChatItemsContainerCtrl* panel = getChild<LLChatItemsContainerCtrl>("chat_history",false,false); if(!panel) return; panel->addMessage(message); + */ + + //"Chat History Editor" !!!!! + + LLColor4 color = nearbychat_get_text_color(chat); + + if (chat.mChatType == CHAT_TYPE_DEBUG_MSG) + { + LLFloaterScriptDebug::addScriptLine(chat.mText, + chat.mFromName, + color, + chat.mFromID); + if (!gSavedSettings.getBOOL("ScriptErrorsAsChat")) + { + return; + } + } + + // could flash the chat button in the status bar here. JC + + LLViewerTextEditor* history_editor = getChild<LLViewerTextEditor>("Chat History Editor"); + + history_editor->setParseHTML(TRUE); + history_editor->setParseHighlights(TRUE); + + if (!chat.mMuted) + nearbychat_add_timestamped_line(history_editor, chat, color); } void LLNearbyChat::onNearbySpeakers() @@ -166,7 +310,9 @@ void LLNearbyChat::reshape(S32 width, S32 height, BOOL called_from_parent) caption->setRect(caption_rect); } - LLPanel* scroll_panel = getChild<LLPanel>("chat_history",false,false); + //LLPanel* scroll_panel = getChild<LLPanel>("chat_history",false,false); + LLViewerTextEditor* scroll_panel = getChild<LLViewerTextEditor>("Chat History Editor"); + if (scroll_panel) { LLRect scroll_rect = scroll_panel->getRect(); @@ -305,10 +451,13 @@ void LLNearbyChat::float_panel() mResizeBar[LLResizeBar::BOTTOM]->setVisible(true); mResizeBar[LLResizeBar::LEFT]->setVisible(true); mResizeBar[LLResizeBar::RIGHT]->setVisible(true); + + translate(4,4); } void LLNearbyChat::onNearbyChatContextMenuItemClicked(const LLSD& userdata) { + /* LLChatItemsContainerCtrl* panel = getChild<LLChatItemsContainerCtrl>("chat_history",false,false); if(!panel) return; @@ -322,15 +471,18 @@ void LLNearbyChat::onNearbyChatContextMenuItemClicked(const LLSD& userdata) panel->setHeaderVisibility(CHATITEMHEADER_SHOW_BOTH); gSavedSettings.setS32("nearbychat_showicons_and_names", (S32)panel->getHeaderVisibility()); - - + */ } bool LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata) { + std::string str = userdata.asString(); + if(str == "nearby_people") + onNearbySpeakers(); + /* LLChatItemsContainerCtrl* panel = getChild<LLChatItemsContainerCtrl>("chat_history",false,false); if(!panel) return false; - std::string str = userdata.asString(); + if(str == "show_buddy_icons") return panel->getHeaderVisibility() == CHATITEMHEADER_SHOW_ONLY_ICON; else if(str == "show_names") @@ -339,6 +491,7 @@ bool LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata) return panel->getHeaderVisibility() == CHATITEMHEADER_SHOW_BOTH; else if(str == "nearby_people") onNearbySpeakers(); + */ return false; } @@ -360,3 +513,11 @@ BOOL LLNearbyChat::handleRightMouseDown(S32 x, S32 y, MASK mask) return LLFloater::handleRightMouseDown(x, y, mask); } +void LLNearbyChat::onOpen(const LLSD& key ) +{ + LLNotificationsUI::LLScreenChannel* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->getChannelByID(LLUUID(NEARBY_CHAT_ID)); + if(chat_channel) + { + chat_channel->removeToastsFromChannel(); + } +} diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 61ff8890ea..74e3710f40 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -77,8 +77,10 @@ public: void onNearbyChatContextMenuItemClicked(const LLSD& userdata); bool onNearbyChatCheckContextMenuItem(const LLSD& userdata); - virtual void onClose(bool app_quitting) { if(app_quitting) destroy(); else setVisible(false); } - + virtual void onClose (bool app_quitting) { if(app_quitting) destroy(); else setVisible(false); } + + virtual void onOpen (const LLSD& key); + private: void pinn_panel(); diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp new file mode 100644 index 0000000000..7b67ae645c --- /dev/null +++ b/indra/newview/llnearbychatbar.cpp @@ -0,0 +1,549 @@ +/** + * @file llnearbychatbar.cpp + * @brief LLNearbyChatBar class implementation + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llnearbychatbar.h" +#include "llbottomtray.h" +#include "llagent.h" +#include "llgesturemgr.h" +#include "llmultigesture.h" +#include "llkeyboard.h" +#include "llanimationstates.h" +#include "llviewerstats.h" +#include "llcommandhandler.h" +#include "llviewercontrol.h" + +S32 LLNearbyChatBar::sLastSpecialChatChannel = 0; + +// legacy calllback glue +void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); + +static LLDefaultChildRegistry::Register<LLGestureComboBox> r("gesture_combo_box"); + +LLGestureComboBox::LLGestureComboBox(const LLComboBox::Params& p) + : LLComboBox(p) + , mGestureLabelTimer() + , mLabel(p.label) +{ + setCommitCallback(boost::bind(&LLGestureComboBox::onCommitGesture, this, _1)); + + // now register us as observer since we have a place to put the results + gGestureManager.addObserver(this); + + // refresh list from current active gestures + refreshGestures(); +} + +LLGestureComboBox::~LLGestureComboBox() +{ + gGestureManager.removeObserver(this); +} + +void LLGestureComboBox::refreshGestures() +{ + //store current selection so we can maintain it + std::string cur_gesture = getValue().asString(); + selectFirstItem(); + // clear + clearRows(); + + // collect list of unique gestures + std::map <std::string, BOOL> unique; + LLGestureManager::item_map_t::iterator it; + for (it = gGestureManager.mActive.begin(); it != gGestureManager.mActive.end(); ++it) + { + LLMultiGesture* gesture = (*it).second; + if (gesture) + { + if (!gesture->mTrigger.empty()) + { + unique[gesture->mTrigger] = TRUE; + } + } + } + + // add unique gestures + std::map <std::string, BOOL>::iterator it2; + for (it2 = unique.begin(); it2 != unique.end(); ++it2) + { + addSimpleElement((*it2).first); + } + + sortByName(); + // Insert label after sorting, at top, with separator below it + addSeparator(ADD_TOP); + addSimpleElement(mLabel, ADD_TOP); + + if (!cur_gesture.empty()) + { + selectByValue(LLSD(cur_gesture)); + } + else + { + selectFirstItem(); + } +} + +void LLGestureComboBox::onCommitGesture(LLUICtrl* ctrl) +{ + LLCtrlListInterface* gestures = getListInterface(); + if (gestures) + { + S32 index = gestures->getFirstSelectedIndex(); + if (index == 0) + { + return; + } + const std::string& trigger = gestures->getSelectedValue().asString(); + + // pretend the user chatted the trigger string, to invoke + // substitution and logging. + std::string text(trigger); + std::string revised_text; + gGestureManager.triggerAndReviseString(text, &revised_text); + + revised_text = utf8str_trim(revised_text); + if (!revised_text.empty()) + { + // Don't play nodding animation + LLNearbyChatBar::sendChatFromViewer(revised_text, CHAT_TYPE_NORMAL, FALSE); + } + } + + mGestureLabelTimer.start(); + // free focus back to chat bar + setFocus(FALSE); +} + +//virtual +void LLGestureComboBox::draw() +{ + // HACK: Leave the name of the gesture in place for a few seconds. + const F32 SHOW_GESTURE_NAME_TIME = 2.f; + if (mGestureLabelTimer.getStarted() && mGestureLabelTimer.getElapsedTimeF32() > SHOW_GESTURE_NAME_TIME) + { + LLCtrlListInterface* gestures = getListInterface(); + if (gestures) gestures->selectFirstItem(); + mGestureLabelTimer.stop(); + } + + LLComboBox::draw(); +} + +LLNearbyChatBar::LLNearbyChatBar() + : LLPanel() + , mChatBox(NULL) +{ +} + +//virtual +BOOL LLNearbyChatBar::postBuild() +{ + mChatBox = getChild<LLLineEditor>("chat_box",TRUE,FALSE); + + if (mChatBox) + { + mChatBox->setCommitCallback(boost::bind(&LLNearbyChatBar::onChatBoxCommit, this)); + mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this); + mChatBox->setFocusLostCallback(&onChatBoxFocusLost, this); + + mChatBox->setIgnoreArrowKeys(TRUE); + mChatBox->setCommitOnFocusLost( FALSE ); + mChatBox->setRevertOnEsc( FALSE ); + mChatBox->setIgnoreTab(TRUE); + mChatBox->setPassDelete(TRUE); + mChatBox->setReplaceNewlinesWithSpaces(FALSE); + mChatBox->setMaxTextLength(1023); + mChatBox->setEnableLineHistory(TRUE); + } + + mTalkBtn = getChild<LLTalkButton>("talk",TRUE,FALSE); + + return TRUE; +} + +//static +LLNearbyChatBar* LLNearbyChatBar::getInstance() +{ + return LLBottomTray::getInstance() ? LLBottomTray::getInstance()->getNearbyChatBar() : NULL; +} + +std::string LLNearbyChatBar::getCurrentChat() +{ + return mChatBox ? mChatBox->getText() : LLStringUtil::null; +} + +// virtual +BOOL LLNearbyChatBar::handleKeyHere( KEY key, MASK mask ) +{ + BOOL handled = FALSE; + + // ALT-RETURN is reserved for windowed/fullscreen toggle + if( KEY_RETURN == key && mask == MASK_CONTROL) + { + // shout + sendChat(CHAT_TYPE_SHOUT); + handled = TRUE; + } + + return handled; +} + +void LLNearbyChatBar::onChatBoxKeystroke(LLLineEditor* caller, void* userdata) +{ + LLNearbyChatBar* self = (LLNearbyChatBar *)userdata; + + LLWString raw_text; + if (self->mChatBox) raw_text = self->mChatBox->getWText(); + + // Can't trim the end, because that will cause autocompletion + // to eat trailing spaces that might be part of a gesture. + LLWStringUtil::trimHead(raw_text); + + S32 length = raw_text.length(); + + if( (length > 0) && (raw_text[0] != '/') ) // forward slash is used for escape (eg. emote) sequences + { + gAgent.startTyping(); + } + else + { + gAgent.stopTyping(); + } + + /* Doesn't work -- can't tell the difference between a backspace + that killed the selection vs. backspace at the end of line. + if (length > 1 + && text[0] == '/' + && key == KEY_BACKSPACE) + { + // the selection will already be deleted, but we need to trim + // off the character before + std::string new_text = raw_text.substr(0, length-1); + self->mInputEditor->setText( new_text ); + self->mInputEditor->setCursorToEnd(); + length = length - 1; + } + */ + + KEY key = gKeyboard->currentKey(); + + // Ignore "special" keys, like backspace, arrows, etc. + if (length > 1 + && raw_text[0] == '/' + && key < KEY_SPECIAL) + { + // we're starting a gesture, attempt to autocomplete + + std::string utf8_trigger = wstring_to_utf8str(raw_text); + std::string utf8_out_str(utf8_trigger); + + if (gGestureManager.matchPrefix(utf8_trigger, &utf8_out_str)) + { + if (self->mChatBox) + { + std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); + self->mChatBox->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part + S32 outlength = self->mChatBox->getLength(); // in characters + + // Select to end of line, starting from the character + // after the last one the user typed. + self->mChatBox->setSelection(length, outlength); + } + } + + //llinfos << "GESTUREDEBUG " << trigger + // << " len " << length + // << " outlen " << out_str.getLength() + // << llendl; + } +} + +// static +void LLNearbyChatBar::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata) +{ + // stop typing animation + gAgent.stopTyping(); +} + +void LLNearbyChatBar::sendChat( EChatType type ) +{ + if (mChatBox) + { + LLWString text = mChatBox->getConvertedText(); + if (!text.empty()) + { + // store sent line in history, duplicates will get filtered + mChatBox->updateHistory(); + // Check if this is destined for another channel + S32 channel = 0; + stripChannelNumber(text, &channel); + + std::string utf8text = wstring_to_utf8str(text); + // Try to trigger a gesture, if not chat to a script. + std::string utf8_revised_text; + if (0 == channel) + { + // discard returned "found" boolean + gGestureManager.triggerAndReviseString(utf8text, &utf8_revised_text); + } + else + { + utf8_revised_text = utf8text; + } + + utf8_revised_text = utf8str_trim(utf8_revised_text); + + if (!utf8_revised_text.empty()) + { + // Chat with animation + sendChatFromViewer(utf8_revised_text, type, TRUE); + } + } + + mChatBox->setText(LLStringExplicit("")); + } + + gAgent.stopTyping(); + + // If the user wants to stop chatting on hitting return, lose focus + // and go out of chat mode. + if (gSavedSettings.getBOOL("CloseChatOnReturn")) + { + stopChat(); + } +} + +void LLNearbyChatBar::onChatBoxCommit() +{ + if (mChatBox && mChatBox->getText().length() > 0) + { + sendChat(CHAT_TYPE_NORMAL); + } + + gAgent.stopTyping(); +} + +void LLNearbyChatBar::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate) +{ + sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate); +} + +void LLNearbyChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate) +{ + // Look for "/20 foo" channel chats. + S32 channel = 0; + LLWString out_text = stripChannelNumber(wtext, &channel); + std::string utf8_out_text = wstring_to_utf8str(out_text); + std::string utf8_text = wstring_to_utf8str(wtext); + + utf8_text = utf8str_trim(utf8_text); + if (!utf8_text.empty()) + { + utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1); + } + + // Don't animate for chats people can't hear (chat to scripts) + if (animate && (channel == 0)) + { + if (type == CHAT_TYPE_WHISPER) + { + lldebugs << "You whisper " << utf8_text << llendl; + gAgent.sendAnimationRequest(ANIM_AGENT_WHISPER, ANIM_REQUEST_START); + } + else if (type == CHAT_TYPE_NORMAL) + { + lldebugs << "You say " << utf8_text << llendl; + gAgent.sendAnimationRequest(ANIM_AGENT_TALK, ANIM_REQUEST_START); + } + else if (type == CHAT_TYPE_SHOUT) + { + lldebugs << "You shout " << utf8_text << llendl; + gAgent.sendAnimationRequest(ANIM_AGENT_SHOUT, ANIM_REQUEST_START); + } + else + { + llinfos << "send_chat_from_viewer() - invalid volume" << llendl; + return; + } + } + else + { + if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP) + { + lldebugs << "Channel chat: " << utf8_text << llendl; + } + } + + send_chat_from_viewer(utf8_out_text, type, channel); +} + +// static +void LLNearbyChatBar::startChat(const char* line) +{ + LLBottomTray *bt = LLBottomTray::getInstance(); + + if (!bt) + return; + + LLNearbyChatBar* cb = bt->getNearbyChatBar(); + + if (!cb || !cb->mChatBox) + return; + + bt->setVisible(TRUE); + cb->mChatBox->setFocus(TRUE); + + if (line) + { + std::string line_string(line); + cb->mChatBox->setText(line_string); + } + + cb->mChatBox->setCursorToEnd(); +} + +// Exit "chat mode" and do the appropriate focus changes +// static +void LLNearbyChatBar::stopChat() +{ + LLBottomTray *bt = LLBottomTray::getInstance(); + + if (!bt) + return; + + LLNearbyChatBar* cb = bt->getNearbyChatBar(); + + if (!cb || !cb->mChatBox) + return; + + cb->mChatBox->setFocus(FALSE); + + // stop typing animation + gAgent.stopTyping(); +} + +// If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20. +// Otherwise returns input and channel 0. +LLWString LLNearbyChatBar::stripChannelNumber(const LLWString &mesg, S32* channel) +{ + if (mesg[0] == '/' + && mesg[1] == '/') + { + // This is a "repeat channel send" + *channel = sLastSpecialChatChannel; + return mesg.substr(2, mesg.length() - 2); + } + else if (mesg[0] == '/' + && mesg[1] + && LLStringOps::isDigit(mesg[1])) + { + // This a special "/20" speak on a channel + S32 pos = 0; + + // Copy the channel number into a string + LLWString channel_string; + llwchar c; + do + { + c = mesg[pos+1]; + channel_string.push_back(c); + pos++; + } + while(c && pos < 64 && LLStringOps::isDigit(c)); + + // Move the pointer forward to the first non-whitespace char + // Check isspace before looping, so we can handle "/33foo" + // as well as "/33 foo" + while(c && iswspace(c)) + { + c = mesg[pos+1]; + pos++; + } + + sLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10); + *channel = sLastSpecialChatChannel; + return mesg.substr(pos, mesg.length() - pos); + } + else + { + // This is normal chat. + *channel = 0; + return mesg; + } +} + +void LLNearbyChatBar::setPTTState(bool state) +{ + mTalkBtn->setSpeakBtnToggleState(state); +} + +void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) +{ + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ChatFromViewer); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ChatData); + msg->addStringFast(_PREHASH_Message, utf8_out_text); + msg->addU8Fast(_PREHASH_Type, type); + msg->addS32("Channel", channel); + + gAgent.sendReliableMessage(); + + LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT); +} + +class LLChatHandler : public LLCommandHandler +{ +public: + // not allowed from outside the app + LLChatHandler() : LLCommandHandler("chat", true) { } + + // Your code here + bool handle(const LLSD& tokens, const LLSD& query_map, + LLWebBrowserCtrl* web) + { + if (tokens.size() < 2) return false; + S32 channel = tokens[0].asInteger(); + std::string mesg = tokens[1].asString(); + send_chat_from_viewer(mesg, CHAT_TYPE_NORMAL, channel); + return true; + } +}; + +// Creating the object registers with the dispatcher. +LLChatHandler gChatHandler; + + diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h new file mode 100644 index 0000000000..d1f5fbff6b --- /dev/null +++ b/indra/newview/llnearbychatbar.h @@ -0,0 +1,104 @@ +/** + * @file llnearbychatbar.h + * @brief LLNearbyChatBar class definition + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLNEARBYCHATBAR_H +#define LL_LLNEARBYCHATBAR_H + +#include "llpanel.h" +#include "llcombobox.h" +#include "llgesturemgr.h" +#include "llchat.h" +#include "llchiclet.h" + +class LLGestureComboBox + : public LLComboBox + , public LLGestureManagerObserver +{ +protected: + LLGestureComboBox(const LLComboBox::Params&); + friend class LLUICtrlFactory; +public: + ~LLGestureComboBox(); + + void refreshGestures(); + void onCommitGesture(LLUICtrl* ctrl); + virtual void draw(); + + // LLGestureManagerObserver trigger + virtual void changed() { refreshGestures(); } + +protected: + LLFrameTimer mGestureLabelTimer; + std::string mLabel; +}; + +class LLNearbyChatBar +: public LLPanel +{ +public: + // constructor for inline chat-bars (e.g. hosted in chat history window) + LLNearbyChatBar(); + ~LLNearbyChatBar() {} + + virtual BOOL postBuild(); + + static LLNearbyChatBar* getInstance(); + + LLLineEditor* getChatBox() { return mChatBox; } + + std::string getCurrentChat(); + virtual BOOL handleKeyHere( KEY key, MASK mask ); + + void setPTTState(bool state); + static void startChat(const char* line); + static void stopChat(); + + static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate); + static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); + +protected: + static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata); + static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata); + + void sendChat( EChatType type ); + void onChatBoxCommit(); + + static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); + + // Which non-zero channel did we last chat on? + static S32 sLastSpecialChatChannel; + + LLLineEditor* mChatBox; + LLTalkButton* mTalkBtn; +}; + +#endif diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index ab66421d35..cb1b65a604 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -61,6 +61,7 @@ LLNearbyChatHandler::LLNearbyChatHandler(e_notification_type type, const LLSD& i // Getting a Channel for our notifications mChannel = LLChannelManager::getInstance()->createChannel(p); mChannel->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_TOP); + mChannel->setOverflowFormatString("You have %d unread nearby chat messages"); mChannel->setStoreToasts(false); } LLNearbyChatHandler::~LLNearbyChatHandler() @@ -71,6 +72,9 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg) if(chat_msg.mSourceType == CHAT_SOURCE_AGENT && chat_msg.mFromID.notNull()) LLRecentPeople::instance().add(chat_msg.mFromID); + 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()) @@ -82,7 +86,9 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg) LLChatItemCtrl* item = LLChatItemCtrl::createInstance(); item->setMessage(chat_msg); - item->setWidth(nearby_chat->getRect().getWidth() - 16); + //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")); item->setVisible(true); @@ -91,7 +97,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg) LLToast* toast = mChannel->addToast(id, item); toast->setOnMouseEnterCallback(boost::bind(&LLNearbyChatHandler::onToastDestroy, this, toast)); - toast->setAndStartTimer(10); //TODO: set correct time + toast->setAndStartTimer(gSavedSettings.getS32("NotificationToastTime")); } void LLNearbyChatHandler::onToastDestroy(LLToast* toast) diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index 757a0e5999..06826998bf 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -49,7 +49,7 @@ LLAlertHandler::LLAlertHandler(e_notification_type type, const LLSD& id) : mIsMo LLBottomTray* tray = LLBottomTray::getInstance(); LLChannelManager::Params p; - p.id = LLUUID("F3E07BC8-A973-476D-8C7F-F3B7293975D1"); + p.id = LLUUID(ALERT_CHANNEL_ID); p.channel_right_bound = tray->getRect().getWidth() / 2; p.channel_width = 0; p.align = NA_CENTRE; diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index cde7efe901..ad09f43c10 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -50,7 +50,7 @@ LLGroupHandler::LLGroupHandler(e_notification_type type, const LLSD& id) mChiclet = tray->getSysWell(); LLChannelManager::Params p; p.chiclet = mChiclet; - p.channel_right_bound = tray->getRect().mRight - 10; //HACK: need to correctly resolve SysWell's position + p.channel_right_bound = tray->getRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); p.channel_width = gSavedSettings.getS32("NotifyBoxWidth"); // Getting a Channel for our notifications @@ -74,7 +74,7 @@ void LLGroupHandler::processNotification(const LLSD& notify) toast = mChannel->addToast(notification->getID(), notify_box); if(!toast) return; - toast->setAndStartTimer(5); + toast->setAndStartTimer(gSavedSettings.getS32("NotificationToastTime")); toast->setOnToastDestroyCallback((boost::bind(&LLGroupHandler::onToastDestroy, this, toast))); mChiclet->setCounter(mChiclet->getCounter() + 1); } diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 7f53809c07..9037fc82ab 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -42,6 +42,8 @@ namespace LLNotificationsUI { +// ID for channel that displays Alert Notifications +#define ALERT_CHANNEL_ID "F3E07BC8-A973-476D-8C7F-F3B7293975D1" // ENotificationType enumerates all possible types of notifications that could be met // diff --git a/indra/newview/lloverlaybar.h b/indra/newview/lloverlaybar.h index f0cf480458..ffdbd96f60 100644 --- a/indra/newview/lloverlaybar.h +++ b/indra/newview/lloverlaybar.h @@ -85,7 +85,6 @@ public: protected: static void* createMediaRemote(void* userdata); static void* createVoiceRemote(void* userdata); - static void* createChatBar(void* userdata); void enableMediaButtons(); diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index bf6ecd6bf4..f57489934a 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -340,12 +340,17 @@ void LLPanelAvatarProfile::processProperties(void* data, EAvatarProcessorType ty if(avatar_groups) { std::string groups; - LLAvatarGroups::group_list_t::const_iterator it = avatar_groups->group_list.begin(); - for(; avatar_groups->group_list.end() != it; ++it) - { + if (!avatar_groups->group_list.empty()) { + LLAvatarGroups::group_list_t::const_iterator it = avatar_groups->group_list.begin(); LLAvatarGroups::LLGroupData group_data = *it; - groups += group_data.group_name; - groups += ", "; + groups+= group_data.group_name; + while (++it != avatar_groups->group_list.end()) + { + group_data = *it; + groups += ", "; + groups += group_data.group_name; + + } } childSetValue("sl_groups",groups); } diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 0cbf10f7c2..7bf7ceb6d2 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -200,6 +200,9 @@ void LLLandmarksPanel::onCopySLURL() // virtual void LLLandmarksPanel::updateVerbs() { + if (!isTabVisible()) + return; + BOOL enabled = FALSE; LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem(); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index d947003109..92a8653252 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -436,11 +436,13 @@ bool LLPanelPeople::updateGroupList() bool LLPanelPeople::filterFriendList() { - if (mFriendVec.size() > 0) - return mFriendList->update(mFriendVec, mFilterSubString); + // We must always update Friends list to clear the latest removed friend. + bool have_names = mFriendList->update(mFriendVec, mFilterSubString); - mFriendList->setCommentText(getString("no_friends")); - return true; + if (mFriendVec.size() == 0) + mFriendList->setCommentText(getString("no_friends")); + + return have_names; } bool LLPanelPeople::filterNearbyList() @@ -784,10 +786,22 @@ void LLPanelPeople::onMoreButtonClicked() void LLPanelPeople::onOpen(const LLSD& key) { - std::string tab_name = key.asString(); + // Profile View is activated through LLSideTray::showPanel(), + // hide Profile View to be able to see Panel People content + hideProfileView(); + std::string tab_name = key.asString(); if (!tab_name.empty()) mTabContainer->selectTabByName(tab_name); else reSelectedCurrentTab(); } + +void LLPanelPeople::hideProfileView() +{ + LLView* view = getChildView("panel_profile_view",true,false); + if(view && view->getVisible()) + { + view->setVisible(false); + } +} diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 6c3b5e0664..2ac1bf424c 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -104,6 +104,8 @@ private: const std::vector<LLUUID>& ids, void*); + void hideProfileView(); + LLFilterEditor* mFilterEditor; LLTabContainer* mTabContainer; LLAvatarList* mFriendList; diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index 7bfe94043f..e8d6ff9ec9 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -45,6 +45,7 @@ #include "llpanelavatar.h" #include "llpanelprofile.h" #include "llpanelpick.h" +#include "llscrollcontainer.h" static const std::string XML_BTN_NEW = "new_btn"; static const std::string XML_BTN_DELETE = "trash_btn"; @@ -203,7 +204,7 @@ void LLPanelPicks::reshapePicksList() last_bottom -= childp->getRect().getHeight(); last_bottom -= PICK_ITEMS_BETWEEN; } - reshapePickItem(childp, last_bottom); + reshapePickItem(childp, last_bottom,pickList->getRect().getWidth()); } S32 height = pickList->getChildCount() * ((*child_first_it)->getRect().getHeight() + PICK_ITEMS_BETWEEN); @@ -213,13 +214,13 @@ void LLPanelPicks::reshapePicksList() pickList->setRect(rc); } -void LLPanelPicks::reshapePickItem(LLView* const pick_item, const S32 last_bottom) +void LLPanelPicks::reshapePickItem(LLView* const pick_item, const S32 last_bottom, const S32 newWidth) { LLRect rc = pick_item->getRect(); rc.mBottom = last_bottom - rc.getHeight(); rc.mTop = last_bottom; - pick_item->reshape(rc.getWidth(), rc.getHeight()); pick_item->setRect(rc); + pick_item->reshape(newWidth, rc.getHeight()); } LLView* LLPanelPicks::getPicksList() const @@ -402,7 +403,7 @@ void LLPanelPicks::setSelectedPickItem(LLPickItem* item) BOOL LLPanelPicks::isMouseInPick( S32 x, S32 y ) { - LLView* scroll = getChild<LLView>("profile_scroll"); + LLScrollContainer* scroll = getChild<LLScrollContainer>("profile_scroll"); if (!scroll->parentPointInView(x, y)) return FALSE; S32 x_l = x; diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h index 3bc79daeb3..e0e7f69532 100644 --- a/indra/newview/llpanelpicks.h +++ b/indra/newview/llpanelpicks.h @@ -102,7 +102,7 @@ private: bool callbackTeleport(const LLSD& notification, const LLSD& response); void reshapePicksList(); - void reshapePickItem(LLView* const pick_item, const S32 last_bottom); + void reshapePickItem(LLView* const pick_item, const S32 last_bottom, const S32 newWidth); LLView* getPicksList() const; void updateButtons(); diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index 590eae555e..ea05b666db 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -39,6 +39,7 @@ #include "llsecondlifeurls.h" #include "llinventory.h" +#include "llparcel.h" #include "llqueryflags.h" @@ -52,6 +53,7 @@ #include "llinventorymodel.h" #include "lltexturectrl.h" #include "llviewerinventory.h" +#include "llviewerparcelmgr.h" #include "llviewerregion.h" #include "llviewertexteditor.h" #include "llworldmap.h" @@ -221,6 +223,8 @@ void LLPanelPlaceInfo::resetLocation() mCreated->setText(not_available); mTitleEditor->setText(LLStringUtil::null); mNotesEditor->setText(LLStringUtil::null); + mSnapshotCtrl->setImageAssetID(LLUUID::null); + mSnapshotCtrl->setFallbackImageName("default_land_picture.j2c"); } //virtual @@ -237,6 +241,12 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type) switch(type) { + case CREATE_LANDMARK: + mCurrentTitle = getString("title_create_landmark"); + + toggleMediaPanel(FALSE); + break; + case PLACE: mCurrentTitle = getString("title_place"); @@ -362,21 +372,33 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data) region_z = llround(parcel_data.global_z); } + std::string name; if (!parcel_data.sim_name.empty()) { - std::string name = llformat("%s (%d, %d, %d)", - parcel_data.sim_name.c_str(), region_x, region_y, region_z); + name = llformat("%s (%d, %d, %d)", + parcel_data.sim_name.c_str(), region_x, region_y, region_z); mRegionName->setText(name); } + + if (mCurrentTitle != getString("title_landmark")) + { + mTitleEditor->setText(parcel_data.name + "; " + name); + mNotesEditor->setText(LLStringUtil::null); + } } void LLPanelPlaceInfo::displayParcelInfo(const LLVector3& pos_region, const LLUUID& region_id, const LLVector3d& pos_global) { - LLSD body; mPosRegion = pos_region; - std::string url = gAgent.getRegion()->getCapability("RemoteParcelRequest"); + + LLViewerRegion* region = gAgent.getRegion(); + if (!region) + return; + + LLSD body; + std::string url = region->getCapability("RemoteParcelRequest"); if (!url.empty()) { body["location"] = ll_sd_from_vector3(pos_region); @@ -395,8 +417,29 @@ void LLPanelPlaceInfo::displayParcelInfo(const LLVector3& pos_region, { mDescEditor->setText(getString("server_update_text")); } - mSnapshotCtrl->setImageAssetID(LLUUID::null); - mSnapshotCtrl->setFallbackImageName("default_land_picture.j2c"); +} + +void LLPanelPlaceInfo::displayAgentParcelInfo() +{ + mPosRegion = gAgent.getPositionAgent(); + + LLViewerRegion* region = gAgent.getRegion(); + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (!region || !parcel) + return; + + LLParcelData parcel_data; + parcel_data.desc = parcel->getDesc(); + parcel_data.flags = parcel->getParcelFlags(); + parcel_data.name = parcel->getName(); + parcel_data.sim_name = gAgent.getRegion()->getName(); + parcel_data.snapshot_id = parcel->getSnapshotID(); + LLVector3d global_pos = gAgent.getPositionGlobal(); + parcel_data.global_x = global_pos.mdV[0]; + parcel_data.global_y = global_pos.mdV[1]; + parcel_data.global_z = global_pos.mdV[2]; + + processParcelInfo(parcel_data); } void LLPanelPlaceInfo::onCommitTitleOrNote(LANDMARK_INFO_TYPE type) diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h index 7f98b6cb76..f06a2d1fb7 100644 --- a/indra/newview/llpanelplaceinfo.h +++ b/indra/newview/llpanelplaceinfo.h @@ -55,6 +55,7 @@ class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver public: enum INFO_TYPE { + CREATE_LANDMARK, PLACE, LANDMARK, TELEPORT_HISTORY @@ -84,9 +85,17 @@ public: /*virtual*/ void setErrorStatus(U32 status, const std::string& reason); void sendParcelInfoRequest(); + + // Displays information about a remote parcel. + // Sends a request to the server. void displayParcelInfo(const LLVector3& pos_region, const LLUUID& region_id, const LLVector3d& pos_global); + + // Displays information about the parcel the agent is currently on + // without sending a request to the server. + void displayAgentParcelInfo(); + void nameUpdatedCallback(LLTextBox* text, const std::string& first, const std::string& last); diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 57c633dd74..b443cc4d5e 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -31,13 +31,16 @@ #include "llviewerprecompiledheaders.h" +#include "llassettype.h" + +#include "lllandmark.h" + #include "llfloaterreg.h" +#include "llnotifications.h" #include "llfiltereditor.h" #include "lltabcontainer.h" #include "lluictrlfactory.h" -#include "lllandmark.h" - #include "llagent.h" #include "lllandmarklist.h" #include "llfloaterworldmap.h" @@ -48,18 +51,8 @@ #include "llviewerparcelmgr.h" #include "llviewerregion.h" -LLPanelPlaces::LLParcelUpdateTimer::LLParcelUpdateTimer(F32 period) -: LLEventTimer(period) -{ -}; - -// virtual -BOOL LLPanelPlaces::LLParcelUpdateTimer::tick() -{ - LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "agent")); - - return TRUE; -} +// Helper function to get local position from global +const LLVector3 get_pos_local_from_global(const LLVector3d &pos_global); static LLRegisterPanelClassWrapper<LLPanelPlaces> t_places("panel_places"); @@ -68,7 +61,9 @@ LLPanelPlaces::LLPanelPlaces() mFilterSubString(LLStringUtil::null), mActivePanel(NULL), mFilterEditor(NULL), - mPlaceInfo(NULL) + mPlaceInfo(NULL), + mItem(NULL), + mPosGlobal() { gInventory.addObserver(this); @@ -86,6 +81,17 @@ LLPanelPlaces::~LLPanelPlaces() BOOL LLPanelPlaces::postBuild() { + mTeleportBtn = getChild<LLButton>("teleport_btn"); + mTeleportBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onTeleportButtonClicked, this)); + + mShowOnMapBtn = getChild<LLButton>("map_btn"); + mShowOnMapBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onShowOnMapButtonClicked, this)); + + //mShareBtn = getChild<LLButton>("share_btn"); + //mShareBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onShareButtonClicked, this)); + + mOverflowBtn = getChild<LLButton>("overflow_btn"); + mTabContainer = getChild<LLTabContainer>("Places Tabs"); if (mTabContainer) { @@ -108,13 +114,9 @@ BOOL LLPanelPlaces::postBuild() } // *TODO: Assign the action to an appropriate event. - childSetAction("overflow_btn", boost::bind(&LLPanelPlaces::toggleMediaPanel, this), this); + mOverflowBtn->setClickedCallback(boost::bind(&LLPanelPlaces::toggleMediaPanel, this)); } - //childSetAction("share_btn", boost::bind(&LLPanelPlaces::onShareButtonClicked, this), this); - childSetAction("teleport_btn", boost::bind(&LLPanelPlaces::onTeleportButtonClicked, this), this); - childSetAction("map_btn", boost::bind(&LLPanelPlaces::onShowOnMapButtonClicked, this), this); - return TRUE; } @@ -124,19 +126,23 @@ void LLPanelPlaces::onOpen(const LLSD& key) return; mPlaceInfoType = key["type"].asString(); - + mPosGlobal.setZero(); togglePlaceInfoPanel(TRUE); + updateVerbs(); if (mPlaceInfoType == "agent") { - // We don't need to teleport to the current location so disable the button - getChild<LLButton>("teleport_btn")->setEnabled(FALSE); - getChild<LLButton>("map_btn")->setEnabled(TRUE); - mPlaceInfo->setInfoType(LLPanelPlaceInfo::PLACE); - mPlaceInfo->displayParcelInfo(gAgent.getPositionAgent(), - gAgent.getRegion()->getRegionID(), - gAgent.getPositionGlobal()); + mPlaceInfo->displayAgentParcelInfo(); + + mPosGlobal = gAgent.getPositionGlobal(); + } + else if (mPlaceInfoType == "create_landmark") + { + mPlaceInfo->setInfoType(LLPanelPlaceInfo::CREATE_LANDMARK); + mPlaceInfo->displayAgentParcelInfo(); + + mPosGlobal = gAgent.getPositionGlobal(); } else if (mPlaceInfoType == "landmark") { @@ -144,27 +150,19 @@ void LLPanelPlaces::onOpen(const LLSD& key) LLInventoryItem* item = gInventory.getItem(item_uuid); if (!item) return; + + setItem(item); + } + else if (mPlaceInfoType == "remote_place") + { + mPosGlobal = LLVector3d(key["x"].asReal(), + key["y"].asReal(), + key["z"].asReal()); - mPlaceInfo->setInfoType(LLPanelPlaceInfo::LANDMARK); - mPlaceInfo->displayItemInfo(item); - - LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID()); - if (!landmark) - return; - - // Select Landmarks tab and set selection to requested landmark so that - // context dependent Verbs buttons update properly. - mTabContainer->selectFirstTab(); // Assume that first tab is Landmarks tab. - LLLandmarksPanel* landmarks_panel = dynamic_cast<LLLandmarksPanel*>(mTabContainer->getCurrentPanel()); - landmarks_panel->setSelectedItem(item_uuid); - - LLUUID region_id; - landmark->getRegionID(region_id); - LLVector3d pos_global; - landmark->getGlobalPos(pos_global); - mPlaceInfo->displayParcelInfo(landmark->getRegionPos(), - region_id, - pos_global); + mPlaceInfo->setInfoType(LLPanelPlaceInfo::PLACE); + mPlaceInfo->displayParcelInfo(get_pos_local_from_global(mPosGlobal), + LLUUID(), + mPosGlobal); } else if (mPlaceInfoType == "teleport_history") { @@ -175,18 +173,47 @@ void LLPanelPlaces::onOpen(const LLSD& key) LLVector3d pos_global = hist_items[index].mGlobalPos; - F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS ); - F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS ); - - LLVector3 pos_local(region_x, region_y, (F32)pos_global.mdV[VZ]); - mPlaceInfo->setInfoType(LLPanelPlaceInfo::TELEPORT_HISTORY); - mPlaceInfo->displayParcelInfo(pos_local, + mPlaceInfo->displayParcelInfo(get_pos_local_from_global(pos_global), hist_items[index].mRegionID, pos_global); } } +void LLPanelPlaces::setItem(LLInventoryItem* item) +{ + mItem = item; + + // If the item is a link get a linked item + if (mItem->getType() == LLAssetType::AT_LINK) + { + mItem = gInventory.getItem(mItem->getAssetUUID()); + if (mItem.isNull()) + return; + } + + mPlaceInfo->setInfoType(LLPanelPlaceInfo::LANDMARK); + mPlaceInfo->displayItemInfo(mItem); + + LLLandmark* lm = gLandmarkList.getAsset(mItem->getAssetUUID(), + boost::bind(&LLPanelPlaces::onLandmarkLoaded, this, _1)); + if (lm) + { + onLandmarkLoaded(lm); + } +} + +void LLPanelPlaces::onLandmarkLoaded(LLLandmark* landmark) +{ + LLUUID region_id; + landmark->getRegionID(region_id); + LLVector3d pos_global; + landmark->getGlobalPos(pos_global); + mPlaceInfo->displayParcelInfo(landmark->getRegionPos(), + region_id, + pos_global); +} + void LLPanelPlaces::onFilterEdit(const std::string& search_string) { if (mFilterSubString != search_string) @@ -212,12 +239,12 @@ void LLPanelPlaces::onTabSelected() mActivePanel->updateVerbs(); } +/* void LLPanelPlaces::onShareButtonClicked() { // TODO: Launch the "Things" Share wizard } -/* void LLPanelPlaces::onAddLandmarkButtonClicked() { LLFloaterReg::showInstance("add_landmark"); @@ -231,24 +258,64 @@ void LLPanelPlaces::onCopySLURLButtonClicked() void LLPanelPlaces::onTeleportButtonClicked() { - mActivePanel->onTeleport(); + if (mPlaceInfo->getVisible()) + { + if (mPlaceInfoType == "landmark") + { + LLSD payload; + payload["asset_id"] = mItem->getAssetUUID(); + LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload); + } + else if (mPlaceInfoType == "remote_place") + { + LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance(); + if (!mPosGlobal.isExactlyZero() && worldmap_instance) + { + gAgent.teleportViaLocation(mPosGlobal); + worldmap_instance->trackLocation(mPosGlobal); + } + } + } + else + { + mActivePanel->onTeleport(); + } } void LLPanelPlaces::onShowOnMapButtonClicked() { - if (mPlaceInfoType == "agent") + if (mPlaceInfo->getVisible()) { - LLVector3d global_pos = gAgent.getPositionGlobal(); - if (!global_pos.isExactlyZero()) - { - LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance(); - if(instance) - { - instance->trackLocation(global_pos); - LLFloaterReg::showInstance("world_map", "center"); + LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance(); + if(!worldmap_instance) + return; - } + if (mPlaceInfoType == "agent" || + mPlaceInfoType == "create_landmark" || + mPlaceInfoType == "remote_place") + { + if (!mPosGlobal.isExactlyZero()) + { + worldmap_instance->trackLocation(mPosGlobal); + LLFloaterReg::showInstance("world_map", "center"); } + } + else if (mPlaceInfoType == "landmark") + { + LLLandmark* landmark = gLandmarkList.getAsset(mItem->getAssetUUID()); + if (!landmark) + return; + + LLVector3d landmark_global_pos; + if (!landmark->getGlobalPos(landmark_global_pos)) + return; + + if (!landmark_global_pos.isExactlyZero()) + { + worldmap_instance->trackLocation(landmark_global_pos); + LLFloaterReg::showInstance("world_map", "center"); + } + } } else { @@ -259,6 +326,11 @@ void LLPanelPlaces::onShowOnMapButtonClicked() void LLPanelPlaces::onBackButtonClicked() { togglePlaceInfoPanel(FALSE); + + // Resetting mPlaceInfoType when Place Info panel is closed. + mPlaceInfoType = LLStringUtil::null; + + updateVerbs(); } void LLPanelPlaces::toggleMediaPanel() @@ -268,6 +340,7 @@ void LLPanelPlaces::toggleMediaPanel() mPlaceInfo->toggleMediaPanel(!mPlaceInfo->isMediaPanelVisible()); } + void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible) { if (!mPlaceInfo) @@ -276,9 +349,6 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible) mPlaceInfo->setVisible(visible); mFilterEditor->setVisible(!visible); mTabContainer->setVisible(!visible); - - // Enable overflow button only for the information about agent's current location. - getChild<LLButton>("overflow_btn")->setEnabled(visible && mPlaceInfoType == "agent"); if (visible) { @@ -331,10 +401,48 @@ void LLPanelPlaces::changed(U32 mask) void LLPanelPlaces::onAgentParcelChange() { - if (mPlaceInfo->getVisible() && mPlaceInfoType == "agent") + if (mPlaceInfo->getVisible() && (mPlaceInfoType == "agent" || mPlaceInfoType == "create_landmark")) + { + LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", mPlaceInfoType)); + } + else + { + updateVerbs(); + } +} + +void LLPanelPlaces::updateVerbs() +{ + bool is_place_info_visible = mPlaceInfo->getVisible(); + bool is_agent_place_info_visible = mPlaceInfoType == "agent"; + if (is_place_info_visible) + { + if (is_agent_place_info_visible || mPlaceInfoType == "create_landmark") + { + // We don't need to teleport to the current location so disable the button + mTeleportBtn->setEnabled(FALSE); + } + else if (mPlaceInfoType == "landmark" || mPlaceInfoType == "remote_place") + { + mTeleportBtn->setEnabled(TRUE); + } + + mShowOnMapBtn->setEnabled(TRUE); + } + else { - // Using timer to delay obtaining agent's coordinates - // not to get the coordinates of previous parcel. - new LLParcelUpdateTimer(.5); + mActivePanel->updateVerbs(); } + + // Enable overflow button only when showing the information about agent's current location. + mOverflowBtn->setEnabled(is_place_info_visible && is_agent_place_info_visible); } + +const LLVector3 get_pos_local_from_global(const LLVector3d &pos_global) +{ + F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS ); + F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS ); + + LLVector3 pos_local(region_x, region_y, (F32)pos_global.mdV[VZ]); + return pos_local; +} diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index e2ba4f39cd..c100ace8cc 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -41,6 +41,8 @@ #include "llinventorymodel.h" #include "llpanelplaceinfo.h" +class LLInventoryItem; +class LLLandmark; class LLPanelPlacesTab; class LLFilterEditor; class LLTabContainer; @@ -55,38 +57,49 @@ public: /*virtual*/ void changed(U32 mask); /*virtual*/ void onOpen(const LLSD& key); + void setItem(LLInventoryItem* item); + +private: + void onLandmarkLoaded(LLLandmark* landmark); void onFilterEdit(const std::string& search_string); void onTabSelected(); + //void onAddLandmarkButtonClicked(); //void onCopySLURLButtonClicked(); - void onShareButtonClicked(); + //void onShareButtonClicked(); void onTeleportButtonClicked(); void onShowOnMapButtonClicked(); void onBackButtonClicked(); + void toggleMediaPanel(); void togglePlaceInfoPanel(BOOL visible); + void onAgentParcelChange(); + void updateVerbs(); -private: - LLFilterEditor* mFilterEditor; - LLPanelPlacesTab* mActivePanel; - LLTabContainer* mTabContainer; - LLPanelPlaceInfo* mPlaceInfo; - std::string mFilterSubString; - - // Place information type currently shown in Information panel - std::string mPlaceInfoType; - - // Helper class to delay the coordinates update - // when agent changes parcel - class LLParcelUpdateTimer : public LLEventTimer - { - public: - LLParcelUpdateTimer(F32 period); - virtual ~LLParcelUpdateTimer() {}; - - virtual BOOL tick(); - }; + LLFilterEditor* mFilterEditor; + LLPanelPlacesTab* mActivePanel; + LLTabContainer* mTabContainer; + LLPanelPlaceInfo* mPlaceInfo; + + //LLButton* mShareBtn; + LLButton* mTeleportBtn; + LLButton* mShowOnMapBtn; + LLButton* mOverflowBtn; + + // Pointer to a landmark item or to a linked landmark + LLPointer<LLInventoryItem> mItem; + + // Absolute position of the location for teleport, may not + // be available (hence zero) + LLVector3d mPosGlobal; + + // Search string for filtering landmarks and teleport + // history locations + std::string mFilterSubString; + + // Information type currently shown in Place Information panel + std::string mPlaceInfoType; }; #endif //LL_LLPANELPLACES_H diff --git a/indra/newview/llpanelplacestab.cpp b/indra/newview/llpanelplacestab.cpp index e5b1f04064..7c0a7b0cc4 100644 --- a/indra/newview/llpanelplacestab.cpp +++ b/indra/newview/llpanelplacestab.cpp @@ -41,6 +41,14 @@ #include "llslurl.h" #include "llworldmap.h" +bool LLPanelPlacesTab::isTabVisible() +{ + LLUICtrl* parent = getParentUICtrl(); + if (!parent) return false; + if (!parent->getVisible()) return false; + return true; +} + void LLPanelPlacesTab::setPanelPlacesButtons(LLPanelPlaces* panel) { //mShareBtn = panel->getChild<LLButton>("share_btn"); diff --git a/indra/newview/llpanelplacestab.h b/indra/newview/llpanelplacestab.h index c098302d1a..1c70869414 100644 --- a/indra/newview/llpanelplacestab.h +++ b/indra/newview/llpanelplacestab.h @@ -49,6 +49,8 @@ public: virtual void onTeleport() = 0; //virtual void onCopySLURL() = 0; + bool isTabVisible(); // Check if parent TabContainer is visible. + void setPanelPlacesButtons(LLPanelPlaces* panel); void onRegionResponse(const LLVector3d& landmark_global_pos, U64 region_handle, diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 77edae261b..51cd05376a 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -143,6 +143,9 @@ void LLTeleportHistoryPanel::onCopySLURL() // virtual void LLTeleportHistoryPanel::updateVerbs() { + if (!isTabVisible()) + return; + S32 index = 0; S32 cur_item = 0; diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 78091ef05b..5dca12e06b 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -37,31 +37,36 @@ #include "lltextbox.h" #include "llscreenchannel.h" +#include "llviewercontrol.h" + #include <algorithm> using namespace LLNotificationsUI; -#define TOAST_MARGIN 5 -#define BOTTOMPANEL_MARGIN 35 -#define NAVBAR_MARGIN 60 - +bool LLScreenChannel::mWasStartUpToastShown = false; //-------------------------------------------------------------------------- LLScreenChannel::LLScreenChannel(): mUnreadToastsPanel(NULL), mToastAlignment(NA_BOTTOM), mStoreToasts(true), + mHiddenToastsNum(0), mOverflowToastHidden(false), mIsHovering(false), mControlHovering(false) { setFollows(FOLLOWS_RIGHT | FOLLOWS_BOTTOM | FOLLOWS_TOP); + + //TODO: load as a resource string + mOverflowFormatString = "You have %d more notification"; + + setMouseOpaque( false ); } -void LLScreenChannel::init(S32 channel_position, LLView* root_view) +void LLScreenChannel::init(S32 channel_left, S32 channel_right) { - root_view->addChild(this); - setRect( LLRect(channel_position, root_view->getRect().getHeight() - NAVBAR_MARGIN, - channel_position, root_view->getRect().mBottom + BOTTOMPANEL_MARGIN)); + S32 channel_top = getRootView()->getRect().getHeight() - gSavedSettings.getS32("NavBarMargin"); + S32 channel_bottom = getRootView()->getRect().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin"); + setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom)); } @@ -79,7 +84,7 @@ void LLScreenChannel::reshape(S32 width, S32 height, BOOL called_from_parent) } //-------------------------------------------------------------------------- -LLToast* LLScreenChannel::addToast(LLUUID id, LLPanel* panel) +LLToast* LLScreenChannel::addToast(LLUUID id, LLPanel* panel, bool is_not_tip) { ToastElem new_toast_elem(id, panel); @@ -92,7 +97,29 @@ LLToast* LLScreenChannel::addToast(LLUUID id, LLPanel* panel) { new_toast_elem.toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2)); } - showToasts(); + + // don't show toasts until StartUp toast will fade, but show alerts + if(!mWasStartUpToastShown && mToastAlignment != NA_CENTRE) + { + new_toast_elem.toast->stopTimer(); + // Count and store only non tip notifications + if(is_not_tip) + { + mHiddenToastsNum++; + storeToast(new_toast_elem); + } + else + { + // destroy tip toasts at once + new_toast_elem.toast->close(); + } + // remove toast from channel + mToastList.pop_back(); + } + else + { + showToasts(); + } return new_toast_elem.toast; } @@ -213,10 +240,20 @@ void LLScreenChannel::showToastsBottom() } toast_rect = (*it).toast->getRect(); - toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+TOAST_MARGIN, toast_rect.getWidth() ,toast_rect.getHeight()); + toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastMargin"), toast_rect.getWidth() ,toast_rect.getHeight()); (*it).toast->setRect(toast_rect); - if((*it).toast->getRect().mTop > getRect().getHeight()) + bool stop_showing_toasts = (*it).toast->getRect().mTop > getRect().getHeight(); + + if(!stop_showing_toasts) + { + if( it != mToastList.rend()-1) + { + stop_showing_toasts = ((*it).toast->getRect().mTop + gSavedSettings.getS32("OverflowToastHeight") + gSavedSettings.getS32("ToastMargin")) > getRect().getHeight(); + } + } + + if(stop_showing_toasts) break; (*it).toast->setVisible(TRUE); @@ -243,7 +280,7 @@ void LLScreenChannel::showToastsCentre() for(it = mToastList.rbegin(); it != mToastList.rend(); ++it) { toast_rect = (*it).toast->getRect(); - toast_rect.setLeftTopAndSize(getRect().mLeft - toast_rect.getWidth() / 2, bottom + toast_rect.getHeight() / 2 + TOAST_MARGIN, toast_rect.getWidth() ,toast_rect.getHeight()); + toast_rect.setLeftTopAndSize(getRect().mLeft - toast_rect.getWidth() / 2, bottom + toast_rect.getHeight() / 2 + gSavedSettings.getS32("ToastMargin"), toast_rect.getWidth() ,toast_rect.getHeight()); (*it).toast->setRect(toast_rect); (*it).toast->setVisible(TRUE); @@ -256,7 +293,7 @@ void LLScreenChannel::showToastsTop() } //-------------------------------------------------------------------------- -void LLScreenChannel::createOverflowToast(S32 bottom) +void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer) { LLRect toast_rect; mUnreadToastsPanel = new LLToast(NULL); @@ -266,21 +303,29 @@ void LLScreenChannel::createOverflowToast(S32 bottom) mUnreadToastsPanel->setOnFadeCallback(boost::bind(&LLScreenChannel::onOverflowToastHide, this)); - LLTextBox* text_box = mUnreadToastsPanel->getChild<LLTextBox>("text"); + LLTextBox* text_box = mUnreadToastsPanel->getChild<LLTextBox>("toast_text"); LLIconCtrl* icon = mUnreadToastsPanel->getChild<LLIconCtrl>("icon"); + std::string text = llformat(mOverflowFormatString.c_str(),mHiddenToastsNum); + if(mHiddenToastsNum == 1) + { + text += "."; + } + else + { + text += "s."; + } - std::string toastsNumStr = llformat("%d", mHiddenToastsNum); - std::string text = "You have " + toastsNumStr + " new notifications."; + toast_rect = mUnreadToastsPanel->getRect(); + mUnreadToastsPanel->reshape(getRect().getWidth(), toast_rect.getHeight(), true); + toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastMargin"), getRect().getWidth(), toast_rect.getHeight()); + mUnreadToastsPanel->setRect(toast_rect); + mUnreadToastsPanel->setAndStartTimer(timer ? timer : gSavedSettings.getS32("NotificationToastTime")); + getRootView()->addChild(mUnreadToastsPanel); - text_box->setText(text); + text_box->setValue(text); text_box->setVisible(TRUE); icon->setVisible(TRUE); - toast_rect = mUnreadToastsPanel->getRect(); - toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+TOAST_MARGIN, toast_rect.getWidth() ,toast_rect.getHeight()); - mUnreadToastsPanel->setRect(toast_rect); - mUnreadToastsPanel->setAndStartTimer(5); - getRootView()->addChild(mUnreadToastsPanel); mUnreadToastsPanel->setVisible(TRUE); } @@ -288,6 +333,7 @@ void LLScreenChannel::createOverflowToast(S32 bottom) void LLScreenChannel::onOverflowToastHide() { mOverflowToastHidden = true; + onCommit(); } //-------------------------------------------------------------------------- diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index 5a9946f772..f05c205e2a 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -54,14 +54,15 @@ typedef enum e_notification_toast_alignment */ class LLScreenChannel : public LLUICtrl { + friend class LLChannelManager; public: LLScreenChannel(); virtual ~LLScreenChannel(); void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - LLToast* addToast(LLUUID id, LLPanel* panel); - void init(S32 channel_position, LLView* root_view); + LLToast* addToast(LLUUID id, LLPanel* panel, bool is_not_tip = true); + void init(S32 channel_left, S32 channel_right); void killToastByNotificationID(LLUUID id); void modifyToastByNotificationID(LLUUID id, LLPanel* panel); @@ -79,8 +80,15 @@ public: void showToasts(); + S32 getNumberOfHiddenToasts() { return mHiddenToastsNum;} + void setNumberOfHiddenToasts(S32 num) { mHiddenToastsNum = num;} + + static void setStartUpToastShown() { mWasStartUpToastShown = true; } + e_notification_toast_alignment getToastAlignment() {return mToastAlignment;} + void setOverflowFormatString ( std::string str) { mOverflowFormatString = str; } + private: struct ToastElem { @@ -117,9 +125,10 @@ private: void showToastsCentre(); void showToastsTop(); - void createOverflowToast(S32 bottom); + void createOverflowToast(S32 bottom, F32 timer = 0); void onOverflowToastHide(); + static bool mWasStartUpToastShown; bool mControlHovering; bool mIsHovering; bool mStoreToasts; @@ -130,6 +139,8 @@ private: std::vector<ToastElem> mStoredToastList; e_notification_toast_alignment mToastAlignment; std::map<LLToast*, bool> mToastEventStack; + + std::string mOverflowFormatString; }; } diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index abcff7cfb1..2688399139 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -63,24 +63,11 @@ LLSideTray* LLSideTray::sInstance = 0; class LLSideTrayInfoPanel: public LLPanel { -protected: - LLSideTrayInfoPanel(){} + public: - static LLSideTrayInfoPanel* createInstance(const string& image, const string& name,const string& description) - { - LLSideTrayInfoPanel* panel = new LLSideTrayInfoPanel(); - LLUICtrlFactory::getInstance()->buildPanel(panel,"panel_sidetray_tab_info.xml"); - if(panel) - panel->setData(image, name,description); - panel->setBorderVisible(true); - return panel; - - } - void setData(const string& image, const string& name,const string& description) + LLSideTrayInfoPanel():LLPanel() { - getChild<LLTextBox>("tab_name",false,false)->setValue(name); - getChild<LLTextBox>("tab_description",false,false)->setValue(description); - getChild<LLIconCtrl>("tab_icon",false,false)->setValue(image); + setBorderVisible(true); } BOOL handleHover(S32 x, S32 y, MASK mask) @@ -91,12 +78,19 @@ public: BOOL handleMouseUp(S32 x, S32 y, MASK mask) { + std::string name = getName(); onCommit(); + LLSideTray::getInstance()->selectTabByName(name); return LLPanel::handleMouseUp(x,y,mask); } + void reshape (S32 width, S32 height, BOOL called_from_parent ) + { + return LLPanel::reshape(width, height, called_from_parent); + } }; +static LLRegisterPanelClassWrapper<LLSideTrayInfoPanel> t_people("panel_sidetray_home_info"); LLSideTray* LLSideTray::getInstance() { @@ -113,7 +107,7 @@ bool LLSideTray::instanceCreated () return sInstance!=0; } -LLSideTrayTab::LLSideTrayTab(const Params& params):mAccordionCtrl(0) +LLSideTrayTab::LLSideTrayTab(const Params& params):mMainPanel(0) { mImagePath = params.image_path; @@ -124,30 +118,12 @@ LLSideTrayTab::~LLSideTrayTab() { } -void LLSideTrayTab::addPanel(LLPanel* panel) -{ - //addChild(panel,false); -} - bool LLSideTrayTab::addChild(LLView* view, S32 tab_group) { - if(mAccordionCtrl == 0) - { - mAccordionCtrl = new LLAccordionCtrl(); - mAccordionCtrl->setVisible(TRUE); - LLPanel::addChild(mAccordionCtrl,tab_group); - } - - - bool res = true; - if(TAB_PANEL_CAPTION_NAME != view->getName())//skip our caption panel - { - mAccordionCtrl->addCollapsibleCtrl(view); - } - else - res = LLPanel::addChild(view,tab_group); - - return res; + if(mMainPanel == 0 && TAB_PANEL_CAPTION_NAME != view->getName())//skip our caption panel + mMainPanel = view; + return LLPanel::addChild(view,tab_group); + //return res; } @@ -185,17 +161,18 @@ void LLSideTrayTab::arrange(S32 width, S32 height ) offset = title_panel->getRect().getHeight(); } - LLRect sRect = mAccordionCtrl->getRect(); + LLRect sRect = mMainPanel->getRect(); sRect.setLeftTopAndSize( splitter_margin, height - offset - splitter_margin, width - 2*splitter_margin, height - offset - 2*splitter_margin); - mAccordionCtrl->setRect(sRect); + mMainPanel->reshape(sRect.getWidth(),sRect.getHeight()); + mMainPanel->setRect(sRect); + + - mAccordionCtrl->setMaxWidth(sRect.getWidth()); - mAccordionCtrl->arrange(); } void LLSideTrayTab::reshape (S32 width, S32 height, BOOL called_from_parent ) { - if(!mAccordionCtrl) + if(!mMainPanel) return; S32 offset = 0; @@ -210,12 +187,12 @@ void LLSideTrayTab::reshape (S32 width, S32 height, BOOL called_from_parent ) - LLRect sRect = mAccordionCtrl->getRect(); + LLRect sRect = mMainPanel->getRect(); sRect.setLeftTopAndSize( splitter_margin, height - offset - splitter_margin, width - 2*splitter_margin, height - offset - 2*splitter_margin); - mAccordionCtrl->setMaxWidth(sRect.getWidth()); - mAccordionCtrl->reshape(sRect.getWidth(), sRect.getHeight()); + //mMainPanel->setMaxWidth(sRect.getWidth()); + mMainPanel->reshape(sRect.getWidth(), sRect.getHeight()); - mAccordionCtrl->setRect(sRect); + mMainPanel->setRect(sRect); } @@ -231,7 +208,9 @@ void LLSideTrayTab::draw() void LLSideTrayTab::onOpen (const LLSD& key) { - mAccordionCtrl->onOpen(key); + LLPanel* panel = dynamic_cast<LLPanel*>(mMainPanel); + if(panel) + panel->onOpen(key); } LLSideTrayTab* LLSideTrayTab::createInstance () @@ -251,7 +230,6 @@ LLSideTray::LLSideTray(Params& params) ,mCollapsed(false) ,mCollapseButton(0) ,mMaxBarWidth(params.rect.width) - ,mHomeTab(0) { mCollapsed=params.collapsed; } @@ -261,10 +239,8 @@ BOOL LLSideTray::postBuild() { createButtons(); - createHomeTab(); - arrange(); - selectTabByName("home_tab"); + selectTabByName("sidebar_home"); if(mCollapsed) collapseSideBar(); @@ -333,8 +309,6 @@ bool LLSideTray::selectTabByIndex(size_t index) bool LLSideTray::selectTabByName (const std::string& name) { LLSideTrayTab* side_bar = getTab(name); - if(side_bar == 0 && name == "home_tab") - side_bar = mHomeTab; if(side_bar == NULL || side_bar == mActiveTab) return false; @@ -416,9 +390,10 @@ void LLSideTray::createButtons () mCollapseButton = createButton(EXPANDED_NAME,"",boost::bind(&LLSideTray::onToggleCollapse, this)); //create buttons for tabs - child_vector_const_iter_t child_it; + child_vector_const_iter_t child_it = mTabs.begin(); + ++child_it; - for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it) + for ( ; child_it != mTabs.end(); ++child_it) { LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it); if(sidebar_tab == NULL) @@ -445,7 +420,7 @@ void LLSideTray::onToggleCollapse() if(mCollapsed) { expandSideBar(); - selectTabByName("home_tab"); + selectTabByName("sidebar_home"); } else collapseSideBar(); @@ -517,10 +492,6 @@ void LLSideTray::arrange () sidebar_tab->setRect(ctrl_rect); sidebar_tab->arrange(mMaxBarWidth,getRect().getHeight()); } - - mHomeTab->setRect(ctrl_rect); - mHomeTab->arrange(mMaxBarWidth,getRect().getHeight()); - } void LLSideTray::collapseSideBar () @@ -619,19 +590,16 @@ void LLSideTray::reshape (S32 width, S32 height, BOOL called_from_parent) sidebar_tab->setRect(ctrl_rect); } - - mHomeTab->reshape(mMaxBarWidth,getRect().getHeight()); - ctrl_rect.setLeftTopAndSize(sidetray_params.default_button_width,getRect().getHeight(),mMaxBarWidth,getRect().getHeight()); - mHomeTab->setRect(ctrl_rect); - - } /** * Activate tab with "panel_name" panel - * if no such tab - return false, otherwise true + * if no such tab - return false, otherwise true. + * TODO* In some cases a pointer to a panel of + * a specific class may be needed so this method + * would need to use templates. */ -bool LLSideTray::showPanel (const std::string& panel_name, const LLSD& params) +LLPanel* LLSideTray::showPanel (const std::string& panel_name, const LLSD& params) { //arrange tabs child_vector_const_iter_t child_it; @@ -644,51 +612,12 @@ bool LLSideTray::showPanel (const std::string& panel_name, const LLSD& params) LLPanel* panel = dynamic_cast<LLPanel*>(view); if(panel) panel->onOpen(params); - return true; + return panel; } } - return false; + return NULL; } -void LLSideTray::createHomeTab() -{ - mHomeTab = LLSideTrayTab::createInstance(); - child_vector_iter_t child_it; - for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it) - { - LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it); - if(sidebar_tab == NULL) - continue; - - LLPanel* panel = LLSideTrayInfoPanel::createInstance(sidebar_tab->mImagePath,sidebar_tab->getTabTitle(),sidebar_tab->getDescription()); - - panel->setCommitCallback(boost::bind(&LLSideTray::onTabButtonClick, this, sidebar_tab->getName())); - - LLAccordionCtrlTab::Params panel_params; - panel_params.display_children(true); - panel_params.collapsible(false); - panel_params.header_visible(false); - panel_params.can_resize(false); - panel_params.min_height(200); - panel_params.padding_left(10); - panel_params.padding_right(10); - panel_params.padding_top(5); - panel_params.padding_bottom(5); - panel_params.name(sidebar_tab->getTabTitle()); - - LLAccordionCtrlTab* ctrl = LLUICtrlFactory::create<LLAccordionCtrlTab>(panel_params); - - - ctrl->setPanel(panel); - ctrl->postBuild(); - mHomeTab->addChild(ctrl,0); - } - - mHomeTab->setBackgroundVisible(true); - mHomeTab->postBuild(); - - LLUICtrl::addChild(mHomeTab, 0); -} static const S32 fake_offset = 132; static const S32 fake_top_offset = 78; diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h index 7b1f4aee04..99e84f8141 100644 --- a/indra/newview/llsidetray.h +++ b/indra/newview/llsidetray.h @@ -65,7 +65,6 @@ protected: public: virtual ~LLSideTrayTab(); - void addPanel (LLPanel* panel); /*virtual*/ BOOL postBuild (); /*virtual*/ bool addChild (LLView* view, S32 tab_group); @@ -87,7 +86,7 @@ private: std::string mImagePath; std::string mDescription; - LLAccordionCtrl* mAccordionCtrl; + LLView* mMainPanel; }; @@ -163,9 +162,9 @@ public: /** * Activate tab with "panel_name" panel - * if no such tab - return false, otherwise true + * if no such tab - return NULL, otherwise a pointer to the panel */ - bool showPanel (const std::string& panel_name, const LLSD& params); + LLPanel* showPanel (const std::string& panel_name, const LLSD& params); /* * collapse SideBar, hiding visible tab and moving tab buttons @@ -209,7 +208,6 @@ protected: void createButtons (); LLButton* createButton (const std::string& name,const std::string& image,LLUICtrl::commit_callback_t callback); - void createHomeTab (); void arrange (); void reflectCollapseChange(); @@ -223,7 +221,6 @@ private: std::map<std::string,LLButton*> mTabButtons; child_vector_t mTabs; - LLSideTrayTab* mHomeTab; LLSideTrayTab* mActiveTab; LLButton* mCollapseButton; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index d0432e7961..3410a1eb68 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -871,8 +871,6 @@ bool idle_startup() gDirUtilp->setLindenUserDir(firstname, lastname); LLFile::mkdir(gDirUtilp->getLindenUserDir()); - LLLocationHistory::getInstance()->load(); - // Set PerAccountSettingsFile to the default value. gSavedSettings.setString("PerAccountSettingsFile", gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, @@ -2517,6 +2515,8 @@ bool idle_startup() // reset timers now that we are running "logged in" logic LLFastTimer::reset(); + LLLocationHistory::getInstance()->load(); + return TRUE; } diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 9144f9c3e0..6f5b25214e 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -104,6 +104,7 @@ bool LLToast::timerHasExpired() if (mTimer.getStarted()) { F32 elapsed_time = mTimer.getElapsedTimeF32(); + // after 4 seconds a toast should start fade if (elapsed_time > 4) { setBackgroundOpaque(FALSE); @@ -119,7 +120,7 @@ bool LLToast::timerHasExpired() //-------------------------------------------------------------------------- void LLToast::hide() { - setVisible(FALSE); //TODO: store in Chiclet's history + setVisible(FALSE); mIsViewed = false; mTimer.stop(); mOnFade(this, LLSD()); diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index 2e2ac5b36c..018664f3d1 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -68,6 +68,7 @@ public: void setAndStartTimer(F32 period); // void resetTimer() { mTimer.start(); } + void stopTimer() { mTimer.stop(); } void close() { die(); } virtual void draw(); virtual void setVisible(BOOL show); diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index 83c25ddc77..f5ed7f8710 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -51,6 +51,8 @@ #include "llglheaders.h" #include "llagent.h" #include "llavatariconctrl.h" +#include "llfloaterinventory.h" +#include "llinventorytype.h" LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification) : LLToastPanel(notification), @@ -64,6 +66,8 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification llwarns << "Group notice for unkown group: " << payload["group_id"].asUUID() << llendl; } + static const LLUIColor textColor = LLUIColorTable::instance().getColor("GroupNotifyTextColor"); + //group icon LLIconCtrl* pGroupIcon = getChild<LLIconCtrl>("group_icon", TRUE); pGroupIcon->setValue(groupData.mInsigniaID); @@ -76,11 +80,36 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification pTitleText->setValue(from.str()); //message body + const std::string& subject = payload["subject"].asString(); const std::string& message = payload["message"].asString(); + LLTextEditor* pMessageText = getChild< LLTextEditor>("message", TRUE, FALSE); + pMessageText->setValue(""); pMessageText->setEnabled(FALSE); pMessageText->setTakesFocus(FALSE); - pMessageText->setValue(message); + + static const LLStyleSP headerstyle(new LLStyle(true, textColor, + "SansSerifBig")); + static const LLStyleSP datestyle(new LLStyle(true, textColor, "serif")); + + pMessageText->appendStyledText(subject + "\n",false,false,headerstyle); + + std::string timeStr = "["+LLTrans::getString("UTCTimeWeek")+"],[" + +LLTrans::getString("UTCTimeDay")+"] [" + +LLTrans::getString("UTCTimeMth")+"] [" + +LLTrans::getString("UTCTimeYr")+"] [" + +LLTrans::getString("UTCTimeHr")+"]:[" + +LLTrans::getString("UTCTimeMin")+"]:[" + +LLTrans::getString("UTCTimeSec")+"] [" + +LLTrans::getString("UTCTimeTimezone")+"]"; + const LLDate timeStamp = notification->getDate(); + LLDate notice_date = timeStamp.notNull() ? timeStamp : LLDate::now(); + LLSD substitution; + substitution["datetime"] = (S32) notice_date.secondsSinceEpoch(); + LLStringUtil::format(timeStr, substitution); + pMessageText->appendStyledText(timeStr, false, false, datestyle); + pMessageText->appendColoredText(std::string("\n\n") + message, false, + false, textColor); //attachment BOOL hasInventory = payload["inventory_offer"].isDefined(); @@ -91,6 +120,13 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification mInventoryOffer = new LLOfferInfo(payload["inventory_offer"]); childSetActionTextbox("attachment", boost::bind( &LLToastGroupNotifyPanel::onClickAttachment, this)); + + //attachment icon + LLIconCtrl* pAttachIcon = getChild<LLIconCtrl>("attachment_icon", TRUE); + LLUIImagePtr attachIconImg = get_item_icon(mInventoryOffer->mType, + LLInventoryType::IT_TEXTURE, + 0, FALSE); + pAttachIcon->setValue(attachIconImg->getName()); } //ok button @@ -128,10 +164,43 @@ void LLToastGroupNotifyPanel::onClickOk() void LLToastGroupNotifyPanel::onClickAttachment() { - mInventoryOffer->forceResponse(IOR_ACCEPT); + if (mInventoryOffer != NULL) { + mInventoryOffer->forceResponse(IOR_ACCEPT); - mInventoryOffer = NULL; + LLTextBox * pAttachLink = getChild<LLTextBox> ("attachment", TRUE, + FALSE); + static const LLUIColor textColor = LLUIColorTable::instance().getColor( + "GroupNotifyDimmedTextColor"); + pAttachLink->setColor(textColor); - LLTextBox * pAttachLink = getChild<LLTextBox>("attachment", TRUE, FALSE); - pAttachLink->setVisible(FALSE); + LLIconCtrl* pAttachIcon = + getChild<LLIconCtrl> ("attachment_icon", TRUE); + pAttachIcon->setEnabled(FALSE); + + //if attachment isn't openable - notify about saving + if (!isAttachmentOpenable(mInventoryOffer->mType)) { + LLNotifications::instance().add("AttachmentSaved"); + } + + mInventoryOffer = NULL; + } } + +//static +bool LLToastGroupNotifyPanel::isAttachmentOpenable(LLAssetType::EType type) +{ + switch(type) + { + case LLAssetType::AT_LANDMARK: + case LLAssetType::AT_FAVORITE: + case LLAssetType::AT_NOTECARD: + case LLAssetType::AT_IMAGE_JPEG: + case LLAssetType::AT_IMAGE_TGA: + case LLAssetType::AT_TEXTURE: + case LLAssetType::AT_TEXTURE_TGA: + return true; + default: + return false; + } +} + diff --git a/indra/newview/lltoastgroupnotifypanel.h b/indra/newview/lltoastgroupnotifypanel.h index f00f840e94..ba98531251 100644 --- a/indra/newview/lltoastgroupnotifypanel.h +++ b/indra/newview/lltoastgroupnotifypanel.h @@ -66,6 +66,7 @@ protected: void onClickOk(); void onClickAttachment(); private: + static bool isAttachmentOpenable(LLAssetType::EType); LLButton* mSaveInventoryBtn; diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index dd37d41ff5..72812d0bb9 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1606,6 +1606,8 @@ void LLToolDragAndDrop::commitGiveInventoryItem(const LLUUID& to_agent, gIMMgr->addSystemMessage(im_session_id, "inventory_item_offered", args); } + // add buddy to recent people list + LLRecentPeople::instance().add(to_agent); } void LLToolDragAndDrop::giveInventoryCategory(const LLUUID& to_agent, @@ -1730,6 +1732,9 @@ void LLToolDragAndDrop::commitGiveInventoryCategory(const LLUUID& to_agent, llinfos << "LLToolDragAndDrop::commitGiveInventoryCategory() - " << cat->getUUID() << llendl; + // add buddy to recent people list + LLRecentPeople::instance().add(to_agent); + // Test out how many items are being given. LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp index acb7f927b6..9fb6d1c874 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -43,6 +43,7 @@ #include "llfloaterurldisplay.h" #include "llfloaterworldmap.h" #include "llpanellogin.h" +#include "llsidetray.h" #include "llslurl.h" #include "llstartup.h" // gStartupState #include "llurlsimstring.h" @@ -202,8 +203,9 @@ bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, bool right_mous S32 z = 0; LLURLSimString::parse(sim_string, ®ion_name, &x, &y, &z); - LLFloaterURLDisplay* url_displayp = LLFloaterReg::getTypedInstance<LLFloaterURLDisplay>("preview_url",LLSD()); - if(url_displayp) url_displayp->setName(region_name); + // LLFloaterURLDisplay functionality moved to LLPanelPlaces in Side Tray. + //LLFloaterURLDisplay* url_displayp = LLFloaterReg::getTypedInstance<LLFloaterURLDisplay>("preview_url",LLSD()); + //if(url_displayp) url_displayp->setName(region_name); // Request a region handle by name LLWorldMap::getInstance()->sendNamedRegionRequest(region_name, @@ -274,12 +276,11 @@ void LLURLDispatcherImpl::regionHandleCallback(U64 region_handle, const std::str local_pos.mV[VY] = (F32)local_y; local_pos.mV[VZ] = (F32)z; - + LLVector3d global_pos = from_region_handle(region_handle); + global_pos += LLVector3d(local_pos); if (teleport) - { - LLVector3d global_pos = from_region_handle(region_handle); - global_pos += LLVector3d(local_pos); + { gAgent.teleportViaLocation(global_pos); LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance(); if(instance) @@ -289,18 +290,28 @@ void LLURLDispatcherImpl::regionHandleCallback(U64 region_handle, const std::str } else { - // display informational floater, allow user to click teleport btn - LLFloaterURLDisplay* url_displayp = LLFloaterReg::getTypedInstance<LLFloaterURLDisplay>("preview_url",LLSD()); - if(url_displayp) - { - url_displayp->displayParcelInfo(region_handle, local_pos); - if(snapshot_id.notNull()) - { - url_displayp->setSnapshotDisplay(snapshot_id); - } - std::string locationString = llformat("%s %d, %d, %d", region_name.c_str(), x, y, z); - url_displayp->setLocationString(locationString); - } + LLSD key; + key["type"] = "remote_place"; + key["x"] = global_pos.mdV[VX]; + key["y"] = global_pos.mdV[VY]; + key["z"] = global_pos.mdV[VZ]; + + LLSideTray::getInstance()->showPanel("panel_places", key); + + // LLFloaterURLDisplay functionality moved to LLPanelPlaces in Side Tray. + +// // display informational floater, allow user to click teleport btn +// LLFloaterURLDisplay* url_displayp = LLFloaterReg::getTypedInstance<LLFloaterURLDisplay>("preview_url",LLSD()); +// if(url_displayp) +// { +// url_displayp->displayParcelInfo(region_handle, local_pos); +// if(snapshot_id.notNull()) +// { +// url_displayp->setSnapshotDisplay(snapshot_id); +// } +// std::string locationString = llformat("%s %d, %d, %d", region_name.c_str(), x, y, z); +// url_displayp->setLocationString(locationString); +// } } } diff --git a/indra/newview/llviewergesture.cpp b/indra/newview/llviewergesture.cpp index 62ed861c86..4155a87e14 100644 --- a/indra/newview/llviewergesture.cpp +++ b/indra/newview/llviewergesture.cpp @@ -46,7 +46,7 @@ #include "llviewermessage.h" // send_guid_sound_trigger #include "llviewernetwork.h" #include "llagent.h" -#include "llbottomtray.h" +#include "llnearbychatbar.h" // Globals LLViewerGestureList gGestureList; @@ -136,7 +136,7 @@ void LLViewerGesture::doTrigger( BOOL send_chat ) { // Don't play nodding animation, since that might not blend // with the gesture animation. - LLBottomTray::getInstance()->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); + LLNearbyChatBar::getInstance()->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); } } diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 63234c2990..4e0c4023fd 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -36,7 +36,7 @@ #include "llviewerkeyboard.h" #include "llmath.h" #include "llagent.h" -#include "llbottomtray.h" +#include "llnearbychatbar.h" #include "llviewercontrol.h" #include "llfocusmgr.h" #include "llmorphview.h" @@ -500,7 +500,7 @@ void stop_moving( EKeystate s ) void start_chat( EKeystate s ) { // start chat - LLBottomTray::startChat(NULL); + LLNearbyChatBar::startChat(NULL); } void start_gesture( EKeystate s ) @@ -508,15 +508,15 @@ void start_gesture( EKeystate s ) if (KEYSTATE_UP == s && !(gFocusMgr.getKeyboardFocus() && gFocusMgr.getKeyboardFocus()->acceptsTextInput())) { - if (LLBottomTray::getInstance()->getCurrentChat().empty()) + if (LLNearbyChatBar::getInstance()->getCurrentChat().empty()) { // No existing chat in chat editor, insert '/' - LLBottomTray::getInstance()->startChat("/"); + LLNearbyChatBar::startChat("/"); } else { // Don't overwrite existing text in chat editor - LLBottomTray::getInstance()->startChat(NULL); + LLNearbyChatBar::startChat(NULL); } } } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index e06e180ed5..7071b65228 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -132,6 +132,7 @@ #include "llfloatermemleak.h" #include "llfasttimerview.h" #include "llavataractions.h" +#include "lllandmarkactions.h" #include "llmemoryview.h" #include "llgivemoney.h" #include "llgroupmgr.h" @@ -5270,24 +5271,6 @@ class LLWorldSetBusy : public view_listener_t } }; -bool can_create_landmark() -{ - BOOL can = FALSE; - - LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if (agent_parcel) -{ - - if (agent_parcel->getAllowLandmark() - || LLViewerParcelMgr::isParcelOwnedByAgent(agent_parcel, GP_LAND_ALLOW_LANDMARK)) - { - can = TRUE; - } - } - - return can; -} - class LLWorldCreateLandmark : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -6675,9 +6658,7 @@ class LLWorldEnableCreateLandmark : public view_listener_t { bool handleEvent(const LLSD& userdata) { - bool new_value = can_create_landmark(); - - return new_value; + return !LLLandmarkActions::landmarkAlreadyExists(); } }; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 74ded99124..25c00bb816 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -209,6 +209,10 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) LLUUID fid; LLMessageSystem* msg = gMessageSystem; const LLSD& payload = notification["payload"]; + + // add friend to recent people list + LLRecentPeople::instance().add(payload["from_id"]); + switch(option) { case 0: @@ -1180,6 +1184,9 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& { opener = open_agent_offer; } + + // add buddy to recent people list + LLRecentPeople::instance().add(mFromID); } break; case IM_TASK_INVENTORY_OFFERED: diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 65f341627a..3aefa84295 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -765,13 +765,17 @@ BOOL LLViewerParcelMgr::canHearSound(const LLVector3d &pos_global) const BOOL LLViewerParcelMgr::inAgentParcel(const LLVector3d &pos_global) const { LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(pos_global); - if (region != gAgent.getRegion()) + LLViewerRegion* agent_region = gAgent.getRegion(); + if (!region || !agent_region) + return FALSE; + + if (region != agent_region) { // Can't be in the agent parcel if you're not in the same region. return FALSE; } - LLVector3 pos_region = gAgent.getRegion()->getPosRegionFromGlobal(pos_global); + LLVector3 pos_region = agent_region->getPosRegionFromGlobal(pos_global); S32 row = S32(pos_region.mV[VY] / PARCEL_GRID_STEP_METERS); S32 column = S32(pos_region.mV[VX] / PARCEL_GRID_STEP_METERS); diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index 902b59c732..0fadba1364 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -47,11 +47,13 @@ #include "llfloateravatarinfo.h" #include "llfloaterworldmap.h" #include "llnotify.h" +#include "llpanelplaces.h" #include "llpreview.h" #include "llpreviewtexture.h" #include "llpreviewnotecard.h" #include "llpreviewlandmark.h" #include "llscrollbar.h" +#include "llsidetray.h" #include "lltooldraganddrop.h" #include "lltrans.h" #include "llviewercontrol.h" @@ -1365,11 +1367,22 @@ void LLViewerTextEditor::openEmbeddedLandmark( LLInventoryItem* item, llwchar wc { if (!item) return; - LLPreviewLandmark* preview = LLFloaterReg::showTypedInstance<LLPreviewLandmark>("preview_landmark", LLSD(item->getUUID()), TAKE_FOCUS_YES); - if (preview) + + LLSD key; + key["type"] = "landmark"; + key["id"] = item->getUUID(); + + LLPanelPlaces *panel = dynamic_cast<LLPanelPlaces*>(LLSideTray::getInstance()->showPanel("panel_places", key)); + if (panel) { - preview->setItem( item ); + panel->setItem(item); } + +// LLPreviewLandmark* preview = LLFloaterReg::showTypedInstance<LLPreviewLandmark>("preview_landmark", LLSD(item->getUUID()), TAKE_FOCUS_YES); +// if (preview) +// { +// preview->setItem( item ); +// } } void LLViewerTextEditor::openEmbeddedNotecard( LLInventoryItem* item, llwchar wc ) diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index a949830dcf..533889b2f7 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -878,7 +878,10 @@ void LLViewerFetchedTexture::init(bool firstinit) LLViewerFetchedTexture::~LLViewerFetchedTexture() { - if (mHasFetcher) + //*NOTE getTextureFetch can return NULL when Viewer is shutting down. + // This is due to LLWearableList is singleton and is destroyed after + // LLAppViewer::cleanup() was called. (see ticket EXT-177) + if (mHasFetcher && LLAppViewer::getTextureFetch()) { LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 3e86f48cc5..f312cc0f63 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -184,6 +184,7 @@ #include "llviewernetwork.h" #include "llpostprocess.h" #include "llbottomtray.h" +#include "llnearbychatbar.h" #include "llnotificationmanager.h" @@ -1559,10 +1560,12 @@ void LLViewerWindow::initWorldUI() getRootView()->sendChildToFront(gSnapshotFloaterView); // new bottom panel + getRootView()->addChild(LLBottomTray::getInstance()); + // Make sure Bottom Tray is behind Side Tray regardless "addChild" order. + getRootView()->sendChildToBack(LLBottomTray::getInstance()); LLRect rc = LLBottomTray::getInstance()->getRect(); rc.mLeft = 0; rc.mRight = mRootView->getRect().getWidth(); - mRootView->addChild(LLBottomTray::getInstance()); LLBottomTray::getInstance()->reshape(rc.getWidth(),rc.getHeight(),FALSE); LLBottomTray::getInstance()->setRect(rc); @@ -1646,12 +1649,10 @@ void LLViewerWindow::initWorldUI() getRootView()->sendChildToFront(gMenuHolder); //Channel Manager - LLNotificationsUI::LLChannelManager * channel_manager - = LLNotificationsUI::LLChannelManager::getInstance(); + LLNotificationsUI::LLChannelManager* channel_manager = LLNotificationsUI::LLChannelManager::getInstance(); getRootView()->addChild(channel_manager); //Notification Manager - LLNotificationsUI::LLNotificationManager* notify_manager = - LLNotificationsUI::LLNotificationManager::getInstance(); + LLNotificationsUI::LLNotificationManager* notify_manager = LLNotificationsUI::LLNotificationManager::getInstance(); getRootView()->addChild(notify_manager); } @@ -2175,7 +2176,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) LLUICtrl* keyboard_focus = gFocusMgr.getKeyboardFocus(); if( keyboard_focus ) { - LLLineEditor* chat_editor = LLBottomTray::instanceExists() ? LLBottomTray::getInstance()->getChatBox() : NULL; + LLLineEditor* chat_editor = LLBottomTray::instanceExists() ? LLBottomTray::getInstance()->getNearbyChatBar()->getChatBox() : NULL; // arrow keys move avatar while chatting hack if (chat_editor && chat_editor->hasFocus()) { diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index fc639fbb21..f1d4520370 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -67,6 +67,9 @@ #include "llfloaterfriends.h" //VIVOX, inorder to refresh communicate panel #include "llfloaterchat.h" // for LLFloaterChat::addChat() +// for Talk Button's state updating +#include "llnearbychatbar.h" + // for base64 decoding #include "apr_base64.h" @@ -5783,6 +5786,7 @@ bool LLVoiceClient::getMuteMic() const void LLVoiceClient::setUserPTTState(bool ptt) { mUserPTTState = ptt; + LLNearbyChatBar::getInstance()->setPTTState(ptt); } bool LLVoiceClient::getUserPTTState() @@ -5793,6 +5797,7 @@ bool LLVoiceClient::getUserPTTState() void LLVoiceClient::toggleUserPTTState(void) { mUserPTTState = !mUserPTTState; + LLNearbyChatBar::getInstance()->setPTTState(mUserPTTState); } void LLVoiceClient::setVoiceEnabled(bool enabled) diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 179c790aed..d55f9fa42f 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -304,7 +304,10 @@ value="0.3344 0.5456 0.5159 1" /> <color name="GroupNotifyTextColor" - value="0 0.12 0.24 1" /> + reference="White"/> + <color + name="GroupNotifyDimmedTextColor" + reference="DkGray"/> <color name="GroupOverTierColor" value="0.43 0.06 0.06 1" /> @@ -493,10 +496,10 @@ value="1 0.82 0.46 1" /> <color name="NotifyCautionWarnColor" - reference="Black" /> + reference="White" /> <color name="NotifyTextColor" - reference="Black" /> + reference="White" /> <color name="ObjectChatColor" reference="LtGray" /> diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml index 3052571b1e..2d67e3d5a9 100644 --- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml @@ -28,5 +28,21 @@ color="1 1 1 1" enabled="true" image_name="closebox.tga" name="close_btn"/> </panel> - <chat_items_container bottom="0" width="250" height="320" follows="left|right|top|bottom" name="chat_history" /> + <text_editor + bg_readonly_color="ChatHistoryBgColor" + bg_writeable_color="ChatHistoryBgColor" + follows="left|top|right|bottom" + font="SansSerif" + layout="topleft" + height="320" + max_length="2147483647" + name="Chat History Editor" + read_only="true" + text_color="ChatHistoryTextColor" + text_readonly_color="ChatHistoryTextColor" + bottom="0" + track_bottom="true" + width="250" + word_wrap="true" /> + </floater> diff --git a/indra/newview/skins/default/xui/en/menu_navbar.xml b/indra/newview/skins/default/xui/en/menu_navbar.xml index 78dff0bd4a..013136a593 100644 --- a/indra/newview/skins/default/xui/en/menu_navbar.xml +++ b/indra/newview/skins/default/xui/en/menu_navbar.xml @@ -23,6 +23,9 @@ <menu_item_call.on_click function="Navbar.Action" parameter="landmark" /> + <menu_item_call.on_enable + function="Navbar.EnableMenuItem" + parameter="can_landmark" /> </menu_item_call> <menu_item_separator layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index e922e3b743..fe1baf22d0 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -181,22 +181,10 @@ function="World.Chat" /> </menu_item_call> <menu_item_check - label="Local Chat" - layout="topleft" - name="Chat History" - shortcut="control|H"> - <menu_item_check.on_check - function="Floater.Visible" - parameter="chat" /> - <menu_item_check.on_click - function="Floater.Toggle" - parameter="chat" /> - </menu_item_check> - <menu_item_check label="Nearby Chat" layout="topleft" name="Nearby Chat" - shortcut="control|N"> + shortcut="control|H"> <menu_item_check.on_check function="Floater.Visible" parameter="nearby_chat" /> @@ -204,29 +192,6 @@ function="Floater.Toggle" parameter="nearby_chat" /> </menu_item_check> - <menu_item_check - label="Communicate" - layout="topleft" - name="Instant Message" - shortcut="control|T"> - <menu_item_check.on_check - function="Floater.Visible" - parameter="communicate" /> - <menu_item_check.on_click - function="Floater.Toggle" - parameter="communicate" /> - </menu_item_check> - <menu_item_separator - layout="topleft" /> - <menu_item_call - label="Media Remote Ctrl" - layout="topleft" - name="Preferences" - shortcut="control|alt|M"> - <menu_item_call.on_click - function="Floater.Toggle" - parameter="media_remote_ctrl" /> - </menu_item_call> <menu_item_separator layout="topleft" /> <menu_item_check @@ -251,6 +216,29 @@ function="Floater.Toggle" parameter="mute" /> </menu_item_check> + <menu_item_separator + layout="topleft" /> + <menu_item_check + label="(Legacy) Communicate" + layout="topleft" + name="Instant Message" + shortcut="control|T"> + <menu_item_check.on_check + function="Floater.Visible" + parameter="communicate" /> + <menu_item_check.on_click + function="Floater.Toggle" + parameter="communicate" /> + </menu_item_check> + <menu_item_call + label="(Temp) Media Remote Ctrl" + layout="topleft" + name="Preferences" + shortcut="control|alt|M"> + <menu_item_call.on_click + function="Floater.Toggle" + parameter="media_remote_ctrl" /> + </menu_item_call> </menu> <menu label="World" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index c89eed37ab..17bb961308 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4191,6 +4191,7 @@ Are you sure you want to quit? name="okcancelignore" notext="Don't Quit" yestext="Quit"/> + <unique/> </notification> <notification @@ -6465,6 +6466,10 @@ Click Accept to join the chat or Decline to decline the invitation. Click Block yestext="Create group for L$100"/> </notification> + <notification icon="notifytip.tga" + name="AttachmentSaved" type="notifytip"> + Attachment has been saved. + </notification> <global name="UnsupportedCPU"> - Your CPU speed does not meet the minimum requirements. diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index bbef5a8892..d42943d225 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -39,105 +39,12 @@ layout="topleft" left="5" min_height="28" - width="250" + width="500" top="0" - min_width="100"> - <line_editor - border_style="line" - border_thickness="1" - follows="left|right" - height="20" - layout="topleft" - left="0" - name="chat_box" - right="-39" - top="3" - width="250" /> - <button follows="right" width="36" top="3" left="214" resize="false" - label="Hx" height="20"> - <button.commit_callback function="Floater.Toggle" parameter="chat"/> - </button> - </layout_panel> - <icon - auto_resize="false" - color="0 0 0 0" - follows="left|right" - height="10" - image_name="spacer24.tga" - layout="topleft" - left="0" - top="0" - width="5" - min_width="5" /> - <view_border - auto_resize="false" - bevel_style="in" - follows="left|right" - height="28" - layout="topleft" - left="270" - top="0" - width="1" /> - <icon - auto_resize="false" - color="0 0 0 0" - follows="left|right" - height="10" - image_name="spacer24.tga" - layout="topleft" - left="0" - top="0" - width="5" - min_width="5" /> - <layout_panel - auto_resize="false" - follows="right" - height="28" - layout="topleft" - min_height="28" - width="100" - top="0" - min_width="100"> - <chiclet_talk - follows="right" - height="20" - layout="topleft" - left="0" - name="talk" - top="3" - width="100" /> - </layout_panel> - <icon - auto_resize="false" - color="0 0 0 0" - follows="left|right" - height="10" - image_name="spacer24.tga" - layout="topleft" - left="0" - name="DUMMY" - top="0" - width="5" - min_width="5"/> - <layout_panel - auto_resize="false" - follows="right" - height="28" - layout="topleft" - min_height="28" - width="90" - top="0" - min_width="90"> - <gesture_combo_box - bottom="22" - follows="right" - height="20" - label="Gestures" - layout="topleft" - name="Gesture" - top="3" - width="90" /> - </layout_panel> + min_width="305" + name="chat_bar" + user_resize="false" + filename="panel_nearby_chat_bar.xml"/> <icon auto_resize="false" color="0 0 0 0" @@ -159,7 +66,8 @@ min_height="28" width="90" top_delta="-10" - min_width="90"> + min_width="90" + user_resize="false"> <button bottom="22" follows="right" @@ -190,7 +98,7 @@ top="0" name="chiclet_list_panel" width="150" - min_width="70"> + user_resize="false"> <chiclet_panel follows="left|right" height="25" @@ -222,14 +130,15 @@ name="im_well_panel" width="40" top="0" - min_width="40" > + min_width="40" + user_resize="false"> <chiclet_notification follows="right" height="25" layout="topleft" left="0" name="im_well" - top="1" + top="2" width="40"> <button image_selected="im_notifications.tga" @@ -285,14 +194,15 @@ top="0" name="sys_well_panel" width="48" - min_width="48"> + min_width="48" + user_resize="false"> <chiclet_notification follows="right" height="25" layout="topleft" left="0" name="sys_well" - top="1" + top="2" width="48"> <button image_selected="bottom_tray_sys_notifications.tga" diff --git a/indra/newview/skins/default/xui/en/panel_chat_item.xml b/indra/newview/skins/default/xui/en/panel_chat_item.xml index b628ee3aa1..713c3a41a2 100644 --- a/indra/newview/skins/default/xui/en/panel_chat_item.xml +++ b/indra/newview/skins/default/xui/en/panel_chat_item.xml @@ -15,7 +15,7 @@ color="1 1 1 1" enabled="true" name="avatar_icon" /> <text - width="160" top="25" left="40" height="20" follows="left|right|top" + width="130" top="25" left="40" height="20" follows="left|right|top" font="SansSerifBigBold" text_color="white" word_wrap="true" mouse_opaque="true" name="sender_name" > Jerry Knight diff --git a/indra/newview/skins/default/xui/en/panel_group_notify.xml b/indra/newview/skins/default/xui/en/panel_group_notify.xml index 1757197372..a39a681f83 100644 --- a/indra/newview/skins/default/xui/en/panel_group_notify.xml +++ b/indra/newview/skins/default/xui/en/panel_group_notify.xml @@ -9,21 +9,23 @@ top="5" left="5" mouse_opaque="true" name="group_icon"/> <text type="string" length="1" follows="left|top|right|bottom" font="SansSerifBigBold" height="20" layout="topleft" left="60" name="title" - text_color="white" top="20" width="300"> + text_color="GroupNotifyTextColor" top="20" width="300"> Sender Name / Group Name </text> </panel> <text_editor type="string" length="1" bg_readonly_color="0 0 0 0" follows="left|top|right|bottom" height="70" hide_scrollbar="true" hide_border="true" layout="topleft" top="55" left="25" name="message" - text_color="white" text_readonly_color="white" width="300" word_wrap="true"> + text_color="GroupNotifyTextColor" text_readonly_color="GroupNotifyTextColor" width="300" word_wrap="true"> Message Body </text_editor> + <icon follows="left|top|right|bottom" height="16" width="16" + layout="topleft" top="135" left="25" mouse_opaque="true" name="attachment_icon" /> <text font="SansSerif" font.style="UNDERLINE" font_shadow="hard" type="string" length="1" follows="left|top|right|bottom" layout="topleft" - left="25" top="135" height="15" width="300" name="attachment" - text_color="white"> + left="45" top="135" height="15" width="280" name="attachment" + text_color="GroupNotifyTextColor"> Attachment </text> <button label="OK" layout="topleft" top="170" left="140" height="20" 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 new file mode 100644 index 0000000000..8b19f9a515 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + default_tab_group="1" + follows="left|bottom|right" + height="25" + layout="topleft" + left="0" + name="chat_bar" + top="24" + width="500"> + <line_editor + border_style="line" + border_thickness="1" + follows="left|right" + height="20" + label="Click here to chat." + layout="topleft" + left_delta="7" + left="0" + name="chat_box" + tool_tip="Press Enter to say, Ctrl-Enter to shout." + top="3" + width="250" /> + <button + follows="right" + width="45" + top="3" + layout="topleft" + left_pad="5" + label="Log" + height="20"> + <button.commit_callback function="Floater.Toggle" parameter="nearby_chat"/> + </button> + <chiclet_talk + follows="right" + height="20" + layout="topleft" + left_pad="5" + name="talk" + top="3" + width="100" /> + <gesture_combo_box + follows="right" + height="20" + label="Gestures" + layout="topleft" + name="Gesture" + left_pad="5" + top="3" + width="90" /> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml index 686dc931d3..1a06e2bb06 100644 --- a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml @@ -9,7 +9,7 @@ left="0" name="picture_item" top="80" - width="310"> + width="245"> <texture_picker allow_no_texture="true" default_image_name="None" @@ -22,32 +22,31 @@ name="picture" tab_stop="false" top="7" - width="90" /> + width="70" /> <text - follows="right" - font="SansSerifBold" + follows="top|left|right" + font="SansSerif" height="20" layout="topleft" - left="100" + left="80" name="picture_name" text_color="black" top="5" use_ellipses="true" - width="170"/> + width="150"/> <text - follows="right" - font="SansSerif" + follows="top|left|right" + font="SansSerifSmall" height="40" layout="topleft" - left="100" name="picture_descr" text_color="white" top="25" use_ellipses="true" - width="170" + width="150" word_wrap="true" /> <button - follows="right" + follows="top|right" height="20" image_disabled="navbar_bg_button.tga" image_disabled_selected="navbar_bg_button.tga" diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml index b746fcf84b..096b60adb1 100644 --- a/indra/newview/skins/default/xui/en/panel_side_tray.xml +++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml @@ -8,6 +8,26 @@ collapsed="true" > <sidetray_tab + name="sidebar_home" + tab_title="Home" + description="Home." + image="icn_voice-groupfocus.tga" + mouse_opaque="false" + background_opaque="false" + background_visible="true" + bg_opaque_color="0.5 0.5 0.5 1.0" + > + <panel + name="panel_home" + filename="panel_sidetray_home_tab.xml" + width="355" + height="465" + label="home" + border="true" + /> + </sidetray_tab> + + <sidetray_tab name="sidebar_people" tab_title="People" description="Find your friends, contacts and people nearby." @@ -17,15 +37,6 @@ background_visible="true" bg_opaque_color="0.5 0.5 0.5 1.0" > - <accordion_tab - name="people_accordion" - title="People" - collapsable="true" - min_width="200" - min_height="200" - expanded="true" - header_visible="false" - > <panel class="panel_people" name="panel_people" @@ -35,7 +46,6 @@ label="People" border="true" /> - </accordion_tab> </sidetray_tab> <!-- *TODO Vadim: isn't the sidetray_tab "label" attribute redundant since we have "tab_title" ? --> <sidetray_tab @@ -48,14 +58,6 @@ background_visible="true" bg_opaque_color="0.5 0.5 0.5 1.0" > - <accordion_tab - name="places_accordian" - title="Places" - collapsable="true" - min_width="355" - min_height="200" - header_visible="false" - > <panel class="panel_places" name="panel_places" @@ -63,7 +65,6 @@ label="Places" border="true" /> - </accordion_tab> </sidetray_tab> <sidetray_tab @@ -75,14 +76,6 @@ background_visible="true" bg_opaque_color="0.5 0.5 0.5 1.0" > - <accordion_tab - name="me_accordion" - title="Me" - collapsable="false" - min_width="200" - min_height="200" - header_visible="false" - > <panel class="panel_me_profile" name="panel_me_profile" @@ -90,7 +83,6 @@ label="Me" border="true" /> - </accordion_tab> </sidetray_tab> <!-- @@ -107,7 +99,7 @@ name="group_accordion" title="Group General" expanded="true" - collapsable="true" + collapsible="true" min_width="200" min_height="200" header_visible="true" @@ -187,7 +179,7 @@ <accordion_tab name="floater_preview_animation" title="Preview Animation" - collapsable="true" + collapsible="true" expanded="false" min_width="200" min_height="200" @@ -206,7 +198,7 @@ <accordion_tab name="floater_preview_gesture" title="Preview Gesture" - collapsable="true" + collapsible="true" expanded="false" min_width="200" min_height="200" @@ -225,7 +217,7 @@ <accordion_tab name="floater_preview_existing_landmark" title="Preview Existing Landmark" - collapsable="true" + collapsible="true" expanded="false" min_width="200" min_height="200" @@ -244,7 +236,7 @@ <accordion_tab name="floater_preview_sound" title="Preview Sound" - collapsable="true" + collapsible="true" expanded="false" min_width="200" min_height="200" @@ -263,7 +255,7 @@ <accordion_tab name="floater_preview_url" title="Preview URL" - collapsable="true" + collapsible="true" expanded="false" min_width="200" min_height="200" @@ -282,7 +274,7 @@ <accordion_tab name="floater_URL_entry" title="URL Entry" - collapsable="true" + collapsible="true" expanded="false" min_width="200" min_height="200" @@ -313,7 +305,7 @@ <accordion_tab name="panel_region_covenant" title="Region Covenant" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" @@ -332,7 +324,7 @@ <accordion_tab name="panel_region_debug" title="Region Debug" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" @@ -351,7 +343,7 @@ <accordion_tab name="panel_region_estate" title="Region Estate" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" @@ -370,7 +362,7 @@ <accordion_tab name="panel_region_general" title="Region General" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" @@ -389,7 +381,7 @@ <accordion_tab name="panel_region_terrain" title="Region Terrain" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" @@ -408,7 +400,7 @@ <accordion_tab name="panel_region_texture" title="Region Texture" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" @@ -427,7 +419,7 @@ <accordion_tab name="floater_region_info" title="Region Info" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" @@ -458,7 +450,7 @@ <accordion_tab name="floater_tools" title="Tools" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" @@ -477,7 +469,7 @@ <accordion_tab name="floater_bulk_perms" title="Bulk Perms" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" @@ -496,7 +488,7 @@ <accordion_tab name="floater_build_options" title="Build Options" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" @@ -528,7 +520,7 @@ <accordion_tab name="floater_gesture" title="Gestures" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" @@ -548,7 +540,7 @@ <accordion_tab name="floater_buy_contents" title="Buy Contents" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" @@ -567,7 +559,7 @@ <accordion_tab name="floater_buy_object" title="Buy Object" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" @@ -586,7 +578,7 @@ <accordion_tab name="floater_inventory_view_finder" title="Inventory View Finder" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" @@ -605,7 +597,7 @@ <accordion_tab name="floater_mute" title="Mute" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" @@ -624,7 +616,7 @@ <accordion_tab name="floater_sell_land" title="Sell Land" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" @@ -643,7 +635,7 @@ <accordion_tab name="floater_telehub" title="Telehub" - collapsable="true" + collapsible="true" min_width="200" min_height="200" expanded="false" diff --git a/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml b/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml new file mode 100644 index 0000000000..a85662603d --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- All our XML is utf-8 encoded. --> + +<panel + name="home_tab" + title="home_tab" + visible="true" + width="300" + height="420" + background_opaque="false" + background_visible="true" + bevel_style="in" + follows="left|top|right|bottom"> + <panel + left="10" width="280" height="130" + background_visible="true" + background_opaque="false" + bg_alpha_color="0.3 0.3 0.3 1.0" + name="sidebar_people" + follows="left|top|right" + class="panel_sidetray_home_info"> + <text + top="-10" width="200" left="5" height="30" follows="left|right|top" + font="SansSerifHugeBold" text_color="white" word_wrap="true" + mouse_opaque="false" name="tab_name" > + People + </text> + <icon + top="-10" right="-10" width="20" height="20" follows="top|right" + color="1 1 1 1" enabled="true" image_name="icn_voice-groupfocus.tga" + mouse_opaque="false" name="tab_icon"/> + <text + top="-40" left="10" right="-10" height="120" follows="left|right|bottom" + font="SansSerifBig" text_color="white" word_wrap="true" + mouse_opaque="false" name="tab_description" > + Find your friends, contacts and people nearby. + </text> + </panel> + <panel + left="10" width="280" height="130" + background_visible="true" + background_opaque="false" + bg_alpha_color="0.3 0.3 0.3 1.0" + name="sidebar_places" + follows="left|top|right" + class="panel_sidetray_home_info"> + <text + top="-10" width="200" left="5" height="30" follows="left|right|top" + font="SansSerifHugeBold" text_color="white" word_wrap="true" + mouse_opaque="false" name="tab_name" > + Places + </text> + <icon + top="-10" right="-10" width="20" height="20" follows="top|right" + color="1 1 1 1" enabled="true" image_name="inv_item_landmark.tga" + mouse_opaque="false" name="tab_icon"/> + <text + top="-40" left="10" right="-10" height="120" follows="left|right|bottom|top" + font="SansSerifBig" text_color="white" word_wrap="true" + mouse_opaque="false" name="tab_description" > + Find your friends, contacts and people nearby. + </text> + </panel> + <panel + left="10" width="280" height="130" + background_visible="true" + background_opaque="false" + bg_alpha_color="0.3 0.3 0.3 1.0" + name="sidebar_me" + follows="left|top|right" + class="panel_sidetray_home_info"> + <text + top="-10" width="200" left="5" height="30" follows="left|right|top" + font="SansSerifHugeBold" text_color="white" word_wrap="true" + mouse_opaque="false" name="tab_name" > + Me + </text> + <icon + top="-10" right="-10" width="20" height="20" follows="top|right" + color="1 1 1 1" enabled="true" image_name="icn_voice-pvtfocus.tga" + mouse_opaque="false" name="tab_icon"/> + <text + top="-40" left="10" right="-10" height="120" follows="left|right|bottom" + font="SansSerifBig" text_color="white" word_wrap="true" + mouse_opaque="false" name="tab_description" > + Change your profile, your look and quick links to your outfits. + </text> + </panel> +</panel> +
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_toast.xml b/indra/newview/skins/default/xui/en/panel_toast.xml index 8952ea1307..ba4915e074 100644 --- a/indra/newview/skins/default/xui/en/panel_toast.xml +++ b/indra/newview/skins/default/xui/en/panel_toast.xml @@ -17,16 +17,16 @@ bg_alpha_color="0.3 0.3 0.3 1.0"> <text - type="string" visible="false" follows="left|top|right|bottom" font="SansSerifBold" height="40" layout="topleft" left="60" - name="text" + name="toast_text" + word_wrap="true" text_color="white" - top="30" + top="20" width="290"> Toast text; </text> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 149da313a2..e5665b0194 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -652,6 +652,7 @@ Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh <string name="Stage">Stage</string> <string name="Other">Other</string> <string name="Any">Any</string> + <string name="You">You</string> <!-- puncutations --> <string name=":">:</string> @@ -785,4 +786,6 @@ If you continue to receive this message, contact customer support. <string name="UTCTimeMin">min,datetime,utc</string> <string name="UTCTimeSec">second,datetime,utc</string> <string name="UTCTimeTimezone">timezone,datetime,utc</string> + + </strings> diff --git a/indra/newview/skins/default/xui/en/widgets/location_input.xml b/indra/newview/skins/default/xui/en/widgets/location_input.xml index efb9a89c6a..eb9bb99b20 100644 --- a/indra/newview/skins/default/xui/en/widgets/location_input.xml +++ b/indra/newview/skins/default/xui/en/widgets/location_input.xml @@ -10,16 +10,13 @@ add_landmark_image_enabled="Favorite_Star_Active" add_landmark_image_disabled="Favorite_Star_Off" hover_glow_amount="0.15" - add_landmark_width="20" - add_landmark_height="20" add_landmark_hpad="2" allow_text_entry="true" - arrow_image="Combobox_Selected" list_position="below" show_text_as_tentative="false" max_chars="20" follows="left|top" - background="TextField_Off"> + > <info_button name="Place Information" label="" tool_tip="About current location" diff --git a/indra/newview/skins/default/xui/en/widgets/slider_bar.xml b/indra/newview/skins/default/xui/en/widgets/slider_bar.xml index 7004de8475..b33acf81cc 100644 --- a/indra/newview/skins/default/xui/en/widgets/slider_bar.xml +++ b/indra/newview/skins/default/xui/en/widgets/slider_bar.xml @@ -3,6 +3,5 @@ thumb_outline_color="SliderThumbOutlineColor" thumb_center_color="SliderThumbCenterColor" thumb_image="SliderThumb_Off" - hover_glow_amount="0.15" track_image="SliderTrack_Horiz" track_highlight_image="SliderTrack_Horiz" /> |